Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--build_files/cmake/config/blender_full.cmake1
-rw-r--r--build_files/cmake/config/blender_lite.cmake1
-rw-r--r--build_files/cmake/config/blender_release.cmake1
-rw-r--r--extern/CMakeLists.txt5
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/AUTHORS26
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/CMakeLists.txt373
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/INSTALL167
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/LICENSE32
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/NEWS337
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/README50
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/cmake/FindCOIN.cmake110
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/cmake/FindGLPK.cmake55
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/cmake/FindGhostscript.cmake10
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/cmake/FindILOG.cmake102
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/cmake/FindSOPLEX.cmake23
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/cmake/LEMONConfig.cmake.in13
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/cmake/nsis/lemon.icobin0 -> 22486 bytes
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/cmake/nsis/uninstall.icobin0 -> 15086 bytes
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/cmake/version.cmake1
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/cmake/version.cmake.in1
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/contrib/CMakeLists.txt19
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/demo/CMakeLists.txt19
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/demo/arg_parser_demo.cc112
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/demo/digraph.lgf29
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/demo/graph_to_eps_demo.cc206
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/demo/lgf_demo.cc70
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/CMakeLists.txt91
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/adaptors.h3638
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/arg_parser.cc474
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/arg_parser.h440
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/assert.h214
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/base.cc37
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bellman_ford.h1116
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bfs.h1754
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bin_heap.h347
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/binomial_heap.h445
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/alteration_notifier.h472
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/array_map.h351
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/bezier.h174
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/default_map.h182
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/edge_set_extender.h627
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/enable_if.h131
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/graph_adaptor_extender.h401
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/graph_extender.h1332
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/lock.h65
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/map_extender.h332
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/path_dump.h177
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/solver_bits.h194
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/traits.h388
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/variant.h494
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/vector_map.h244
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/windows.cc166
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/windows.h44
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/bucket_heap.h594
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/capacity_scaling.h1014
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/cbc.cc460
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/cbc.h129
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/christofides_tsp.h254
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/circulation.h807
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/clp.cc464
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/clp.h164
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/color.cc44
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/color.h204
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/concept_check.h77
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/bpgraph.h1029
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/digraph.h491
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/graph.h788
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/graph_components.h2134
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/heap.h324
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/maps.h223
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/path.h312
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/config.h22
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/config.h.in22
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/connectivity.h1688
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/core.h2506
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/cost_scaling.h1607
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/counter.h249
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/cplex.cc994
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/cplex.h292
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/cycle_canceling.h1230
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/dfs.h1637
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/dheap.h352
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/dijkstra.h1303
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/dim2.h726
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/dimacs.h448
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/edge_set.h1420
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/edmonds_karp.h556
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/elevator.h982
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/error.h276
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/euler.h287
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/fib_heap.h475
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/fractional_matching.h2139
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/full_graph.h1082
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/glpk.cc1012
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/glpk.h263
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/gomory_hu.h568
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/graph_to_eps.h1186
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/greedy_tsp.h251
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/grid_graph.h699
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/grosso_locatelli_pullan_mc.h840
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/hao_orlin.h1015
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/hartmann_orlin_mmc.h654
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/howard_mmc.h651
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/hypercube_graph.h459
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/insertion_tsp.h533
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/karp_mmc.h590
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/kruskal.h324
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/lemon.pc.in10
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/lgf_reader.h3854
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/lgf_writer.h2687
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/list_graph.h2510
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/lp.h95
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/lp_base.cc30
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/lp_base.h2147
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/lp_skeleton.cc143
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/lp_skeleton.h234
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/maps.h4057
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/matching.h3505
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/math.h77
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/max_cardinality_search.h794
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/min_cost_arborescence.h808
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/nagamochi_ibaraki.h702
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/nauty_reader.h113
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/nearest_neighbor_tsp.h238
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/network_simplex.h1659
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/opt2_tsp.h367
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/pairing_heap.h474
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/path.h1164
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/planarity.h2754
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/preflow.h985
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/quad_heap.h343
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/radix_heap.h438
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/radix_sort.h487
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/random.cc29
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/random.h1005
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/smart_graph.h1344
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/soplex.cc465
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/soplex.h158
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/static_graph.h476
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/suurballe.h776
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/time_measure.h610
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/tolerance.h242
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/lemon/unionfind.h1824
-rwxr-xr-xextern/quadriflow/3rd/lemon-1.3.1/scripts/unify-sources.sh390
-rwxr-xr-xextern/quadriflow/3rd/lemon-1.3.1/scripts/valgrind-wrapper.sh22
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/CMakeLists.txt161
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/adaptors_test.cc1468
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/arc_look_up_test.cc84
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/bellman_ford_test.cc289
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/bfs_test.cc239
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/bpgraph_test.cc456
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/circulation_test.cc169
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/connectivity_test.cc316
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/counter_test.cc118
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/dfs_test.cc238
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/digraph_test.cc569
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/dijkstra_test.cc246
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/dim_test.cc87
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/edge_set_test.cc396
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/error_test.cc90
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/euler_test.cc225
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/fractional_matching_test.cc527
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/gomory_hu_test.cc142
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/graph_copy_test.cc388
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/graph_test.cc603
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/graph_test.h421
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/graph_utils_test.cc217
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/hao_orlin_test.cc164
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/heap_test.cc310
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/kruskal_test.cc147
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/lgf_reader_writer_test.cc578
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/lgf_test.cc169
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/lp_test.cc470
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/maps_test.cc1022
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/matching_test.cc449
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/max_cardinality_search_test.cc162
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/max_clique_test.cc188
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/max_flow_test.cc395
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/min_cost_arborescence_test.cc207
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/min_cost_flow_test.cc548
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/min_mean_cycle_test.cc223
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/mip_test.cc171
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/nagamochi_ibaraki_test.cc142
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/path_test.cc339
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/planarity_test.cc262
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/radix_sort_test.cc266
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/random_test.cc40
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/suurballe_test.cc267
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/test_tools.h50
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/test_tools_fail.cc25
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/test_tools_pass.cc25
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/time_measure_test.cc60
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/tsp_test.cc287
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/test/unionfind_test.cc102
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/tools/CMakeLists.txt31
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/tools/dimacs-solver.cc279
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/tools/dimacs-to-lgf.cc148
-rwxr-xr-xextern/quadriflow/3rd/lemon-1.3.1/tools/lemon-0.x-to-1.x.sh134
-rw-r--r--extern/quadriflow/3rd/lemon-1.3.1/tools/lgf-gen.cc847
-rw-r--r--extern/quadriflow/3rd/pcg32/pcg32/pcg32.h209
-rw-r--r--extern/quadriflow/3rd/pss/pss/parallel_stable_sort.h140
-rw-r--r--extern/quadriflow/3rd/pss/pss/pss_common.h106
-rw-r--r--extern/quadriflow/CMakeLists.txt105
-rw-r--r--extern/quadriflow/LICENSE.txt37
-rw-r--r--extern/quadriflow/README.md134
-rw-r--r--extern/quadriflow/src/Optimizer.cu281
-rw-r--r--extern/quadriflow/src/adjacent-matrix.cpp35
-rw-r--r--extern/quadriflow/src/adjacent-matrix.hpp37
-rw-r--r--extern/quadriflow/src/compare-key.hpp102
-rw-r--r--extern/quadriflow/src/config.hpp34
-rw-r--r--extern/quadriflow/src/dedge.cpp487
-rw-r--r--extern/quadriflow/src/dedge.hpp25
-rw-r--r--extern/quadriflow/src/disajoint-tree.hpp151
-rw-r--r--extern/quadriflow/src/dset.hpp163
-rw-r--r--extern/quadriflow/src/field-math.hpp483
-rw-r--r--extern/quadriflow/src/flow.hpp375
-rw-r--r--extern/quadriflow/src/hierarchy.cpp1343
-rw-r--r--extern/quadriflow/src/hierarchy.hpp99
-rw-r--r--extern/quadriflow/src/loader.cpp159
-rw-r--r--extern/quadriflow/src/loader.hpp15
-rw-r--r--extern/quadriflow/src/localsat.cpp295
-rw-r--r--extern/quadriflow/src/localsat.hpp31
-rw-r--r--extern/quadriflow/src/main.cpp127
-rw-r--r--extern/quadriflow/src/merge-vertex.cpp44
-rw-r--r--extern/quadriflow/src/merge-vertex.hpp14
-rw-r--r--extern/quadriflow/src/optimizer.cpp1419
-rw-r--r--extern/quadriflow/src/optimizer.hpp56
-rw-r--r--extern/quadriflow/src/parametrizer-flip.cpp583
-rw-r--r--extern/quadriflow/src/parametrizer-int.cpp425
-rw-r--r--extern/quadriflow/src/parametrizer-mesh.cpp615
-rw-r--r--extern/quadriflow/src/parametrizer-scale.cpp119
-rw-r--r--extern/quadriflow/src/parametrizer-sing.cpp142
-rw-r--r--extern/quadriflow/src/parametrizer.cpp247
-rw-r--r--extern/quadriflow/src/parametrizer.hpp177
-rw-r--r--extern/quadriflow/src/post-solver.cpp427
-rw-r--r--extern/quadriflow/src/post-solver.hpp64
-rw-r--r--extern/quadriflow/src/serialize.hpp127
-rw-r--r--extern/quadriflow/src/subdivide.cpp516
-rw-r--r--extern/quadriflow/src/subdivide.hpp17
-rw-r--r--intern/CMakeLists.txt5
-rw-r--r--intern/quadriflow/CMakeLists.txt45
-rw-r--r--intern/quadriflow/quadriflow_capi.cpp238
-rw-r--r--intern/quadriflow/quadriflow_capi.hpp54
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py16
-rw-r--r--source/blender/blenkernel/BKE_mesh_remesh_voxel.h8
-rw-r--r--source/blender/blenkernel/CMakeLists.txt10
-rw-r--r--source/blender/blenkernel/intern/mesh_remesh_voxel.c146
-rw-r--r--source/blender/editors/object/object_intern.h1
-rw-r--r--source/blender/editors/object/object_ops.c1
-rw-r--r--source/blender/editors/object/object_remesh.c390
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h9
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c13
-rw-r--r--source/blender/windowmanager/WM_api.h1
254 files changed, 119812 insertions, 9 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 747acf27c64..ad705821596 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -263,6 +263,8 @@ endif()
option(WITH_HEADLESS "Build without graphical support (renderfarm, server mode only)" OFF)
mark_as_advanced(WITH_HEADLESS)
+option(WITH_QUADRIFLOW "Build with quadriflow remesher support" ON)
+
option(WITH_AUDASPACE "Build with blenders audio library (only disable if you know what you're doing!)" ON)
option(WITH_SYSTEM_AUDASPACE "Build with external audaspace library installed on the system (only enable if you know what you're doing!)" OFF)
mark_as_advanced(WITH_AUDASPACE)
@@ -673,6 +675,7 @@ if(NOT WITH_BOOST)
set_and_warn(WITH_INTERNATIONAL OFF)
set_and_warn(WITH_OPENVDB OFF)
set_and_warn(WITH_OPENCOLORIO OFF)
+ set_and_warn(WITH_QUADRIFLOW OFF)
elseif(WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_INTERNATIONAL OR
WITH_OPENVDB OR WITH_OPENCOLORIO)
# Keep enabled
@@ -1765,6 +1768,7 @@ if(FIRST_RUN)
info_cfg_option(WITH_OPENIMAGEDENOISE)
info_cfg_option(WITH_OPENVDB)
info_cfg_option(WITH_ALEMBIC)
+ info_cfg_option(WITH_QUADRIFLOW)
info_cfg_text("Compiler Options:")
info_cfg_option(WITH_BUILDINFO)
diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake
index 75c5e0f34c1..403d38f6a05 100644
--- a/build_files/cmake/config/blender_full.cmake
+++ b/build_files/cmake/config/blender_full.cmake
@@ -46,6 +46,7 @@ set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
set(WITH_OPENVDB ON CACHE BOOL "" FORCE)
set(WITH_OPENVDB_BLOSC ON CACHE BOOL "" FORCE)
set(WITH_PYTHON_INSTALL ON CACHE BOOL "" FORCE)
+set(WITH_QUADRIFLOW ON CACHE BOOL "" FORCE)
set(WITH_RAYOPTIMIZATION ON CACHE BOOL "" FORCE)
set(WITH_SDL ON CACHE BOOL "" FORCE)
set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake
index 6596d1db674..e98f4f098bb 100644
--- a/build_files/cmake/config/blender_lite.cmake
+++ b/build_files/cmake/config/blender_lite.cmake
@@ -50,6 +50,7 @@ set(WITH_OPENIMAGEIO OFF CACHE BOOL "" FORCE)
set(WITH_OPENMP OFF CACHE BOOL "" FORCE)
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
set(WITH_OPENVDB OFF CACHE BOOL "" FORCE)
+set(WITH_QUADRIFLOW OFF CACHE BOOL "" FORCE)
set(WITH_RAYOPTIMIZATION OFF CACHE BOOL "" FORCE)
set(WITH_SDL OFF CACHE BOOL "" FORCE)
set(WITH_X11_XINPUT OFF CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/config/blender_release.cmake b/build_files/cmake/config/blender_release.cmake
index 08218a5e57c..2d7b167764b 100644
--- a/build_files/cmake/config/blender_release.cmake
+++ b/build_files/cmake/config/blender_release.cmake
@@ -47,6 +47,7 @@ set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
set(WITH_OPENVDB ON CACHE BOOL "" FORCE)
set(WITH_OPENVDB_BLOSC ON CACHE BOOL "" FORCE)
set(WITH_PYTHON_INSTALL ON CACHE BOOL "" FORCE)
+set(WITH_QUADRIFLOW ON CACHE BOOL "" FORCE)
set(WITH_RAYOPTIMIZATION ON CACHE BOOL "" FORCE)
set(WITH_SDL ON CACHE BOOL "" FORCE)
set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE)
diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt
index 3b2a8c172aa..0d9010b15ea 100644
--- a/extern/CMakeLists.txt
+++ b/extern/CMakeLists.txt
@@ -105,3 +105,8 @@ if(WITH_AUDASPACE AND NOT WITH_SYSTEM_AUDASPACE)
set(AUDASPACE_CMAKE_CFG ${CMAKE_CURRENT_SOURCE_DIR}/audaspace/blender_config.cmake)
add_subdirectory(audaspace)
endif()
+
+if(WITH_QUADRIFLOW)
+ set(QUADRIFLOW_CMAKE_CFG ${CMAKE_CURRENT_SOURCE_DIR}/quadriflow/blender_config.cmake)
+ add_subdirectory(quadriflow)
+endif()
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/AUTHORS b/extern/quadriflow/3rd/lemon-1.3.1/AUTHORS
new file mode 100644
index 00000000000..4019ca6213a
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/AUTHORS
@@ -0,0 +1,26 @@
+The main developers of release series 1.x are
+
+ * Balazs Dezso <deba@inf.elte.hu>
+ * Alpar Juttner <alpar@cs.elte.hu>
+ * Peter Kovacs <kpeter@inf.elte.hu>
+ * Akos Ladanyi <ladanyi@tmit.bme.hu>
+
+For more complete list of contributors, please visit the history of
+the LEMON source code repository: http://lemon.cs.elte.hu/hg/lemon
+
+Moreover, this version is heavily based on version 0.x of LEMON. Here
+is the list of people who contributed to those versions.
+
+ * Mihaly Barasz <klao@cs.elte.hu>
+ * Johanna Becker <beckerjc@cs.elte.hu>
+ * Attila Bernath <athos@cs.elte.hu>
+ * Balazs Dezso <deba@inf.elte.hu>
+ * Peter Hegyi <hegyi@tmit.bme.hu>
+ * Alpar Juttner <alpar@cs.elte.hu>
+ * Peter Kovacs <kpeter@inf.elte.hu>
+ * Akos Ladanyi <ladanyi@tmit.bme.hu>
+ * Marton Makai <marci@cs.elte.hu>
+ * Jacint Szabo <jacint@cs.elte.hu>
+
+Again, please visit the history of the old LEMON repository for more
+details: http://lemon.cs.elte.hu/hg/lemon-0.x \ No newline at end of file
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/CMakeLists.txt b/extern/quadriflow/3rd/lemon-1.3.1/CMakeLists.txt
new file mode 100644
index 00000000000..7aa6d430906
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/CMakeLists.txt
@@ -0,0 +1,373 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 3.1)
+
+SET(PROJECT_NAME "LEMON")
+PROJECT(${PROJECT_NAME})
+
+INCLUDE(FindPythonInterp)
+INCLUDE(FindWget)
+
+IF(EXISTS ${PROJECT_SOURCE_DIR}/cmake/version.cmake)
+ INCLUDE(${PROJECT_SOURCE_DIR}/cmake/version.cmake)
+ELSEIF(DEFINED ENV{LEMON_VERSION})
+ SET(LEMON_VERSION $ENV{LEMON_VERSION} CACHE STRING "LEMON version string.")
+ELSE()
+ EXECUTE_PROCESS(
+ COMMAND
+ hg log -r. --template "{latesttag}"
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+ OUTPUT_VARIABLE HG_REVISION_TAG
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ EXECUTE_PROCESS(
+ COMMAND
+ hg log -r. --template "{latesttagdistance}"
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+ OUTPUT_VARIABLE HG_REVISION_DIST
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ EXECUTE_PROCESS(
+ COMMAND
+ hg log -r. --template "{node|short}"
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+ OUTPUT_VARIABLE HG_REVISION_ID
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+
+ IF(HG_REVISION_TAG STREQUAL "")
+ SET(HG_REVISION_ID "hg-tip")
+ ELSE()
+ IF(HG_REVISION_TAG STREQUAL "null")
+ SET(HG_REVISION_TAG "trunk")
+ ELSEIF(HG_REVISION_TAG MATCHES "^r")
+ STRING(SUBSTRING ${HG_REVISION_TAG} 1 -1 HG_REVISION_TAG)
+ ENDIF()
+ IF(HG_REVISION_DIST STREQUAL "0")
+ SET(HG_REVISION ${HG_REVISION_TAG})
+ ELSE()
+ SET(HG_REVISION
+ "${HG_REVISION_TAG}+${HG_REVISION_DIST}-${HG_REVISION_ID}")
+ ENDIF()
+ ENDIF()
+
+ SET(LEMON_VERSION ${HG_REVISION} CACHE STRING "LEMON version string.")
+ENDIF()
+
+SET(PROJECT_VERSION ${LEMON_VERSION})
+
+SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
+
+FIND_PACKAGE(Doxygen)
+FIND_PACKAGE(Ghostscript)
+
+SET(LEMON_ENABLE_GLPK YES CACHE STRING "Enable GLPK solver backend.")
+SET(LEMON_ENABLE_ILOG YES CACHE STRING "Enable ILOG (CPLEX) solver backend.")
+SET(LEMON_ENABLE_COIN YES CACHE STRING "Enable COIN solver backend.")
+SET(LEMON_ENABLE_SOPLEX YES CACHE STRING "Enable SoPlex solver backend.")
+
+IF(LEMON_ENABLE_GLPK)
+ FIND_PACKAGE(GLPK 4.33)
+ENDIF(LEMON_ENABLE_GLPK)
+IF(LEMON_ENABLE_ILOG)
+ FIND_PACKAGE(ILOG)
+ENDIF(LEMON_ENABLE_ILOG)
+IF(LEMON_ENABLE_COIN)
+ FIND_PACKAGE(COIN)
+ENDIF(LEMON_ENABLE_COIN)
+IF(LEMON_ENABLE_SOPLEX)
+ FIND_PACKAGE(SOPLEX)
+ENDIF(LEMON_ENABLE_SOPLEX)
+
+IF(GLPK_FOUND)
+ SET(LEMON_HAVE_LP TRUE)
+ SET(LEMON_HAVE_MIP TRUE)
+ SET(LEMON_HAVE_GLPK TRUE)
+ENDIF(GLPK_FOUND)
+IF(ILOG_FOUND)
+ SET(LEMON_HAVE_LP TRUE)
+ SET(LEMON_HAVE_MIP TRUE)
+ SET(LEMON_HAVE_CPLEX TRUE)
+ENDIF(ILOG_FOUND)
+IF(COIN_FOUND)
+ SET(LEMON_HAVE_LP TRUE)
+ SET(LEMON_HAVE_MIP TRUE)
+ SET(LEMON_HAVE_CLP TRUE)
+ SET(LEMON_HAVE_CBC TRUE)
+ENDIF(COIN_FOUND)
+IF(SOPLEX_FOUND)
+ SET(LEMON_HAVE_LP TRUE)
+ SET(LEMON_HAVE_SOPLEX TRUE)
+ENDIF(SOPLEX_FOUND)
+
+IF(ILOG_FOUND)
+ SET(DEFAULT_LP "CPLEX")
+ SET(DEFAULT_MIP "CPLEX")
+ELSEIF(COIN_FOUND)
+ SET(DEFAULT_LP "CLP")
+ SET(DEFAULT_MIP "CBC")
+ELSEIF(GLPK_FOUND)
+ SET(DEFAULT_LP "GLPK")
+ SET(DEFAULT_MIP "GLPK")
+ELSEIF(SOPLEX_FOUND)
+ SET(DEFAULT_LP "SOPLEX")
+ENDIF()
+
+IF(NOT LEMON_DEFAULT_LP OR
+ (NOT ILOG_FOUND AND (LEMON_DEFAULT_LP STREQUAL "CPLEX")) OR
+ (NOT COIN_FOUND AND (LEMON_DEFAULT_LP STREQUAL "CLP")) OR
+ (NOT GLPK_FOUND AND (LEMON_DEFAULT_LP STREQUAL "GLPK")) OR
+ (NOT SOPLEX_FOUND AND (LEMON_DEFAULT_LP STREQUAL "SOPLEX")))
+ SET(LEMON_DEFAULT_LP ${DEFAULT_LP} CACHE STRING
+ "Default LP solver backend (GLPK, CPLEX, CLP or SOPLEX)" FORCE)
+ELSE()
+ SET(LEMON_DEFAULT_LP ${DEFAULT_LP} CACHE STRING
+ "Default LP solver backend (GLPK, CPLEX, CLP or SOPLEX)")
+ENDIF()
+IF(NOT LEMON_DEFAULT_MIP OR
+ (NOT ILOG_FOUND AND (LEMON_DEFAULT_MIP STREQUAL "CPLEX")) OR
+ (NOT COIN_FOUND AND (LEMON_DEFAULT_MIP STREQUAL "CBC")) OR
+ (NOT GLPK_FOUND AND (LEMON_DEFAULT_MIP STREQUAL "GLPK")))
+ SET(LEMON_DEFAULT_MIP ${DEFAULT_MIP} CACHE STRING
+ "Default MIP solver backend (GLPK, CPLEX or CBC)" FORCE)
+ELSE()
+ SET(LEMON_DEFAULT_MIP ${DEFAULT_MIP} CACHE STRING
+ "Default MIP solver backend (GLPK, CPLEX or CBC)")
+ENDIF()
+
+
+IF(DEFINED ENV{LEMON_CXX_WARNING})
+ SET(CXX_WARNING $ENV{LEMON_CXX_WARNING})
+ELSE()
+ IF(CMAKE_COMPILER_IS_GNUCXX)
+ SET(CXX_WARNING "-Wall -W -Wunused -Wformat=2 -Wctor-dtor-privacy -Wnon-virtual-dtor -Wno-char-subscripts -Wwrite-strings -Wno-char-subscripts -Wreturn-type -Wcast-qual -Wcast-align -Wsign-promo -Woverloaded-virtual -fno-strict-aliasing -Wold-style-cast -Wno-unknown-pragmas")
+ SET(CMAKE_CXX_FLAGS_DEBUG CACHE STRING "-ggdb")
+ SET(CMAKE_C_FLAGS_DEBUG CACHE STRING "-ggdb")
+ ELSEIF(MSVC)
+ # This part is unnecessary 'casue the same is set by the lemon/core.h.
+ # Still keep it as an example.
+ SET(CXX_WARNING "/wd4250 /wd4355 /wd4503 /wd4800 /wd4996")
+ # Suppressed warnings:
+ # C4250: 'class1' : inherits 'class2::member' via dominance
+ # C4355: 'this' : used in base member initializer list
+ # C4503: 'function' : decorated name length exceeded, name was truncated
+ # C4800: 'type' : forcing value to bool 'true' or 'false'
+ # (performance warning)
+ # C4996: 'function': was declared deprecated
+ ELSE()
+ SET(CXX_WARNING "-Wall")
+ ENDIF()
+ENDIF()
+SET(LEMON_CXX_WARNING_FLAGS ${CXX_WARNING} CACHE STRING "LEMON warning flags.")
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LEMON_CXX_WARNING_FLAGS}")
+
+IF(MSVC)
+ SET( CMAKE_CXX_FLAGS_MAINTAINER "/WX ${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING
+ "Flags used by the C++ compiler during maintainer builds."
+ )
+ SET( CMAKE_C_FLAGS_MAINTAINER "/WX ${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING
+ "Flags used by the C compiler during maintainer builds."
+ )
+ SET( CMAKE_EXE_LINKER_FLAGS_MAINTAINER
+ "${CMAKE_EXE_LINKER_FLAGS_DEBUG}" CACHE STRING
+ "Flags used for linking binaries during maintainer builds."
+ )
+ SET( CMAKE_SHARED_LINKER_FLAGS_MAINTAINER
+ "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE STRING
+ "Flags used by the shared libraries linker during maintainer builds."
+ )
+ELSE()
+ SET( CMAKE_CXX_FLAGS_MAINTAINER "-Werror -ggdb -O0" CACHE STRING
+ "Flags used by the C++ compiler during maintainer builds."
+ )
+ SET( CMAKE_C_FLAGS_MAINTAINER "-Werror -O0" CACHE STRING
+ "Flags used by the C compiler during maintainer builds."
+ )
+ SET( CMAKE_EXE_LINKER_FLAGS_MAINTAINER
+ "${CMAKE_EXE_LINKER_FLAGS_DEBUG}" CACHE STRING
+ "Flags used for linking binaries during maintainer builds."
+ )
+ SET( CMAKE_SHARED_LINKER_FLAGS_MAINTAINER
+ "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE STRING
+ "Flags used by the shared libraries linker during maintainer builds."
+ )
+ENDIF()
+
+MARK_AS_ADVANCED(
+ CMAKE_CXX_FLAGS_MAINTAINER
+ CMAKE_C_FLAGS_MAINTAINER
+ CMAKE_EXE_LINKER_FLAGS_MAINTAINER
+ CMAKE_SHARED_LINKER_FLAGS_MAINTAINER )
+
+IF(CMAKE_CONFIGURATION_TYPES)
+ LIST(APPEND CMAKE_CONFIGURATION_TYPES Maintainer)
+ LIST(REMOVE_DUPLICATES CMAKE_CONFIGURATION_TYPES)
+ SET(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" CACHE STRING
+ "Add the configurations that we need"
+ FORCE)
+ endif()
+
+IF(NOT CMAKE_BUILD_TYPE)
+ SET(CMAKE_BUILD_TYPE "Release")
+ENDIF()
+
+SET( CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
+ "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel Maintainer."
+ FORCE )
+
+
+INCLUDE(CheckTypeSize)
+CHECK_TYPE_SIZE("long long" LONG_LONG)
+SET(LEMON_HAVE_LONG_LONG ${HAVE_LONG_LONG})
+
+INCLUDE(FindThreads)
+
+IF(NOT LEMON_THREADING)
+ IF(CMAKE_USE_PTHREADS_INIT)
+ SET(LEMON_THREADING "Pthread")
+ ELSEIF(CMAKE_USE_WIN32_THREADS_INIT)
+ SET(LEMON_THREADING "Win32")
+ ELSE()
+ SET(LEMON_THREADING "None")
+ ENDIF()
+ENDIF()
+
+SET( LEMON_THREADING "${LEMON_THREADING}" CACHE STRING
+ "Choose the threading library, options are: Pthread Win32 None."
+ FORCE )
+
+IF(LEMON_THREADING STREQUAL "Pthread")
+ SET(LEMON_USE_PTHREAD TRUE)
+ELSEIF(LEMON_THREADING STREQUAL "Win32")
+ SET(LEMON_USE_WIN32_THREADS TRUE)
+ENDIF()
+
+ENABLE_TESTING()
+
+IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer")
+ ADD_CUSTOM_TARGET(check ALL COMMAND ${CMAKE_CTEST_COMMAND})
+ELSE()
+ ADD_CUSTOM_TARGET(check COMMAND ${CMAKE_CTEST_COMMAND})
+ENDIF()
+
+ADD_SUBDIRECTORY(lemon)
+IF(${CMAKE_SOURCE_DIR} STREQUAL ${PROJECT_SOURCE_DIR})
+ ADD_SUBDIRECTORY(contrib)
+ ADD_SUBDIRECTORY(demo)
+ ADD_SUBDIRECTORY(tools)
+ ADD_SUBDIRECTORY(doc)
+ ADD_SUBDIRECTORY(test)
+ENDIF()
+
+CONFIGURE_FILE(
+ ${PROJECT_SOURCE_DIR}/cmake/LEMONConfig.cmake.in
+ ${PROJECT_BINARY_DIR}/cmake/LEMONConfig.cmake
+ @ONLY
+)
+IF(UNIX)
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/cmake/LEMONConfig.cmake
+ DESTINATION share/lemon/cmake
+ )
+ELSEIF(WIN32)
+ INSTALL(
+ FILES ${PROJECT_BINARY_DIR}/cmake/LEMONConfig.cmake
+ DESTINATION cmake
+ )
+ENDIF()
+
+CONFIGURE_FILE(
+ ${PROJECT_SOURCE_DIR}/cmake/version.cmake.in
+ ${PROJECT_BINARY_DIR}/cmake/version.cmake
+ @ONLY
+)
+
+SET(ARCHIVE_BASE_NAME ${CMAKE_PROJECT_NAME})
+STRING(TOLOWER ${ARCHIVE_BASE_NAME} ARCHIVE_BASE_NAME)
+SET(ARCHIVE_NAME ${ARCHIVE_BASE_NAME}-${PROJECT_VERSION})
+ADD_CUSTOM_TARGET(dist
+ COMMAND cmake -E remove_directory ${ARCHIVE_NAME}
+ COMMAND hg archive ${ARCHIVE_NAME}
+ COMMAND cmake -E copy cmake/version.cmake ${ARCHIVE_NAME}/cmake/version.cmake
+ COMMAND tar -czf ${ARCHIVE_BASE_NAME}-nodoc-${PROJECT_VERSION}.tar.gz ${ARCHIVE_NAME}
+ COMMAND zip -r ${ARCHIVE_BASE_NAME}-nodoc-${PROJECT_VERSION}.zip ${ARCHIVE_NAME}
+ COMMAND cmake -E copy_directory doc/html ${ARCHIVE_NAME}/doc/html
+ COMMAND tar -czf ${ARCHIVE_NAME}.tar.gz ${ARCHIVE_NAME}
+ COMMAND zip -r ${ARCHIVE_NAME}.zip ${ARCHIVE_NAME}
+ COMMAND cmake -E copy_directory doc/html ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}
+ COMMAND tar -czf ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}.tar.gz ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}
+ COMMAND zip -r ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}.zip ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}
+ COMMAND cmake -E remove_directory ${ARCHIVE_NAME}
+ COMMAND cmake -E remove_directory ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}
+ DEPENDS html
+ WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
+
+# CPACK config (Basically for NSIS)
+IF(${CMAKE_SOURCE_DIR} STREQUAL ${PROJECT_SOURCE_DIR})
+ SET(CPACK_PACKAGE_NAME ${PROJECT_NAME})
+ SET(CPACK_PACKAGE_VENDOR "EGRES")
+ SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY
+ "LEMON - Library for Efficient Modeling and Optimization in Networks")
+ SET(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
+
+ SET(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
+
+ SET(CPACK_PACKAGE_INSTALL_DIRECTORY
+ "${PROJECT_NAME} ${PROJECT_VERSION}")
+ SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY
+ "${PROJECT_NAME} ${PROJECT_VERSION}")
+
+ SET(CPACK_COMPONENTS_ALL headers library html_documentation bin)
+
+ SET(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C++ headers")
+ SET(CPACK_COMPONENT_LIBRARY_DISPLAY_NAME "Dynamic-link library")
+ SET(CPACK_COMPONENT_BIN_DISPLAY_NAME "Command line utilities")
+ SET(CPACK_COMPONENT_HTML_DOCUMENTATION_DISPLAY_NAME "HTML documentation")
+
+ SET(CPACK_COMPONENT_HEADERS_DESCRIPTION
+ "C++ header files")
+ SET(CPACK_COMPONENT_LIBRARY_DESCRIPTION
+ "DLL and import library")
+ SET(CPACK_COMPONENT_BIN_DESCRIPTION
+ "Command line utilities")
+ SET(CPACK_COMPONENT_HTML_DOCUMENTATION_DESCRIPTION
+ "Doxygen generated documentation")
+
+ SET(CPACK_COMPONENT_HEADERS_DEPENDS library)
+
+ SET(CPACK_COMPONENT_HEADERS_GROUP "Development")
+ SET(CPACK_COMPONENT_LIBRARY_GROUP "Development")
+ SET(CPACK_COMPONENT_HTML_DOCUMENTATION_GROUP "Documentation")
+
+ SET(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION
+ "Components needed to develop software using LEMON")
+ SET(CPACK_COMPONENT_GROUP_DOCUMENTATION_DESCRIPTION
+ "Documentation of LEMON")
+
+ SET(CPACK_ALL_INSTALL_TYPES Full Developer)
+
+ SET(CPACK_COMPONENT_HEADERS_INSTALL_TYPES Developer Full)
+ SET(CPACK_COMPONENT_LIBRARY_INSTALL_TYPES Developer Full)
+ SET(CPACK_COMPONENT_HTML_DOCUMENTATION_INSTALL_TYPES Full)
+
+ SET(CPACK_GENERATOR "NSIS")
+ SET(CPACK_NSIS_MUI_ICON "${PROJECT_SOURCE_DIR}/cmake/nsis/lemon.ico")
+ SET(CPACK_NSIS_MUI_UNIICON "${PROJECT_SOURCE_DIR}/cmake/nsis/uninstall.ico")
+ #SET(CPACK_PACKAGE_ICON "${PROJECT_SOURCE_DIR}/cmake/nsis\\\\installer.bmp")
+ SET(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\lemon.ico")
+ SET(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} ${PROJECT_NAME}")
+ SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\lemon.cs.elte.hu")
+ SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\lemon.cs.elte.hu")
+ SET(CPACK_NSIS_CONTACT "lemon-user@lemon.cs.elte.hu")
+ SET(CPACK_NSIS_CREATE_ICONS_EXTRA "
+ CreateShortCut \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Documentation.lnk\\\" \\\"$INSTDIR\\\\share\\\\doc\\\\index.html\\\"
+ ")
+ SET(CPACK_NSIS_DELETE_ICONS_EXTRA "
+ !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP
+ Delete \\\"$SMPROGRAMS\\\\$MUI_TEMP\\\\Documentation.lnk\\\"
+ ")
+
+ INCLUDE(CPack)
+ENDIF()
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/INSTALL b/extern/quadriflow/3rd/lemon-1.3.1/INSTALL
new file mode 100644
index 00000000000..3fba5b263f7
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/INSTALL
@@ -0,0 +1,167 @@
+Installation Instructions
+=========================
+
+This file contains instructions for building and installing LEMON from
+source on Linux. The process on Windows is similar.
+
+Note that it is not necessary to install LEMON in order to use
+it. Instead, you can easily integrate it with your own code
+directly. For instructions, see
+https://lemon.cs.elte.hu/trac/lemon/wiki/HowToCompile
+
+
+In order to install LEMON from the extracted source tarball you have to
+issue the following commands:
+
+ 1. Step into the root of the source directory.
+
+ $ cd lemon-x.y.z
+
+ 2. Create a build subdirectory and step into it.
+
+ $ mkdir build
+ $ cd build
+
+ 3. Perform system checks and create the makefiles.
+
+ $ cmake ..
+
+ 4. Build LEMON.
+
+ $ make
+
+ This command compiles the non-template part of LEMON into
+ libemon.a file. It also compiles the programs in the 'tools' and
+ 'demo' subdirectories.
+
+ 5. [Optional] Compile and run the self-tests.
+
+ $ make check
+
+ 5. [Optional] Generate the user documentation.
+
+ $ make html
+
+ The release tarballs already include the documentation.
+
+ Note that for this step you need to have the following tools
+ installed: Python, Doxygen, Graphviz, Ghostscript, LaTeX.
+
+ 6. [Optional] Install LEMON
+
+ $ make install
+
+ This command installs LEMON under /usr/local (you will need root
+ privileges to be able to do that). If you want to install it to
+ some other location, then pass the
+ -DCMAKE_INSTALL_PREFIX=DIRECTORY flag to cmake in Step 3.
+ For example:
+
+ $ cmake -DCMAKE_INSTALL_PREFIX=/home/username/lemon'
+
+Configure Options and Variables
+===============================
+
+In Step 3, you can customize the build process by passing options to CMAKE.
+
+$ cmake [OPTIONS] ..
+
+You find a list of the most useful options below.
+
+-DCMAKE_INSTALL_PREFIX=PREFIX
+
+ Set the installation prefix to PREFIX. By default it is /usr/local.
+
+-DCMAKE_BUILD_TYPE=[Release|Debug|Maintainer|...]
+
+ This sets the compiler options. The choices are the following
+
+ 'Release': A strong optimization is turned on (-O3 with gcc). This
+ is the default setting and we strongly recommend using this for
+ the final compilation.
+
+ 'Debug': Optimization is turned off and debug info is added (-O0
+ -ggdb with gcc). If is recommended during the development.
+
+ 'Maintainer': The same as 'Debug' but the compiler warnings are
+ converted to errors (-Werror with gcc). In addition, 'make' will
+ also automatically compile and execute the test codes. It is the
+ best way of ensuring that LEMON codebase is clean and safe.
+
+ 'RelWithDebInfo': Optimized build with debug info.
+
+ 'MinSizeRel': Size optimized build (-Os with gcc)
+
+-DTEST_WITH_VALGRIND=YES
+
+ Using this, the test codes will be executed using valgrind. It is a
+ very effective way of identifying indexing problems and memory leaks.
+
+-DCMAKE_CXX_COMPILER=path-to-compiler
+
+ Change the compiler to be used.
+
+-DBUILD_SHARED_LIBS=TRUE
+
+ Build shared library instead of static one. Think twice if you
+ really want to use this option.
+
+-DLEMON_DOC_SOURCE_BROWSER=YES
+
+ Include the browsable cross referenced LEMON source code into the
+ doc. It makes the doc quite bloated, but may be useful for
+ developing LEMON itself.
+
+-DLEMON_DOC_USE_MATHJAX=YES
+
+ Use MathJax (http://mathjax.org) for rendering the math formulae in
+ the doc. It of much higher quality compared to the default LaTeX
+ generated static images and it allows copy&paste of the formulae to
+ LaTeX, Open Office, MS Word etc. documents.
+
+ On the other hand, it needs either Internet access or a locally
+ installed version of MathJax to properly render the doc.
+
+-DLEMON_DOC_MATHJAX_RELPATH=DIRECTORY
+
+ The location of the MathJax library. It defaults to
+ http://www.mathjax.org/mathjax, which necessitates Internet access
+ for proper rendering. The easiest way to make it usable offline is
+ to set this parameter to 'mathjax' and copy all files of the MathJax
+ library into the 'doc/html/mathjax' subdirectory of the build
+ location.
+
+ See http://docs.mathjax.org/en/latest/installation.html for more details.
+
+
+-DLEMON_ENABLE_GLPK=NO
+-DLEMON_ENABLE_COIN=NO
+-DLEMON_ENABLE_ILOG=NO
+
+ Enable optional third party libraries. They are all enabled by default.
+
+-DLEMON_DEFAULT_LP=GLPK
+
+ Sets the default LP solver backend. The supported values are
+ CPLEX, CLP and GLPK. By default, it is set to the first one which
+ is enabled and succesfully discovered.
+
+-DLEMON_DEFAULT_MIP=GLPK
+
+ Sets the default MIP solver backend. The supported values are
+ CPLEX, CBC and GLPK. By default, it is set to the first one which
+ is enabled and succesfully discovered.
+
+-DGLPK_ROOT_DIR=DIRECTORY
+-DCOIN_ROOT_DIR=DIRECTORY
+-DILOG_ROOT_DIR=DIRECTORY
+
+ Root directory prefixes of optional third party libraries.
+
+Makefile Variables
+==================
+
+make VERBOSE=1
+
+ This results in a more verbose output by showing the full
+ compiler and linker commands. \ No newline at end of file
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/LICENSE b/extern/quadriflow/3rd/lemon-1.3.1/LICENSE
new file mode 100644
index 00000000000..5b1c4255062
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/LICENSE
@@ -0,0 +1,32 @@
+LEMON code without an explicit copyright notice is covered by the following
+copyright/license.
+
+Copyright (C) 2003-2012 Egervary Jeno Kombinatorikus Optimalizalasi
+Kutatocsoport (Egervary Combinatorial Optimization Research Group,
+EGRES).
+
+===========================================================================
+Boost Software License, Version 1.0
+===========================================================================
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/NEWS b/extern/quadriflow/3rd/lemon-1.3.1/NEWS
new file mode 100644
index 00000000000..7908ca3a455
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/NEWS
@@ -0,0 +1,337 @@
+2014-07-07 Version 1.3.1 released
+
+ Bugfix release.
+
+ #484: Require CMAKE 2.8
+ #471, #472, #480: Various clang compatibility fixes
+ #481, #482: Fix shared lib build and versioning
+ #476: Fix invalid map query in NearestNeighborTsp
+ #478: Bugfix in debug checking and lower bound handling
+ in min cost flow algorithms
+ #479, #465: Bugfix in default LP/MIP backend settings
+ #476: Bugfix in tsp_test
+ #487: Add missing include header and std:: namespace spec.
+ #474: Fix division by zero error in NetworkSimplex
+
+2013-08-10 Version 1.3 released
+
+ This is major feature release
+
+ * New data structures
+
+ #69 : Bipartite graph concepts and implementations
+
+ * New algorithms
+
+ #177: Port Edmonds-Karp algorithm
+ #380, #405: Heuristic algorithm for the max clique problem
+ #386: Heuristic algorithms for symmetric TSP
+ ----: Nagamochi-Ibaraki algorithm [5087694945e4]
+ #397, #56: Max. cardinality search
+
+ * Other new features
+
+ #223: Thread safe graph and graph map implementations
+ #442: Different TimeStamp print formats
+ #457: File export functionality to LpBase
+ #362: Bidirectional iterator support for radixSort()
+
+ * Implementation improvements
+
+ ----: Network Simplex
+ #391: Better update process, pivot rule and arc mixing
+ #435: Improved Altering List pivot rule
+ #417: Various fine tunings in CostScaling
+ #438: Optional iteration limit in HowardMmc
+ #436: Ensure strongly polynomial running time for CycleCanceling
+ while keeping the same performance
+ ----: Make the CBC interface be compatible with latest CBC releases
+ [ee581a0ecfbf]
+
+ * CMAKE has become the default build environment (#434)
+
+ ----: Autotool support has been dropped
+ ----: Improved LP/MIP configuration
+ #465: Enable/disable options for LP/MIP backends
+ #446: Better CPLEX discovery
+ #460: Add cmake config to find SoPlex
+ ----: Allow CPACK configuration on all platforms
+ #390: Add 'Maintainer' CMAKE build type
+ #388: Add 'check' target.
+ #401: Add contrib dir
+ #389: Better version string setting in CMAKE
+ #433: Support shared library build
+ #416: Support testing with valgrind
+
+ * Doc improvements
+
+ #395: SOURCE_BROWSER Doxygen switch is configurable from CMAKE
+ update-external-tags CMAKE target
+ #455: Optionally use MathJax for rendering the math formulae
+ #402, #437, #459, #456, #463: Various doc improvements
+
+ * Bugfixes (compared to release 1.2):
+
+ #432: Add missing doc/template.h and doc/references.bib to release
+ tarball
+ ----: Intel C++ compatibility fixes
+ #441: Fix buggy reinitialization in _solver_bits::VarIndex::clear()
+ #444: Bugfix in path copy constructors and assignment operators
+ #447: Bugfix in AllArcLookUp<>
+ #448: Bugfix in adaptor_test.cc
+ #449: Fix clang compilation warnings and errors
+ #440: Fix a bug + remove redundant typedefs in dimacs-solver
+ #453: Avoid GCC 4.7 compiler warnings
+ #445: Fix missing initialization in CplexEnv::CplexEnv()
+ #428: Add missing lemon/lemon.pc.cmake to the release tarball
+ #393: Create and install lemon.pc
+ #429: Fix VS warnings
+ #430: Fix LpBase::Constr two-side limit bug
+ #392: Bug fix in Dfs::start(s,t)
+ #414: Fix wrong initialization in Preflow
+ #418: Better Win CodeBlock/MinGW support
+ #419: Build environment improvements
+ - Build of mip_test and lp_test precede the running of the tests
+ - Also search for coin libs under ${COIN_ROOT_DIR}/lib/coin
+ - Do not look for COIN_VOL libraries
+ #382: Allow lgf file without Arc maps
+ #417: Bug fix in CostScaling
+ #366: Fix Pred[Matrix]MapPath::empty()
+ #371: Bug fix in (di)graphCopy()
+ The target graph is cleared before adding nodes and arcs/edges.
+ #364: Add missing UndirectedTags
+ #368: Fix the usage of std::numeric_limits<>::min() in Network Simplex
+ #372: Fix a critical bug in preflow
+ #461: Bugfix in assert.h
+ #470: Fix compilation issues related to various gcc versions
+ #446: Fix #define indicating CPLEX availability
+ #294: Add explicit namespace to
+ ignore_unused_variable_warning() usages
+ #420: Bugfix in IterableValueMap
+ #439: Bugfix in biNodeConnected()
+
+
+2010-03-19 Version 1.2 released
+
+ This is major feature release
+
+ * New algorithms
+ * Bellman-Ford algorithm (#51)
+ * Minimum mean cycle algorithms (#179)
+ * Karp, Hartman-Orlin and Howard algorithms
+ * New minimum cost flow algorithms (#180)
+ * Cost Scaling algorithms
+ * Capacity Scaling algorithm
+ * Cycle-Canceling algorithms
+ * Planarity related algorithms (#62)
+ * Planarity checking algorithm
+ * Planar embedding algorithm
+ * Schnyder's planar drawing algorithm
+ * Coloring planar graphs with five or six colors
+ * Fractional matching algorithms (#314)
+ * New data structures
+ * StaticDigraph structure (#68)
+ * Several new priority queue structures (#50, #301)
+ * Fibonacci, Radix, Bucket, Pairing, Binomial
+ D-ary and fourary heaps (#301)
+ * Iterable map structures (#73)
+ * Other new tools and functionality
+ * Map utility functions (#320)
+ * Reserve functions are added to ListGraph and SmartGraph (#311)
+ * A resize() function is added to HypercubeGraph (#311)
+ * A count() function is added to CrossRefMap (#302)
+ * Support for multiple targets in Suurballe using fullInit() (#181)
+ * Traits class and named parameters for Suurballe (#323)
+ * Separate reset() and resetParams() functions in NetworkSimplex
+ to handle graph changes (#327)
+ * tolerance() functions are added to HaoOrlin (#306)
+ * Implementation improvements
+ * Improvements in weighted matching algorithms (#314)
+ * Jumpstart initialization
+ * ArcIt iteration is based on out-arc lists instead of in-arc lists
+ in ListDigraph (#311)
+ * Faster add row operation in CbcMip (#203)
+ * Better implementation for split() in ListDigraph (#311)
+ * ArgParser can also throw exception instead of exit(1) (#332)
+ * Miscellaneous
+ * A simple interactive bootstrap script
+ * Doc improvements (#62,#180,#299,#302,#303,#304,#307,#311,#331,#315,
+ #316,#319)
+ * BibTeX references in the doc (#184)
+ * Optionally use valgrind when running tests
+ * Also check ReferenceMapTag in concept checks (#312)
+ * dimacs-solver uses long long type by default.
+ * Several bugfixes (compared to release 1.1):
+ #295: Suppress MSVC warnings using pragmas
+ ----: Various CMAKE related improvements
+ * Remove duplications from doc/CMakeLists.txt
+ * Rename documentation install folder from 'docs' to 'html'
+ * Add tools/CMakeLists.txt to the tarball
+ * Generate and install LEMONConfig.cmake
+ * Change the label of the html project in Visual Studio
+ * Fix the check for the 'long long' type
+ * Put the version string into config.h
+ * Minor CMake improvements
+ * Set the version to 'hg-tip' if everything fails
+ #311: Add missing 'explicit' keywords
+ #302: Fix the implementation and doc of CrossRefMap
+ #308: Remove duplicate list_graph.h entry from source list
+ #307: Bugfix in Preflow and Circulation
+ #305: Bugfix and extension in the rename script
+ #312: Also check ReferenceMapTag in concept checks
+ #250: Bugfix in pathSource() and pathTarget()
+ #321: Use pathCopy(from,to) instead of copyPath(to,from)
+ #322: Distribure LEMONConfig.cmake.in
+ #330: Bug fix in map_extender.h
+ #336: Fix the date field comment of graphToEps() output
+ #323: Bug fix in Suurballe
+ #335: Fix clear() function in ExtendFindEnum
+ #337: Use void* as the LPX object pointer
+ #317: Fix (and improve) error message in mip_test.cc
+ Remove unnecessary OsiCbc dependency
+ #356: Allow multiple executions of weighted matching algorithms (#356)
+
+2009-05-13 Version 1.1 released
+
+ This is the second stable release of the 1.x series. It
+ features a better coverage of the tools available in the 0.x
+ series, a thoroughly reworked LP/MIP interface plus various
+ improvements in the existing tools.
+
+ * Much improved M$ Windows support
+ * Various improvements in the CMAKE build system
+ * Compilation warnings are fixed/suppressed
+ * Support IBM xlC compiler
+ * New algorithms
+ * Connectivity related algorithms (#61)
+ * Euler walks (#65)
+ * Preflow push-relabel max. flow algorithm (#176)
+ * Circulation algorithm (push-relabel based) (#175)
+ * Suurballe algorithm (#47)
+ * Gomory-Hu algorithm (#66)
+ * Hao-Orlin algorithm (#58)
+ * Edmond's maximum cardinality and weighted matching algorithms
+ in general graphs (#48,#265)
+ * Minimum cost arborescence/branching (#60)
+ * Network Simplex min. cost flow algorithm (#234)
+ * New data structures
+ * Full graph structure (#57)
+ * Grid graph structure (#57)
+ * Hypercube graph structure (#57)
+ * Graph adaptors (#67)
+ * ArcSet and EdgeSet classes (#67)
+ * Elevator class (#174)
+ * Other new tools
+ * LP/MIP interface (#44)
+ * Support for GLPK, CPLEX, Soplex, COIN-OR CLP and CBC
+ * Reader for the Nauty file format (#55)
+ * DIMACS readers (#167)
+ * Radix sort algorithms (#72)
+ * RangeIdMap and CrossRefMap (#160)
+ * New command line tools
+ * DIMACS to LGF converter (#182)
+ * lgf-gen - a graph generator (#45)
+ * DIMACS solver utility (#226)
+ * Other code improvements
+ * Lognormal distribution added to Random (#102)
+ * Better (i.e. O(1) time) item counting in SmartGraph (#3)
+ * The standard maps of graphs are guaranteed to be
+ reference maps (#190)
+ * Miscellaneous
+ * Various doc improvements
+ * Improved 0.x -> 1.x converter script
+
+ * Several bugfixes (compared to release 1.0):
+ #170: Bugfix SmartDigraph::split()
+ #171: Bugfix in SmartGraph::restoreSnapshot()
+ #172: Extended test cases for graphs and digraphs
+ #173: Bugfix in Random
+ * operator()s always return a double now
+ * the faulty real<Num>(Num) and real<Num>(Num,Num)
+ have been removed
+ #187: Remove DijkstraWidestPathOperationTraits
+ #61: Bugfix in DfsVisit
+ #193: Bugfix in GraphReader::skipSection()
+ #195: Bugfix in ConEdgeIt()
+ #197: Bugfix in heap unionfind
+ * This bug affects Edmond's general matching algorithms
+ #207: Fix 'make install' without 'make html' using CMAKE
+ #208: Suppress or fix VS2008 compilation warnings
+ ----: Update the LEMON icon
+ ----: Enable the component-based installer
+ (in installers made by CPACK)
+ ----: Set the proper version for CMAKE in the tarballs
+ (made by autotools)
+ ----: Minor clarification in the LICENSE file
+ ----: Add missing unistd.h include to time_measure.h
+ #204: Compilation bug fixed in graph_to_eps.h with VS2005
+ #214,#215: windows.h should never be included by LEMON headers
+ #230: Build systems check the availability of 'long long' type
+ #229: Default implementation of Tolerance<> is used for integer types
+ #211,#212: Various fixes for compiling on AIX
+ ----: Improvements in CMAKE config
+ - docs is installed in share/doc/
+ - detects newer versions of Ghostscript
+ #239: Fix missing 'inline' specifier in time_measure.h
+ #274,#280: Install lemon/config.h
+ #275: Prefix macro names with LEMON_ in lemon/config.h
+ ----: Small script for making the release tarballs added
+ ----: Minor improvement in unify-sources.sh (a76f55d7d397)
+
+2009-03-27 LEMON joins to the COIN-OR initiative
+
+ COIN-OR (Computational Infrastructure for Operations Research,
+ http://www.coin-or.org) project is an initiative to spur the
+ development of open-source software for the operations research
+ community.
+
+2008-10-13 Version 1.0 released
+
+ This is the first stable release of LEMON. Compared to the 0.x
+ release series, it features a considerably smaller but more
+ matured set of tools. The API has also completely revised and
+ changed in several places.
+
+ * The major name changes compared to the 0.x series (see the
+ Migration Guide in the doc for more details)
+ * Graph -> Digraph, UGraph -> Graph
+ * Edge -> Arc, UEdge -> Edge
+ * source(UEdge)/target(UEdge) -> u(Edge)/v(Edge)
+ * Other improvements
+ * Better documentation
+ * Reviewed and cleaned up codebase
+ * CMake based build system (along with the autotools based one)
+ * Contents of the library (ported from 0.x)
+ * Algorithms
+ * breadth-first search (bfs.h)
+ * depth-first search (dfs.h)
+ * Dijkstra's algorithm (dijkstra.h)
+ * Kruskal's algorithm (kruskal.h)
+ * Data structures
+ * graph data structures (list_graph.h, smart_graph.h)
+ * path data structures (path.h)
+ * binary heap data structure (bin_heap.h)
+ * union-find data structures (unionfind.h)
+ * miscellaneous property maps (maps.h)
+ * two dimensional vector and bounding box (dim2.h)
+ * Concepts
+ * graph structure concepts (concepts/digraph.h, concepts/graph.h,
+ concepts/graph_components.h)
+ * concepts for other structures (concepts/heap.h, concepts/maps.h,
+ concepts/path.h)
+ * Tools
+ * Mersenne twister random number generator (random.h)
+ * tools for measuring cpu and wall clock time (time_measure.h)
+ * tools for counting steps and events (counter.h)
+ * tool for parsing command line arguments (arg_parser.h)
+ * tool for visualizing graphs (graph_to_eps.h)
+ * tools for reading and writing data in LEMON Graph Format
+ (lgf_reader.h, lgf_writer.h)
+ * tools to handle the anomalies of calculations with
+ floating point numbers (tolerance.h)
+ * tools to manage RGB colors (color.h)
+ * Infrastructure
+ * extended assertion handling (assert.h)
+ * exception classes and error handling (error.h)
+ * concept checking (concept_check.h)
+ * commonly used mathematical constants (math.h)
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/README b/extern/quadriflow/3rd/lemon-1.3.1/README
new file mode 100644
index 00000000000..52a768c3911
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/README
@@ -0,0 +1,50 @@
+=====================================================================
+LEMON - a Library for Efficient Modeling and Optimization in Networks
+=====================================================================
+
+LEMON is an open source library written in C++. It provides
+easy-to-use implementations of common data structures and algorithms
+in the area of optimization and helps implementing new ones. The main
+focus is on graphs and graph algorithms, thus it is especially
+suitable for solving design and optimization problems of
+telecommunication networks. To achieve wide usability its data
+structures and algorithms provide generic interfaces.
+
+Contents
+========
+
+LICENSE
+
+ Copying, distribution and modification conditions and terms.
+
+NEWS
+
+ News and version history.
+
+INSTALL
+
+ General building and installation instructions.
+
+lemon/
+
+ Source code of LEMON library.
+
+doc/
+
+ Documentation of LEMON. The starting page is doc/html/index.html.
+
+demo/
+
+ Some example programs to make you easier to get familiar with LEMON.
+
+scripts/
+
+ Scripts that make it easier to develop LEMON.
+
+test/
+
+ Programs to check the integrity and correctness of LEMON.
+
+tools/
+
+ Various utilities related to LEMON.
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/cmake/FindCOIN.cmake b/extern/quadriflow/3rd/lemon-1.3.1/cmake/FindCOIN.cmake
new file mode 100644
index 00000000000..d4ed735df94
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/cmake/FindCOIN.cmake
@@ -0,0 +1,110 @@
+SET(COIN_ROOT_DIR "" CACHE PATH "COIN root directory")
+
+FIND_PATH(COIN_INCLUDE_DIR coin/CoinUtilsConfig.h
+ HINTS ${COIN_ROOT_DIR}/include
+)
+FIND_LIBRARY(COIN_CBC_LIBRARY
+ NAMES Cbc libCbc
+ HINTS ${COIN_ROOT_DIR}/lib/coin
+ HINTS ${COIN_ROOT_DIR}/lib
+)
+FIND_LIBRARY(COIN_CBC_SOLVER_LIBRARY
+ NAMES CbcSolver libCbcSolver
+ HINTS ${COIN_ROOT_DIR}/lib/coin
+ HINTS ${COIN_ROOT_DIR}/lib
+)
+FIND_LIBRARY(COIN_CGL_LIBRARY
+ NAMES Cgl libCgl
+ HINTS ${COIN_ROOT_DIR}/lib/coin
+ HINTS ${COIN_ROOT_DIR}/lib
+)
+FIND_LIBRARY(COIN_CLP_LIBRARY
+ NAMES Clp libClp
+ HINTS ${COIN_ROOT_DIR}/lib/coin
+ HINTS ${COIN_ROOT_DIR}/lib
+)
+FIND_LIBRARY(COIN_COIN_UTILS_LIBRARY
+ NAMES CoinUtils libCoinUtils
+ HINTS ${COIN_ROOT_DIR}/lib/coin
+ HINTS ${COIN_ROOT_DIR}/lib
+)
+FIND_LIBRARY(COIN_OSI_LIBRARY
+ NAMES Osi libOsi
+ HINTS ${COIN_ROOT_DIR}/lib/coin
+ HINTS ${COIN_ROOT_DIR}/lib
+)
+FIND_LIBRARY(COIN_OSI_CBC_LIBRARY
+ NAMES OsiCbc libOsiCbc
+ HINTS ${COIN_ROOT_DIR}/lib/coin
+ HINTS ${COIN_ROOT_DIR}/lib
+)
+FIND_LIBRARY(COIN_OSI_CLP_LIBRARY
+ NAMES OsiClp libOsiClp
+ HINTS ${COIN_ROOT_DIR}/lib/coin
+ HINTS ${COIN_ROOT_DIR}/lib
+)
+FIND_LIBRARY(COIN_OSI_VOL_LIBRARY
+ NAMES OsiVol libOsiVol
+ HINTS ${COIN_ROOT_DIR}/lib/coin
+ HINTS ${COIN_ROOT_DIR}/lib
+)
+FIND_LIBRARY(COIN_VOL_LIBRARY
+ NAMES Vol libVol
+ HINTS ${COIN_ROOT_DIR}/lib/coin
+ HINTS ${COIN_ROOT_DIR}/lib
+)
+
+FIND_LIBRARY(COIN_ZLIB_LIBRARY
+ NAMES z libz
+ HINTS ${COIN_ROOT_DIR}/lib/coin
+ HINTS ${COIN_ROOT_DIR}/lib
+)
+FIND_LIBRARY(COIN_BZ2_LIBRARY
+ NAMES bz2 libbz2
+ HINTS ${COIN_ROOT_DIR}/lib/coin
+ HINTS ${COIN_ROOT_DIR}/lib
+)
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(COIN DEFAULT_MSG
+ COIN_INCLUDE_DIR
+ COIN_CBC_LIBRARY
+ COIN_CBC_SOLVER_LIBRARY
+ COIN_CGL_LIBRARY
+ COIN_CLP_LIBRARY
+ COIN_COIN_UTILS_LIBRARY
+ COIN_OSI_LIBRARY
+ COIN_OSI_CBC_LIBRARY
+ COIN_OSI_CLP_LIBRARY
+ # COIN_OSI_VOL_LIBRARY
+ # COIN_VOL_LIBRARY
+)
+
+IF(COIN_FOUND)
+ SET(COIN_INCLUDE_DIRS ${COIN_INCLUDE_DIR})
+ SET(COIN_CLP_LIBRARIES "${COIN_CLP_LIBRARY};${COIN_COIN_UTILS_LIBRARY};${COIN_ZLIB_LIBRARY};${COIN_BZ2_LIBRARY}")
+ IF(COIN_ZLIB_LIBRARY)
+ SET(COIN_CLP_LIBRARIES "${COIN_CLP_LIBRARIES};${COIN_ZLIB_LIBRARY}")
+ ENDIF(COIN_ZLIB_LIBRARY)
+ IF(COIN_BZ2_LIBRARY)
+ SET(COIN_CLP_LIBRARIES "${COIN_CLP_LIBRARIES};${COIN_BZ2_LIBRARY}")
+ ENDIF(COIN_BZ2_LIBRARY)
+ SET(COIN_CBC_LIBRARIES "${COIN_CBC_LIBRARY};${COIN_CBC_SOLVER_LIBRARY};${COIN_CGL_LIBRARY};${COIN_OSI_LIBRARY};${COIN_OSI_CBC_LIBRARY};${COIN_OSI_CLP_LIBRARY};${COIN_ZLIB_LIBRARY};${COIN_BZ2_LIBRARY};${COIN_CLP_LIBRARIES}")
+ SET(COIN_LIBRARIES ${COIN_CBC_LIBRARIES})
+ENDIF(COIN_FOUND)
+
+MARK_AS_ADVANCED(
+ COIN_INCLUDE_DIR
+ COIN_CBC_LIBRARY
+ COIN_CBC_SOLVER_LIBRARY
+ COIN_CGL_LIBRARY
+ COIN_CLP_LIBRARY
+ COIN_COIN_UTILS_LIBRARY
+ COIN_OSI_LIBRARY
+ COIN_OSI_CBC_LIBRARY
+ COIN_OSI_CLP_LIBRARY
+ COIN_OSI_VOL_LIBRARY
+ COIN_VOL_LIBRARY
+ COIN_ZLIB_LIBRARY
+ COIN_BZ2_LIBRARY
+)
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/cmake/FindGLPK.cmake b/extern/quadriflow/3rd/lemon-1.3.1/cmake/FindGLPK.cmake
new file mode 100644
index 00000000000..55e5e3ee056
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/cmake/FindGLPK.cmake
@@ -0,0 +1,55 @@
+SET(GLPK_ROOT_DIR "" CACHE PATH "GLPK root directory")
+
+SET(GLPK_REGKEY "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Glpk;InstallPath]")
+GET_FILENAME_COMPONENT(GLPK_ROOT_PATH ${GLPK_REGKEY} ABSOLUTE)
+
+FIND_PATH(GLPK_INCLUDE_DIR
+ glpk.h
+ PATHS ${GLPK_REGKEY}/include
+ HINTS ${GLPK_ROOT_DIR}/include
+)
+FIND_LIBRARY(GLPK_LIBRARY
+ glpk
+ PATHS ${GLPK_REGKEY}/lib
+ HINTS ${GLPK_ROOT_DIR}/lib
+)
+
+IF(GLPK_INCLUDE_DIR AND GLPK_LIBRARY)
+ FILE(READ ${GLPK_INCLUDE_DIR}/glpk.h GLPK_GLPK_H)
+
+ STRING(REGEX MATCH "define[ ]+GLP_MAJOR_VERSION[ ]+[0-9]+" GLPK_MAJOR_VERSION_LINE "${GLPK_GLPK_H}")
+ STRING(REGEX REPLACE "define[ ]+GLP_MAJOR_VERSION[ ]+([0-9]+)" "\\1" GLPK_VERSION_MAJOR "${GLPK_MAJOR_VERSION_LINE}")
+
+ STRING(REGEX MATCH "define[ ]+GLP_MINOR_VERSION[ ]+[0-9]+" GLPK_MINOR_VERSION_LINE "${GLPK_GLPK_H}")
+ STRING(REGEX REPLACE "define[ ]+GLP_MINOR_VERSION[ ]+([0-9]+)" "\\1" GLPK_VERSION_MINOR "${GLPK_MINOR_VERSION_LINE}")
+
+ SET(GLPK_VERSION_STRING "${GLPK_VERSION_MAJOR}.${GLPK_VERSION_MINOR}")
+
+ IF(GLPK_FIND_VERSION)
+ IF(GLPK_FIND_VERSION_COUNT GREATER 2)
+ MESSAGE(SEND_ERROR "unexpected version string")
+ ENDIF(GLPK_FIND_VERSION_COUNT GREATER 2)
+
+ MATH(EXPR GLPK_REQUESTED_VERSION "${GLPK_FIND_VERSION_MAJOR}*100 + ${GLPK_FIND_VERSION_MINOR}")
+ MATH(EXPR GLPK_FOUND_VERSION "${GLPK_VERSION_MAJOR}*100 + ${GLPK_VERSION_MINOR}")
+
+ IF(GLPK_FOUND_VERSION LESS GLPK_REQUESTED_VERSION)
+ SET(GLPK_PROPER_VERSION_FOUND FALSE)
+ ELSE(GLPK_FOUND_VERSION LESS GLPK_REQUESTED_VERSION)
+ SET(GLPK_PROPER_VERSION_FOUND TRUE)
+ ENDIF(GLPK_FOUND_VERSION LESS GLPK_REQUESTED_VERSION)
+ ELSE(GLPK_FIND_VERSION)
+ SET(GLPK_PROPER_VERSION_FOUND TRUE)
+ ENDIF(GLPK_FIND_VERSION)
+ENDIF(GLPK_INCLUDE_DIR AND GLPK_LIBRARY)
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLPK DEFAULT_MSG GLPK_LIBRARY GLPK_INCLUDE_DIR GLPK_PROPER_VERSION_FOUND)
+
+IF(GLPK_FOUND)
+ SET(GLPK_INCLUDE_DIRS ${GLPK_INCLUDE_DIR})
+ SET(GLPK_LIBRARIES ${GLPK_LIBRARY})
+ SET(GLPK_BIN_DIR ${GLPK_ROOT_PATH}/bin)
+ENDIF(GLPK_FOUND)
+
+MARK_AS_ADVANCED(GLPK_LIBRARY GLPK_INCLUDE_DIR GLPK_BIN_DIR)
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/cmake/FindGhostscript.cmake b/extern/quadriflow/3rd/lemon-1.3.1/cmake/FindGhostscript.cmake
new file mode 100644
index 00000000000..3366a000e1b
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/cmake/FindGhostscript.cmake
@@ -0,0 +1,10 @@
+INCLUDE(FindPackageHandleStandardArgs)
+
+FIND_PROGRAM(GHOSTSCRIPT_EXECUTABLE
+ NAMES gs gswin32c
+ PATHS "$ENV{ProgramFiles}/gs"
+ PATH_SUFFIXES gs8.61/bin gs8.62/bin gs8.63/bin gs8.64/bin gs8.65/bin
+ DOC "Ghostscript: PostScript and PDF language interpreter and previewer."
+)
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Ghostscript DEFAULT_MSG GHOSTSCRIPT_EXECUTABLE)
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/cmake/FindILOG.cmake b/extern/quadriflow/3rd/lemon-1.3.1/cmake/FindILOG.cmake
new file mode 100644
index 00000000000..a09fc9a2753
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/cmake/FindILOG.cmake
@@ -0,0 +1,102 @@
+FIND_PATH(ILOG_ROOT_DIR
+ NAMES cplex
+ DOC "CPLEX STUDIO root directory"
+ PATHS /opt/ibm/ILOG /usr/local/ibm/ILOG /usr/local/ILOG /usr/local/ilog
+ PATHS "$ENV{HOME}/ILOG" "$ENV{HOME}/.local/ILOG"
+ PATHS "$ENV{HOME}/ibm/ILOG" "$ENV{HOME}/.local/ibm/ILOG"
+ PATHS "C:/Program Files/IBM/ILOG"
+ PATH_SUFFIXES "CPLEX_Studio126" "CPLEX_Studio125"
+ "CPLEX_Studio124" "CPLEX_Studio123" "CPLEX_Studio122"
+ NO_DEFAULT_PATH
+)
+
+IF(WIN32)
+ IF(MSVC_VERSION STREQUAL "1400")
+ SET(ILOG_WIN_COMPILER "windows_vs2005")
+ ELSEIF(MSVC_VERSION STREQUAL "1500")
+ SET(ILOG_WIN_COMPILER "windows_vs2008")
+ ELSEIF(MSVC_VERSION STREQUAL "1600")
+ SET(ILOG_WIN_COMPILER "windows_vs2010")
+ ELSE()
+ SET(ILOG_WIN_COMPILER "windows_vs2008")
+ ENDIF()
+ IF(CMAKE_CL_64)
+ SET(ILOG_WIN_COMPILER "x64_${ILOG_WIN_COMPILER}")
+ SET(ILOG_WIN_PLATFORM "x64_win32")
+ ELSE()
+ SET(ILOG_WIN_COMPILER "x86_${ILOG_WIN_COMPILER}")
+ SET(ILOG_WIN_PLATFORM "x86_win32")
+ ENDIF()
+ENDIF()
+
+FIND_PATH(ILOG_CPLEX_ROOT_DIR
+ NAMES include/ilcplex
+ HINTS ${ILOG_ROOT_DIR}/cplex ${ILOG_ROOT_DIR}/cplex121
+ ${ILOG_ROOT_DIR}/cplex122 ${ILOG_ROOT_DIR}/cplex123
+ DOC "CPLEX root directory"
+ NO_DEFAULT_PATH
+)
+
+FIND_PATH(ILOG_CONCERT_ROOT_DIR
+ NAMES include/ilconcert
+ HINTS ${ILOG_ROOT_DIR}/concert ${ILOG_ROOT_DIR}/concert29
+ DOC "CONCERT root directory"
+ NO_DEFAULT_PATH
+)
+
+FIND_PATH(ILOG_CPLEX_INCLUDE_DIR
+ ilcplex/cplex.h
+ HINTS ${ILOG_CPLEX_ROOT_DIR}/include
+ NO_DEFAULT_PATH
+)
+
+FIND_PATH(ILOG_CONCERT_INCLUDE_DIR
+ ilconcert/ilobasic.h
+ HINTS ${ILOG_CONCERT_ROOT_DIR}/include
+ NO_DEFAULT_PATH
+)
+
+FIND_LIBRARY(ILOG_CPLEX_LIBRARY
+ cplex cplex121 cplex122 cplex123 cplex124
+ HINTS ${ILOG_CPLEX_ROOT_DIR}/lib/x86_sles10_4.1/static_pic
+ ${ILOG_CPLEX_ROOT_DIR}/lib/x86-64_sles10_4.1/static_pic
+ ${ILOG_CPLEX_ROOT_DIR}/lib/x86_debian4.0_4.1/static_pic
+ ${ILOG_CPLEX_ROOT_DIR}/lib/x86-64_debian4.0_4.1/static_pic
+ ${ILOG_CPLEX_ROOT_DIR}/lib/${ILOG_WIN_COMPILER}/stat_mda
+ NO_DEFAULT_PATH
+ )
+
+FIND_LIBRARY(ILOG_CONCERT_LIBRARY
+ concert
+ HINTS ${ILOG_CONCERT_ROOT_DIR}/lib/x86_sles10_4.1/static_pic
+ ${ILOG_CONCERT_ROOT_DIR}/lib/x86-64_sles10_4.1/static_pic
+ ${ILOG_CONCERT_ROOT_DIR}/lib/x86_debian4.0_4.1/static_pic
+ ${ILOG_CONCERT_ROOT_DIR}/lib/x86-64_debian4.0_4.1/static_pic
+ ${ILOG_CONCERT_ROOT_DIR}/lib/${ILOG_WIN_COMPILER}/stat_mda
+ NO_DEFAULT_PATH
+ )
+
+FIND_FILE(ILOG_CPLEX_DLL
+ cplex121.dll cplex122.dll cplex123.dll cplex124.dll
+ HINTS ${ILOG_CPLEX_ROOT_DIR}/bin/${ILOG_WIN_PLATFORM}
+ NO_DEFAULT_PATH
+ )
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(ILOG
+ DEFAULT_MSG ILOG_CPLEX_LIBRARY ILOG_CPLEX_INCLUDE_DIR
+ )
+
+IF(ILOG_FOUND)
+ SET(ILOG_INCLUDE_DIRS ${ILOG_CPLEX_INCLUDE_DIR} ${ILOG_CONCERT_INCLUDE_DIR})
+ SET(ILOG_LIBRARIES ${ILOG_CPLEX_LIBRARY} ${ILOG_CONCERT_LIBRARY})
+ IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ # SET(CPLEX_LIBRARIES "${CPLEX_LIBRARIES};m;pthread")
+ SET(ILOG_LIBRARIES ${ILOG_LIBRARIES} "m" "pthread")
+ ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ENDIF(ILOG_FOUND)
+
+MARK_AS_ADVANCED(
+ ILOG_CPLEX_LIBRARY ILOG_CPLEX_INCLUDE_DIR ILOG_CPLEX_DLL
+ ILOG_CONCERT_LIBRARY ILOG_CONCERT_INCLUDE_DIR ILOG_CONCERT_DLL
+ )
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/cmake/FindSOPLEX.cmake b/extern/quadriflow/3rd/lemon-1.3.1/cmake/FindSOPLEX.cmake
new file mode 100644
index 00000000000..d27cff0f3e1
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/cmake/FindSOPLEX.cmake
@@ -0,0 +1,23 @@
+SET(SOPLEX_ROOT_DIR "" CACHE PATH "SoPlex root directory")
+
+FIND_PATH(SOPLEX_INCLUDE_DIR
+ soplex.h
+ HINTS ${SOPLEX_ROOT_DIR}/src
+)
+FIND_LIBRARY(SOPLEX_LIBRARY
+ soplex
+ HINTS ${SOPLEX_ROOT_DIR}/lib
+)
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(SOPLEX DEFAULT_MSG SOPLEX_LIBRARY SOPLEX_INCLUDE_DIR)
+
+IF(SOPLEX_FOUND)
+ SET(SOPLEX_INCLUDE_DIRS ${SOPLEX_INCLUDE_DIR})
+ SET(SOPLEX_LIBRARIES ${SOPLEX_LIBRARY})
+ IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ SET(SOPLEX_LIBRARIES "${SOPLEX_LIBRARIES};z")
+ ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ENDIF(SOPLEX_FOUND)
+
+MARK_AS_ADVANCED(SOPLEX_LIBRARY SOPLEX_INCLUDE_DIR)
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/cmake/LEMONConfig.cmake.in b/extern/quadriflow/3rd/lemon-1.3.1/cmake/LEMONConfig.cmake.in
new file mode 100644
index 00000000000..b0d2d8b4c3f
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/cmake/LEMONConfig.cmake.in
@@ -0,0 +1,13 @@
+SET(LEMON_INCLUDE_DIR "@CMAKE_INSTALL_PREFIX@/include" CACHE PATH "LEMON include directory")
+SET(LEMON_INCLUDE_DIRS "${LEMON_INCLUDE_DIR}")
+
+IF(UNIX)
+ SET(LEMON_LIB_NAME "libemon.a")
+ELSEIF(WIN32)
+ SET(LEMON_LIB_NAME "lemon.lib")
+ENDIF(UNIX)
+
+SET(LEMON_LIBRARY "@CMAKE_INSTALL_PREFIX@/lib/${LEMON_LIB_NAME}" CACHE FILEPATH "LEMON library")
+SET(LEMON_LIBRARIES "${LEMON_LIBRARY}")
+
+MARK_AS_ADVANCED(LEMON_LIBRARY LEMON_INCLUDE_DIR)
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/cmake/nsis/lemon.ico b/extern/quadriflow/3rd/lemon-1.3.1/cmake/nsis/lemon.ico
new file mode 100644
index 00000000000..bbfd8c143d9
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/cmake/nsis/lemon.ico
Binary files differ
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/cmake/nsis/uninstall.ico b/extern/quadriflow/3rd/lemon-1.3.1/cmake/nsis/uninstall.ico
new file mode 100644
index 00000000000..7495f7c3c27
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/cmake/nsis/uninstall.ico
Binary files differ
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/cmake/version.cmake b/extern/quadriflow/3rd/lemon-1.3.1/cmake/version.cmake
new file mode 100644
index 00000000000..91369e1cac7
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/cmake/version.cmake
@@ -0,0 +1 @@
+SET(LEMON_VERSION "1.3.1" CACHE STRING "LEMON version string.")
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/cmake/version.cmake.in b/extern/quadriflow/3rd/lemon-1.3.1/cmake/version.cmake.in
new file mode 100644
index 00000000000..7cd4b689926
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/cmake/version.cmake.in
@@ -0,0 +1 @@
+SET(LEMON_VERSION "@LEMON_VERSION@" CACHE STRING "LEMON version string.")
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/contrib/CMakeLists.txt b/extern/quadriflow/3rd/lemon-1.3.1/contrib/CMakeLists.txt
new file mode 100644
index 00000000000..b6c11e2aad4
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/contrib/CMakeLists.txt
@@ -0,0 +1,19 @@
+INCLUDE_DIRECTORIES(
+ ${PROJECT_SOURCE_DIR}
+ ${PROJECT_BINARY_DIR}
+)
+
+LINK_DIRECTORIES(
+ ${PROJECT_BINARY_DIR}/lemon
+)
+
+# Uncomment (and adjust) the following two lines. 'myprog' is the name
+# of the final executable ('.exe' will automatically be added to the
+# name on Windows) and 'myprog-main.cc' is the source code it is
+# compiled from. You can add more source files separated by
+# whitespaces. Moreover, you can add multiple similar blocks if you
+# want to build more than one executables.
+
+# ADD_EXECUTABLE(myprog myprog-main.cc)
+# TARGET_LINK_LIBRARIES(myprog lemon)
+
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/demo/CMakeLists.txt b/extern/quadriflow/3rd/lemon-1.3.1/demo/CMakeLists.txt
new file mode 100644
index 00000000000..e0566f407f0
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/demo/CMakeLists.txt
@@ -0,0 +1,19 @@
+INCLUDE_DIRECTORIES(
+ ${PROJECT_SOURCE_DIR}
+ ${PROJECT_BINARY_DIR}
+)
+
+LINK_DIRECTORIES(
+ ${PROJECT_BINARY_DIR}/lemon
+)
+
+SET(DEMOS
+ arg_parser_demo
+ graph_to_eps_demo
+ lgf_demo
+)
+
+FOREACH(DEMO_NAME ${DEMOS})
+ ADD_EXECUTABLE(${DEMO_NAME} ${DEMO_NAME}.cc)
+ TARGET_LINK_LIBRARIES(${DEMO_NAME} lemon)
+ENDFOREACH()
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/demo/arg_parser_demo.cc b/extern/quadriflow/3rd/lemon-1.3.1/demo/arg_parser_demo.cc
new file mode 100644
index 00000000000..1bafac0c860
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/demo/arg_parser_demo.cc
@@ -0,0 +1,112 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2010
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\ingroup demos
+///\file
+///\brief Argument parser demo
+///
+/// This example shows how the argument parser can be used.
+///
+/// \include arg_parser_demo.cc
+
+#include <lemon/arg_parser.h>
+
+using namespace lemon;
+int main(int argc, char **argv)
+{
+ // Initialize the argument parser
+ ArgParser ap(argc, argv);
+ int i;
+ std::string s;
+ double d = 1.0;
+ bool b, nh;
+ bool g1, g2, g3;
+
+ // Add a mandatory integer option with storage reference
+ ap.refOption("n", "An integer input.", i, true);
+ // Add a double option with storage reference (the default value is 1.0)
+ ap.refOption("val", "A double input.", d);
+ // Add a double option without storage reference (the default value is 3.14)
+ ap.doubleOption("val2", "A double input.", 3.14);
+ // Set synonym for -val option
+ ap.synonym("vals", "val");
+ // Add a string option
+ ap.refOption("name", "A string input.", s);
+ // Add bool options
+ ap.refOption("f", "A switch.", b)
+ .refOption("nohelp", "", nh)
+ .refOption("gra", "Choice A", g1)
+ .refOption("grb", "Choice B", g2)
+ .refOption("grc", "Choice C", g3);
+ // Bundle -gr* options into a group
+ ap.optionGroup("gr", "gra")
+ .optionGroup("gr", "grb")
+ .optionGroup("gr", "grc");
+ // Set the group mandatory
+ ap.mandatoryGroup("gr");
+ // Set the options of the group exclusive (only one option can be given)
+ ap.onlyOneGroup("gr");
+ // Add non-parsed arguments (e.g. input files)
+ ap.other("infile", "The input file.")
+ .other("...");
+
+ // Throw an exception when problems occurs. The default behavior is to
+ // exit(1) on these cases, but this makes Valgrind falsely warn
+ // about memory leaks.
+ ap.throwOnProblems();
+
+ // Perform the parsing process
+ // (in case of any error it terminates the program)
+ // The try {} construct is necessary only if the ap.trowOnProblems()
+ // setting is in use.
+ try {
+ ap.parse();
+ } catch (ArgParserException &) { return 1; }
+
+ // Check each option if it has been given and print its value
+ std::cout << "Parameters of '" << ap.commandName() << "':\n";
+
+ std::cout << " Value of -n: " << i << std::endl;
+ if(ap.given("val")) std::cout << " Value of -val: " << d << std::endl;
+ if(ap.given("val2")) {
+ d = ap["val2"];
+ std::cout << " Value of -val2: " << d << std::endl;
+ }
+ if(ap.given("name")) std::cout << " Value of -name: " << s << std::endl;
+ if(ap.given("f")) std::cout << " -f is given\n";
+ if(ap.given("nohelp")) std::cout << " Value of -nohelp: " << nh << std::endl;
+ if(ap.given("gra")) std::cout << " -gra is given\n";
+ if(ap.given("grb")) std::cout << " -grb is given\n";
+ if(ap.given("grc")) std::cout << " -grc is given\n";
+
+ switch(ap.files().size()) {
+ case 0:
+ std::cout << " No file argument was given.\n";
+ break;
+ case 1:
+ std::cout << " 1 file argument was given. It is:\n";
+ break;
+ default:
+ std::cout << " "
+ << ap.files().size() << " file arguments were given. They are:\n";
+ }
+ for(unsigned int i=0;i<ap.files().size();++i)
+ std::cout << " '" << ap.files()[i] << "'\n";
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/demo/digraph.lgf b/extern/quadriflow/3rd/lemon-1.3.1/demo/digraph.lgf
new file mode 100644
index 00000000000..83ba7da13c2
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/demo/digraph.lgf
@@ -0,0 +1,29 @@
+@nodes
+label
+0
+1
+2
+3
+4
+5
+6
+7
+@arcs
+ label capacity
+0 1 0 16
+0 2 1 12
+0 3 2 20
+1 2 3 10
+1 4 4 10
+1 5 5 13
+2 3 6 10
+2 4 7 8
+2 6 8 8
+5 3 9 20
+3 6 10 25
+4 7 11 15
+5 7 12 15
+6 7 13 18
+@attributes
+source 0
+target 7
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/demo/graph_to_eps_demo.cc b/extern/quadriflow/3rd/lemon-1.3.1/demo/graph_to_eps_demo.cc
new file mode 100644
index 00000000000..f2f55a92861
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/demo/graph_to_eps_demo.cc
@@ -0,0 +1,206 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+/// \ingroup demos
+/// \file
+/// \brief Demo of the graph drawing function \ref graphToEps()
+///
+/// This demo program shows examples how to use the function \ref
+/// graphToEps(). It takes no input but simply creates seven
+/// <tt>.eps</tt> files demonstrating the capability of \ref
+/// graphToEps(), and showing how to draw directed graphs,
+/// how to handle parallel egdes, how to change the properties (like
+/// color, shape, size, title etc.) of nodes and arcs individually
+/// using appropriate graph maps.
+///
+/// \include graph_to_eps_demo.cc
+
+#include<lemon/list_graph.h>
+#include<lemon/graph_to_eps.h>
+#include<lemon/math.h>
+
+using namespace std;
+using namespace lemon;
+
+int main()
+{
+ Palette palette;
+ Palette paletteW(true);
+
+ // Create a small digraph
+ ListDigraph g;
+ typedef ListDigraph::Node Node;
+ typedef ListDigraph::NodeIt NodeIt;
+ typedef ListDigraph::Arc Arc;
+ typedef dim2::Point<int> Point;
+
+ Node n1=g.addNode();
+ Node n2=g.addNode();
+ Node n3=g.addNode();
+ Node n4=g.addNode();
+ Node n5=g.addNode();
+
+ ListDigraph::NodeMap<Point> coords(g);
+ ListDigraph::NodeMap<double> sizes(g);
+ ListDigraph::NodeMap<int> colors(g);
+ ListDigraph::NodeMap<int> shapes(g);
+ ListDigraph::ArcMap<int> acolors(g);
+ ListDigraph::ArcMap<int> widths(g);
+
+ coords[n1]=Point(50,50); sizes[n1]=1; colors[n1]=1; shapes[n1]=0;
+ coords[n2]=Point(50,70); sizes[n2]=2; colors[n2]=2; shapes[n2]=2;
+ coords[n3]=Point(70,70); sizes[n3]=1; colors[n3]=3; shapes[n3]=0;
+ coords[n4]=Point(70,50); sizes[n4]=2; colors[n4]=4; shapes[n4]=1;
+ coords[n5]=Point(85,60); sizes[n5]=3; colors[n5]=5; shapes[n5]=2;
+
+ Arc a;
+
+ a=g.addArc(n1,n2); acolors[a]=0; widths[a]=1;
+ a=g.addArc(n2,n3); acolors[a]=0; widths[a]=1;
+ a=g.addArc(n3,n5); acolors[a]=0; widths[a]=3;
+ a=g.addArc(n5,n4); acolors[a]=0; widths[a]=1;
+ a=g.addArc(n4,n1); acolors[a]=0; widths[a]=1;
+ a=g.addArc(n2,n4); acolors[a]=1; widths[a]=2;
+ a=g.addArc(n3,n4); acolors[a]=2; widths[a]=1;
+
+ IdMap<ListDigraph,Node> id(g);
+
+ // Create .eps files showing the digraph with different options
+ cout << "Create 'graph_to_eps_demo_out_1_pure.eps'" << endl;
+ graphToEps(g,"graph_to_eps_demo_out_1_pure.eps").
+ coords(coords).
+ title("Sample .eps figure").
+ copyright("(C) 2003-2009 LEMON Project").
+ run();
+
+ cout << "Create 'graph_to_eps_demo_out_2.eps'" << endl;
+ graphToEps(g,"graph_to_eps_demo_out_2.eps").
+ coords(coords).
+ title("Sample .eps figure").
+ copyright("(C) 2003-2009 LEMON Project").
+ absoluteNodeSizes().absoluteArcWidths().
+ nodeScale(2).nodeSizes(sizes).
+ nodeShapes(shapes).
+ nodeColors(composeMap(palette,colors)).
+ arcColors(composeMap(palette,acolors)).
+ arcWidthScale(.4).arcWidths(widths).
+ nodeTexts(id).nodeTextSize(3).
+ run();
+
+ cout << "Create 'graph_to_eps_demo_out_3_arr.eps'" << endl;
+ graphToEps(g,"graph_to_eps_demo_out_3_arr.eps").
+ title("Sample .eps figure (with arrowheads)").
+ copyright("(C) 2003-2009 LEMON Project").
+ absoluteNodeSizes().absoluteArcWidths().
+ nodeColors(composeMap(palette,colors)).
+ coords(coords).
+ nodeScale(2).nodeSizes(sizes).
+ nodeShapes(shapes).
+ arcColors(composeMap(palette,acolors)).
+ arcWidthScale(.4).arcWidths(widths).
+ nodeTexts(id).nodeTextSize(3).
+ drawArrows().arrowWidth(2).arrowLength(2).
+ run();
+
+ // Add more arcs to the digraph
+ a=g.addArc(n1,n4); acolors[a]=2; widths[a]=1;
+ a=g.addArc(n4,n1); acolors[a]=1; widths[a]=2;
+
+ a=g.addArc(n1,n2); acolors[a]=1; widths[a]=1;
+ a=g.addArc(n1,n2); acolors[a]=2; widths[a]=1;
+ a=g.addArc(n1,n2); acolors[a]=3; widths[a]=1;
+ a=g.addArc(n1,n2); acolors[a]=4; widths[a]=1;
+ a=g.addArc(n1,n2); acolors[a]=5; widths[a]=1;
+ a=g.addArc(n1,n2); acolors[a]=6; widths[a]=1;
+ a=g.addArc(n1,n2); acolors[a]=7; widths[a]=1;
+
+ cout << "Create 'graph_to_eps_demo_out_4_par.eps'" << endl;
+ graphToEps(g,"graph_to_eps_demo_out_4_par.eps").
+ title("Sample .eps figure (parallel arcs)").
+ copyright("(C) 2003-2009 LEMON Project").
+ absoluteNodeSizes().absoluteArcWidths().
+ nodeShapes(shapes).
+ coords(coords).
+ nodeScale(2).nodeSizes(sizes).
+ nodeColors(composeMap(palette,colors)).
+ arcColors(composeMap(palette,acolors)).
+ arcWidthScale(.4).arcWidths(widths).
+ nodeTexts(id).nodeTextSize(3).
+ enableParallel().parArcDist(1.5).
+ run();
+
+ cout << "Create 'graph_to_eps_demo_out_5_par_arr.eps'" << endl;
+ graphToEps(g,"graph_to_eps_demo_out_5_par_arr.eps").
+ title("Sample .eps figure (parallel arcs and arrowheads)").
+ copyright("(C) 2003-2009 LEMON Project").
+ absoluteNodeSizes().absoluteArcWidths().
+ nodeScale(2).nodeSizes(sizes).
+ coords(coords).
+ nodeShapes(shapes).
+ nodeColors(composeMap(palette,colors)).
+ arcColors(composeMap(palette,acolors)).
+ arcWidthScale(.3).arcWidths(widths).
+ nodeTexts(id).nodeTextSize(3).
+ enableParallel().parArcDist(1).
+ drawArrows().arrowWidth(1).arrowLength(1).
+ run();
+
+ cout << "Create 'graph_to_eps_demo_out_6_par_arr_a4.eps'" << endl;
+ graphToEps(g,"graph_to_eps_demo_out_6_par_arr_a4.eps").
+ title("Sample .eps figure (fits to A4)").
+ copyright("(C) 2003-2009 LEMON Project").
+ scaleToA4().
+ absoluteNodeSizes().absoluteArcWidths().
+ nodeScale(2).nodeSizes(sizes).
+ coords(coords).
+ nodeShapes(shapes).
+ nodeColors(composeMap(palette,colors)).
+ arcColors(composeMap(palette,acolors)).
+ arcWidthScale(.3).arcWidths(widths).
+ nodeTexts(id).nodeTextSize(3).
+ enableParallel().parArcDist(1).
+ drawArrows().arrowWidth(1).arrowLength(1).
+ run();
+
+ // Create an .eps file showing the colors of a default Palette
+ ListDigraph h;
+ ListDigraph::NodeMap<int> hcolors(h);
+ ListDigraph::NodeMap<Point> hcoords(h);
+
+ int cols=int(std::sqrt(double(palette.size())));
+ for(int i=0;i<int(paletteW.size());i++) {
+ Node n=h.addNode();
+ hcoords[n]=Point(1+i%cols,1+i/cols);
+ hcolors[n]=i;
+ }
+
+ cout << "Create 'graph_to_eps_demo_out_7_colors.eps'" << endl;
+ graphToEps(h,"graph_to_eps_demo_out_7_colors.eps").
+ scale(60).
+ title("Sample .eps figure (Palette demo)").
+ copyright("(C) 2003-2009 LEMON Project").
+ coords(hcoords).
+ absoluteNodeSizes().absoluteArcWidths().
+ nodeScale(.45).
+ distantColorNodeTexts().
+ nodeTexts(hcolors).nodeTextSize(.6).
+ nodeColors(composeMap(paletteW,hcolors)).
+ run();
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/demo/lgf_demo.cc b/extern/quadriflow/3rd/lemon-1.3.1/demo/lgf_demo.cc
new file mode 100644
index 00000000000..e2d31cdf440
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/demo/lgf_demo.cc
@@ -0,0 +1,70 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\ingroup demos
+///\file
+///\brief Demonstrating graph input and output
+///
+/// This program gives an example of how to read and write a digraph
+/// and additional maps from/to a stream or a file using the
+/// \ref lgf-format "LGF" format.
+///
+/// The \c "digraph.lgf" file:
+/// \include digraph.lgf
+///
+/// And the program which reads it and prints the digraph to the
+/// standard output:
+/// \include lgf_demo.cc
+
+#include <iostream>
+#include <lemon/smart_graph.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/lgf_writer.h>
+
+using namespace lemon;
+
+int main() {
+ SmartDigraph g;
+ SmartDigraph::ArcMap<int> cap(g);
+ SmartDigraph::Node s, t;
+
+ try {
+ digraphReader(g, "digraph.lgf"). // read the directed graph into g
+ arcMap("capacity", cap). // read the 'capacity' arc map into cap
+ node("source", s). // read 'source' node to s
+ node("target", t). // read 'target' node to t
+ run();
+ } catch (Exception& error) { // check if there was any error
+ std::cerr << "Error: " << error.what() << std::endl;
+ return -1;
+ }
+
+ std::cout << "A digraph is read from 'digraph.lgf'." << std::endl;
+ std::cout << "Number of nodes: " << countNodes(g) << std::endl;
+ std::cout << "Number of arcs: " << countArcs(g) << std::endl;
+
+ std::cout << "We can write it to the standard output:" << std::endl;
+
+ digraphWriter(g). // write g to the standard output
+ arcMap("capacity", cap). // write cap into 'capacity'
+ node("source", s). // write s to 'source'
+ node("target", t). // write t to 'target'
+ run();
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/CMakeLists.txt b/extern/quadriflow/3rd/lemon-1.3.1/lemon/CMakeLists.txt
new file mode 100644
index 00000000000..4e6567e49c7
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/CMakeLists.txt
@@ -0,0 +1,91 @@
+INCLUDE_DIRECTORIES(
+ ${PROJECT_SOURCE_DIR}
+ ${PROJECT_BINARY_DIR}
+)
+
+CONFIGURE_FILE(
+ ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
+ ${CMAKE_CURRENT_BINARY_DIR}/config.h
+)
+
+CONFIGURE_FILE(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lemon.pc.in
+ ${CMAKE_CURRENT_BINARY_DIR}/lemon.pc
+ @ONLY
+)
+
+SET(LEMON_SOURCES
+ arg_parser.cc
+ base.cc
+ color.cc
+ lp_base.cc
+ lp_skeleton.cc
+ random.cc
+ bits/windows.cc
+)
+
+IF(LEMON_HAVE_GLPK)
+ SET(LEMON_SOURCES ${LEMON_SOURCES} glpk.cc)
+ INCLUDE_DIRECTORIES(${GLPK_INCLUDE_DIRS})
+ IF(WIN32)
+ INSTALL(FILES ${GLPK_BIN_DIR}/glpk.dll DESTINATION bin)
+ INSTALL(FILES ${GLPK_BIN_DIR}/libltdl3.dll DESTINATION bin)
+ INSTALL(FILES ${GLPK_BIN_DIR}/zlib1.dll DESTINATION bin)
+ ENDIF()
+ENDIF()
+
+IF(LEMON_HAVE_CPLEX)
+ SET(LEMON_SOURCES ${LEMON_SOURCES} cplex.cc)
+ INCLUDE_DIRECTORIES(${ILOG_INCLUDE_DIRS})
+ENDIF()
+
+IF(LEMON_HAVE_CLP)
+ SET(LEMON_SOURCES ${LEMON_SOURCES} clp.cc)
+ INCLUDE_DIRECTORIES(${COIN_INCLUDE_DIRS})
+ENDIF()
+
+IF(LEMON_HAVE_CBC)
+ SET(LEMON_SOURCES ${LEMON_SOURCES} cbc.cc)
+ INCLUDE_DIRECTORIES(${COIN_INCLUDE_DIRS})
+ENDIF()
+
+IF(LEMON_HAVE_SOPLEX)
+ SET(LEMON_SOURCES ${LEMON_SOURCES} soplex.cc)
+ INCLUDE_DIRECTORIES(${SOPLEX_INCLUDE_DIRS})
+ENDIF()
+
+ADD_LIBRARY(lemon ${LEMON_SOURCES})
+
+TARGET_LINK_LIBRARIES(lemon
+ ${GLPK_LIBRARIES} ${COIN_LIBRARIES} ${ILOG_LIBRARIES} ${SOPLEX_LIBRARIES}
+ )
+
+IF(UNIX)
+ SET_TARGET_PROPERTIES(lemon PROPERTIES OUTPUT_NAME emon VERSION ${LEMON_VERSION} SOVERSION ${LEMON_VERSION})
+ENDIF()
+
+INSTALL(
+ TARGETS lemon
+ ARCHIVE DESTINATION lib
+ LIBRARY DESTINATION lib
+ COMPONENT library
+)
+
+INSTALL(
+ DIRECTORY . bits concepts
+ DESTINATION include/lemon
+ COMPONENT headers
+ FILES_MATCHING PATTERN "*.h"
+)
+
+INSTALL(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/config.h
+ DESTINATION include/lemon
+ COMPONENT headers
+)
+
+INSTALL(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/lemon.pc
+ DESTINATION lib/pkgconfig
+)
+
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/adaptors.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/adaptors.h
new file mode 100644
index 00000000000..1a40f8ea2c6
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/adaptors.h
@@ -0,0 +1,3638 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_ADAPTORS_H
+#define LEMON_ADAPTORS_H
+
+/// \ingroup graph_adaptors
+/// \file
+/// \brief Adaptor classes for digraphs and graphs
+///
+/// This file contains several useful adaptors for digraphs and graphs.
+
+#include <lemon/core.h>
+#include <lemon/maps.h>
+#include <lemon/bits/variant.h>
+
+#include <lemon/bits/graph_adaptor_extender.h>
+#include <lemon/bits/map_extender.h>
+#include <lemon/tolerance.h>
+
+#include <algorithm>
+
+namespace lemon {
+
+#ifdef _MSC_VER
+#define LEMON_SCOPE_FIX(OUTER, NESTED) OUTER::NESTED
+#else
+#define LEMON_SCOPE_FIX(OUTER, NESTED) typename OUTER::template NESTED
+#endif
+
+ template<typename DGR>
+ class DigraphAdaptorBase {
+ public:
+ typedef DGR Digraph;
+ typedef DigraphAdaptorBase Adaptor;
+
+ protected:
+ DGR* _digraph;
+ DigraphAdaptorBase() : _digraph(0) { }
+ void initialize(DGR& digraph) { _digraph = &digraph; }
+
+ public:
+ DigraphAdaptorBase(DGR& digraph) : _digraph(&digraph) { }
+
+ typedef typename DGR::Node Node;
+ typedef typename DGR::Arc Arc;
+
+ void first(Node& i) const { _digraph->first(i); }
+ void first(Arc& i) const { _digraph->first(i); }
+ void firstIn(Arc& i, const Node& n) const { _digraph->firstIn(i, n); }
+ void firstOut(Arc& i, const Node& n ) const { _digraph->firstOut(i, n); }
+
+ void next(Node& i) const { _digraph->next(i); }
+ void next(Arc& i) const { _digraph->next(i); }
+ void nextIn(Arc& i) const { _digraph->nextIn(i); }
+ void nextOut(Arc& i) const { _digraph->nextOut(i); }
+
+ Node source(const Arc& a) const { return _digraph->source(a); }
+ Node target(const Arc& a) const { return _digraph->target(a); }
+
+ typedef NodeNumTagIndicator<DGR> NodeNumTag;
+ int nodeNum() const { return _digraph->nodeNum(); }
+
+ typedef ArcNumTagIndicator<DGR> ArcNumTag;
+ int arcNum() const { return _digraph->arcNum(); }
+
+ typedef FindArcTagIndicator<DGR> FindArcTag;
+ Arc findArc(const Node& u, const Node& v, const Arc& prev = INVALID) const {
+ return _digraph->findArc(u, v, prev);
+ }
+
+ Node addNode() { return _digraph->addNode(); }
+ Arc addArc(const Node& u, const Node& v) { return _digraph->addArc(u, v); }
+
+ void erase(const Node& n) { _digraph->erase(n); }
+ void erase(const Arc& a) { _digraph->erase(a); }
+
+ void clear() { _digraph->clear(); }
+
+ int id(const Node& n) const { return _digraph->id(n); }
+ int id(const Arc& a) const { return _digraph->id(a); }
+
+ Node nodeFromId(int ix) const { return _digraph->nodeFromId(ix); }
+ Arc arcFromId(int ix) const { return _digraph->arcFromId(ix); }
+
+ int maxNodeId() const { return _digraph->maxNodeId(); }
+ int maxArcId() const { return _digraph->maxArcId(); }
+
+ typedef typename ItemSetTraits<DGR, Node>::ItemNotifier NodeNotifier;
+ NodeNotifier& notifier(Node) const { return _digraph->notifier(Node()); }
+
+ typedef typename ItemSetTraits<DGR, Arc>::ItemNotifier ArcNotifier;
+ ArcNotifier& notifier(Arc) const { return _digraph->notifier(Arc()); }
+
+ template <typename V>
+ class NodeMap : public DGR::template NodeMap<V> {
+ typedef typename DGR::template NodeMap<V> Parent;
+
+ public:
+ explicit NodeMap(const Adaptor& adaptor)
+ : Parent(*adaptor._digraph) {}
+ NodeMap(const Adaptor& adaptor, const V& value)
+ : Parent(*adaptor._digraph, value) { }
+
+ private:
+ NodeMap& operator=(const NodeMap& cmap) {
+ return operator=<NodeMap>(cmap);
+ }
+
+ template <typename CMap>
+ NodeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+
+ };
+
+ template <typename V>
+ class ArcMap : public DGR::template ArcMap<V> {
+ typedef typename DGR::template ArcMap<V> Parent;
+
+ public:
+ explicit ArcMap(const DigraphAdaptorBase<DGR>& adaptor)
+ : Parent(*adaptor._digraph) {}
+ ArcMap(const DigraphAdaptorBase<DGR>& adaptor, const V& value)
+ : Parent(*adaptor._digraph, value) {}
+
+ private:
+ ArcMap& operator=(const ArcMap& cmap) {
+ return operator=<ArcMap>(cmap);
+ }
+
+ template <typename CMap>
+ ArcMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+
+ };
+
+ };
+
+ template<typename GR>
+ class GraphAdaptorBase {
+ public:
+ typedef GR Graph;
+
+ protected:
+ GR* _graph;
+
+ GraphAdaptorBase() : _graph(0) {}
+
+ void initialize(GR& graph) { _graph = &graph; }
+
+ public:
+ GraphAdaptorBase(GR& graph) : _graph(&graph) {}
+
+ typedef typename GR::Node Node;
+ typedef typename GR::Arc Arc;
+ typedef typename GR::Edge Edge;
+
+ void first(Node& i) const { _graph->first(i); }
+ void first(Arc& i) const { _graph->first(i); }
+ void first(Edge& i) const { _graph->first(i); }
+ void firstIn(Arc& i, const Node& n) const { _graph->firstIn(i, n); }
+ void firstOut(Arc& i, const Node& n ) const { _graph->firstOut(i, n); }
+ void firstInc(Edge &i, bool &d, const Node &n) const {
+ _graph->firstInc(i, d, n);
+ }
+
+ void next(Node& i) const { _graph->next(i); }
+ void next(Arc& i) const { _graph->next(i); }
+ void next(Edge& i) const { _graph->next(i); }
+ void nextIn(Arc& i) const { _graph->nextIn(i); }
+ void nextOut(Arc& i) const { _graph->nextOut(i); }
+ void nextInc(Edge &i, bool &d) const { _graph->nextInc(i, d); }
+
+ Node u(const Edge& e) const { return _graph->u(e); }
+ Node v(const Edge& e) const { return _graph->v(e); }
+
+ Node source(const Arc& a) const { return _graph->source(a); }
+ Node target(const Arc& a) const { return _graph->target(a); }
+
+ typedef NodeNumTagIndicator<Graph> NodeNumTag;
+ int nodeNum() const { return _graph->nodeNum(); }
+
+ typedef ArcNumTagIndicator<Graph> ArcNumTag;
+ int arcNum() const { return _graph->arcNum(); }
+
+ typedef EdgeNumTagIndicator<Graph> EdgeNumTag;
+ int edgeNum() const { return _graph->edgeNum(); }
+
+ typedef FindArcTagIndicator<Graph> FindArcTag;
+ Arc findArc(const Node& u, const Node& v,
+ const Arc& prev = INVALID) const {
+ return _graph->findArc(u, v, prev);
+ }
+
+ typedef FindEdgeTagIndicator<Graph> FindEdgeTag;
+ Edge findEdge(const Node& u, const Node& v,
+ const Edge& prev = INVALID) const {
+ return _graph->findEdge(u, v, prev);
+ }
+
+ Node addNode() { return _graph->addNode(); }
+ Edge addEdge(const Node& u, const Node& v) { return _graph->addEdge(u, v); }
+
+ void erase(const Node& i) { _graph->erase(i); }
+ void erase(const Edge& i) { _graph->erase(i); }
+
+ void clear() { _graph->clear(); }
+
+ bool direction(const Arc& a) const { return _graph->direction(a); }
+ Arc direct(const Edge& e, bool d) const { return _graph->direct(e, d); }
+
+ int id(const Node& v) const { return _graph->id(v); }
+ int id(const Arc& a) const { return _graph->id(a); }
+ int id(const Edge& e) const { return _graph->id(e); }
+
+ Node nodeFromId(int ix) const { return _graph->nodeFromId(ix); }
+ Arc arcFromId(int ix) const { return _graph->arcFromId(ix); }
+ Edge edgeFromId(int ix) const { return _graph->edgeFromId(ix); }
+
+ int maxNodeId() const { return _graph->maxNodeId(); }
+ int maxArcId() const { return _graph->maxArcId(); }
+ int maxEdgeId() const { return _graph->maxEdgeId(); }
+
+ typedef typename ItemSetTraits<GR, Node>::ItemNotifier NodeNotifier;
+ NodeNotifier& notifier(Node) const { return _graph->notifier(Node()); }
+
+ typedef typename ItemSetTraits<GR, Arc>::ItemNotifier ArcNotifier;
+ ArcNotifier& notifier(Arc) const { return _graph->notifier(Arc()); }
+
+ typedef typename ItemSetTraits<GR, Edge>::ItemNotifier EdgeNotifier;
+ EdgeNotifier& notifier(Edge) const { return _graph->notifier(Edge()); }
+
+ template <typename V>
+ class NodeMap : public GR::template NodeMap<V> {
+ typedef typename GR::template NodeMap<V> Parent;
+
+ public:
+ explicit NodeMap(const GraphAdaptorBase<GR>& adapter)
+ : Parent(*adapter._graph) {}
+ NodeMap(const GraphAdaptorBase<GR>& adapter, const V& value)
+ : Parent(*adapter._graph, value) {}
+
+ private:
+ NodeMap& operator=(const NodeMap& cmap) {
+ return operator=<NodeMap>(cmap);
+ }
+
+ template <typename CMap>
+ NodeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+
+ };
+
+ template <typename V>
+ class ArcMap : public GR::template ArcMap<V> {
+ typedef typename GR::template ArcMap<V> Parent;
+
+ public:
+ explicit ArcMap(const GraphAdaptorBase<GR>& adapter)
+ : Parent(*adapter._graph) {}
+ ArcMap(const GraphAdaptorBase<GR>& adapter, const V& value)
+ : Parent(*adapter._graph, value) {}
+
+ private:
+ ArcMap& operator=(const ArcMap& cmap) {
+ return operator=<ArcMap>(cmap);
+ }
+
+ template <typename CMap>
+ ArcMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ template <typename V>
+ class EdgeMap : public GR::template EdgeMap<V> {
+ typedef typename GR::template EdgeMap<V> Parent;
+
+ public:
+ explicit EdgeMap(const GraphAdaptorBase<GR>& adapter)
+ : Parent(*adapter._graph) {}
+ EdgeMap(const GraphAdaptorBase<GR>& adapter, const V& value)
+ : Parent(*adapter._graph, value) {}
+
+ private:
+ EdgeMap& operator=(const EdgeMap& cmap) {
+ return operator=<EdgeMap>(cmap);
+ }
+
+ template <typename CMap>
+ EdgeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ };
+
+ template <typename DGR>
+ class ReverseDigraphBase : public DigraphAdaptorBase<DGR> {
+ typedef DigraphAdaptorBase<DGR> Parent;
+ public:
+ typedef DGR Digraph;
+ protected:
+ ReverseDigraphBase() : Parent() { }
+ public:
+ typedef typename Parent::Node Node;
+ typedef typename Parent::Arc Arc;
+
+ void firstIn(Arc& a, const Node& n) const { Parent::firstOut(a, n); }
+ void firstOut(Arc& a, const Node& n ) const { Parent::firstIn(a, n); }
+
+ void nextIn(Arc& a) const { Parent::nextOut(a); }
+ void nextOut(Arc& a) const { Parent::nextIn(a); }
+
+ Node source(const Arc& a) const { return Parent::target(a); }
+ Node target(const Arc& a) const { return Parent::source(a); }
+
+ Arc addArc(const Node& u, const Node& v) { return Parent::addArc(v, u); }
+
+ typedef FindArcTagIndicator<DGR> FindArcTag;
+ Arc findArc(const Node& u, const Node& v,
+ const Arc& prev = INVALID) const {
+ return Parent::findArc(v, u, prev);
+ }
+
+ };
+
+ /// \ingroup graph_adaptors
+ ///
+ /// \brief Adaptor class for reversing the orientation of the arcs in
+ /// a digraph.
+ ///
+ /// ReverseDigraph can be used for reversing the arcs in a digraph.
+ /// It conforms to the \ref concepts::Digraph "Digraph" concept.
+ ///
+ /// The adapted digraph can also be modified through this adaptor
+ /// by adding or removing nodes or arcs, unless the \c GR template
+ /// parameter is set to be \c const.
+ ///
+ /// This class provides item counting in the same time as the adapted
+ /// digraph structure.
+ ///
+ /// \tparam DGR The type of the adapted digraph.
+ /// It must conform to the \ref concepts::Digraph "Digraph" concept.
+ /// It can also be specified to be \c const.
+ ///
+ /// \note The \c Node and \c Arc types of this adaptor and the adapted
+ /// digraph are convertible to each other.
+ template<typename DGR>
+#ifdef DOXYGEN
+ class ReverseDigraph {
+#else
+ class ReverseDigraph :
+ public DigraphAdaptorExtender<ReverseDigraphBase<DGR> > {
+#endif
+ typedef DigraphAdaptorExtender<ReverseDigraphBase<DGR> > Parent;
+ public:
+ /// The type of the adapted digraph.
+ typedef DGR Digraph;
+ protected:
+ ReverseDigraph() { }
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Creates a reverse digraph adaptor for the given digraph.
+ explicit ReverseDigraph(DGR& digraph) {
+ Parent::initialize(digraph);
+ }
+ };
+
+ /// \brief Returns a read-only ReverseDigraph adaptor
+ ///
+ /// This function just returns a read-only \ref ReverseDigraph adaptor.
+ /// \ingroup graph_adaptors
+ /// \relates ReverseDigraph
+ template<typename DGR>
+ ReverseDigraph<const DGR> reverseDigraph(const DGR& digraph) {
+ return ReverseDigraph<const DGR>(digraph);
+ }
+
+
+ template <typename DGR, typename NF, typename AF, bool ch = true>
+ class SubDigraphBase : public DigraphAdaptorBase<DGR> {
+ typedef DigraphAdaptorBase<DGR> Parent;
+ public:
+ typedef DGR Digraph;
+ typedef NF NodeFilterMap;
+ typedef AF ArcFilterMap;
+
+ typedef SubDigraphBase Adaptor;
+ protected:
+ NF* _node_filter;
+ AF* _arc_filter;
+ SubDigraphBase()
+ : Parent(), _node_filter(0), _arc_filter(0) { }
+
+ void initialize(DGR& digraph, NF& node_filter, AF& arc_filter) {
+ Parent::initialize(digraph);
+ _node_filter = &node_filter;
+ _arc_filter = &arc_filter;
+ }
+
+ public:
+
+ typedef typename Parent::Node Node;
+ typedef typename Parent::Arc Arc;
+
+ void first(Node& i) const {
+ Parent::first(i);
+ while (i != INVALID && !(*_node_filter)[i]) Parent::next(i);
+ }
+
+ void first(Arc& i) const {
+ Parent::first(i);
+ while (i != INVALID && (!(*_arc_filter)[i]
+ || !(*_node_filter)[Parent::source(i)]
+ || !(*_node_filter)[Parent::target(i)]))
+ Parent::next(i);
+ }
+
+ void firstIn(Arc& i, const Node& n) const {
+ Parent::firstIn(i, n);
+ while (i != INVALID && (!(*_arc_filter)[i]
+ || !(*_node_filter)[Parent::source(i)]))
+ Parent::nextIn(i);
+ }
+
+ void firstOut(Arc& i, const Node& n) const {
+ Parent::firstOut(i, n);
+ while (i != INVALID && (!(*_arc_filter)[i]
+ || !(*_node_filter)[Parent::target(i)]))
+ Parent::nextOut(i);
+ }
+
+ void next(Node& i) const {
+ Parent::next(i);
+ while (i != INVALID && !(*_node_filter)[i]) Parent::next(i);
+ }
+
+ void next(Arc& i) const {
+ Parent::next(i);
+ while (i != INVALID && (!(*_arc_filter)[i]
+ || !(*_node_filter)[Parent::source(i)]
+ || !(*_node_filter)[Parent::target(i)]))
+ Parent::next(i);
+ }
+
+ void nextIn(Arc& i) const {
+ Parent::nextIn(i);
+ while (i != INVALID && (!(*_arc_filter)[i]
+ || !(*_node_filter)[Parent::source(i)]))
+ Parent::nextIn(i);
+ }
+
+ void nextOut(Arc& i) const {
+ Parent::nextOut(i);
+ while (i != INVALID && (!(*_arc_filter)[i]
+ || !(*_node_filter)[Parent::target(i)]))
+ Parent::nextOut(i);
+ }
+
+ void status(const Node& n, bool v) const { _node_filter->set(n, v); }
+ void status(const Arc& a, bool v) const { _arc_filter->set(a, v); }
+
+ bool status(const Node& n) const { return (*_node_filter)[n]; }
+ bool status(const Arc& a) const { return (*_arc_filter)[a]; }
+
+ typedef False NodeNumTag;
+ typedef False ArcNumTag;
+
+ typedef FindArcTagIndicator<DGR> FindArcTag;
+ Arc findArc(const Node& source, const Node& target,
+ const Arc& prev = INVALID) const {
+ if (!(*_node_filter)[source] || !(*_node_filter)[target]) {
+ return INVALID;
+ }
+ Arc arc = Parent::findArc(source, target, prev);
+ while (arc != INVALID && !(*_arc_filter)[arc]) {
+ arc = Parent::findArc(source, target, arc);
+ }
+ return arc;
+ }
+
+ public:
+
+ template <typename V>
+ class NodeMap
+ : public SubMapExtender<SubDigraphBase<DGR, NF, AF, ch>,
+ LEMON_SCOPE_FIX(DigraphAdaptorBase<DGR>, NodeMap<V>)> {
+ typedef SubMapExtender<SubDigraphBase<DGR, NF, AF, ch>,
+ LEMON_SCOPE_FIX(DigraphAdaptorBase<DGR>, NodeMap<V>)> Parent;
+
+ public:
+ typedef V Value;
+
+ NodeMap(const SubDigraphBase<DGR, NF, AF, ch>& adaptor)
+ : Parent(adaptor) {}
+ NodeMap(const SubDigraphBase<DGR, NF, AF, ch>& adaptor, const V& value)
+ : Parent(adaptor, value) {}
+
+ private:
+ NodeMap& operator=(const NodeMap& cmap) {
+ return operator=<NodeMap>(cmap);
+ }
+
+ template <typename CMap>
+ NodeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ template <typename V>
+ class ArcMap
+ : public SubMapExtender<SubDigraphBase<DGR, NF, AF, ch>,
+ LEMON_SCOPE_FIX(DigraphAdaptorBase<DGR>, ArcMap<V>)> {
+ typedef SubMapExtender<SubDigraphBase<DGR, NF, AF, ch>,
+ LEMON_SCOPE_FIX(DigraphAdaptorBase<DGR>, ArcMap<V>)> Parent;
+
+ public:
+ typedef V Value;
+
+ ArcMap(const SubDigraphBase<DGR, NF, AF, ch>& adaptor)
+ : Parent(adaptor) {}
+ ArcMap(const SubDigraphBase<DGR, NF, AF, ch>& adaptor, const V& value)
+ : Parent(adaptor, value) {}
+
+ private:
+ ArcMap& operator=(const ArcMap& cmap) {
+ return operator=<ArcMap>(cmap);
+ }
+
+ template <typename CMap>
+ ArcMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ };
+
+ template <typename DGR, typename NF, typename AF>
+ class SubDigraphBase<DGR, NF, AF, false>
+ : public DigraphAdaptorBase<DGR> {
+ typedef DigraphAdaptorBase<DGR> Parent;
+ public:
+ typedef DGR Digraph;
+ typedef NF NodeFilterMap;
+ typedef AF ArcFilterMap;
+
+ typedef SubDigraphBase Adaptor;
+ protected:
+ NF* _node_filter;
+ AF* _arc_filter;
+ SubDigraphBase()
+ : Parent(), _node_filter(0), _arc_filter(0) { }
+
+ void initialize(DGR& digraph, NF& node_filter, AF& arc_filter) {
+ Parent::initialize(digraph);
+ _node_filter = &node_filter;
+ _arc_filter = &arc_filter;
+ }
+
+ public:
+
+ typedef typename Parent::Node Node;
+ typedef typename Parent::Arc Arc;
+
+ void first(Node& i) const {
+ Parent::first(i);
+ while (i!=INVALID && !(*_node_filter)[i]) Parent::next(i);
+ }
+
+ void first(Arc& i) const {
+ Parent::first(i);
+ while (i!=INVALID && !(*_arc_filter)[i]) Parent::next(i);
+ }
+
+ void firstIn(Arc& i, const Node& n) const {
+ Parent::firstIn(i, n);
+ while (i!=INVALID && !(*_arc_filter)[i]) Parent::nextIn(i);
+ }
+
+ void firstOut(Arc& i, const Node& n) const {
+ Parent::firstOut(i, n);
+ while (i!=INVALID && !(*_arc_filter)[i]) Parent::nextOut(i);
+ }
+
+ void next(Node& i) const {
+ Parent::next(i);
+ while (i!=INVALID && !(*_node_filter)[i]) Parent::next(i);
+ }
+ void next(Arc& i) const {
+ Parent::next(i);
+ while (i!=INVALID && !(*_arc_filter)[i]) Parent::next(i);
+ }
+ void nextIn(Arc& i) const {
+ Parent::nextIn(i);
+ while (i!=INVALID && !(*_arc_filter)[i]) Parent::nextIn(i);
+ }
+
+ void nextOut(Arc& i) const {
+ Parent::nextOut(i);
+ while (i!=INVALID && !(*_arc_filter)[i]) Parent::nextOut(i);
+ }
+
+ void status(const Node& n, bool v) const { _node_filter->set(n, v); }
+ void status(const Arc& a, bool v) const { _arc_filter->set(a, v); }
+
+ bool status(const Node& n) const { return (*_node_filter)[n]; }
+ bool status(const Arc& a) const { return (*_arc_filter)[a]; }
+
+ typedef False NodeNumTag;
+ typedef False ArcNumTag;
+
+ typedef FindArcTagIndicator<DGR> FindArcTag;
+ Arc findArc(const Node& source, const Node& target,
+ const Arc& prev = INVALID) const {
+ if (!(*_node_filter)[source] || !(*_node_filter)[target]) {
+ return INVALID;
+ }
+ Arc arc = Parent::findArc(source, target, prev);
+ while (arc != INVALID && !(*_arc_filter)[arc]) {
+ arc = Parent::findArc(source, target, arc);
+ }
+ return arc;
+ }
+
+ template <typename V>
+ class NodeMap
+ : public SubMapExtender<SubDigraphBase<DGR, NF, AF, false>,
+ LEMON_SCOPE_FIX(DigraphAdaptorBase<DGR>, NodeMap<V>)> {
+ typedef SubMapExtender<SubDigraphBase<DGR, NF, AF, false>,
+ LEMON_SCOPE_FIX(DigraphAdaptorBase<DGR>, NodeMap<V>)> Parent;
+
+ public:
+ typedef V Value;
+
+ NodeMap(const SubDigraphBase<DGR, NF, AF, false>& adaptor)
+ : Parent(adaptor) {}
+ NodeMap(const SubDigraphBase<DGR, NF, AF, false>& adaptor, const V& value)
+ : Parent(adaptor, value) {}
+
+ private:
+ NodeMap& operator=(const NodeMap& cmap) {
+ return operator=<NodeMap>(cmap);
+ }
+
+ template <typename CMap>
+ NodeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ template <typename V>
+ class ArcMap
+ : public SubMapExtender<SubDigraphBase<DGR, NF, AF, false>,
+ LEMON_SCOPE_FIX(DigraphAdaptorBase<DGR>, ArcMap<V>)> {
+ typedef SubMapExtender<SubDigraphBase<DGR, NF, AF, false>,
+ LEMON_SCOPE_FIX(DigraphAdaptorBase<DGR>, ArcMap<V>)> Parent;
+
+ public:
+ typedef V Value;
+
+ ArcMap(const SubDigraphBase<DGR, NF, AF, false>& adaptor)
+ : Parent(adaptor) {}
+ ArcMap(const SubDigraphBase<DGR, NF, AF, false>& adaptor, const V& value)
+ : Parent(adaptor, value) {}
+
+ private:
+ ArcMap& operator=(const ArcMap& cmap) {
+ return operator=<ArcMap>(cmap);
+ }
+
+ template <typename CMap>
+ ArcMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ };
+
+ /// \ingroup graph_adaptors
+ ///
+ /// \brief Adaptor class for hiding nodes and arcs in a digraph
+ ///
+ /// SubDigraph can be used for hiding nodes and arcs in a digraph.
+ /// A \c bool node map and a \c bool arc map must be specified, which
+ /// define the filters for nodes and arcs.
+ /// Only the nodes and arcs with \c true filter value are
+ /// shown in the subdigraph. The arcs that are incident to hidden
+ /// nodes are also filtered out.
+ /// This adaptor conforms to the \ref concepts::Digraph "Digraph" concept.
+ ///
+ /// The adapted digraph can also be modified through this adaptor
+ /// by adding or removing nodes or arcs, unless the \c GR template
+ /// parameter is set to be \c const.
+ ///
+ /// This class provides only linear time counting for nodes and arcs.
+ ///
+ /// \tparam DGR The type of the adapted digraph.
+ /// It must conform to the \ref concepts::Digraph "Digraph" concept.
+ /// It can also be specified to be \c const.
+ /// \tparam NF The type of the node filter map.
+ /// It must be a \c bool (or convertible) node map of the
+ /// adapted digraph. The default type is
+ /// \ref concepts::Digraph::NodeMap "DGR::NodeMap<bool>".
+ /// \tparam AF The type of the arc filter map.
+ /// It must be \c bool (or convertible) arc map of the
+ /// adapted digraph. The default type is
+ /// \ref concepts::Digraph::ArcMap "DGR::ArcMap<bool>".
+ ///
+ /// \note The \c Node and \c Arc types of this adaptor and the adapted
+ /// digraph are convertible to each other.
+ ///
+ /// \see FilterNodes
+ /// \see FilterArcs
+#ifdef DOXYGEN
+ template<typename DGR, typename NF, typename AF>
+ class SubDigraph {
+#else
+ template<typename DGR,
+ typename NF = typename DGR::template NodeMap<bool>,
+ typename AF = typename DGR::template ArcMap<bool> >
+ class SubDigraph :
+ public DigraphAdaptorExtender<SubDigraphBase<DGR, NF, AF, true> > {
+#endif
+ public:
+ /// The type of the adapted digraph.
+ typedef DGR Digraph;
+ /// The type of the node filter map.
+ typedef NF NodeFilterMap;
+ /// The type of the arc filter map.
+ typedef AF ArcFilterMap;
+
+ typedef DigraphAdaptorExtender<SubDigraphBase<DGR, NF, AF, true> >
+ Parent;
+
+ typedef typename Parent::Node Node;
+ typedef typename Parent::Arc Arc;
+
+ protected:
+ SubDigraph() { }
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Creates a subdigraph for the given digraph with the
+ /// given node and arc filter maps.
+ SubDigraph(DGR& digraph, NF& node_filter, AF& arc_filter) {
+ Parent::initialize(digraph, node_filter, arc_filter);
+ }
+
+ /// \brief Sets the status of the given node
+ ///
+ /// This function sets the status of the given node.
+ /// It is done by simply setting the assigned value of \c n
+ /// to \c v in the node filter map.
+ void status(const Node& n, bool v) const { Parent::status(n, v); }
+
+ /// \brief Sets the status of the given arc
+ ///
+ /// This function sets the status of the given arc.
+ /// It is done by simply setting the assigned value of \c a
+ /// to \c v in the arc filter map.
+ void status(const Arc& a, bool v) const { Parent::status(a, v); }
+
+ /// \brief Returns the status of the given node
+ ///
+ /// This function returns the status of the given node.
+ /// It is \c true if the given node is enabled (i.e. not hidden).
+ bool status(const Node& n) const { return Parent::status(n); }
+
+ /// \brief Returns the status of the given arc
+ ///
+ /// This function returns the status of the given arc.
+ /// It is \c true if the given arc is enabled (i.e. not hidden).
+ bool status(const Arc& a) const { return Parent::status(a); }
+
+ /// \brief Disables the given node
+ ///
+ /// This function disables the given node in the subdigraph,
+ /// so the iteration jumps over it.
+ /// It is the same as \ref status() "status(n, false)".
+ void disable(const Node& n) const { Parent::status(n, false); }
+
+ /// \brief Disables the given arc
+ ///
+ /// This function disables the given arc in the subdigraph,
+ /// so the iteration jumps over it.
+ /// It is the same as \ref status() "status(a, false)".
+ void disable(const Arc& a) const { Parent::status(a, false); }
+
+ /// \brief Enables the given node
+ ///
+ /// This function enables the given node in the subdigraph.
+ /// It is the same as \ref status() "status(n, true)".
+ void enable(const Node& n) const { Parent::status(n, true); }
+
+ /// \brief Enables the given arc
+ ///
+ /// This function enables the given arc in the subdigraph.
+ /// It is the same as \ref status() "status(a, true)".
+ void enable(const Arc& a) const { Parent::status(a, true); }
+
+ };
+
+ /// \brief Returns a read-only SubDigraph adaptor
+ ///
+ /// This function just returns a read-only \ref SubDigraph adaptor.
+ /// \ingroup graph_adaptors
+ /// \relates SubDigraph
+ template<typename DGR, typename NF, typename AF>
+ SubDigraph<const DGR, NF, AF>
+ subDigraph(const DGR& digraph,
+ NF& node_filter, AF& arc_filter) {
+ return SubDigraph<const DGR, NF, AF>
+ (digraph, node_filter, arc_filter);
+ }
+
+ template<typename DGR, typename NF, typename AF>
+ SubDigraph<const DGR, const NF, AF>
+ subDigraph(const DGR& digraph,
+ const NF& node_filter, AF& arc_filter) {
+ return SubDigraph<const DGR, const NF, AF>
+ (digraph, node_filter, arc_filter);
+ }
+
+ template<typename DGR, typename NF, typename AF>
+ SubDigraph<const DGR, NF, const AF>
+ subDigraph(const DGR& digraph,
+ NF& node_filter, const AF& arc_filter) {
+ return SubDigraph<const DGR, NF, const AF>
+ (digraph, node_filter, arc_filter);
+ }
+
+ template<typename DGR, typename NF, typename AF>
+ SubDigraph<const DGR, const NF, const AF>
+ subDigraph(const DGR& digraph,
+ const NF& node_filter, const AF& arc_filter) {
+ return SubDigraph<const DGR, const NF, const AF>
+ (digraph, node_filter, arc_filter);
+ }
+
+
+ template <typename GR, typename NF, typename EF, bool ch = true>
+ class SubGraphBase : public GraphAdaptorBase<GR> {
+ typedef GraphAdaptorBase<GR> Parent;
+ public:
+ typedef GR Graph;
+ typedef NF NodeFilterMap;
+ typedef EF EdgeFilterMap;
+
+ typedef SubGraphBase Adaptor;
+ protected:
+
+ NF* _node_filter;
+ EF* _edge_filter;
+
+ SubGraphBase()
+ : Parent(), _node_filter(0), _edge_filter(0) { }
+
+ void initialize(GR& graph, NF& node_filter, EF& edge_filter) {
+ Parent::initialize(graph);
+ _node_filter = &node_filter;
+ _edge_filter = &edge_filter;
+ }
+
+ public:
+
+ typedef typename Parent::Node Node;
+ typedef typename Parent::Arc Arc;
+ typedef typename Parent::Edge Edge;
+
+ void first(Node& i) const {
+ Parent::first(i);
+ while (i!=INVALID && !(*_node_filter)[i]) Parent::next(i);
+ }
+
+ void first(Arc& i) const {
+ Parent::first(i);
+ while (i!=INVALID && (!(*_edge_filter)[i]
+ || !(*_node_filter)[Parent::source(i)]
+ || !(*_node_filter)[Parent::target(i)]))
+ Parent::next(i);
+ }
+
+ void first(Edge& i) const {
+ Parent::first(i);
+ while (i!=INVALID && (!(*_edge_filter)[i]
+ || !(*_node_filter)[Parent::u(i)]
+ || !(*_node_filter)[Parent::v(i)]))
+ Parent::next(i);
+ }
+
+ void firstIn(Arc& i, const Node& n) const {
+ Parent::firstIn(i, n);
+ while (i!=INVALID && (!(*_edge_filter)[i]
+ || !(*_node_filter)[Parent::source(i)]))
+ Parent::nextIn(i);
+ }
+
+ void firstOut(Arc& i, const Node& n) const {
+ Parent::firstOut(i, n);
+ while (i!=INVALID && (!(*_edge_filter)[i]
+ || !(*_node_filter)[Parent::target(i)]))
+ Parent::nextOut(i);
+ }
+
+ void firstInc(Edge& i, bool& d, const Node& n) const {
+ Parent::firstInc(i, d, n);
+ while (i!=INVALID && (!(*_edge_filter)[i]
+ || !(*_node_filter)[Parent::u(i)]
+ || !(*_node_filter)[Parent::v(i)]))
+ Parent::nextInc(i, d);
+ }
+
+ void next(Node& i) const {
+ Parent::next(i);
+ while (i!=INVALID && !(*_node_filter)[i]) Parent::next(i);
+ }
+
+ void next(Arc& i) const {
+ Parent::next(i);
+ while (i!=INVALID && (!(*_edge_filter)[i]
+ || !(*_node_filter)[Parent::source(i)]
+ || !(*_node_filter)[Parent::target(i)]))
+ Parent::next(i);
+ }
+
+ void next(Edge& i) const {
+ Parent::next(i);
+ while (i!=INVALID && (!(*_edge_filter)[i]
+ || !(*_node_filter)[Parent::u(i)]
+ || !(*_node_filter)[Parent::v(i)]))
+ Parent::next(i);
+ }
+
+ void nextIn(Arc& i) const {
+ Parent::nextIn(i);
+ while (i!=INVALID && (!(*_edge_filter)[i]
+ || !(*_node_filter)[Parent::source(i)]))
+ Parent::nextIn(i);
+ }
+
+ void nextOut(Arc& i) const {
+ Parent::nextOut(i);
+ while (i!=INVALID && (!(*_edge_filter)[i]
+ || !(*_node_filter)[Parent::target(i)]))
+ Parent::nextOut(i);
+ }
+
+ void nextInc(Edge& i, bool& d) const {
+ Parent::nextInc(i, d);
+ while (i!=INVALID && (!(*_edge_filter)[i]
+ || !(*_node_filter)[Parent::u(i)]
+ || !(*_node_filter)[Parent::v(i)]))
+ Parent::nextInc(i, d);
+ }
+
+ void status(const Node& n, bool v) const { _node_filter->set(n, v); }
+ void status(const Edge& e, bool v) const { _edge_filter->set(e, v); }
+
+ bool status(const Node& n) const { return (*_node_filter)[n]; }
+ bool status(const Edge& e) const { return (*_edge_filter)[e]; }
+
+ typedef False NodeNumTag;
+ typedef False ArcNumTag;
+ typedef False EdgeNumTag;
+
+ typedef FindArcTagIndicator<Graph> FindArcTag;
+ Arc findArc(const Node& u, const Node& v,
+ const Arc& prev = INVALID) const {
+ if (!(*_node_filter)[u] || !(*_node_filter)[v]) {
+ return INVALID;
+ }
+ Arc arc = Parent::findArc(u, v, prev);
+ while (arc != INVALID && !(*_edge_filter)[arc]) {
+ arc = Parent::findArc(u, v, arc);
+ }
+ return arc;
+ }
+
+ typedef FindEdgeTagIndicator<Graph> FindEdgeTag;
+ Edge findEdge(const Node& u, const Node& v,
+ const Edge& prev = INVALID) const {
+ if (!(*_node_filter)[u] || !(*_node_filter)[v]) {
+ return INVALID;
+ }
+ Edge edge = Parent::findEdge(u, v, prev);
+ while (edge != INVALID && !(*_edge_filter)[edge]) {
+ edge = Parent::findEdge(u, v, edge);
+ }
+ return edge;
+ }
+
+ template <typename V>
+ class NodeMap
+ : public SubMapExtender<SubGraphBase<GR, NF, EF, ch>,
+ LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, NodeMap<V>)> {
+ typedef SubMapExtender<SubGraphBase<GR, NF, EF, ch>,
+ LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, NodeMap<V>)> Parent;
+
+ public:
+ typedef V Value;
+
+ NodeMap(const SubGraphBase<GR, NF, EF, ch>& adaptor)
+ : Parent(adaptor) {}
+ NodeMap(const SubGraphBase<GR, NF, EF, ch>& adaptor, const V& value)
+ : Parent(adaptor, value) {}
+
+ private:
+ NodeMap& operator=(const NodeMap& cmap) {
+ return operator=<NodeMap>(cmap);
+ }
+
+ template <typename CMap>
+ NodeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ template <typename V>
+ class ArcMap
+ : public SubMapExtender<SubGraphBase<GR, NF, EF, ch>,
+ LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, ArcMap<V>)> {
+ typedef SubMapExtender<SubGraphBase<GR, NF, EF, ch>,
+ LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, ArcMap<V>)> Parent;
+
+ public:
+ typedef V Value;
+
+ ArcMap(const SubGraphBase<GR, NF, EF, ch>& adaptor)
+ : Parent(adaptor) {}
+ ArcMap(const SubGraphBase<GR, NF, EF, ch>& adaptor, const V& value)
+ : Parent(adaptor, value) {}
+
+ private:
+ ArcMap& operator=(const ArcMap& cmap) {
+ return operator=<ArcMap>(cmap);
+ }
+
+ template <typename CMap>
+ ArcMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ template <typename V>
+ class EdgeMap
+ : public SubMapExtender<SubGraphBase<GR, NF, EF, ch>,
+ LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, EdgeMap<V>)> {
+ typedef SubMapExtender<SubGraphBase<GR, NF, EF, ch>,
+ LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, EdgeMap<V>)> Parent;
+
+ public:
+ typedef V Value;
+
+ EdgeMap(const SubGraphBase<GR, NF, EF, ch>& adaptor)
+ : Parent(adaptor) {}
+
+ EdgeMap(const SubGraphBase<GR, NF, EF, ch>& adaptor, const V& value)
+ : Parent(adaptor, value) {}
+
+ private:
+ EdgeMap& operator=(const EdgeMap& cmap) {
+ return operator=<EdgeMap>(cmap);
+ }
+
+ template <typename CMap>
+ EdgeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ };
+
+ template <typename GR, typename NF, typename EF>
+ class SubGraphBase<GR, NF, EF, false>
+ : public GraphAdaptorBase<GR> {
+ typedef GraphAdaptorBase<GR> Parent;
+ public:
+ typedef GR Graph;
+ typedef NF NodeFilterMap;
+ typedef EF EdgeFilterMap;
+
+ typedef SubGraphBase Adaptor;
+ protected:
+ NF* _node_filter;
+ EF* _edge_filter;
+ SubGraphBase()
+ : Parent(), _node_filter(0), _edge_filter(0) { }
+
+ void initialize(GR& graph, NF& node_filter, EF& edge_filter) {
+ Parent::initialize(graph);
+ _node_filter = &node_filter;
+ _edge_filter = &edge_filter;
+ }
+
+ public:
+
+ typedef typename Parent::Node Node;
+ typedef typename Parent::Arc Arc;
+ typedef typename Parent::Edge Edge;
+
+ void first(Node& i) const {
+ Parent::first(i);
+ while (i!=INVALID && !(*_node_filter)[i]) Parent::next(i);
+ }
+
+ void first(Arc& i) const {
+ Parent::first(i);
+ while (i!=INVALID && !(*_edge_filter)[i]) Parent::next(i);
+ }
+
+ void first(Edge& i) const {
+ Parent::first(i);
+ while (i!=INVALID && !(*_edge_filter)[i]) Parent::next(i);
+ }
+
+ void firstIn(Arc& i, const Node& n) const {
+ Parent::firstIn(i, n);
+ while (i!=INVALID && !(*_edge_filter)[i]) Parent::nextIn(i);
+ }
+
+ void firstOut(Arc& i, const Node& n) const {
+ Parent::firstOut(i, n);
+ while (i!=INVALID && !(*_edge_filter)[i]) Parent::nextOut(i);
+ }
+
+ void firstInc(Edge& i, bool& d, const Node& n) const {
+ Parent::firstInc(i, d, n);
+ while (i!=INVALID && !(*_edge_filter)[i]) Parent::nextInc(i, d);
+ }
+
+ void next(Node& i) const {
+ Parent::next(i);
+ while (i!=INVALID && !(*_node_filter)[i]) Parent::next(i);
+ }
+ void next(Arc& i) const {
+ Parent::next(i);
+ while (i!=INVALID && !(*_edge_filter)[i]) Parent::next(i);
+ }
+ void next(Edge& i) const {
+ Parent::next(i);
+ while (i!=INVALID && !(*_edge_filter)[i]) Parent::next(i);
+ }
+ void nextIn(Arc& i) const {
+ Parent::nextIn(i);
+ while (i!=INVALID && !(*_edge_filter)[i]) Parent::nextIn(i);
+ }
+
+ void nextOut(Arc& i) const {
+ Parent::nextOut(i);
+ while (i!=INVALID && !(*_edge_filter)[i]) Parent::nextOut(i);
+ }
+ void nextInc(Edge& i, bool& d) const {
+ Parent::nextInc(i, d);
+ while (i!=INVALID && !(*_edge_filter)[i]) Parent::nextInc(i, d);
+ }
+
+ void status(const Node& n, bool v) const { _node_filter->set(n, v); }
+ void status(const Edge& e, bool v) const { _edge_filter->set(e, v); }
+
+ bool status(const Node& n) const { return (*_node_filter)[n]; }
+ bool status(const Edge& e) const { return (*_edge_filter)[e]; }
+
+ typedef False NodeNumTag;
+ typedef False ArcNumTag;
+ typedef False EdgeNumTag;
+
+ typedef FindArcTagIndicator<Graph> FindArcTag;
+ Arc findArc(const Node& u, const Node& v,
+ const Arc& prev = INVALID) const {
+ Arc arc = Parent::findArc(u, v, prev);
+ while (arc != INVALID && !(*_edge_filter)[arc]) {
+ arc = Parent::findArc(u, v, arc);
+ }
+ return arc;
+ }
+
+ typedef FindEdgeTagIndicator<Graph> FindEdgeTag;
+ Edge findEdge(const Node& u, const Node& v,
+ const Edge& prev = INVALID) const {
+ Edge edge = Parent::findEdge(u, v, prev);
+ while (edge != INVALID && !(*_edge_filter)[edge]) {
+ edge = Parent::findEdge(u, v, edge);
+ }
+ return edge;
+ }
+
+ template <typename V>
+ class NodeMap
+ : public SubMapExtender<SubGraphBase<GR, NF, EF, false>,
+ LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, NodeMap<V>)> {
+ typedef SubMapExtender<SubGraphBase<GR, NF, EF, false>,
+ LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, NodeMap<V>)> Parent;
+
+ public:
+ typedef V Value;
+
+ NodeMap(const SubGraphBase<GR, NF, EF, false>& adaptor)
+ : Parent(adaptor) {}
+ NodeMap(const SubGraphBase<GR, NF, EF, false>& adaptor, const V& value)
+ : Parent(adaptor, value) {}
+
+ private:
+ NodeMap& operator=(const NodeMap& cmap) {
+ return operator=<NodeMap>(cmap);
+ }
+
+ template <typename CMap>
+ NodeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ template <typename V>
+ class ArcMap
+ : public SubMapExtender<SubGraphBase<GR, NF, EF, false>,
+ LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, ArcMap<V>)> {
+ typedef SubMapExtender<SubGraphBase<GR, NF, EF, false>,
+ LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, ArcMap<V>)> Parent;
+
+ public:
+ typedef V Value;
+
+ ArcMap(const SubGraphBase<GR, NF, EF, false>& adaptor)
+ : Parent(adaptor) {}
+ ArcMap(const SubGraphBase<GR, NF, EF, false>& adaptor, const V& value)
+ : Parent(adaptor, value) {}
+
+ private:
+ ArcMap& operator=(const ArcMap& cmap) {
+ return operator=<ArcMap>(cmap);
+ }
+
+ template <typename CMap>
+ ArcMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ template <typename V>
+ class EdgeMap
+ : public SubMapExtender<SubGraphBase<GR, NF, EF, false>,
+ LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, EdgeMap<V>)> {
+ typedef SubMapExtender<SubGraphBase<GR, NF, EF, false>,
+ LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, EdgeMap<V>)> Parent;
+
+ public:
+ typedef V Value;
+
+ EdgeMap(const SubGraphBase<GR, NF, EF, false>& adaptor)
+ : Parent(adaptor) {}
+
+ EdgeMap(const SubGraphBase<GR, NF, EF, false>& adaptor, const V& value)
+ : Parent(adaptor, value) {}
+
+ private:
+ EdgeMap& operator=(const EdgeMap& cmap) {
+ return operator=<EdgeMap>(cmap);
+ }
+
+ template <typename CMap>
+ EdgeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ };
+
+ /// \ingroup graph_adaptors
+ ///
+ /// \brief Adaptor class for hiding nodes and edges in an undirected
+ /// graph.
+ ///
+ /// SubGraph can be used for hiding nodes and edges in a graph.
+ /// A \c bool node map and a \c bool edge map must be specified, which
+ /// define the filters for nodes and edges.
+ /// Only the nodes and edges with \c true filter value are
+ /// shown in the subgraph. The edges that are incident to hidden
+ /// nodes are also filtered out.
+ /// This adaptor conforms to the \ref concepts::Graph "Graph" concept.
+ ///
+ /// The adapted graph can also be modified through this adaptor
+ /// by adding or removing nodes or edges, unless the \c GR template
+ /// parameter is set to be \c const.
+ ///
+ /// This class provides only linear time counting for nodes, edges and arcs.
+ ///
+ /// \tparam GR The type of the adapted graph.
+ /// It must conform to the \ref concepts::Graph "Graph" concept.
+ /// It can also be specified to be \c const.
+ /// \tparam NF The type of the node filter map.
+ /// It must be a \c bool (or convertible) node map of the
+ /// adapted graph. The default type is
+ /// \ref concepts::Graph::NodeMap "GR::NodeMap<bool>".
+ /// \tparam EF The type of the edge filter map.
+ /// It must be a \c bool (or convertible) edge map of the
+ /// adapted graph. The default type is
+ /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<bool>".
+ ///
+ /// \note The \c Node, \c Edge and \c Arc types of this adaptor and the
+ /// adapted graph are convertible to each other.
+ ///
+ /// \see FilterNodes
+ /// \see FilterEdges
+#ifdef DOXYGEN
+ template<typename GR, typename NF, typename EF>
+ class SubGraph {
+#else
+ template<typename GR,
+ typename NF = typename GR::template NodeMap<bool>,
+ typename EF = typename GR::template EdgeMap<bool> >
+ class SubGraph :
+ public GraphAdaptorExtender<SubGraphBase<GR, NF, EF, true> > {
+#endif
+ public:
+ /// The type of the adapted graph.
+ typedef GR Graph;
+ /// The type of the node filter map.
+ typedef NF NodeFilterMap;
+ /// The type of the edge filter map.
+ typedef EF EdgeFilterMap;
+
+ typedef GraphAdaptorExtender<SubGraphBase<GR, NF, EF, true> >
+ Parent;
+
+ typedef typename Parent::Node Node;
+ typedef typename Parent::Edge Edge;
+
+ protected:
+ SubGraph() { }
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Creates a subgraph for the given graph with the given node
+ /// and edge filter maps.
+ SubGraph(GR& graph, NF& node_filter, EF& edge_filter) {
+ this->initialize(graph, node_filter, edge_filter);
+ }
+
+ /// \brief Sets the status of the given node
+ ///
+ /// This function sets the status of the given node.
+ /// It is done by simply setting the assigned value of \c n
+ /// to \c v in the node filter map.
+ void status(const Node& n, bool v) const { Parent::status(n, v); }
+
+ /// \brief Sets the status of the given edge
+ ///
+ /// This function sets the status of the given edge.
+ /// It is done by simply setting the assigned value of \c e
+ /// to \c v in the edge filter map.
+ void status(const Edge& e, bool v) const { Parent::status(e, v); }
+
+ /// \brief Returns the status of the given node
+ ///
+ /// This function returns the status of the given node.
+ /// It is \c true if the given node is enabled (i.e. not hidden).
+ bool status(const Node& n) const { return Parent::status(n); }
+
+ /// \brief Returns the status of the given edge
+ ///
+ /// This function returns the status of the given edge.
+ /// It is \c true if the given edge is enabled (i.e. not hidden).
+ bool status(const Edge& e) const { return Parent::status(e); }
+
+ /// \brief Disables the given node
+ ///
+ /// This function disables the given node in the subdigraph,
+ /// so the iteration jumps over it.
+ /// It is the same as \ref status() "status(n, false)".
+ void disable(const Node& n) const { Parent::status(n, false); }
+
+ /// \brief Disables the given edge
+ ///
+ /// This function disables the given edge in the subgraph,
+ /// so the iteration jumps over it.
+ /// It is the same as \ref status() "status(e, false)".
+ void disable(const Edge& e) const { Parent::status(e, false); }
+
+ /// \brief Enables the given node
+ ///
+ /// This function enables the given node in the subdigraph.
+ /// It is the same as \ref status() "status(n, true)".
+ void enable(const Node& n) const { Parent::status(n, true); }
+
+ /// \brief Enables the given edge
+ ///
+ /// This function enables the given edge in the subgraph.
+ /// It is the same as \ref status() "status(e, true)".
+ void enable(const Edge& e) const { Parent::status(e, true); }
+
+ };
+
+ /// \brief Returns a read-only SubGraph adaptor
+ ///
+ /// This function just returns a read-only \ref SubGraph adaptor.
+ /// \ingroup graph_adaptors
+ /// \relates SubGraph
+ template<typename GR, typename NF, typename EF>
+ SubGraph<const GR, NF, EF>
+ subGraph(const GR& graph, NF& node_filter, EF& edge_filter) {
+ return SubGraph<const GR, NF, EF>
+ (graph, node_filter, edge_filter);
+ }
+
+ template<typename GR, typename NF, typename EF>
+ SubGraph<const GR, const NF, EF>
+ subGraph(const GR& graph, const NF& node_filter, EF& edge_filter) {
+ return SubGraph<const GR, const NF, EF>
+ (graph, node_filter, edge_filter);
+ }
+
+ template<typename GR, typename NF, typename EF>
+ SubGraph<const GR, NF, const EF>
+ subGraph(const GR& graph, NF& node_filter, const EF& edge_filter) {
+ return SubGraph<const GR, NF, const EF>
+ (graph, node_filter, edge_filter);
+ }
+
+ template<typename GR, typename NF, typename EF>
+ SubGraph<const GR, const NF, const EF>
+ subGraph(const GR& graph, const NF& node_filter, const EF& edge_filter) {
+ return SubGraph<const GR, const NF, const EF>
+ (graph, node_filter, edge_filter);
+ }
+
+
+ /// \ingroup graph_adaptors
+ ///
+ /// \brief Adaptor class for hiding nodes in a digraph or a graph.
+ ///
+ /// FilterNodes adaptor can be used for hiding nodes in a digraph or a
+ /// graph. A \c bool node map must be specified, which defines the filter
+ /// for the nodes. Only the nodes with \c true filter value and the
+ /// arcs/edges incident to nodes both with \c true filter value are shown
+ /// in the subgraph. This adaptor conforms to the \ref concepts::Digraph
+ /// "Digraph" concept or the \ref concepts::Graph "Graph" concept
+ /// depending on the \c GR template parameter.
+ ///
+ /// The adapted (di)graph can also be modified through this adaptor
+ /// by adding or removing nodes or arcs/edges, unless the \c GR template
+ /// parameter is set to be \c const.
+ ///
+ /// This class provides only linear time item counting.
+ ///
+ /// \tparam GR The type of the adapted digraph or graph.
+ /// It must conform to the \ref concepts::Digraph "Digraph" concept
+ /// or the \ref concepts::Graph "Graph" concept.
+ /// It can also be specified to be \c const.
+ /// \tparam NF The type of the node filter map.
+ /// It must be a \c bool (or convertible) node map of the
+ /// adapted (di)graph. The default type is
+ /// \ref concepts::Graph::NodeMap "GR::NodeMap<bool>".
+ ///
+ /// \note The \c Node and <tt>Arc/Edge</tt> types of this adaptor and the
+ /// adapted (di)graph are convertible to each other.
+#ifdef DOXYGEN
+ template<typename GR, typename NF>
+ class FilterNodes {
+#else
+ template<typename GR,
+ typename NF = typename GR::template NodeMap<bool>,
+ typename Enable = void>
+ class FilterNodes :
+ public DigraphAdaptorExtender<
+ SubDigraphBase<GR, NF, ConstMap<typename GR::Arc, Const<bool, true> >,
+ true> > {
+#endif
+ typedef DigraphAdaptorExtender<
+ SubDigraphBase<GR, NF, ConstMap<typename GR::Arc, Const<bool, true> >,
+ true> > Parent;
+
+ public:
+
+ typedef GR Digraph;
+ typedef NF NodeFilterMap;
+
+ typedef typename Parent::Node Node;
+
+ protected:
+ ConstMap<typename Digraph::Arc, Const<bool, true> > const_true_map;
+
+ FilterNodes() : const_true_map() {}
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Creates a subgraph for the given digraph or graph with the
+ /// given node filter map.
+ FilterNodes(GR& graph, NF& node_filter)
+ : Parent(), const_true_map()
+ {
+ Parent::initialize(graph, node_filter, const_true_map);
+ }
+
+ /// \brief Sets the status of the given node
+ ///
+ /// This function sets the status of the given node.
+ /// It is done by simply setting the assigned value of \c n
+ /// to \c v in the node filter map.
+ void status(const Node& n, bool v) const { Parent::status(n, v); }
+
+ /// \brief Returns the status of the given node
+ ///
+ /// This function returns the status of the given node.
+ /// It is \c true if the given node is enabled (i.e. not hidden).
+ bool status(const Node& n) const { return Parent::status(n); }
+
+ /// \brief Disables the given node
+ ///
+ /// This function disables the given node, so the iteration
+ /// jumps over it.
+ /// It is the same as \ref status() "status(n, false)".
+ void disable(const Node& n) const { Parent::status(n, false); }
+
+ /// \brief Enables the given node
+ ///
+ /// This function enables the given node.
+ /// It is the same as \ref status() "status(n, true)".
+ void enable(const Node& n) const { Parent::status(n, true); }
+
+ };
+
+ template<typename GR, typename NF>
+ class FilterNodes<GR, NF,
+ typename enable_if<UndirectedTagIndicator<GR> >::type> :
+ public GraphAdaptorExtender<
+ SubGraphBase<GR, NF, ConstMap<typename GR::Edge, Const<bool, true> >,
+ true> > {
+
+ typedef GraphAdaptorExtender<
+ SubGraphBase<GR, NF, ConstMap<typename GR::Edge, Const<bool, true> >,
+ true> > Parent;
+
+ public:
+
+ typedef GR Graph;
+ typedef NF NodeFilterMap;
+
+ typedef typename Parent::Node Node;
+
+ protected:
+ ConstMap<typename GR::Edge, Const<bool, true> > const_true_map;
+
+ FilterNodes() : const_true_map() {}
+
+ public:
+
+ FilterNodes(GR& graph, NodeFilterMap& node_filter) :
+ Parent(), const_true_map() {
+ Parent::initialize(graph, node_filter, const_true_map);
+ }
+
+ void status(const Node& n, bool v) const { Parent::status(n, v); }
+ bool status(const Node& n) const { return Parent::status(n); }
+ void disable(const Node& n) const { Parent::status(n, false); }
+ void enable(const Node& n) const { Parent::status(n, true); }
+
+ };
+
+
+ /// \brief Returns a read-only FilterNodes adaptor
+ ///
+ /// This function just returns a read-only \ref FilterNodes adaptor.
+ /// \ingroup graph_adaptors
+ /// \relates FilterNodes
+ template<typename GR, typename NF>
+ FilterNodes<const GR, NF>
+ filterNodes(const GR& graph, NF& node_filter) {
+ return FilterNodes<const GR, NF>(graph, node_filter);
+ }
+
+ template<typename GR, typename NF>
+ FilterNodes<const GR, const NF>
+ filterNodes(const GR& graph, const NF& node_filter) {
+ return FilterNodes<const GR, const NF>(graph, node_filter);
+ }
+
+ /// \ingroup graph_adaptors
+ ///
+ /// \brief Adaptor class for hiding arcs in a digraph.
+ ///
+ /// FilterArcs adaptor can be used for hiding arcs in a digraph.
+ /// A \c bool arc map must be specified, which defines the filter for
+ /// the arcs. Only the arcs with \c true filter value are shown in the
+ /// subdigraph. This adaptor conforms to the \ref concepts::Digraph
+ /// "Digraph" concept.
+ ///
+ /// The adapted digraph can also be modified through this adaptor
+ /// by adding or removing nodes or arcs, unless the \c GR template
+ /// parameter is set to be \c const.
+ ///
+ /// This class provides only linear time counting for nodes and arcs.
+ ///
+ /// \tparam DGR The type of the adapted digraph.
+ /// It must conform to the \ref concepts::Digraph "Digraph" concept.
+ /// It can also be specified to be \c const.
+ /// \tparam AF The type of the arc filter map.
+ /// It must be a \c bool (or convertible) arc map of the
+ /// adapted digraph. The default type is
+ /// \ref concepts::Digraph::ArcMap "DGR::ArcMap<bool>".
+ ///
+ /// \note The \c Node and \c Arc types of this adaptor and the adapted
+ /// digraph are convertible to each other.
+#ifdef DOXYGEN
+ template<typename DGR,
+ typename AF>
+ class FilterArcs {
+#else
+ template<typename DGR,
+ typename AF = typename DGR::template ArcMap<bool> >
+ class FilterArcs :
+ public DigraphAdaptorExtender<
+ SubDigraphBase<DGR, ConstMap<typename DGR::Node, Const<bool, true> >,
+ AF, false> > {
+#endif
+ typedef DigraphAdaptorExtender<
+ SubDigraphBase<DGR, ConstMap<typename DGR::Node, Const<bool, true> >,
+ AF, false> > Parent;
+
+ public:
+
+ /// The type of the adapted digraph.
+ typedef DGR Digraph;
+ /// The type of the arc filter map.
+ typedef AF ArcFilterMap;
+
+ typedef typename Parent::Arc Arc;
+
+ protected:
+ ConstMap<typename DGR::Node, Const<bool, true> > const_true_map;
+
+ FilterArcs() : const_true_map() {}
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Creates a subdigraph for the given digraph with the given arc
+ /// filter map.
+ FilterArcs(DGR& digraph, ArcFilterMap& arc_filter)
+ : Parent(), const_true_map() {
+ Parent::initialize(digraph, const_true_map, arc_filter);
+ }
+
+ /// \brief Sets the status of the given arc
+ ///
+ /// This function sets the status of the given arc.
+ /// It is done by simply setting the assigned value of \c a
+ /// to \c v in the arc filter map.
+ void status(const Arc& a, bool v) const { Parent::status(a, v); }
+
+ /// \brief Returns the status of the given arc
+ ///
+ /// This function returns the status of the given arc.
+ /// It is \c true if the given arc is enabled (i.e. not hidden).
+ bool status(const Arc& a) const { return Parent::status(a); }
+
+ /// \brief Disables the given arc
+ ///
+ /// This function disables the given arc in the subdigraph,
+ /// so the iteration jumps over it.
+ /// It is the same as \ref status() "status(a, false)".
+ void disable(const Arc& a) const { Parent::status(a, false); }
+
+ /// \brief Enables the given arc
+ ///
+ /// This function enables the given arc in the subdigraph.
+ /// It is the same as \ref status() "status(a, true)".
+ void enable(const Arc& a) const { Parent::status(a, true); }
+
+ };
+
+ /// \brief Returns a read-only FilterArcs adaptor
+ ///
+ /// This function just returns a read-only \ref FilterArcs adaptor.
+ /// \ingroup graph_adaptors
+ /// \relates FilterArcs
+ template<typename DGR, typename AF>
+ FilterArcs<const DGR, AF>
+ filterArcs(const DGR& digraph, AF& arc_filter) {
+ return FilterArcs<const DGR, AF>(digraph, arc_filter);
+ }
+
+ template<typename DGR, typename AF>
+ FilterArcs<const DGR, const AF>
+ filterArcs(const DGR& digraph, const AF& arc_filter) {
+ return FilterArcs<const DGR, const AF>(digraph, arc_filter);
+ }
+
+ /// \ingroup graph_adaptors
+ ///
+ /// \brief Adaptor class for hiding edges in a graph.
+ ///
+ /// FilterEdges adaptor can be used for hiding edges in a graph.
+ /// A \c bool edge map must be specified, which defines the filter for
+ /// the edges. Only the edges with \c true filter value are shown in the
+ /// subgraph. This adaptor conforms to the \ref concepts::Graph
+ /// "Graph" concept.
+ ///
+ /// The adapted graph can also be modified through this adaptor
+ /// by adding or removing nodes or edges, unless the \c GR template
+ /// parameter is set to be \c const.
+ ///
+ /// This class provides only linear time counting for nodes, edges and arcs.
+ ///
+ /// \tparam GR The type of the adapted graph.
+ /// It must conform to the \ref concepts::Graph "Graph" concept.
+ /// It can also be specified to be \c const.
+ /// \tparam EF The type of the edge filter map.
+ /// It must be a \c bool (or convertible) edge map of the
+ /// adapted graph. The default type is
+ /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<bool>".
+ ///
+ /// \note The \c Node, \c Edge and \c Arc types of this adaptor and the
+ /// adapted graph are convertible to each other.
+#ifdef DOXYGEN
+ template<typename GR,
+ typename EF>
+ class FilterEdges {
+#else
+ template<typename GR,
+ typename EF = typename GR::template EdgeMap<bool> >
+ class FilterEdges :
+ public GraphAdaptorExtender<
+ SubGraphBase<GR, ConstMap<typename GR::Node, Const<bool, true> >,
+ EF, false> > {
+#endif
+ typedef GraphAdaptorExtender<
+ SubGraphBase<GR, ConstMap<typename GR::Node, Const<bool, true > >,
+ EF, false> > Parent;
+
+ public:
+
+ /// The type of the adapted graph.
+ typedef GR Graph;
+ /// The type of the edge filter map.
+ typedef EF EdgeFilterMap;
+
+ typedef typename Parent::Edge Edge;
+
+ protected:
+ ConstMap<typename GR::Node, Const<bool, true> > const_true_map;
+
+ FilterEdges() : const_true_map(true) {
+ Parent::setNodeFilterMap(const_true_map);
+ }
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Creates a subgraph for the given graph with the given edge
+ /// filter map.
+ FilterEdges(GR& graph, EF& edge_filter)
+ : Parent(), const_true_map() {
+ Parent::initialize(graph, const_true_map, edge_filter);
+ }
+
+ /// \brief Sets the status of the given edge
+ ///
+ /// This function sets the status of the given edge.
+ /// It is done by simply setting the assigned value of \c e
+ /// to \c v in the edge filter map.
+ void status(const Edge& e, bool v) const { Parent::status(e, v); }
+
+ /// \brief Returns the status of the given edge
+ ///
+ /// This function returns the status of the given edge.
+ /// It is \c true if the given edge is enabled (i.e. not hidden).
+ bool status(const Edge& e) const { return Parent::status(e); }
+
+ /// \brief Disables the given edge
+ ///
+ /// This function disables the given edge in the subgraph,
+ /// so the iteration jumps over it.
+ /// It is the same as \ref status() "status(e, false)".
+ void disable(const Edge& e) const { Parent::status(e, false); }
+
+ /// \brief Enables the given edge
+ ///
+ /// This function enables the given edge in the subgraph.
+ /// It is the same as \ref status() "status(e, true)".
+ void enable(const Edge& e) const { Parent::status(e, true); }
+
+ };
+
+ /// \brief Returns a read-only FilterEdges adaptor
+ ///
+ /// This function just returns a read-only \ref FilterEdges adaptor.
+ /// \ingroup graph_adaptors
+ /// \relates FilterEdges
+ template<typename GR, typename EF>
+ FilterEdges<const GR, EF>
+ filterEdges(const GR& graph, EF& edge_filter) {
+ return FilterEdges<const GR, EF>(graph, edge_filter);
+ }
+
+ template<typename GR, typename EF>
+ FilterEdges<const GR, const EF>
+ filterEdges(const GR& graph, const EF& edge_filter) {
+ return FilterEdges<const GR, const EF>(graph, edge_filter);
+ }
+
+
+ template <typename DGR>
+ class UndirectorBase {
+ public:
+ typedef DGR Digraph;
+ typedef UndirectorBase Adaptor;
+
+ typedef True UndirectedTag;
+
+ typedef typename Digraph::Arc Edge;
+ typedef typename Digraph::Node Node;
+
+ class Arc {
+ friend class UndirectorBase;
+ protected:
+ Edge _edge;
+ bool _forward;
+
+ Arc(const Edge& edge, bool forward)
+ : _edge(edge), _forward(forward) {}
+
+ public:
+ Arc() {}
+
+ Arc(Invalid) : _edge(INVALID), _forward(true) {}
+
+ operator const Edge&() const { return _edge; }
+
+ bool operator==(const Arc &other) const {
+ return _forward == other._forward && _edge == other._edge;
+ }
+ bool operator!=(const Arc &other) const {
+ return _forward != other._forward || _edge != other._edge;
+ }
+ bool operator<(const Arc &other) const {
+ return _forward < other._forward ||
+ (_forward == other._forward && _edge < other._edge);
+ }
+ };
+
+ void first(Node& n) const {
+ _digraph->first(n);
+ }
+
+ void next(Node& n) const {
+ _digraph->next(n);
+ }
+
+ void first(Arc& a) const {
+ _digraph->first(a._edge);
+ a._forward = true;
+ }
+
+ void next(Arc& a) const {
+ if (a._forward) {
+ a._forward = false;
+ } else {
+ _digraph->next(a._edge);
+ a._forward = true;
+ }
+ }
+
+ void first(Edge& e) const {
+ _digraph->first(e);
+ }
+
+ void next(Edge& e) const {
+ _digraph->next(e);
+ }
+
+ void firstOut(Arc& a, const Node& n) const {
+ _digraph->firstIn(a._edge, n);
+ if (a._edge != INVALID ) {
+ a._forward = false;
+ } else {
+ _digraph->firstOut(a._edge, n);
+ a._forward = true;
+ }
+ }
+ void nextOut(Arc &a) const {
+ if (!a._forward) {
+ Node n = _digraph->target(a._edge);
+ _digraph->nextIn(a._edge);
+ if (a._edge == INVALID) {
+ _digraph->firstOut(a._edge, n);
+ a._forward = true;
+ }
+ }
+ else {
+ _digraph->nextOut(a._edge);
+ }
+ }
+
+ void firstIn(Arc &a, const Node &n) const {
+ _digraph->firstOut(a._edge, n);
+ if (a._edge != INVALID ) {
+ a._forward = false;
+ } else {
+ _digraph->firstIn(a._edge, n);
+ a._forward = true;
+ }
+ }
+ void nextIn(Arc &a) const {
+ if (!a._forward) {
+ Node n = _digraph->source(a._edge);
+ _digraph->nextOut(a._edge);
+ if (a._edge == INVALID ) {
+ _digraph->firstIn(a._edge, n);
+ a._forward = true;
+ }
+ }
+ else {
+ _digraph->nextIn(a._edge);
+ }
+ }
+
+ void firstInc(Edge &e, bool &d, const Node &n) const {
+ d = true;
+ _digraph->firstOut(e, n);
+ if (e != INVALID) return;
+ d = false;
+ _digraph->firstIn(e, n);
+ }
+
+ void nextInc(Edge &e, bool &d) const {
+ if (d) {
+ Node s = _digraph->source(e);
+ _digraph->nextOut(e);
+ if (e != INVALID) return;
+ d = false;
+ _digraph->firstIn(e, s);
+ } else {
+ _digraph->nextIn(e);
+ }
+ }
+
+ Node u(const Edge& e) const {
+ return _digraph->source(e);
+ }
+
+ Node v(const Edge& e) const {
+ return _digraph->target(e);
+ }
+
+ Node source(const Arc &a) const {
+ return a._forward ? _digraph->source(a._edge) : _digraph->target(a._edge);
+ }
+
+ Node target(const Arc &a) const {
+ return a._forward ? _digraph->target(a._edge) : _digraph->source(a._edge);
+ }
+
+ static Arc direct(const Edge &e, bool d) {
+ return Arc(e, d);
+ }
+
+ static bool direction(const Arc &a) { return a._forward; }
+
+ Node nodeFromId(int ix) const { return _digraph->nodeFromId(ix); }
+ Arc arcFromId(int ix) const {
+ return direct(_digraph->arcFromId(ix >> 1), bool(ix & 1));
+ }
+ Edge edgeFromId(int ix) const { return _digraph->arcFromId(ix); }
+
+ int id(const Node &n) const { return _digraph->id(n); }
+ int id(const Arc &a) const {
+ return (_digraph->id(a) << 1) | (a._forward ? 1 : 0);
+ }
+ int id(const Edge &e) const { return _digraph->id(e); }
+
+ int maxNodeId() const { return _digraph->maxNodeId(); }
+ int maxArcId() const { return (_digraph->maxArcId() << 1) | 1; }
+ int maxEdgeId() const { return _digraph->maxArcId(); }
+
+ Node addNode() { return _digraph->addNode(); }
+ Edge addEdge(const Node& u, const Node& v) {
+ return _digraph->addArc(u, v);
+ }
+
+ void erase(const Node& i) { _digraph->erase(i); }
+ void erase(const Edge& i) { _digraph->erase(i); }
+
+ void clear() { _digraph->clear(); }
+
+ typedef NodeNumTagIndicator<Digraph> NodeNumTag;
+ int nodeNum() const { return _digraph->nodeNum(); }
+
+ typedef ArcNumTagIndicator<Digraph> ArcNumTag;
+ int arcNum() const { return 2 * _digraph->arcNum(); }
+
+ typedef ArcNumTag EdgeNumTag;
+ int edgeNum() const { return _digraph->arcNum(); }
+
+ typedef FindArcTagIndicator<Digraph> FindArcTag;
+ Arc findArc(Node s, Node t, Arc p = INVALID) const {
+ if (p == INVALID) {
+ Edge arc = _digraph->findArc(s, t);
+ if (arc != INVALID) return direct(arc, true);
+ arc = _digraph->findArc(t, s);
+ if (arc != INVALID) return direct(arc, false);
+ } else if (direction(p)) {
+ Edge arc = _digraph->findArc(s, t, p);
+ if (arc != INVALID) return direct(arc, true);
+ arc = _digraph->findArc(t, s);
+ if (arc != INVALID) return direct(arc, false);
+ } else {
+ Edge arc = _digraph->findArc(t, s, p);
+ if (arc != INVALID) return direct(arc, false);
+ }
+ return INVALID;
+ }
+
+ typedef FindArcTag FindEdgeTag;
+ Edge findEdge(Node s, Node t, Edge p = INVALID) const {
+ if (s != t) {
+ if (p == INVALID) {
+ Edge arc = _digraph->findArc(s, t);
+ if (arc != INVALID) return arc;
+ arc = _digraph->findArc(t, s);
+ if (arc != INVALID) return arc;
+ } else if (_digraph->source(p) == s) {
+ Edge arc = _digraph->findArc(s, t, p);
+ if (arc != INVALID) return arc;
+ arc = _digraph->findArc(t, s);
+ if (arc != INVALID) return arc;
+ } else {
+ Edge arc = _digraph->findArc(t, s, p);
+ if (arc != INVALID) return arc;
+ }
+ } else {
+ return _digraph->findArc(s, t, p);
+ }
+ return INVALID;
+ }
+
+ private:
+
+ template <typename V>
+ class ArcMapBase {
+ private:
+
+ typedef typename DGR::template ArcMap<V> MapImpl;
+
+ public:
+
+ typedef typename MapTraits<MapImpl>::ReferenceMapTag ReferenceMapTag;
+
+ typedef V Value;
+ typedef Arc Key;
+ typedef typename MapTraits<MapImpl>::ConstReturnValue ConstReturnValue;
+ typedef typename MapTraits<MapImpl>::ReturnValue ReturnValue;
+ typedef typename MapTraits<MapImpl>::ConstReturnValue ConstReference;
+ typedef typename MapTraits<MapImpl>::ReturnValue Reference;
+
+ ArcMapBase(const UndirectorBase<DGR>& adaptor) :
+ _forward(*adaptor._digraph), _backward(*adaptor._digraph) {}
+
+ ArcMapBase(const UndirectorBase<DGR>& adaptor, const V& value)
+ : _forward(*adaptor._digraph, value),
+ _backward(*adaptor._digraph, value) {}
+
+ void set(const Arc& a, const V& value) {
+ if (direction(a)) {
+ _forward.set(a, value);
+ } else {
+ _backward.set(a, value);
+ }
+ }
+
+ ConstReturnValue operator[](const Arc& a) const {
+ if (direction(a)) {
+ return _forward[a];
+ } else {
+ return _backward[a];
+ }
+ }
+
+ ReturnValue operator[](const Arc& a) {
+ if (direction(a)) {
+ return _forward[a];
+ } else {
+ return _backward[a];
+ }
+ }
+
+ protected:
+
+ MapImpl _forward, _backward;
+
+ };
+
+ public:
+
+ template <typename V>
+ class NodeMap : public DGR::template NodeMap<V> {
+ typedef typename DGR::template NodeMap<V> Parent;
+
+ public:
+ typedef V Value;
+
+ explicit NodeMap(const UndirectorBase<DGR>& adaptor)
+ : Parent(*adaptor._digraph) {}
+
+ NodeMap(const UndirectorBase<DGR>& adaptor, const V& value)
+ : Parent(*adaptor._digraph, value) { }
+
+ private:
+ NodeMap& operator=(const NodeMap& cmap) {
+ return operator=<NodeMap>(cmap);
+ }
+
+ template <typename CMap>
+ NodeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+
+ };
+
+ template <typename V>
+ class ArcMap
+ : public SubMapExtender<UndirectorBase<DGR>, ArcMapBase<V> > {
+ typedef SubMapExtender<UndirectorBase<DGR>, ArcMapBase<V> > Parent;
+
+ public:
+ typedef V Value;
+
+ explicit ArcMap(const UndirectorBase<DGR>& adaptor)
+ : Parent(adaptor) {}
+
+ ArcMap(const UndirectorBase<DGR>& adaptor, const V& value)
+ : Parent(adaptor, value) {}
+
+ private:
+ ArcMap& operator=(const ArcMap& cmap) {
+ return operator=<ArcMap>(cmap);
+ }
+
+ template <typename CMap>
+ ArcMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ template <typename V>
+ class EdgeMap : public Digraph::template ArcMap<V> {
+ typedef typename Digraph::template ArcMap<V> Parent;
+
+ public:
+ typedef V Value;
+
+ explicit EdgeMap(const UndirectorBase<DGR>& adaptor)
+ : Parent(*adaptor._digraph) {}
+
+ EdgeMap(const UndirectorBase<DGR>& adaptor, const V& value)
+ : Parent(*adaptor._digraph, value) {}
+
+ private:
+ EdgeMap& operator=(const EdgeMap& cmap) {
+ return operator=<EdgeMap>(cmap);
+ }
+
+ template <typename CMap>
+ EdgeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+
+ };
+
+ typedef typename ItemSetTraits<DGR, Node>::ItemNotifier NodeNotifier;
+ NodeNotifier& notifier(Node) const { return _digraph->notifier(Node()); }
+
+ typedef typename ItemSetTraits<DGR, Edge>::ItemNotifier EdgeNotifier;
+ EdgeNotifier& notifier(Edge) const { return _digraph->notifier(Edge()); }
+
+ typedef EdgeNotifier ArcNotifier;
+ ArcNotifier& notifier(Arc) const { return _digraph->notifier(Edge()); }
+
+ protected:
+
+ UndirectorBase() : _digraph(0) {}
+
+ DGR* _digraph;
+
+ void initialize(DGR& digraph) {
+ _digraph = &digraph;
+ }
+
+ };
+
+ /// \ingroup graph_adaptors
+ ///
+ /// \brief Adaptor class for viewing a digraph as an undirected graph.
+ ///
+ /// Undirector adaptor can be used for viewing a digraph as an undirected
+ /// graph. All arcs of the underlying digraph are showed in the
+ /// adaptor as an edge (and also as a pair of arcs, of course).
+ /// This adaptor conforms to the \ref concepts::Graph "Graph" concept.
+ ///
+ /// The adapted digraph can also be modified through this adaptor
+ /// by adding or removing nodes or edges, unless the \c GR template
+ /// parameter is set to be \c const.
+ ///
+ /// This class provides item counting in the same time as the adapted
+ /// digraph structure.
+ ///
+ /// \tparam DGR The type of the adapted digraph.
+ /// It must conform to the \ref concepts::Digraph "Digraph" concept.
+ /// It can also be specified to be \c const.
+ ///
+ /// \note The \c Node type of this adaptor and the adapted digraph are
+ /// convertible to each other, moreover the \c Edge type of the adaptor
+ /// and the \c Arc type of the adapted digraph are also convertible to
+ /// each other.
+ /// (Thus the \c Arc type of the adaptor is convertible to the \c Arc type
+ /// of the adapted digraph.)
+ template<typename DGR>
+#ifdef DOXYGEN
+ class Undirector {
+#else
+ class Undirector :
+ public GraphAdaptorExtender<UndirectorBase<DGR> > {
+#endif
+ typedef GraphAdaptorExtender<UndirectorBase<DGR> > Parent;
+ public:
+ /// The type of the adapted digraph.
+ typedef DGR Digraph;
+ protected:
+ Undirector() { }
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Creates an undirected graph from the given digraph.
+ Undirector(DGR& digraph) {
+ this->initialize(digraph);
+ }
+
+ /// \brief Arc map combined from two original arc maps
+ ///
+ /// This map adaptor class adapts two arc maps of the underlying
+ /// digraph to get an arc map of the undirected graph.
+ /// Its value type is inherited from the first arc map type (\c FW).
+ /// \tparam FW The type of the "foward" arc map.
+ /// \tparam BK The type of the "backward" arc map.
+ template <typename FW, typename BK>
+ class CombinedArcMap {
+ public:
+
+ /// The key type of the map
+ typedef typename Parent::Arc Key;
+ /// The value type of the map
+ typedef typename FW::Value Value;
+
+ typedef typename MapTraits<FW>::ReferenceMapTag ReferenceMapTag;
+
+ typedef typename MapTraits<FW>::ReturnValue ReturnValue;
+ typedef typename MapTraits<FW>::ConstReturnValue ConstReturnValue;
+ typedef typename MapTraits<FW>::ReturnValue Reference;
+ typedef typename MapTraits<FW>::ConstReturnValue ConstReference;
+
+ /// Constructor
+ CombinedArcMap(FW& forward, BK& backward)
+ : _forward(&forward), _backward(&backward) {}
+
+ /// Sets the value associated with the given key.
+ void set(const Key& e, const Value& a) {
+ if (Parent::direction(e)) {
+ _forward->set(e, a);
+ } else {
+ _backward->set(e, a);
+ }
+ }
+
+ /// Returns the value associated with the given key.
+ ConstReturnValue operator[](const Key& e) const {
+ if (Parent::direction(e)) {
+ return (*_forward)[e];
+ } else {
+ return (*_backward)[e];
+ }
+ }
+
+ /// Returns a reference to the value associated with the given key.
+ ReturnValue operator[](const Key& e) {
+ if (Parent::direction(e)) {
+ return (*_forward)[e];
+ } else {
+ return (*_backward)[e];
+ }
+ }
+
+ protected:
+
+ FW* _forward;
+ BK* _backward;
+
+ };
+
+ /// \brief Returns a combined arc map
+ ///
+ /// This function just returns a combined arc map.
+ template <typename FW, typename BK>
+ static CombinedArcMap<FW, BK>
+ combinedArcMap(FW& forward, BK& backward) {
+ return CombinedArcMap<FW, BK>(forward, backward);
+ }
+
+ template <typename FW, typename BK>
+ static CombinedArcMap<const FW, BK>
+ combinedArcMap(const FW& forward, BK& backward) {
+ return CombinedArcMap<const FW, BK>(forward, backward);
+ }
+
+ template <typename FW, typename BK>
+ static CombinedArcMap<FW, const BK>
+ combinedArcMap(FW& forward, const BK& backward) {
+ return CombinedArcMap<FW, const BK>(forward, backward);
+ }
+
+ template <typename FW, typename BK>
+ static CombinedArcMap<const FW, const BK>
+ combinedArcMap(const FW& forward, const BK& backward) {
+ return CombinedArcMap<const FW, const BK>(forward, backward);
+ }
+
+ };
+
+ /// \brief Returns a read-only Undirector adaptor
+ ///
+ /// This function just returns a read-only \ref Undirector adaptor.
+ /// \ingroup graph_adaptors
+ /// \relates Undirector
+ template<typename DGR>
+ Undirector<const DGR> undirector(const DGR& digraph) {
+ return Undirector<const DGR>(digraph);
+ }
+
+
+ template <typename GR, typename DM>
+ class OrienterBase {
+ public:
+
+ typedef GR Graph;
+ typedef DM DirectionMap;
+
+ typedef typename GR::Node Node;
+ typedef typename GR::Edge Arc;
+
+ void reverseArc(const Arc& arc) {
+ _direction->set(arc, !(*_direction)[arc]);
+ }
+
+ void first(Node& i) const { _graph->first(i); }
+ void first(Arc& i) const { _graph->first(i); }
+ void firstIn(Arc& i, const Node& n) const {
+ bool d = true;
+ _graph->firstInc(i, d, n);
+ while (i != INVALID && d == (*_direction)[i]) _graph->nextInc(i, d);
+ }
+ void firstOut(Arc& i, const Node& n ) const {
+ bool d = true;
+ _graph->firstInc(i, d, n);
+ while (i != INVALID && d != (*_direction)[i]) _graph->nextInc(i, d);
+ }
+
+ void next(Node& i) const { _graph->next(i); }
+ void next(Arc& i) const { _graph->next(i); }
+ void nextIn(Arc& i) const {
+ bool d = !(*_direction)[i];
+ _graph->nextInc(i, d);
+ while (i != INVALID && d == (*_direction)[i]) _graph->nextInc(i, d);
+ }
+ void nextOut(Arc& i) const {
+ bool d = (*_direction)[i];
+ _graph->nextInc(i, d);
+ while (i != INVALID && d != (*_direction)[i]) _graph->nextInc(i, d);
+ }
+
+ Node source(const Arc& e) const {
+ return (*_direction)[e] ? _graph->u(e) : _graph->v(e);
+ }
+ Node target(const Arc& e) const {
+ return (*_direction)[e] ? _graph->v(e) : _graph->u(e);
+ }
+
+ typedef NodeNumTagIndicator<Graph> NodeNumTag;
+ int nodeNum() const { return _graph->nodeNum(); }
+
+ typedef EdgeNumTagIndicator<Graph> ArcNumTag;
+ int arcNum() const { return _graph->edgeNum(); }
+
+ typedef FindEdgeTagIndicator<Graph> FindArcTag;
+ Arc findArc(const Node& u, const Node& v,
+ const Arc& prev = INVALID) const {
+ Arc arc = _graph->findEdge(u, v, prev);
+ while (arc != INVALID && source(arc) != u) {
+ arc = _graph->findEdge(u, v, arc);
+ }
+ return arc;
+ }
+
+ Node addNode() {
+ return Node(_graph->addNode());
+ }
+
+ Arc addArc(const Node& u, const Node& v) {
+ Arc arc = _graph->addEdge(u, v);
+ _direction->set(arc, _graph->u(arc) == u);
+ return arc;
+ }
+
+ void erase(const Node& i) { _graph->erase(i); }
+ void erase(const Arc& i) { _graph->erase(i); }
+
+ void clear() { _graph->clear(); }
+
+ int id(const Node& v) const { return _graph->id(v); }
+ int id(const Arc& e) const { return _graph->id(e); }
+
+ Node nodeFromId(int idx) const { return _graph->nodeFromId(idx); }
+ Arc arcFromId(int idx) const { return _graph->edgeFromId(idx); }
+
+ int maxNodeId() const { return _graph->maxNodeId(); }
+ int maxArcId() const { return _graph->maxEdgeId(); }
+
+ typedef typename ItemSetTraits<GR, Node>::ItemNotifier NodeNotifier;
+ NodeNotifier& notifier(Node) const { return _graph->notifier(Node()); }
+
+ typedef typename ItemSetTraits<GR, Arc>::ItemNotifier ArcNotifier;
+ ArcNotifier& notifier(Arc) const { return _graph->notifier(Arc()); }
+
+ template <typename V>
+ class NodeMap : public GR::template NodeMap<V> {
+ typedef typename GR::template NodeMap<V> Parent;
+
+ public:
+
+ explicit NodeMap(const OrienterBase<GR, DM>& adapter)
+ : Parent(*adapter._graph) {}
+
+ NodeMap(const OrienterBase<GR, DM>& adapter, const V& value)
+ : Parent(*adapter._graph, value) {}
+
+ private:
+ NodeMap& operator=(const NodeMap& cmap) {
+ return operator=<NodeMap>(cmap);
+ }
+
+ template <typename CMap>
+ NodeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+
+ };
+
+ template <typename V>
+ class ArcMap : public GR::template EdgeMap<V> {
+ typedef typename Graph::template EdgeMap<V> Parent;
+
+ public:
+
+ explicit ArcMap(const OrienterBase<GR, DM>& adapter)
+ : Parent(*adapter._graph) { }
+
+ ArcMap(const OrienterBase<GR, DM>& adapter, const V& value)
+ : Parent(*adapter._graph, value) { }
+
+ private:
+ ArcMap& operator=(const ArcMap& cmap) {
+ return operator=<ArcMap>(cmap);
+ }
+
+ template <typename CMap>
+ ArcMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+
+
+ protected:
+ Graph* _graph;
+ DM* _direction;
+
+ void initialize(GR& graph, DM& direction) {
+ _graph = &graph;
+ _direction = &direction;
+ }
+
+ };
+
+ /// \ingroup graph_adaptors
+ ///
+ /// \brief Adaptor class for orienting the edges of a graph to get a digraph
+ ///
+ /// Orienter adaptor can be used for orienting the edges of a graph to
+ /// get a digraph. A \c bool edge map of the underlying graph must be
+ /// specified, which define the direction of the arcs in the adaptor.
+ /// The arcs can be easily reversed by the \c reverseArc() member function
+ /// of the adaptor.
+ /// This class conforms to the \ref concepts::Digraph "Digraph" concept.
+ ///
+ /// The adapted graph can also be modified through this adaptor
+ /// by adding or removing nodes or arcs, unless the \c GR template
+ /// parameter is set to be \c const.
+ ///
+ /// This class provides item counting in the same time as the adapted
+ /// graph structure.
+ ///
+ /// \tparam GR The type of the adapted graph.
+ /// It must conform to the \ref concepts::Graph "Graph" concept.
+ /// It can also be specified to be \c const.
+ /// \tparam DM The type of the direction map.
+ /// It must be a \c bool (or convertible) edge map of the
+ /// adapted graph. The default type is
+ /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<bool>".
+ ///
+ /// \note The \c Node type of this adaptor and the adapted graph are
+ /// convertible to each other, moreover the \c Arc type of the adaptor
+ /// and the \c Edge type of the adapted graph are also convertible to
+ /// each other.
+#ifdef DOXYGEN
+ template<typename GR,
+ typename DM>
+ class Orienter {
+#else
+ template<typename GR,
+ typename DM = typename GR::template EdgeMap<bool> >
+ class Orienter :
+ public DigraphAdaptorExtender<OrienterBase<GR, DM> > {
+#endif
+ typedef DigraphAdaptorExtender<OrienterBase<GR, DM> > Parent;
+ public:
+
+ /// The type of the adapted graph.
+ typedef GR Graph;
+ /// The type of the direction edge map.
+ typedef DM DirectionMap;
+
+ typedef typename Parent::Arc Arc;
+
+ protected:
+ Orienter() { }
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Constructor of the adaptor.
+ Orienter(GR& graph, DM& direction) {
+ Parent::initialize(graph, direction);
+ }
+
+ /// \brief Reverses the given arc
+ ///
+ /// This function reverses the given arc.
+ /// It is done by simply negate the assigned value of \c a
+ /// in the direction map.
+ void reverseArc(const Arc& a) {
+ Parent::reverseArc(a);
+ }
+ };
+
+ /// \brief Returns a read-only Orienter adaptor
+ ///
+ /// This function just returns a read-only \ref Orienter adaptor.
+ /// \ingroup graph_adaptors
+ /// \relates Orienter
+ template<typename GR, typename DM>
+ Orienter<const GR, DM>
+ orienter(const GR& graph, DM& direction) {
+ return Orienter<const GR, DM>(graph, direction);
+ }
+
+ template<typename GR, typename DM>
+ Orienter<const GR, const DM>
+ orienter(const GR& graph, const DM& direction) {
+ return Orienter<const GR, const DM>(graph, direction);
+ }
+
+ namespace _adaptor_bits {
+
+ template <typename DGR, typename CM, typename FM, typename TL>
+ class ResForwardFilter {
+ public:
+
+ typedef typename DGR::Arc Key;
+ typedef bool Value;
+
+ private:
+
+ const CM* _capacity;
+ const FM* _flow;
+ TL _tolerance;
+
+ public:
+
+ ResForwardFilter(const CM& capacity, const FM& flow,
+ const TL& tolerance = TL())
+ : _capacity(&capacity), _flow(&flow), _tolerance(tolerance) { }
+
+ bool operator[](const typename DGR::Arc& a) const {
+ return _tolerance.positive((*_capacity)[a] - (*_flow)[a]);
+ }
+ };
+
+ template<typename DGR,typename CM, typename FM, typename TL>
+ class ResBackwardFilter {
+ public:
+
+ typedef typename DGR::Arc Key;
+ typedef bool Value;
+
+ private:
+
+ const CM* _capacity;
+ const FM* _flow;
+ TL _tolerance;
+
+ public:
+
+ ResBackwardFilter(const CM& capacity, const FM& flow,
+ const TL& tolerance = TL())
+ : _capacity(&capacity), _flow(&flow), _tolerance(tolerance) { }
+
+ bool operator[](const typename DGR::Arc& a) const {
+ return _tolerance.positive((*_flow)[a]);
+ }
+ };
+
+ }
+
+ /// \ingroup graph_adaptors
+ ///
+ /// \brief Adaptor class for composing the residual digraph for directed
+ /// flow and circulation problems.
+ ///
+ /// ResidualDigraph can be used for composing the \e residual digraph
+ /// for directed flow and circulation problems. Let \f$ G=(V, A) \f$
+ /// be a directed graph and let \f$ F \f$ be a number type.
+ /// Let \f$ flow, cap: A\to F \f$ be functions on the arcs.
+ /// This adaptor implements a digraph structure with node set \f$ V \f$
+ /// and arc set \f$ A_{forward}\cup A_{backward} \f$,
+ /// where \f$ A_{forward}=\{uv : uv\in A, flow(uv)<cap(uv)\} \f$ and
+ /// \f$ A_{backward}=\{vu : uv\in A, flow(uv)>0\} \f$, i.e. the so
+ /// called residual digraph.
+ /// When the union \f$ A_{forward}\cup A_{backward} \f$ is taken,
+ /// multiplicities are counted, i.e. the adaptor has exactly
+ /// \f$ |A_{forward}| + |A_{backward}|\f$ arcs (it may have parallel
+ /// arcs).
+ /// This class conforms to the \ref concepts::Digraph "Digraph" concept.
+ ///
+ /// This class provides only linear time counting for nodes and arcs.
+ ///
+ /// \tparam DGR The type of the adapted digraph.
+ /// It must conform to the \ref concepts::Digraph "Digraph" concept.
+ /// It is implicitly \c const.
+ /// \tparam CM The type of the capacity map.
+ /// It must be an arc map of some numerical type, which defines
+ /// the capacities in the flow problem. It is implicitly \c const.
+ /// The default type is
+ /// \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
+ /// \tparam FM The type of the flow map.
+ /// It must be an arc map of some numerical type, which defines
+ /// the flow values in the flow problem. The default type is \c CM.
+ /// \tparam TL The tolerance type for handling inexact computation.
+ /// The default tolerance type depends on the value type of the
+ /// capacity map.
+ ///
+ /// \note This adaptor is implemented using Undirector and FilterArcs
+ /// adaptors.
+ ///
+ /// \note The \c Node type of this adaptor and the adapted digraph are
+ /// convertible to each other, moreover the \c Arc type of the adaptor
+ /// is convertible to the \c Arc type of the adapted digraph.
+#ifdef DOXYGEN
+ template<typename DGR, typename CM, typename FM, typename TL>
+ class ResidualDigraph
+#else
+ template<typename DGR,
+ typename CM = typename DGR::template ArcMap<int>,
+ typename FM = CM,
+ typename TL = Tolerance<typename CM::Value> >
+ class ResidualDigraph
+ : public SubDigraph<
+ Undirector<const DGR>,
+ ConstMap<typename DGR::Node, Const<bool, true> >,
+ typename Undirector<const DGR>::template CombinedArcMap<
+ _adaptor_bits::ResForwardFilter<const DGR, CM, FM, TL>,
+ _adaptor_bits::ResBackwardFilter<const DGR, CM, FM, TL> > >
+#endif
+ {
+ public:
+
+ /// The type of the underlying digraph.
+ typedef DGR Digraph;
+ /// The type of the capacity map.
+ typedef CM CapacityMap;
+ /// The type of the flow map.
+ typedef FM FlowMap;
+ /// The tolerance type.
+ typedef TL Tolerance;
+
+ typedef typename CapacityMap::Value Value;
+ typedef ResidualDigraph Adaptor;
+
+ protected:
+
+ typedef Undirector<const Digraph> Undirected;
+
+ typedef ConstMap<typename DGR::Node, Const<bool, true> > NodeFilter;
+
+ typedef _adaptor_bits::ResForwardFilter<const DGR, CM,
+ FM, TL> ForwardFilter;
+
+ typedef _adaptor_bits::ResBackwardFilter<const DGR, CM,
+ FM, TL> BackwardFilter;
+
+ typedef typename Undirected::
+ template CombinedArcMap<ForwardFilter, BackwardFilter> ArcFilter;
+
+ typedef SubDigraph<Undirected, NodeFilter, ArcFilter> Parent;
+
+ const CapacityMap* _capacity;
+ FlowMap* _flow;
+
+ Undirected _graph;
+ NodeFilter _node_filter;
+ ForwardFilter _forward_filter;
+ BackwardFilter _backward_filter;
+ ArcFilter _arc_filter;
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Constructor of the residual digraph adaptor. The parameters are the
+ /// digraph, the capacity map, the flow map, and a tolerance object.
+ ResidualDigraph(const DGR& digraph, const CM& capacity,
+ FM& flow, const TL& tolerance = Tolerance())
+ : Parent(), _capacity(&capacity), _flow(&flow),
+ _graph(digraph), _node_filter(),
+ _forward_filter(capacity, flow, tolerance),
+ _backward_filter(capacity, flow, tolerance),
+ _arc_filter(_forward_filter, _backward_filter)
+ {
+ Parent::initialize(_graph, _node_filter, _arc_filter);
+ }
+
+ typedef typename Parent::Arc Arc;
+
+ /// \brief Returns the residual capacity of the given arc.
+ ///
+ /// Returns the residual capacity of the given arc.
+ Value residualCapacity(const Arc& a) const {
+ if (Undirected::direction(a)) {
+ return (*_capacity)[a] - (*_flow)[a];
+ } else {
+ return (*_flow)[a];
+ }
+ }
+
+ /// \brief Augments on the given arc in the residual digraph.
+ ///
+ /// Augments on the given arc in the residual digraph. It increases
+ /// or decreases the flow value on the original arc according to the
+ /// direction of the residual arc.
+ void augment(const Arc& a, const Value& v) const {
+ if (Undirected::direction(a)) {
+ _flow->set(a, (*_flow)[a] + v);
+ } else {
+ _flow->set(a, (*_flow)[a] - v);
+ }
+ }
+
+ /// \brief Returns \c true if the given residual arc is a forward arc.
+ ///
+ /// Returns \c true if the given residual arc has the same orientation
+ /// as the original arc, i.e. it is a so called forward arc.
+ static bool forward(const Arc& a) {
+ return Undirected::direction(a);
+ }
+
+ /// \brief Returns \c true if the given residual arc is a backward arc.
+ ///
+ /// Returns \c true if the given residual arc has the opposite orientation
+ /// than the original arc, i.e. it is a so called backward arc.
+ static bool backward(const Arc& a) {
+ return !Undirected::direction(a);
+ }
+
+ /// \brief Returns the forward oriented residual arc.
+ ///
+ /// Returns the forward oriented residual arc related to the given
+ /// arc of the underlying digraph.
+ static Arc forward(const typename Digraph::Arc& a) {
+ return Undirected::direct(a, true);
+ }
+
+ /// \brief Returns the backward oriented residual arc.
+ ///
+ /// Returns the backward oriented residual arc related to the given
+ /// arc of the underlying digraph.
+ static Arc backward(const typename Digraph::Arc& a) {
+ return Undirected::direct(a, false);
+ }
+
+ /// \brief Residual capacity map.
+ ///
+ /// This map adaptor class can be used for obtaining the residual
+ /// capacities as an arc map of the residual digraph.
+ /// Its value type is inherited from the capacity map.
+ class ResidualCapacity {
+ protected:
+ const Adaptor* _adaptor;
+ public:
+ /// The key type of the map
+ typedef Arc Key;
+ /// The value type of the map
+ typedef typename CapacityMap::Value Value;
+
+ /// Constructor
+ ResidualCapacity(const ResidualDigraph<DGR, CM, FM, TL>& adaptor)
+ : _adaptor(&adaptor) {}
+
+ /// Returns the value associated with the given residual arc
+ Value operator[](const Arc& a) const {
+ return _adaptor->residualCapacity(a);
+ }
+
+ };
+
+ /// \brief Returns a residual capacity map
+ ///
+ /// This function just returns a residual capacity map.
+ ResidualCapacity residualCapacity() const {
+ return ResidualCapacity(*this);
+ }
+
+ };
+
+ /// \brief Returns a (read-only) Residual adaptor
+ ///
+ /// This function just returns a (read-only) \ref ResidualDigraph adaptor.
+ /// \ingroup graph_adaptors
+ /// \relates ResidualDigraph
+ template<typename DGR, typename CM, typename FM>
+ ResidualDigraph<DGR, CM, FM>
+ residualDigraph(const DGR& digraph, const CM& capacity_map, FM& flow_map) {
+ return ResidualDigraph<DGR, CM, FM> (digraph, capacity_map, flow_map);
+ }
+
+
+ template <typename DGR>
+ class SplitNodesBase {
+ typedef DigraphAdaptorBase<const DGR> Parent;
+
+ public:
+
+ typedef DGR Digraph;
+ typedef SplitNodesBase Adaptor;
+
+ typedef typename DGR::Node DigraphNode;
+ typedef typename DGR::Arc DigraphArc;
+
+ class Node;
+ class Arc;
+
+ private:
+
+ template <typename T> class NodeMapBase;
+ template <typename T> class ArcMapBase;
+
+ public:
+
+ class Node : public DigraphNode {
+ friend class SplitNodesBase;
+ template <typename T> friend class NodeMapBase;
+ private:
+
+ bool _in;
+ Node(DigraphNode node, bool in)
+ : DigraphNode(node), _in(in) {}
+
+ public:
+
+ Node() {}
+ Node(Invalid) : DigraphNode(INVALID), _in(true) {}
+
+ bool operator==(const Node& node) const {
+ return DigraphNode::operator==(node) && _in == node._in;
+ }
+
+ bool operator!=(const Node& node) const {
+ return !(*this == node);
+ }
+
+ bool operator<(const Node& node) const {
+ return DigraphNode::operator<(node) ||
+ (DigraphNode::operator==(node) && _in < node._in);
+ }
+ };
+
+ class Arc {
+ friend class SplitNodesBase;
+ template <typename T> friend class ArcMapBase;
+ private:
+ typedef BiVariant<DigraphArc, DigraphNode> ArcImpl;
+
+ explicit Arc(const DigraphArc& arc) : _item(arc) {}
+ explicit Arc(const DigraphNode& node) : _item(node) {}
+
+ ArcImpl _item;
+
+ public:
+ Arc() {}
+ Arc(Invalid) : _item(DigraphArc(INVALID)) {}
+
+ bool operator==(const Arc& arc) const {
+ if (_item.firstState()) {
+ if (arc._item.firstState()) {
+ return _item.first() == arc._item.first();
+ }
+ } else {
+ if (arc._item.secondState()) {
+ return _item.second() == arc._item.second();
+ }
+ }
+ return false;
+ }
+
+ bool operator!=(const Arc& arc) const {
+ return !(*this == arc);
+ }
+
+ bool operator<(const Arc& arc) const {
+ if (_item.firstState()) {
+ if (arc._item.firstState()) {
+ return _item.first() < arc._item.first();
+ }
+ return false;
+ } else {
+ if (arc._item.secondState()) {
+ return _item.second() < arc._item.second();
+ }
+ return true;
+ }
+ }
+
+ operator DigraphArc() const { return _item.first(); }
+ operator DigraphNode() const { return _item.second(); }
+
+ };
+
+ void first(Node& n) const {
+ _digraph->first(n);
+ n._in = true;
+ }
+
+ void next(Node& n) const {
+ if (n._in) {
+ n._in = false;
+ } else {
+ n._in = true;
+ _digraph->next(n);
+ }
+ }
+
+ void first(Arc& e) const {
+ e._item.setSecond();
+ _digraph->first(e._item.second());
+ if (e._item.second() == INVALID) {
+ e._item.setFirst();
+ _digraph->first(e._item.first());
+ }
+ }
+
+ void next(Arc& e) const {
+ if (e._item.secondState()) {
+ _digraph->next(e._item.second());
+ if (e._item.second() == INVALID) {
+ e._item.setFirst();
+ _digraph->first(e._item.first());
+ }
+ } else {
+ _digraph->next(e._item.first());
+ }
+ }
+
+ void firstOut(Arc& e, const Node& n) const {
+ if (n._in) {
+ e._item.setSecond(n);
+ } else {
+ e._item.setFirst();
+ _digraph->firstOut(e._item.first(), n);
+ }
+ }
+
+ void nextOut(Arc& e) const {
+ if (!e._item.firstState()) {
+ e._item.setFirst(INVALID);
+ } else {
+ _digraph->nextOut(e._item.first());
+ }
+ }
+
+ void firstIn(Arc& e, const Node& n) const {
+ if (!n._in) {
+ e._item.setSecond(n);
+ } else {
+ e._item.setFirst();
+ _digraph->firstIn(e._item.first(), n);
+ }
+ }
+
+ void nextIn(Arc& e) const {
+ if (!e._item.firstState()) {
+ e._item.setFirst(INVALID);
+ } else {
+ _digraph->nextIn(e._item.first());
+ }
+ }
+
+ Node source(const Arc& e) const {
+ if (e._item.firstState()) {
+ return Node(_digraph->source(e._item.first()), false);
+ } else {
+ return Node(e._item.second(), true);
+ }
+ }
+
+ Node target(const Arc& e) const {
+ if (e._item.firstState()) {
+ return Node(_digraph->target(e._item.first()), true);
+ } else {
+ return Node(e._item.second(), false);
+ }
+ }
+
+ int id(const Node& n) const {
+ return (_digraph->id(n) << 1) | (n._in ? 0 : 1);
+ }
+ Node nodeFromId(int ix) const {
+ return Node(_digraph->nodeFromId(ix >> 1), (ix & 1) == 0);
+ }
+ int maxNodeId() const {
+ return 2 * _digraph->maxNodeId() + 1;
+ }
+
+ int id(const Arc& e) const {
+ if (e._item.firstState()) {
+ return _digraph->id(e._item.first()) << 1;
+ } else {
+ return (_digraph->id(e._item.second()) << 1) | 1;
+ }
+ }
+ Arc arcFromId(int ix) const {
+ if ((ix & 1) == 0) {
+ return Arc(_digraph->arcFromId(ix >> 1));
+ } else {
+ return Arc(_digraph->nodeFromId(ix >> 1));
+ }
+ }
+ int maxArcId() const {
+ return std::max(_digraph->maxNodeId() << 1,
+ (_digraph->maxArcId() << 1) | 1);
+ }
+
+ static bool inNode(const Node& n) {
+ return n._in;
+ }
+
+ static bool outNode(const Node& n) {
+ return !n._in;
+ }
+
+ static bool origArc(const Arc& e) {
+ return e._item.firstState();
+ }
+
+ static bool bindArc(const Arc& e) {
+ return e._item.secondState();
+ }
+
+ static Node inNode(const DigraphNode& n) {
+ return Node(n, true);
+ }
+
+ static Node outNode(const DigraphNode& n) {
+ return Node(n, false);
+ }
+
+ static Arc arc(const DigraphNode& n) {
+ return Arc(n);
+ }
+
+ static Arc arc(const DigraphArc& e) {
+ return Arc(e);
+ }
+
+ typedef True NodeNumTag;
+ int nodeNum() const {
+ return 2 * countNodes(*_digraph);
+ }
+
+ typedef True ArcNumTag;
+ int arcNum() const {
+ return countArcs(*_digraph) + countNodes(*_digraph);
+ }
+
+ typedef True FindArcTag;
+ Arc findArc(const Node& u, const Node& v,
+ const Arc& prev = INVALID) const {
+ if (inNode(u) && outNode(v)) {
+ if (static_cast<const DigraphNode&>(u) ==
+ static_cast<const DigraphNode&>(v) && prev == INVALID) {
+ return Arc(u);
+ }
+ }
+ else if (outNode(u) && inNode(v)) {
+ return Arc(::lemon::findArc(*_digraph, u, v, prev));
+ }
+ return INVALID;
+ }
+
+ private:
+
+ template <typename V>
+ class NodeMapBase
+ : public MapTraits<typename Parent::template NodeMap<V> > {
+ typedef typename Parent::template NodeMap<V> NodeImpl;
+ public:
+ typedef Node Key;
+ typedef V Value;
+ typedef typename MapTraits<NodeImpl>::ReferenceMapTag ReferenceMapTag;
+ typedef typename MapTraits<NodeImpl>::ReturnValue ReturnValue;
+ typedef typename MapTraits<NodeImpl>::ConstReturnValue ConstReturnValue;
+ typedef typename MapTraits<NodeImpl>::ReturnValue Reference;
+ typedef typename MapTraits<NodeImpl>::ConstReturnValue ConstReference;
+
+ NodeMapBase(const SplitNodesBase<DGR>& adaptor)
+ : _in_map(*adaptor._digraph), _out_map(*adaptor._digraph) {}
+ NodeMapBase(const SplitNodesBase<DGR>& adaptor, const V& value)
+ : _in_map(*adaptor._digraph, value),
+ _out_map(*adaptor._digraph, value) {}
+
+ void set(const Node& key, const V& val) {
+ if (SplitNodesBase<DGR>::inNode(key)) { _in_map.set(key, val); }
+ else {_out_map.set(key, val); }
+ }
+
+ ReturnValue operator[](const Node& key) {
+ if (SplitNodesBase<DGR>::inNode(key)) { return _in_map[key]; }
+ else { return _out_map[key]; }
+ }
+
+ ConstReturnValue operator[](const Node& key) const {
+ if (Adaptor::inNode(key)) { return _in_map[key]; }
+ else { return _out_map[key]; }
+ }
+
+ private:
+ NodeImpl _in_map, _out_map;
+ };
+
+ template <typename V>
+ class ArcMapBase
+ : public MapTraits<typename Parent::template ArcMap<V> > {
+ typedef typename Parent::template ArcMap<V> ArcImpl;
+ typedef typename Parent::template NodeMap<V> NodeImpl;
+ public:
+ typedef Arc Key;
+ typedef V Value;
+ typedef typename MapTraits<ArcImpl>::ReferenceMapTag ReferenceMapTag;
+ typedef typename MapTraits<ArcImpl>::ReturnValue ReturnValue;
+ typedef typename MapTraits<ArcImpl>::ConstReturnValue ConstReturnValue;
+ typedef typename MapTraits<ArcImpl>::ReturnValue Reference;
+ typedef typename MapTraits<ArcImpl>::ConstReturnValue ConstReference;
+
+ ArcMapBase(const SplitNodesBase<DGR>& adaptor)
+ : _arc_map(*adaptor._digraph), _node_map(*adaptor._digraph) {}
+ ArcMapBase(const SplitNodesBase<DGR>& adaptor, const V& value)
+ : _arc_map(*adaptor._digraph, value),
+ _node_map(*adaptor._digraph, value) {}
+
+ void set(const Arc& key, const V& val) {
+ if (SplitNodesBase<DGR>::origArc(key)) {
+ _arc_map.set(static_cast<const DigraphArc&>(key), val);
+ } else {
+ _node_map.set(static_cast<const DigraphNode&>(key), val);
+ }
+ }
+
+ ReturnValue operator[](const Arc& key) {
+ if (SplitNodesBase<DGR>::origArc(key)) {
+ return _arc_map[static_cast<const DigraphArc&>(key)];
+ } else {
+ return _node_map[static_cast<const DigraphNode&>(key)];
+ }
+ }
+
+ ConstReturnValue operator[](const Arc& key) const {
+ if (SplitNodesBase<DGR>::origArc(key)) {
+ return _arc_map[static_cast<const DigraphArc&>(key)];
+ } else {
+ return _node_map[static_cast<const DigraphNode&>(key)];
+ }
+ }
+
+ private:
+ ArcImpl _arc_map;
+ NodeImpl _node_map;
+ };
+
+ public:
+
+ template <typename V>
+ class NodeMap
+ : public SubMapExtender<SplitNodesBase<DGR>, NodeMapBase<V> > {
+ typedef SubMapExtender<SplitNodesBase<DGR>, NodeMapBase<V> > Parent;
+
+ public:
+ typedef V Value;
+
+ NodeMap(const SplitNodesBase<DGR>& adaptor)
+ : Parent(adaptor) {}
+
+ NodeMap(const SplitNodesBase<DGR>& adaptor, const V& value)
+ : Parent(adaptor, value) {}
+
+ private:
+ NodeMap& operator=(const NodeMap& cmap) {
+ return operator=<NodeMap>(cmap);
+ }
+
+ template <typename CMap>
+ NodeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ template <typename V>
+ class ArcMap
+ : public SubMapExtender<SplitNodesBase<DGR>, ArcMapBase<V> > {
+ typedef SubMapExtender<SplitNodesBase<DGR>, ArcMapBase<V> > Parent;
+
+ public:
+ typedef V Value;
+
+ ArcMap(const SplitNodesBase<DGR>& adaptor)
+ : Parent(adaptor) {}
+
+ ArcMap(const SplitNodesBase<DGR>& adaptor, const V& value)
+ : Parent(adaptor, value) {}
+
+ private:
+ ArcMap& operator=(const ArcMap& cmap) {
+ return operator=<ArcMap>(cmap);
+ }
+
+ template <typename CMap>
+ ArcMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ protected:
+
+ SplitNodesBase() : _digraph(0) {}
+
+ DGR* _digraph;
+
+ void initialize(Digraph& digraph) {
+ _digraph = &digraph;
+ }
+
+ };
+
+ /// \ingroup graph_adaptors
+ ///
+ /// \brief Adaptor class for splitting the nodes of a digraph.
+ ///
+ /// SplitNodes adaptor can be used for splitting each node into an
+ /// \e in-node and an \e out-node in a digraph. Formaly, the adaptor
+ /// replaces each node \f$ u \f$ in the digraph with two nodes,
+ /// namely node \f$ u_{in} \f$ and node \f$ u_{out} \f$.
+ /// If there is a \f$ (v, u) \f$ arc in the original digraph, then the
+ /// new target of the arc will be \f$ u_{in} \f$ and similarly the
+ /// source of each original \f$ (u, v) \f$ arc will be \f$ u_{out} \f$.
+ /// The adaptor adds an additional \e bind \e arc from \f$ u_{in} \f$
+ /// to \f$ u_{out} \f$ for each node \f$ u \f$ of the original digraph.
+ ///
+ /// The aim of this class is running an algorithm with respect to node
+ /// costs or capacities if the algorithm considers only arc costs or
+ /// capacities directly.
+ /// In this case you can use \c SplitNodes adaptor, and set the node
+ /// costs/capacities of the original digraph to the \e bind \e arcs
+ /// in the adaptor.
+ ///
+ /// This class provides item counting in the same time as the adapted
+ /// digraph structure.
+ ///
+ /// \tparam DGR The type of the adapted digraph.
+ /// It must conform to the \ref concepts::Digraph "Digraph" concept.
+ /// It is implicitly \c const.
+ ///
+ /// \note The \c Node type of this adaptor is converible to the \c Node
+ /// type of the adapted digraph.
+ template <typename DGR>
+#ifdef DOXYGEN
+ class SplitNodes {
+#else
+ class SplitNodes
+ : public DigraphAdaptorExtender<SplitNodesBase<const DGR> > {
+#endif
+ typedef DigraphAdaptorExtender<SplitNodesBase<const DGR> > Parent;
+
+ public:
+ typedef DGR Digraph;
+
+ typedef typename DGR::Node DigraphNode;
+ typedef typename DGR::Arc DigraphArc;
+
+ typedef typename Parent::Node Node;
+ typedef typename Parent::Arc Arc;
+
+ /// \brief Constructor
+ ///
+ /// Constructor of the adaptor.
+ SplitNodes(const DGR& g) {
+ Parent::initialize(g);
+ }
+
+ /// \brief Returns \c true if the given node is an in-node.
+ ///
+ /// Returns \c true if the given node is an in-node.
+ static bool inNode(const Node& n) {
+ return Parent::inNode(n);
+ }
+
+ /// \brief Returns \c true if the given node is an out-node.
+ ///
+ /// Returns \c true if the given node is an out-node.
+ static bool outNode(const Node& n) {
+ return Parent::outNode(n);
+ }
+
+ /// \brief Returns \c true if the given arc is an original arc.
+ ///
+ /// Returns \c true if the given arc is one of the arcs in the
+ /// original digraph.
+ static bool origArc(const Arc& a) {
+ return Parent::origArc(a);
+ }
+
+ /// \brief Returns \c true if the given arc is a bind arc.
+ ///
+ /// Returns \c true if the given arc is a bind arc, i.e. it connects
+ /// an in-node and an out-node.
+ static bool bindArc(const Arc& a) {
+ return Parent::bindArc(a);
+ }
+
+ /// \brief Returns the in-node created from the given original node.
+ ///
+ /// Returns the in-node created from the given original node.
+ static Node inNode(const DigraphNode& n) {
+ return Parent::inNode(n);
+ }
+
+ /// \brief Returns the out-node created from the given original node.
+ ///
+ /// Returns the out-node created from the given original node.
+ static Node outNode(const DigraphNode& n) {
+ return Parent::outNode(n);
+ }
+
+ /// \brief Returns the bind arc that corresponds to the given
+ /// original node.
+ ///
+ /// Returns the bind arc in the adaptor that corresponds to the given
+ /// original node, i.e. the arc connecting the in-node and out-node
+ /// of \c n.
+ static Arc arc(const DigraphNode& n) {
+ return Parent::arc(n);
+ }
+
+ /// \brief Returns the arc that corresponds to the given original arc.
+ ///
+ /// Returns the arc in the adaptor that corresponds to the given
+ /// original arc.
+ static Arc arc(const DigraphArc& a) {
+ return Parent::arc(a);
+ }
+
+ /// \brief Node map combined from two original node maps
+ ///
+ /// This map adaptor class adapts two node maps of the original digraph
+ /// to get a node map of the split digraph.
+ /// Its value type is inherited from the first node map type (\c IN).
+ /// \tparam IN The type of the node map for the in-nodes.
+ /// \tparam OUT The type of the node map for the out-nodes.
+ template <typename IN, typename OUT>
+ class CombinedNodeMap {
+ public:
+
+ /// The key type of the map
+ typedef Node Key;
+ /// The value type of the map
+ typedef typename IN::Value Value;
+
+ typedef typename MapTraits<IN>::ReferenceMapTag ReferenceMapTag;
+ typedef typename MapTraits<IN>::ReturnValue ReturnValue;
+ typedef typename MapTraits<IN>::ConstReturnValue ConstReturnValue;
+ typedef typename MapTraits<IN>::ReturnValue Reference;
+ typedef typename MapTraits<IN>::ConstReturnValue ConstReference;
+
+ /// Constructor
+ CombinedNodeMap(IN& in_map, OUT& out_map)
+ : _in_map(in_map), _out_map(out_map) {}
+
+ /// Returns the value associated with the given key.
+ Value operator[](const Key& key) const {
+ if (SplitNodesBase<const DGR>::inNode(key)) {
+ return _in_map[key];
+ } else {
+ return _out_map[key];
+ }
+ }
+
+ /// Returns a reference to the value associated with the given key.
+ Value& operator[](const Key& key) {
+ if (SplitNodesBase<const DGR>::inNode(key)) {
+ return _in_map[key];
+ } else {
+ return _out_map[key];
+ }
+ }
+
+ /// Sets the value associated with the given key.
+ void set(const Key& key, const Value& value) {
+ if (SplitNodesBase<const DGR>::inNode(key)) {
+ _in_map.set(key, value);
+ } else {
+ _out_map.set(key, value);
+ }
+ }
+
+ private:
+
+ IN& _in_map;
+ OUT& _out_map;
+
+ };
+
+
+ /// \brief Returns a combined node map
+ ///
+ /// This function just returns a combined node map.
+ template <typename IN, typename OUT>
+ static CombinedNodeMap<IN, OUT>
+ combinedNodeMap(IN& in_map, OUT& out_map) {
+ return CombinedNodeMap<IN, OUT>(in_map, out_map);
+ }
+
+ template <typename IN, typename OUT>
+ static CombinedNodeMap<const IN, OUT>
+ combinedNodeMap(const IN& in_map, OUT& out_map) {
+ return CombinedNodeMap<const IN, OUT>(in_map, out_map);
+ }
+
+ template <typename IN, typename OUT>
+ static CombinedNodeMap<IN, const OUT>
+ combinedNodeMap(IN& in_map, const OUT& out_map) {
+ return CombinedNodeMap<IN, const OUT>(in_map, out_map);
+ }
+
+ template <typename IN, typename OUT>
+ static CombinedNodeMap<const IN, const OUT>
+ combinedNodeMap(const IN& in_map, const OUT& out_map) {
+ return CombinedNodeMap<const IN, const OUT>(in_map, out_map);
+ }
+
+ /// \brief Arc map combined from an arc map and a node map of the
+ /// original digraph.
+ ///
+ /// This map adaptor class adapts an arc map and a node map of the
+ /// original digraph to get an arc map of the split digraph.
+ /// Its value type is inherited from the original arc map type (\c AM).
+ /// \tparam AM The type of the arc map.
+ /// \tparam NM the type of the node map.
+ template <typename AM, typename NM>
+ class CombinedArcMap {
+ public:
+
+ /// The key type of the map
+ typedef Arc Key;
+ /// The value type of the map
+ typedef typename AM::Value Value;
+
+ typedef typename MapTraits<AM>::ReferenceMapTag ReferenceMapTag;
+ typedef typename MapTraits<AM>::ReturnValue ReturnValue;
+ typedef typename MapTraits<AM>::ConstReturnValue ConstReturnValue;
+ typedef typename MapTraits<AM>::ReturnValue Reference;
+ typedef typename MapTraits<AM>::ConstReturnValue ConstReference;
+
+ /// Constructor
+ CombinedArcMap(AM& arc_map, NM& node_map)
+ : _arc_map(arc_map), _node_map(node_map) {}
+
+ /// Returns the value associated with the given key.
+ Value operator[](const Key& arc) const {
+ if (SplitNodesBase<const DGR>::origArc(arc)) {
+ return _arc_map[arc];
+ } else {
+ return _node_map[arc];
+ }
+ }
+
+ /// Returns a reference to the value associated with the given key.
+ Value& operator[](const Key& arc) {
+ if (SplitNodesBase<const DGR>::origArc(arc)) {
+ return _arc_map[arc];
+ } else {
+ return _node_map[arc];
+ }
+ }
+
+ /// Sets the value associated with the given key.
+ void set(const Arc& arc, const Value& val) {
+ if (SplitNodesBase<const DGR>::origArc(arc)) {
+ _arc_map.set(arc, val);
+ } else {
+ _node_map.set(arc, val);
+ }
+ }
+
+ private:
+
+ AM& _arc_map;
+ NM& _node_map;
+
+ };
+
+ /// \brief Returns a combined arc map
+ ///
+ /// This function just returns a combined arc map.
+ template <typename ArcMap, typename NodeMap>
+ static CombinedArcMap<ArcMap, NodeMap>
+ combinedArcMap(ArcMap& arc_map, NodeMap& node_map) {
+ return CombinedArcMap<ArcMap, NodeMap>(arc_map, node_map);
+ }
+
+ template <typename ArcMap, typename NodeMap>
+ static CombinedArcMap<const ArcMap, NodeMap>
+ combinedArcMap(const ArcMap& arc_map, NodeMap& node_map) {
+ return CombinedArcMap<const ArcMap, NodeMap>(arc_map, node_map);
+ }
+
+ template <typename ArcMap, typename NodeMap>
+ static CombinedArcMap<ArcMap, const NodeMap>
+ combinedArcMap(ArcMap& arc_map, const NodeMap& node_map) {
+ return CombinedArcMap<ArcMap, const NodeMap>(arc_map, node_map);
+ }
+
+ template <typename ArcMap, typename NodeMap>
+ static CombinedArcMap<const ArcMap, const NodeMap>
+ combinedArcMap(const ArcMap& arc_map, const NodeMap& node_map) {
+ return CombinedArcMap<const ArcMap, const NodeMap>(arc_map, node_map);
+ }
+
+ };
+
+ /// \brief Returns a (read-only) SplitNodes adaptor
+ ///
+ /// This function just returns a (read-only) \ref SplitNodes adaptor.
+ /// \ingroup graph_adaptors
+ /// \relates SplitNodes
+ template<typename DGR>
+ SplitNodes<DGR>
+ splitNodes(const DGR& digraph) {
+ return SplitNodes<DGR>(digraph);
+ }
+
+#undef LEMON_SCOPE_FIX
+
+} //namespace lemon
+
+#endif //LEMON_ADAPTORS_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/arg_parser.cc b/extern/quadriflow/3rd/lemon-1.3.1/lemon/arg_parser.cc
new file mode 100644
index 00000000000..35a73d9f308
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/arg_parser.cc
@@ -0,0 +1,474 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2010
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/arg_parser.h>
+
+namespace lemon {
+
+ void ArgParser::_terminate(ArgParserException::Reason reason) const
+ {
+ if(_exit_on_problems)
+ exit(1);
+ else throw(ArgParserException(reason));
+ }
+
+
+ void ArgParser::_showHelp(void *p)
+ {
+ (static_cast<ArgParser*>(p))->showHelp();
+ (static_cast<ArgParser*>(p))->_terminate(ArgParserException::HELP);
+ }
+
+ ArgParser::ArgParser(int argc, const char * const *argv)
+ :_argc(argc), _argv(argv), _command_name(argv[0]),
+ _exit_on_problems(true) {
+ funcOption("-help","Print a short help message",_showHelp,this);
+ synonym("help","-help");
+ synonym("h","-help");
+ }
+
+ ArgParser::~ArgParser()
+ {
+ for(Opts::iterator i=_opts.begin();i!=_opts.end();++i)
+ if(i->second.self_delete)
+ switch(i->second.type) {
+ case BOOL:
+ delete i->second.bool_p;
+ break;
+ case STRING:
+ delete i->second.string_p;
+ break;
+ case DOUBLE:
+ delete i->second.double_p;
+ break;
+ case INTEGER:
+ delete i->second.int_p;
+ break;
+ case UNKNOWN:
+ break;
+ case FUNC:
+ break;
+ }
+ }
+
+
+ ArgParser &ArgParser::intOption(const std::string &name,
+ const std::string &help,
+ int value, bool obl)
+ {
+ ParData p;
+ p.int_p=new int(value);
+ p.self_delete=true;
+ p.help=help;
+ p.type=INTEGER;
+ p.mandatory=obl;
+ _opts[name]=p;
+ return *this;
+ }
+
+ ArgParser &ArgParser::doubleOption(const std::string &name,
+ const std::string &help,
+ double value, bool obl)
+ {
+ ParData p;
+ p.double_p=new double(value);
+ p.self_delete=true;
+ p.help=help;
+ p.type=DOUBLE;
+ p.mandatory=obl;
+ _opts[name]=p;
+ return *this;
+ }
+
+ ArgParser &ArgParser::boolOption(const std::string &name,
+ const std::string &help,
+ bool value, bool obl)
+ {
+ ParData p;
+ p.bool_p=new bool(value);
+ p.self_delete=true;
+ p.help=help;
+ p.type=BOOL;
+ p.mandatory=obl;
+ _opts[name]=p;
+ return *this;
+ }
+
+ ArgParser &ArgParser::stringOption(const std::string &name,
+ const std::string &help,
+ std::string value, bool obl)
+ {
+ ParData p;
+ p.string_p=new std::string(value);
+ p.self_delete=true;
+ p.help=help;
+ p.type=STRING;
+ p.mandatory=obl;
+ _opts[name]=p;
+ return *this;
+ }
+
+ ArgParser &ArgParser::refOption(const std::string &name,
+ const std::string &help,
+ int &ref, bool obl)
+ {
+ ParData p;
+ p.int_p=&ref;
+ p.self_delete=false;
+ p.help=help;
+ p.type=INTEGER;
+ p.mandatory=obl;
+ _opts[name]=p;
+ return *this;
+ }
+
+ ArgParser &ArgParser::refOption(const std::string &name,
+ const std::string &help,
+ double &ref, bool obl)
+ {
+ ParData p;
+ p.double_p=&ref;
+ p.self_delete=false;
+ p.help=help;
+ p.type=DOUBLE;
+ p.mandatory=obl;
+ _opts[name]=p;
+ return *this;
+ }
+
+ ArgParser &ArgParser::refOption(const std::string &name,
+ const std::string &help,
+ bool &ref, bool obl)
+ {
+ ParData p;
+ p.bool_p=&ref;
+ p.self_delete=false;
+ p.help=help;
+ p.type=BOOL;
+ p.mandatory=obl;
+ _opts[name]=p;
+
+ ref = false;
+
+ return *this;
+ }
+
+ ArgParser &ArgParser::refOption(const std::string &name,
+ const std::string &help,
+ std::string &ref, bool obl)
+ {
+ ParData p;
+ p.string_p=&ref;
+ p.self_delete=false;
+ p.help=help;
+ p.type=STRING;
+ p.mandatory=obl;
+ _opts[name]=p;
+ return *this;
+ }
+
+ ArgParser &ArgParser::funcOption(const std::string &name,
+ const std::string &help,
+ void (*func)(void *),void *data)
+ {
+ ParData p;
+ p.func_p.p=func;
+ p.func_p.data=data;
+ p.self_delete=false;
+ p.help=help;
+ p.type=FUNC;
+ p.mandatory=false;
+ _opts[name]=p;
+ return *this;
+ }
+
+ ArgParser &ArgParser::optionGroup(const std::string &group,
+ const std::string &opt)
+ {
+ Opts::iterator i = _opts.find(opt);
+ LEMON_ASSERT(i!=_opts.end(), "Unknown option: '"+opt+"'");
+ LEMON_ASSERT(!(i->second.ingroup),
+ "Option already in option group: '"+opt+"'");
+ GroupData &g=_groups[group];
+ g.opts.push_back(opt);
+ i->second.ingroup=true;
+ return *this;
+ }
+
+ ArgParser &ArgParser::onlyOneGroup(const std::string &group)
+ {
+ GroupData &g=_groups[group];
+ g.only_one=true;
+ return *this;
+ }
+
+ ArgParser &ArgParser::synonym(const std::string &syn,
+ const std::string &opt)
+ {
+ Opts::iterator o = _opts.find(opt);
+ Opts::iterator s = _opts.find(syn);
+ LEMON_ASSERT(o!=_opts.end(), "Unknown option: '"+opt+"'");
+ LEMON_ASSERT(s==_opts.end(), "Option already used: '"+syn+"'");
+ ParData p;
+ p.help=opt;
+ p.mandatory=false;
+ p.syn=true;
+ _opts[syn]=p;
+ o->second.has_syn=true;
+ return *this;
+ }
+
+ ArgParser &ArgParser::mandatoryGroup(const std::string &group)
+ {
+ GroupData &g=_groups[group];
+ g.mandatory=true;
+ return *this;
+ }
+
+ ArgParser &ArgParser::other(const std::string &name,
+ const std::string &help)
+ {
+ _others_help.push_back(OtherArg(name,help));
+ return *this;
+ }
+
+ void ArgParser::show(std::ostream &os,Opts::const_iterator i) const
+ {
+ os << "-" << i->first;
+ if(i->second.has_syn)
+ for(Opts::const_iterator j=_opts.begin();j!=_opts.end();++j)
+ if(j->second.syn&&j->second.help==i->first)
+ os << "|-" << j->first;
+ switch(i->second.type) {
+ case STRING:
+ os << " str";
+ break;
+ case INTEGER:
+ os << " int";
+ break;
+ case DOUBLE:
+ os << " num";
+ break;
+ default:
+ break;
+ }
+ }
+
+ void ArgParser::show(std::ostream &os,Groups::const_iterator i) const
+ {
+ GroupData::Opts::const_iterator o=i->second.opts.begin();
+ while(o!=i->second.opts.end()) {
+ show(os,_opts.find(*o));
+ ++o;
+ if(o!=i->second.opts.end()) os<<'|';
+ }
+ }
+
+ void ArgParser::showHelp(Opts::const_iterator i) const
+ {
+ if(i->second.help.size()==0||i->second.syn) return;
+ std::cerr << " ";
+ show(std::cerr,i);
+ std::cerr << std::endl;
+ std::cerr << " " << i->second.help << std::endl;
+ }
+ void ArgParser::showHelp(std::vector<ArgParser::OtherArg>::const_iterator i)
+ const
+ {
+ if(i->help.size()==0) return;
+ std::cerr << " " << i->name << std::endl
+ << " " << i->help << std::endl;
+ }
+
+ void ArgParser::shortHelp() const
+ {
+ const unsigned int LINE_LEN=77;
+ const std::string indent(" ");
+ std::cerr << "Usage:\n " << _command_name;
+ int pos=_command_name.size()+2;
+ for(Groups::const_iterator g=_groups.begin();g!=_groups.end();++g) {
+ std::ostringstream cstr;
+ cstr << ' ';
+ if(!g->second.mandatory) cstr << '[';
+ show(cstr,g);
+ if(!g->second.mandatory) cstr << ']';
+ if(pos+cstr.str().size()>LINE_LEN) {
+ std::cerr << std::endl << indent;
+ pos=indent.size();
+ }
+ std::cerr << cstr.str();
+ pos+=cstr.str().size();
+ }
+ for(Opts::const_iterator i=_opts.begin();i!=_opts.end();++i)
+ if(!i->second.ingroup&&!i->second.syn) {
+ std::ostringstream cstr;
+ cstr << ' ';
+ if(!i->second.mandatory) cstr << '[';
+ show(cstr,i);
+ if(!i->second.mandatory) cstr << ']';
+ if(pos+cstr.str().size()>LINE_LEN) {
+ std::cerr << std::endl << indent;
+ pos=indent.size();
+ }
+ std::cerr << cstr.str();
+ pos+=cstr.str().size();
+ }
+ for(std::vector<OtherArg>::const_iterator i=_others_help.begin();
+ i!=_others_help.end();++i)
+ {
+ std::ostringstream cstr;
+ cstr << ' ' << i->name;
+
+ if(pos+cstr.str().size()>LINE_LEN) {
+ std::cerr << std::endl << indent;
+ pos=indent.size();
+ }
+ std::cerr << cstr.str();
+ pos+=cstr.str().size();
+ }
+ std::cerr << std::endl;
+ }
+
+ void ArgParser::showHelp() const
+ {
+ shortHelp();
+ std::cerr << "Where:\n";
+ for(std::vector<OtherArg>::const_iterator i=_others_help.begin();
+ i!=_others_help.end();++i) showHelp(i);
+ for(Opts::const_iterator i=_opts.begin();i!=_opts.end();++i) showHelp(i);
+ _terminate(ArgParserException::HELP);
+ }
+
+
+ void ArgParser::unknownOpt(std::string arg) const
+ {
+ std::cerr << "\nUnknown option: " << arg << "\n";
+ std::cerr << "\nType '" << _command_name <<
+ " --help' to obtain a short summary on the usage.\n\n";
+ _terminate(ArgParserException::UNKNOWN_OPT);
+ }
+
+ void ArgParser::requiresValue(std::string arg, OptType t) const
+ {
+ std::cerr << "Argument '" << arg << "' requires a";
+ switch(t) {
+ case STRING:
+ std::cerr << " string";
+ break;
+ case INTEGER:
+ std::cerr << "n integer";
+ break;
+ case DOUBLE:
+ std::cerr << " floating point";
+ break;
+ default:
+ break;
+ }
+ std::cerr << " value\n\n";
+ showHelp();
+ }
+
+
+ void ArgParser::checkMandatories() const
+ {
+ bool ok=true;
+ for(Opts::const_iterator i=_opts.begin();i!=_opts.end();++i)
+ if(i->second.mandatory&&!i->second.set)
+ {
+ if(ok)
+ std::cerr << _command_name
+ << ": The following mandatory arguments are missing.\n";
+ ok=false;
+ showHelp(i);
+ }
+ for(Groups::const_iterator i=_groups.begin();i!=_groups.end();++i)
+ if(i->second.mandatory||i->second.only_one)
+ {
+ int set=0;
+ for(GroupData::Opts::const_iterator o=i->second.opts.begin();
+ o!=i->second.opts.end();++o)
+ if(_opts.find(*o)->second.set) ++set;
+ if(i->second.mandatory&&!set) {
+ std::cerr << _command_name <<
+ ": At least one of the following arguments is mandatory.\n";
+ ok=false;
+ for(GroupData::Opts::const_iterator o=i->second.opts.begin();
+ o!=i->second.opts.end();++o)
+ showHelp(_opts.find(*o));
+ }
+ if(i->second.only_one&&set>1) {
+ std::cerr << _command_name <<
+ ": At most one of the following arguments can be given.\n";
+ ok=false;
+ for(GroupData::Opts::const_iterator o=i->second.opts.begin();
+ o!=i->second.opts.end();++o)
+ showHelp(_opts.find(*o));
+ }
+ }
+ if(!ok) {
+ std::cerr << "\nType '" << _command_name <<
+ " --help' to obtain a short summary on the usage.\n\n";
+ _terminate(ArgParserException::INVALID_OPT);
+ }
+ }
+
+ ArgParser &ArgParser::parse()
+ {
+ for(int ar=1; ar<_argc; ++ar) {
+ std::string arg(_argv[ar]);
+ if (arg[0] != '-' || arg.size() == 1) {
+ _file_args.push_back(arg);
+ }
+ else {
+ Opts::iterator i = _opts.find(arg.substr(1));
+ if(i==_opts.end()) unknownOpt(arg);
+ else {
+ if(i->second.syn) i=_opts.find(i->second.help);
+ ParData &p(i->second);
+ if (p.type==BOOL) *p.bool_p=true;
+ else if (p.type==FUNC) p.func_p.p(p.func_p.data);
+ else if(++ar==_argc) requiresValue(arg, p.type);
+ else {
+ std::string val(_argv[ar]);
+ std::istringstream vals(val);
+ switch(p.type) {
+ case STRING:
+ *p.string_p=val;
+ break;
+ case INTEGER:
+ vals >> *p.int_p;
+ break;
+ case DOUBLE:
+ vals >> *p.double_p;
+ break;
+ default:
+ break;
+ }
+ if(p.type!=STRING&&(!vals||!vals.eof()))
+ requiresValue(arg, p.type);
+ }
+ p.set = true;
+ }
+ }
+ }
+ checkMandatories();
+
+ return *this;
+ }
+
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/arg_parser.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/arg_parser.h
new file mode 100644
index 00000000000..3fbe75c97e5
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/arg_parser.h
@@ -0,0 +1,440 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2010
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_ARG_PARSER_H
+#define LEMON_ARG_PARSER_H
+
+#include <vector>
+#include <map>
+#include <list>
+#include <string>
+#include <iostream>
+#include <sstream>
+#include <algorithm>
+#include <lemon/assert.h>
+
+///\ingroup misc
+///\file
+///\brief A tool to parse command line arguments.
+
+namespace lemon {
+
+ ///Exception used by ArgParser
+
+ ///Exception used by ArgParser.
+ ///
+ class ArgParserException : public Exception {
+ public:
+ /// Reasons for failure
+
+ /// Reasons for failure.
+ ///
+ enum Reason {
+ HELP, ///< <tt>--help</tt> option was given.
+ UNKNOWN_OPT, ///< Unknown option was given.
+ INVALID_OPT ///< Invalid combination of options.
+ };
+
+ private:
+ Reason _reason;
+
+ public:
+ ///Constructor
+ ArgParserException(Reason r) throw() : _reason(r) {}
+ ///Virtual destructor
+ virtual ~ArgParserException() throw() {}
+ ///A short description of the exception
+ virtual const char* what() const throw() {
+ switch(_reason)
+ {
+ case HELP:
+ return "lemon::ArgParseException: ask for help";
+ break;
+ case UNKNOWN_OPT:
+ return "lemon::ArgParseException: unknown option";
+ break;
+ case INVALID_OPT:
+ return "lemon::ArgParseException: invalid combination of options";
+ break;
+ }
+ return "";
+ }
+ ///Return the reason for the failure
+ Reason reason() const {return _reason; }
+ };
+
+
+ ///Command line arguments parser
+
+ ///\ingroup misc
+ ///Command line arguments parser.
+ ///
+ ///For a complete example see the \ref arg_parser_demo.cc demo file.
+ class ArgParser {
+
+ static void _showHelp(void *p);
+ protected:
+
+ int _argc;
+ const char * const *_argv;
+
+ enum OptType { UNKNOWN=0, BOOL=1, STRING=2, DOUBLE=3, INTEGER=4, FUNC=5 };
+
+ class ParData {
+ public:
+ union {
+ bool *bool_p;
+ int *int_p;
+ double *double_p;
+ std::string *string_p;
+ struct {
+ void (*p)(void *);
+ void *data;
+ } func_p;
+
+ };
+ std::string help;
+ bool mandatory;
+ OptType type;
+ bool set;
+ bool ingroup;
+ bool has_syn;
+ bool syn;
+ bool self_delete;
+ ParData() : mandatory(false), type(UNKNOWN), set(false), ingroup(false),
+ has_syn(false), syn(false), self_delete(false) {}
+ };
+
+ typedef std::map<std::string,ParData> Opts;
+ Opts _opts;
+
+ class GroupData
+ {
+ public:
+ typedef std::list<std::string> Opts;
+ Opts opts;
+ bool only_one;
+ bool mandatory;
+ GroupData() :only_one(false), mandatory(false) {}
+ };
+
+ typedef std::map<std::string,GroupData> Groups;
+ Groups _groups;
+
+ struct OtherArg
+ {
+ std::string name;
+ std::string help;
+ OtherArg(std::string n, std::string h) :name(n), help(h) {}
+
+ };
+
+ std::vector<OtherArg> _others_help;
+ std::vector<std::string> _file_args;
+ std::string _command_name;
+
+
+ private:
+ //Bind a function to an option.
+
+ //\param name The name of the option. The leading '-' must be omitted.
+ //\param help A help string.
+ //\retval func The function to be called when the option is given. It
+ // must be of type "void f(void *)"
+ //\param data Data to be passed to \c func
+ ArgParser &funcOption(const std::string &name,
+ const std::string &help,
+ void (*func)(void *),void *data);
+
+ bool _exit_on_problems;
+
+ void _terminate(ArgParserException::Reason reason) const;
+
+ public:
+
+ ///Constructor
+ ArgParser(int argc, const char * const *argv);
+
+ ~ArgParser();
+
+ ///\name Options
+ ///
+
+ ///@{
+
+ ///Add a new integer type option
+
+ ///Add a new integer type option.
+ ///\param name The name of the option. The leading '-' must be omitted.
+ ///\param help A help string.
+ ///\param value A default value for the option.
+ ///\param obl Indicate if the option is mandatory.
+ ArgParser &intOption(const std::string &name,
+ const std::string &help,
+ int value=0, bool obl=false);
+
+ ///Add a new floating point type option
+
+ ///Add a new floating point type option.
+ ///\param name The name of the option. The leading '-' must be omitted.
+ ///\param help A help string.
+ ///\param value A default value for the option.
+ ///\param obl Indicate if the option is mandatory.
+ ArgParser &doubleOption(const std::string &name,
+ const std::string &help,
+ double value=0, bool obl=false);
+
+ ///Add a new bool type option
+
+ ///Add a new bool type option.
+ ///\param name The name of the option. The leading '-' must be omitted.
+ ///\param help A help string.
+ ///\param value A default value for the option.
+ ///\param obl Indicate if the option is mandatory.
+ ///\note A mandatory bool obtion is of very little use.
+ ArgParser &boolOption(const std::string &name,
+ const std::string &help,
+ bool value=false, bool obl=false);
+
+ ///Add a new string type option
+
+ ///Add a new string type option.
+ ///\param name The name of the option. The leading '-' must be omitted.
+ ///\param help A help string.
+ ///\param value A default value for the option.
+ ///\param obl Indicate if the option is mandatory.
+ ArgParser &stringOption(const std::string &name,
+ const std::string &help,
+ std::string value="", bool obl=false);
+
+ ///Give help string for non-parsed arguments.
+
+ ///With this function you can give help string for non-parsed arguments.
+ ///The parameter \c name will be printed in the short usage line, while
+ ///\c help gives a more detailed description.
+ ArgParser &other(const std::string &name,
+ const std::string &help="");
+
+ ///@}
+
+ ///\name Options with External Storage
+ ///Using this functions, the value of the option will be directly written
+ ///into a variable once the option appears in the command line.
+
+ ///@{
+
+ ///Add a new integer type option with a storage reference
+
+ ///Add a new integer type option with a storage reference.
+ ///\param name The name of the option. The leading '-' must be omitted.
+ ///\param help A help string.
+ ///\param obl Indicate if the option is mandatory.
+ ///\retval ref The value of the argument will be written to this variable.
+ ArgParser &refOption(const std::string &name,
+ const std::string &help,
+ int &ref, bool obl=false);
+
+ ///Add a new floating type option with a storage reference
+
+ ///Add a new floating type option with a storage reference.
+ ///\param name The name of the option. The leading '-' must be omitted.
+ ///\param help A help string.
+ ///\param obl Indicate if the option is mandatory.
+ ///\retval ref The value of the argument will be written to this variable.
+ ArgParser &refOption(const std::string &name,
+ const std::string &help,
+ double &ref, bool obl=false);
+
+ ///Add a new bool type option with a storage reference
+
+ ///Add a new bool type option with a storage reference.
+ ///\param name The name of the option. The leading '-' must be omitted.
+ ///\param help A help string.
+ ///\param obl Indicate if the option is mandatory.
+ ///\retval ref The value of the argument will be written to this variable.
+ ///\note A mandatory bool obtion is of very little use.
+ ArgParser &refOption(const std::string &name,
+ const std::string &help,
+ bool &ref, bool obl=false);
+
+ ///Add a new string type option with a storage reference
+
+ ///Add a new string type option with a storage reference.
+ ///\param name The name of the option. The leading '-' must be omitted.
+ ///\param help A help string.
+ ///\param obl Indicate if the option is mandatory.
+ ///\retval ref The value of the argument will be written to this variable.
+ ArgParser &refOption(const std::string &name,
+ const std::string &help,
+ std::string &ref, bool obl=false);
+
+ ///@}
+
+ ///\name Option Groups and Synonyms
+ ///
+
+ ///@{
+
+ ///Bundle some options into a group
+
+ /// You can group some option by calling this function repeatedly for each
+ /// option to be grouped with the same groupname.
+ ///\param group The group name.
+ ///\param opt The option name.
+ ArgParser &optionGroup(const std::string &group,
+ const std::string &opt);
+
+ ///Make the members of a group exclusive
+
+ ///If you call this function for a group, than at most one of them can be
+ ///given at the same time.
+ ArgParser &onlyOneGroup(const std::string &group);
+
+ ///Make a group mandatory
+
+ ///Using this function, at least one of the members of \c group
+ ///must be given.
+ ArgParser &mandatoryGroup(const std::string &group);
+
+ ///Create synonym to an option
+
+ ///With this function you can create a synonym \c syn of the
+ ///option \c opt.
+ ArgParser &synonym(const std::string &syn,
+ const std::string &opt);
+
+ ///@}
+
+ private:
+ void show(std::ostream &os,Opts::const_iterator i) const;
+ void show(std::ostream &os,Groups::const_iterator i) const;
+ void showHelp(Opts::const_iterator i) const;
+ void showHelp(std::vector<OtherArg>::const_iterator i) const;
+
+ void unknownOpt(std::string arg) const;
+
+ void requiresValue(std::string arg, OptType t) const;
+ void checkMandatories() const;
+
+ void shortHelp() const;
+ void showHelp() const;
+ public:
+
+ ///Start the parsing process
+ ArgParser &parse();
+
+ /// Synonym for parse()
+ ArgParser &run()
+ {
+ return parse();
+ }
+
+ ///Give back the command name (the 0th argument)
+ const std::string &commandName() const { return _command_name; }
+
+ ///Check if an opion has been given to the command.
+ bool given(std::string op) const
+ {
+ Opts::const_iterator i = _opts.find(op);
+ return i!=_opts.end()?i->second.set:false;
+ }
+
+
+ ///Magic type for operator[]
+
+ ///This is the type of the return value of ArgParser::operator[]().
+ ///It automatically converts to \c int, \c double, \c bool or
+ ///\c std::string if the type of the option matches, which is checked
+ ///with an \ref LEMON_ASSERT "assertion" (i.e. it performs runtime
+ ///type checking).
+ class RefType
+ {
+ const ArgParser &_parser;
+ std::string _name;
+ public:
+ ///\e
+ RefType(const ArgParser &p,const std::string &n) :_parser(p),_name(n) {}
+ ///\e
+ operator bool()
+ {
+ Opts::const_iterator i = _parser._opts.find(_name);
+ LEMON_ASSERT(i!=_parser._opts.end(),
+ std::string()+"Unkown option: '"+_name+"'");
+ LEMON_ASSERT(i->second.type==ArgParser::BOOL,
+ std::string()+"'"+_name+"' is a bool option");
+ return *(i->second.bool_p);
+ }
+ ///\e
+ operator std::string()
+ {
+ Opts::const_iterator i = _parser._opts.find(_name);
+ LEMON_ASSERT(i!=_parser._opts.end(),
+ std::string()+"Unkown option: '"+_name+"'");
+ LEMON_ASSERT(i->second.type==ArgParser::STRING,
+ std::string()+"'"+_name+"' is a string option");
+ return *(i->second.string_p);
+ }
+ ///\e
+ operator double()
+ {
+ Opts::const_iterator i = _parser._opts.find(_name);
+ LEMON_ASSERT(i!=_parser._opts.end(),
+ std::string()+"Unkown option: '"+_name+"'");
+ LEMON_ASSERT(i->second.type==ArgParser::DOUBLE ||
+ i->second.type==ArgParser::INTEGER,
+ std::string()+"'"+_name+"' is a floating point option");
+ return i->second.type==ArgParser::DOUBLE ?
+ *(i->second.double_p) : *(i->second.int_p);
+ }
+ ///\e
+ operator int()
+ {
+ Opts::const_iterator i = _parser._opts.find(_name);
+ LEMON_ASSERT(i!=_parser._opts.end(),
+ std::string()+"Unkown option: '"+_name+"'");
+ LEMON_ASSERT(i->second.type==ArgParser::INTEGER,
+ std::string()+"'"+_name+"' is an integer option");
+ return *(i->second.int_p);
+ }
+
+ };
+
+ ///Give back the value of an option
+
+ ///Give back the value of an option.
+ ///\sa RefType
+ RefType operator[](const std::string &n) const
+ {
+ return RefType(*this, n);
+ }
+
+ ///Give back the non-option type arguments.
+
+ ///Give back a reference to a vector consisting of the program arguments
+ ///not starting with a '-' character.
+ const std::vector<std::string> &files() const { return _file_args; }
+
+ ///Throw instead of exit in case of problems
+ void throwOnProblems()
+ {
+ _exit_on_problems=false;
+ }
+ };
+}
+
+#endif // LEMON_ARG_PARSER_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/assert.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/assert.h
new file mode 100644
index 00000000000..f6c1dfc8e59
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/assert.h
@@ -0,0 +1,214 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_ASSERT_H
+#define LEMON_ASSERT_H
+
+/// \ingroup exceptions
+/// \file
+/// \brief Extended assertion handling
+
+#include <lemon/error.h>
+
+namespace lemon {
+
+ inline void assert_fail_abort(const char *file, int line,
+ const char *function, const char* message,
+ const char *assertion)
+ {
+ std::cerr << file << ":" << line << ": ";
+ if (function)
+ std::cerr << function << ": ";
+ std::cerr << message;
+ if (assertion)
+ std::cerr << " (assertion '" << assertion << "' failed)";
+ std::cerr << std::endl;
+ std::abort();
+ }
+
+ namespace _assert_bits {
+
+
+ inline const char* cstringify(const std::string& str) {
+ return str.c_str();
+ }
+
+ inline const char* cstringify(const char* str) {
+ return str;
+ }
+ }
+}
+
+#endif // LEMON_ASSERT_H
+
+#undef LEMON_ASSERT
+#undef LEMON_DEBUG
+
+#if (defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \
+ (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
+#error "LEMON assertion system is not set properly"
+#endif
+
+#if ((defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \
+ (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 || \
+ defined(LEMON_ENABLE_ASSERTS)) && \
+ (defined(LEMON_DISABLE_ASSERTS) || \
+ defined(NDEBUG))
+#error "LEMON assertion system is not set properly"
+#endif
+
+
+#if defined LEMON_ASSERT_ABORT
+# undef LEMON_ASSERT_HANDLER
+# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
+#elif defined LEMON_ASSERT_CUSTOM
+# undef LEMON_ASSERT_HANDLER
+# ifndef LEMON_CUSTOM_ASSERT_HANDLER
+# error "LEMON_CUSTOM_ASSERT_HANDLER is not set"
+# endif
+# define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER
+#elif defined LEMON_DISABLE_ASSERTS
+# undef LEMON_ASSERT_HANDLER
+#elif defined NDEBUG
+# undef LEMON_ASSERT_HANDLER
+#else
+# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
+#endif
+
+#ifndef LEMON_FUNCTION_NAME
+# if defined __GNUC__
+# define LEMON_FUNCTION_NAME (__PRETTY_FUNCTION__)
+# elif defined _MSC_VER
+# define LEMON_FUNCTION_NAME (__FUNCSIG__)
+# elif __STDC_VERSION__ >= 199901L
+# define LEMON_FUNCTION_NAME (__func__)
+# else
+# define LEMON_FUNCTION_NAME ("<unknown>")
+# endif
+#endif
+
+#ifdef DOXYGEN
+
+/// \ingroup exceptions
+///
+/// \brief Macro for assertion with customizable message
+///
+/// Macro for assertion with customizable message.
+/// \param exp An expression that must be convertible to \c bool. If it is \c
+/// false, then an assertion is raised. The concrete behaviour depends on the
+/// settings of the assertion system.
+/// \param msg A <tt>const char*</tt> parameter, which can be used to provide
+/// information about the circumstances of the failed assertion.
+///
+/// The assertions are enabled in the default behaviour.
+/// You can disable them with the following code:
+/// \code
+/// #define LEMON_DISABLE_ASSERTS
+/// \endcode
+/// or with compilation parameters:
+/// \code
+/// g++ -DLEMON_DISABLE_ASSERTS
+/// make CXXFLAGS='-DLEMON_DISABLE_ASSERTS'
+/// \endcode
+/// The checking is also disabled when the standard macro \c NDEBUG is defined.
+///
+/// As a default behaviour the failed assertion prints a short log message to
+/// the standard error and aborts the execution.
+///
+/// However, the following modes can be used in the assertion system:
+/// - \c LEMON_ASSERT_ABORT The failed assertion prints a short log message to
+/// the standard error and aborts the program. It is the default behaviour.
+/// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler
+/// function.
+/// \code
+/// void custom_assert_handler(const char* file, int line,
+/// const char* function, const char* message,
+/// const char* assertion);
+/// \endcode
+/// The name of the function should be defined as the \c
+/// LEMON_CUSTOM_ASSERT_HANDLER macro name.
+/// \code
+/// #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
+/// \endcode
+/// Whenever an assertion is occured, the custom assertion
+/// handler is called with appropiate parameters.
+///
+/// The assertion mode can also be changed within one compilation unit.
+/// If the macros are redefined with other settings and the
+/// \ref lemon/assert.h "assert.h" file is reincluded, then the
+/// behaviour is changed appropiately to the new settings.
+# define LEMON_ASSERT(exp, msg) \
+ (static_cast<void> (!!(exp) ? 0 : ( \
+ LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
+ LEMON_FUNCTION_NAME, \
+ ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
+
+/// \ingroup exceptions
+///
+/// \brief Macro for internal assertions
+///
+/// Macro for internal assertions, it is used in the library to check
+/// the consistency of results of algorithms, several pre- and
+/// postconditions and invariants. The checking is disabled by
+/// default, but it can be turned on with the macro \c
+/// LEMON_ENABLE_DEBUG.
+/// \code
+/// #define LEMON_ENABLE_DEBUG
+/// \endcode
+/// or with compilation parameters:
+/// \code
+/// g++ -DLEMON_ENABLE_DEBUG
+/// make CXXFLAGS='-DLEMON_ENABLE_DEBUG'
+/// \endcode
+///
+/// This macro works like the \c LEMON_ASSERT macro, therefore the
+/// current behaviour depends on the settings of \c LEMON_ASSERT
+/// macro.
+///
+/// \see LEMON_ASSERT
+# define LEMON_DEBUG(exp, msg) \
+ (static_cast<void> (!!(exp) ? 0 : ( \
+ LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
+ LEMON_FUNCTION_NAME, \
+ ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
+
+#else
+
+# ifndef LEMON_ASSERT_HANDLER
+# define LEMON_ASSERT(exp, msg) (static_cast<void>(0))
+# define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
+# else
+# define LEMON_ASSERT(exp, msg) \
+ (static_cast<void> (!!(exp) ? 0 : ( \
+ LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
+ LEMON_FUNCTION_NAME, \
+ ::lemon::_assert_bits::cstringify(msg), \
+ #exp), 0)))
+# if defined LEMON_ENABLE_DEBUG
+# define LEMON_DEBUG(exp, msg) \
+ (static_cast<void> (!!(exp) ? 0 : ( \
+ LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
+ LEMON_FUNCTION_NAME, \
+ ::lemon::_assert_bits::cstringify(msg), \
+ #exp), 0)))
+# else
+# define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
+# endif
+# endif
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/base.cc b/extern/quadriflow/3rd/lemon-1.3.1/lemon/base.cc
new file mode 100644
index 00000000000..a057b41cbc0
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/base.cc
@@ -0,0 +1,37 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\file
+///\brief Some basic non-inline functions and static global data.
+
+#include<lemon/tolerance.h>
+#include<lemon/core.h>
+#include<lemon/time_measure.h>
+namespace lemon {
+
+ float Tolerance<float>::def_epsilon = static_cast<float>(1e-4);
+ double Tolerance<double>::def_epsilon = 1e-10;
+ long double Tolerance<long double>::def_epsilon = 1e-14;
+
+#ifndef LEMON_ONLY_TEMPLATES
+ const Invalid INVALID = Invalid();
+#endif
+
+ TimeStamp::Format TimeStamp::_format = TimeStamp::NORMAL;
+
+} //namespace lemon
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bellman_ford.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bellman_ford.h
new file mode 100644
index 00000000000..310758ebb59
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bellman_ford.h
@@ -0,0 +1,1116 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BELLMAN_FORD_H
+#define LEMON_BELLMAN_FORD_H
+
+/// \ingroup shortest_path
+/// \file
+/// \brief Bellman-Ford algorithm.
+
+#include <lemon/list_graph.h>
+#include <lemon/bits/path_dump.h>
+#include <lemon/core.h>
+#include <lemon/error.h>
+#include <lemon/maps.h>
+#include <lemon/path.h>
+
+#include <limits>
+
+namespace lemon {
+
+ /// \brief Default OperationTraits for the BellmanFord algorithm class.
+ ///
+ /// This operation traits class defines all computational operations
+ /// and constants that are used in the Bellman-Ford algorithm.
+ /// The default implementation is based on the \c numeric_limits class.
+ /// If the numeric type does not have infinity value, then the maximum
+ /// value is used as extremal infinity value.
+ template <
+ typename V,
+ bool has_inf = std::numeric_limits<V>::has_infinity>
+ struct BellmanFordDefaultOperationTraits {
+ /// \e
+ typedef V Value;
+ /// \brief Gives back the zero value of the type.
+ static Value zero() {
+ return static_cast<Value>(0);
+ }
+ /// \brief Gives back the positive infinity value of the type.
+ static Value infinity() {
+ return std::numeric_limits<Value>::infinity();
+ }
+ /// \brief Gives back the sum of the given two elements.
+ static Value plus(const Value& left, const Value& right) {
+ return left + right;
+ }
+ /// \brief Gives back \c true only if the first value is less than
+ /// the second.
+ static bool less(const Value& left, const Value& right) {
+ return left < right;
+ }
+ };
+
+ template <typename V>
+ struct BellmanFordDefaultOperationTraits<V, false> {
+ typedef V Value;
+ static Value zero() {
+ return static_cast<Value>(0);
+ }
+ static Value infinity() {
+ return std::numeric_limits<Value>::max();
+ }
+ static Value plus(const Value& left, const Value& right) {
+ if (left == infinity() || right == infinity()) return infinity();
+ return left + right;
+ }
+ static bool less(const Value& left, const Value& right) {
+ return left < right;
+ }
+ };
+
+ /// \brief Default traits class of BellmanFord class.
+ ///
+ /// Default traits class of BellmanFord class.
+ /// \param GR The type of the digraph.
+ /// \param LEN The type of the length map.
+ template<typename GR, typename LEN>
+ struct BellmanFordDefaultTraits {
+ /// The type of the digraph the algorithm runs on.
+ typedef GR Digraph;
+
+ /// \brief The type of the map that stores the arc lengths.
+ ///
+ /// The type of the map that stores the arc lengths.
+ /// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
+ typedef LEN LengthMap;
+
+ /// The type of the arc lengths.
+ typedef typename LEN::Value Value;
+
+ /// \brief Operation traits for Bellman-Ford algorithm.
+ ///
+ /// It defines the used operations and the infinity value for the
+ /// given \c Value type.
+ /// \see BellmanFordDefaultOperationTraits
+ typedef BellmanFordDefaultOperationTraits<Value> OperationTraits;
+
+ /// \brief The type of the map that stores the last arcs of the
+ /// shortest paths.
+ ///
+ /// The type of the map that stores the last
+ /// arcs of the shortest paths.
+ /// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ typedef typename GR::template NodeMap<typename GR::Arc> PredMap;
+
+ /// \brief Instantiates a \c PredMap.
+ ///
+ /// This function instantiates a \ref PredMap.
+ /// \param g is the digraph to which we would like to define the
+ /// \ref PredMap.
+ static PredMap *createPredMap(const GR& g) {
+ return new PredMap(g);
+ }
+
+ /// \brief The type of the map that stores the distances of the nodes.
+ ///
+ /// The type of the map that stores the distances of the nodes.
+ /// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ typedef typename GR::template NodeMap<typename LEN::Value> DistMap;
+
+ /// \brief Instantiates a \c DistMap.
+ ///
+ /// This function instantiates a \ref DistMap.
+ /// \param g is the digraph to which we would like to define the
+ /// \ref DistMap.
+ static DistMap *createDistMap(const GR& g) {
+ return new DistMap(g);
+ }
+
+ };
+
+ /// \brief %BellmanFord algorithm class.
+ ///
+ /// \ingroup shortest_path
+ /// This class provides an efficient implementation of the Bellman-Ford
+ /// algorithm. The maximum time complexity of the algorithm is
+ /// <tt>O(nm)</tt>.
+ ///
+ /// The Bellman-Ford algorithm solves the single-source shortest path
+ /// problem when the arcs can have negative lengths, but the digraph
+ /// should not contain directed cycles with negative total length.
+ /// If all arc costs are non-negative, consider to use the Dijkstra
+ /// algorithm instead, since it is more efficient.
+ ///
+ /// The arc lengths are passed to the algorithm using a
+ /// \ref concepts::ReadMap "ReadMap", so it is easy to change it to any
+ /// kind of length. The type of the length values is determined by the
+ /// \ref concepts::ReadMap::Value "Value" type of the length map.
+ ///
+ /// There is also a \ref bellmanFord() "function-type interface" for the
+ /// Bellman-Ford algorithm, which is convenient in the simplier cases and
+ /// it can be used easier.
+ ///
+ /// \tparam GR The type of the digraph the algorithm runs on.
+ /// The default type is \ref ListDigraph.
+ /// \tparam LEN A \ref concepts::ReadMap "readable" arc map that specifies
+ /// the lengths of the arcs. The default map type is
+ /// \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
+ /// \tparam TR The traits class that defines various types used by the
+ /// algorithm. By default, it is \ref BellmanFordDefaultTraits
+ /// "BellmanFordDefaultTraits<GR, LEN>".
+ /// In most cases, this parameter should not be set directly,
+ /// consider to use the named template parameters instead.
+#ifdef DOXYGEN
+ template <typename GR, typename LEN, typename TR>
+#else
+ template <typename GR=ListDigraph,
+ typename LEN=typename GR::template ArcMap<int>,
+ typename TR=BellmanFordDefaultTraits<GR,LEN> >
+#endif
+ class BellmanFord {
+ public:
+
+ ///The type of the underlying digraph.
+ typedef typename TR::Digraph Digraph;
+
+ /// \brief The type of the arc lengths.
+ typedef typename TR::LengthMap::Value Value;
+ /// \brief The type of the map that stores the arc lengths.
+ typedef typename TR::LengthMap LengthMap;
+ /// \brief The type of the map that stores the last
+ /// arcs of the shortest paths.
+ typedef typename TR::PredMap PredMap;
+ /// \brief The type of the map that stores the distances of the nodes.
+ typedef typename TR::DistMap DistMap;
+ /// The type of the paths.
+ typedef PredMapPath<Digraph, PredMap> Path;
+ ///\brief The \ref lemon::BellmanFordDefaultOperationTraits
+ /// "operation traits class" of the algorithm.
+ typedef typename TR::OperationTraits OperationTraits;
+
+ ///\brief The \ref lemon::BellmanFordDefaultTraits "traits class"
+ ///of the algorithm.
+ typedef TR Traits;
+
+ private:
+
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::NodeIt NodeIt;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::OutArcIt OutArcIt;
+
+ // Pointer to the underlying digraph.
+ const Digraph *_gr;
+ // Pointer to the length map
+ const LengthMap *_length;
+ // Pointer to the map of predecessors arcs.
+ PredMap *_pred;
+ // Indicates if _pred is locally allocated (true) or not.
+ bool _local_pred;
+ // Pointer to the map of distances.
+ DistMap *_dist;
+ // Indicates if _dist is locally allocated (true) or not.
+ bool _local_dist;
+
+ typedef typename Digraph::template NodeMap<bool> MaskMap;
+ MaskMap *_mask;
+
+ std::vector<Node> _process;
+
+ // Creates the maps if necessary.
+ void create_maps() {
+ if(!_pred) {
+ _local_pred = true;
+ _pred = Traits::createPredMap(*_gr);
+ }
+ if(!_dist) {
+ _local_dist = true;
+ _dist = Traits::createDistMap(*_gr);
+ }
+ if(!_mask) {
+ _mask = new MaskMap(*_gr);
+ }
+ }
+
+ public :
+
+ typedef BellmanFord Create;
+
+ /// \name Named Template Parameters
+
+ ///@{
+
+ template <class T>
+ struct SetPredMapTraits : public Traits {
+ typedef T PredMap;
+ static PredMap *createPredMap(const Digraph&) {
+ LEMON_ASSERT(false, "PredMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// \c PredMap type.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting
+ /// \c PredMap type.
+ /// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ template <class T>
+ struct SetPredMap
+ : public BellmanFord< Digraph, LengthMap, SetPredMapTraits<T> > {
+ typedef BellmanFord< Digraph, LengthMap, SetPredMapTraits<T> > Create;
+ };
+
+ template <class T>
+ struct SetDistMapTraits : public Traits {
+ typedef T DistMap;
+ static DistMap *createDistMap(const Digraph&) {
+ LEMON_ASSERT(false, "DistMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// \c DistMap type.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting
+ /// \c DistMap type.
+ /// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ template <class T>
+ struct SetDistMap
+ : public BellmanFord< Digraph, LengthMap, SetDistMapTraits<T> > {
+ typedef BellmanFord< Digraph, LengthMap, SetDistMapTraits<T> > Create;
+ };
+
+ template <class T>
+ struct SetOperationTraitsTraits : public Traits {
+ typedef T OperationTraits;
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// \c OperationTraits type.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting
+ /// \c OperationTraits type.
+ /// For more information, see \ref BellmanFordDefaultOperationTraits.
+ template <class T>
+ struct SetOperationTraits
+ : public BellmanFord< Digraph, LengthMap, SetOperationTraitsTraits<T> > {
+ typedef BellmanFord< Digraph, LengthMap, SetOperationTraitsTraits<T> >
+ Create;
+ };
+
+ ///@}
+
+ protected:
+
+ BellmanFord() {}
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// \param g The digraph the algorithm runs on.
+ /// \param length The length map used by the algorithm.
+ BellmanFord(const Digraph& g, const LengthMap& length) :
+ _gr(&g), _length(&length),
+ _pred(0), _local_pred(false),
+ _dist(0), _local_dist(false), _mask(0) {}
+
+ ///Destructor.
+ ~BellmanFord() {
+ if(_local_pred) delete _pred;
+ if(_local_dist) delete _dist;
+ if(_mask) delete _mask;
+ }
+
+ /// \brief Sets the length map.
+ ///
+ /// Sets the length map.
+ /// \return <tt>(*this)</tt>
+ BellmanFord &lengthMap(const LengthMap &map) {
+ _length = &map;
+ return *this;
+ }
+
+ /// \brief Sets the map that stores the predecessor arcs.
+ ///
+ /// Sets the map that stores the predecessor arcs.
+ /// If you don't use this function before calling \ref run()
+ /// or \ref init(), an instance will be allocated automatically.
+ /// The destructor deallocates this automatically allocated map,
+ /// of course.
+ /// \return <tt>(*this)</tt>
+ BellmanFord &predMap(PredMap &map) {
+ if(_local_pred) {
+ delete _pred;
+ _local_pred=false;
+ }
+ _pred = &map;
+ return *this;
+ }
+
+ /// \brief Sets the map that stores the distances of the nodes.
+ ///
+ /// Sets the map that stores the distances of the nodes calculated
+ /// by the algorithm.
+ /// If you don't use this function before calling \ref run()
+ /// or \ref init(), an instance will be allocated automatically.
+ /// The destructor deallocates this automatically allocated map,
+ /// of course.
+ /// \return <tt>(*this)</tt>
+ BellmanFord &distMap(DistMap &map) {
+ if(_local_dist) {
+ delete _dist;
+ _local_dist=false;
+ }
+ _dist = &map;
+ return *this;
+ }
+
+ /// \name Execution Control
+ /// The simplest way to execute the Bellman-Ford algorithm is to use
+ /// one of the member functions called \ref run().\n
+ /// If you need better control on the execution, you have to call
+ /// \ref init() first, then you can add several source nodes
+ /// with \ref addSource(). Finally the actual path computation can be
+ /// performed with \ref start(), \ref checkedStart() or
+ /// \ref limitedStart().
+
+ ///@{
+
+ /// \brief Initializes the internal data structures.
+ ///
+ /// Initializes the internal data structures. The optional parameter
+ /// is the initial distance of each node.
+ void init(const Value value = OperationTraits::infinity()) {
+ create_maps();
+ for (NodeIt it(*_gr); it != INVALID; ++it) {
+ _pred->set(it, INVALID);
+ _dist->set(it, value);
+ }
+ _process.clear();
+ if (OperationTraits::less(value, OperationTraits::infinity())) {
+ for (NodeIt it(*_gr); it != INVALID; ++it) {
+ _process.push_back(it);
+ _mask->set(it, true);
+ }
+ } else {
+ for (NodeIt it(*_gr); it != INVALID; ++it) {
+ _mask->set(it, false);
+ }
+ }
+ }
+
+ /// \brief Adds a new source node.
+ ///
+ /// This function adds a new source node. The optional second parameter
+ /// is the initial distance of the node.
+ void addSource(Node source, Value dst = OperationTraits::zero()) {
+ _dist->set(source, dst);
+ if (!(*_mask)[source]) {
+ _process.push_back(source);
+ _mask->set(source, true);
+ }
+ }
+
+ /// \brief Executes one round from the Bellman-Ford algorithm.
+ ///
+ /// If the algoritm calculated the distances in the previous round
+ /// exactly for the paths of at most \c k arcs, then this function
+ /// will calculate the distances exactly for the paths of at most
+ /// <tt>k+1</tt> arcs. Performing \c k iterations using this function
+ /// calculates the shortest path distances exactly for the paths
+ /// consisting of at most \c k arcs.
+ ///
+ /// \warning The paths with limited arc number cannot be retrieved
+ /// easily with \ref path() or \ref predArc() functions. If you also
+ /// need the shortest paths and not only the distances, you should
+ /// store the \ref predMap() "predecessor map" after each iteration
+ /// and build the path manually.
+ ///
+ /// \return \c true when the algorithm have not found more shorter
+ /// paths.
+ ///
+ /// \see ActiveIt
+ bool processNextRound() {
+ for (int i = 0; i < int(_process.size()); ++i) {
+ _mask->set(_process[i], false);
+ }
+ std::vector<Node> nextProcess;
+ std::vector<Value> values(_process.size());
+ for (int i = 0; i < int(_process.size()); ++i) {
+ values[i] = (*_dist)[_process[i]];
+ }
+ for (int i = 0; i < int(_process.size()); ++i) {
+ for (OutArcIt it(*_gr, _process[i]); it != INVALID; ++it) {
+ Node target = _gr->target(it);
+ Value relaxed = OperationTraits::plus(values[i], (*_length)[it]);
+ if (OperationTraits::less(relaxed, (*_dist)[target])) {
+ _pred->set(target, it);
+ _dist->set(target, relaxed);
+ if (!(*_mask)[target]) {
+ _mask->set(target, true);
+ nextProcess.push_back(target);
+ }
+ }
+ }
+ }
+ _process.swap(nextProcess);
+ return _process.empty();
+ }
+
+ /// \brief Executes one weak round from the Bellman-Ford algorithm.
+ ///
+ /// If the algorithm calculated the distances in the previous round
+ /// at least for the paths of at most \c k arcs, then this function
+ /// will calculate the distances at least for the paths of at most
+ /// <tt>k+1</tt> arcs.
+ /// This function does not make it possible to calculate the shortest
+ /// path distances exactly for paths consisting of at most \c k arcs,
+ /// this is why it is called weak round.
+ ///
+ /// \return \c true when the algorithm have not found more shorter
+ /// paths.
+ ///
+ /// \see ActiveIt
+ bool processNextWeakRound() {
+ for (int i = 0; i < int(_process.size()); ++i) {
+ _mask->set(_process[i], false);
+ }
+ std::vector<Node> nextProcess;
+ for (int i = 0; i < int(_process.size()); ++i) {
+ for (OutArcIt it(*_gr, _process[i]); it != INVALID; ++it) {
+ Node target = _gr->target(it);
+ Value relaxed =
+ OperationTraits::plus((*_dist)[_process[i]], (*_length)[it]);
+ if (OperationTraits::less(relaxed, (*_dist)[target])) {
+ _pred->set(target, it);
+ _dist->set(target, relaxed);
+ if (!(*_mask)[target]) {
+ _mask->set(target, true);
+ nextProcess.push_back(target);
+ }
+ }
+ }
+ }
+ _process.swap(nextProcess);
+ return _process.empty();
+ }
+
+ /// \brief Executes the algorithm.
+ ///
+ /// Executes the algorithm.
+ ///
+ /// This method runs the Bellman-Ford algorithm from the root node(s)
+ /// in order to compute the shortest path to each node.
+ ///
+ /// The algorithm computes
+ /// - the shortest path tree (forest),
+ /// - the distance of each node from the root(s).
+ ///
+ /// \pre init() must be called and at least one root node should be
+ /// added with addSource() before using this function.
+ void start() {
+ int num = countNodes(*_gr) - 1;
+ for (int i = 0; i < num; ++i) {
+ if (processNextWeakRound()) break;
+ }
+ }
+
+ /// \brief Executes the algorithm and checks the negative cycles.
+ ///
+ /// Executes the algorithm and checks the negative cycles.
+ ///
+ /// This method runs the Bellman-Ford algorithm from the root node(s)
+ /// in order to compute the shortest path to each node and also checks
+ /// if the digraph contains cycles with negative total length.
+ ///
+ /// The algorithm computes
+ /// - the shortest path tree (forest),
+ /// - the distance of each node from the root(s).
+ ///
+ /// \return \c false if there is a negative cycle in the digraph.
+ ///
+ /// \pre init() must be called and at least one root node should be
+ /// added with addSource() before using this function.
+ bool checkedStart() {
+ int num = countNodes(*_gr);
+ for (int i = 0; i < num; ++i) {
+ if (processNextWeakRound()) return true;
+ }
+ return _process.empty();
+ }
+
+ /// \brief Executes the algorithm with arc number limit.
+ ///
+ /// Executes the algorithm with arc number limit.
+ ///
+ /// This method runs the Bellman-Ford algorithm from the root node(s)
+ /// in order to compute the shortest path distance for each node
+ /// using only the paths consisting of at most \c num arcs.
+ ///
+ /// The algorithm computes
+ /// - the limited distance of each node from the root(s),
+ /// - the predecessor arc for each node.
+ ///
+ /// \warning The paths with limited arc number cannot be retrieved
+ /// easily with \ref path() or \ref predArc() functions. If you also
+ /// need the shortest paths and not only the distances, you should
+ /// store the \ref predMap() "predecessor map" after each iteration
+ /// and build the path manually.
+ ///
+ /// \pre init() must be called and at least one root node should be
+ /// added with addSource() before using this function.
+ void limitedStart(int num) {
+ for (int i = 0; i < num; ++i) {
+ if (processNextRound()) break;
+ }
+ }
+
+ /// \brief Runs the algorithm from the given root node.
+ ///
+ /// This method runs the Bellman-Ford algorithm from the given root
+ /// node \c s in order to compute the shortest path to each node.
+ ///
+ /// The algorithm computes
+ /// - the shortest path tree (forest),
+ /// - the distance of each node from the root(s).
+ ///
+ /// \note bf.run(s) is just a shortcut of the following code.
+ /// \code
+ /// bf.init();
+ /// bf.addSource(s);
+ /// bf.start();
+ /// \endcode
+ void run(Node s) {
+ init();
+ addSource(s);
+ start();
+ }
+
+ /// \brief Runs the algorithm from the given root node with arc
+ /// number limit.
+ ///
+ /// This method runs the Bellman-Ford algorithm from the given root
+ /// node \c s in order to compute the shortest path distance for each
+ /// node using only the paths consisting of at most \c num arcs.
+ ///
+ /// The algorithm computes
+ /// - the limited distance of each node from the root(s),
+ /// - the predecessor arc for each node.
+ ///
+ /// \warning The paths with limited arc number cannot be retrieved
+ /// easily with \ref path() or \ref predArc() functions. If you also
+ /// need the shortest paths and not only the distances, you should
+ /// store the \ref predMap() "predecessor map" after each iteration
+ /// and build the path manually.
+ ///
+ /// \note bf.run(s, num) is just a shortcut of the following code.
+ /// \code
+ /// bf.init();
+ /// bf.addSource(s);
+ /// bf.limitedStart(num);
+ /// \endcode
+ void run(Node s, int num) {
+ init();
+ addSource(s);
+ limitedStart(num);
+ }
+
+ ///@}
+
+ /// \brief LEMON iterator for getting the active nodes.
+ ///
+ /// This class provides a common style LEMON iterator that traverses
+ /// the active nodes of the Bellman-Ford algorithm after the last
+ /// phase. These nodes should be checked in the next phase to
+ /// find augmenting arcs outgoing from them.
+ class ActiveIt {
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor for getting the active nodes of the given BellmanFord
+ /// instance.
+ ActiveIt(const BellmanFord& algorithm) : _algorithm(&algorithm)
+ {
+ _index = _algorithm->_process.size() - 1;
+ }
+
+ /// \brief Invalid constructor.
+ ///
+ /// Invalid constructor.
+ ActiveIt(Invalid) : _algorithm(0), _index(-1) {}
+
+ /// \brief Conversion to \c Node.
+ ///
+ /// Conversion to \c Node.
+ operator Node() const {
+ return _index >= 0 ? _algorithm->_process[_index] : INVALID;
+ }
+
+ /// \brief Increment operator.
+ ///
+ /// Increment operator.
+ ActiveIt& operator++() {
+ --_index;
+ return *this;
+ }
+
+ bool operator==(const ActiveIt& it) const {
+ return static_cast<Node>(*this) == static_cast<Node>(it);
+ }
+ bool operator!=(const ActiveIt& it) const {
+ return static_cast<Node>(*this) != static_cast<Node>(it);
+ }
+ bool operator<(const ActiveIt& it) const {
+ return static_cast<Node>(*this) < static_cast<Node>(it);
+ }
+
+ private:
+ const BellmanFord* _algorithm;
+ int _index;
+ };
+
+ /// \name Query Functions
+ /// The result of the Bellman-Ford algorithm can be obtained using these
+ /// functions.\n
+ /// Either \ref run() or \ref init() should be called before using them.
+
+ ///@{
+
+ /// \brief The shortest path to the given node.
+ ///
+ /// Gives back the shortest path to the given node from the root(s).
+ ///
+ /// \warning \c t should be reached from the root(s).
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ Path path(Node t) const
+ {
+ return Path(*_gr, *_pred, t);
+ }
+
+ /// \brief The distance of the given node from the root(s).
+ ///
+ /// Returns the distance of the given node from the root(s).
+ ///
+ /// \warning If node \c v is not reached from the root(s), then
+ /// the return value of this function is undefined.
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ Value dist(Node v) const { return (*_dist)[v]; }
+
+ /// \brief Returns the 'previous arc' of the shortest path tree for
+ /// the given node.
+ ///
+ /// This function returns the 'previous arc' of the shortest path
+ /// tree for node \c v, i.e. it returns the last arc of a
+ /// shortest path from a root to \c v. It is \c INVALID if \c v
+ /// is not reached from the root(s) or if \c v is a root.
+ ///
+ /// The shortest path tree used here is equal to the shortest path
+ /// tree used in \ref predNode() and \ref predMap().
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ Arc predArc(Node v) const { return (*_pred)[v]; }
+
+ /// \brief Returns the 'previous node' of the shortest path tree for
+ /// the given node.
+ ///
+ /// This function returns the 'previous node' of the shortest path
+ /// tree for node \c v, i.e. it returns the last but one node of
+ /// a shortest path from a root to \c v. It is \c INVALID if \c v
+ /// is not reached from the root(s) or if \c v is a root.
+ ///
+ /// The shortest path tree used here is equal to the shortest path
+ /// tree used in \ref predArc() and \ref predMap().
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ Node predNode(Node v) const {
+ return (*_pred)[v] == INVALID ? INVALID : _gr->source((*_pred)[v]);
+ }
+
+ /// \brief Returns a const reference to the node map that stores the
+ /// distances of the nodes.
+ ///
+ /// Returns a const reference to the node map that stores the distances
+ /// of the nodes calculated by the algorithm.
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ const DistMap &distMap() const { return *_dist;}
+
+ /// \brief Returns a const reference to the node map that stores the
+ /// predecessor arcs.
+ ///
+ /// Returns a const reference to the node map that stores the predecessor
+ /// arcs, which form the shortest path tree (forest).
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ const PredMap &predMap() const { return *_pred; }
+
+ /// \brief Checks if a node is reached from the root(s).
+ ///
+ /// Returns \c true if \c v is reached from the root(s).
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ bool reached(Node v) const {
+ return (*_dist)[v] != OperationTraits::infinity();
+ }
+
+ /// \brief Gives back a negative cycle.
+ ///
+ /// This function gives back a directed cycle with negative total
+ /// length if the algorithm has already found one.
+ /// Otherwise it gives back an empty path.
+ lemon::Path<Digraph> negativeCycle() const {
+ typename Digraph::template NodeMap<int> state(*_gr, -1);
+ lemon::Path<Digraph> cycle;
+ for (int i = 0; i < int(_process.size()); ++i) {
+ if (state[_process[i]] != -1) continue;
+ for (Node v = _process[i]; (*_pred)[v] != INVALID;
+ v = _gr->source((*_pred)[v])) {
+ if (state[v] == i) {
+ cycle.addFront((*_pred)[v]);
+ for (Node u = _gr->source((*_pred)[v]); u != v;
+ u = _gr->source((*_pred)[u])) {
+ cycle.addFront((*_pred)[u]);
+ }
+ return cycle;
+ }
+ else if (state[v] >= 0) {
+ break;
+ }
+ state[v] = i;
+ }
+ }
+ return cycle;
+ }
+
+ ///@}
+ };
+
+ /// \brief Default traits class of bellmanFord() function.
+ ///
+ /// Default traits class of bellmanFord() function.
+ /// \tparam GR The type of the digraph.
+ /// \tparam LEN The type of the length map.
+ template <typename GR, typename LEN>
+ struct BellmanFordWizardDefaultTraits {
+ /// The type of the digraph the algorithm runs on.
+ typedef GR Digraph;
+
+ /// \brief The type of the map that stores the arc lengths.
+ ///
+ /// The type of the map that stores the arc lengths.
+ /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
+ typedef LEN LengthMap;
+
+ /// The type of the arc lengths.
+ typedef typename LEN::Value Value;
+
+ /// \brief Operation traits for Bellman-Ford algorithm.
+ ///
+ /// It defines the used operations and the infinity value for the
+ /// given \c Value type.
+ /// \see BellmanFordDefaultOperationTraits
+ typedef BellmanFordDefaultOperationTraits<Value> OperationTraits;
+
+ /// \brief The type of the map that stores the last
+ /// arcs of the shortest paths.
+ ///
+ /// The type of the map that stores the last arcs of the shortest paths.
+ /// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ typedef typename GR::template NodeMap<typename GR::Arc> PredMap;
+
+ /// \brief Instantiates a \c PredMap.
+ ///
+ /// This function instantiates a \ref PredMap.
+ /// \param g is the digraph to which we would like to define the
+ /// \ref PredMap.
+ static PredMap *createPredMap(const GR &g) {
+ return new PredMap(g);
+ }
+
+ /// \brief The type of the map that stores the distances of the nodes.
+ ///
+ /// The type of the map that stores the distances of the nodes.
+ /// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ typedef typename GR::template NodeMap<Value> DistMap;
+
+ /// \brief Instantiates a \c DistMap.
+ ///
+ /// This function instantiates a \ref DistMap.
+ /// \param g is the digraph to which we would like to define the
+ /// \ref DistMap.
+ static DistMap *createDistMap(const GR &g) {
+ return new DistMap(g);
+ }
+
+ ///The type of the shortest paths.
+
+ ///The type of the shortest paths.
+ ///It must meet the \ref concepts::Path "Path" concept.
+ typedef lemon::Path<Digraph> Path;
+ };
+
+ /// \brief Default traits class used by BellmanFordWizard.
+ ///
+ /// Default traits class used by BellmanFordWizard.
+ /// \tparam GR The type of the digraph.
+ /// \tparam LEN The type of the length map.
+ template <typename GR, typename LEN>
+ class BellmanFordWizardBase
+ : public BellmanFordWizardDefaultTraits<GR, LEN> {
+
+ typedef BellmanFordWizardDefaultTraits<GR, LEN> Base;
+ protected:
+ // Type of the nodes in the digraph.
+ typedef typename Base::Digraph::Node Node;
+
+ // Pointer to the underlying digraph.
+ void *_graph;
+ // Pointer to the length map
+ void *_length;
+ // Pointer to the map of predecessors arcs.
+ void *_pred;
+ // Pointer to the map of distances.
+ void *_dist;
+ //Pointer to the shortest path to the target node.
+ void *_path;
+ //Pointer to the distance of the target node.
+ void *_di;
+
+ public:
+ /// Constructor.
+
+ /// This constructor does not require parameters, it initiates
+ /// all of the attributes to default values \c 0.
+ BellmanFordWizardBase() :
+ _graph(0), _length(0), _pred(0), _dist(0), _path(0), _di(0) {}
+
+ /// Constructor.
+
+ /// This constructor requires two parameters,
+ /// others are initiated to \c 0.
+ /// \param gr The digraph the algorithm runs on.
+ /// \param len The length map.
+ BellmanFordWizardBase(const GR& gr,
+ const LEN& len) :
+ _graph(reinterpret_cast<void*>(const_cast<GR*>(&gr))),
+ _length(reinterpret_cast<void*>(const_cast<LEN*>(&len))),
+ _pred(0), _dist(0), _path(0), _di(0) {}
+
+ };
+
+ /// \brief Auxiliary class for the function-type interface of the
+ /// \ref BellmanFord "Bellman-Ford" algorithm.
+ ///
+ /// This auxiliary class is created to implement the
+ /// \ref bellmanFord() "function-type interface" of the
+ /// \ref BellmanFord "Bellman-Ford" algorithm.
+ /// It does not have own \ref run() method, it uses the
+ /// functions and features of the plain \ref BellmanFord.
+ ///
+ /// This class should only be used through the \ref bellmanFord()
+ /// function, which makes it easier to use the algorithm.
+ ///
+ /// \tparam TR The traits class that defines various types used by the
+ /// algorithm.
+ template<class TR>
+ class BellmanFordWizard : public TR {
+ typedef TR Base;
+
+ typedef typename TR::Digraph Digraph;
+
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::NodeIt NodeIt;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::OutArcIt ArcIt;
+
+ typedef typename TR::LengthMap LengthMap;
+ typedef typename LengthMap::Value Value;
+ typedef typename TR::PredMap PredMap;
+ typedef typename TR::DistMap DistMap;
+ typedef typename TR::Path Path;
+
+ public:
+ /// Constructor.
+ BellmanFordWizard() : TR() {}
+
+ /// \brief Constructor that requires parameters.
+ ///
+ /// Constructor that requires parameters.
+ /// These parameters will be the default values for the traits class.
+ /// \param gr The digraph the algorithm runs on.
+ /// \param len The length map.
+ BellmanFordWizard(const Digraph& gr, const LengthMap& len)
+ : TR(gr, len) {}
+
+ /// \brief Copy constructor
+ BellmanFordWizard(const TR &b) : TR(b) {}
+
+ ~BellmanFordWizard() {}
+
+ /// \brief Runs the Bellman-Ford algorithm from the given source node.
+ ///
+ /// This method runs the Bellman-Ford algorithm from the given source
+ /// node in order to compute the shortest path to each node.
+ void run(Node s) {
+ BellmanFord<Digraph,LengthMap,TR>
+ bf(*reinterpret_cast<const Digraph*>(Base::_graph),
+ *reinterpret_cast<const LengthMap*>(Base::_length));
+ if (Base::_pred) bf.predMap(*reinterpret_cast<PredMap*>(Base::_pred));
+ if (Base::_dist) bf.distMap(*reinterpret_cast<DistMap*>(Base::_dist));
+ bf.run(s);
+ }
+
+ /// \brief Runs the Bellman-Ford algorithm to find the shortest path
+ /// between \c s and \c t.
+ ///
+ /// This method runs the Bellman-Ford algorithm from node \c s
+ /// in order to compute the shortest path to node \c t.
+ /// Actually, it computes the shortest path to each node, but using
+ /// this function you can retrieve the distance and the shortest path
+ /// for a single target node easier.
+ ///
+ /// \return \c true if \c t is reachable form \c s.
+ bool run(Node s, Node t) {
+ BellmanFord<Digraph,LengthMap,TR>
+ bf(*reinterpret_cast<const Digraph*>(Base::_graph),
+ *reinterpret_cast<const LengthMap*>(Base::_length));
+ if (Base::_pred) bf.predMap(*reinterpret_cast<PredMap*>(Base::_pred));
+ if (Base::_dist) bf.distMap(*reinterpret_cast<DistMap*>(Base::_dist));
+ bf.run(s);
+ if (Base::_path) *reinterpret_cast<Path*>(Base::_path) = bf.path(t);
+ if (Base::_di) *reinterpret_cast<Value*>(Base::_di) = bf.dist(t);
+ return bf.reached(t);
+ }
+
+ template<class T>
+ struct SetPredMapBase : public Base {
+ typedef T PredMap;
+ static PredMap *createPredMap(const Digraph &) { return 0; };
+ SetPredMapBase(const TR &b) : TR(b) {}
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// the predecessor map.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting
+ /// the map that stores the predecessor arcs of the nodes.
+ template<class T>
+ BellmanFordWizard<SetPredMapBase<T> > predMap(const T &t) {
+ Base::_pred=reinterpret_cast<void*>(const_cast<T*>(&t));
+ return BellmanFordWizard<SetPredMapBase<T> >(*this);
+ }
+
+ template<class T>
+ struct SetDistMapBase : public Base {
+ typedef T DistMap;
+ static DistMap *createDistMap(const Digraph &) { return 0; };
+ SetDistMapBase(const TR &b) : TR(b) {}
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// the distance map.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting
+ /// the map that stores the distances of the nodes calculated
+ /// by the algorithm.
+ template<class T>
+ BellmanFordWizard<SetDistMapBase<T> > distMap(const T &t) {
+ Base::_dist=reinterpret_cast<void*>(const_cast<T*>(&t));
+ return BellmanFordWizard<SetDistMapBase<T> >(*this);
+ }
+
+ template<class T>
+ struct SetPathBase : public Base {
+ typedef T Path;
+ SetPathBase(const TR &b) : TR(b) {}
+ };
+
+ /// \brief \ref named-func-param "Named parameter" for getting
+ /// the shortest path to the target node.
+ ///
+ /// \ref named-func-param "Named parameter" for getting
+ /// the shortest path to the target node.
+ template<class T>
+ BellmanFordWizard<SetPathBase<T> > path(const T &t)
+ {
+ Base::_path=reinterpret_cast<void*>(const_cast<T*>(&t));
+ return BellmanFordWizard<SetPathBase<T> >(*this);
+ }
+
+ /// \brief \ref named-func-param "Named parameter" for getting
+ /// the distance of the target node.
+ ///
+ /// \ref named-func-param "Named parameter" for getting
+ /// the distance of the target node.
+ BellmanFordWizard dist(const Value &d)
+ {
+ Base::_di=reinterpret_cast<void*>(const_cast<Value*>(&d));
+ return *this;
+ }
+
+ };
+
+ /// \brief Function type interface for the \ref BellmanFord "Bellman-Ford"
+ /// algorithm.
+ ///
+ /// \ingroup shortest_path
+ /// Function type interface for the \ref BellmanFord "Bellman-Ford"
+ /// algorithm.
+ ///
+ /// This function also has several \ref named-templ-func-param
+ /// "named parameters", they are declared as the members of class
+ /// \ref BellmanFordWizard.
+ /// The following examples show how to use these parameters.
+ /// \code
+ /// // Compute shortest path from node s to each node
+ /// bellmanFord(g,length).predMap(preds).distMap(dists).run(s);
+ ///
+ /// // Compute shortest path from s to t
+ /// bool reached = bellmanFord(g,length).path(p).dist(d).run(s,t);
+ /// \endcode
+ /// \warning Don't forget to put the \ref BellmanFordWizard::run() "run()"
+ /// to the end of the parameter list.
+ /// \sa BellmanFordWizard
+ /// \sa BellmanFord
+ template<typename GR, typename LEN>
+ BellmanFordWizard<BellmanFordWizardBase<GR,LEN> >
+ bellmanFord(const GR& digraph,
+ const LEN& length)
+ {
+ return BellmanFordWizard<BellmanFordWizardBase<GR,LEN> >(digraph, length);
+ }
+
+} //END OF NAMESPACE LEMON
+
+#endif
+
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bfs.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bfs.h
new file mode 100644
index 00000000000..e5f4e5c5a31
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bfs.h
@@ -0,0 +1,1754 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BFS_H
+#define LEMON_BFS_H
+
+///\ingroup search
+///\file
+///\brief BFS algorithm.
+
+#include <lemon/list_graph.h>
+#include <lemon/bits/path_dump.h>
+#include <lemon/core.h>
+#include <lemon/error.h>
+#include <lemon/maps.h>
+#include <lemon/path.h>
+
+namespace lemon {
+
+ ///Default traits class of Bfs class.
+
+ ///Default traits class of Bfs class.
+ ///\tparam GR Digraph type.
+ template<class GR>
+ struct BfsDefaultTraits
+ {
+ ///The type of the digraph the algorithm runs on.
+ typedef GR Digraph;
+
+ ///\brief The type of the map that stores the predecessor
+ ///arcs of the shortest paths.
+ ///
+ ///The type of the map that stores the predecessor
+ ///arcs of the shortest paths.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ typedef typename Digraph::template NodeMap<typename Digraph::Arc> PredMap;
+ ///Instantiates a \c PredMap.
+
+ ///This function instantiates a \ref PredMap.
+ ///\param g is the digraph, to which we would like to define the
+ ///\ref PredMap.
+ static PredMap *createPredMap(const Digraph &g)
+ {
+ return new PredMap(g);
+ }
+
+ ///The type of the map that indicates which nodes are processed.
+
+ ///The type of the map that indicates which nodes are processed.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ ///By default, it is a NullMap.
+ typedef NullMap<typename Digraph::Node,bool> ProcessedMap;
+ ///Instantiates a \c ProcessedMap.
+
+ ///This function instantiates a \ref ProcessedMap.
+ ///\param g is the digraph, to which
+ ///we would like to define the \ref ProcessedMap
+#ifdef DOXYGEN
+ static ProcessedMap *createProcessedMap(const Digraph &g)
+#else
+ static ProcessedMap *createProcessedMap(const Digraph &)
+#endif
+ {
+ return new ProcessedMap();
+ }
+
+ ///The type of the map that indicates which nodes are reached.
+
+ ///The type of the map that indicates which nodes are reached.
+ ///It must conform to
+ ///the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
+ typedef typename Digraph::template NodeMap<bool> ReachedMap;
+ ///Instantiates a \c ReachedMap.
+
+ ///This function instantiates a \ref ReachedMap.
+ ///\param g is the digraph, to which
+ ///we would like to define the \ref ReachedMap.
+ static ReachedMap *createReachedMap(const Digraph &g)
+ {
+ return new ReachedMap(g);
+ }
+
+ ///The type of the map that stores the distances of the nodes.
+
+ ///The type of the map that stores the distances of the nodes.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ typedef typename Digraph::template NodeMap<int> DistMap;
+ ///Instantiates a \c DistMap.
+
+ ///This function instantiates a \ref DistMap.
+ ///\param g is the digraph, to which we would like to define the
+ ///\ref DistMap.
+ static DistMap *createDistMap(const Digraph &g)
+ {
+ return new DistMap(g);
+ }
+ };
+
+ ///%BFS algorithm class.
+
+ ///\ingroup search
+ ///This class provides an efficient implementation of the %BFS algorithm.
+ ///
+ ///There is also a \ref bfs() "function-type interface" for the BFS
+ ///algorithm, which is convenient in the simplier cases and it can be
+ ///used easier.
+ ///
+ ///\tparam GR The type of the digraph the algorithm runs on.
+ ///The default type is \ref ListDigraph.
+ ///\tparam TR The traits class that defines various types used by the
+ ///algorithm. By default, it is \ref BfsDefaultTraits
+ ///"BfsDefaultTraits<GR>".
+ ///In most cases, this parameter should not be set directly,
+ ///consider to use the named template parameters instead.
+#ifdef DOXYGEN
+ template <typename GR,
+ typename TR>
+#else
+ template <typename GR=ListDigraph,
+ typename TR=BfsDefaultTraits<GR> >
+#endif
+ class Bfs {
+ public:
+
+ ///The type of the digraph the algorithm runs on.
+ typedef typename TR::Digraph Digraph;
+
+ ///\brief The type of the map that stores the predecessor arcs of the
+ ///shortest paths.
+ typedef typename TR::PredMap PredMap;
+ ///The type of the map that stores the distances of the nodes.
+ typedef typename TR::DistMap DistMap;
+ ///The type of the map that indicates which nodes are reached.
+ typedef typename TR::ReachedMap ReachedMap;
+ ///The type of the map that indicates which nodes are processed.
+ typedef typename TR::ProcessedMap ProcessedMap;
+ ///The type of the paths.
+ typedef PredMapPath<Digraph, PredMap> Path;
+
+ ///The \ref lemon::BfsDefaultTraits "traits class" of the algorithm.
+ typedef TR Traits;
+
+ private:
+
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::NodeIt NodeIt;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::OutArcIt OutArcIt;
+
+ //Pointer to the underlying digraph.
+ const Digraph *G;
+ //Pointer to the map of predecessor arcs.
+ PredMap *_pred;
+ //Indicates if _pred is locally allocated (true) or not.
+ bool local_pred;
+ //Pointer to the map of distances.
+ DistMap *_dist;
+ //Indicates if _dist is locally allocated (true) or not.
+ bool local_dist;
+ //Pointer to the map of reached status of the nodes.
+ ReachedMap *_reached;
+ //Indicates if _reached is locally allocated (true) or not.
+ bool local_reached;
+ //Pointer to the map of processed status of the nodes.
+ ProcessedMap *_processed;
+ //Indicates if _processed is locally allocated (true) or not.
+ bool local_processed;
+
+ std::vector<typename Digraph::Node> _queue;
+ int _queue_head,_queue_tail,_queue_next_dist;
+ int _curr_dist;
+
+ //Creates the maps if necessary.
+ void create_maps()
+ {
+ if(!_pred) {
+ local_pred = true;
+ _pred = Traits::createPredMap(*G);
+ }
+ if(!_dist) {
+ local_dist = true;
+ _dist = Traits::createDistMap(*G);
+ }
+ if(!_reached) {
+ local_reached = true;
+ _reached = Traits::createReachedMap(*G);
+ }
+ if(!_processed) {
+ local_processed = true;
+ _processed = Traits::createProcessedMap(*G);
+ }
+ }
+
+ protected:
+
+ Bfs() {}
+
+ public:
+
+ typedef Bfs Create;
+
+ ///\name Named Template Parameters
+
+ ///@{
+
+ template <class T>
+ struct SetPredMapTraits : public Traits {
+ typedef T PredMap;
+ static PredMap *createPredMap(const Digraph &)
+ {
+ LEMON_ASSERT(false, "PredMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///\c PredMap type.
+ ///
+ ///\ref named-templ-param "Named parameter" for setting
+ ///\c PredMap type.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ template <class T>
+ struct SetPredMap : public Bfs< Digraph, SetPredMapTraits<T> > {
+ typedef Bfs< Digraph, SetPredMapTraits<T> > Create;
+ };
+
+ template <class T>
+ struct SetDistMapTraits : public Traits {
+ typedef T DistMap;
+ static DistMap *createDistMap(const Digraph &)
+ {
+ LEMON_ASSERT(false, "DistMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///\c DistMap type.
+ ///
+ ///\ref named-templ-param "Named parameter" for setting
+ ///\c DistMap type.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ template <class T>
+ struct SetDistMap : public Bfs< Digraph, SetDistMapTraits<T> > {
+ typedef Bfs< Digraph, SetDistMapTraits<T> > Create;
+ };
+
+ template <class T>
+ struct SetReachedMapTraits : public Traits {
+ typedef T ReachedMap;
+ static ReachedMap *createReachedMap(const Digraph &)
+ {
+ LEMON_ASSERT(false, "ReachedMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///\c ReachedMap type.
+ ///
+ ///\ref named-templ-param "Named parameter" for setting
+ ///\c ReachedMap type.
+ ///It must conform to
+ ///the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
+ template <class T>
+ struct SetReachedMap : public Bfs< Digraph, SetReachedMapTraits<T> > {
+ typedef Bfs< Digraph, SetReachedMapTraits<T> > Create;
+ };
+
+ template <class T>
+ struct SetProcessedMapTraits : public Traits {
+ typedef T ProcessedMap;
+ static ProcessedMap *createProcessedMap(const Digraph &)
+ {
+ LEMON_ASSERT(false, "ProcessedMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///\c ProcessedMap type.
+ ///
+ ///\ref named-templ-param "Named parameter" for setting
+ ///\c ProcessedMap type.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ template <class T>
+ struct SetProcessedMap : public Bfs< Digraph, SetProcessedMapTraits<T> > {
+ typedef Bfs< Digraph, SetProcessedMapTraits<T> > Create;
+ };
+
+ struct SetStandardProcessedMapTraits : public Traits {
+ typedef typename Digraph::template NodeMap<bool> ProcessedMap;
+ static ProcessedMap *createProcessedMap(const Digraph &g)
+ {
+ return new ProcessedMap(g);
+ return 0; // ignore warnings
+ }
+ };
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///\c ProcessedMap type to be <tt>Digraph::NodeMap<bool></tt>.
+ ///
+ ///\ref named-templ-param "Named parameter" for setting
+ ///\c ProcessedMap type to be <tt>Digraph::NodeMap<bool></tt>.
+ ///If you don't set it explicitly, it will be automatically allocated.
+ struct SetStandardProcessedMap :
+ public Bfs< Digraph, SetStandardProcessedMapTraits > {
+ typedef Bfs< Digraph, SetStandardProcessedMapTraits > Create;
+ };
+
+ ///@}
+
+ public:
+
+ ///Constructor.
+
+ ///Constructor.
+ ///\param g The digraph the algorithm runs on.
+ Bfs(const Digraph &g) :
+ G(&g),
+ _pred(NULL), local_pred(false),
+ _dist(NULL), local_dist(false),
+ _reached(NULL), local_reached(false),
+ _processed(NULL), local_processed(false)
+ { }
+
+ ///Destructor.
+ ~Bfs()
+ {
+ if(local_pred) delete _pred;
+ if(local_dist) delete _dist;
+ if(local_reached) delete _reached;
+ if(local_processed) delete _processed;
+ }
+
+ ///Sets the map that stores the predecessor arcs.
+
+ ///Sets the map that stores the predecessor arcs.
+ ///If you don't use this function before calling \ref run(Node) "run()"
+ ///or \ref init(), an instance will be allocated automatically.
+ ///The destructor deallocates this automatically allocated map,
+ ///of course.
+ ///\return <tt> (*this) </tt>
+ Bfs &predMap(PredMap &m)
+ {
+ if(local_pred) {
+ delete _pred;
+ local_pred=false;
+ }
+ _pred = &m;
+ return *this;
+ }
+
+ ///Sets the map that indicates which nodes are reached.
+
+ ///Sets the map that indicates which nodes are reached.
+ ///If you don't use this function before calling \ref run(Node) "run()"
+ ///or \ref init(), an instance will be allocated automatically.
+ ///The destructor deallocates this automatically allocated map,
+ ///of course.
+ ///\return <tt> (*this) </tt>
+ Bfs &reachedMap(ReachedMap &m)
+ {
+ if(local_reached) {
+ delete _reached;
+ local_reached=false;
+ }
+ _reached = &m;
+ return *this;
+ }
+
+ ///Sets the map that indicates which nodes are processed.
+
+ ///Sets the map that indicates which nodes are processed.
+ ///If you don't use this function before calling \ref run(Node) "run()"
+ ///or \ref init(), an instance will be allocated automatically.
+ ///The destructor deallocates this automatically allocated map,
+ ///of course.
+ ///\return <tt> (*this) </tt>
+ Bfs &processedMap(ProcessedMap &m)
+ {
+ if(local_processed) {
+ delete _processed;
+ local_processed=false;
+ }
+ _processed = &m;
+ return *this;
+ }
+
+ ///Sets the map that stores the distances of the nodes.
+
+ ///Sets the map that stores the distances of the nodes calculated by
+ ///the algorithm.
+ ///If you don't use this function before calling \ref run(Node) "run()"
+ ///or \ref init(), an instance will be allocated automatically.
+ ///The destructor deallocates this automatically allocated map,
+ ///of course.
+ ///\return <tt> (*this) </tt>
+ Bfs &distMap(DistMap &m)
+ {
+ if(local_dist) {
+ delete _dist;
+ local_dist=false;
+ }
+ _dist = &m;
+ return *this;
+ }
+
+ public:
+
+ ///\name Execution Control
+ ///The simplest way to execute the BFS algorithm is to use one of the
+ ///member functions called \ref run(Node) "run()".\n
+ ///If you need better control on the execution, you have to call
+ ///\ref init() first, then you can add several source nodes with
+ ///\ref addSource(). Finally the actual path computation can be
+ ///performed with one of the \ref start() functions.
+
+ ///@{
+
+ ///\brief Initializes the internal data structures.
+ ///
+ ///Initializes the internal data structures.
+ void init()
+ {
+ create_maps();
+ _queue.resize(countNodes(*G));
+ _queue_head=_queue_tail=0;
+ _curr_dist=1;
+ for ( NodeIt u(*G) ; u!=INVALID ; ++u ) {
+ _pred->set(u,INVALID);
+ _reached->set(u,false);
+ _processed->set(u,false);
+ }
+ }
+
+ ///Adds a new source node.
+
+ ///Adds a new source node to the set of nodes to be processed.
+ ///
+ void addSource(Node s)
+ {
+ if(!(*_reached)[s])
+ {
+ _reached->set(s,true);
+ _pred->set(s,INVALID);
+ _dist->set(s,0);
+ _queue[_queue_head++]=s;
+ _queue_next_dist=_queue_head;
+ }
+ }
+
+ ///Processes the next node.
+
+ ///Processes the next node.
+ ///
+ ///\return The processed node.
+ ///
+ ///\pre The queue must not be empty.
+ Node processNextNode()
+ {
+ if(_queue_tail==_queue_next_dist) {
+ _curr_dist++;
+ _queue_next_dist=_queue_head;
+ }
+ Node n=_queue[_queue_tail++];
+ _processed->set(n,true);
+ Node m;
+ for(OutArcIt e(*G,n);e!=INVALID;++e)
+ if(!(*_reached)[m=G->target(e)]) {
+ _queue[_queue_head++]=m;
+ _reached->set(m,true);
+ _pred->set(m,e);
+ _dist->set(m,_curr_dist);
+ }
+ return n;
+ }
+
+ ///Processes the next node.
+
+ ///Processes the next node and checks if the given target node
+ ///is reached. If the target node is reachable from the processed
+ ///node, then the \c reach parameter will be set to \c true.
+ ///
+ ///\param target The target node.
+ ///\retval reach Indicates if the target node is reached.
+ ///It should be initially \c false.
+ ///
+ ///\return The processed node.
+ ///
+ ///\pre The queue must not be empty.
+ Node processNextNode(Node target, bool& reach)
+ {
+ if(_queue_tail==_queue_next_dist) {
+ _curr_dist++;
+ _queue_next_dist=_queue_head;
+ }
+ Node n=_queue[_queue_tail++];
+ _processed->set(n,true);
+ Node m;
+ for(OutArcIt e(*G,n);e!=INVALID;++e)
+ if(!(*_reached)[m=G->target(e)]) {
+ _queue[_queue_head++]=m;
+ _reached->set(m,true);
+ _pred->set(m,e);
+ _dist->set(m,_curr_dist);
+ reach = reach || (target == m);
+ }
+ return n;
+ }
+
+ ///Processes the next node.
+
+ ///Processes the next node and checks if at least one of reached
+ ///nodes has \c true value in the \c nm node map. If one node
+ ///with \c true value is reachable from the processed node, then the
+ ///\c rnode parameter will be set to the first of such nodes.
+ ///
+ ///\param nm A \c bool (or convertible) node map that indicates the
+ ///possible targets.
+ ///\retval rnode The reached target node.
+ ///It should be initially \c INVALID.
+ ///
+ ///\return The processed node.
+ ///
+ ///\pre The queue must not be empty.
+ template<class NM>
+ Node processNextNode(const NM& nm, Node& rnode)
+ {
+ if(_queue_tail==_queue_next_dist) {
+ _curr_dist++;
+ _queue_next_dist=_queue_head;
+ }
+ Node n=_queue[_queue_tail++];
+ _processed->set(n,true);
+ Node m;
+ for(OutArcIt e(*G,n);e!=INVALID;++e)
+ if(!(*_reached)[m=G->target(e)]) {
+ _queue[_queue_head++]=m;
+ _reached->set(m,true);
+ _pred->set(m,e);
+ _dist->set(m,_curr_dist);
+ if (nm[m] && rnode == INVALID) rnode = m;
+ }
+ return n;
+ }
+
+ ///The next node to be processed.
+
+ ///Returns the next node to be processed or \c INVALID if the queue
+ ///is empty.
+ Node nextNode() const
+ {
+ return _queue_tail<_queue_head?_queue[_queue_tail]:INVALID;
+ }
+
+ ///Returns \c false if there are nodes to be processed.
+
+ ///Returns \c false if there are nodes to be processed
+ ///in the queue.
+ bool emptyQueue() const { return _queue_tail==_queue_head; }
+
+ ///Returns the number of the nodes to be processed.
+
+ ///Returns the number of the nodes to be processed
+ ///in the queue.
+ int queueSize() const { return _queue_head-_queue_tail; }
+
+ ///Executes the algorithm.
+
+ ///Executes the algorithm.
+ ///
+ ///This method runs the %BFS algorithm from the root node(s)
+ ///in order to compute the shortest path to each node.
+ ///
+ ///The algorithm computes
+ ///- the shortest path tree (forest),
+ ///- the distance of each node from the root(s).
+ ///
+ ///\pre init() must be called and at least one root node should be
+ ///added with addSource() before using this function.
+ ///
+ ///\note <tt>b.start()</tt> is just a shortcut of the following code.
+ ///\code
+ /// while ( !b.emptyQueue() ) {
+ /// b.processNextNode();
+ /// }
+ ///\endcode
+ void start()
+ {
+ while ( !emptyQueue() ) processNextNode();
+ }
+
+ ///Executes the algorithm until the given target node is reached.
+
+ ///Executes the algorithm until the given target node is reached.
+ ///
+ ///This method runs the %BFS algorithm from the root node(s)
+ ///in order to compute the shortest path to \c t.
+ ///
+ ///The algorithm computes
+ ///- the shortest path to \c t,
+ ///- the distance of \c t from the root(s).
+ ///
+ ///\pre init() must be called and at least one root node should be
+ ///added with addSource() before using this function.
+ ///
+ ///\note <tt>b.start(t)</tt> is just a shortcut of the following code.
+ ///\code
+ /// bool reach = false;
+ /// while ( !b.emptyQueue() && !reach ) {
+ /// b.processNextNode(t, reach);
+ /// }
+ ///\endcode
+ void start(Node t)
+ {
+ bool reach = false;
+ while ( !emptyQueue() && !reach ) processNextNode(t, reach);
+ }
+
+ ///Executes the algorithm until a condition is met.
+
+ ///Executes the algorithm until a condition is met.
+ ///
+ ///This method runs the %BFS algorithm from the root node(s) in
+ ///order to compute the shortest path to a node \c v with
+ /// <tt>nm[v]</tt> true, if such a node can be found.
+ ///
+ ///\param nm A \c bool (or convertible) node map. The algorithm
+ ///will stop when it reaches a node \c v with <tt>nm[v]</tt> true.
+ ///
+ ///\return The reached node \c v with <tt>nm[v]</tt> true or
+ ///\c INVALID if no such node was found.
+ ///
+ ///\pre init() must be called and at least one root node should be
+ ///added with addSource() before using this function.
+ ///
+ ///\note <tt>b.start(nm)</tt> is just a shortcut of the following code.
+ ///\code
+ /// Node rnode = INVALID;
+ /// while ( !b.emptyQueue() && rnode == INVALID ) {
+ /// b.processNextNode(nm, rnode);
+ /// }
+ /// return rnode;
+ ///\endcode
+ template<class NodeBoolMap>
+ Node start(const NodeBoolMap &nm)
+ {
+ Node rnode = INVALID;
+ while ( !emptyQueue() && rnode == INVALID ) {
+ processNextNode(nm, rnode);
+ }
+ return rnode;
+ }
+
+ ///Runs the algorithm from the given source node.
+
+ ///This method runs the %BFS algorithm from node \c s
+ ///in order to compute the shortest path to each node.
+ ///
+ ///The algorithm computes
+ ///- the shortest path tree,
+ ///- the distance of each node from the root.
+ ///
+ ///\note <tt>b.run(s)</tt> is just a shortcut of the following code.
+ ///\code
+ /// b.init();
+ /// b.addSource(s);
+ /// b.start();
+ ///\endcode
+ void run(Node s) {
+ init();
+ addSource(s);
+ start();
+ }
+
+ ///Finds the shortest path between \c s and \c t.
+
+ ///This method runs the %BFS algorithm from node \c s
+ ///in order to compute the shortest path to node \c t
+ ///(it stops searching when \c t is processed).
+ ///
+ ///\return \c true if \c t is reachable form \c s.
+ ///
+ ///\note Apart from the return value, <tt>b.run(s,t)</tt> is just a
+ ///shortcut of the following code.
+ ///\code
+ /// b.init();
+ /// b.addSource(s);
+ /// b.start(t);
+ ///\endcode
+ bool run(Node s,Node t) {
+ init();
+ addSource(s);
+ start(t);
+ return reached(t);
+ }
+
+ ///Runs the algorithm to visit all nodes in the digraph.
+
+ ///This method runs the %BFS algorithm in order to visit all nodes
+ ///in the digraph.
+ ///
+ ///\note <tt>b.run(s)</tt> is just a shortcut of the following code.
+ ///\code
+ /// b.init();
+ /// for (NodeIt n(gr); n != INVALID; ++n) {
+ /// if (!b.reached(n)) {
+ /// b.addSource(n);
+ /// b.start();
+ /// }
+ /// }
+ ///\endcode
+ void run() {
+ init();
+ for (NodeIt n(*G); n != INVALID; ++n) {
+ if (!reached(n)) {
+ addSource(n);
+ start();
+ }
+ }
+ }
+
+ ///@}
+
+ ///\name Query Functions
+ ///The results of the BFS algorithm can be obtained using these
+ ///functions.\n
+ ///Either \ref run(Node) "run()" or \ref start() should be called
+ ///before using them.
+
+ ///@{
+
+ ///The shortest path to the given node.
+
+ ///Returns the shortest path to the given node from the root(s).
+ ///
+ ///\warning \c t should be reached from the root(s).
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ Path path(Node t) const { return Path(*G, *_pred, t); }
+
+ ///The distance of the given node from the root(s).
+
+ ///Returns the distance of the given node from the root(s).
+ ///
+ ///\warning If node \c v is not reached from the root(s), then
+ ///the return value of this function is undefined.
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ int dist(Node v) const { return (*_dist)[v]; }
+
+ ///\brief Returns the 'previous arc' of the shortest path tree for
+ ///the given node.
+ ///
+ ///This function returns the 'previous arc' of the shortest path
+ ///tree for the node \c v, i.e. it returns the last arc of a
+ ///shortest path from a root to \c v. It is \c INVALID if \c v
+ ///is not reached from the root(s) or if \c v is a root.
+ ///
+ ///The shortest path tree used here is equal to the shortest path
+ ///tree used in \ref predNode() and \ref predMap().
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ Arc predArc(Node v) const { return (*_pred)[v];}
+
+ ///\brief Returns the 'previous node' of the shortest path tree for
+ ///the given node.
+ ///
+ ///This function returns the 'previous node' of the shortest path
+ ///tree for the node \c v, i.e. it returns the last but one node
+ ///of a shortest path from a root to \c v. It is \c INVALID
+ ///if \c v is not reached from the root(s) or if \c v is a root.
+ ///
+ ///The shortest path tree used here is equal to the shortest path
+ ///tree used in \ref predArc() and \ref predMap().
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID:
+ G->source((*_pred)[v]); }
+
+ ///\brief Returns a const reference to the node map that stores the
+ /// distances of the nodes.
+ ///
+ ///Returns a const reference to the node map that stores the distances
+ ///of the nodes calculated by the algorithm.
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ const DistMap &distMap() const { return *_dist;}
+
+ ///\brief Returns a const reference to the node map that stores the
+ ///predecessor arcs.
+ ///
+ ///Returns a const reference to the node map that stores the predecessor
+ ///arcs, which form the shortest path tree (forest).
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ const PredMap &predMap() const { return *_pred;}
+
+ ///Checks if the given node is reached from the root(s).
+
+ ///Returns \c true if \c v is reached from the root(s).
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ bool reached(Node v) const { return (*_reached)[v]; }
+
+ ///@}
+ };
+
+ ///Default traits class of bfs() function.
+
+ ///Default traits class of bfs() function.
+ ///\tparam GR Digraph type.
+ template<class GR>
+ struct BfsWizardDefaultTraits
+ {
+ ///The type of the digraph the algorithm runs on.
+ typedef GR Digraph;
+
+ ///\brief The type of the map that stores the predecessor
+ ///arcs of the shortest paths.
+ ///
+ ///The type of the map that stores the predecessor
+ ///arcs of the shortest paths.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ typedef typename Digraph::template NodeMap<typename Digraph::Arc> PredMap;
+ ///Instantiates a PredMap.
+
+ ///This function instantiates a PredMap.
+ ///\param g is the digraph, to which we would like to define the
+ ///PredMap.
+ static PredMap *createPredMap(const Digraph &g)
+ {
+ return new PredMap(g);
+ }
+
+ ///The type of the map that indicates which nodes are processed.
+
+ ///The type of the map that indicates which nodes are processed.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ ///By default, it is a NullMap.
+ typedef NullMap<typename Digraph::Node,bool> ProcessedMap;
+ ///Instantiates a ProcessedMap.
+
+ ///This function instantiates a ProcessedMap.
+ ///\param g is the digraph, to which
+ ///we would like to define the ProcessedMap.
+#ifdef DOXYGEN
+ static ProcessedMap *createProcessedMap(const Digraph &g)
+#else
+ static ProcessedMap *createProcessedMap(const Digraph &)
+#endif
+ {
+ return new ProcessedMap();
+ }
+
+ ///The type of the map that indicates which nodes are reached.
+
+ ///The type of the map that indicates which nodes are reached.
+ ///It must conform to
+ ///the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
+ typedef typename Digraph::template NodeMap<bool> ReachedMap;
+ ///Instantiates a ReachedMap.
+
+ ///This function instantiates a ReachedMap.
+ ///\param g is the digraph, to which
+ ///we would like to define the ReachedMap.
+ static ReachedMap *createReachedMap(const Digraph &g)
+ {
+ return new ReachedMap(g);
+ }
+
+ ///The type of the map that stores the distances of the nodes.
+
+ ///The type of the map that stores the distances of the nodes.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ typedef typename Digraph::template NodeMap<int> DistMap;
+ ///Instantiates a DistMap.
+
+ ///This function instantiates a DistMap.
+ ///\param g is the digraph, to which we would like to define
+ ///the DistMap
+ static DistMap *createDistMap(const Digraph &g)
+ {
+ return new DistMap(g);
+ }
+
+ ///The type of the shortest paths.
+
+ ///The type of the shortest paths.
+ ///It must conform to the \ref concepts::Path "Path" concept.
+ typedef lemon::Path<Digraph> Path;
+ };
+
+ /// Default traits class used by BfsWizard
+
+ /// Default traits class used by BfsWizard.
+ /// \tparam GR The type of the digraph.
+ template<class GR>
+ class BfsWizardBase : public BfsWizardDefaultTraits<GR>
+ {
+
+ typedef BfsWizardDefaultTraits<GR> Base;
+ protected:
+ //The type of the nodes in the digraph.
+ typedef typename Base::Digraph::Node Node;
+
+ //Pointer to the digraph the algorithm runs on.
+ void *_g;
+ //Pointer to the map of reached nodes.
+ void *_reached;
+ //Pointer to the map of processed nodes.
+ void *_processed;
+ //Pointer to the map of predecessors arcs.
+ void *_pred;
+ //Pointer to the map of distances.
+ void *_dist;
+ //Pointer to the shortest path to the target node.
+ void *_path;
+ //Pointer to the distance of the target node.
+ int *_di;
+
+ public:
+ /// Constructor.
+
+ /// This constructor does not require parameters, it initiates
+ /// all of the attributes to \c 0.
+ BfsWizardBase() : _g(0), _reached(0), _processed(0), _pred(0),
+ _dist(0), _path(0), _di(0) {}
+
+ /// Constructor.
+
+ /// This constructor requires one parameter,
+ /// others are initiated to \c 0.
+ /// \param g The digraph the algorithm runs on.
+ BfsWizardBase(const GR &g) :
+ _g(reinterpret_cast<void*>(const_cast<GR*>(&g))),
+ _reached(0), _processed(0), _pred(0), _dist(0), _path(0), _di(0) {}
+
+ };
+
+ /// Auxiliary class for the function-type interface of BFS algorithm.
+
+ /// This auxiliary class is created to implement the
+ /// \ref bfs() "function-type interface" of \ref Bfs algorithm.
+ /// It does not have own \ref run(Node) "run()" method, it uses the
+ /// functions and features of the plain \ref Bfs.
+ ///
+ /// This class should only be used through the \ref bfs() function,
+ /// which makes it easier to use the algorithm.
+ ///
+ /// \tparam TR The traits class that defines various types used by the
+ /// algorithm.
+ template<class TR>
+ class BfsWizard : public TR
+ {
+ typedef TR Base;
+
+ typedef typename TR::Digraph Digraph;
+
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::NodeIt NodeIt;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::OutArcIt OutArcIt;
+
+ typedef typename TR::PredMap PredMap;
+ typedef typename TR::DistMap DistMap;
+ typedef typename TR::ReachedMap ReachedMap;
+ typedef typename TR::ProcessedMap ProcessedMap;
+ typedef typename TR::Path Path;
+
+ public:
+
+ /// Constructor.
+ BfsWizard() : TR() {}
+
+ /// Constructor that requires parameters.
+
+ /// Constructor that requires parameters.
+ /// These parameters will be the default values for the traits class.
+ /// \param g The digraph the algorithm runs on.
+ BfsWizard(const Digraph &g) :
+ TR(g) {}
+
+ ///Copy constructor
+ BfsWizard(const TR &b) : TR(b) {}
+
+ ~BfsWizard() {}
+
+ ///Runs BFS algorithm from the given source node.
+
+ ///This method runs BFS algorithm from node \c s
+ ///in order to compute the shortest path to each node.
+ void run(Node s)
+ {
+ Bfs<Digraph,TR> alg(*reinterpret_cast<const Digraph*>(Base::_g));
+ if (Base::_pred)
+ alg.predMap(*reinterpret_cast<PredMap*>(Base::_pred));
+ if (Base::_dist)
+ alg.distMap(*reinterpret_cast<DistMap*>(Base::_dist));
+ if (Base::_reached)
+ alg.reachedMap(*reinterpret_cast<ReachedMap*>(Base::_reached));
+ if (Base::_processed)
+ alg.processedMap(*reinterpret_cast<ProcessedMap*>(Base::_processed));
+ if (s!=INVALID)
+ alg.run(s);
+ else
+ alg.run();
+ }
+
+ ///Finds the shortest path between \c s and \c t.
+
+ ///This method runs BFS algorithm from node \c s
+ ///in order to compute the shortest path to node \c t
+ ///(it stops searching when \c t is processed).
+ ///
+ ///\return \c true if \c t is reachable form \c s.
+ bool run(Node s, Node t)
+ {
+ Bfs<Digraph,TR> alg(*reinterpret_cast<const Digraph*>(Base::_g));
+ if (Base::_pred)
+ alg.predMap(*reinterpret_cast<PredMap*>(Base::_pred));
+ if (Base::_dist)
+ alg.distMap(*reinterpret_cast<DistMap*>(Base::_dist));
+ if (Base::_reached)
+ alg.reachedMap(*reinterpret_cast<ReachedMap*>(Base::_reached));
+ if (Base::_processed)
+ alg.processedMap(*reinterpret_cast<ProcessedMap*>(Base::_processed));
+ alg.run(s,t);
+ if (Base::_path)
+ *reinterpret_cast<Path*>(Base::_path) = alg.path(t);
+ if (Base::_di)
+ *Base::_di = alg.dist(t);
+ return alg.reached(t);
+ }
+
+ ///Runs BFS algorithm to visit all nodes in the digraph.
+
+ ///This method runs BFS algorithm in order to visit all nodes
+ ///in the digraph.
+ void run()
+ {
+ run(INVALID);
+ }
+
+ template<class T>
+ struct SetPredMapBase : public Base {
+ typedef T PredMap;
+ static PredMap *createPredMap(const Digraph &) { return 0; };
+ SetPredMapBase(const TR &b) : TR(b) {}
+ };
+
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///the predecessor map.
+ ///
+ ///\ref named-templ-param "Named parameter" function for setting
+ ///the map that stores the predecessor arcs of the nodes.
+ template<class T>
+ BfsWizard<SetPredMapBase<T> > predMap(const T &t)
+ {
+ Base::_pred=reinterpret_cast<void*>(const_cast<T*>(&t));
+ return BfsWizard<SetPredMapBase<T> >(*this);
+ }
+
+ template<class T>
+ struct SetReachedMapBase : public Base {
+ typedef T ReachedMap;
+ static ReachedMap *createReachedMap(const Digraph &) { return 0; };
+ SetReachedMapBase(const TR &b) : TR(b) {}
+ };
+
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///the reached map.
+ ///
+ ///\ref named-templ-param "Named parameter" function for setting
+ ///the map that indicates which nodes are reached.
+ template<class T>
+ BfsWizard<SetReachedMapBase<T> > reachedMap(const T &t)
+ {
+ Base::_reached=reinterpret_cast<void*>(const_cast<T*>(&t));
+ return BfsWizard<SetReachedMapBase<T> >(*this);
+ }
+
+ template<class T>
+ struct SetDistMapBase : public Base {
+ typedef T DistMap;
+ static DistMap *createDistMap(const Digraph &) { return 0; };
+ SetDistMapBase(const TR &b) : TR(b) {}
+ };
+
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///the distance map.
+ ///
+ ///\ref named-templ-param "Named parameter" function for setting
+ ///the map that stores the distances of the nodes calculated
+ ///by the algorithm.
+ template<class T>
+ BfsWizard<SetDistMapBase<T> > distMap(const T &t)
+ {
+ Base::_dist=reinterpret_cast<void*>(const_cast<T*>(&t));
+ return BfsWizard<SetDistMapBase<T> >(*this);
+ }
+
+ template<class T>
+ struct SetProcessedMapBase : public Base {
+ typedef T ProcessedMap;
+ static ProcessedMap *createProcessedMap(const Digraph &) { return 0; };
+ SetProcessedMapBase(const TR &b) : TR(b) {}
+ };
+
+ ///\brief \ref named-func-param "Named parameter" for setting
+ ///the processed map.
+ ///
+ ///\ref named-templ-param "Named parameter" function for setting
+ ///the map that indicates which nodes are processed.
+ template<class T>
+ BfsWizard<SetProcessedMapBase<T> > processedMap(const T &t)
+ {
+ Base::_processed=reinterpret_cast<void*>(const_cast<T*>(&t));
+ return BfsWizard<SetProcessedMapBase<T> >(*this);
+ }
+
+ template<class T>
+ struct SetPathBase : public Base {
+ typedef T Path;
+ SetPathBase(const TR &b) : TR(b) {}
+ };
+ ///\brief \ref named-func-param "Named parameter"
+ ///for getting the shortest path to the target node.
+ ///
+ ///\ref named-func-param "Named parameter"
+ ///for getting the shortest path to the target node.
+ template<class T>
+ BfsWizard<SetPathBase<T> > path(const T &t)
+ {
+ Base::_path=reinterpret_cast<void*>(const_cast<T*>(&t));
+ return BfsWizard<SetPathBase<T> >(*this);
+ }
+
+ ///\brief \ref named-func-param "Named parameter"
+ ///for getting the distance of the target node.
+ ///
+ ///\ref named-func-param "Named parameter"
+ ///for getting the distance of the target node.
+ BfsWizard dist(const int &d)
+ {
+ Base::_di=const_cast<int*>(&d);
+ return *this;
+ }
+
+ };
+
+ ///Function-type interface for BFS algorithm.
+
+ /// \ingroup search
+ ///Function-type interface for BFS algorithm.
+ ///
+ ///This function also has several \ref named-func-param "named parameters",
+ ///they are declared as the members of class \ref BfsWizard.
+ ///The following examples show how to use these parameters.
+ ///\code
+ /// // Compute shortest path from node s to each node
+ /// bfs(g).predMap(preds).distMap(dists).run(s);
+ ///
+ /// // Compute shortest path from s to t
+ /// bool reached = bfs(g).path(p).dist(d).run(s,t);
+ ///\endcode
+ ///\warning Don't forget to put the \ref BfsWizard::run(Node) "run()"
+ ///to the end of the parameter list.
+ ///\sa BfsWizard
+ ///\sa Bfs
+ template<class GR>
+ BfsWizard<BfsWizardBase<GR> >
+ bfs(const GR &digraph)
+ {
+ return BfsWizard<BfsWizardBase<GR> >(digraph);
+ }
+
+#ifdef DOXYGEN
+ /// \brief Visitor class for BFS.
+ ///
+ /// This class defines the interface of the BfsVisit events, and
+ /// it could be the base of a real visitor class.
+ template <typename GR>
+ struct BfsVisitor {
+ typedef GR Digraph;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::Node Node;
+ /// \brief Called for the source node(s) of the BFS.
+ ///
+ /// This function is called for the source node(s) of the BFS.
+ void start(const Node& node) {}
+ /// \brief Called when a node is reached first time.
+ ///
+ /// This function is called when a node is reached first time.
+ void reach(const Node& node) {}
+ /// \brief Called when a node is processed.
+ ///
+ /// This function is called when a node is processed.
+ void process(const Node& node) {}
+ /// \brief Called when an arc reaches a new node.
+ ///
+ /// This function is called when the BFS finds an arc whose target node
+ /// is not reached yet.
+ void discover(const Arc& arc) {}
+ /// \brief Called when an arc is examined but its target node is
+ /// already discovered.
+ ///
+ /// This function is called when an arc is examined but its target node is
+ /// already discovered.
+ void examine(const Arc& arc) {}
+ };
+#else
+ template <typename GR>
+ struct BfsVisitor {
+ typedef GR Digraph;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::Node Node;
+ void start(const Node&) {}
+ void reach(const Node&) {}
+ void process(const Node&) {}
+ void discover(const Arc&) {}
+ void examine(const Arc&) {}
+
+ template <typename _Visitor>
+ struct Constraints {
+ void constraints() {
+ Arc arc;
+ Node node;
+ visitor.start(node);
+ visitor.reach(node);
+ visitor.process(node);
+ visitor.discover(arc);
+ visitor.examine(arc);
+ }
+ _Visitor& visitor;
+ Constraints() {}
+ };
+ };
+#endif
+
+ /// \brief Default traits class of BfsVisit class.
+ ///
+ /// Default traits class of BfsVisit class.
+ /// \tparam GR The type of the digraph the algorithm runs on.
+ template<class GR>
+ struct BfsVisitDefaultTraits {
+
+ /// \brief The type of the digraph the algorithm runs on.
+ typedef GR Digraph;
+
+ /// \brief The type of the map that indicates which nodes are reached.
+ ///
+ /// The type of the map that indicates which nodes are reached.
+ /// It must conform to
+ ///the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
+ typedef typename Digraph::template NodeMap<bool> ReachedMap;
+
+ /// \brief Instantiates a ReachedMap.
+ ///
+ /// This function instantiates a ReachedMap.
+ /// \param digraph is the digraph, to which
+ /// we would like to define the ReachedMap.
+ static ReachedMap *createReachedMap(const Digraph &digraph) {
+ return new ReachedMap(digraph);
+ }
+
+ };
+
+ /// \ingroup search
+ ///
+ /// \brief BFS algorithm class with visitor interface.
+ ///
+ /// This class provides an efficient implementation of the BFS algorithm
+ /// with visitor interface.
+ ///
+ /// The BfsVisit class provides an alternative interface to the Bfs
+ /// class. It works with callback mechanism, the BfsVisit object calls
+ /// the member functions of the \c Visitor class on every BFS event.
+ ///
+ /// This interface of the BFS algorithm should be used in special cases
+ /// when extra actions have to be performed in connection with certain
+ /// events of the BFS algorithm. Otherwise consider to use Bfs or bfs()
+ /// instead.
+ ///
+ /// \tparam GR The type of the digraph the algorithm runs on.
+ /// The default type is \ref ListDigraph.
+ /// The value of GR is not used directly by \ref BfsVisit,
+ /// it is only passed to \ref BfsVisitDefaultTraits.
+ /// \tparam VS The Visitor type that is used by the algorithm.
+ /// \ref BfsVisitor "BfsVisitor<GR>" is an empty visitor, which
+ /// does not observe the BFS events. If you want to observe the BFS
+ /// events, you should implement your own visitor class.
+ /// \tparam TR The traits class that defines various types used by the
+ /// algorithm. By default, it is \ref BfsVisitDefaultTraits
+ /// "BfsVisitDefaultTraits<GR>".
+ /// In most cases, this parameter should not be set directly,
+ /// consider to use the named template parameters instead.
+#ifdef DOXYGEN
+ template <typename GR, typename VS, typename TR>
+#else
+ template <typename GR = ListDigraph,
+ typename VS = BfsVisitor<GR>,
+ typename TR = BfsVisitDefaultTraits<GR> >
+#endif
+ class BfsVisit {
+ public:
+
+ ///The traits class.
+ typedef TR Traits;
+
+ ///The type of the digraph the algorithm runs on.
+ typedef typename Traits::Digraph Digraph;
+
+ ///The visitor type used by the algorithm.
+ typedef VS Visitor;
+
+ ///The type of the map that indicates which nodes are reached.
+ typedef typename Traits::ReachedMap ReachedMap;
+
+ private:
+
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::NodeIt NodeIt;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::OutArcIt OutArcIt;
+
+ //Pointer to the underlying digraph.
+ const Digraph *_digraph;
+ //Pointer to the visitor object.
+ Visitor *_visitor;
+ //Pointer to the map of reached status of the nodes.
+ ReachedMap *_reached;
+ //Indicates if _reached is locally allocated (true) or not.
+ bool local_reached;
+
+ std::vector<typename Digraph::Node> _list;
+ int _list_front, _list_back;
+
+ //Creates the maps if necessary.
+ void create_maps() {
+ if(!_reached) {
+ local_reached = true;
+ _reached = Traits::createReachedMap(*_digraph);
+ }
+ }
+
+ protected:
+
+ BfsVisit() {}
+
+ public:
+
+ typedef BfsVisit Create;
+
+ /// \name Named Template Parameters
+
+ ///@{
+ template <class T>
+ struct SetReachedMapTraits : public Traits {
+ typedef T ReachedMap;
+ static ReachedMap *createReachedMap(const Digraph &digraph) {
+ LEMON_ASSERT(false, "ReachedMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// ReachedMap type.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting ReachedMap type.
+ template <class T>
+ struct SetReachedMap : public BfsVisit< Digraph, Visitor,
+ SetReachedMapTraits<T> > {
+ typedef BfsVisit< Digraph, Visitor, SetReachedMapTraits<T> > Create;
+ };
+ ///@}
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ ///
+ /// \param digraph The digraph the algorithm runs on.
+ /// \param visitor The visitor object of the algorithm.
+ BfsVisit(const Digraph& digraph, Visitor& visitor)
+ : _digraph(&digraph), _visitor(&visitor),
+ _reached(0), local_reached(false) {}
+
+ /// \brief Destructor.
+ ~BfsVisit() {
+ if(local_reached) delete _reached;
+ }
+
+ /// \brief Sets the map that indicates which nodes are reached.
+ ///
+ /// Sets the map that indicates which nodes are reached.
+ /// If you don't use this function before calling \ref run(Node) "run()"
+ /// or \ref init(), an instance will be allocated automatically.
+ /// The destructor deallocates this automatically allocated map,
+ /// of course.
+ /// \return <tt> (*this) </tt>
+ BfsVisit &reachedMap(ReachedMap &m) {
+ if(local_reached) {
+ delete _reached;
+ local_reached = false;
+ }
+ _reached = &m;
+ return *this;
+ }
+
+ public:
+
+ /// \name Execution Control
+ /// The simplest way to execute the BFS algorithm is to use one of the
+ /// member functions called \ref run(Node) "run()".\n
+ /// If you need better control on the execution, you have to call
+ /// \ref init() first, then you can add several source nodes with
+ /// \ref addSource(). Finally the actual path computation can be
+ /// performed with one of the \ref start() functions.
+
+ /// @{
+
+ /// \brief Initializes the internal data structures.
+ ///
+ /// Initializes the internal data structures.
+ void init() {
+ create_maps();
+ _list.resize(countNodes(*_digraph));
+ _list_front = _list_back = -1;
+ for (NodeIt u(*_digraph) ; u != INVALID ; ++u) {
+ _reached->set(u, false);
+ }
+ }
+
+ /// \brief Adds a new source node.
+ ///
+ /// Adds a new source node to the set of nodes to be processed.
+ void addSource(Node s) {
+ if(!(*_reached)[s]) {
+ _reached->set(s,true);
+ _visitor->start(s);
+ _visitor->reach(s);
+ _list[++_list_back] = s;
+ }
+ }
+
+ /// \brief Processes the next node.
+ ///
+ /// Processes the next node.
+ ///
+ /// \return The processed node.
+ ///
+ /// \pre The queue must not be empty.
+ Node processNextNode() {
+ Node n = _list[++_list_front];
+ _visitor->process(n);
+ Arc e;
+ for (_digraph->firstOut(e, n); e != INVALID; _digraph->nextOut(e)) {
+ Node m = _digraph->target(e);
+ if (!(*_reached)[m]) {
+ _visitor->discover(e);
+ _visitor->reach(m);
+ _reached->set(m, true);
+ _list[++_list_back] = m;
+ } else {
+ _visitor->examine(e);
+ }
+ }
+ return n;
+ }
+
+ /// \brief Processes the next node.
+ ///
+ /// Processes the next node and checks if the given target node
+ /// is reached. If the target node is reachable from the processed
+ /// node, then the \c reach parameter will be set to \c true.
+ ///
+ /// \param target The target node.
+ /// \retval reach Indicates if the target node is reached.
+ /// It should be initially \c false.
+ ///
+ /// \return The processed node.
+ ///
+ /// \pre The queue must not be empty.
+ Node processNextNode(Node target, bool& reach) {
+ Node n = _list[++_list_front];
+ _visitor->process(n);
+ Arc e;
+ for (_digraph->firstOut(e, n); e != INVALID; _digraph->nextOut(e)) {
+ Node m = _digraph->target(e);
+ if (!(*_reached)[m]) {
+ _visitor->discover(e);
+ _visitor->reach(m);
+ _reached->set(m, true);
+ _list[++_list_back] = m;
+ reach = reach || (target == m);
+ } else {
+ _visitor->examine(e);
+ }
+ }
+ return n;
+ }
+
+ /// \brief Processes the next node.
+ ///
+ /// Processes the next node and checks if at least one of reached
+ /// nodes has \c true value in the \c nm node map. If one node
+ /// with \c true value is reachable from the processed node, then the
+ /// \c rnode parameter will be set to the first of such nodes.
+ ///
+ /// \param nm A \c bool (or convertible) node map that indicates the
+ /// possible targets.
+ /// \retval rnode The reached target node.
+ /// It should be initially \c INVALID.
+ ///
+ /// \return The processed node.
+ ///
+ /// \pre The queue must not be empty.
+ template <typename NM>
+ Node processNextNode(const NM& nm, Node& rnode) {
+ Node n = _list[++_list_front];
+ _visitor->process(n);
+ Arc e;
+ for (_digraph->firstOut(e, n); e != INVALID; _digraph->nextOut(e)) {
+ Node m = _digraph->target(e);
+ if (!(*_reached)[m]) {
+ _visitor->discover(e);
+ _visitor->reach(m);
+ _reached->set(m, true);
+ _list[++_list_back] = m;
+ if (nm[m] && rnode == INVALID) rnode = m;
+ } else {
+ _visitor->examine(e);
+ }
+ }
+ return n;
+ }
+
+ /// \brief The next node to be processed.
+ ///
+ /// Returns the next node to be processed or \c INVALID if the queue
+ /// is empty.
+ Node nextNode() const {
+ return _list_front != _list_back ? _list[_list_front + 1] : INVALID;
+ }
+
+ /// \brief Returns \c false if there are nodes
+ /// to be processed.
+ ///
+ /// Returns \c false if there are nodes
+ /// to be processed in the queue.
+ bool emptyQueue() const { return _list_front == _list_back; }
+
+ /// \brief Returns the number of the nodes to be processed.
+ ///
+ /// Returns the number of the nodes to be processed in the queue.
+ int queueSize() const { return _list_back - _list_front; }
+
+ /// \brief Executes the algorithm.
+ ///
+ /// Executes the algorithm.
+ ///
+ /// This method runs the %BFS algorithm from the root node(s)
+ /// in order to compute the shortest path to each node.
+ ///
+ /// The algorithm computes
+ /// - the shortest path tree (forest),
+ /// - the distance of each node from the root(s).
+ ///
+ /// \pre init() must be called and at least one root node should be added
+ /// with addSource() before using this function.
+ ///
+ /// \note <tt>b.start()</tt> is just a shortcut of the following code.
+ /// \code
+ /// while ( !b.emptyQueue() ) {
+ /// b.processNextNode();
+ /// }
+ /// \endcode
+ void start() {
+ while ( !emptyQueue() ) processNextNode();
+ }
+
+ /// \brief Executes the algorithm until the given target node is reached.
+ ///
+ /// Executes the algorithm until the given target node is reached.
+ ///
+ /// This method runs the %BFS algorithm from the root node(s)
+ /// in order to compute the shortest path to \c t.
+ ///
+ /// The algorithm computes
+ /// - the shortest path to \c t,
+ /// - the distance of \c t from the root(s).
+ ///
+ /// \pre init() must be called and at least one root node should be
+ /// added with addSource() before using this function.
+ ///
+ /// \note <tt>b.start(t)</tt> is just a shortcut of the following code.
+ /// \code
+ /// bool reach = false;
+ /// while ( !b.emptyQueue() && !reach ) {
+ /// b.processNextNode(t, reach);
+ /// }
+ /// \endcode
+ void start(Node t) {
+ bool reach = false;
+ while ( !emptyQueue() && !reach ) processNextNode(t, reach);
+ }
+
+ /// \brief Executes the algorithm until a condition is met.
+ ///
+ /// Executes the algorithm until a condition is met.
+ ///
+ /// This method runs the %BFS algorithm from the root node(s) in
+ /// order to compute the shortest path to a node \c v with
+ /// <tt>nm[v]</tt> true, if such a node can be found.
+ ///
+ /// \param nm must be a bool (or convertible) node map. The
+ /// algorithm will stop when it reaches a node \c v with
+ /// <tt>nm[v]</tt> true.
+ ///
+ /// \return The reached node \c v with <tt>nm[v]</tt> true or
+ /// \c INVALID if no such node was found.
+ ///
+ /// \pre init() must be called and at least one root node should be
+ /// added with addSource() before using this function.
+ ///
+ /// \note <tt>b.start(nm)</tt> is just a shortcut of the following code.
+ /// \code
+ /// Node rnode = INVALID;
+ /// while ( !b.emptyQueue() && rnode == INVALID ) {
+ /// b.processNextNode(nm, rnode);
+ /// }
+ /// return rnode;
+ /// \endcode
+ template <typename NM>
+ Node start(const NM &nm) {
+ Node rnode = INVALID;
+ while ( !emptyQueue() && rnode == INVALID ) {
+ processNextNode(nm, rnode);
+ }
+ return rnode;
+ }
+
+ /// \brief Runs the algorithm from the given source node.
+ ///
+ /// This method runs the %BFS algorithm from node \c s
+ /// in order to compute the shortest path to each node.
+ ///
+ /// The algorithm computes
+ /// - the shortest path tree,
+ /// - the distance of each node from the root.
+ ///
+ /// \note <tt>b.run(s)</tt> is just a shortcut of the following code.
+ ///\code
+ /// b.init();
+ /// b.addSource(s);
+ /// b.start();
+ ///\endcode
+ void run(Node s) {
+ init();
+ addSource(s);
+ start();
+ }
+
+ /// \brief Finds the shortest path between \c s and \c t.
+ ///
+ /// This method runs the %BFS algorithm from node \c s
+ /// in order to compute the shortest path to node \c t
+ /// (it stops searching when \c t is processed).
+ ///
+ /// \return \c true if \c t is reachable form \c s.
+ ///
+ /// \note Apart from the return value, <tt>b.run(s,t)</tt> is just a
+ /// shortcut of the following code.
+ ///\code
+ /// b.init();
+ /// b.addSource(s);
+ /// b.start(t);
+ ///\endcode
+ bool run(Node s,Node t) {
+ init();
+ addSource(s);
+ start(t);
+ return reached(t);
+ }
+
+ /// \brief Runs the algorithm to visit all nodes in the digraph.
+ ///
+ /// This method runs the %BFS algorithm in order to visit all nodes
+ /// in the digraph.
+ ///
+ /// \note <tt>b.run(s)</tt> is just a shortcut of the following code.
+ ///\code
+ /// b.init();
+ /// for (NodeIt n(gr); n != INVALID; ++n) {
+ /// if (!b.reached(n)) {
+ /// b.addSource(n);
+ /// b.start();
+ /// }
+ /// }
+ ///\endcode
+ void run() {
+ init();
+ for (NodeIt it(*_digraph); it != INVALID; ++it) {
+ if (!reached(it)) {
+ addSource(it);
+ start();
+ }
+ }
+ }
+
+ ///@}
+
+ /// \name Query Functions
+ /// The results of the BFS algorithm can be obtained using these
+ /// functions.\n
+ /// Either \ref run(Node) "run()" or \ref start() should be called
+ /// before using them.
+
+ ///@{
+
+ /// \brief Checks if the given node is reached from the root(s).
+ ///
+ /// Returns \c true if \c v is reached from the root(s).
+ ///
+ /// \pre Either \ref run(Node) "run()" or \ref init()
+ /// must be called before using this function.
+ bool reached(Node v) const { return (*_reached)[v]; }
+
+ ///@}
+
+ };
+
+} //END OF NAMESPACE LEMON
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bin_heap.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bin_heap.h
new file mode 100644
index 00000000000..02c66582210
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bin_heap.h
@@ -0,0 +1,347 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BIN_HEAP_H
+#define LEMON_BIN_HEAP_H
+
+///\ingroup heaps
+///\file
+///\brief Binary heap implementation.
+
+#include <vector>
+#include <utility>
+#include <functional>
+
+namespace lemon {
+
+ /// \ingroup heaps
+ ///
+ /// \brief Binary heap data structure.
+ ///
+ /// This class implements the \e binary \e heap data structure.
+ /// It fully conforms to the \ref concepts::Heap "heap concept".
+ ///
+ /// \tparam PR Type of the priorities of the items.
+ /// \tparam IM A read-writable item map with \c int values, used
+ /// internally to handle the cross references.
+ /// \tparam CMP A functor class for comparing the priorities.
+ /// The default is \c std::less<PR>.
+#ifdef DOXYGEN
+ template <typename PR, typename IM, typename CMP>
+#else
+ template <typename PR, typename IM, typename CMP = std::less<PR> >
+#endif
+ class BinHeap {
+ public:
+
+ /// Type of the item-int map.
+ typedef IM ItemIntMap;
+ /// Type of the priorities.
+ typedef PR Prio;
+ /// Type of the items stored in the heap.
+ typedef typename ItemIntMap::Key Item;
+ /// Type of the item-priority pairs.
+ typedef std::pair<Item,Prio> Pair;
+ /// Functor type for comparing the priorities.
+ typedef CMP Compare;
+
+ /// \brief Type to represent the states of the items.
+ ///
+ /// Each item has a state associated to it. It can be "in heap",
+ /// "pre-heap" or "post-heap". The latter two are indifferent from the
+ /// heap's point of view, but may be useful to the user.
+ ///
+ /// The item-int map must be initialized in such way that it assigns
+ /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
+ enum State {
+ IN_HEAP = 0, ///< = 0.
+ PRE_HEAP = -1, ///< = -1.
+ POST_HEAP = -2 ///< = -2.
+ };
+
+ private:
+ std::vector<Pair> _data;
+ Compare _comp;
+ ItemIntMap &_iim;
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// \param map A map that assigns \c int values to the items.
+ /// It is used internally to handle the cross references.
+ /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
+ explicit BinHeap(ItemIntMap &map) : _iim(map) {}
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// \param map A map that assigns \c int values to the items.
+ /// It is used internally to handle the cross references.
+ /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
+ /// \param comp The function object used for comparing the priorities.
+ BinHeap(ItemIntMap &map, const Compare &comp)
+ : _iim(map), _comp(comp) {}
+
+
+ /// \brief The number of items stored in the heap.
+ ///
+ /// This function returns the number of items stored in the heap.
+ int size() const { return _data.size(); }
+
+ /// \brief Check if the heap is empty.
+ ///
+ /// This function returns \c true if the heap is empty.
+ bool empty() const { return _data.empty(); }
+
+ /// \brief Make the heap empty.
+ ///
+ /// This functon makes the heap empty.
+ /// It does not change the cross reference map. If you want to reuse
+ /// a heap that is not surely empty, you should first clear it and
+ /// then you should set the cross reference map to \c PRE_HEAP
+ /// for each item.
+ void clear() {
+ _data.clear();
+ }
+
+ private:
+ static int parent(int i) { return (i-1)/2; }
+
+ static int secondChild(int i) { return 2*i+2; }
+ bool less(const Pair &p1, const Pair &p2) const {
+ return _comp(p1.second, p2.second);
+ }
+
+ int bubbleUp(int hole, Pair p) {
+ int par = parent(hole);
+ while( hole>0 && less(p,_data[par]) ) {
+ move(_data[par],hole);
+ hole = par;
+ par = parent(hole);
+ }
+ move(p, hole);
+ return hole;
+ }
+
+ int bubbleDown(int hole, Pair p, int length) {
+ int child = secondChild(hole);
+ while(child < length) {
+ if( less(_data[child-1], _data[child]) ) {
+ --child;
+ }
+ if( !less(_data[child], p) )
+ goto ok;
+ move(_data[child], hole);
+ hole = child;
+ child = secondChild(hole);
+ }
+ child--;
+ if( child<length && less(_data[child], p) ) {
+ move(_data[child], hole);
+ hole=child;
+ }
+ ok:
+ move(p, hole);
+ return hole;
+ }
+
+ void move(const Pair &p, int i) {
+ _data[i] = p;
+ _iim.set(p.first, i);
+ }
+
+ public:
+
+ /// \brief Insert a pair of item and priority into the heap.
+ ///
+ /// This function inserts \c p.first to the heap with priority
+ /// \c p.second.
+ /// \param p The pair to insert.
+ /// \pre \c p.first must not be stored in the heap.
+ void push(const Pair &p) {
+ int n = _data.size();
+ _data.resize(n+1);
+ bubbleUp(n, p);
+ }
+
+ /// \brief Insert an item into the heap with the given priority.
+ ///
+ /// This function inserts the given item into the heap with the
+ /// given priority.
+ /// \param i The item to insert.
+ /// \param p The priority of the item.
+ /// \pre \e i must not be stored in the heap.
+ void push(const Item &i, const Prio &p) { push(Pair(i,p)); }
+
+ /// \brief Return the item having minimum priority.
+ ///
+ /// This function returns the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ Item top() const {
+ return _data[0].first;
+ }
+
+ /// \brief The minimum priority.
+ ///
+ /// This function returns the minimum priority.
+ /// \pre The heap must be non-empty.
+ Prio prio() const {
+ return _data[0].second;
+ }
+
+ /// \brief Remove the item having minimum priority.
+ ///
+ /// This function removes the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ void pop() {
+ int n = _data.size()-1;
+ _iim.set(_data[0].first, POST_HEAP);
+ if (n > 0) {
+ bubbleDown(0, _data[n], n);
+ }
+ _data.pop_back();
+ }
+
+ /// \brief Remove the given item from the heap.
+ ///
+ /// This function removes the given item from the heap if it is
+ /// already stored.
+ /// \param i The item to delete.
+ /// \pre \e i must be in the heap.
+ void erase(const Item &i) {
+ int h = _iim[i];
+ int n = _data.size()-1;
+ _iim.set(_data[h].first, POST_HEAP);
+ if( h < n ) {
+ if ( bubbleUp(h, _data[n]) == h) {
+ bubbleDown(h, _data[n], n);
+ }
+ }
+ _data.pop_back();
+ }
+
+ /// \brief The priority of the given item.
+ ///
+ /// This function returns the priority of the given item.
+ /// \param i The item.
+ /// \pre \e i must be in the heap.
+ Prio operator[](const Item &i) const {
+ int idx = _iim[i];
+ return _data[idx].second;
+ }
+
+ /// \brief Set the priority of an item or insert it, if it is
+ /// not stored in the heap.
+ ///
+ /// This method sets the priority of the given item if it is
+ /// already stored in the heap. Otherwise it inserts the given
+ /// item into the heap with the given priority.
+ /// \param i The item.
+ /// \param p The priority.
+ void set(const Item &i, const Prio &p) {
+ int idx = _iim[i];
+ if( idx < 0 ) {
+ push(i,p);
+ }
+ else if( _comp(p, _data[idx].second) ) {
+ bubbleUp(idx, Pair(i,p));
+ }
+ else {
+ bubbleDown(idx, Pair(i,p), _data.size());
+ }
+ }
+
+ /// \brief Decrease the priority of an item to the given value.
+ ///
+ /// This function decreases the priority of an item to the given value.
+ /// \param i The item.
+ /// \param p The priority.
+ /// \pre \e i must be stored in the heap with priority at least \e p.
+ void decrease(const Item &i, const Prio &p) {
+ int idx = _iim[i];
+ bubbleUp(idx, Pair(i,p));
+ }
+
+ /// \brief Increase the priority of an item to the given value.
+ ///
+ /// This function increases the priority of an item to the given value.
+ /// \param i The item.
+ /// \param p The priority.
+ /// \pre \e i must be stored in the heap with priority at most \e p.
+ void increase(const Item &i, const Prio &p) {
+ int idx = _iim[i];
+ bubbleDown(idx, Pair(i,p), _data.size());
+ }
+
+ /// \brief Return the state of an item.
+ ///
+ /// This method returns \c PRE_HEAP if the given item has never
+ /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
+ /// and \c POST_HEAP otherwise.
+ /// In the latter case it is possible that the item will get back
+ /// to the heap again.
+ /// \param i The item.
+ State state(const Item &i) const {
+ int s = _iim[i];
+ if( s>=0 )
+ s=0;
+ return State(s);
+ }
+
+ /// \brief Set the state of an item in the heap.
+ ///
+ /// This function sets the state of the given item in the heap.
+ /// It can be used to manually clear the heap when it is important
+ /// to achive better time complexity.
+ /// \param i The item.
+ /// \param st The state. It should not be \c IN_HEAP.
+ void state(const Item& i, State st) {
+ switch (st) {
+ case POST_HEAP:
+ case PRE_HEAP:
+ if (state(i) == IN_HEAP) {
+ erase(i);
+ }
+ _iim[i] = st;
+ break;
+ case IN_HEAP:
+ break;
+ }
+ }
+
+ /// \brief Replace an item in the heap.
+ ///
+ /// This function replaces item \c i with item \c j.
+ /// Item \c i must be in the heap, while \c j must be out of the heap.
+ /// After calling this method, item \c i will be out of the
+ /// heap and \c j will be in the heap with the same prioriority
+ /// as item \c i had before.
+ void replace(const Item& i, const Item& j) {
+ int idx = _iim[i];
+ _iim.set(i, _iim[j]);
+ _iim.set(j, idx);
+ _data[idx].first = j;
+ }
+
+ }; // class BinHeap
+
+} // namespace lemon
+
+#endif // LEMON_BIN_HEAP_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/binomial_heap.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/binomial_heap.h
new file mode 100644
index 00000000000..5bc13787058
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/binomial_heap.h
@@ -0,0 +1,445 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2010
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BINOMIAL_HEAP_H
+#define LEMON_BINOMIAL_HEAP_H
+
+///\file
+///\ingroup heaps
+///\brief Binomial Heap implementation.
+
+#include <vector>
+#include <utility>
+#include <functional>
+#include <lemon/math.h>
+#include <lemon/counter.h>
+
+namespace lemon {
+
+ /// \ingroup heaps
+ ///
+ ///\brief Binomial heap data structure.
+ ///
+ /// This class implements the \e binomial \e heap data structure.
+ /// It fully conforms to the \ref concepts::Heap "heap concept".
+ ///
+ /// The methods \ref increase() and \ref erase() are not efficient
+ /// in a binomial heap. In case of many calls of these operations,
+ /// it is better to use other heap structure, e.g. \ref BinHeap
+ /// "binary heap".
+ ///
+ /// \tparam PR Type of the priorities of the items.
+ /// \tparam IM A read-writable item map with \c int values, used
+ /// internally to handle the cross references.
+ /// \tparam CMP A functor class for comparing the priorities.
+ /// The default is \c std::less<PR>.
+#ifdef DOXYGEN
+ template <typename PR, typename IM, typename CMP>
+#else
+ template <typename PR, typename IM, typename CMP = std::less<PR> >
+#endif
+ class BinomialHeap {
+ public:
+ /// Type of the item-int map.
+ typedef IM ItemIntMap;
+ /// Type of the priorities.
+ typedef PR Prio;
+ /// Type of the items stored in the heap.
+ typedef typename ItemIntMap::Key Item;
+ /// Functor type for comparing the priorities.
+ typedef CMP Compare;
+
+ /// \brief Type to represent the states of the items.
+ ///
+ /// Each item has a state associated to it. It can be "in heap",
+ /// "pre-heap" or "post-heap". The latter two are indifferent from the
+ /// heap's point of view, but may be useful to the user.
+ ///
+ /// The item-int map must be initialized in such way that it assigns
+ /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
+ enum State {
+ IN_HEAP = 0, ///< = 0.
+ PRE_HEAP = -1, ///< = -1.
+ POST_HEAP = -2 ///< = -2.
+ };
+
+ private:
+ class Store;
+
+ std::vector<Store> _data;
+ int _min, _head;
+ ItemIntMap &_iim;
+ Compare _comp;
+ int _num_items;
+
+ public:
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// \param map A map that assigns \c int values to the items.
+ /// It is used internally to handle the cross references.
+ /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
+ explicit BinomialHeap(ItemIntMap &map)
+ : _min(0), _head(-1), _iim(map), _num_items(0) {}
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// \param map A map that assigns \c int values to the items.
+ /// It is used internally to handle the cross references.
+ /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
+ /// \param comp The function object used for comparing the priorities.
+ BinomialHeap(ItemIntMap &map, const Compare &comp)
+ : _min(0), _head(-1), _iim(map), _comp(comp), _num_items(0) {}
+
+ /// \brief The number of items stored in the heap.
+ ///
+ /// This function returns the number of items stored in the heap.
+ int size() const { return _num_items; }
+
+ /// \brief Check if the heap is empty.
+ ///
+ /// This function returns \c true if the heap is empty.
+ bool empty() const { return _num_items==0; }
+
+ /// \brief Make the heap empty.
+ ///
+ /// This functon makes the heap empty.
+ /// It does not change the cross reference map. If you want to reuse
+ /// a heap that is not surely empty, you should first clear it and
+ /// then you should set the cross reference map to \c PRE_HEAP
+ /// for each item.
+ void clear() {
+ _data.clear(); _min=0; _num_items=0; _head=-1;
+ }
+
+ /// \brief Set the priority of an item or insert it, if it is
+ /// not stored in the heap.
+ ///
+ /// This method sets the priority of the given item if it is
+ /// already stored in the heap. Otherwise it inserts the given
+ /// item into the heap with the given priority.
+ /// \param item The item.
+ /// \param value The priority.
+ void set (const Item& item, const Prio& value) {
+ int i=_iim[item];
+ if ( i >= 0 && _data[i].in ) {
+ if ( _comp(value, _data[i].prio) ) decrease(item, value);
+ if ( _comp(_data[i].prio, value) ) increase(item, value);
+ } else push(item, value);
+ }
+
+ /// \brief Insert an item into the heap with the given priority.
+ ///
+ /// This function inserts the given item into the heap with the
+ /// given priority.
+ /// \param item The item to insert.
+ /// \param value The priority of the item.
+ /// \pre \e item must not be stored in the heap.
+ void push (const Item& item, const Prio& value) {
+ int i=_iim[item];
+ if ( i<0 ) {
+ int s=_data.size();
+ _iim.set( item,s );
+ Store st;
+ st.name=item;
+ st.prio=value;
+ _data.push_back(st);
+ i=s;
+ }
+ else {
+ _data[i].parent=_data[i].right_neighbor=_data[i].child=-1;
+ _data[i].degree=0;
+ _data[i].in=true;
+ _data[i].prio=value;
+ }
+
+ if( 0==_num_items ) {
+ _head=i;
+ _min=i;
+ } else {
+ merge(i);
+ if( _comp(_data[i].prio, _data[_min].prio) ) _min=i;
+ }
+ ++_num_items;
+ }
+
+ /// \brief Return the item having minimum priority.
+ ///
+ /// This function returns the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ Item top() const { return _data[_min].name; }
+
+ /// \brief The minimum priority.
+ ///
+ /// This function returns the minimum priority.
+ /// \pre The heap must be non-empty.
+ Prio prio() const { return _data[_min].prio; }
+
+ /// \brief The priority of the given item.
+ ///
+ /// This function returns the priority of the given item.
+ /// \param item The item.
+ /// \pre \e item must be in the heap.
+ const Prio& operator[](const Item& item) const {
+ return _data[_iim[item]].prio;
+ }
+
+ /// \brief Remove the item having minimum priority.
+ ///
+ /// This function removes the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ void pop() {
+ _data[_min].in=false;
+
+ int head_child=-1;
+ if ( _data[_min].child!=-1 ) {
+ int child=_data[_min].child;
+ int neighb;
+ while( child!=-1 ) {
+ neighb=_data[child].right_neighbor;
+ _data[child].parent=-1;
+ _data[child].right_neighbor=head_child;
+ head_child=child;
+ child=neighb;
+ }
+ }
+
+ if ( _data[_head].right_neighbor==-1 ) {
+ // there was only one root
+ _head=head_child;
+ }
+ else {
+ // there were more roots
+ if( _head!=_min ) { unlace(_min); }
+ else { _head=_data[_head].right_neighbor; }
+ merge(head_child);
+ }
+ _min=findMin();
+ --_num_items;
+ }
+
+ /// \brief Remove the given item from the heap.
+ ///
+ /// This function removes the given item from the heap if it is
+ /// already stored.
+ /// \param item The item to delete.
+ /// \pre \e item must be in the heap.
+ void erase (const Item& item) {
+ int i=_iim[item];
+ if ( i >= 0 && _data[i].in ) {
+ decrease( item, _data[_min].prio-1 );
+ pop();
+ }
+ }
+
+ /// \brief Decrease the priority of an item to the given value.
+ ///
+ /// This function decreases the priority of an item to the given value.
+ /// \param item The item.
+ /// \param value The priority.
+ /// \pre \e item must be stored in the heap with priority at least \e value.
+ void decrease (Item item, const Prio& value) {
+ int i=_iim[item];
+ int p=_data[i].parent;
+ _data[i].prio=value;
+
+ while( p!=-1 && _comp(value, _data[p].prio) ) {
+ _data[i].name=_data[p].name;
+ _data[i].prio=_data[p].prio;
+ _data[p].name=item;
+ _data[p].prio=value;
+ _iim[_data[i].name]=i;
+ i=p;
+ p=_data[p].parent;
+ }
+ _iim[item]=i;
+ if ( _comp(value, _data[_min].prio) ) _min=i;
+ }
+
+ /// \brief Increase the priority of an item to the given value.
+ ///
+ /// This function increases the priority of an item to the given value.
+ /// \param item The item.
+ /// \param value The priority.
+ /// \pre \e item must be stored in the heap with priority at most \e value.
+ void increase (Item item, const Prio& value) {
+ erase(item);
+ push(item, value);
+ }
+
+ /// \brief Return the state of an item.
+ ///
+ /// This method returns \c PRE_HEAP if the given item has never
+ /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
+ /// and \c POST_HEAP otherwise.
+ /// In the latter case it is possible that the item will get back
+ /// to the heap again.
+ /// \param item The item.
+ State state(const Item &item) const {
+ int i=_iim[item];
+ if( i>=0 ) {
+ if ( _data[i].in ) i=0;
+ else i=-2;
+ }
+ return State(i);
+ }
+
+ /// \brief Set the state of an item in the heap.
+ ///
+ /// This function sets the state of the given item in the heap.
+ /// It can be used to manually clear the heap when it is important
+ /// to achive better time complexity.
+ /// \param i The item.
+ /// \param st The state. It should not be \c IN_HEAP.
+ void state(const Item& i, State st) {
+ switch (st) {
+ case POST_HEAP:
+ case PRE_HEAP:
+ if (state(i) == IN_HEAP) {
+ erase(i);
+ }
+ _iim[i] = st;
+ break;
+ case IN_HEAP:
+ break;
+ }
+ }
+
+ private:
+
+ // Find the minimum of the roots
+ int findMin() {
+ if( _head!=-1 ) {
+ int min_loc=_head, min_val=_data[_head].prio;
+ for( int x=_data[_head].right_neighbor; x!=-1;
+ x=_data[x].right_neighbor ) {
+ if( _comp( _data[x].prio,min_val ) ) {
+ min_val=_data[x].prio;
+ min_loc=x;
+ }
+ }
+ return min_loc;
+ }
+ else return -1;
+ }
+
+ // Merge the heap with another heap starting at the given position
+ void merge(int a) {
+ if( _head==-1 || a==-1 ) return;
+ if( _data[a].right_neighbor==-1 &&
+ _data[a].degree<=_data[_head].degree ) {
+ _data[a].right_neighbor=_head;
+ _head=a;
+ } else {
+ interleave(a);
+ }
+ if( _data[_head].right_neighbor==-1 ) return;
+
+ int x=_head;
+ int x_prev=-1, x_next=_data[x].right_neighbor;
+ while( x_next!=-1 ) {
+ if( _data[x].degree!=_data[x_next].degree ||
+ ( _data[x_next].right_neighbor!=-1 &&
+ _data[_data[x_next].right_neighbor].degree==_data[x].degree ) ) {
+ x_prev=x;
+ x=x_next;
+ }
+ else {
+ if( _comp(_data[x_next].prio,_data[x].prio) ) {
+ if( x_prev==-1 ) {
+ _head=x_next;
+ } else {
+ _data[x_prev].right_neighbor=x_next;
+ }
+ fuse(x,x_next);
+ x=x_next;
+ }
+ else {
+ _data[x].right_neighbor=_data[x_next].right_neighbor;
+ fuse(x_next,x);
+ }
+ }
+ x_next=_data[x].right_neighbor;
+ }
+ }
+
+ // Interleave the elements of the given list into the list of the roots
+ void interleave(int a) {
+ int p=_head, q=a;
+ int curr=_data.size();
+ _data.push_back(Store());
+
+ while( p!=-1 || q!=-1 ) {
+ if( q==-1 || ( p!=-1 && _data[p].degree<_data[q].degree ) ) {
+ _data[curr].right_neighbor=p;
+ curr=p;
+ p=_data[p].right_neighbor;
+ }
+ else {
+ _data[curr].right_neighbor=q;
+ curr=q;
+ q=_data[q].right_neighbor;
+ }
+ }
+
+ _head=_data.back().right_neighbor;
+ _data.pop_back();
+ }
+
+ // Lace node a under node b
+ void fuse(int a, int b) {
+ _data[a].parent=b;
+ _data[a].right_neighbor=_data[b].child;
+ _data[b].child=a;
+
+ ++_data[b].degree;
+ }
+
+ // Unlace node a (if it has siblings)
+ void unlace(int a) {
+ int neighb=_data[a].right_neighbor;
+ int other=_head;
+
+ while( _data[other].right_neighbor!=a )
+ other=_data[other].right_neighbor;
+ _data[other].right_neighbor=neighb;
+ }
+
+ private:
+
+ class Store {
+ friend class BinomialHeap;
+
+ Item name;
+ int parent;
+ int right_neighbor;
+ int child;
+ int degree;
+ bool in;
+ Prio prio;
+
+ Store() : parent(-1), right_neighbor(-1), child(-1), degree(0),
+ in(true) {}
+ };
+ };
+
+} //namespace lemon
+
+#endif //LEMON_BINOMIAL_HEAP_H
+
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/alteration_notifier.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/alteration_notifier.h
new file mode 100644
index 00000000000..d14fe3634dd
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/alteration_notifier.h
@@ -0,0 +1,472 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BITS_ALTERATION_NOTIFIER_H
+#define LEMON_BITS_ALTERATION_NOTIFIER_H
+
+#include <vector>
+#include <list>
+
+#include <lemon/core.h>
+#include <lemon/bits/lock.h>
+
+//\ingroup graphbits
+//\file
+//\brief Observer notifier for graph alteration observers.
+
+namespace lemon {
+
+ // \ingroup graphbits
+ //
+ // \brief Notifier class to notify observes about alterations in
+ // a container.
+ //
+ // The simple graphs can be refered as two containers: a node container
+ // and an edge container. But they do not store values directly, they
+ // are just key continars for more value containers, which are the
+ // node and edge maps.
+ //
+ // The node and edge sets of the graphs can be changed as we add or erase
+ // nodes and edges in the graph. LEMON would like to handle easily
+ // that the node and edge maps should contain values for all nodes or
+ // edges. If we want to check on every indicing if the map contains
+ // the current indicing key that cause a drawback in the performance
+ // in the library. We use another solution: we notify all maps about
+ // an alteration in the graph, which cause only drawback on the
+ // alteration of the graph.
+ //
+ // This class provides an interface to a node or edge container.
+ // The first() and next() member functions make possible
+ // to iterate on the keys of the container.
+ // The id() function returns an integer id for each key.
+ // The maxId() function gives back an upper bound of the ids.
+ //
+ // For the proper functonality of this class, we should notify it
+ // about each alteration in the container. The alterations have four type:
+ // add(), erase(), build() and clear(). The add() and
+ // erase() signal that only one or few items added or erased to or
+ // from the graph. If all items are erased from the graph or if a new graph
+ // is built from an empty graph, then it can be signaled with the
+ // clear() and build() members. Important rule that if we erase items
+ // from graphs we should first signal the alteration and after that erase
+ // them from the container, on the other way on item addition we should
+ // first extend the container and just after that signal the alteration.
+ //
+ // The alteration can be observed with a class inherited from the
+ // ObserverBase nested class. The signals can be handled with
+ // overriding the virtual functions defined in the base class. The
+ // observer base can be attached to the notifier with the
+ // attach() member and can be detached with detach() function. The
+ // alteration handlers should not call any function which signals
+ // an other alteration in the same notifier and should not
+ // detach any observer from the notifier.
+ //
+ // Alteration observers try to be exception safe. If an add() or
+ // a clear() function throws an exception then the remaining
+ // observeres will not be notified and the fulfilled additions will
+ // be rolled back by calling the erase() or clear() functions.
+ // Hence erase() and clear() should not throw exception.
+ // Actullay, they can throw only \ref ImmediateDetach exception,
+ // which detach the observer from the notifier.
+ //
+ // There are some cases, when the alteration observing is not completly
+ // reliable. If we want to carry out the node degree in the graph
+ // as in the \ref InDegMap and we use the reverseArc(), then it cause
+ // unreliable functionality. Because the alteration observing signals
+ // only erasing and adding but not the reversing, it will stores bad
+ // degrees. Apart form that the subgraph adaptors cannot even signal
+ // the alterations because just a setting in the filter map can modify
+ // the graph and this cannot be watched in any way.
+ //
+ // \param _Container The container which is observed.
+ // \param _Item The item type which is obserbved.
+
+ template <typename _Container, typename _Item>
+ class AlterationNotifier {
+ public:
+
+ typedef True Notifier;
+
+ typedef _Container Container;
+ typedef _Item Item;
+
+ // \brief Exception which can be called from clear() and
+ // erase().
+ //
+ // From the clear() and erase() function only this
+ // exception is allowed to throw. The exception immediatly
+ // detaches the current observer from the notifier. Because the
+ // clear() and erase() should not throw other exceptions
+ // it can be used to invalidate the observer.
+ struct ImmediateDetach {};
+
+ // \brief ObserverBase is the base class for the observers.
+ //
+ // ObserverBase is the abstract base class for the observers.
+ // It will be notified about an item was inserted into or
+ // erased from the graph.
+ //
+ // The observer interface contains some pure virtual functions
+ // to override. The add() and erase() functions are
+ // to notify the oberver when one item is added or erased.
+ //
+ // The build() and clear() members are to notify the observer
+ // about the container is built from an empty container or
+ // is cleared to an empty container.
+ class ObserverBase {
+ protected:
+ typedef AlterationNotifier Notifier;
+
+ friend class AlterationNotifier;
+
+ // \brief Default constructor.
+ //
+ // Default constructor for ObserverBase.
+ ObserverBase() : _notifier(0) {}
+
+ // \brief Constructor which attach the observer into notifier.
+ //
+ // Constructor which attach the observer into notifier.
+ ObserverBase(AlterationNotifier& nf) {
+ attach(nf);
+ }
+
+ // \brief Constructor which attach the obserever to the same notifier.
+ //
+ // Constructor which attach the obserever to the same notifier as
+ // the other observer is attached to.
+ ObserverBase(const ObserverBase& copy) {
+ if (copy.attached()) {
+ attach(*copy.notifier());
+ }
+ }
+
+ // \brief Destructor
+ virtual ~ObserverBase() {
+ if (attached()) {
+ detach();
+ }
+ }
+
+ // \brief Attaches the observer into an AlterationNotifier.
+ //
+ // This member attaches the observer into an AlterationNotifier.
+ void attach(AlterationNotifier& nf) {
+ nf.attach(*this);
+ }
+
+ // \brief Detaches the observer into an AlterationNotifier.
+ //
+ // This member detaches the observer from an AlterationNotifier.
+ void detach() {
+ _notifier->detach(*this);
+ }
+
+ // \brief Gives back a pointer to the notifier which the map
+ // attached into.
+ //
+ // This function gives back a pointer to the notifier which the map
+ // attached into.
+ Notifier* notifier() const { return const_cast<Notifier*>(_notifier); }
+
+ // Gives back true when the observer is attached into a notifier.
+ bool attached() const { return _notifier != 0; }
+
+ private:
+
+ ObserverBase& operator=(const ObserverBase& copy);
+
+ protected:
+
+ Notifier* _notifier;
+ typename std::list<ObserverBase*>::iterator _index;
+
+ // \brief The member function to notificate the observer about an
+ // item is added to the container.
+ //
+ // The add() member function notificates the observer about an item
+ // is added to the container. It have to be overrided in the
+ // subclasses.
+ virtual void add(const Item&) = 0;
+
+ // \brief The member function to notificate the observer about
+ // more item is added to the container.
+ //
+ // The add() member function notificates the observer about more item
+ // is added to the container. It have to be overrided in the
+ // subclasses.
+ virtual void add(const std::vector<Item>& items) = 0;
+
+ // \brief The member function to notificate the observer about an
+ // item is erased from the container.
+ //
+ // The erase() member function notificates the observer about an
+ // item is erased from the container. It have to be overrided in
+ // the subclasses.
+ virtual void erase(const Item&) = 0;
+
+ // \brief The member function to notificate the observer about
+ // more item is erased from the container.
+ //
+ // The erase() member function notificates the observer about more item
+ // is erased from the container. It have to be overrided in the
+ // subclasses.
+ virtual void erase(const std::vector<Item>& items) = 0;
+
+ // \brief The member function to notificate the observer about the
+ // container is built.
+ //
+ // The build() member function notificates the observer about the
+ // container is built from an empty container. It have to be
+ // overrided in the subclasses.
+ virtual void build() = 0;
+
+ // \brief The member function to notificate the observer about all
+ // items are erased from the container.
+ //
+ // The clear() member function notificates the observer about all
+ // items are erased from the container. It have to be overrided in
+ // the subclasses.
+ virtual void clear() = 0;
+
+ };
+
+ protected:
+
+ const Container* container;
+
+ typedef std::list<ObserverBase*> Observers;
+ Observers _observers;
+ lemon::bits::Lock _lock;
+
+ public:
+
+ // \brief Default constructor.
+ //
+ // The default constructor of the AlterationNotifier.
+ // It creates an empty notifier.
+ AlterationNotifier()
+ : container(0) {}
+
+ // \brief Constructor.
+ //
+ // Constructor with the observed container parameter.
+ AlterationNotifier(const Container& _container)
+ : container(&_container) {}
+
+ // \brief Copy Constructor of the AlterationNotifier.
+ //
+ // Copy constructor of the AlterationNotifier.
+ // It creates only an empty notifier because the copiable
+ // notifier's observers have to be registered still into that notifier.
+ AlterationNotifier(const AlterationNotifier& _notifier)
+ : container(_notifier.container) {}
+
+ // \brief Destructor.
+ //
+ // Destructor of the AlterationNotifier.
+ ~AlterationNotifier() {
+ typename Observers::iterator it;
+ for (it = _observers.begin(); it != _observers.end(); ++it) {
+ (*it)->_notifier = 0;
+ }
+ }
+
+ // \brief Sets the container.
+ //
+ // Sets the container.
+ void setContainer(const Container& _container) {
+ container = &_container;
+ }
+
+ protected:
+
+ AlterationNotifier& operator=(const AlterationNotifier&);
+
+ public:
+
+ // \brief First item in the container.
+ //
+ // Returns the first item in the container. It is
+ // for start the iteration on the container.
+ void first(Item& item) const {
+ container->first(item);
+ }
+
+ // \brief Next item in the container.
+ //
+ // Returns the next item in the container. It is
+ // for iterate on the container.
+ void next(Item& item) const {
+ container->next(item);
+ }
+
+ // \brief Returns the id of the item.
+ //
+ // Returns the id of the item provided by the container.
+ int id(const Item& item) const {
+ return container->id(item);
+ }
+
+ // \brief Returns the maximum id of the container.
+ //
+ // Returns the maximum id of the container.
+ int maxId() const {
+ return container->maxId(Item());
+ }
+
+ protected:
+
+ void attach(ObserverBase& observer) {
+ _lock.lock();
+ observer._index = _observers.insert(_observers.begin(), &observer);
+ observer._notifier = this;
+ _lock.unlock();
+ }
+
+ void detach(ObserverBase& observer) {
+ _lock.lock();
+ _observers.erase(observer._index);
+ observer._index = _observers.end();
+ observer._notifier = 0;
+ _lock.unlock();
+ }
+
+ public:
+
+ // \brief Notifies all the registed observers about an item added to
+ // the container.
+ //
+ // It notifies all the registed observers about an item added to
+ // the container.
+ void add(const Item& item) {
+ typename Observers::reverse_iterator it;
+ try {
+ for (it = _observers.rbegin(); it != _observers.rend(); ++it) {
+ (*it)->add(item);
+ }
+ } catch (...) {
+ typename Observers::iterator jt;
+ for (jt = it.base(); jt != _observers.end(); ++jt) {
+ (*jt)->erase(item);
+ }
+ throw;
+ }
+ }
+
+ // \brief Notifies all the registed observers about more item added to
+ // the container.
+ //
+ // It notifies all the registed observers about more item added to
+ // the container.
+ void add(const std::vector<Item>& items) {
+ typename Observers::reverse_iterator it;
+ try {
+ for (it = _observers.rbegin(); it != _observers.rend(); ++it) {
+ (*it)->add(items);
+ }
+ } catch (...) {
+ typename Observers::iterator jt;
+ for (jt = it.base(); jt != _observers.end(); ++jt) {
+ (*jt)->erase(items);
+ }
+ throw;
+ }
+ }
+
+ // \brief Notifies all the registed observers about an item erased from
+ // the container.
+ //
+ // It notifies all the registed observers about an item erased from
+ // the container.
+ void erase(const Item& item) throw() {
+ typename Observers::iterator it = _observers.begin();
+ while (it != _observers.end()) {
+ try {
+ (*it)->erase(item);
+ ++it;
+ } catch (const ImmediateDetach&) {
+ (*it)->_index = _observers.end();
+ (*it)->_notifier = 0;
+ it = _observers.erase(it);
+ }
+ }
+ }
+
+ // \brief Notifies all the registed observers about more item erased
+ // from the container.
+ //
+ // It notifies all the registed observers about more item erased from
+ // the container.
+ void erase(const std::vector<Item>& items) {
+ typename Observers::iterator it = _observers.begin();
+ while (it != _observers.end()) {
+ try {
+ (*it)->erase(items);
+ ++it;
+ } catch (const ImmediateDetach&) {
+ (*it)->_index = _observers.end();
+ (*it)->_notifier = 0;
+ it = _observers.erase(it);
+ }
+ }
+ }
+
+ // \brief Notifies all the registed observers about the container is
+ // built.
+ //
+ // Notifies all the registed observers about the container is built
+ // from an empty container.
+ void build() {
+ typename Observers::reverse_iterator it;
+ try {
+ for (it = _observers.rbegin(); it != _observers.rend(); ++it) {
+ (*it)->build();
+ }
+ } catch (...) {
+ typename Observers::iterator jt;
+ for (jt = it.base(); jt != _observers.end(); ++jt) {
+ (*jt)->clear();
+ }
+ throw;
+ }
+ }
+
+ // \brief Notifies all the registed observers about all items are
+ // erased.
+ //
+ // Notifies all the registed observers about all items are erased
+ // from the container.
+ void clear() {
+ typename Observers::iterator it = _observers.begin();
+ while (it != _observers.end()) {
+ try {
+ (*it)->clear();
+ ++it;
+ } catch (const ImmediateDetach&) {
+ (*it)->_index = _observers.end();
+ (*it)->_notifier = 0;
+ it = _observers.erase(it);
+ }
+ }
+ }
+ };
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/array_map.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/array_map.h
new file mode 100644
index 00000000000..355ee008246
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/array_map.h
@@ -0,0 +1,351 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BITS_ARRAY_MAP_H
+#define LEMON_BITS_ARRAY_MAP_H
+
+#include <memory>
+
+#include <lemon/bits/traits.h>
+#include <lemon/bits/alteration_notifier.h>
+#include <lemon/concept_check.h>
+#include <lemon/concepts/maps.h>
+
+// \ingroup graphbits
+// \file
+// \brief Graph map based on the array storage.
+
+namespace lemon {
+
+ // \ingroup graphbits
+ //
+ // \brief Graph map based on the array storage.
+ //
+ // The ArrayMap template class is graph map structure that automatically
+ // updates the map when a key is added to or erased from the graph.
+ // This map uses the allocators to implement the container functionality.
+ //
+ // The template parameters are the Graph, the current Item type and
+ // the Value type of the map.
+ template <typename _Graph, typename _Item, typename _Value>
+ class ArrayMap
+ : public ItemSetTraits<_Graph, _Item>::ItemNotifier::ObserverBase {
+ public:
+ // The graph type.
+ typedef _Graph GraphType;
+ // The item type.
+ typedef _Item Item;
+ // The reference map tag.
+ typedef True ReferenceMapTag;
+
+ // The key type of the map.
+ typedef _Item Key;
+ // The value type of the map.
+ typedef _Value Value;
+
+ // The const reference type of the map.
+ typedef const _Value& ConstReference;
+ // The reference type of the map.
+ typedef _Value& Reference;
+
+ // The map type.
+ typedef ArrayMap Map;
+
+ // The notifier type.
+ typedef typename ItemSetTraits<_Graph, _Item>::ItemNotifier Notifier;
+
+ private:
+
+ // The MapBase of the Map which imlements the core regisitry function.
+ typedef typename Notifier::ObserverBase Parent;
+
+ typedef std::allocator<Value> Allocator;
+
+ public:
+
+ // \brief Graph initialized map constructor.
+ //
+ // Graph initialized map constructor.
+ explicit ArrayMap(const GraphType& graph) {
+ Parent::attach(graph.notifier(Item()));
+ allocate_memory();
+ Notifier* nf = Parent::notifier();
+ Item it;
+ for (nf->first(it); it != INVALID; nf->next(it)) {
+ int id = nf->id(it);;
+ allocator.construct(&(values[id]), Value());
+ }
+ }
+
+ // \brief Constructor to use default value to initialize the map.
+ //
+ // It constructs a map and initialize all of the the map.
+ ArrayMap(const GraphType& graph, const Value& value) {
+ Parent::attach(graph.notifier(Item()));
+ allocate_memory();
+ Notifier* nf = Parent::notifier();
+ Item it;
+ for (nf->first(it); it != INVALID; nf->next(it)) {
+ int id = nf->id(it);;
+ allocator.construct(&(values[id]), value);
+ }
+ }
+
+ private:
+ // \brief Constructor to copy a map of the same map type.
+ //
+ // Constructor to copy a map of the same map type.
+ ArrayMap(const ArrayMap& copy) : Parent() {
+ if (copy.attached()) {
+ attach(*copy.notifier());
+ }
+ capacity = copy.capacity;
+ if (capacity == 0) return;
+ values = allocator.allocate(capacity);
+ Notifier* nf = Parent::notifier();
+ Item it;
+ for (nf->first(it); it != INVALID; nf->next(it)) {
+ int id = nf->id(it);;
+ allocator.construct(&(values[id]), copy.values[id]);
+ }
+ }
+
+ // \brief Assign operator.
+ //
+ // This operator assigns for each item in the map the
+ // value mapped to the same item in the copied map.
+ // The parameter map should be indiced with the same
+ // itemset because this assign operator does not change
+ // the container of the map.
+ ArrayMap& operator=(const ArrayMap& cmap) {
+ return operator=<ArrayMap>(cmap);
+ }
+
+
+ // \brief Template assign operator.
+ //
+ // The given parameter should conform to the ReadMap
+ // concecpt and could be indiced by the current item set of
+ // the NodeMap. In this case the value for each item
+ // is assigned by the value of the given ReadMap.
+ template <typename CMap>
+ ArrayMap& operator=(const CMap& cmap) {
+ checkConcept<concepts::ReadMap<Key, _Value>, CMap>();
+ const typename Parent::Notifier* nf = Parent::notifier();
+ Item it;
+ for (nf->first(it); it != INVALID; nf->next(it)) {
+ set(it, cmap[it]);
+ }
+ return *this;
+ }
+
+ public:
+ // \brief The destructor of the map.
+ //
+ // The destructor of the map.
+ virtual ~ArrayMap() {
+ if (attached()) {
+ clear();
+ detach();
+ }
+ }
+
+ protected:
+
+ using Parent::attach;
+ using Parent::detach;
+ using Parent::attached;
+
+ public:
+
+ // \brief The subscript operator.
+ //
+ // The subscript operator. The map can be subscripted by the
+ // actual keys of the graph.
+ Value& operator[](const Key& key) {
+ int id = Parent::notifier()->id(key);
+ return values[id];
+ }
+
+ // \brief The const subscript operator.
+ //
+ // The const subscript operator. The map can be subscripted by the
+ // actual keys of the graph.
+ const Value& operator[](const Key& key) const {
+ int id = Parent::notifier()->id(key);
+ return values[id];
+ }
+
+ // \brief Setter function of the map.
+ //
+ // Setter function of the map. Equivalent with map[key] = val.
+ // This is a compatibility feature with the not dereferable maps.
+ void set(const Key& key, const Value& val) {
+ (*this)[key] = val;
+ }
+
+ protected:
+
+ // \brief Adds a new key to the map.
+ //
+ // It adds a new key to the map. It is called by the observer notifier
+ // and it overrides the add() member function of the observer base.
+ virtual void add(const Key& key) {
+ Notifier* nf = Parent::notifier();
+ int id = nf->id(key);
+ if (id >= capacity) {
+ int new_capacity = (capacity == 0 ? 1 : capacity);
+ while (new_capacity <= id) {
+ new_capacity <<= 1;
+ }
+ Value* new_values = allocator.allocate(new_capacity);
+ Item it;
+ for (nf->first(it); it != INVALID; nf->next(it)) {
+ int jd = nf->id(it);;
+ if (id != jd) {
+ allocator.construct(&(new_values[jd]), values[jd]);
+ allocator.destroy(&(values[jd]));
+ }
+ }
+ if (capacity != 0) allocator.deallocate(values, capacity);
+ values = new_values;
+ capacity = new_capacity;
+ }
+ allocator.construct(&(values[id]), Value());
+ }
+
+ // \brief Adds more new keys to the map.
+ //
+ // It adds more new keys to the map. It is called by the observer notifier
+ // and it overrides the add() member function of the observer base.
+ virtual void add(const std::vector<Key>& keys) {
+ Notifier* nf = Parent::notifier();
+ int max_id = -1;
+ for (int i = 0; i < int(keys.size()); ++i) {
+ int id = nf->id(keys[i]);
+ if (id > max_id) {
+ max_id = id;
+ }
+ }
+ if (max_id >= capacity) {
+ int new_capacity = (capacity == 0 ? 1 : capacity);
+ while (new_capacity <= max_id) {
+ new_capacity <<= 1;
+ }
+ Value* new_values = allocator.allocate(new_capacity);
+ Item it;
+ for (nf->first(it); it != INVALID; nf->next(it)) {
+ int id = nf->id(it);
+ bool found = false;
+ for (int i = 0; i < int(keys.size()); ++i) {
+ int jd = nf->id(keys[i]);
+ if (id == jd) {
+ found = true;
+ break;
+ }
+ }
+ if (found) continue;
+ allocator.construct(&(new_values[id]), values[id]);
+ allocator.destroy(&(values[id]));
+ }
+ if (capacity != 0) allocator.deallocate(values, capacity);
+ values = new_values;
+ capacity = new_capacity;
+ }
+ for (int i = 0; i < int(keys.size()); ++i) {
+ int id = nf->id(keys[i]);
+ allocator.construct(&(values[id]), Value());
+ }
+ }
+
+ // \brief Erase a key from the map.
+ //
+ // Erase a key from the map. It is called by the observer notifier
+ // and it overrides the erase() member function of the observer base.
+ virtual void erase(const Key& key) {
+ int id = Parent::notifier()->id(key);
+ allocator.destroy(&(values[id]));
+ }
+
+ // \brief Erase more keys from the map.
+ //
+ // Erase more keys from the map. It is called by the observer notifier
+ // and it overrides the erase() member function of the observer base.
+ virtual void erase(const std::vector<Key>& keys) {
+ for (int i = 0; i < int(keys.size()); ++i) {
+ int id = Parent::notifier()->id(keys[i]);
+ allocator.destroy(&(values[id]));
+ }
+ }
+
+ // \brief Builds the map.
+ //
+ // It builds the map. It is called by the observer notifier
+ // and it overrides the build() member function of the observer base.
+ virtual void build() {
+ Notifier* nf = Parent::notifier();
+ allocate_memory();
+ Item it;
+ for (nf->first(it); it != INVALID; nf->next(it)) {
+ int id = nf->id(it);;
+ allocator.construct(&(values[id]), Value());
+ }
+ }
+
+ // \brief Clear the map.
+ //
+ // It erase all items from the map. It is called by the observer notifier
+ // and it overrides the clear() member function of the observer base.
+ virtual void clear() {
+ Notifier* nf = Parent::notifier();
+ if (capacity != 0) {
+ Item it;
+ for (nf->first(it); it != INVALID; nf->next(it)) {
+ int id = nf->id(it);
+ allocator.destroy(&(values[id]));
+ }
+ allocator.deallocate(values, capacity);
+ capacity = 0;
+ }
+ }
+
+ private:
+
+ void allocate_memory() {
+ int max_id = Parent::notifier()->maxId();
+ if (max_id == -1) {
+ capacity = 0;
+ values = 0;
+ return;
+ }
+ capacity = 1;
+ while (capacity <= max_id) {
+ capacity <<= 1;
+ }
+ values = allocator.allocate(capacity);
+ }
+
+ int capacity;
+ Value* values;
+ Allocator allocator;
+
+ };
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/bezier.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/bezier.h
new file mode 100644
index 00000000000..9d8d1413d07
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/bezier.h
@@ -0,0 +1,174 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BEZIER_H
+#define LEMON_BEZIER_H
+
+//\ingroup misc
+//\file
+//\brief Classes to compute with Bezier curves.
+//
+//Up to now this file is used internally by \ref graph_to_eps.h
+
+#include<lemon/dim2.h>
+
+namespace lemon {
+ namespace dim2 {
+
+class BezierBase {
+public:
+ typedef lemon::dim2::Point<double> Point;
+protected:
+ static Point conv(Point x,Point y,double t) {return (1-t)*x+t*y;}
+};
+
+class Bezier1 : public BezierBase
+{
+public:
+ Point p1,p2;
+
+ Bezier1() {}
+ Bezier1(Point _p1, Point _p2) :p1(_p1), p2(_p2) {}
+
+ Point operator()(double t) const
+ {
+ // return conv(conv(p1,p2,t),conv(p2,p3,t),t);
+ return conv(p1,p2,t);
+ }
+ Bezier1 before(double t) const
+ {
+ return Bezier1(p1,conv(p1,p2,t));
+ }
+
+ Bezier1 after(double t) const
+ {
+ return Bezier1(conv(p1,p2,t),p2);
+ }
+
+ Bezier1 revert() const { return Bezier1(p2,p1);}
+ Bezier1 operator()(double a,double b) const { return before(b).after(a/b); }
+ Point grad() const { return p2-p1; }
+ Point norm() const { return rot90(p2-p1); }
+ Point grad(double) const { return grad(); }
+ Point norm(double t) const { return rot90(grad(t)); }
+};
+
+class Bezier2 : public BezierBase
+{
+public:
+ Point p1,p2,p3;
+
+ Bezier2() {}
+ Bezier2(Point _p1, Point _p2, Point _p3) :p1(_p1), p2(_p2), p3(_p3) {}
+ Bezier2(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,.5)), p3(b.p2) {}
+ Point operator()(double t) const
+ {
+ // return conv(conv(p1,p2,t),conv(p2,p3,t),t);
+ return ((1-t)*(1-t))*p1+(2*(1-t)*t)*p2+(t*t)*p3;
+ }
+ Bezier2 before(double t) const
+ {
+ Point q(conv(p1,p2,t));
+ Point r(conv(p2,p3,t));
+ return Bezier2(p1,q,conv(q,r,t));
+ }
+
+ Bezier2 after(double t) const
+ {
+ Point q(conv(p1,p2,t));
+ Point r(conv(p2,p3,t));
+ return Bezier2(conv(q,r,t),r,p3);
+ }
+ Bezier2 revert() const { return Bezier2(p3,p2,p1);}
+ Bezier2 operator()(double a,double b) const { return before(b).after(a/b); }
+ Bezier1 grad() const { return Bezier1(2.0*(p2-p1),2.0*(p3-p2)); }
+ Bezier1 norm() const { return Bezier1(2.0*rot90(p2-p1),2.0*rot90(p3-p2)); }
+ Point grad(double t) const { return grad()(t); }
+ Point norm(double t) const { return rot90(grad(t)); }
+};
+
+class Bezier3 : public BezierBase
+{
+public:
+ Point p1,p2,p3,p4;
+
+ Bezier3() {}
+ Bezier3(Point _p1, Point _p2, Point _p3, Point _p4)
+ : p1(_p1), p2(_p2), p3(_p3), p4(_p4) {}
+ Bezier3(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,1.0/3.0)),
+ p3(conv(b.p1,b.p2,2.0/3.0)), p4(b.p2) {}
+ Bezier3(const Bezier2 &b) : p1(b.p1), p2(conv(b.p1,b.p2,2.0/3.0)),
+ p3(conv(b.p2,b.p3,1.0/3.0)), p4(b.p3) {}
+
+ Point operator()(double t) const
+ {
+ // return Bezier2(conv(p1,p2,t),conv(p2,p3,t),conv(p3,p4,t))(t);
+ return ((1-t)*(1-t)*(1-t))*p1+(3*t*(1-t)*(1-t))*p2+
+ (3*t*t*(1-t))*p3+(t*t*t)*p4;
+ }
+ Bezier3 before(double t) const
+ {
+ Point p(conv(p1,p2,t));
+ Point q(conv(p2,p3,t));
+ Point r(conv(p3,p4,t));
+ Point a(conv(p,q,t));
+ Point b(conv(q,r,t));
+ Point c(conv(a,b,t));
+ return Bezier3(p1,p,a,c);
+ }
+
+ Bezier3 after(double t) const
+ {
+ Point p(conv(p1,p2,t));
+ Point q(conv(p2,p3,t));
+ Point r(conv(p3,p4,t));
+ Point a(conv(p,q,t));
+ Point b(conv(q,r,t));
+ Point c(conv(a,b,t));
+ return Bezier3(c,b,r,p4);
+ }
+ Bezier3 revert() const { return Bezier3(p4,p3,p2,p1);}
+ Bezier3 operator()(double a,double b) const { return before(b).after(a/b); }
+ Bezier2 grad() const { return Bezier2(3.0*(p2-p1),3.0*(p3-p2),3.0*(p4-p3)); }
+ Bezier2 norm() const { return Bezier2(3.0*rot90(p2-p1),
+ 3.0*rot90(p3-p2),
+ 3.0*rot90(p4-p3)); }
+ Point grad(double t) const { return grad()(t); }
+ Point norm(double t) const { return rot90(grad(t)); }
+
+ template<class R,class F,class S,class D>
+ R recSplit(F &_f,const S &_s,D _d) const
+ {
+ const Point a=(p1+p2)/2;
+ const Point b=(p2+p3)/2;
+ const Point c=(p3+p4)/2;
+ const Point d=(a+b)/2;
+ const Point e=(b+c)/2;
+ // const Point f=(d+e)/2;
+ R f1=_f(Bezier3(p1,a,d,e),_d);
+ R f2=_f(Bezier3(e,d,c,p4),_d);
+ return _s(f1,f2);
+ }
+
+};
+
+
+} //END OF NAMESPACE dim2
+} //END OF NAMESPACE lemon
+
+#endif // LEMON_BEZIER_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/default_map.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/default_map.h
new file mode 100644
index 00000000000..23728e427ad
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/default_map.h
@@ -0,0 +1,182 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BITS_DEFAULT_MAP_H
+#define LEMON_BITS_DEFAULT_MAP_H
+
+#include <lemon/config.h>
+#include <lemon/bits/array_map.h>
+#include <lemon/bits/vector_map.h>
+//#include <lemon/bits/debug_map.h>
+
+//\ingroup graphbits
+//\file
+//\brief Graph maps that construct and destruct their elements dynamically.
+
+namespace lemon {
+
+
+ //#ifndef LEMON_USE_DEBUG_MAP
+
+ template <typename _Graph, typename _Item, typename _Value>
+ struct DefaultMapSelector {
+ typedef ArrayMap<_Graph, _Item, _Value> Map;
+ };
+
+ // bool
+ template <typename _Graph, typename _Item>
+ struct DefaultMapSelector<_Graph, _Item, bool> {
+ typedef VectorMap<_Graph, _Item, bool> Map;
+ };
+
+ // char
+ template <typename _Graph, typename _Item>
+ struct DefaultMapSelector<_Graph, _Item, char> {
+ typedef VectorMap<_Graph, _Item, char> Map;
+ };
+
+ template <typename _Graph, typename _Item>
+ struct DefaultMapSelector<_Graph, _Item, signed char> {
+ typedef VectorMap<_Graph, _Item, signed char> Map;
+ };
+
+ template <typename _Graph, typename _Item>
+ struct DefaultMapSelector<_Graph, _Item, unsigned char> {
+ typedef VectorMap<_Graph, _Item, unsigned char> Map;
+ };
+
+
+ // int
+ template <typename _Graph, typename _Item>
+ struct DefaultMapSelector<_Graph, _Item, signed int> {
+ typedef VectorMap<_Graph, _Item, signed int> Map;
+ };
+
+ template <typename _Graph, typename _Item>
+ struct DefaultMapSelector<_Graph, _Item, unsigned int> {
+ typedef VectorMap<_Graph, _Item, unsigned int> Map;
+ };
+
+
+ // short
+ template <typename _Graph, typename _Item>
+ struct DefaultMapSelector<_Graph, _Item, signed short> {
+ typedef VectorMap<_Graph, _Item, signed short> Map;
+ };
+
+ template <typename _Graph, typename _Item>
+ struct DefaultMapSelector<_Graph, _Item, unsigned short> {
+ typedef VectorMap<_Graph, _Item, unsigned short> Map;
+ };
+
+
+ // long
+ template <typename _Graph, typename _Item>
+ struct DefaultMapSelector<_Graph, _Item, signed long> {
+ typedef VectorMap<_Graph, _Item, signed long> Map;
+ };
+
+ template <typename _Graph, typename _Item>
+ struct DefaultMapSelector<_Graph, _Item, unsigned long> {
+ typedef VectorMap<_Graph, _Item, unsigned long> Map;
+ };
+
+
+#if defined LEMON_HAVE_LONG_LONG
+
+ // long long
+ template <typename _Graph, typename _Item>
+ struct DefaultMapSelector<_Graph, _Item, signed long long> {
+ typedef VectorMap<_Graph, _Item, signed long long> Map;
+ };
+
+ template <typename _Graph, typename _Item>
+ struct DefaultMapSelector<_Graph, _Item, unsigned long long> {
+ typedef VectorMap<_Graph, _Item, unsigned long long> Map;
+ };
+
+#endif
+
+
+ // float
+ template <typename _Graph, typename _Item>
+ struct DefaultMapSelector<_Graph, _Item, float> {
+ typedef VectorMap<_Graph, _Item, float> Map;
+ };
+
+
+ // double
+ template <typename _Graph, typename _Item>
+ struct DefaultMapSelector<_Graph, _Item, double> {
+ typedef VectorMap<_Graph, _Item, double> Map;
+ };
+
+
+ // long double
+ template <typename _Graph, typename _Item>
+ struct DefaultMapSelector<_Graph, _Item, long double> {
+ typedef VectorMap<_Graph, _Item, long double> Map;
+ };
+
+
+ // pointer
+ template <typename _Graph, typename _Item, typename _Ptr>
+ struct DefaultMapSelector<_Graph, _Item, _Ptr*> {
+ typedef VectorMap<_Graph, _Item, _Ptr*> Map;
+ };
+
+// #else
+
+// template <typename _Graph, typename _Item, typename _Value>
+// struct DefaultMapSelector {
+// typedef DebugMap<_Graph, _Item, _Value> Map;
+// };
+
+// #endif
+
+ // DefaultMap class
+ template <typename _Graph, typename _Item, typename _Value>
+ class DefaultMap
+ : public DefaultMapSelector<_Graph, _Item, _Value>::Map {
+ typedef typename DefaultMapSelector<_Graph, _Item, _Value>::Map Parent;
+
+ public:
+ typedef DefaultMap<_Graph, _Item, _Value> Map;
+
+ typedef typename Parent::GraphType GraphType;
+ typedef typename Parent::Value Value;
+
+ explicit DefaultMap(const GraphType& graph) : Parent(graph) {}
+ DefaultMap(const GraphType& graph, const Value& value)
+ : Parent(graph, value) {}
+
+ DefaultMap& operator=(const DefaultMap& cmap) {
+ return operator=<DefaultMap>(cmap);
+ }
+
+ template <typename CMap>
+ DefaultMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+
+ };
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/edge_set_extender.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/edge_set_extender.h
new file mode 100644
index 00000000000..364ca2ee6a9
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/edge_set_extender.h
@@ -0,0 +1,627 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BITS_EDGE_SET_EXTENDER_H
+#define LEMON_BITS_EDGE_SET_EXTENDER_H
+
+#include <lemon/core.h>
+#include <lemon/error.h>
+#include <lemon/bits/default_map.h>
+#include <lemon/bits/map_extender.h>
+
+//\ingroup digraphbits
+//\file
+//\brief Extenders for the arc set types
+namespace lemon {
+
+ // \ingroup digraphbits
+ //
+ // \brief Extender for the ArcSets
+ template <typename Base>
+ class ArcSetExtender : public Base {
+ typedef Base Parent;
+
+ public:
+
+ typedef ArcSetExtender Digraph;
+
+ // Base extensions
+
+ typedef typename Parent::Node Node;
+ typedef typename Parent::Arc Arc;
+
+ int maxId(Node) const {
+ return Parent::maxNodeId();
+ }
+
+ int maxId(Arc) const {
+ return Parent::maxArcId();
+ }
+
+ Node fromId(int id, Node) const {
+ return Parent::nodeFromId(id);
+ }
+
+ Arc fromId(int id, Arc) const {
+ return Parent::arcFromId(id);
+ }
+
+ Node oppositeNode(const Node &n, const Arc &e) const {
+ if (n == Parent::source(e))
+ return Parent::target(e);
+ else if(n==Parent::target(e))
+ return Parent::source(e);
+ else
+ return INVALID;
+ }
+
+
+ // Alteration notifier extensions
+
+ // The arc observer registry.
+ typedef AlterationNotifier<ArcSetExtender, Arc> ArcNotifier;
+
+ protected:
+
+ mutable ArcNotifier arc_notifier;
+
+ public:
+
+ using Parent::notifier;
+
+ // Gives back the arc alteration notifier.
+ ArcNotifier& notifier(Arc) const {
+ return arc_notifier;
+ }
+
+ // Iterable extensions
+
+ class NodeIt : public Node {
+ const Digraph* digraph;
+ public:
+
+ NodeIt() {}
+
+ NodeIt(Invalid i) : Node(i) { }
+
+ explicit NodeIt(const Digraph& _graph) : digraph(&_graph) {
+ _graph.first(static_cast<Node&>(*this));
+ }
+
+ NodeIt(const Digraph& _graph, const Node& node)
+ : Node(node), digraph(&_graph) {}
+
+ NodeIt& operator++() {
+ digraph->next(*this);
+ return *this;
+ }
+
+ };
+
+
+ class ArcIt : public Arc {
+ const Digraph* digraph;
+ public:
+
+ ArcIt() { }
+
+ ArcIt(Invalid i) : Arc(i) { }
+
+ explicit ArcIt(const Digraph& _graph) : digraph(&_graph) {
+ _graph.first(static_cast<Arc&>(*this));
+ }
+
+ ArcIt(const Digraph& _graph, const Arc& e) :
+ Arc(e), digraph(&_graph) { }
+
+ ArcIt& operator++() {
+ digraph->next(*this);
+ return *this;
+ }
+
+ };
+
+
+ class OutArcIt : public Arc {
+ const Digraph* digraph;
+ public:
+
+ OutArcIt() { }
+
+ OutArcIt(Invalid i) : Arc(i) { }
+
+ OutArcIt(const Digraph& _graph, const Node& node)
+ : digraph(&_graph) {
+ _graph.firstOut(*this, node);
+ }
+
+ OutArcIt(const Digraph& _graph, const Arc& arc)
+ : Arc(arc), digraph(&_graph) {}
+
+ OutArcIt& operator++() {
+ digraph->nextOut(*this);
+ return *this;
+ }
+
+ };
+
+
+ class InArcIt : public Arc {
+ const Digraph* digraph;
+ public:
+
+ InArcIt() { }
+
+ InArcIt(Invalid i) : Arc(i) { }
+
+ InArcIt(const Digraph& _graph, const Node& node)
+ : digraph(&_graph) {
+ _graph.firstIn(*this, node);
+ }
+
+ InArcIt(const Digraph& _graph, const Arc& arc) :
+ Arc(arc), digraph(&_graph) {}
+
+ InArcIt& operator++() {
+ digraph->nextIn(*this);
+ return *this;
+ }
+
+ };
+
+ // \brief Base node of the iterator
+ //
+ // Returns the base node (ie. the source in this case) of the iterator
+ Node baseNode(const OutArcIt &e) const {
+ return Parent::source(static_cast<const Arc&>(e));
+ }
+ // \brief Running node of the iterator
+ //
+ // Returns the running node (ie. the target in this case) of the
+ // iterator
+ Node runningNode(const OutArcIt &e) const {
+ return Parent::target(static_cast<const Arc&>(e));
+ }
+
+ // \brief Base node of the iterator
+ //
+ // Returns the base node (ie. the target in this case) of the iterator
+ Node baseNode(const InArcIt &e) const {
+ return Parent::target(static_cast<const Arc&>(e));
+ }
+ // \brief Running node of the iterator
+ //
+ // Returns the running node (ie. the source in this case) of the
+ // iterator
+ Node runningNode(const InArcIt &e) const {
+ return Parent::source(static_cast<const Arc&>(e));
+ }
+
+ using Parent::first;
+
+ // Mappable extension
+
+ template <typename _Value>
+ class ArcMap
+ : public MapExtender<DefaultMap<Digraph, Arc, _Value> > {
+ typedef MapExtender<DefaultMap<Digraph, Arc, _Value> > Parent;
+
+ public:
+ explicit ArcMap(const Digraph& _g)
+ : Parent(_g) {}
+ ArcMap(const Digraph& _g, const _Value& _v)
+ : Parent(_g, _v) {}
+
+ ArcMap& operator=(const ArcMap& cmap) {
+ return operator=<ArcMap>(cmap);
+ }
+
+ template <typename CMap>
+ ArcMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+
+ };
+
+
+ // Alteration extension
+
+ Arc addArc(const Node& from, const Node& to) {
+ Arc arc = Parent::addArc(from, to);
+ notifier(Arc()).add(arc);
+ return arc;
+ }
+
+ void clear() {
+ notifier(Arc()).clear();
+ Parent::clear();
+ }
+
+ void erase(const Arc& arc) {
+ notifier(Arc()).erase(arc);
+ Parent::erase(arc);
+ }
+
+ ArcSetExtender() {
+ arc_notifier.setContainer(*this);
+ }
+
+ ~ArcSetExtender() {
+ arc_notifier.clear();
+ }
+
+ };
+
+
+ // \ingroup digraphbits
+ //
+ // \brief Extender for the EdgeSets
+ template <typename Base>
+ class EdgeSetExtender : public Base {
+ typedef Base Parent;
+
+ public:
+
+ typedef EdgeSetExtender Graph;
+
+ typedef True UndirectedTag;
+
+ typedef typename Parent::Node Node;
+ typedef typename Parent::Arc Arc;
+ typedef typename Parent::Edge Edge;
+
+ int maxId(Node) const {
+ return Parent::maxNodeId();
+ }
+
+ int maxId(Arc) const {
+ return Parent::maxArcId();
+ }
+
+ int maxId(Edge) const {
+ return Parent::maxEdgeId();
+ }
+
+ Node fromId(int id, Node) const {
+ return Parent::nodeFromId(id);
+ }
+
+ Arc fromId(int id, Arc) const {
+ return Parent::arcFromId(id);
+ }
+
+ Edge fromId(int id, Edge) const {
+ return Parent::edgeFromId(id);
+ }
+
+ Node oppositeNode(const Node &n, const Edge &e) const {
+ if( n == Parent::u(e))
+ return Parent::v(e);
+ else if( n == Parent::v(e))
+ return Parent::u(e);
+ else
+ return INVALID;
+ }
+
+ Arc oppositeArc(const Arc &e) const {
+ return Parent::direct(e, !Parent::direction(e));
+ }
+
+ using Parent::direct;
+ Arc direct(const Edge &e, const Node &s) const {
+ return Parent::direct(e, Parent::u(e) == s);
+ }
+
+ typedef AlterationNotifier<EdgeSetExtender, Arc> ArcNotifier;
+ typedef AlterationNotifier<EdgeSetExtender, Edge> EdgeNotifier;
+
+
+ protected:
+
+ mutable ArcNotifier arc_notifier;
+ mutable EdgeNotifier edge_notifier;
+
+ public:
+
+ using Parent::notifier;
+
+ ArcNotifier& notifier(Arc) const {
+ return arc_notifier;
+ }
+
+ EdgeNotifier& notifier(Edge) const {
+ return edge_notifier;
+ }
+
+
+ class NodeIt : public Node {
+ const Graph* graph;
+ public:
+
+ NodeIt() {}
+
+ NodeIt(Invalid i) : Node(i) { }
+
+ explicit NodeIt(const Graph& _graph) : graph(&_graph) {
+ _graph.first(static_cast<Node&>(*this));
+ }
+
+ NodeIt(const Graph& _graph, const Node& node)
+ : Node(node), graph(&_graph) {}
+
+ NodeIt& operator++() {
+ graph->next(*this);
+ return *this;
+ }
+
+ };
+
+
+ class ArcIt : public Arc {
+ const Graph* graph;
+ public:
+
+ ArcIt() { }
+
+ ArcIt(Invalid i) : Arc(i) { }
+
+ explicit ArcIt(const Graph& _graph) : graph(&_graph) {
+ _graph.first(static_cast<Arc&>(*this));
+ }
+
+ ArcIt(const Graph& _graph, const Arc& e) :
+ Arc(e), graph(&_graph) { }
+
+ ArcIt& operator++() {
+ graph->next(*this);
+ return *this;
+ }
+
+ };
+
+
+ class OutArcIt : public Arc {
+ const Graph* graph;
+ public:
+
+ OutArcIt() { }
+
+ OutArcIt(Invalid i) : Arc(i) { }
+
+ OutArcIt(const Graph& _graph, const Node& node)
+ : graph(&_graph) {
+ _graph.firstOut(*this, node);
+ }
+
+ OutArcIt(const Graph& _graph, const Arc& arc)
+ : Arc(arc), graph(&_graph) {}
+
+ OutArcIt& operator++() {
+ graph->nextOut(*this);
+ return *this;
+ }
+
+ };
+
+
+ class InArcIt : public Arc {
+ const Graph* graph;
+ public:
+
+ InArcIt() { }
+
+ InArcIt(Invalid i) : Arc(i) { }
+
+ InArcIt(const Graph& _graph, const Node& node)
+ : graph(&_graph) {
+ _graph.firstIn(*this, node);
+ }
+
+ InArcIt(const Graph& _graph, const Arc& arc) :
+ Arc(arc), graph(&_graph) {}
+
+ InArcIt& operator++() {
+ graph->nextIn(*this);
+ return *this;
+ }
+
+ };
+
+
+ class EdgeIt : public Parent::Edge {
+ const Graph* graph;
+ public:
+
+ EdgeIt() { }
+
+ EdgeIt(Invalid i) : Edge(i) { }
+
+ explicit EdgeIt(const Graph& _graph) : graph(&_graph) {
+ _graph.first(static_cast<Edge&>(*this));
+ }
+
+ EdgeIt(const Graph& _graph, const Edge& e) :
+ Edge(e), graph(&_graph) { }
+
+ EdgeIt& operator++() {
+ graph->next(*this);
+ return *this;
+ }
+
+ };
+
+ class IncEdgeIt : public Parent::Edge {
+ friend class EdgeSetExtender;
+ const Graph* graph;
+ bool direction;
+ public:
+
+ IncEdgeIt() { }
+
+ IncEdgeIt(Invalid i) : Edge(i), direction(false) { }
+
+ IncEdgeIt(const Graph& _graph, const Node &n) : graph(&_graph) {
+ _graph.firstInc(*this, direction, n);
+ }
+
+ IncEdgeIt(const Graph& _graph, const Edge &ue, const Node &n)
+ : graph(&_graph), Edge(ue) {
+ direction = (_graph.source(ue) == n);
+ }
+
+ IncEdgeIt& operator++() {
+ graph->nextInc(*this, direction);
+ return *this;
+ }
+ };
+
+ // \brief Base node of the iterator
+ //
+ // Returns the base node (ie. the source in this case) of the iterator
+ Node baseNode(const OutArcIt &e) const {
+ return Parent::source(static_cast<const Arc&>(e));
+ }
+ // \brief Running node of the iterator
+ //
+ // Returns the running node (ie. the target in this case) of the
+ // iterator
+ Node runningNode(const OutArcIt &e) const {
+ return Parent::target(static_cast<const Arc&>(e));
+ }
+
+ // \brief Base node of the iterator
+ //
+ // Returns the base node (ie. the target in this case) of the iterator
+ Node baseNode(const InArcIt &e) const {
+ return Parent::target(static_cast<const Arc&>(e));
+ }
+ // \brief Running node of the iterator
+ //
+ // Returns the running node (ie. the source in this case) of the
+ // iterator
+ Node runningNode(const InArcIt &e) const {
+ return Parent::source(static_cast<const Arc&>(e));
+ }
+
+ // Base node of the iterator
+ //
+ // Returns the base node of the iterator
+ Node baseNode(const IncEdgeIt &e) const {
+ return e.direction ? this->u(e) : this->v(e);
+ }
+ // Running node of the iterator
+ //
+ // Returns the running node of the iterator
+ Node runningNode(const IncEdgeIt &e) const {
+ return e.direction ? this->v(e) : this->u(e);
+ }
+
+
+ template <typename _Value>
+ class ArcMap
+ : public MapExtender<DefaultMap<Graph, Arc, _Value> > {
+ typedef MapExtender<DefaultMap<Graph, Arc, _Value> > Parent;
+
+ public:
+ explicit ArcMap(const Graph& _g)
+ : Parent(_g) {}
+ ArcMap(const Graph& _g, const _Value& _v)
+ : Parent(_g, _v) {}
+
+ ArcMap& operator=(const ArcMap& cmap) {
+ return operator=<ArcMap>(cmap);
+ }
+
+ template <typename CMap>
+ ArcMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+
+ };
+
+
+ template <typename _Value>
+ class EdgeMap
+ : public MapExtender<DefaultMap<Graph, Edge, _Value> > {
+ typedef MapExtender<DefaultMap<Graph, Edge, _Value> > Parent;
+
+ public:
+ explicit EdgeMap(const Graph& _g)
+ : Parent(_g) {}
+
+ EdgeMap(const Graph& _g, const _Value& _v)
+ : Parent(_g, _v) {}
+
+ EdgeMap& operator=(const EdgeMap& cmap) {
+ return operator=<EdgeMap>(cmap);
+ }
+
+ template <typename CMap>
+ EdgeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+
+ };
+
+
+ // Alteration extension
+
+ Edge addEdge(const Node& from, const Node& to) {
+ Edge edge = Parent::addEdge(from, to);
+ notifier(Edge()).add(edge);
+ std::vector<Arc> arcs;
+ arcs.push_back(Parent::direct(edge, true));
+ arcs.push_back(Parent::direct(edge, false));
+ notifier(Arc()).add(arcs);
+ return edge;
+ }
+
+ void clear() {
+ notifier(Arc()).clear();
+ notifier(Edge()).clear();
+ Parent::clear();
+ }
+
+ void erase(const Edge& edge) {
+ std::vector<Arc> arcs;
+ arcs.push_back(Parent::direct(edge, true));
+ arcs.push_back(Parent::direct(edge, false));
+ notifier(Arc()).erase(arcs);
+ notifier(Edge()).erase(edge);
+ Parent::erase(edge);
+ }
+
+
+ EdgeSetExtender() {
+ arc_notifier.setContainer(*this);
+ edge_notifier.setContainer(*this);
+ }
+
+ ~EdgeSetExtender() {
+ edge_notifier.clear();
+ arc_notifier.clear();
+ }
+
+ };
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/enable_if.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/enable_if.h
new file mode 100644
index 00000000000..f0d8de4d3cc
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/enable_if.h
@@ -0,0 +1,131 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+// This file contains a modified version of the enable_if library from BOOST.
+// See the appropriate copyright notice below.
+
+// Boost enable_if library
+
+// Copyright 2003 (c) The Trustees of Indiana University.
+
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Jaakko Jarvi (jajarvi at osl.iu.edu)
+// Jeremiah Willcock (jewillco at osl.iu.edu)
+// Andrew Lumsdaine (lums at osl.iu.edu)
+
+
+#ifndef LEMON_BITS_ENABLE_IF_H
+#define LEMON_BITS_ENABLE_IF_H
+
+//\file
+//\brief Miscellaneous basic utilities
+
+namespace lemon
+{
+
+ // Basic type for defining "tags". A "YES" condition for \c enable_if.
+
+ // Basic type for defining "tags". A "YES" condition for \c enable_if.
+ //
+ //\sa False
+ struct True {
+ //\e
+ static const bool value = true;
+ };
+
+ // Basic type for defining "tags". A "NO" condition for \c enable_if.
+
+ // Basic type for defining "tags". A "NO" condition for \c enable_if.
+ //
+ //\sa True
+ struct False {
+ //\e
+ static const bool value = false;
+ };
+
+
+
+ template <typename T>
+ struct Wrap {
+ const T &value;
+ Wrap(const T &t) : value(t) {}
+ };
+
+ /**************** dummy class to avoid ambiguity ****************/
+
+ template<int T> struct dummy { dummy(int) {} };
+
+ /**************** enable_if from BOOST ****************/
+
+ template <typename Type, typename T = void>
+ struct exists {
+ typedef T type;
+ };
+
+
+ template <bool B, class T = void>
+ struct enable_if_c {
+ typedef T type;
+ };
+
+ template <class T>
+ struct enable_if_c<false, T> {};
+
+ template <class Cond, class T = void>
+ struct enable_if : public enable_if_c<Cond::value, T> {};
+
+ template <bool B, class T>
+ struct lazy_enable_if_c {
+ typedef typename T::type type;
+ };
+
+ template <class T>
+ struct lazy_enable_if_c<false, T> {};
+
+ template <class Cond, class T>
+ struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};
+
+
+ template <bool B, class T = void>
+ struct disable_if_c {
+ typedef T type;
+ };
+
+ template <class T>
+ struct disable_if_c<true, T> {};
+
+ template <class Cond, class T = void>
+ struct disable_if : public disable_if_c<Cond::value, T> {};
+
+ template <bool B, class T>
+ struct lazy_disable_if_c {
+ typedef typename T::type type;
+ };
+
+ template <class T>
+ struct lazy_disable_if_c<true, T> {};
+
+ template <class Cond, class T>
+ struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};
+
+} // namespace lemon
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/graph_adaptor_extender.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/graph_adaptor_extender.h
new file mode 100644
index 00000000000..c38c8e1d608
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/graph_adaptor_extender.h
@@ -0,0 +1,401 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BITS_GRAPH_ADAPTOR_EXTENDER_H
+#define LEMON_BITS_GRAPH_ADAPTOR_EXTENDER_H
+
+#include <lemon/core.h>
+#include <lemon/error.h>
+
+namespace lemon {
+
+ template <typename _Digraph>
+ class DigraphAdaptorExtender : public _Digraph {
+ typedef _Digraph Parent;
+
+ public:
+
+ typedef _Digraph Digraph;
+ typedef DigraphAdaptorExtender Adaptor;
+
+ // Base extensions
+
+ typedef typename Parent::Node Node;
+ typedef typename Parent::Arc Arc;
+
+ int maxId(Node) const {
+ return Parent::maxNodeId();
+ }
+
+ int maxId(Arc) const {
+ return Parent::maxArcId();
+ }
+
+ Node fromId(int id, Node) const {
+ return Parent::nodeFromId(id);
+ }
+
+ Arc fromId(int id, Arc) const {
+ return Parent::arcFromId(id);
+ }
+
+ Node oppositeNode(const Node &n, const Arc &e) const {
+ if (n == Parent::source(e))
+ return Parent::target(e);
+ else if(n==Parent::target(e))
+ return Parent::source(e);
+ else
+ return INVALID;
+ }
+
+ class NodeIt : public Node {
+ const Adaptor* _adaptor;
+ public:
+
+ NodeIt() {}
+
+ NodeIt(Invalid i) : Node(i) { }
+
+ explicit NodeIt(const Adaptor& adaptor) : _adaptor(&adaptor) {
+ _adaptor->first(static_cast<Node&>(*this));
+ }
+
+ NodeIt(const Adaptor& adaptor, const Node& node)
+ : Node(node), _adaptor(&adaptor) {}
+
+ NodeIt& operator++() {
+ _adaptor->next(*this);
+ return *this;
+ }
+
+ };
+
+
+ class ArcIt : public Arc {
+ const Adaptor* _adaptor;
+ public:
+
+ ArcIt() { }
+
+ ArcIt(Invalid i) : Arc(i) { }
+
+ explicit ArcIt(const Adaptor& adaptor) : _adaptor(&adaptor) {
+ _adaptor->first(static_cast<Arc&>(*this));
+ }
+
+ ArcIt(const Adaptor& adaptor, const Arc& e) :
+ Arc(e), _adaptor(&adaptor) { }
+
+ ArcIt& operator++() {
+ _adaptor->next(*this);
+ return *this;
+ }
+
+ };
+
+
+ class OutArcIt : public Arc {
+ const Adaptor* _adaptor;
+ public:
+
+ OutArcIt() { }
+
+ OutArcIt(Invalid i) : Arc(i) { }
+
+ OutArcIt(const Adaptor& adaptor, const Node& node)
+ : _adaptor(&adaptor) {
+ _adaptor->firstOut(*this, node);
+ }
+
+ OutArcIt(const Adaptor& adaptor, const Arc& arc)
+ : Arc(arc), _adaptor(&adaptor) {}
+
+ OutArcIt& operator++() {
+ _adaptor->nextOut(*this);
+ return *this;
+ }
+
+ };
+
+
+ class InArcIt : public Arc {
+ const Adaptor* _adaptor;
+ public:
+
+ InArcIt() { }
+
+ InArcIt(Invalid i) : Arc(i) { }
+
+ InArcIt(const Adaptor& adaptor, const Node& node)
+ : _adaptor(&adaptor) {
+ _adaptor->firstIn(*this, node);
+ }
+
+ InArcIt(const Adaptor& adaptor, const Arc& arc) :
+ Arc(arc), _adaptor(&adaptor) {}
+
+ InArcIt& operator++() {
+ _adaptor->nextIn(*this);
+ return *this;
+ }
+
+ };
+
+ Node baseNode(const OutArcIt &e) const {
+ return Parent::source(e);
+ }
+ Node runningNode(const OutArcIt &e) const {
+ return Parent::target(e);
+ }
+
+ Node baseNode(const InArcIt &e) const {
+ return Parent::target(e);
+ }
+ Node runningNode(const InArcIt &e) const {
+ return Parent::source(e);
+ }
+
+ };
+
+ template <typename _Graph>
+ class GraphAdaptorExtender : public _Graph {
+ typedef _Graph Parent;
+
+ public:
+
+ typedef _Graph Graph;
+ typedef GraphAdaptorExtender Adaptor;
+
+ typedef True UndirectedTag;
+
+ typedef typename Parent::Node Node;
+ typedef typename Parent::Arc Arc;
+ typedef typename Parent::Edge Edge;
+
+ // Graph extension
+
+ int maxId(Node) const {
+ return Parent::maxNodeId();
+ }
+
+ int maxId(Arc) const {
+ return Parent::maxArcId();
+ }
+
+ int maxId(Edge) const {
+ return Parent::maxEdgeId();
+ }
+
+ Node fromId(int id, Node) const {
+ return Parent::nodeFromId(id);
+ }
+
+ Arc fromId(int id, Arc) const {
+ return Parent::arcFromId(id);
+ }
+
+ Edge fromId(int id, Edge) const {
+ return Parent::edgeFromId(id);
+ }
+
+ Node oppositeNode(const Node &n, const Edge &e) const {
+ if( n == Parent::u(e))
+ return Parent::v(e);
+ else if( n == Parent::v(e))
+ return Parent::u(e);
+ else
+ return INVALID;
+ }
+
+ Arc oppositeArc(const Arc &a) const {
+ return Parent::direct(a, !Parent::direction(a));
+ }
+
+ using Parent::direct;
+ Arc direct(const Edge &e, const Node &s) const {
+ return Parent::direct(e, Parent::u(e) == s);
+ }
+
+
+ class NodeIt : public Node {
+ const Adaptor* _adaptor;
+ public:
+
+ NodeIt() {}
+
+ NodeIt(Invalid i) : Node(i) { }
+
+ explicit NodeIt(const Adaptor& adaptor) : _adaptor(&adaptor) {
+ _adaptor->first(static_cast<Node&>(*this));
+ }
+
+ NodeIt(const Adaptor& adaptor, const Node& node)
+ : Node(node), _adaptor(&adaptor) {}
+
+ NodeIt& operator++() {
+ _adaptor->next(*this);
+ return *this;
+ }
+
+ };
+
+
+ class ArcIt : public Arc {
+ const Adaptor* _adaptor;
+ public:
+
+ ArcIt() { }
+
+ ArcIt(Invalid i) : Arc(i) { }
+
+ explicit ArcIt(const Adaptor& adaptor) : _adaptor(&adaptor) {
+ _adaptor->first(static_cast<Arc&>(*this));
+ }
+
+ ArcIt(const Adaptor& adaptor, const Arc& e) :
+ Arc(e), _adaptor(&adaptor) { }
+
+ ArcIt& operator++() {
+ _adaptor->next(*this);
+ return *this;
+ }
+
+ };
+
+
+ class OutArcIt : public Arc {
+ const Adaptor* _adaptor;
+ public:
+
+ OutArcIt() { }
+
+ OutArcIt(Invalid i) : Arc(i) { }
+
+ OutArcIt(const Adaptor& adaptor, const Node& node)
+ : _adaptor(&adaptor) {
+ _adaptor->firstOut(*this, node);
+ }
+
+ OutArcIt(const Adaptor& adaptor, const Arc& arc)
+ : Arc(arc), _adaptor(&adaptor) {}
+
+ OutArcIt& operator++() {
+ _adaptor->nextOut(*this);
+ return *this;
+ }
+
+ };
+
+
+ class InArcIt : public Arc {
+ const Adaptor* _adaptor;
+ public:
+
+ InArcIt() { }
+
+ InArcIt(Invalid i) : Arc(i) { }
+
+ InArcIt(const Adaptor& adaptor, const Node& node)
+ : _adaptor(&adaptor) {
+ _adaptor->firstIn(*this, node);
+ }
+
+ InArcIt(const Adaptor& adaptor, const Arc& arc) :
+ Arc(arc), _adaptor(&adaptor) {}
+
+ InArcIt& operator++() {
+ _adaptor->nextIn(*this);
+ return *this;
+ }
+
+ };
+
+ class EdgeIt : public Parent::Edge {
+ const Adaptor* _adaptor;
+ public:
+
+ EdgeIt() { }
+
+ EdgeIt(Invalid i) : Edge(i) { }
+
+ explicit EdgeIt(const Adaptor& adaptor) : _adaptor(&adaptor) {
+ _adaptor->first(static_cast<Edge&>(*this));
+ }
+
+ EdgeIt(const Adaptor& adaptor, const Edge& e) :
+ Edge(e), _adaptor(&adaptor) { }
+
+ EdgeIt& operator++() {
+ _adaptor->next(*this);
+ return *this;
+ }
+
+ };
+
+ class IncEdgeIt : public Edge {
+ friend class GraphAdaptorExtender;
+ const Adaptor* _adaptor;
+ bool direction;
+ public:
+
+ IncEdgeIt() { }
+
+ IncEdgeIt(Invalid i) : Edge(i), direction(false) { }
+
+ IncEdgeIt(const Adaptor& adaptor, const Node &n) : _adaptor(&adaptor) {
+ _adaptor->firstInc(static_cast<Edge&>(*this), direction, n);
+ }
+
+ IncEdgeIt(const Adaptor& adaptor, const Edge &e, const Node &n)
+ : _adaptor(&adaptor), Edge(e) {
+ direction = (_adaptor->u(e) == n);
+ }
+
+ IncEdgeIt& operator++() {
+ _adaptor->nextInc(*this, direction);
+ return *this;
+ }
+ };
+
+ Node baseNode(const OutArcIt &a) const {
+ return Parent::source(a);
+ }
+ Node runningNode(const OutArcIt &a) const {
+ return Parent::target(a);
+ }
+
+ Node baseNode(const InArcIt &a) const {
+ return Parent::target(a);
+ }
+ Node runningNode(const InArcIt &a) const {
+ return Parent::source(a);
+ }
+
+ Node baseNode(const IncEdgeIt &e) const {
+ return e.direction ? Parent::u(e) : Parent::v(e);
+ }
+ Node runningNode(const IncEdgeIt &e) const {
+ return e.direction ? Parent::v(e) : Parent::u(e);
+ }
+
+ };
+
+}
+
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/graph_extender.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/graph_extender.h
new file mode 100644
index 00000000000..755a8907f50
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/graph_extender.h
@@ -0,0 +1,1332 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BITS_GRAPH_EXTENDER_H
+#define LEMON_BITS_GRAPH_EXTENDER_H
+
+#include <lemon/core.h>
+
+#include <lemon/bits/map_extender.h>
+#include <lemon/bits/default_map.h>
+
+#include <lemon/concept_check.h>
+#include <lemon/concepts/maps.h>
+
+//\ingroup graphbits
+//\file
+//\brief Extenders for the graph types
+namespace lemon {
+
+ // \ingroup graphbits
+ //
+ // \brief Extender for the digraph implementations
+ template <typename Base>
+ class DigraphExtender : public Base {
+ typedef Base Parent;
+
+ public:
+
+ typedef DigraphExtender Digraph;
+
+ // Base extensions
+
+ typedef typename Parent::Node Node;
+ typedef typename Parent::Arc Arc;
+
+ int maxId(Node) const {
+ return Parent::maxNodeId();
+ }
+
+ int maxId(Arc) const {
+ return Parent::maxArcId();
+ }
+
+ static Node fromId(int id, Node) {
+ return Parent::nodeFromId(id);
+ }
+
+ static Arc fromId(int id, Arc) {
+ return Parent::arcFromId(id);
+ }
+
+ Node oppositeNode(const Node &node, const Arc &arc) const {
+ if (node == Parent::source(arc))
+ return Parent::target(arc);
+ else if(node == Parent::target(arc))
+ return Parent::source(arc);
+ else
+ return INVALID;
+ }
+
+ // Alterable extension
+
+ typedef AlterationNotifier<DigraphExtender, Node> NodeNotifier;
+ typedef AlterationNotifier<DigraphExtender, Arc> ArcNotifier;
+
+
+ protected:
+
+ mutable NodeNotifier node_notifier;
+ mutable ArcNotifier arc_notifier;
+
+ public:
+
+ NodeNotifier& notifier(Node) const {
+ return node_notifier;
+ }
+
+ ArcNotifier& notifier(Arc) const {
+ return arc_notifier;
+ }
+
+ class NodeIt : public Node {
+ const Digraph* _digraph;
+ public:
+
+ NodeIt() {}
+
+ NodeIt(Invalid i) : Node(i) { }
+
+ explicit NodeIt(const Digraph& digraph) : _digraph(&digraph) {
+ _digraph->first(static_cast<Node&>(*this));
+ }
+
+ NodeIt(const Digraph& digraph, const Node& node)
+ : Node(node), _digraph(&digraph) {}
+
+ NodeIt& operator++() {
+ _digraph->next(*this);
+ return *this;
+ }
+
+ };
+
+
+ class ArcIt : public Arc {
+ const Digraph* _digraph;
+ public:
+
+ ArcIt() { }
+
+ ArcIt(Invalid i) : Arc(i) { }
+
+ explicit ArcIt(const Digraph& digraph) : _digraph(&digraph) {
+ _digraph->first(static_cast<Arc&>(*this));
+ }
+
+ ArcIt(const Digraph& digraph, const Arc& arc) :
+ Arc(arc), _digraph(&digraph) { }
+
+ ArcIt& operator++() {
+ _digraph->next(*this);
+ return *this;
+ }
+
+ };
+
+
+ class OutArcIt : public Arc {
+ const Digraph* _digraph;
+ public:
+
+ OutArcIt() { }
+
+ OutArcIt(Invalid i) : Arc(i) { }
+
+ OutArcIt(const Digraph& digraph, const Node& node)
+ : _digraph(&digraph) {
+ _digraph->firstOut(*this, node);
+ }
+
+ OutArcIt(const Digraph& digraph, const Arc& arc)
+ : Arc(arc), _digraph(&digraph) {}
+
+ OutArcIt& operator++() {
+ _digraph->nextOut(*this);
+ return *this;
+ }
+
+ };
+
+
+ class InArcIt : public Arc {
+ const Digraph* _digraph;
+ public:
+
+ InArcIt() { }
+
+ InArcIt(Invalid i) : Arc(i) { }
+
+ InArcIt(const Digraph& digraph, const Node& node)
+ : _digraph(&digraph) {
+ _digraph->firstIn(*this, node);
+ }
+
+ InArcIt(const Digraph& digraph, const Arc& arc) :
+ Arc(arc), _digraph(&digraph) {}
+
+ InArcIt& operator++() {
+ _digraph->nextIn(*this);
+ return *this;
+ }
+
+ };
+
+ // \brief Base node of the iterator
+ //
+ // Returns the base node (i.e. the source in this case) of the iterator
+ Node baseNode(const OutArcIt &arc) const {
+ return Parent::source(arc);
+ }
+ // \brief Running node of the iterator
+ //
+ // Returns the running node (i.e. the target in this case) of the
+ // iterator
+ Node runningNode(const OutArcIt &arc) const {
+ return Parent::target(arc);
+ }
+
+ // \brief Base node of the iterator
+ //
+ // Returns the base node (i.e. the target in this case) of the iterator
+ Node baseNode(const InArcIt &arc) const {
+ return Parent::target(arc);
+ }
+ // \brief Running node of the iterator
+ //
+ // Returns the running node (i.e. the source in this case) of the
+ // iterator
+ Node runningNode(const InArcIt &arc) const {
+ return Parent::source(arc);
+ }
+
+
+ template <typename _Value>
+ class NodeMap
+ : public MapExtender<DefaultMap<Digraph, Node, _Value> > {
+ typedef MapExtender<DefaultMap<Digraph, Node, _Value> > Parent;
+
+ public:
+ explicit NodeMap(const Digraph& digraph)
+ : Parent(digraph) {}
+ NodeMap(const Digraph& digraph, const _Value& value)
+ : Parent(digraph, value) {}
+
+ private:
+ NodeMap& operator=(const NodeMap& cmap) {
+ return operator=<NodeMap>(cmap);
+ }
+
+ template <typename CMap>
+ NodeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+
+ };
+
+ template <typename _Value>
+ class ArcMap
+ : public MapExtender<DefaultMap<Digraph, Arc, _Value> > {
+ typedef MapExtender<DefaultMap<Digraph, Arc, _Value> > Parent;
+
+ public:
+ explicit ArcMap(const Digraph& digraph)
+ : Parent(digraph) {}
+ ArcMap(const Digraph& digraph, const _Value& value)
+ : Parent(digraph, value) {}
+
+ private:
+ ArcMap& operator=(const ArcMap& cmap) {
+ return operator=<ArcMap>(cmap);
+ }
+
+ template <typename CMap>
+ ArcMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+
+ Node addNode() {
+ Node node = Parent::addNode();
+ notifier(Node()).add(node);
+ return node;
+ }
+
+ Arc addArc(const Node& from, const Node& to) {
+ Arc arc = Parent::addArc(from, to);
+ notifier(Arc()).add(arc);
+ return arc;
+ }
+
+ void clear() {
+ notifier(Arc()).clear();
+ notifier(Node()).clear();
+ Parent::clear();
+ }
+
+ template <typename Digraph, typename NodeRefMap, typename ArcRefMap>
+ void build(const Digraph& digraph, NodeRefMap& nodeRef, ArcRefMap& arcRef) {
+ Parent::build(digraph, nodeRef, arcRef);
+ notifier(Node()).build();
+ notifier(Arc()).build();
+ }
+
+ void erase(const Node& node) {
+ Arc arc;
+ Parent::firstOut(arc, node);
+ while (arc != INVALID ) {
+ erase(arc);
+ Parent::firstOut(arc, node);
+ }
+
+ Parent::firstIn(arc, node);
+ while (arc != INVALID ) {
+ erase(arc);
+ Parent::firstIn(arc, node);
+ }
+
+ notifier(Node()).erase(node);
+ Parent::erase(node);
+ }
+
+ void erase(const Arc& arc) {
+ notifier(Arc()).erase(arc);
+ Parent::erase(arc);
+ }
+
+ DigraphExtender() {
+ node_notifier.setContainer(*this);
+ arc_notifier.setContainer(*this);
+ }
+
+
+ ~DigraphExtender() {
+ arc_notifier.clear();
+ node_notifier.clear();
+ }
+ };
+
+ // \ingroup _graphbits
+ //
+ // \brief Extender for the Graphs
+ template <typename Base>
+ class GraphExtender : public Base {
+ typedef Base Parent;
+
+ public:
+
+ typedef GraphExtender Graph;
+
+ typedef True UndirectedTag;
+
+ typedef typename Parent::Node Node;
+ typedef typename Parent::Arc Arc;
+ typedef typename Parent::Edge Edge;
+
+ // Graph extension
+
+ int maxId(Node) const {
+ return Parent::maxNodeId();
+ }
+
+ int maxId(Arc) const {
+ return Parent::maxArcId();
+ }
+
+ int maxId(Edge) const {
+ return Parent::maxEdgeId();
+ }
+
+ static Node fromId(int id, Node) {
+ return Parent::nodeFromId(id);
+ }
+
+ static Arc fromId(int id, Arc) {
+ return Parent::arcFromId(id);
+ }
+
+ static Edge fromId(int id, Edge) {
+ return Parent::edgeFromId(id);
+ }
+
+ Node oppositeNode(const Node &n, const Edge &e) const {
+ if( n == Parent::u(e))
+ return Parent::v(e);
+ else if( n == Parent::v(e))
+ return Parent::u(e);
+ else
+ return INVALID;
+ }
+
+ Arc oppositeArc(const Arc &arc) const {
+ return Parent::direct(arc, !Parent::direction(arc));
+ }
+
+ using Parent::direct;
+ Arc direct(const Edge &edge, const Node &node) const {
+ return Parent::direct(edge, Parent::u(edge) == node);
+ }
+
+ // Alterable extension
+
+ typedef AlterationNotifier<GraphExtender, Node> NodeNotifier;
+ typedef AlterationNotifier<GraphExtender, Arc> ArcNotifier;
+ typedef AlterationNotifier<GraphExtender, Edge> EdgeNotifier;
+
+
+ protected:
+
+ mutable NodeNotifier node_notifier;
+ mutable ArcNotifier arc_notifier;
+ mutable EdgeNotifier edge_notifier;
+
+ public:
+
+ NodeNotifier& notifier(Node) const {
+ return node_notifier;
+ }
+
+ ArcNotifier& notifier(Arc) const {
+ return arc_notifier;
+ }
+
+ EdgeNotifier& notifier(Edge) const {
+ return edge_notifier;
+ }
+
+
+
+ class NodeIt : public Node {
+ const Graph* _graph;
+ public:
+
+ NodeIt() {}
+
+ NodeIt(Invalid i) : Node(i) { }
+
+ explicit NodeIt(const Graph& graph) : _graph(&graph) {
+ _graph->first(static_cast<Node&>(*this));
+ }
+
+ NodeIt(const Graph& graph, const Node& node)
+ : Node(node), _graph(&graph) {}
+
+ NodeIt& operator++() {
+ _graph->next(*this);
+ return *this;
+ }
+
+ };
+
+
+ class ArcIt : public Arc {
+ const Graph* _graph;
+ public:
+
+ ArcIt() { }
+
+ ArcIt(Invalid i) : Arc(i) { }
+
+ explicit ArcIt(const Graph& graph) : _graph(&graph) {
+ _graph->first(static_cast<Arc&>(*this));
+ }
+
+ ArcIt(const Graph& graph, const Arc& arc) :
+ Arc(arc), _graph(&graph) { }
+
+ ArcIt& operator++() {
+ _graph->next(*this);
+ return *this;
+ }
+
+ };
+
+
+ class OutArcIt : public Arc {
+ const Graph* _graph;
+ public:
+
+ OutArcIt() { }
+
+ OutArcIt(Invalid i) : Arc(i) { }
+
+ OutArcIt(const Graph& graph, const Node& node)
+ : _graph(&graph) {
+ _graph->firstOut(*this, node);
+ }
+
+ OutArcIt(const Graph& graph, const Arc& arc)
+ : Arc(arc), _graph(&graph) {}
+
+ OutArcIt& operator++() {
+ _graph->nextOut(*this);
+ return *this;
+ }
+
+ };
+
+
+ class InArcIt : public Arc {
+ const Graph* _graph;
+ public:
+
+ InArcIt() { }
+
+ InArcIt(Invalid i) : Arc(i) { }
+
+ InArcIt(const Graph& graph, const Node& node)
+ : _graph(&graph) {
+ _graph->firstIn(*this, node);
+ }
+
+ InArcIt(const Graph& graph, const Arc& arc) :
+ Arc(arc), _graph(&graph) {}
+
+ InArcIt& operator++() {
+ _graph->nextIn(*this);
+ return *this;
+ }
+
+ };
+
+
+ class EdgeIt : public Parent::Edge {
+ const Graph* _graph;
+ public:
+
+ EdgeIt() { }
+
+ EdgeIt(Invalid i) : Edge(i) { }
+
+ explicit EdgeIt(const Graph& graph) : _graph(&graph) {
+ _graph->first(static_cast<Edge&>(*this));
+ }
+
+ EdgeIt(const Graph& graph, const Edge& edge) :
+ Edge(edge), _graph(&graph) { }
+
+ EdgeIt& operator++() {
+ _graph->next(*this);
+ return *this;
+ }
+
+ };
+
+ class IncEdgeIt : public Parent::Edge {
+ friend class GraphExtender;
+ const Graph* _graph;
+ bool _direction;
+ public:
+
+ IncEdgeIt() { }
+
+ IncEdgeIt(Invalid i) : Edge(i), _direction(false) { }
+
+ IncEdgeIt(const Graph& graph, const Node &node) : _graph(&graph) {
+ _graph->firstInc(*this, _direction, node);
+ }
+
+ IncEdgeIt(const Graph& graph, const Edge &edge, const Node &node)
+ : _graph(&graph), Edge(edge) {
+ _direction = (_graph->source(edge) == node);
+ }
+
+ IncEdgeIt& operator++() {
+ _graph->nextInc(*this, _direction);
+ return *this;
+ }
+ };
+
+ // \brief Base node of the iterator
+ //
+ // Returns the base node (ie. the source in this case) of the iterator
+ Node baseNode(const OutArcIt &arc) const {
+ return Parent::source(static_cast<const Arc&>(arc));
+ }
+ // \brief Running node of the iterator
+ //
+ // Returns the running node (ie. the target in this case) of the
+ // iterator
+ Node runningNode(const OutArcIt &arc) const {
+ return Parent::target(static_cast<const Arc&>(arc));
+ }
+
+ // \brief Base node of the iterator
+ //
+ // Returns the base node (ie. the target in this case) of the iterator
+ Node baseNode(const InArcIt &arc) const {
+ return Parent::target(static_cast<const Arc&>(arc));
+ }
+ // \brief Running node of the iterator
+ //
+ // Returns the running node (ie. the source in this case) of the
+ // iterator
+ Node runningNode(const InArcIt &arc) const {
+ return Parent::source(static_cast<const Arc&>(arc));
+ }
+
+ // Base node of the iterator
+ //
+ // Returns the base node of the iterator
+ Node baseNode(const IncEdgeIt &edge) const {
+ return edge._direction ? this->u(edge) : this->v(edge);
+ }
+ // Running node of the iterator
+ //
+ // Returns the running node of the iterator
+ Node runningNode(const IncEdgeIt &edge) const {
+ return edge._direction ? this->v(edge) : this->u(edge);
+ }
+
+ // Mappable extension
+
+ template <typename _Value>
+ class NodeMap
+ : public MapExtender<DefaultMap<Graph, Node, _Value> > {
+ typedef MapExtender<DefaultMap<Graph, Node, _Value> > Parent;
+
+ public:
+ explicit NodeMap(const Graph& graph)
+ : Parent(graph) {}
+ NodeMap(const Graph& graph, const _Value& value)
+ : Parent(graph, value) {}
+
+ private:
+ NodeMap& operator=(const NodeMap& cmap) {
+ return operator=<NodeMap>(cmap);
+ }
+
+ template <typename CMap>
+ NodeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+
+ };
+
+ template <typename _Value>
+ class ArcMap
+ : public MapExtender<DefaultMap<Graph, Arc, _Value> > {
+ typedef MapExtender<DefaultMap<Graph, Arc, _Value> > Parent;
+
+ public:
+ explicit ArcMap(const Graph& graph)
+ : Parent(graph) {}
+ ArcMap(const Graph& graph, const _Value& value)
+ : Parent(graph, value) {}
+
+ private:
+ ArcMap& operator=(const ArcMap& cmap) {
+ return operator=<ArcMap>(cmap);
+ }
+
+ template <typename CMap>
+ ArcMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+
+ template <typename _Value>
+ class EdgeMap
+ : public MapExtender<DefaultMap<Graph, Edge, _Value> > {
+ typedef MapExtender<DefaultMap<Graph, Edge, _Value> > Parent;
+
+ public:
+ explicit EdgeMap(const Graph& graph)
+ : Parent(graph) {}
+
+ EdgeMap(const Graph& graph, const _Value& value)
+ : Parent(graph, value) {}
+
+ private:
+ EdgeMap& operator=(const EdgeMap& cmap) {
+ return operator=<EdgeMap>(cmap);
+ }
+
+ template <typename CMap>
+ EdgeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+
+ };
+
+ // Alteration extension
+
+ Node addNode() {
+ Node node = Parent::addNode();
+ notifier(Node()).add(node);
+ return node;
+ }
+
+ Edge addEdge(const Node& from, const Node& to) {
+ Edge edge = Parent::addEdge(from, to);
+ notifier(Edge()).add(edge);
+ std::vector<Arc> ev;
+ ev.push_back(Parent::direct(edge, true));
+ ev.push_back(Parent::direct(edge, false));
+ notifier(Arc()).add(ev);
+ return edge;
+ }
+
+ void clear() {
+ notifier(Arc()).clear();
+ notifier(Edge()).clear();
+ notifier(Node()).clear();
+ Parent::clear();
+ }
+
+ template <typename Graph, typename NodeRefMap, typename EdgeRefMap>
+ void build(const Graph& graph, NodeRefMap& nodeRef,
+ EdgeRefMap& edgeRef) {
+ Parent::build(graph, nodeRef, edgeRef);
+ notifier(Node()).build();
+ notifier(Edge()).build();
+ notifier(Arc()).build();
+ }
+
+ void erase(const Node& node) {
+ Arc arc;
+ Parent::firstOut(arc, node);
+ while (arc != INVALID ) {
+ erase(arc);
+ Parent::firstOut(arc, node);
+ }
+
+ Parent::firstIn(arc, node);
+ while (arc != INVALID ) {
+ erase(arc);
+ Parent::firstIn(arc, node);
+ }
+
+ notifier(Node()).erase(node);
+ Parent::erase(node);
+ }
+
+ void erase(const Edge& edge) {
+ std::vector<Arc> av;
+ av.push_back(Parent::direct(edge, true));
+ av.push_back(Parent::direct(edge, false));
+ notifier(Arc()).erase(av);
+ notifier(Edge()).erase(edge);
+ Parent::erase(edge);
+ }
+
+ GraphExtender() {
+ node_notifier.setContainer(*this);
+ arc_notifier.setContainer(*this);
+ edge_notifier.setContainer(*this);
+ }
+
+ ~GraphExtender() {
+ edge_notifier.clear();
+ arc_notifier.clear();
+ node_notifier.clear();
+ }
+
+ };
+
+ // \ingroup _graphbits
+ //
+ // \brief Extender for the BpGraphs
+ template <typename Base>
+ class BpGraphExtender : public Base {
+ typedef Base Parent;
+
+ public:
+
+ typedef BpGraphExtender BpGraph;
+
+ typedef True UndirectedTag;
+
+ typedef typename Parent::Node Node;
+ typedef typename Parent::RedNode RedNode;
+ typedef typename Parent::BlueNode BlueNode;
+ typedef typename Parent::Arc Arc;
+ typedef typename Parent::Edge Edge;
+
+ // BpGraph extension
+
+ using Parent::first;
+ using Parent::next;
+ using Parent::id;
+
+ int maxId(Node) const {
+ return Parent::maxNodeId();
+ }
+
+ int maxId(RedNode) const {
+ return Parent::maxRedId();
+ }
+
+ int maxId(BlueNode) const {
+ return Parent::maxBlueId();
+ }
+
+ int maxId(Arc) const {
+ return Parent::maxArcId();
+ }
+
+ int maxId(Edge) const {
+ return Parent::maxEdgeId();
+ }
+
+ static Node fromId(int id, Node) {
+ return Parent::nodeFromId(id);
+ }
+
+ static Arc fromId(int id, Arc) {
+ return Parent::arcFromId(id);
+ }
+
+ static Edge fromId(int id, Edge) {
+ return Parent::edgeFromId(id);
+ }
+
+ Node u(Edge e) const { return this->redNode(e); }
+ Node v(Edge e) const { return this->blueNode(e); }
+
+ Node oppositeNode(const Node &n, const Edge &e) const {
+ if( n == u(e))
+ return v(e);
+ else if( n == v(e))
+ return u(e);
+ else
+ return INVALID;
+ }
+
+ Arc oppositeArc(const Arc &arc) const {
+ return Parent::direct(arc, !Parent::direction(arc));
+ }
+
+ using Parent::direct;
+ Arc direct(const Edge &edge, const Node &node) const {
+ return Parent::direct(edge, Parent::redNode(edge) == node);
+ }
+
+ RedNode asRedNode(const Node& node) const {
+ if (node == INVALID || Parent::blue(node)) {
+ return INVALID;
+ } else {
+ return Parent::asRedNodeUnsafe(node);
+ }
+ }
+
+ BlueNode asBlueNode(const Node& node) const {
+ if (node == INVALID || Parent::red(node)) {
+ return INVALID;
+ } else {
+ return Parent::asBlueNodeUnsafe(node);
+ }
+ }
+
+ // Alterable extension
+
+ typedef AlterationNotifier<BpGraphExtender, Node> NodeNotifier;
+ typedef AlterationNotifier<BpGraphExtender, RedNode> RedNodeNotifier;
+ typedef AlterationNotifier<BpGraphExtender, BlueNode> BlueNodeNotifier;
+ typedef AlterationNotifier<BpGraphExtender, Arc> ArcNotifier;
+ typedef AlterationNotifier<BpGraphExtender, Edge> EdgeNotifier;
+
+
+ protected:
+
+ mutable NodeNotifier node_notifier;
+ mutable RedNodeNotifier red_node_notifier;
+ mutable BlueNodeNotifier blue_node_notifier;
+ mutable ArcNotifier arc_notifier;
+ mutable EdgeNotifier edge_notifier;
+
+ public:
+
+ NodeNotifier& notifier(Node) const {
+ return node_notifier;
+ }
+
+ RedNodeNotifier& notifier(RedNode) const {
+ return red_node_notifier;
+ }
+
+ BlueNodeNotifier& notifier(BlueNode) const {
+ return blue_node_notifier;
+ }
+
+ ArcNotifier& notifier(Arc) const {
+ return arc_notifier;
+ }
+
+ EdgeNotifier& notifier(Edge) const {
+ return edge_notifier;
+ }
+
+
+
+ class NodeIt : public Node {
+ const BpGraph* _graph;
+ public:
+
+ NodeIt() {}
+
+ NodeIt(Invalid i) : Node(i) { }
+
+ explicit NodeIt(const BpGraph& graph) : _graph(&graph) {
+ _graph->first(static_cast<Node&>(*this));
+ }
+
+ NodeIt(const BpGraph& graph, const Node& node)
+ : Node(node), _graph(&graph) {}
+
+ NodeIt& operator++() {
+ _graph->next(*this);
+ return *this;
+ }
+
+ };
+
+ class RedNodeIt : public RedNode {
+ const BpGraph* _graph;
+ public:
+
+ RedNodeIt() {}
+
+ RedNodeIt(Invalid i) : RedNode(i) { }
+
+ explicit RedNodeIt(const BpGraph& graph) : _graph(&graph) {
+ _graph->first(static_cast<RedNode&>(*this));
+ }
+
+ RedNodeIt(const BpGraph& graph, const RedNode& node)
+ : RedNode(node), _graph(&graph) {}
+
+ RedNodeIt& operator++() {
+ _graph->next(static_cast<RedNode&>(*this));
+ return *this;
+ }
+
+ };
+
+ class BlueNodeIt : public BlueNode {
+ const BpGraph* _graph;
+ public:
+
+ BlueNodeIt() {}
+
+ BlueNodeIt(Invalid i) : BlueNode(i) { }
+
+ explicit BlueNodeIt(const BpGraph& graph) : _graph(&graph) {
+ _graph->first(static_cast<BlueNode&>(*this));
+ }
+
+ BlueNodeIt(const BpGraph& graph, const BlueNode& node)
+ : BlueNode(node), _graph(&graph) {}
+
+ BlueNodeIt& operator++() {
+ _graph->next(static_cast<BlueNode&>(*this));
+ return *this;
+ }
+
+ };
+
+
+ class ArcIt : public Arc {
+ const BpGraph* _graph;
+ public:
+
+ ArcIt() { }
+
+ ArcIt(Invalid i) : Arc(i) { }
+
+ explicit ArcIt(const BpGraph& graph) : _graph(&graph) {
+ _graph->first(static_cast<Arc&>(*this));
+ }
+
+ ArcIt(const BpGraph& graph, const Arc& arc) :
+ Arc(arc), _graph(&graph) { }
+
+ ArcIt& operator++() {
+ _graph->next(*this);
+ return *this;
+ }
+
+ };
+
+
+ class OutArcIt : public Arc {
+ const BpGraph* _graph;
+ public:
+
+ OutArcIt() { }
+
+ OutArcIt(Invalid i) : Arc(i) { }
+
+ OutArcIt(const BpGraph& graph, const Node& node)
+ : _graph(&graph) {
+ _graph->firstOut(*this, node);
+ }
+
+ OutArcIt(const BpGraph& graph, const Arc& arc)
+ : Arc(arc), _graph(&graph) {}
+
+ OutArcIt& operator++() {
+ _graph->nextOut(*this);
+ return *this;
+ }
+
+ };
+
+
+ class InArcIt : public Arc {
+ const BpGraph* _graph;
+ public:
+
+ InArcIt() { }
+
+ InArcIt(Invalid i) : Arc(i) { }
+
+ InArcIt(const BpGraph& graph, const Node& node)
+ : _graph(&graph) {
+ _graph->firstIn(*this, node);
+ }
+
+ InArcIt(const BpGraph& graph, const Arc& arc) :
+ Arc(arc), _graph(&graph) {}
+
+ InArcIt& operator++() {
+ _graph->nextIn(*this);
+ return *this;
+ }
+
+ };
+
+
+ class EdgeIt : public Parent::Edge {
+ const BpGraph* _graph;
+ public:
+
+ EdgeIt() { }
+
+ EdgeIt(Invalid i) : Edge(i) { }
+
+ explicit EdgeIt(const BpGraph& graph) : _graph(&graph) {
+ _graph->first(static_cast<Edge&>(*this));
+ }
+
+ EdgeIt(const BpGraph& graph, const Edge& edge) :
+ Edge(edge), _graph(&graph) { }
+
+ EdgeIt& operator++() {
+ _graph->next(*this);
+ return *this;
+ }
+
+ };
+
+ class IncEdgeIt : public Parent::Edge {
+ friend class BpGraphExtender;
+ const BpGraph* _graph;
+ bool _direction;
+ public:
+
+ IncEdgeIt() { }
+
+ IncEdgeIt(Invalid i) : Edge(i), _direction(false) { }
+
+ IncEdgeIt(const BpGraph& graph, const Node &node) : _graph(&graph) {
+ _graph->firstInc(*this, _direction, node);
+ }
+
+ IncEdgeIt(const BpGraph& graph, const Edge &edge, const Node &node)
+ : _graph(&graph), Edge(edge) {
+ _direction = (_graph->source(edge) == node);
+ }
+
+ IncEdgeIt& operator++() {
+ _graph->nextInc(*this, _direction);
+ return *this;
+ }
+ };
+
+ // \brief Base node of the iterator
+ //
+ // Returns the base node (ie. the source in this case) of the iterator
+ Node baseNode(const OutArcIt &arc) const {
+ return Parent::source(static_cast<const Arc&>(arc));
+ }
+ // \brief Running node of the iterator
+ //
+ // Returns the running node (ie. the target in this case) of the
+ // iterator
+ Node runningNode(const OutArcIt &arc) const {
+ return Parent::target(static_cast<const Arc&>(arc));
+ }
+
+ // \brief Base node of the iterator
+ //
+ // Returns the base node (ie. the target in this case) of the iterator
+ Node baseNode(const InArcIt &arc) const {
+ return Parent::target(static_cast<const Arc&>(arc));
+ }
+ // \brief Running node of the iterator
+ //
+ // Returns the running node (ie. the source in this case) of the
+ // iterator
+ Node runningNode(const InArcIt &arc) const {
+ return Parent::source(static_cast<const Arc&>(arc));
+ }
+
+ // Base node of the iterator
+ //
+ // Returns the base node of the iterator
+ Node baseNode(const IncEdgeIt &edge) const {
+ return edge._direction ? this->u(edge) : this->v(edge);
+ }
+ // Running node of the iterator
+ //
+ // Returns the running node of the iterator
+ Node runningNode(const IncEdgeIt &edge) const {
+ return edge._direction ? this->v(edge) : this->u(edge);
+ }
+
+ // Mappable extension
+
+ template <typename _Value>
+ class NodeMap
+ : public MapExtender<DefaultMap<BpGraph, Node, _Value> > {
+ typedef MapExtender<DefaultMap<BpGraph, Node, _Value> > Parent;
+
+ public:
+ explicit NodeMap(const BpGraph& bpgraph)
+ : Parent(bpgraph) {}
+ NodeMap(const BpGraph& bpgraph, const _Value& value)
+ : Parent(bpgraph, value) {}
+
+ private:
+ NodeMap& operator=(const NodeMap& cmap) {
+ return operator=<NodeMap>(cmap);
+ }
+
+ template <typename CMap>
+ NodeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+
+ };
+
+ template <typename _Value>
+ class RedNodeMap
+ : public MapExtender<DefaultMap<BpGraph, RedNode, _Value> > {
+ typedef MapExtender<DefaultMap<BpGraph, RedNode, _Value> > Parent;
+
+ public:
+ explicit RedNodeMap(const BpGraph& bpgraph)
+ : Parent(bpgraph) {}
+ RedNodeMap(const BpGraph& bpgraph, const _Value& value)
+ : Parent(bpgraph, value) {}
+
+ private:
+ RedNodeMap& operator=(const RedNodeMap& cmap) {
+ return operator=<RedNodeMap>(cmap);
+ }
+
+ template <typename CMap>
+ RedNodeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+
+ };
+
+ template <typename _Value>
+ class BlueNodeMap
+ : public MapExtender<DefaultMap<BpGraph, BlueNode, _Value> > {
+ typedef MapExtender<DefaultMap<BpGraph, BlueNode, _Value> > Parent;
+
+ public:
+ explicit BlueNodeMap(const BpGraph& bpgraph)
+ : Parent(bpgraph) {}
+ BlueNodeMap(const BpGraph& bpgraph, const _Value& value)
+ : Parent(bpgraph, value) {}
+
+ private:
+ BlueNodeMap& operator=(const BlueNodeMap& cmap) {
+ return operator=<BlueNodeMap>(cmap);
+ }
+
+ template <typename CMap>
+ BlueNodeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+
+ };
+
+ template <typename _Value>
+ class ArcMap
+ : public MapExtender<DefaultMap<BpGraph, Arc, _Value> > {
+ typedef MapExtender<DefaultMap<BpGraph, Arc, _Value> > Parent;
+
+ public:
+ explicit ArcMap(const BpGraph& graph)
+ : Parent(graph) {}
+ ArcMap(const BpGraph& graph, const _Value& value)
+ : Parent(graph, value) {}
+
+ private:
+ ArcMap& operator=(const ArcMap& cmap) {
+ return operator=<ArcMap>(cmap);
+ }
+
+ template <typename CMap>
+ ArcMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+
+ template <typename _Value>
+ class EdgeMap
+ : public MapExtender<DefaultMap<BpGraph, Edge, _Value> > {
+ typedef MapExtender<DefaultMap<BpGraph, Edge, _Value> > Parent;
+
+ public:
+ explicit EdgeMap(const BpGraph& graph)
+ : Parent(graph) {}
+
+ EdgeMap(const BpGraph& graph, const _Value& value)
+ : Parent(graph, value) {}
+
+ private:
+ EdgeMap& operator=(const EdgeMap& cmap) {
+ return operator=<EdgeMap>(cmap);
+ }
+
+ template <typename CMap>
+ EdgeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+
+ };
+
+ // Alteration extension
+
+ RedNode addRedNode() {
+ RedNode node = Parent::addRedNode();
+ notifier(RedNode()).add(node);
+ notifier(Node()).add(node);
+ return node;
+ }
+
+ BlueNode addBlueNode() {
+ BlueNode node = Parent::addBlueNode();
+ notifier(BlueNode()).add(node);
+ notifier(Node()).add(node);
+ return node;
+ }
+
+ Edge addEdge(const RedNode& from, const BlueNode& to) {
+ Edge edge = Parent::addEdge(from, to);
+ notifier(Edge()).add(edge);
+ std::vector<Arc> av;
+ av.push_back(Parent::direct(edge, true));
+ av.push_back(Parent::direct(edge, false));
+ notifier(Arc()).add(av);
+ return edge;
+ }
+
+ void clear() {
+ notifier(Arc()).clear();
+ notifier(Edge()).clear();
+ notifier(Node()).clear();
+ notifier(BlueNode()).clear();
+ notifier(RedNode()).clear();
+ Parent::clear();
+ }
+
+ template <typename BpGraph, typename NodeRefMap, typename EdgeRefMap>
+ void build(const BpGraph& graph, NodeRefMap& nodeRef,
+ EdgeRefMap& edgeRef) {
+ Parent::build(graph, nodeRef, edgeRef);
+ notifier(RedNode()).build();
+ notifier(BlueNode()).build();
+ notifier(Node()).build();
+ notifier(Edge()).build();
+ notifier(Arc()).build();
+ }
+
+ void erase(const Node& node) {
+ Arc arc;
+ Parent::firstOut(arc, node);
+ while (arc != INVALID ) {
+ erase(arc);
+ Parent::firstOut(arc, node);
+ }
+
+ Parent::firstIn(arc, node);
+ while (arc != INVALID ) {
+ erase(arc);
+ Parent::firstIn(arc, node);
+ }
+
+ if (Parent::red(node)) {
+ notifier(RedNode()).erase(this->asRedNodeUnsafe(node));
+ } else {
+ notifier(BlueNode()).erase(this->asBlueNodeUnsafe(node));
+ }
+
+ notifier(Node()).erase(node);
+ Parent::erase(node);
+ }
+
+ void erase(const Edge& edge) {
+ std::vector<Arc> av;
+ av.push_back(Parent::direct(edge, true));
+ av.push_back(Parent::direct(edge, false));
+ notifier(Arc()).erase(av);
+ notifier(Edge()).erase(edge);
+ Parent::erase(edge);
+ }
+
+ BpGraphExtender() {
+ red_node_notifier.setContainer(*this);
+ blue_node_notifier.setContainer(*this);
+ node_notifier.setContainer(*this);
+ arc_notifier.setContainer(*this);
+ edge_notifier.setContainer(*this);
+ }
+
+ ~BpGraphExtender() {
+ edge_notifier.clear();
+ arc_notifier.clear();
+ node_notifier.clear();
+ blue_node_notifier.clear();
+ red_node_notifier.clear();
+ }
+
+ };
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/lock.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/lock.h
new file mode 100644
index 00000000000..09069998cdb
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/lock.h
@@ -0,0 +1,65 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BITS_LOCK_H
+#define LEMON_BITS_LOCK_H
+
+#include <lemon/config.h>
+#if defined(LEMON_USE_PTHREAD)
+#include <pthread.h>
+#elif defined(LEMON_USE_WIN32_THREADS)
+#include <lemon/bits/windows.h>
+#endif
+
+namespace lemon {
+ namespace bits {
+
+#if defined(LEMON_USE_PTHREAD)
+ class Lock {
+ public:
+ Lock() {
+ pthread_mutex_init(&_lock, 0);
+ }
+ ~Lock() {
+ pthread_mutex_destroy(&_lock);
+ }
+ void lock() {
+ pthread_mutex_lock(&_lock);
+ }
+ void unlock() {
+ pthread_mutex_unlock(&_lock);
+ }
+
+ private:
+ pthread_mutex_t _lock;
+ };
+#elif defined(LEMON_USE_WIN32_THREADS)
+ class Lock : public WinLock {};
+#else
+ class Lock {
+ public:
+ Lock() {}
+ ~Lock() {}
+ void lock() {}
+ void unlock() {}
+ };
+#endif
+ }
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/map_extender.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/map_extender.h
new file mode 100644
index 00000000000..f32403e65ae
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/map_extender.h
@@ -0,0 +1,332 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BITS_MAP_EXTENDER_H
+#define LEMON_BITS_MAP_EXTENDER_H
+
+#include <iterator>
+
+#include <lemon/bits/traits.h>
+
+#include <lemon/concept_check.h>
+#include <lemon/concepts/maps.h>
+
+//\file
+//\brief Extenders for iterable maps.
+
+namespace lemon {
+
+ // \ingroup graphbits
+ //
+ // \brief Extender for maps
+ template <typename _Map>
+ class MapExtender : public _Map {
+ typedef _Map Parent;
+ typedef typename Parent::GraphType GraphType;
+
+ public:
+
+ typedef MapExtender Map;
+ typedef typename Parent::Key Item;
+
+ typedef typename Parent::Key Key;
+ typedef typename Parent::Value Value;
+ typedef typename Parent::Reference Reference;
+ typedef typename Parent::ConstReference ConstReference;
+
+ typedef typename Parent::ReferenceMapTag ReferenceMapTag;
+
+ class MapIt;
+ class ConstMapIt;
+
+ friend class MapIt;
+ friend class ConstMapIt;
+
+ public:
+
+ MapExtender(const GraphType& graph)
+ : Parent(graph) {}
+
+ MapExtender(const GraphType& graph, const Value& value)
+ : Parent(graph, value) {}
+
+ private:
+ MapExtender& operator=(const MapExtender& cmap) {
+ return operator=<MapExtender>(cmap);
+ }
+
+ template <typename CMap>
+ MapExtender& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+
+ public:
+ class MapIt : public Item {
+ typedef Item Parent;
+
+ public:
+
+ typedef typename Map::Value Value;
+
+ MapIt() : map(NULL) {}
+
+ MapIt(Invalid i) : Parent(i), map(NULL) {}
+
+ explicit MapIt(Map& _map) : map(&_map) {
+ map->notifier()->first(*this);
+ }
+
+ MapIt(const Map& _map, const Item& item)
+ : Parent(item), map(&_map) {}
+
+ MapIt& operator++() {
+ map->notifier()->next(*this);
+ return *this;
+ }
+
+ typename MapTraits<Map>::ConstReturnValue operator*() const {
+ return (*map)[*this];
+ }
+
+ typename MapTraits<Map>::ReturnValue operator*() {
+ return (*map)[*this];
+ }
+
+ void set(const Value& value) {
+ map->set(*this, value);
+ }
+
+ protected:
+ Map* map;
+
+ };
+
+ class ConstMapIt : public Item {
+ typedef Item Parent;
+
+ public:
+
+ typedef typename Map::Value Value;
+
+ ConstMapIt() : map(NULL) {}
+
+ ConstMapIt(Invalid i) : Parent(i), map(NULL) {}
+
+ explicit ConstMapIt(Map& _map) : map(&_map) {
+ map->notifier()->first(*this);
+ }
+
+ ConstMapIt(const Map& _map, const Item& item)
+ : Parent(item), map(_map) {}
+
+ ConstMapIt& operator++() {
+ map->notifier()->next(*this);
+ return *this;
+ }
+
+ typename MapTraits<Map>::ConstReturnValue operator*() const {
+ return map[*this];
+ }
+
+ protected:
+ const Map* map;
+ };
+
+ class ItemIt : public Item {
+ typedef Item Parent;
+
+ public:
+ ItemIt() : map(NULL) {}
+
+
+ ItemIt(Invalid i) : Parent(i), map(NULL) {}
+
+ explicit ItemIt(Map& _map) : map(&_map) {
+ map->notifier()->first(*this);
+ }
+
+ ItemIt(const Map& _map, const Item& item)
+ : Parent(item), map(&_map) {}
+
+ ItemIt& operator++() {
+ map->notifier()->next(*this);
+ return *this;
+ }
+
+ protected:
+ const Map* map;
+
+ };
+ };
+
+ // \ingroup graphbits
+ //
+ // \brief Extender for maps which use a subset of the items.
+ template <typename _Graph, typename _Map>
+ class SubMapExtender : public _Map {
+ typedef _Map Parent;
+ typedef _Graph GraphType;
+
+ public:
+
+ typedef SubMapExtender Map;
+ typedef typename Parent::Key Item;
+
+ typedef typename Parent::Key Key;
+ typedef typename Parent::Value Value;
+ typedef typename Parent::Reference Reference;
+ typedef typename Parent::ConstReference ConstReference;
+
+ typedef typename Parent::ReferenceMapTag ReferenceMapTag;
+
+ class MapIt;
+ class ConstMapIt;
+
+ friend class MapIt;
+ friend class ConstMapIt;
+
+ public:
+
+ SubMapExtender(const GraphType& _graph)
+ : Parent(_graph), graph(_graph) {}
+
+ SubMapExtender(const GraphType& _graph, const Value& _value)
+ : Parent(_graph, _value), graph(_graph) {}
+
+ private:
+ SubMapExtender& operator=(const SubMapExtender& cmap) {
+ return operator=<MapExtender>(cmap);
+ }
+
+ template <typename CMap>
+ SubMapExtender& operator=(const CMap& cmap) {
+ checkConcept<concepts::ReadMap<Key, Value>, CMap>();
+ Item it;
+ for (graph.first(it); it != INVALID; graph.next(it)) {
+ Parent::set(it, cmap[it]);
+ }
+ return *this;
+ }
+
+ public:
+ class MapIt : public Item {
+ typedef Item Parent;
+
+ public:
+ typedef typename Map::Value Value;
+
+ MapIt() : map(NULL) {}
+
+ MapIt(Invalid i) : Parent(i), map(NULL) { }
+
+ explicit MapIt(Map& _map) : map(&_map) {
+ map->graph.first(*this);
+ }
+
+ MapIt(const Map& _map, const Item& item)
+ : Parent(item), map(&_map) {}
+
+ MapIt& operator++() {
+ map->graph.next(*this);
+ return *this;
+ }
+
+ typename MapTraits<Map>::ConstReturnValue operator*() const {
+ return (*map)[*this];
+ }
+
+ typename MapTraits<Map>::ReturnValue operator*() {
+ return (*map)[*this];
+ }
+
+ void set(const Value& value) {
+ map->set(*this, value);
+ }
+
+ protected:
+ Map* map;
+
+ };
+
+ class ConstMapIt : public Item {
+ typedef Item Parent;
+
+ public:
+
+ typedef typename Map::Value Value;
+
+ ConstMapIt() : map(NULL) {}
+
+ ConstMapIt(Invalid i) : Parent(i), map(NULL) { }
+
+ explicit ConstMapIt(Map& _map) : map(&_map) {
+ map->graph.first(*this);
+ }
+
+ ConstMapIt(const Map& _map, const Item& item)
+ : Parent(item), map(&_map) {}
+
+ ConstMapIt& operator++() {
+ map->graph.next(*this);
+ return *this;
+ }
+
+ typename MapTraits<Map>::ConstReturnValue operator*() const {
+ return (*map)[*this];
+ }
+
+ protected:
+ const Map* map;
+ };
+
+ class ItemIt : public Item {
+ typedef Item Parent;
+
+ public:
+ ItemIt() : map(NULL) {}
+
+
+ ItemIt(Invalid i) : Parent(i), map(NULL) { }
+
+ explicit ItemIt(Map& _map) : map(&_map) {
+ map->graph.first(*this);
+ }
+
+ ItemIt(const Map& _map, const Item& item)
+ : Parent(item), map(&_map) {}
+
+ ItemIt& operator++() {
+ map->graph.next(*this);
+ return *this;
+ }
+
+ protected:
+ const Map* map;
+
+ };
+
+ private:
+
+ const GraphType& graph;
+
+ };
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/path_dump.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/path_dump.h
new file mode 100644
index 00000000000..3e8cb8dd58c
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/path_dump.h
@@ -0,0 +1,177 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BITS_PATH_DUMP_H
+#define LEMON_BITS_PATH_DUMP_H
+
+#include <lemon/core.h>
+#include <lemon/concept_check.h>
+
+namespace lemon {
+
+ template <typename _Digraph, typename _PredMap>
+ class PredMapPath {
+ public:
+ typedef True RevPathTag;
+
+ typedef _Digraph Digraph;
+ typedef typename Digraph::Arc Arc;
+ typedef _PredMap PredMap;
+
+ PredMapPath(const Digraph& _digraph, const PredMap& _predMap,
+ typename Digraph::Node _target)
+ : digraph(_digraph), predMap(_predMap), target(_target) {}
+
+ int length() const {
+ int len = 0;
+ typename Digraph::Node node = target;
+ typename Digraph::Arc arc;
+ while ((arc = predMap[node]) != INVALID) {
+ node = digraph.source(arc);
+ ++len;
+ }
+ return len;
+ }
+
+ bool empty() const {
+ return predMap[target] == INVALID;
+ }
+
+ class RevArcIt {
+ public:
+ RevArcIt() {}
+ RevArcIt(Invalid) : path(0), current(INVALID) {}
+ RevArcIt(const PredMapPath& _path)
+ : path(&_path), current(_path.target) {
+ if (path->predMap[current] == INVALID) current = INVALID;
+ }
+
+ operator const typename Digraph::Arc() const {
+ return path->predMap[current];
+ }
+
+ RevArcIt& operator++() {
+ current = path->digraph.source(path->predMap[current]);
+ if (path->predMap[current] == INVALID) current = INVALID;
+ return *this;
+ }
+
+ bool operator==(const RevArcIt& e) const {
+ return current == e.current;
+ }
+
+ bool operator!=(const RevArcIt& e) const {
+ return current != e.current;
+ }
+
+ bool operator<(const RevArcIt& e) const {
+ return current < e.current;
+ }
+
+ private:
+ const PredMapPath* path;
+ typename Digraph::Node current;
+ };
+
+ private:
+ const Digraph& digraph;
+ const PredMap& predMap;
+ typename Digraph::Node target;
+ };
+
+
+ template <typename _Digraph, typename _PredMatrixMap>
+ class PredMatrixMapPath {
+ public:
+ typedef True RevPathTag;
+
+ typedef _Digraph Digraph;
+ typedef typename Digraph::Arc Arc;
+ typedef _PredMatrixMap PredMatrixMap;
+
+ PredMatrixMapPath(const Digraph& _digraph,
+ const PredMatrixMap& _predMatrixMap,
+ typename Digraph::Node _source,
+ typename Digraph::Node _target)
+ : digraph(_digraph), predMatrixMap(_predMatrixMap),
+ source(_source), target(_target) {}
+
+ int length() const {
+ int len = 0;
+ typename Digraph::Node node = target;
+ typename Digraph::Arc arc;
+ while ((arc = predMatrixMap(source, node)) != INVALID) {
+ node = digraph.source(arc);
+ ++len;
+ }
+ return len;
+ }
+
+ bool empty() const {
+ return predMatrixMap(source, target) == INVALID;
+ }
+
+ class RevArcIt {
+ public:
+ RevArcIt() {}
+ RevArcIt(Invalid) : path(0), current(INVALID) {}
+ RevArcIt(const PredMatrixMapPath& _path)
+ : path(&_path), current(_path.target) {
+ if (path->predMatrixMap(path->source, current) == INVALID)
+ current = INVALID;
+ }
+
+ operator const typename Digraph::Arc() const {
+ return path->predMatrixMap(path->source, current);
+ }
+
+ RevArcIt& operator++() {
+ current =
+ path->digraph.source(path->predMatrixMap(path->source, current));
+ if (path->predMatrixMap(path->source, current) == INVALID)
+ current = INVALID;
+ return *this;
+ }
+
+ bool operator==(const RevArcIt& e) const {
+ return current == e.current;
+ }
+
+ bool operator!=(const RevArcIt& e) const {
+ return current != e.current;
+ }
+
+ bool operator<(const RevArcIt& e) const {
+ return current < e.current;
+ }
+
+ private:
+ const PredMatrixMapPath* path;
+ typename Digraph::Node current;
+ };
+
+ private:
+ const Digraph& digraph;
+ const PredMatrixMap& predMatrixMap;
+ typename Digraph::Node source;
+ typename Digraph::Node target;
+ };
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/solver_bits.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/solver_bits.h
new file mode 100644
index 00000000000..c34212be8cd
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/solver_bits.h
@@ -0,0 +1,194 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BITS_SOLVER_BITS_H
+#define LEMON_BITS_SOLVER_BITS_H
+
+#include <vector>
+
+namespace lemon {
+
+ namespace _solver_bits {
+
+ class VarIndex {
+ private:
+ struct ItemT {
+ int prev, next;
+ int index;
+ };
+ std::vector<ItemT> items;
+ int first_item, last_item, first_free_item;
+
+ std::vector<int> cross;
+
+ public:
+
+ VarIndex()
+ : first_item(-1), last_item(-1), first_free_item(-1) {
+ }
+
+ void clear() {
+ first_item = -1;
+ last_item = -1;
+ first_free_item = -1;
+ items.clear();
+ cross.clear();
+ }
+
+ int addIndex(int idx) {
+ int n;
+ if (first_free_item == -1) {
+ n = items.size();
+ items.push_back(ItemT());
+ } else {
+ n = first_free_item;
+ first_free_item = items[n].next;
+ if (first_free_item != -1) {
+ items[first_free_item].prev = -1;
+ }
+ }
+ items[n].index = idx;
+ if (static_cast<int>(cross.size()) <= idx) {
+ cross.resize(idx + 1, -1);
+ }
+ cross[idx] = n;
+
+ items[n].prev = last_item;
+ items[n].next = -1;
+ if (last_item != -1) {
+ items[last_item].next = n;
+ } else {
+ first_item = n;
+ }
+ last_item = n;
+
+ return n;
+ }
+
+ int addIndex(int idx, int n) {
+ while (n >= static_cast<int>(items.size())) {
+ items.push_back(ItemT());
+ items.back().prev = -1;
+ items.back().next = first_free_item;
+ if (first_free_item != -1) {
+ items[first_free_item].prev = items.size() - 1;
+ }
+ first_free_item = items.size() - 1;
+ }
+ if (items[n].next != -1) {
+ items[items[n].next].prev = items[n].prev;
+ }
+ if (items[n].prev != -1) {
+ items[items[n].prev].next = items[n].next;
+ } else {
+ first_free_item = items[n].next;
+ }
+
+ items[n].index = idx;
+ if (static_cast<int>(cross.size()) <= idx) {
+ cross.resize(idx + 1, -1);
+ }
+ cross[idx] = n;
+
+ items[n].prev = last_item;
+ items[n].next = -1;
+ if (last_item != -1) {
+ items[last_item].next = n;
+ } else {
+ first_item = n;
+ }
+ last_item = n;
+
+ return n;
+ }
+
+ void eraseIndex(int idx) {
+ int n = cross[idx];
+
+ if (items[n].prev != -1) {
+ items[items[n].prev].next = items[n].next;
+ } else {
+ first_item = items[n].next;
+ }
+ if (items[n].next != -1) {
+ items[items[n].next].prev = items[n].prev;
+ } else {
+ last_item = items[n].prev;
+ }
+
+ if (first_free_item != -1) {
+ items[first_free_item].prev = n;
+ }
+ items[n].next = first_free_item;
+ items[n].prev = -1;
+ first_free_item = n;
+
+ while (!cross.empty() && cross.back() == -1) {
+ cross.pop_back();
+ }
+ }
+
+ int maxIndex() const {
+ return cross.size() - 1;
+ }
+
+ void shiftIndices(int idx) {
+ for (int i = idx + 1; i < static_cast<int>(cross.size()); ++i) {
+ cross[i - 1] = cross[i];
+ if (cross[i] != -1) {
+ --items[cross[i]].index;
+ }
+ }
+ cross.back() = -1;
+ cross.pop_back();
+ while (!cross.empty() && cross.back() == -1) {
+ cross.pop_back();
+ }
+ }
+
+ void relocateIndex(int idx, int jdx) {
+ cross[idx] = cross[jdx];
+ items[cross[jdx]].index = idx;
+ cross[jdx] = -1;
+
+ while (!cross.empty() && cross.back() == -1) {
+ cross.pop_back();
+ }
+ }
+
+ int operator[](int idx) const {
+ return cross[idx];
+ }
+
+ int operator()(int fdx) const {
+ return items[fdx].index;
+ }
+
+ void firstItem(int& fdx) const {
+ fdx = first_item;
+ }
+
+ void nextItem(int& fdx) const {
+ fdx = items[fdx].next;
+ }
+
+ };
+ }
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/traits.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/traits.h
new file mode 100644
index 00000000000..53fbd45647a
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/traits.h
@@ -0,0 +1,388 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BITS_TRAITS_H
+#define LEMON_BITS_TRAITS_H
+
+//\file
+//\brief Traits for graphs and maps
+//
+
+#include <lemon/bits/enable_if.h>
+
+namespace lemon {
+
+ struct InvalidType {};
+
+ template <typename GR, typename _Item>
+ class ItemSetTraits {};
+
+
+ template <typename GR, typename Enable = void>
+ struct NodeNotifierIndicator {
+ typedef InvalidType Type;
+ };
+ template <typename GR>
+ struct NodeNotifierIndicator<
+ GR,
+ typename enable_if<typename GR::NodeNotifier::Notifier, void>::type
+ > {
+ typedef typename GR::NodeNotifier Type;
+ };
+
+ template <typename GR>
+ class ItemSetTraits<GR, typename GR::Node> {
+ public:
+
+ typedef GR Graph;
+ typedef GR Digraph;
+
+ typedef typename GR::Node Item;
+ typedef typename GR::NodeIt ItemIt;
+
+ typedef typename NodeNotifierIndicator<GR>::Type ItemNotifier;
+
+ template <typename V>
+ class Map : public GR::template NodeMap<V> {
+ typedef typename GR::template NodeMap<V> Parent;
+
+ public:
+ typedef typename GR::template NodeMap<V> Type;
+ typedef typename Parent::Value Value;
+
+ Map(const GR& _digraph) : Parent(_digraph) {}
+ Map(const GR& _digraph, const Value& _value)
+ : Parent(_digraph, _value) {}
+
+ };
+
+ };
+
+ template <typename GR, typename Enable = void>
+ struct ArcNotifierIndicator {
+ typedef InvalidType Type;
+ };
+ template <typename GR>
+ struct ArcNotifierIndicator<
+ GR,
+ typename enable_if<typename GR::ArcNotifier::Notifier, void>::type
+ > {
+ typedef typename GR::ArcNotifier Type;
+ };
+
+ template <typename GR>
+ class ItemSetTraits<GR, typename GR::Arc> {
+ public:
+
+ typedef GR Graph;
+ typedef GR Digraph;
+
+ typedef typename GR::Arc Item;
+ typedef typename GR::ArcIt ItemIt;
+
+ typedef typename ArcNotifierIndicator<GR>::Type ItemNotifier;
+
+ template <typename V>
+ class Map : public GR::template ArcMap<V> {
+ typedef typename GR::template ArcMap<V> Parent;
+
+ public:
+ typedef typename GR::template ArcMap<V> Type;
+ typedef typename Parent::Value Value;
+
+ Map(const GR& _digraph) : Parent(_digraph) {}
+ Map(const GR& _digraph, const Value& _value)
+ : Parent(_digraph, _value) {}
+ };
+
+ };
+
+ template <typename GR, typename Enable = void>
+ struct EdgeNotifierIndicator {
+ typedef InvalidType Type;
+ };
+ template <typename GR>
+ struct EdgeNotifierIndicator<
+ GR,
+ typename enable_if<typename GR::EdgeNotifier::Notifier, void>::type
+ > {
+ typedef typename GR::EdgeNotifier Type;
+ };
+
+ template <typename GR>
+ class ItemSetTraits<GR, typename GR::Edge> {
+ public:
+
+ typedef GR Graph;
+ typedef GR Digraph;
+
+ typedef typename GR::Edge Item;
+ typedef typename GR::EdgeIt ItemIt;
+
+ typedef typename EdgeNotifierIndicator<GR>::Type ItemNotifier;
+
+ template <typename V>
+ class Map : public GR::template EdgeMap<V> {
+ typedef typename GR::template EdgeMap<V> Parent;
+
+ public:
+ typedef typename GR::template EdgeMap<V> Type;
+ typedef typename Parent::Value Value;
+
+ Map(const GR& _digraph) : Parent(_digraph) {}
+ Map(const GR& _digraph, const Value& _value)
+ : Parent(_digraph, _value) {}
+ };
+
+ };
+
+ template <typename GR, typename Enable = void>
+ struct RedNodeNotifierIndicator {
+ typedef InvalidType Type;
+ };
+ template <typename GR>
+ struct RedNodeNotifierIndicator<
+ GR,
+ typename enable_if<typename GR::RedNodeNotifier::Notifier, void>::type
+ > {
+ typedef typename GR::RedNodeNotifier Type;
+ };
+
+ template <typename GR>
+ class ItemSetTraits<GR, typename GR::RedNode> {
+ public:
+
+ typedef GR BpGraph;
+ typedef GR Graph;
+ typedef GR Digraph;
+
+ typedef typename GR::RedNode Item;
+ typedef typename GR::RedNodeIt ItemIt;
+
+ typedef typename RedNodeNotifierIndicator<GR>::Type ItemNotifier;
+
+ template <typename V>
+ class Map : public GR::template RedNodeMap<V> {
+ typedef typename GR::template RedNodeMap<V> Parent;
+
+ public:
+ typedef typename GR::template RedNodeMap<V> Type;
+ typedef typename Parent::Value Value;
+
+ Map(const GR& _bpgraph) : Parent(_bpgraph) {}
+ Map(const GR& _bpgraph, const Value& _value)
+ : Parent(_bpgraph, _value) {}
+
+ };
+
+ };
+
+ template <typename GR, typename Enable = void>
+ struct BlueNodeNotifierIndicator {
+ typedef InvalidType Type;
+ };
+ template <typename GR>
+ struct BlueNodeNotifierIndicator<
+ GR,
+ typename enable_if<typename GR::BlueNodeNotifier::Notifier, void>::type
+ > {
+ typedef typename GR::BlueNodeNotifier Type;
+ };
+
+ template <typename GR>
+ class ItemSetTraits<GR, typename GR::BlueNode> {
+ public:
+
+ typedef GR BpGraph;
+ typedef GR Graph;
+ typedef GR Digraph;
+
+ typedef typename GR::BlueNode Item;
+ typedef typename GR::BlueNodeIt ItemIt;
+
+ typedef typename BlueNodeNotifierIndicator<GR>::Type ItemNotifier;
+
+ template <typename V>
+ class Map : public GR::template BlueNodeMap<V> {
+ typedef typename GR::template BlueNodeMap<V> Parent;
+
+ public:
+ typedef typename GR::template BlueNodeMap<V> Type;
+ typedef typename Parent::Value Value;
+
+ Map(const GR& _bpgraph) : Parent(_bpgraph) {}
+ Map(const GR& _bpgraph, const Value& _value)
+ : Parent(_bpgraph, _value) {}
+
+ };
+
+ };
+
+ template <typename Map, typename Enable = void>
+ struct MapTraits {
+ typedef False ReferenceMapTag;
+
+ typedef typename Map::Key Key;
+ typedef typename Map::Value Value;
+
+ typedef Value ConstReturnValue;
+ typedef Value ReturnValue;
+ };
+
+ template <typename Map>
+ struct MapTraits<
+ Map, typename enable_if<typename Map::ReferenceMapTag, void>::type >
+ {
+ typedef True ReferenceMapTag;
+
+ typedef typename Map::Key Key;
+ typedef typename Map::Value Value;
+
+ typedef typename Map::ConstReference ConstReturnValue;
+ typedef typename Map::Reference ReturnValue;
+
+ typedef typename Map::ConstReference ConstReference;
+ typedef typename Map::Reference Reference;
+ };
+
+ template <typename MatrixMap, typename Enable = void>
+ struct MatrixMapTraits {
+ typedef False ReferenceMapTag;
+
+ typedef typename MatrixMap::FirstKey FirstKey;
+ typedef typename MatrixMap::SecondKey SecondKey;
+ typedef typename MatrixMap::Value Value;
+
+ typedef Value ConstReturnValue;
+ typedef Value ReturnValue;
+ };
+
+ template <typename MatrixMap>
+ struct MatrixMapTraits<
+ MatrixMap, typename enable_if<typename MatrixMap::ReferenceMapTag,
+ void>::type >
+ {
+ typedef True ReferenceMapTag;
+
+ typedef typename MatrixMap::FirstKey FirstKey;
+ typedef typename MatrixMap::SecondKey SecondKey;
+ typedef typename MatrixMap::Value Value;
+
+ typedef typename MatrixMap::ConstReference ConstReturnValue;
+ typedef typename MatrixMap::Reference ReturnValue;
+
+ typedef typename MatrixMap::ConstReference ConstReference;
+ typedef typename MatrixMap::Reference Reference;
+ };
+
+ // Indicators for the tags
+
+ template <typename GR, typename Enable = void>
+ struct NodeNumTagIndicator {
+ static const bool value = false;
+ };
+
+ template <typename GR>
+ struct NodeNumTagIndicator<
+ GR,
+ typename enable_if<typename GR::NodeNumTag, void>::type
+ > {
+ static const bool value = true;
+ };
+
+ template <typename GR, typename Enable = void>
+ struct ArcNumTagIndicator {
+ static const bool value = false;
+ };
+
+ template <typename GR>
+ struct ArcNumTagIndicator<
+ GR,
+ typename enable_if<typename GR::ArcNumTag, void>::type
+ > {
+ static const bool value = true;
+ };
+
+ template <typename GR, typename Enable = void>
+ struct EdgeNumTagIndicator {
+ static const bool value = false;
+ };
+
+ template <typename GR>
+ struct EdgeNumTagIndicator<
+ GR,
+ typename enable_if<typename GR::EdgeNumTag, void>::type
+ > {
+ static const bool value = true;
+ };
+
+ template <typename GR, typename Enable = void>
+ struct FindArcTagIndicator {
+ static const bool value = false;
+ };
+
+ template <typename GR>
+ struct FindArcTagIndicator<
+ GR,
+ typename enable_if<typename GR::FindArcTag, void>::type
+ > {
+ static const bool value = true;
+ };
+
+ template <typename GR, typename Enable = void>
+ struct FindEdgeTagIndicator {
+ static const bool value = false;
+ };
+
+ template <typename GR>
+ struct FindEdgeTagIndicator<
+ GR,
+ typename enable_if<typename GR::FindEdgeTag, void>::type
+ > {
+ static const bool value = true;
+ };
+
+ template <typename GR, typename Enable = void>
+ struct UndirectedTagIndicator {
+ static const bool value = false;
+ };
+
+ template <typename GR>
+ struct UndirectedTagIndicator<
+ GR,
+ typename enable_if<typename GR::UndirectedTag, void>::type
+ > {
+ static const bool value = true;
+ };
+
+ template <typename GR, typename Enable = void>
+ struct BuildTagIndicator {
+ static const bool value = false;
+ };
+
+ template <typename GR>
+ struct BuildTagIndicator<
+ GR,
+ typename enable_if<typename GR::BuildTag, void>::type
+ > {
+ static const bool value = true;
+ };
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/variant.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/variant.h
new file mode 100644
index 00000000000..b8301892e61
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/variant.h
@@ -0,0 +1,494 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BITS_VARIANT_H
+#define LEMON_BITS_VARIANT_H
+
+#include <lemon/assert.h>
+
+// \file
+// \brief Variant types
+
+namespace lemon {
+
+ namespace _variant_bits {
+
+ template <int left, int right>
+ struct CTMax {
+ static const int value = left < right ? right : left;
+ };
+
+ }
+
+
+ // \brief Simple Variant type for two types
+ //
+ // Simple Variant type for two types. The Variant type is a type-safe
+ // union. C++ has strong limitations for using unions, for
+ // example you cannot store a type with non-default constructor or
+ // destructor in a union. This class always knowns the current
+ // state of the variant and it cares for the proper construction
+ // and destruction.
+ template <typename _First, typename _Second>
+ class BiVariant {
+ public:
+
+ // \brief The \c First type.
+ typedef _First First;
+ // \brief The \c Second type.
+ typedef _Second Second;
+
+ // \brief Constructor
+ //
+ // This constructor initalizes to the default value of the \c First
+ // type.
+ BiVariant() {
+ flag = true;
+ new(reinterpret_cast<First*>(data)) First();
+ }
+
+ // \brief Constructor
+ //
+ // This constructor initalizes to the given value of the \c First
+ // type.
+ BiVariant(const First& f) {
+ flag = true;
+ new(reinterpret_cast<First*>(data)) First(f);
+ }
+
+ // \brief Constructor
+ //
+ // This constructor initalizes to the given value of the \c
+ // Second type.
+ BiVariant(const Second& s) {
+ flag = false;
+ new(reinterpret_cast<Second*>(data)) Second(s);
+ }
+
+ // \brief Copy constructor
+ //
+ // Copy constructor
+ BiVariant(const BiVariant& bivariant) {
+ flag = bivariant.flag;
+ if (flag) {
+ new(reinterpret_cast<First*>(data)) First(bivariant.first());
+ } else {
+ new(reinterpret_cast<Second*>(data)) Second(bivariant.second());
+ }
+ }
+
+ // \brief Destrcutor
+ //
+ // Destructor
+ ~BiVariant() {
+ destroy();
+ }
+
+ // \brief Set to the default value of the \c First type.
+ //
+ // This function sets the variant to the default value of the \c
+ // First type.
+ BiVariant& setFirst() {
+ destroy();
+ flag = true;
+ new(reinterpret_cast<First*>(data)) First();
+ return *this;
+ }
+
+ // \brief Set to the given value of the \c First type.
+ //
+ // This function sets the variant to the given value of the \c
+ // First type.
+ BiVariant& setFirst(const First& f) {
+ destroy();
+ flag = true;
+ new(reinterpret_cast<First*>(data)) First(f);
+ return *this;
+ }
+
+ // \brief Set to the default value of the \c Second type.
+ //
+ // This function sets the variant to the default value of the \c
+ // Second type.
+ BiVariant& setSecond() {
+ destroy();
+ flag = false;
+ new(reinterpret_cast<Second*>(data)) Second();
+ return *this;
+ }
+
+ // \brief Set to the given value of the \c Second type.
+ //
+ // This function sets the variant to the given value of the \c
+ // Second type.
+ BiVariant& setSecond(const Second& s) {
+ destroy();
+ flag = false;
+ new(reinterpret_cast<Second*>(data)) Second(s);
+ return *this;
+ }
+
+ // \brief Operator form of the \c setFirst()
+ BiVariant& operator=(const First& f) {
+ return setFirst(f);
+ }
+
+ // \brief Operator form of the \c setSecond()
+ BiVariant& operator=(const Second& s) {
+ return setSecond(s);
+ }
+
+ // \brief Assign operator
+ BiVariant& operator=(const BiVariant& bivariant) {
+ if (this == &bivariant) return *this;
+ destroy();
+ flag = bivariant.flag;
+ if (flag) {
+ new(reinterpret_cast<First*>(data)) First(bivariant.first());
+ } else {
+ new(reinterpret_cast<Second*>(data)) Second(bivariant.second());
+ }
+ return *this;
+ }
+
+ // \brief Reference to the value
+ //
+ // Reference to the value of the \c First type.
+ // \pre The BiVariant should store value of \c First type.
+ First& first() {
+ LEMON_DEBUG(flag, "Variant wrong state");
+ return *reinterpret_cast<First*>(data);
+ }
+
+ // \brief Const reference to the value
+ //
+ // Const reference to the value of the \c First type.
+ // \pre The BiVariant should store value of \c First type.
+ const First& first() const {
+ LEMON_DEBUG(flag, "Variant wrong state");
+ return *reinterpret_cast<const First*>(data);
+ }
+
+ // \brief Operator form of the \c first()
+ operator First&() { return first(); }
+ // \brief Operator form of the const \c first()
+ operator const First&() const { return first(); }
+
+ // \brief Reference to the value
+ //
+ // Reference to the value of the \c Second type.
+ // \pre The BiVariant should store value of \c Second type.
+ Second& second() {
+ LEMON_DEBUG(!flag, "Variant wrong state");
+ return *reinterpret_cast<Second*>(data);
+ }
+
+ // \brief Const reference to the value
+ //
+ // Const reference to the value of the \c Second type.
+ // \pre The BiVariant should store value of \c Second type.
+ const Second& second() const {
+ LEMON_DEBUG(!flag, "Variant wrong state");
+ return *reinterpret_cast<const Second*>(data);
+ }
+
+ // \brief Operator form of the \c second()
+ operator Second&() { return second(); }
+ // \brief Operator form of the const \c second()
+ operator const Second&() const { return second(); }
+
+ // \brief %True when the variant is in the first state
+ //
+ // %True when the variant stores value of the \c First type.
+ bool firstState() const { return flag; }
+
+ // \brief %True when the variant is in the second state
+ //
+ // %True when the variant stores value of the \c Second type.
+ bool secondState() const { return !flag; }
+
+ private:
+
+ void destroy() {
+ if (flag) {
+ reinterpret_cast<First*>(data)->~First();
+ } else {
+ reinterpret_cast<Second*>(data)->~Second();
+ }
+ }
+
+ char data[_variant_bits::CTMax<sizeof(First), sizeof(Second)>::value];
+ bool flag;
+ };
+
+ namespace _variant_bits {
+
+ template <int _idx, typename _TypeMap>
+ struct Memory {
+
+ typedef typename _TypeMap::template Map<_idx>::Type Current;
+
+ static void destroy(int index, char* place) {
+ if (index == _idx) {
+ reinterpret_cast<Current*>(place)->~Current();
+ } else {
+ Memory<_idx - 1, _TypeMap>::destroy(index, place);
+ }
+ }
+
+ static void copy(int index, char* to, const char* from) {
+ if (index == _idx) {
+ new (reinterpret_cast<Current*>(to))
+ Current(reinterpret_cast<const Current*>(from));
+ } else {
+ Memory<_idx - 1, _TypeMap>::copy(index, to, from);
+ }
+ }
+
+ };
+
+ template <typename _TypeMap>
+ struct Memory<-1, _TypeMap> {
+
+ static void destroy(int, char*) {
+ LEMON_DEBUG(false, "Variant wrong index.");
+ }
+
+ static void copy(int, char*, const char*) {
+ LEMON_DEBUG(false, "Variant wrong index.");
+ }
+ };
+
+ template <int _idx, typename _TypeMap>
+ struct Size {
+ static const int value =
+ CTMax<sizeof(typename _TypeMap::template Map<_idx>::Type),
+ Size<_idx - 1, _TypeMap>::value>::value;
+ };
+
+ template <typename _TypeMap>
+ struct Size<0, _TypeMap> {
+ static const int value =
+ sizeof(typename _TypeMap::template Map<0>::Type);
+ };
+
+ }
+
+ // \brief Variant type
+ //
+ // Simple Variant type. The Variant type is a type-safe union.
+ // C++ has strong limitations for using unions, for example you
+ // cannot store type with non-default constructor or destructor in
+ // a union. This class always knowns the current state of the
+ // variant and it cares for the proper construction and
+ // destruction.
+ //
+ // \param _num The number of the types which can be stored in the
+ // variant type.
+ // \param _TypeMap This class describes the types of the Variant. The
+ // _TypeMap::Map<index>::Type should be a valid type for each index
+ // in the range {0, 1, ..., _num - 1}. The \c VariantTypeMap is helper
+ // class to define such type mappings up to 10 types.
+ //
+ // And the usage of the class:
+ //\code
+ // typedef Variant<3, VariantTypeMap<int, std::string, double> > MyVariant;
+ // MyVariant var;
+ // var.set<0>(12);
+ // std::cout << var.get<0>() << std::endl;
+ // var.set<1>("alpha");
+ // std::cout << var.get<1>() << std::endl;
+ // var.set<2>(0.75);
+ // std::cout << var.get<2>() << std::endl;
+ //\endcode
+ //
+ // The result of course:
+ //\code
+ // 12
+ // alpha
+ // 0.75
+ //\endcode
+ template <int _num, typename _TypeMap>
+ class Variant {
+ public:
+
+ static const int num = _num;
+
+ typedef _TypeMap TypeMap;
+
+ // \brief Constructor
+ //
+ // This constructor initalizes to the default value of the \c type
+ // with 0 index.
+ Variant() {
+ flag = 0;
+ new(reinterpret_cast<typename TypeMap::template Map<0>::Type*>(data))
+ typename TypeMap::template Map<0>::Type();
+ }
+
+
+ // \brief Copy constructor
+ //
+ // Copy constructor
+ Variant(const Variant& variant) {
+ flag = variant.flag;
+ _variant_bits::Memory<num - 1, TypeMap>::copy(flag, data, variant.data);
+ }
+
+ // \brief Assign operator
+ //
+ // Assign operator
+ Variant& operator=(const Variant& variant) {
+ if (this == &variant) return *this;
+ _variant_bits::Memory<num - 1, TypeMap>::
+ destroy(flag, data);
+ flag = variant.flag;
+ _variant_bits::Memory<num - 1, TypeMap>::
+ copy(flag, data, variant.data);
+ return *this;
+ }
+
+ // \brief Destrcutor
+ //
+ // Destructor
+ ~Variant() {
+ _variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);
+ }
+
+ // \brief Set to the default value of the type with \c _idx index.
+ //
+ // This function sets the variant to the default value of the
+ // type with \c _idx index.
+ template <int _idx>
+ Variant& set() {
+ _variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);
+ flag = _idx;
+ new(reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>(data))
+ typename TypeMap::template Map<_idx>::Type();
+ return *this;
+ }
+
+ // \brief Set to the given value of the type with \c _idx index.
+ //
+ // This function sets the variant to the given value of the type
+ // with \c _idx index.
+ template <int _idx>
+ Variant& set(const typename _TypeMap::template Map<_idx>::Type& init) {
+ _variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);
+ flag = _idx;
+ new(reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>(data))
+ typename TypeMap::template Map<_idx>::Type(init);
+ return *this;
+ }
+
+ // \brief Gets the current value of the type with \c _idx index.
+ //
+ // Gets the current value of the type with \c _idx index.
+ template <int _idx>
+ const typename TypeMap::template Map<_idx>::Type& get() const {
+ LEMON_DEBUG(_idx == flag, "Variant wrong index");
+ return *reinterpret_cast<const typename TypeMap::
+ template Map<_idx>::Type*>(data);
+ }
+
+ // \brief Gets the current value of the type with \c _idx index.
+ //
+ // Gets the current value of the type with \c _idx index.
+ template <int _idx>
+ typename _TypeMap::template Map<_idx>::Type& get() {
+ LEMON_DEBUG(_idx == flag, "Variant wrong index");
+ return *reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>
+ (data);
+ }
+
+ // \brief Returns the current state of the variant.
+ //
+ // Returns the current state of the variant.
+ int state() const {
+ return flag;
+ }
+
+ private:
+
+ char data[_variant_bits::Size<num - 1, TypeMap>::value];
+ int flag;
+ };
+
+ namespace _variant_bits {
+
+ template <int _index, typename _List>
+ struct Get {
+ typedef typename Get<_index - 1, typename _List::Next>::Type Type;
+ };
+
+ template <typename _List>
+ struct Get<0, _List> {
+ typedef typename _List::Type Type;
+ };
+
+ struct List {};
+
+ template <typename _Type, typename _List>
+ struct Insert {
+ typedef _List Next;
+ typedef _Type Type;
+ };
+
+ template <int _idx, typename _T0, typename _T1, typename _T2,
+ typename _T3, typename _T4, typename _T5, typename _T6,
+ typename _T7, typename _T8, typename _T9>
+ struct Mapper {
+ typedef List L10;
+ typedef Insert<_T9, L10> L9;
+ typedef Insert<_T8, L9> L8;
+ typedef Insert<_T7, L8> L7;
+ typedef Insert<_T6, L7> L6;
+ typedef Insert<_T5, L6> L5;
+ typedef Insert<_T4, L5> L4;
+ typedef Insert<_T3, L4> L3;
+ typedef Insert<_T2, L3> L2;
+ typedef Insert<_T1, L2> L1;
+ typedef Insert<_T0, L1> L0;
+ typedef typename Get<_idx, L0>::Type Type;
+ };
+
+ }
+
+ // \brief Helper class for Variant
+ //
+ // Helper class to define type mappings for Variant. This class
+ // converts the template parameters to be mappable by integer.
+ // \see Variant
+ template <
+ typename _T0,
+ typename _T1 = void, typename _T2 = void, typename _T3 = void,
+ typename _T4 = void, typename _T5 = void, typename _T6 = void,
+ typename _T7 = void, typename _T8 = void, typename _T9 = void>
+ struct VariantTypeMap {
+ template <int _idx>
+ struct Map {
+ typedef typename _variant_bits::
+ Mapper<_idx, _T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7, _T8, _T9>::Type
+ Type;
+ };
+ };
+
+}
+
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/vector_map.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/vector_map.h
new file mode 100644
index 00000000000..d60841defbd
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/vector_map.h
@@ -0,0 +1,244 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BITS_VECTOR_MAP_H
+#define LEMON_BITS_VECTOR_MAP_H
+
+#include <vector>
+#include <algorithm>
+
+#include <lemon/core.h>
+#include <lemon/bits/alteration_notifier.h>
+
+#include <lemon/concept_check.h>
+#include <lemon/concepts/maps.h>
+
+//\ingroup graphbits
+//
+//\file
+//\brief Vector based graph maps.
+namespace lemon {
+
+ // \ingroup graphbits
+ //
+ // \brief Graph map based on the std::vector storage.
+ //
+ // The VectorMap template class is graph map structure that automatically
+ // updates the map when a key is added to or erased from the graph.
+ // This map type uses std::vector to store the values.
+ //
+ // \tparam _Graph The graph this map is attached to.
+ // \tparam _Item The item type of the graph items.
+ // \tparam _Value The value type of the map.
+ template <typename _Graph, typename _Item, typename _Value>
+ class VectorMap
+ : public ItemSetTraits<_Graph, _Item>::ItemNotifier::ObserverBase {
+ private:
+
+ // The container type of the map.
+ typedef std::vector<_Value> Container;
+
+ public:
+
+ // The graph type of the map.
+ typedef _Graph GraphType;
+ // The item type of the map.
+ typedef _Item Item;
+ // The reference map tag.
+ typedef True ReferenceMapTag;
+
+ // The key type of the map.
+ typedef _Item Key;
+ // The value type of the map.
+ typedef _Value Value;
+
+ // The notifier type.
+ typedef typename ItemSetTraits<_Graph, _Item>::ItemNotifier Notifier;
+
+ // The map type.
+ typedef VectorMap Map;
+
+ // The reference type of the map;
+ typedef typename Container::reference Reference;
+ // The const reference type of the map;
+ typedef typename Container::const_reference ConstReference;
+
+ private:
+
+ // The base class of the map.
+ typedef typename Notifier::ObserverBase Parent;
+
+ public:
+
+ // \brief Constructor to attach the new map into the notifier.
+ //
+ // It constructs a map and attachs it into the notifier.
+ // It adds all the items of the graph to the map.
+ VectorMap(const GraphType& graph) {
+ Parent::attach(graph.notifier(Item()));
+ container.resize(Parent::notifier()->maxId() + 1);
+ }
+
+ // \brief Constructor uses given value to initialize the map.
+ //
+ // It constructs a map uses a given value to initialize the map.
+ // It adds all the items of the graph to the map.
+ VectorMap(const GraphType& graph, const Value& value) {
+ Parent::attach(graph.notifier(Item()));
+ container.resize(Parent::notifier()->maxId() + 1, value);
+ }
+
+ private:
+ // \brief Copy constructor
+ //
+ // Copy constructor.
+ VectorMap(const VectorMap& _copy) : Parent() {
+ if (_copy.attached()) {
+ Parent::attach(*_copy.notifier());
+ container = _copy.container;
+ }
+ }
+
+ // \brief Assign operator.
+ //
+ // This operator assigns for each item in the map the
+ // value mapped to the same item in the copied map.
+ // The parameter map should be indiced with the same
+ // itemset because this assign operator does not change
+ // the container of the map.
+ VectorMap& operator=(const VectorMap& cmap) {
+ return operator=<VectorMap>(cmap);
+ }
+
+
+ // \brief Template assign operator.
+ //
+ // The given parameter should conform to the ReadMap
+ // concecpt and could be indiced by the current item set of
+ // the NodeMap. In this case the value for each item
+ // is assigned by the value of the given ReadMap.
+ template <typename CMap>
+ VectorMap& operator=(const CMap& cmap) {
+ checkConcept<concepts::ReadMap<Key, _Value>, CMap>();
+ const typename Parent::Notifier* nf = Parent::notifier();
+ Item it;
+ for (nf->first(it); it != INVALID; nf->next(it)) {
+ set(it, cmap[it]);
+ }
+ return *this;
+ }
+
+ public:
+
+ // \brief The subcript operator.
+ //
+ // The subscript operator. The map can be subscripted by the
+ // actual items of the graph.
+ Reference operator[](const Key& key) {
+ return container[Parent::notifier()->id(key)];
+ }
+
+ // \brief The const subcript operator.
+ //
+ // The const subscript operator. The map can be subscripted by the
+ // actual items of the graph.
+ ConstReference operator[](const Key& key) const {
+ return container[Parent::notifier()->id(key)];
+ }
+
+
+ // \brief The setter function of the map.
+ //
+ // It the same as operator[](key) = value expression.
+ void set(const Key& key, const Value& value) {
+ (*this)[key] = value;
+ }
+
+ protected:
+
+ // \brief Adds a new key to the map.
+ //
+ // It adds a new key to the map. It is called by the observer notifier
+ // and it overrides the add() member function of the observer base.
+ virtual void add(const Key& key) {
+ int id = Parent::notifier()->id(key);
+ if (id >= int(container.size())) {
+ container.resize(id + 1);
+ }
+ }
+
+ // \brief Adds more new keys to the map.
+ //
+ // It adds more new keys to the map. It is called by the observer notifier
+ // and it overrides the add() member function of the observer base.
+ virtual void add(const std::vector<Key>& keys) {
+ int max = container.size() - 1;
+ for (int i = 0; i < int(keys.size()); ++i) {
+ int id = Parent::notifier()->id(keys[i]);
+ if (id >= max) {
+ max = id;
+ }
+ }
+ container.resize(max + 1);
+ }
+
+ // \brief Erase a key from the map.
+ //
+ // Erase a key from the map. It is called by the observer notifier
+ // and it overrides the erase() member function of the observer base.
+ virtual void erase(const Key& key) {
+ container[Parent::notifier()->id(key)] = Value();
+ }
+
+ // \brief Erase more keys from the map.
+ //
+ // It erases more keys from the map. It is called by the observer notifier
+ // and it overrides the erase() member function of the observer base.
+ virtual void erase(const std::vector<Key>& keys) {
+ for (int i = 0; i < int(keys.size()); ++i) {
+ container[Parent::notifier()->id(keys[i])] = Value();
+ }
+ }
+
+ // \brief Build the map.
+ //
+ // It builds the map. It is called by the observer notifier
+ // and it overrides the build() member function of the observer base.
+ virtual void build() {
+ int size = Parent::notifier()->maxId() + 1;
+ container.reserve(size);
+ container.resize(size);
+ }
+
+ // \brief Clear the map.
+ //
+ // It erases all items from the map. It is called by the observer notifier
+ // and it overrides the clear() member function of the observer base.
+ virtual void clear() {
+ container.clear();
+ }
+
+ private:
+
+ Container container;
+
+ };
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/windows.cc b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/windows.cc
new file mode 100644
index 00000000000..7ad901c619c
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/windows.cc
@@ -0,0 +1,166 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\file
+///\brief Some basic non-inline functions and static global data.
+
+#include<lemon/bits/windows.h>
+
+#ifdef WIN32
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#ifdef UNICODE
+#undef UNICODE
+#endif
+#include <windows.h>
+#ifdef LOCALE_INVARIANT
+#define MY_LOCALE LOCALE_INVARIANT
+#else
+#define MY_LOCALE LOCALE_NEUTRAL
+#endif
+#else
+#include <unistd.h>
+#include <ctime>
+#ifndef WIN32
+#include <sys/times.h>
+#endif
+#include <sys/time.h>
+#endif
+
+#include <cmath>
+#include <sstream>
+
+namespace lemon {
+ namespace bits {
+ void getWinProcTimes(double &rtime,
+ double &utime, double &stime,
+ double &cutime, double &cstime)
+ {
+#ifdef WIN32
+ static const double ch = 4294967296.0e-7;
+ static const double cl = 1.0e-7;
+
+ FILETIME system;
+ GetSystemTimeAsFileTime(&system);
+ rtime = ch * system.dwHighDateTime + cl * system.dwLowDateTime;
+
+ FILETIME create, exit, kernel, user;
+ if (GetProcessTimes(GetCurrentProcess(),&create, &exit, &kernel, &user)) {
+ utime = ch * user.dwHighDateTime + cl * user.dwLowDateTime;
+ stime = ch * kernel.dwHighDateTime + cl * kernel.dwLowDateTime;
+ cutime = 0;
+ cstime = 0;
+ } else {
+ rtime = 0;
+ utime = 0;
+ stime = 0;
+ cutime = 0;
+ cstime = 0;
+ }
+#else
+ timeval tv;
+ gettimeofday(&tv, 0);
+ rtime=tv.tv_sec+double(tv.tv_usec)/1e6;
+
+ tms ts;
+ double tck=sysconf(_SC_CLK_TCK);
+ times(&ts);
+ utime=ts.tms_utime/tck;
+ stime=ts.tms_stime/tck;
+ cutime=ts.tms_cutime/tck;
+ cstime=ts.tms_cstime/tck;
+#endif
+ }
+
+ std::string getWinFormattedDate()
+ {
+ std::ostringstream os;
+#ifdef WIN32
+ SYSTEMTIME time;
+ GetSystemTime(&time);
+ char buf1[11], buf2[9], buf3[5];
+ if (GetDateFormat(MY_LOCALE, 0, &time,
+ ("ddd MMM dd"), buf1, 11) &&
+ GetTimeFormat(MY_LOCALE, 0, &time,
+ ("HH':'mm':'ss"), buf2, 9) &&
+ GetDateFormat(MY_LOCALE, 0, &time,
+ ("yyyy"), buf3, 5)) {
+ os << buf1 << ' ' << buf2 << ' ' << buf3;
+ }
+ else os << "unknown";
+#else
+ timeval tv;
+ gettimeofday(&tv, 0);
+
+ char cbuf[26];
+ ctime_r(&tv.tv_sec,cbuf);
+ os << cbuf;
+#endif
+ return os.str();
+ }
+
+ int getWinRndSeed()
+ {
+#ifdef WIN32
+ FILETIME time;
+ GetSystemTimeAsFileTime(&time);
+ return GetCurrentProcessId() + time.dwHighDateTime + time.dwLowDateTime;
+#else
+ timeval tv;
+ gettimeofday(&tv, 0);
+ return getpid() + tv.tv_sec + tv.tv_usec;
+#endif
+ }
+
+ WinLock::WinLock() {
+#ifdef WIN32
+ CRITICAL_SECTION *lock = new CRITICAL_SECTION;
+ InitializeCriticalSection(lock);
+ _repr = lock;
+#else
+ _repr = 0; //Just to avoid 'unused variable' warning with clang
+#endif
+ }
+
+ WinLock::~WinLock() {
+#ifdef WIN32
+ CRITICAL_SECTION *lock = static_cast<CRITICAL_SECTION*>(_repr);
+ DeleteCriticalSection(lock);
+ delete lock;
+#endif
+ }
+
+ void WinLock::lock() {
+#ifdef WIN32
+ CRITICAL_SECTION *lock = static_cast<CRITICAL_SECTION*>(_repr);
+ EnterCriticalSection(lock);
+#endif
+ }
+
+ void WinLock::unlock() {
+#ifdef WIN32
+ CRITICAL_SECTION *lock = static_cast<CRITICAL_SECTION*>(_repr);
+ LeaveCriticalSection(lock);
+#endif
+ }
+ }
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/windows.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/windows.h
new file mode 100644
index 00000000000..c09bb1284c5
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/windows.h
@@ -0,0 +1,44 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BITS_WINDOWS_H
+#define LEMON_BITS_WINDOWS_H
+
+#include <string>
+
+namespace lemon {
+ namespace bits {
+ void getWinProcTimes(double &rtime,
+ double &utime, double &stime,
+ double &cutime, double &cstime);
+ std::string getWinFormattedDate();
+ int getWinRndSeed();
+
+ class WinLock {
+ public:
+ WinLock();
+ ~WinLock();
+ void lock();
+ void unlock();
+ private:
+ void *_repr;
+ };
+ }
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bucket_heap.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bucket_heap.h
new file mode 100644
index 00000000000..92dbc08f011
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bucket_heap.h
@@ -0,0 +1,594 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2010
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BUCKET_HEAP_H
+#define LEMON_BUCKET_HEAP_H
+
+///\ingroup heaps
+///\file
+///\brief Bucket heap implementation.
+
+#include <vector>
+#include <utility>
+#include <functional>
+
+namespace lemon {
+
+ namespace _bucket_heap_bits {
+
+ template <bool MIN>
+ struct DirectionTraits {
+ static bool less(int left, int right) {
+ return left < right;
+ }
+ static void increase(int& value) {
+ ++value;
+ }
+ };
+
+ template <>
+ struct DirectionTraits<false> {
+ static bool less(int left, int right) {
+ return left > right;
+ }
+ static void increase(int& value) {
+ --value;
+ }
+ };
+
+ }
+
+ /// \ingroup heaps
+ ///
+ /// \brief Bucket heap data structure.
+ ///
+ /// This class implements the \e bucket \e heap data structure.
+ /// It practically conforms to the \ref concepts::Heap "heap concept",
+ /// but it has some limitations.
+ ///
+ /// The bucket heap is a very simple structure. It can store only
+ /// \c int priorities and it maintains a list of items for each priority
+ /// in the range <tt>[0..C)</tt>. So it should only be used when the
+ /// priorities are small. It is not intended to use as a Dijkstra heap.
+ ///
+ /// \tparam IM A read-writable item map with \c int values, used
+ /// internally to handle the cross references.
+ /// \tparam MIN Indicate if the heap is a \e min-heap or a \e max-heap.
+ /// The default is \e min-heap. If this parameter is set to \c false,
+ /// then the comparison is reversed, so the top(), prio() and pop()
+ /// functions deal with the item having maximum priority instead of the
+ /// minimum.
+ ///
+ /// \sa SimpleBucketHeap
+ template <typename IM, bool MIN = true>
+ class BucketHeap {
+
+ public:
+
+ /// Type of the item-int map.
+ typedef IM ItemIntMap;
+ /// Type of the priorities.
+ typedef int Prio;
+ /// Type of the items stored in the heap.
+ typedef typename ItemIntMap::Key Item;
+ /// Type of the item-priority pairs.
+ typedef std::pair<Item,Prio> Pair;
+
+ private:
+
+ typedef _bucket_heap_bits::DirectionTraits<MIN> Direction;
+
+ public:
+
+ /// \brief Type to represent the states of the items.
+ ///
+ /// Each item has a state associated to it. It can be "in heap",
+ /// "pre-heap" or "post-heap". The latter two are indifferent from the
+ /// heap's point of view, but may be useful to the user.
+ ///
+ /// The item-int map must be initialized in such way that it assigns
+ /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
+ enum State {
+ IN_HEAP = 0, ///< = 0.
+ PRE_HEAP = -1, ///< = -1.
+ POST_HEAP = -2 ///< = -2.
+ };
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// \param map A map that assigns \c int values to the items.
+ /// It is used internally to handle the cross references.
+ /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
+ explicit BucketHeap(ItemIntMap &map) : _iim(map), _minimum(0) {}
+
+ /// \brief The number of items stored in the heap.
+ ///
+ /// This function returns the number of items stored in the heap.
+ int size() const { return _data.size(); }
+
+ /// \brief Check if the heap is empty.
+ ///
+ /// This function returns \c true if the heap is empty.
+ bool empty() const { return _data.empty(); }
+
+ /// \brief Make the heap empty.
+ ///
+ /// This functon makes the heap empty.
+ /// It does not change the cross reference map. If you want to reuse
+ /// a heap that is not surely empty, you should first clear it and
+ /// then you should set the cross reference map to \c PRE_HEAP
+ /// for each item.
+ void clear() {
+ _data.clear(); _first.clear(); _minimum = 0;
+ }
+
+ private:
+
+ void relocateLast(int idx) {
+ if (idx + 1 < int(_data.size())) {
+ _data[idx] = _data.back();
+ if (_data[idx].prev != -1) {
+ _data[_data[idx].prev].next = idx;
+ } else {
+ _first[_data[idx].value] = idx;
+ }
+ if (_data[idx].next != -1) {
+ _data[_data[idx].next].prev = idx;
+ }
+ _iim[_data[idx].item] = idx;
+ }
+ _data.pop_back();
+ }
+
+ void unlace(int idx) {
+ if (_data[idx].prev != -1) {
+ _data[_data[idx].prev].next = _data[idx].next;
+ } else {
+ _first[_data[idx].value] = _data[idx].next;
+ }
+ if (_data[idx].next != -1) {
+ _data[_data[idx].next].prev = _data[idx].prev;
+ }
+ }
+
+ void lace(int idx) {
+ if (int(_first.size()) <= _data[idx].value) {
+ _first.resize(_data[idx].value + 1, -1);
+ }
+ _data[idx].next = _first[_data[idx].value];
+ if (_data[idx].next != -1) {
+ _data[_data[idx].next].prev = idx;
+ }
+ _first[_data[idx].value] = idx;
+ _data[idx].prev = -1;
+ }
+
+ public:
+
+ /// \brief Insert a pair of item and priority into the heap.
+ ///
+ /// This function inserts \c p.first to the heap with priority
+ /// \c p.second.
+ /// \param p The pair to insert.
+ /// \pre \c p.first must not be stored in the heap.
+ void push(const Pair& p) {
+ push(p.first, p.second);
+ }
+
+ /// \brief Insert an item into the heap with the given priority.
+ ///
+ /// This function inserts the given item into the heap with the
+ /// given priority.
+ /// \param i The item to insert.
+ /// \param p The priority of the item.
+ /// \pre \e i must not be stored in the heap.
+ void push(const Item &i, const Prio &p) {
+ int idx = _data.size();
+ _iim[i] = idx;
+ _data.push_back(BucketItem(i, p));
+ lace(idx);
+ if (Direction::less(p, _minimum)) {
+ _minimum = p;
+ }
+ }
+
+ /// \brief Return the item having minimum priority.
+ ///
+ /// This function returns the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ Item top() const {
+ while (_first[_minimum] == -1) {
+ Direction::increase(_minimum);
+ }
+ return _data[_first[_minimum]].item;
+ }
+
+ /// \brief The minimum priority.
+ ///
+ /// This function returns the minimum priority.
+ /// \pre The heap must be non-empty.
+ Prio prio() const {
+ while (_first[_minimum] == -1) {
+ Direction::increase(_minimum);
+ }
+ return _minimum;
+ }
+
+ /// \brief Remove the item having minimum priority.
+ ///
+ /// This function removes the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ void pop() {
+ while (_first[_minimum] == -1) {
+ Direction::increase(_minimum);
+ }
+ int idx = _first[_minimum];
+ _iim[_data[idx].item] = -2;
+ unlace(idx);
+ relocateLast(idx);
+ }
+
+ /// \brief Remove the given item from the heap.
+ ///
+ /// This function removes the given item from the heap if it is
+ /// already stored.
+ /// \param i The item to delete.
+ /// \pre \e i must be in the heap.
+ void erase(const Item &i) {
+ int idx = _iim[i];
+ _iim[_data[idx].item] = -2;
+ unlace(idx);
+ relocateLast(idx);
+ }
+
+ /// \brief The priority of the given item.
+ ///
+ /// This function returns the priority of the given item.
+ /// \param i The item.
+ /// \pre \e i must be in the heap.
+ Prio operator[](const Item &i) const {
+ int idx = _iim[i];
+ return _data[idx].value;
+ }
+
+ /// \brief Set the priority of an item or insert it, if it is
+ /// not stored in the heap.
+ ///
+ /// This method sets the priority of the given item if it is
+ /// already stored in the heap. Otherwise it inserts the given
+ /// item into the heap with the given priority.
+ /// \param i The item.
+ /// \param p The priority.
+ void set(const Item &i, const Prio &p) {
+ int idx = _iim[i];
+ if (idx < 0) {
+ push(i, p);
+ } else if (Direction::less(p, _data[idx].value)) {
+ decrease(i, p);
+ } else {
+ increase(i, p);
+ }
+ }
+
+ /// \brief Decrease the priority of an item to the given value.
+ ///
+ /// This function decreases the priority of an item to the given value.
+ /// \param i The item.
+ /// \param p The priority.
+ /// \pre \e i must be stored in the heap with priority at least \e p.
+ void decrease(const Item &i, const Prio &p) {
+ int idx = _iim[i];
+ unlace(idx);
+ _data[idx].value = p;
+ if (Direction::less(p, _minimum)) {
+ _minimum = p;
+ }
+ lace(idx);
+ }
+
+ /// \brief Increase the priority of an item to the given value.
+ ///
+ /// This function increases the priority of an item to the given value.
+ /// \param i The item.
+ /// \param p The priority.
+ /// \pre \e i must be stored in the heap with priority at most \e p.
+ void increase(const Item &i, const Prio &p) {
+ int idx = _iim[i];
+ unlace(idx);
+ _data[idx].value = p;
+ lace(idx);
+ }
+
+ /// \brief Return the state of an item.
+ ///
+ /// This method returns \c PRE_HEAP if the given item has never
+ /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
+ /// and \c POST_HEAP otherwise.
+ /// In the latter case it is possible that the item will get back
+ /// to the heap again.
+ /// \param i The item.
+ State state(const Item &i) const {
+ int idx = _iim[i];
+ if (idx >= 0) idx = 0;
+ return State(idx);
+ }
+
+ /// \brief Set the state of an item in the heap.
+ ///
+ /// This function sets the state of the given item in the heap.
+ /// It can be used to manually clear the heap when it is important
+ /// to achive better time complexity.
+ /// \param i The item.
+ /// \param st The state. It should not be \c IN_HEAP.
+ void state(const Item& i, State st) {
+ switch (st) {
+ case POST_HEAP:
+ case PRE_HEAP:
+ if (state(i) == IN_HEAP) {
+ erase(i);
+ }
+ _iim[i] = st;
+ break;
+ case IN_HEAP:
+ break;
+ }
+ }
+
+ private:
+
+ struct BucketItem {
+ BucketItem(const Item& _item, int _value)
+ : item(_item), value(_value) {}
+
+ Item item;
+ int value;
+
+ int prev, next;
+ };
+
+ ItemIntMap& _iim;
+ std::vector<int> _first;
+ std::vector<BucketItem> _data;
+ mutable int _minimum;
+
+ }; // class BucketHeap
+
+ /// \ingroup heaps
+ ///
+ /// \brief Simplified bucket heap data structure.
+ ///
+ /// This class implements a simplified \e bucket \e heap data
+ /// structure. It does not provide some functionality, but it is
+ /// faster and simpler than BucketHeap. The main difference is
+ /// that BucketHeap stores a doubly-linked list for each key while
+ /// this class stores only simply-linked lists. It supports erasing
+ /// only for the item having minimum priority and it does not support
+ /// key increasing and decreasing.
+ ///
+ /// Note that this implementation does not conform to the
+ /// \ref concepts::Heap "heap concept" due to the lack of some
+ /// functionality.
+ ///
+ /// \tparam IM A read-writable item map with \c int values, used
+ /// internally to handle the cross references.
+ /// \tparam MIN Indicate if the heap is a \e min-heap or a \e max-heap.
+ /// The default is \e min-heap. If this parameter is set to \c false,
+ /// then the comparison is reversed, so the top(), prio() and pop()
+ /// functions deal with the item having maximum priority instead of the
+ /// minimum.
+ ///
+ /// \sa BucketHeap
+ template <typename IM, bool MIN = true >
+ class SimpleBucketHeap {
+
+ public:
+
+ /// Type of the item-int map.
+ typedef IM ItemIntMap;
+ /// Type of the priorities.
+ typedef int Prio;
+ /// Type of the items stored in the heap.
+ typedef typename ItemIntMap::Key Item;
+ /// Type of the item-priority pairs.
+ typedef std::pair<Item,Prio> Pair;
+
+ private:
+
+ typedef _bucket_heap_bits::DirectionTraits<MIN> Direction;
+
+ public:
+
+ /// \brief Type to represent the states of the items.
+ ///
+ /// Each item has a state associated to it. It can be "in heap",
+ /// "pre-heap" or "post-heap". The latter two are indifferent from the
+ /// heap's point of view, but may be useful to the user.
+ ///
+ /// The item-int map must be initialized in such way that it assigns
+ /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
+ enum State {
+ IN_HEAP = 0, ///< = 0.
+ PRE_HEAP = -1, ///< = -1.
+ POST_HEAP = -2 ///< = -2.
+ };
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// \param map A map that assigns \c int values to the items.
+ /// It is used internally to handle the cross references.
+ /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
+ explicit SimpleBucketHeap(ItemIntMap &map)
+ : _iim(map), _free(-1), _num(0), _minimum(0) {}
+
+ /// \brief The number of items stored in the heap.
+ ///
+ /// This function returns the number of items stored in the heap.
+ int size() const { return _num; }
+
+ /// \brief Check if the heap is empty.
+ ///
+ /// This function returns \c true if the heap is empty.
+ bool empty() const { return _num == 0; }
+
+ /// \brief Make the heap empty.
+ ///
+ /// This functon makes the heap empty.
+ /// It does not change the cross reference map. If you want to reuse
+ /// a heap that is not surely empty, you should first clear it and
+ /// then you should set the cross reference map to \c PRE_HEAP
+ /// for each item.
+ void clear() {
+ _data.clear(); _first.clear(); _free = -1; _num = 0; _minimum = 0;
+ }
+
+ /// \brief Insert a pair of item and priority into the heap.
+ ///
+ /// This function inserts \c p.first to the heap with priority
+ /// \c p.second.
+ /// \param p The pair to insert.
+ /// \pre \c p.first must not be stored in the heap.
+ void push(const Pair& p) {
+ push(p.first, p.second);
+ }
+
+ /// \brief Insert an item into the heap with the given priority.
+ ///
+ /// This function inserts the given item into the heap with the
+ /// given priority.
+ /// \param i The item to insert.
+ /// \param p The priority of the item.
+ /// \pre \e i must not be stored in the heap.
+ void push(const Item &i, const Prio &p) {
+ int idx;
+ if (_free == -1) {
+ idx = _data.size();
+ _data.push_back(BucketItem(i));
+ } else {
+ idx = _free;
+ _free = _data[idx].next;
+ _data[idx].item = i;
+ }
+ _iim[i] = idx;
+ if (p >= int(_first.size())) _first.resize(p + 1, -1);
+ _data[idx].next = _first[p];
+ _first[p] = idx;
+ if (Direction::less(p, _minimum)) {
+ _minimum = p;
+ }
+ ++_num;
+ }
+
+ /// \brief Return the item having minimum priority.
+ ///
+ /// This function returns the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ Item top() const {
+ while (_first[_minimum] == -1) {
+ Direction::increase(_minimum);
+ }
+ return _data[_first[_minimum]].item;
+ }
+
+ /// \brief The minimum priority.
+ ///
+ /// This function returns the minimum priority.
+ /// \pre The heap must be non-empty.
+ Prio prio() const {
+ while (_first[_minimum] == -1) {
+ Direction::increase(_minimum);
+ }
+ return _minimum;
+ }
+
+ /// \brief Remove the item having minimum priority.
+ ///
+ /// This function removes the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ void pop() {
+ while (_first[_minimum] == -1) {
+ Direction::increase(_minimum);
+ }
+ int idx = _first[_minimum];
+ _iim[_data[idx].item] = -2;
+ _first[_minimum] = _data[idx].next;
+ _data[idx].next = _free;
+ _free = idx;
+ --_num;
+ }
+
+ /// \brief The priority of the given item.
+ ///
+ /// This function returns the priority of the given item.
+ /// \param i The item.
+ /// \pre \e i must be in the heap.
+ /// \warning This operator is not a constant time function because
+ /// it scans the whole data structure to find the proper value.
+ Prio operator[](const Item &i) const {
+ for (int k = 0; k < int(_first.size()); ++k) {
+ int idx = _first[k];
+ while (idx != -1) {
+ if (_data[idx].item == i) {
+ return k;
+ }
+ idx = _data[idx].next;
+ }
+ }
+ return -1;
+ }
+
+ /// \brief Return the state of an item.
+ ///
+ /// This method returns \c PRE_HEAP if the given item has never
+ /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
+ /// and \c POST_HEAP otherwise.
+ /// In the latter case it is possible that the item will get back
+ /// to the heap again.
+ /// \param i The item.
+ State state(const Item &i) const {
+ int idx = _iim[i];
+ if (idx >= 0) idx = 0;
+ return State(idx);
+ }
+
+ private:
+
+ struct BucketItem {
+ BucketItem(const Item& _item)
+ : item(_item) {}
+
+ Item item;
+ int next;
+ };
+
+ ItemIntMap& _iim;
+ std::vector<int> _first;
+ std::vector<BucketItem> _data;
+ int _free, _num;
+ mutable int _minimum;
+
+ }; // class SimpleBucketHeap
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/capacity_scaling.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/capacity_scaling.h
new file mode 100644
index 00000000000..ca64b56d3b3
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/capacity_scaling.h
@@ -0,0 +1,1014 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_CAPACITY_SCALING_H
+#define LEMON_CAPACITY_SCALING_H
+
+/// \ingroup min_cost_flow_algs
+///
+/// \file
+/// \brief Capacity Scaling algorithm for finding a minimum cost flow.
+
+#include <vector>
+#include <limits>
+#include <lemon/core.h>
+#include <lemon/bin_heap.h>
+
+namespace lemon {
+
+ /// \brief Default traits class of CapacityScaling algorithm.
+ ///
+ /// Default traits class of CapacityScaling algorithm.
+ /// \tparam GR Digraph type.
+ /// \tparam V The number type used for flow amounts, capacity bounds
+ /// and supply values. By default it is \c int.
+ /// \tparam C The number type used for costs and potentials.
+ /// By default it is the same as \c V.
+ template <typename GR, typename V = int, typename C = V>
+ struct CapacityScalingDefaultTraits
+ {
+ /// The type of the digraph
+ typedef GR Digraph;
+ /// The type of the flow amounts, capacity bounds and supply values
+ typedef V Value;
+ /// The type of the arc costs
+ typedef C Cost;
+
+ /// \brief The type of the heap used for internal Dijkstra computations.
+ ///
+ /// The type of the heap used for internal Dijkstra computations.
+ /// It must conform to the \ref lemon::concepts::Heap "Heap" concept,
+ /// its priority type must be \c Cost and its cross reference type
+ /// must be \ref RangeMap "RangeMap<int>".
+ typedef BinHeap<Cost, RangeMap<int> > Heap;
+ };
+
+ /// \addtogroup min_cost_flow_algs
+ /// @{
+
+ /// \brief Implementation of the Capacity Scaling algorithm for
+ /// finding a \ref min_cost_flow "minimum cost flow".
+ ///
+ /// \ref CapacityScaling implements the capacity scaling version
+ /// of the successive shortest path algorithm for finding a
+ /// \ref min_cost_flow "minimum cost flow" \cite amo93networkflows,
+ /// \cite edmondskarp72theoretical. It is an efficient dual
+ /// solution method, which runs in polynomial time
+ /// \f$O(m\log U (n+m)\log n)\f$, where <i>U</i> denotes the maximum
+ /// of node supply and arc capacity values.
+ ///
+ /// This algorithm is typically slower than \ref CostScaling and
+ /// \ref NetworkSimplex, but in special cases, it can be more
+ /// efficient than them.
+ /// (For more information, see \ref min_cost_flow_algs "the module page".)
+ ///
+ /// Most of the parameters of the problem (except for the digraph)
+ /// can be given using separate functions, and the algorithm can be
+ /// executed using the \ref run() function. If some parameters are not
+ /// specified, then default values will be used.
+ ///
+ /// \tparam GR The digraph type the algorithm runs on.
+ /// \tparam V The number type used for flow amounts, capacity bounds
+ /// and supply values in the algorithm. By default, it is \c int.
+ /// \tparam C The number type used for costs and potentials in the
+ /// algorithm. By default, it is the same as \c V.
+ /// \tparam TR The traits class that defines various types used by the
+ /// algorithm. By default, it is \ref CapacityScalingDefaultTraits
+ /// "CapacityScalingDefaultTraits<GR, V, C>".
+ /// In most cases, this parameter should not be set directly,
+ /// consider to use the named template parameters instead.
+ ///
+ /// \warning Both \c V and \c C must be signed number types.
+ /// \warning Capacity bounds and supply values must be integer, but
+ /// arc costs can be arbitrary real numbers.
+ /// \warning This algorithm does not support negative costs for
+ /// arcs having infinite upper bound.
+#ifdef DOXYGEN
+ template <typename GR, typename V, typename C, typename TR>
+#else
+ template < typename GR, typename V = int, typename C = V,
+ typename TR = CapacityScalingDefaultTraits<GR, V, C> >
+#endif
+ class CapacityScaling
+ {
+ public:
+
+ /// The type of the digraph
+ typedef typename TR::Digraph Digraph;
+ /// The type of the flow amounts, capacity bounds and supply values
+ typedef typename TR::Value Value;
+ /// The type of the arc costs
+ typedef typename TR::Cost Cost;
+
+ /// The type of the heap used for internal Dijkstra computations
+ typedef typename TR::Heap Heap;
+
+ /// \brief The \ref lemon::CapacityScalingDefaultTraits "traits class"
+ /// of the algorithm
+ typedef TR Traits;
+
+ public:
+
+ /// \brief Problem type constants for the \c run() function.
+ ///
+ /// Enum type containing the problem type constants that can be
+ /// returned by the \ref run() function of the algorithm.
+ enum ProblemType {
+ /// The problem has no feasible solution (flow).
+ INFEASIBLE,
+ /// The problem has optimal solution (i.e. it is feasible and
+ /// bounded), and the algorithm has found optimal flow and node
+ /// potentials (primal and dual solutions).
+ OPTIMAL,
+ /// The digraph contains an arc of negative cost and infinite
+ /// upper bound. It means that the objective function is unbounded
+ /// on that arc, however, note that it could actually be bounded
+ /// over the feasible flows, but this algroithm cannot handle
+ /// these cases.
+ UNBOUNDED
+ };
+
+ private:
+
+ TEMPLATE_DIGRAPH_TYPEDEFS(GR);
+
+ typedef std::vector<int> IntVector;
+ typedef std::vector<Value> ValueVector;
+ typedef std::vector<Cost> CostVector;
+ typedef std::vector<char> BoolVector;
+ // Note: vector<char> is used instead of vector<bool> for efficiency reasons
+
+ private:
+
+ // Data related to the underlying digraph
+ const GR &_graph;
+ int _node_num;
+ int _arc_num;
+ int _res_arc_num;
+ int _root;
+
+ // Parameters of the problem
+ bool _has_lower;
+ Value _sum_supply;
+
+ // Data structures for storing the digraph
+ IntNodeMap _node_id;
+ IntArcMap _arc_idf;
+ IntArcMap _arc_idb;
+ IntVector _first_out;
+ BoolVector _forward;
+ IntVector _source;
+ IntVector _target;
+ IntVector _reverse;
+
+ // Node and arc data
+ ValueVector _lower;
+ ValueVector _upper;
+ CostVector _cost;
+ ValueVector _supply;
+
+ ValueVector _res_cap;
+ CostVector _pi;
+ ValueVector _excess;
+ IntVector _excess_nodes;
+ IntVector _deficit_nodes;
+
+ Value _delta;
+ int _factor;
+ IntVector _pred;
+
+ public:
+
+ /// \brief Constant for infinite upper bounds (capacities).
+ ///
+ /// Constant for infinite upper bounds (capacities).
+ /// It is \c std::numeric_limits<Value>::infinity() if available,
+ /// \c std::numeric_limits<Value>::max() otherwise.
+ const Value INF;
+
+ private:
+
+ // Special implementation of the Dijkstra algorithm for finding
+ // shortest paths in the residual network of the digraph with
+ // respect to the reduced arc costs and modifying the node
+ // potentials according to the found distance labels.
+ class ResidualDijkstra
+ {
+ private:
+
+ int _node_num;
+ bool _geq;
+ const IntVector &_first_out;
+ const IntVector &_target;
+ const CostVector &_cost;
+ const ValueVector &_res_cap;
+ const ValueVector &_excess;
+ CostVector &_pi;
+ IntVector &_pred;
+
+ IntVector _proc_nodes;
+ CostVector _dist;
+
+ public:
+
+ ResidualDijkstra(CapacityScaling& cs) :
+ _node_num(cs._node_num), _geq(cs._sum_supply < 0),
+ _first_out(cs._first_out), _target(cs._target), _cost(cs._cost),
+ _res_cap(cs._res_cap), _excess(cs._excess), _pi(cs._pi),
+ _pred(cs._pred), _dist(cs._node_num)
+ {}
+
+ int run(int s, Value delta = 1) {
+ RangeMap<int> heap_cross_ref(_node_num, Heap::PRE_HEAP);
+ Heap heap(heap_cross_ref);
+ heap.push(s, 0);
+ _pred[s] = -1;
+ _proc_nodes.clear();
+
+ // Process nodes
+ while (!heap.empty() && _excess[heap.top()] > -delta) {
+ int u = heap.top(), v;
+ Cost d = heap.prio() + _pi[u], dn;
+ _dist[u] = heap.prio();
+ _proc_nodes.push_back(u);
+ heap.pop();
+
+ // Traverse outgoing residual arcs
+ int last_out = _geq ? _first_out[u+1] : _first_out[u+1] - 1;
+ for (int a = _first_out[u]; a != last_out; ++a) {
+ if (_res_cap[a] < delta) continue;
+ v = _target[a];
+ switch (heap.state(v)) {
+ case Heap::PRE_HEAP:
+ heap.push(v, d + _cost[a] - _pi[v]);
+ _pred[v] = a;
+ break;
+ case Heap::IN_HEAP:
+ dn = d + _cost[a] - _pi[v];
+ if (dn < heap[v]) {
+ heap.decrease(v, dn);
+ _pred[v] = a;
+ }
+ break;
+ case Heap::POST_HEAP:
+ break;
+ }
+ }
+ }
+ if (heap.empty()) return -1;
+
+ // Update potentials of processed nodes
+ int t = heap.top();
+ Cost dt = heap.prio();
+ for (int i = 0; i < int(_proc_nodes.size()); ++i) {
+ _pi[_proc_nodes[i]] += _dist[_proc_nodes[i]] - dt;
+ }
+
+ return t;
+ }
+
+ }; //class ResidualDijkstra
+
+ public:
+
+ /// \name Named Template Parameters
+ /// @{
+
+ template <typename T>
+ struct SetHeapTraits : public Traits {
+ typedef T Heap;
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// \c Heap type.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting \c Heap
+ /// type, which is used for internal Dijkstra computations.
+ /// It must conform to the \ref lemon::concepts::Heap "Heap" concept,
+ /// its priority type must be \c Cost and its cross reference type
+ /// must be \ref RangeMap "RangeMap<int>".
+ template <typename T>
+ struct SetHeap
+ : public CapacityScaling<GR, V, C, SetHeapTraits<T> > {
+ typedef CapacityScaling<GR, V, C, SetHeapTraits<T> > Create;
+ };
+
+ /// @}
+
+ protected:
+
+ CapacityScaling() {}
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// The constructor of the class.
+ ///
+ /// \param graph The digraph the algorithm runs on.
+ CapacityScaling(const GR& graph) :
+ _graph(graph), _node_id(graph), _arc_idf(graph), _arc_idb(graph),
+ INF(std::numeric_limits<Value>::has_infinity ?
+ std::numeric_limits<Value>::infinity() :
+ std::numeric_limits<Value>::max())
+ {
+ // Check the number types
+ LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
+ "The flow type of CapacityScaling must be signed");
+ LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
+ "The cost type of CapacityScaling must be signed");
+
+ // Reset data structures
+ reset();
+ }
+
+ /// \name Parameters
+ /// The parameters of the algorithm can be specified using these
+ /// functions.
+
+ /// @{
+
+ /// \brief Set the lower bounds on the arcs.
+ ///
+ /// This function sets the lower bounds on the arcs.
+ /// If it is not used before calling \ref run(), the lower bounds
+ /// will be set to zero on all arcs.
+ ///
+ /// \param map An arc map storing the lower bounds.
+ /// Its \c Value type must be convertible to the \c Value type
+ /// of the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ template <typename LowerMap>
+ CapacityScaling& lowerMap(const LowerMap& map) {
+ _has_lower = true;
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ _lower[_arc_idf[a]] = map[a];
+ }
+ return *this;
+ }
+
+ /// \brief Set the upper bounds (capacities) on the arcs.
+ ///
+ /// This function sets the upper bounds (capacities) on the arcs.
+ /// If it is not used before calling \ref run(), the upper bounds
+ /// will be set to \ref INF on all arcs (i.e. the flow value will be
+ /// unbounded from above).
+ ///
+ /// \param map An arc map storing the upper bounds.
+ /// Its \c Value type must be convertible to the \c Value type
+ /// of the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ template<typename UpperMap>
+ CapacityScaling& upperMap(const UpperMap& map) {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ _upper[_arc_idf[a]] = map[a];
+ }
+ return *this;
+ }
+
+ /// \brief Set the costs of the arcs.
+ ///
+ /// This function sets the costs of the arcs.
+ /// If it is not used before calling \ref run(), the costs
+ /// will be set to \c 1 on all arcs.
+ ///
+ /// \param map An arc map storing the costs.
+ /// Its \c Value type must be convertible to the \c Cost type
+ /// of the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ template<typename CostMap>
+ CapacityScaling& costMap(const CostMap& map) {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ _cost[_arc_idf[a]] = map[a];
+ _cost[_arc_idb[a]] = -map[a];
+ }
+ return *this;
+ }
+
+ /// \brief Set the supply values of the nodes.
+ ///
+ /// This function sets the supply values of the nodes.
+ /// If neither this function nor \ref stSupply() is used before
+ /// calling \ref run(), the supply of each node will be set to zero.
+ ///
+ /// \param map A node map storing the supply values.
+ /// Its \c Value type must be convertible to the \c Value type
+ /// of the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ template<typename SupplyMap>
+ CapacityScaling& supplyMap(const SupplyMap& map) {
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ _supply[_node_id[n]] = map[n];
+ }
+ return *this;
+ }
+
+ /// \brief Set single source and target nodes and a supply value.
+ ///
+ /// This function sets a single source node and a single target node
+ /// and the required flow value.
+ /// If neither this function nor \ref supplyMap() is used before
+ /// calling \ref run(), the supply of each node will be set to zero.
+ ///
+ /// Using this function has the same effect as using \ref supplyMap()
+ /// with a map in which \c k is assigned to \c s, \c -k is
+ /// assigned to \c t and all other nodes have zero supply value.
+ ///
+ /// \param s The source node.
+ /// \param t The target node.
+ /// \param k The required amount of flow from node \c s to node \c t
+ /// (i.e. the supply of \c s and the demand of \c t).
+ ///
+ /// \return <tt>(*this)</tt>
+ CapacityScaling& stSupply(const Node& s, const Node& t, Value k) {
+ for (int i = 0; i != _node_num; ++i) {
+ _supply[i] = 0;
+ }
+ _supply[_node_id[s]] = k;
+ _supply[_node_id[t]] = -k;
+ return *this;
+ }
+
+ /// @}
+
+ /// \name Execution control
+ /// The algorithm can be executed using \ref run().
+
+ /// @{
+
+ /// \brief Run the algorithm.
+ ///
+ /// This function runs the algorithm.
+ /// The paramters can be specified using functions \ref lowerMap(),
+ /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply().
+ /// For example,
+ /// \code
+ /// CapacityScaling<ListDigraph> cs(graph);
+ /// cs.lowerMap(lower).upperMap(upper).costMap(cost)
+ /// .supplyMap(sup).run();
+ /// \endcode
+ ///
+ /// This function can be called more than once. All the given parameters
+ /// are kept for the next call, unless \ref resetParams() or \ref reset()
+ /// is used, thus only the modified parameters have to be set again.
+ /// If the underlying digraph was also modified after the construction
+ /// of the class (or the last \ref reset() call), then the \ref reset()
+ /// function must be called.
+ ///
+ /// \param factor The capacity scaling factor. It must be larger than
+ /// one to use scaling. If it is less or equal to one, then scaling
+ /// will be disabled.
+ ///
+ /// \return \c INFEASIBLE if no feasible flow exists,
+ /// \n \c OPTIMAL if the problem has optimal solution
+ /// (i.e. it is feasible and bounded), and the algorithm has found
+ /// optimal flow and node potentials (primal and dual solutions),
+ /// \n \c UNBOUNDED if the digraph contains an arc of negative cost
+ /// and infinite upper bound. It means that the objective function
+ /// is unbounded on that arc, however, note that it could actually be
+ /// bounded over the feasible flows, but this algroithm cannot handle
+ /// these cases.
+ ///
+ /// \see ProblemType
+ /// \see resetParams(), reset()
+ ProblemType run(int factor = 4) {
+ _factor = factor;
+ ProblemType pt = init();
+ if (pt != OPTIMAL) return pt;
+ return start();
+ }
+
+ /// \brief Reset all the parameters that have been given before.
+ ///
+ /// This function resets all the paramaters that have been given
+ /// before using functions \ref lowerMap(), \ref upperMap(),
+ /// \ref costMap(), \ref supplyMap(), \ref stSupply().
+ ///
+ /// It is useful for multiple \ref run() calls. Basically, all the given
+ /// parameters are kept for the next \ref run() call, unless
+ /// \ref resetParams() or \ref reset() is used.
+ /// If the underlying digraph was also modified after the construction
+ /// of the class or the last \ref reset() call, then the \ref reset()
+ /// function must be used, otherwise \ref resetParams() is sufficient.
+ ///
+ /// For example,
+ /// \code
+ /// CapacityScaling<ListDigraph> cs(graph);
+ ///
+ /// // First run
+ /// cs.lowerMap(lower).upperMap(upper).costMap(cost)
+ /// .supplyMap(sup).run();
+ ///
+ /// // Run again with modified cost map (resetParams() is not called,
+ /// // so only the cost map have to be set again)
+ /// cost[e] += 100;
+ /// cs.costMap(cost).run();
+ ///
+ /// // Run again from scratch using resetParams()
+ /// // (the lower bounds will be set to zero on all arcs)
+ /// cs.resetParams();
+ /// cs.upperMap(capacity).costMap(cost)
+ /// .supplyMap(sup).run();
+ /// \endcode
+ ///
+ /// \return <tt>(*this)</tt>
+ ///
+ /// \see reset(), run()
+ CapacityScaling& resetParams() {
+ for (int i = 0; i != _node_num; ++i) {
+ _supply[i] = 0;
+ }
+ for (int j = 0; j != _res_arc_num; ++j) {
+ _lower[j] = 0;
+ _upper[j] = INF;
+ _cost[j] = _forward[j] ? 1 : -1;
+ }
+ _has_lower = false;
+ return *this;
+ }
+
+ /// \brief Reset the internal data structures and all the parameters
+ /// that have been given before.
+ ///
+ /// This function resets the internal data structures and all the
+ /// paramaters that have been given before using functions \ref lowerMap(),
+ /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply().
+ ///
+ /// It is useful for multiple \ref run() calls. Basically, all the given
+ /// parameters are kept for the next \ref run() call, unless
+ /// \ref resetParams() or \ref reset() is used.
+ /// If the underlying digraph was also modified after the construction
+ /// of the class or the last \ref reset() call, then the \ref reset()
+ /// function must be used, otherwise \ref resetParams() is sufficient.
+ ///
+ /// See \ref resetParams() for examples.
+ ///
+ /// \return <tt>(*this)</tt>
+ ///
+ /// \see resetParams(), run()
+ CapacityScaling& reset() {
+ // Resize vectors
+ _node_num = countNodes(_graph);
+ _arc_num = countArcs(_graph);
+ _res_arc_num = 2 * (_arc_num + _node_num);
+ _root = _node_num;
+ ++_node_num;
+
+ _first_out.resize(_node_num + 1);
+ _forward.resize(_res_arc_num);
+ _source.resize(_res_arc_num);
+ _target.resize(_res_arc_num);
+ _reverse.resize(_res_arc_num);
+
+ _lower.resize(_res_arc_num);
+ _upper.resize(_res_arc_num);
+ _cost.resize(_res_arc_num);
+ _supply.resize(_node_num);
+
+ _res_cap.resize(_res_arc_num);
+ _pi.resize(_node_num);
+ _excess.resize(_node_num);
+ _pred.resize(_node_num);
+
+ // Copy the graph
+ int i = 0, j = 0, k = 2 * _arc_num + _node_num - 1;
+ for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
+ _node_id[n] = i;
+ }
+ i = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
+ _first_out[i] = j;
+ for (OutArcIt a(_graph, n); a != INVALID; ++a, ++j) {
+ _arc_idf[a] = j;
+ _forward[j] = true;
+ _source[j] = i;
+ _target[j] = _node_id[_graph.runningNode(a)];
+ }
+ for (InArcIt a(_graph, n); a != INVALID; ++a, ++j) {
+ _arc_idb[a] = j;
+ _forward[j] = false;
+ _source[j] = i;
+ _target[j] = _node_id[_graph.runningNode(a)];
+ }
+ _forward[j] = false;
+ _source[j] = i;
+ _target[j] = _root;
+ _reverse[j] = k;
+ _forward[k] = true;
+ _source[k] = _root;
+ _target[k] = i;
+ _reverse[k] = j;
+ ++j; ++k;
+ }
+ _first_out[i] = j;
+ _first_out[_node_num] = k;
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ int fi = _arc_idf[a];
+ int bi = _arc_idb[a];
+ _reverse[fi] = bi;
+ _reverse[bi] = fi;
+ }
+
+ // Reset parameters
+ resetParams();
+ return *this;
+ }
+
+ /// @}
+
+ /// \name Query Functions
+ /// The results of the algorithm can be obtained using these
+ /// functions.\n
+ /// The \ref run() function must be called before using them.
+
+ /// @{
+
+ /// \brief Return the total cost of the found flow.
+ ///
+ /// This function returns the total cost of the found flow.
+ /// Its complexity is O(m).
+ ///
+ /// \note The return type of the function can be specified as a
+ /// template parameter. For example,
+ /// \code
+ /// cs.totalCost<double>();
+ /// \endcode
+ /// It is useful if the total cost cannot be stored in the \c Cost
+ /// type of the algorithm, which is the default return type of the
+ /// function.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ template <typename Number>
+ Number totalCost() const {
+ Number c = 0;
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ int i = _arc_idb[a];
+ c += static_cast<Number>(_res_cap[i]) *
+ (-static_cast<Number>(_cost[i]));
+ }
+ return c;
+ }
+
+#ifndef DOXYGEN
+ Cost totalCost() const {
+ return totalCost<Cost>();
+ }
+#endif
+
+ /// \brief Return the flow on the given arc.
+ ///
+ /// This function returns the flow on the given arc.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ Value flow(const Arc& a) const {
+ return _res_cap[_arc_idb[a]];
+ }
+
+ /// \brief Copy the flow values (the primal solution) into the
+ /// given map.
+ ///
+ /// This function copies the flow value on each arc into the given
+ /// map. The \c Value type of the algorithm must be convertible to
+ /// the \c Value type of the map.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ template <typename FlowMap>
+ void flowMap(FlowMap &map) const {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ map.set(a, _res_cap[_arc_idb[a]]);
+ }
+ }
+
+ /// \brief Return the potential (dual value) of the given node.
+ ///
+ /// This function returns the potential (dual value) of the
+ /// given node.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ Cost potential(const Node& n) const {
+ return _pi[_node_id[n]];
+ }
+
+ /// \brief Copy the potential values (the dual solution) into the
+ /// given map.
+ ///
+ /// This function copies the potential (dual value) of each node
+ /// into the given map.
+ /// The \c Cost type of the algorithm must be convertible to the
+ /// \c Value type of the map.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ template <typename PotentialMap>
+ void potentialMap(PotentialMap &map) const {
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ map.set(n, _pi[_node_id[n]]);
+ }
+ }
+
+ /// @}
+
+ private:
+
+ // Initialize the algorithm
+ ProblemType init() {
+ if (_node_num <= 1) return INFEASIBLE;
+
+ // Check the sum of supply values
+ _sum_supply = 0;
+ for (int i = 0; i != _root; ++i) {
+ _sum_supply += _supply[i];
+ }
+ if (_sum_supply > 0) return INFEASIBLE;
+
+ // Check lower and upper bounds
+ LEMON_DEBUG(checkBoundMaps(),
+ "Upper bounds must be greater or equal to the lower bounds");
+
+
+ // Initialize vectors
+ for (int i = 0; i != _root; ++i) {
+ _pi[i] = 0;
+ _excess[i] = _supply[i];
+ }
+
+ // Remove non-zero lower bounds
+ const Value MAX = std::numeric_limits<Value>::max();
+ int last_out;
+ if (_has_lower) {
+ for (int i = 0; i != _root; ++i) {
+ last_out = _first_out[i+1];
+ for (int j = _first_out[i]; j != last_out; ++j) {
+ if (_forward[j]) {
+ Value c = _lower[j];
+ if (c >= 0) {
+ _res_cap[j] = _upper[j] < MAX ? _upper[j] - c : INF;
+ } else {
+ _res_cap[j] = _upper[j] < MAX + c ? _upper[j] - c : INF;
+ }
+ _excess[i] -= c;
+ _excess[_target[j]] += c;
+ } else {
+ _res_cap[j] = 0;
+ }
+ }
+ }
+ } else {
+ for (int j = 0; j != _res_arc_num; ++j) {
+ _res_cap[j] = _forward[j] ? _upper[j] : 0;
+ }
+ }
+
+ // Handle negative costs
+ for (int i = 0; i != _root; ++i) {
+ last_out = _first_out[i+1] - 1;
+ for (int j = _first_out[i]; j != last_out; ++j) {
+ Value rc = _res_cap[j];
+ if (_cost[j] < 0 && rc > 0) {
+ if (rc >= MAX) return UNBOUNDED;
+ _excess[i] -= rc;
+ _excess[_target[j]] += rc;
+ _res_cap[j] = 0;
+ _res_cap[_reverse[j]] += rc;
+ }
+ }
+ }
+
+ // Handle GEQ supply type
+ if (_sum_supply < 0) {
+ _pi[_root] = 0;
+ _excess[_root] = -_sum_supply;
+ for (int a = _first_out[_root]; a != _res_arc_num; ++a) {
+ int ra = _reverse[a];
+ _res_cap[a] = -_sum_supply + 1;
+ _res_cap[ra] = 0;
+ _cost[a] = 0;
+ _cost[ra] = 0;
+ }
+ } else {
+ _pi[_root] = 0;
+ _excess[_root] = 0;
+ for (int a = _first_out[_root]; a != _res_arc_num; ++a) {
+ int ra = _reverse[a];
+ _res_cap[a] = 1;
+ _res_cap[ra] = 0;
+ _cost[a] = 0;
+ _cost[ra] = 0;
+ }
+ }
+
+ // Initialize delta value
+ if (_factor > 1) {
+ // With scaling
+ Value max_sup = 0, max_dem = 0, max_cap = 0;
+ for (int i = 0; i != _root; ++i) {
+ Value ex = _excess[i];
+ if ( ex > max_sup) max_sup = ex;
+ if (-ex > max_dem) max_dem = -ex;
+ int last_out = _first_out[i+1] - 1;
+ for (int j = _first_out[i]; j != last_out; ++j) {
+ if (_res_cap[j] > max_cap) max_cap = _res_cap[j];
+ }
+ }
+ max_sup = std::min(std::min(max_sup, max_dem), max_cap);
+ for (_delta = 1; 2 * _delta <= max_sup; _delta *= 2) ;
+ } else {
+ // Without scaling
+ _delta = 1;
+ }
+
+ return OPTIMAL;
+ }
+
+ // Check if the upper bound is greater than or equal to the lower bound
+ // on each forward arc.
+ bool checkBoundMaps() {
+ for (int j = 0; j != _res_arc_num; ++j) {
+ if (_forward[j] && _upper[j] < _lower[j]) return false;
+ }
+ return true;
+ }
+
+ ProblemType start() {
+ // Execute the algorithm
+ ProblemType pt;
+ if (_delta > 1)
+ pt = startWithScaling();
+ else
+ pt = startWithoutScaling();
+
+ // Handle non-zero lower bounds
+ if (_has_lower) {
+ int limit = _first_out[_root];
+ for (int j = 0; j != limit; ++j) {
+ if (_forward[j]) _res_cap[_reverse[j]] += _lower[j];
+ }
+ }
+
+ // Shift potentials if necessary
+ Cost pr = _pi[_root];
+ if (_sum_supply < 0 || pr > 0) {
+ for (int i = 0; i != _node_num; ++i) {
+ _pi[i] -= pr;
+ }
+ }
+
+ return pt;
+ }
+
+ // Execute the capacity scaling algorithm
+ ProblemType startWithScaling() {
+ // Perform capacity scaling phases
+ int s, t;
+ ResidualDijkstra _dijkstra(*this);
+ while (true) {
+ // Saturate all arcs not satisfying the optimality condition
+ int last_out;
+ for (int u = 0; u != _node_num; ++u) {
+ last_out = _sum_supply < 0 ?
+ _first_out[u+1] : _first_out[u+1] - 1;
+ for (int a = _first_out[u]; a != last_out; ++a) {
+ int v = _target[a];
+ Cost c = _cost[a] + _pi[u] - _pi[v];
+ Value rc = _res_cap[a];
+ if (c < 0 && rc >= _delta) {
+ _excess[u] -= rc;
+ _excess[v] += rc;
+ _res_cap[a] = 0;
+ _res_cap[_reverse[a]] += rc;
+ }
+ }
+ }
+
+ // Find excess nodes and deficit nodes
+ _excess_nodes.clear();
+ _deficit_nodes.clear();
+ for (int u = 0; u != _node_num; ++u) {
+ Value ex = _excess[u];
+ if (ex >= _delta) _excess_nodes.push_back(u);
+ if (ex <= -_delta) _deficit_nodes.push_back(u);
+ }
+ int next_node = 0, next_def_node = 0;
+
+ // Find augmenting shortest paths
+ while (next_node < int(_excess_nodes.size())) {
+ // Check deficit nodes
+ if (_delta > 1) {
+ bool delta_deficit = false;
+ for ( ; next_def_node < int(_deficit_nodes.size());
+ ++next_def_node ) {
+ if (_excess[_deficit_nodes[next_def_node]] <= -_delta) {
+ delta_deficit = true;
+ break;
+ }
+ }
+ if (!delta_deficit) break;
+ }
+
+ // Run Dijkstra in the residual network
+ s = _excess_nodes[next_node];
+ if ((t = _dijkstra.run(s, _delta)) == -1) {
+ if (_delta > 1) {
+ ++next_node;
+ continue;
+ }
+ return INFEASIBLE;
+ }
+
+ // Augment along a shortest path from s to t
+ Value d = std::min(_excess[s], -_excess[t]);
+ int u = t;
+ int a;
+ if (d > _delta) {
+ while ((a = _pred[u]) != -1) {
+ if (_res_cap[a] < d) d = _res_cap[a];
+ u = _source[a];
+ }
+ }
+ u = t;
+ while ((a = _pred[u]) != -1) {
+ _res_cap[a] -= d;
+ _res_cap[_reverse[a]] += d;
+ u = _source[a];
+ }
+ _excess[s] -= d;
+ _excess[t] += d;
+
+ if (_excess[s] < _delta) ++next_node;
+ }
+
+ if (_delta == 1) break;
+ _delta = _delta <= _factor ? 1 : _delta / _factor;
+ }
+
+ return OPTIMAL;
+ }
+
+ // Execute the successive shortest path algorithm
+ ProblemType startWithoutScaling() {
+ // Find excess nodes
+ _excess_nodes.clear();
+ for (int i = 0; i != _node_num; ++i) {
+ if (_excess[i] > 0) _excess_nodes.push_back(i);
+ }
+ if (_excess_nodes.size() == 0) return OPTIMAL;
+ int next_node = 0;
+
+ // Find shortest paths
+ int s, t;
+ ResidualDijkstra _dijkstra(*this);
+ while ( _excess[_excess_nodes[next_node]] > 0 ||
+ ++next_node < int(_excess_nodes.size()) )
+ {
+ // Run Dijkstra in the residual network
+ s = _excess_nodes[next_node];
+ if ((t = _dijkstra.run(s)) == -1) return INFEASIBLE;
+
+ // Augment along a shortest path from s to t
+ Value d = std::min(_excess[s], -_excess[t]);
+ int u = t;
+ int a;
+ if (d > 1) {
+ while ((a = _pred[u]) != -1) {
+ if (_res_cap[a] < d) d = _res_cap[a];
+ u = _source[a];
+ }
+ }
+ u = t;
+ while ((a = _pred[u]) != -1) {
+ _res_cap[a] -= d;
+ _res_cap[_reverse[a]] += d;
+ u = _source[a];
+ }
+ _excess[s] -= d;
+ _excess[t] += d;
+ }
+
+ return OPTIMAL;
+ }
+
+ }; //class CapacityScaling
+
+ ///@}
+
+} //namespace lemon
+
+#endif //LEMON_CAPACITY_SCALING_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/cbc.cc b/extern/quadriflow/3rd/lemon-1.3.1/lemon/cbc.cc
new file mode 100644
index 00000000000..62331b1e2e1
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/cbc.cc
@@ -0,0 +1,460 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\file
+///\brief Implementation of the CBC MIP solver interface.
+
+#include "cbc.h"
+
+#include <coin/CoinModel.hpp>
+#include <coin/CbcModel.hpp>
+#include <coin/OsiSolverInterface.hpp>
+
+#include "coin/OsiClpSolverInterface.hpp"
+
+#include "coin/CbcCutGenerator.hpp"
+#include "coin/CbcHeuristicLocal.hpp"
+#include "coin/CbcHeuristicGreedy.hpp"
+#include "coin/CbcHeuristicFPump.hpp"
+#include "coin/CbcHeuristicRINS.hpp"
+
+#include "coin/CglGomory.hpp"
+#include "coin/CglProbing.hpp"
+#include "coin/CglKnapsackCover.hpp"
+#include "coin/CglOddHole.hpp"
+#include "coin/CglClique.hpp"
+#include "coin/CglFlowCover.hpp"
+#include "coin/CglMixedIntegerRounding.hpp"
+
+#include "coin/CbcHeuristic.hpp"
+
+namespace lemon {
+
+ CbcMip::CbcMip() {
+ _prob = new CoinModel();
+ _prob->setProblemName("LEMON");
+ _osi_solver = 0;
+ _cbc_model = 0;
+ messageLevel(MESSAGE_NOTHING);
+ }
+
+ CbcMip::CbcMip(const CbcMip& other) {
+ _prob = new CoinModel(*other._prob);
+ _prob->setProblemName("LEMON");
+ _osi_solver = 0;
+ _cbc_model = 0;
+ messageLevel(MESSAGE_NOTHING);
+ }
+
+ CbcMip::~CbcMip() {
+ delete _prob;
+ if (_osi_solver) delete _osi_solver;
+ if (_cbc_model) delete _cbc_model;
+ }
+
+ const char* CbcMip::_solverName() const { return "CbcMip"; }
+
+ int CbcMip::_addCol() {
+ _prob->addColumn(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX, 0.0, 0, false);
+ return _prob->numberColumns() - 1;
+ }
+
+ CbcMip* CbcMip::newSolver() const {
+ CbcMip* newlp = new CbcMip;
+ return newlp;
+ }
+
+ CbcMip* CbcMip::cloneSolver() const {
+ CbcMip* copylp = new CbcMip(*this);
+ return copylp;
+ }
+
+ int CbcMip::_addRow() {
+ _prob->addRow(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX);
+ return _prob->numberRows() - 1;
+ }
+
+ int CbcMip::_addRow(Value l, ExprIterator b, ExprIterator e, Value u) {
+ std::vector<int> indexes;
+ std::vector<Value> values;
+
+ for(ExprIterator it = b; it != e; ++it) {
+ indexes.push_back(it->first);
+ values.push_back(it->second);
+ }
+
+ _prob->addRow(values.size(), &indexes.front(), &values.front(), l, u);
+ return _prob->numberRows() - 1;
+ }
+
+ void CbcMip::_eraseCol(int i) {
+ _prob->deleteColumn(i);
+ }
+
+ void CbcMip::_eraseRow(int i) {
+ _prob->deleteRow(i);
+ }
+
+ void CbcMip::_eraseColId(int i) {
+ cols.eraseIndex(i);
+ }
+
+ void CbcMip::_eraseRowId(int i) {
+ rows.eraseIndex(i);
+ }
+
+ void CbcMip::_getColName(int c, std::string& name) const {
+ name = _prob->getColumnName(c);
+ }
+
+ void CbcMip::_setColName(int c, const std::string& name) {
+ _prob->setColumnName(c, name.c_str());
+ }
+
+ int CbcMip::_colByName(const std::string& name) const {
+ return _prob->column(name.c_str());
+ }
+
+ void CbcMip::_getRowName(int r, std::string& name) const {
+ name = _prob->getRowName(r);
+ }
+
+ void CbcMip::_setRowName(int r, const std::string& name) {
+ _prob->setRowName(r, name.c_str());
+ }
+
+ int CbcMip::_rowByName(const std::string& name) const {
+ return _prob->row(name.c_str());
+ }
+
+ void CbcMip::_setRowCoeffs(int i, ExprIterator b, ExprIterator e) {
+ for (ExprIterator it = b; it != e; ++it) {
+ _prob->setElement(i, it->first, it->second);
+ }
+ }
+
+ void CbcMip::_getRowCoeffs(int ix, InsertIterator b) const {
+ int length = _prob->numberRows();
+
+ std::vector<int> indices(length);
+ std::vector<Value> values(length);
+
+ length = _prob->getRow(ix, &indices[0], &values[0]);
+
+ for (int i = 0; i < length; ++i) {
+ *b = std::make_pair(indices[i], values[i]);
+ ++b;
+ }
+ }
+
+ void CbcMip::_setColCoeffs(int ix, ExprIterator b, ExprIterator e) {
+ for (ExprIterator it = b; it != e; ++it) {
+ _prob->setElement(it->first, ix, it->second);
+ }
+ }
+
+ void CbcMip::_getColCoeffs(int ix, InsertIterator b) const {
+ int length = _prob->numberColumns();
+
+ std::vector<int> indices(length);
+ std::vector<Value> values(length);
+
+ length = _prob->getColumn(ix, &indices[0], &values[0]);
+
+ for (int i = 0; i < length; ++i) {
+ *b = std::make_pair(indices[i], values[i]);
+ ++b;
+ }
+ }
+
+ void CbcMip::_setCoeff(int ix, int jx, Value value) {
+ _prob->setElement(ix, jx, value);
+ }
+
+ CbcMip::Value CbcMip::_getCoeff(int ix, int jx) const {
+ return _prob->getElement(ix, jx);
+ }
+
+
+ void CbcMip::_setColLowerBound(int i, Value lo) {
+ LEMON_ASSERT(lo != INF, "Invalid bound");
+ _prob->setColumnLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
+ }
+
+ CbcMip::Value CbcMip::_getColLowerBound(int i) const {
+ double val = _prob->getColumnLower(i);
+ return val == - COIN_DBL_MAX ? - INF : val;
+ }
+
+ void CbcMip::_setColUpperBound(int i, Value up) {
+ LEMON_ASSERT(up != -INF, "Invalid bound");
+ _prob->setColumnUpper(i, up == INF ? COIN_DBL_MAX : up);
+ }
+
+ CbcMip::Value CbcMip::_getColUpperBound(int i) const {
+ double val = _prob->getColumnUpper(i);
+ return val == COIN_DBL_MAX ? INF : val;
+ }
+
+ void CbcMip::_setRowLowerBound(int i, Value lo) {
+ LEMON_ASSERT(lo != INF, "Invalid bound");
+ _prob->setRowLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
+ }
+
+ CbcMip::Value CbcMip::_getRowLowerBound(int i) const {
+ double val = _prob->getRowLower(i);
+ return val == - COIN_DBL_MAX ? - INF : val;
+ }
+
+ void CbcMip::_setRowUpperBound(int i, Value up) {
+ LEMON_ASSERT(up != -INF, "Invalid bound");
+ _prob->setRowUpper(i, up == INF ? COIN_DBL_MAX : up);
+ }
+
+ CbcMip::Value CbcMip::_getRowUpperBound(int i) const {
+ double val = _prob->getRowUpper(i);
+ return val == COIN_DBL_MAX ? INF : val;
+ }
+
+ void CbcMip::_setObjCoeffs(ExprIterator b, ExprIterator e) {
+ int num = _prob->numberColumns();
+ for (int i = 0; i < num; ++i) {
+ _prob->setColumnObjective(i, 0.0);
+ }
+ for (ExprIterator it = b; it != e; ++it) {
+ _prob->setColumnObjective(it->first, it->second);
+ }
+ }
+
+ void CbcMip::_getObjCoeffs(InsertIterator b) const {
+ int num = _prob->numberColumns();
+ for (int i = 0; i < num; ++i) {
+ Value coef = _prob->getColumnObjective(i);
+ if (coef != 0.0) {
+ *b = std::make_pair(i, coef);
+ ++b;
+ }
+ }
+ }
+
+ void CbcMip::_setObjCoeff(int i, Value obj_coef) {
+ _prob->setColumnObjective(i, obj_coef);
+ }
+
+ CbcMip::Value CbcMip::_getObjCoeff(int i) const {
+ return _prob->getColumnObjective(i);
+ }
+
+ CbcMip::SolveExitStatus CbcMip::_solve() {
+
+ if (_osi_solver) {
+ delete _osi_solver;
+ }
+ _osi_solver = new OsiClpSolverInterface();
+
+ _osi_solver->loadFromCoinModel(*_prob);
+
+ if (_cbc_model) {
+ delete _cbc_model;
+ }
+ _cbc_model= new CbcModel(*_osi_solver);
+
+ _osi_solver->messageHandler()->setLogLevel(_message_level);
+ _cbc_model->setLogLevel(_message_level);
+
+ _cbc_model->initialSolve();
+ _cbc_model->solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry);
+
+ if (!_cbc_model->isInitialSolveAbandoned() &&
+ _cbc_model->isInitialSolveProvenOptimal() &&
+ !_cbc_model->isInitialSolveProvenPrimalInfeasible() &&
+ !_cbc_model->isInitialSolveProvenDualInfeasible()) {
+
+ CglProbing generator1;
+ generator1.setUsingObjective(true);
+ generator1.setMaxPass(3);
+ generator1.setMaxProbe(100);
+ generator1.setMaxLook(50);
+ generator1.setRowCuts(3);
+ _cbc_model->addCutGenerator(&generator1, -1, "Probing");
+
+ CglGomory generator2;
+ generator2.setLimit(300);
+ _cbc_model->addCutGenerator(&generator2, -1, "Gomory");
+
+ CglKnapsackCover generator3;
+ _cbc_model->addCutGenerator(&generator3, -1, "Knapsack");
+
+ CglOddHole generator4;
+ generator4.setMinimumViolation(0.005);
+ generator4.setMinimumViolationPer(0.00002);
+ generator4.setMaximumEntries(200);
+ _cbc_model->addCutGenerator(&generator4, -1, "OddHole");
+
+ CglClique generator5;
+ generator5.setStarCliqueReport(false);
+ generator5.setRowCliqueReport(false);
+ _cbc_model->addCutGenerator(&generator5, -1, "Clique");
+
+ CglMixedIntegerRounding mixedGen;
+ _cbc_model->addCutGenerator(&mixedGen, -1, "MixedIntegerRounding");
+
+ CglFlowCover flowGen;
+ _cbc_model->addCutGenerator(&flowGen, -1, "FlowCover");
+
+ OsiClpSolverInterface* osiclp =
+ dynamic_cast<OsiClpSolverInterface*>(_cbc_model->solver());
+ if (osiclp->getNumRows() < 300 && osiclp->getNumCols() < 500) {
+ osiclp->setupForRepeatedUse(2, 0);
+ }
+
+ CbcRounding heuristic1(*_cbc_model);
+ heuristic1.setWhen(3);
+ _cbc_model->addHeuristic(&heuristic1);
+
+ CbcHeuristicLocal heuristic2(*_cbc_model);
+ heuristic2.setWhen(3);
+ _cbc_model->addHeuristic(&heuristic2);
+
+ CbcHeuristicGreedyCover heuristic3(*_cbc_model);
+ heuristic3.setAlgorithm(11);
+ heuristic3.setWhen(3);
+ _cbc_model->addHeuristic(&heuristic3);
+
+ CbcHeuristicFPump heuristic4(*_cbc_model);
+ heuristic4.setWhen(3);
+ _cbc_model->addHeuristic(&heuristic4);
+
+ CbcHeuristicRINS heuristic5(*_cbc_model);
+ heuristic5.setWhen(3);
+ _cbc_model->addHeuristic(&heuristic5);
+
+ if (_cbc_model->getNumCols() < 500) {
+ _cbc_model->setMaximumCutPassesAtRoot(-100);
+ } else if (_cbc_model->getNumCols() < 5000) {
+ _cbc_model->setMaximumCutPassesAtRoot(100);
+ } else {
+ _cbc_model->setMaximumCutPassesAtRoot(20);
+ }
+
+ if (_cbc_model->getNumCols() < 5000) {
+ _cbc_model->setNumberStrong(10);
+ }
+
+ _cbc_model->solver()->setIntParam(OsiMaxNumIterationHotStart, 100);
+ _cbc_model->branchAndBound();
+ }
+
+ if (_cbc_model->isAbandoned()) {
+ return UNSOLVED;
+ } else {
+ return SOLVED;
+ }
+ }
+
+ CbcMip::Value CbcMip::_getSol(int i) const {
+ return _cbc_model->getColSolution()[i];
+ }
+
+ CbcMip::Value CbcMip::_getSolValue() const {
+ return _cbc_model->getObjValue();
+ }
+
+ CbcMip::ProblemType CbcMip::_getType() const {
+ if (_cbc_model->isProvenOptimal()) {
+ return OPTIMAL;
+ } else if (_cbc_model->isContinuousUnbounded()) {
+ return UNBOUNDED;
+ }
+ return FEASIBLE;
+ }
+
+ void CbcMip::_setSense(Sense sense) {
+ switch (sense) {
+ case MIN:
+ _prob->setOptimizationDirection(1.0);
+ break;
+ case MAX:
+ _prob->setOptimizationDirection(- 1.0);
+ break;
+ }
+ }
+
+ CbcMip::Sense CbcMip::_getSense() const {
+ if (_prob->optimizationDirection() > 0.0) {
+ return MIN;
+ } else if (_prob->optimizationDirection() < 0.0) {
+ return MAX;
+ } else {
+ LEMON_ASSERT(false, "Wrong sense");
+ return CbcMip::Sense();
+ }
+ }
+
+ void CbcMip::_setColType(int i, CbcMip::ColTypes col_type) {
+ switch (col_type){
+ case INTEGER:
+ _prob->setInteger(i);
+ break;
+ case REAL:
+ _prob->setContinuous(i);
+ break;
+ default:;
+ LEMON_ASSERT(false, "Wrong sense");
+ }
+ }
+
+ CbcMip::ColTypes CbcMip::_getColType(int i) const {
+ return _prob->getColumnIsInteger(i) ? INTEGER : REAL;
+ }
+
+ void CbcMip::_clear() {
+ delete _prob;
+ if (_osi_solver) {
+ delete _osi_solver;
+ _osi_solver = 0;
+ }
+ if (_cbc_model) {
+ delete _cbc_model;
+ _cbc_model = 0;
+ }
+
+ _prob = new CoinModel();
+ }
+
+ void CbcMip::_messageLevel(MessageLevel level) {
+ switch (level) {
+ case MESSAGE_NOTHING:
+ _message_level = 0;
+ break;
+ case MESSAGE_ERROR:
+ _message_level = 1;
+ break;
+ case MESSAGE_WARNING:
+ _message_level = 1;
+ break;
+ case MESSAGE_NORMAL:
+ _message_level = 2;
+ break;
+ case MESSAGE_VERBOSE:
+ _message_level = 3;
+ break;
+ }
+ }
+
+} //END OF NAMESPACE LEMON
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/cbc.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/cbc.h
new file mode 100644
index 00000000000..968e504ac35
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/cbc.h
@@ -0,0 +1,129 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_CBC_H
+#define LEMON_CBC_H
+
+///\file
+///\brief Header of the LEMON-CBC mip solver interface.
+///\ingroup lp_group
+
+#include <lemon/lp_base.h>
+
+class CoinModel;
+class OsiSolverInterface;
+class CbcModel;
+
+namespace lemon {
+
+ /// \brief Interface for the CBC MIP solver
+ ///
+ /// This class implements an interface for the CBC MIP solver.
+ ///\ingroup lp_group
+ class CbcMip : public MipSolver {
+ protected:
+
+ CoinModel *_prob;
+ OsiSolverInterface *_osi_solver;
+ CbcModel *_cbc_model;
+
+ public:
+
+ /// \e
+ CbcMip();
+ /// \e
+ CbcMip(const CbcMip&);
+ /// \e
+ ~CbcMip();
+ /// \e
+ virtual CbcMip* newSolver() const;
+ /// \e
+ virtual CbcMip* cloneSolver() const;
+
+ protected:
+
+ virtual const char* _solverName() const;
+
+ virtual int _addCol();
+ virtual int _addRow();
+ virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
+
+ virtual void _eraseCol(int i);
+ virtual void _eraseRow(int i);
+
+ virtual void _eraseColId(int i);
+ virtual void _eraseRowId(int i);
+
+ virtual void _getColName(int col, std::string& name) const;
+ virtual void _setColName(int col, const std::string& name);
+ virtual int _colByName(const std::string& name) const;
+
+ virtual void _getRowName(int row, std::string& name) const;
+ virtual void _setRowName(int row, const std::string& name);
+ virtual int _rowByName(const std::string& name) const;
+
+ virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
+ virtual void _getRowCoeffs(int i, InsertIterator b) const;
+
+ virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
+ virtual void _getColCoeffs(int i, InsertIterator b) const;
+
+ virtual void _setCoeff(int row, int col, Value value);
+ virtual Value _getCoeff(int row, int col) const;
+
+ virtual void _setColLowerBound(int i, Value value);
+ virtual Value _getColLowerBound(int i) const;
+ virtual void _setColUpperBound(int i, Value value);
+ virtual Value _getColUpperBound(int i) const;
+
+ virtual void _setRowLowerBound(int i, Value value);
+ virtual Value _getRowLowerBound(int i) const;
+ virtual void _setRowUpperBound(int i, Value value);
+ virtual Value _getRowUpperBound(int i) const;
+
+ virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
+ virtual void _getObjCoeffs(InsertIterator b) const;
+
+ virtual void _setObjCoeff(int i, Value obj_coef);
+ virtual Value _getObjCoeff(int i) const;
+
+ virtual void _setSense(Sense sense);
+ virtual Sense _getSense() const;
+
+ virtual ColTypes _getColType(int col) const;
+ virtual void _setColType(int col, ColTypes col_type);
+
+ virtual SolveExitStatus _solve();
+ virtual ProblemType _getType() const;
+ virtual Value _getSol(int i) const;
+ virtual Value _getSolValue() const;
+
+ virtual void _clear();
+
+ virtual void _messageLevel(MessageLevel level);
+ void _applyMessageLevel();
+
+ int _message_level;
+
+
+
+ };
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/christofides_tsp.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/christofides_tsp.h
new file mode 100644
index 00000000000..2997567a689
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/christofides_tsp.h
@@ -0,0 +1,254 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_CHRISTOFIDES_TSP_H
+#define LEMON_CHRISTOFIDES_TSP_H
+
+/// \ingroup tsp
+/// \file
+/// \brief Christofides algorithm for symmetric TSP
+
+#include <lemon/full_graph.h>
+#include <lemon/smart_graph.h>
+#include <lemon/kruskal.h>
+#include <lemon/matching.h>
+#include <lemon/euler.h>
+
+namespace lemon {
+
+ /// \ingroup tsp
+ ///
+ /// \brief Christofides algorithm for symmetric TSP.
+ ///
+ /// ChristofidesTsp implements Christofides' heuristic for solving
+ /// symmetric \ref tsp "TSP".
+ ///
+ /// This a well-known approximation method for the TSP problem with
+ /// metric cost function.
+ /// It has a guaranteed approximation factor of 3/2 (i.e. it finds a tour
+ /// whose total cost is at most 3/2 of the optimum), but it usually
+ /// provides better solutions in practice.
+ /// This implementation runs in O(n<sup>3</sup>log(n)) time.
+ ///
+ /// The algorithm starts with a \ref spantree "minimum cost spanning tree" and
+ /// finds a \ref MaxWeightedPerfectMatching "minimum cost perfect matching"
+ /// in the subgraph induced by the nodes that have odd degree in the
+ /// spanning tree.
+ /// Finally, it constructs the tour from the \ref EulerIt "Euler traversal"
+ /// of the union of the spanning tree and the matching.
+ /// During this last step, the algorithm simply skips the visited nodes
+ /// (i.e. creates shortcuts) assuming that the triangle inequality holds
+ /// for the cost function.
+ ///
+ /// \tparam CM Type of the cost map.
+ ///
+ /// \warning CM::Value must be a signed number type.
+ template <typename CM>
+ class ChristofidesTsp
+ {
+ public:
+
+ /// Type of the cost map
+ typedef CM CostMap;
+ /// Type of the edge costs
+ typedef typename CM::Value Cost;
+
+ private:
+
+ GRAPH_TYPEDEFS(FullGraph);
+
+ const FullGraph &_gr;
+ const CostMap &_cost;
+ std::vector<Node> _path;
+ Cost _sum;
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ /// \param gr The \ref FullGraph "full graph" the algorithm runs on.
+ /// \param cost The cost map.
+ ChristofidesTsp(const FullGraph &gr, const CostMap &cost)
+ : _gr(gr), _cost(cost) {}
+
+ /// \name Execution Control
+ /// @{
+
+ /// \brief Runs the algorithm.
+ ///
+ /// This function runs the algorithm.
+ ///
+ /// \return The total cost of the found tour.
+ Cost run() {
+ _path.clear();
+
+ if (_gr.nodeNum() == 0) return _sum = 0;
+ else if (_gr.nodeNum() == 1) {
+ _path.push_back(_gr(0));
+ return _sum = 0;
+ }
+ else if (_gr.nodeNum() == 2) {
+ _path.push_back(_gr(0));
+ _path.push_back(_gr(1));
+ return _sum = 2 * _cost[_gr.edge(_gr(0), _gr(1))];
+ }
+
+ // Compute min. cost spanning tree
+ std::vector<Edge> tree;
+ kruskal(_gr, _cost, std::back_inserter(tree));
+
+ FullGraph::NodeMap<int> deg(_gr, 0);
+ for (int i = 0; i != int(tree.size()); ++i) {
+ Edge e = tree[i];
+ ++deg[_gr.u(e)];
+ ++deg[_gr.v(e)];
+ }
+
+ // Copy the induced subgraph of odd nodes
+ std::vector<Node> odd_nodes;
+ for (NodeIt u(_gr); u != INVALID; ++u) {
+ if (deg[u] % 2 == 1) odd_nodes.push_back(u);
+ }
+
+ SmartGraph sgr;
+ SmartGraph::EdgeMap<Cost> scost(sgr);
+ for (int i = 0; i != int(odd_nodes.size()); ++i) {
+ sgr.addNode();
+ }
+ for (int i = 0; i != int(odd_nodes.size()); ++i) {
+ for (int j = 0; j != int(odd_nodes.size()); ++j) {
+ if (j == i) continue;
+ SmartGraph::Edge e =
+ sgr.addEdge(sgr.nodeFromId(i), sgr.nodeFromId(j));
+ scost[e] = -_cost[_gr.edge(odd_nodes[i], odd_nodes[j])];
+ }
+ }
+
+ // Compute min. cost perfect matching
+ MaxWeightedPerfectMatching<SmartGraph, SmartGraph::EdgeMap<Cost> >
+ mwpm(sgr, scost);
+ mwpm.run();
+
+ for (SmartGraph::EdgeIt e(sgr); e != INVALID; ++e) {
+ if (mwpm.matching(e)) {
+ tree.push_back( _gr.edge(odd_nodes[sgr.id(sgr.u(e))],
+ odd_nodes[sgr.id(sgr.v(e))]) );
+ }
+ }
+
+ // Join the spanning tree and the matching
+ sgr.clear();
+ for (int i = 0; i != _gr.nodeNum(); ++i) {
+ sgr.addNode();
+ }
+ for (int i = 0; i != int(tree.size()); ++i) {
+ int ui = _gr.id(_gr.u(tree[i])),
+ vi = _gr.id(_gr.v(tree[i]));
+ sgr.addEdge(sgr.nodeFromId(ui), sgr.nodeFromId(vi));
+ }
+
+ // Compute the tour from the Euler traversal
+ SmartGraph::NodeMap<bool> visited(sgr, false);
+ for (EulerIt<SmartGraph> e(sgr); e != INVALID; ++e) {
+ SmartGraph::Node n = sgr.target(e);
+ if (!visited[n]) {
+ _path.push_back(_gr(sgr.id(n)));
+ visited[n] = true;
+ }
+ }
+
+ _sum = _cost[_gr.edge(_path.back(), _path.front())];
+ for (int i = 0; i < int(_path.size())-1; ++i) {
+ _sum += _cost[_gr.edge(_path[i], _path[i+1])];
+ }
+
+ return _sum;
+ }
+
+ /// @}
+
+ /// \name Query Functions
+ /// @{
+
+ /// \brief The total cost of the found tour.
+ ///
+ /// This function returns the total cost of the found tour.
+ ///
+ /// \pre run() must be called before using this function.
+ Cost tourCost() const {
+ return _sum;
+ }
+
+ /// \brief Returns a const reference to the node sequence of the
+ /// found tour.
+ ///
+ /// This function returns a const reference to a vector
+ /// that stores the node sequence of the found tour.
+ ///
+ /// \pre run() must be called before using this function.
+ const std::vector<Node>& tourNodes() const {
+ return _path;
+ }
+
+ /// \brief Gives back the node sequence of the found tour.
+ ///
+ /// This function copies the node sequence of the found tour into
+ /// an STL container through the given output iterator. The
+ /// <tt>value_type</tt> of the container must be <tt>FullGraph::Node</tt>.
+ /// For example,
+ /// \code
+ /// std::vector<FullGraph::Node> nodes(countNodes(graph));
+ /// tsp.tourNodes(nodes.begin());
+ /// \endcode
+ /// or
+ /// \code
+ /// std::list<FullGraph::Node> nodes;
+ /// tsp.tourNodes(std::back_inserter(nodes));
+ /// \endcode
+ ///
+ /// \pre run() must be called before using this function.
+ template <typename Iterator>
+ void tourNodes(Iterator out) const {
+ std::copy(_path.begin(), _path.end(), out);
+ }
+
+ /// \brief Gives back the found tour as a path.
+ ///
+ /// This function copies the found tour as a list of arcs/edges into
+ /// the given \ref lemon::concepts::Path "path structure".
+ ///
+ /// \pre run() must be called before using this function.
+ template <typename Path>
+ void tour(Path &path) const {
+ path.clear();
+ for (int i = 0; i < int(_path.size()) - 1; ++i) {
+ path.addBack(_gr.arc(_path[i], _path[i+1]));
+ }
+ if (int(_path.size()) >= 2) {
+ path.addBack(_gr.arc(_path.back(), _path.front()));
+ }
+ }
+
+ /// @}
+
+ };
+
+}; // namespace lemon
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/circulation.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/circulation.h
new file mode 100644
index 00000000000..b0f717b2615
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/circulation.h
@@ -0,0 +1,807 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_CIRCULATION_H
+#define LEMON_CIRCULATION_H
+
+#include <lemon/tolerance.h>
+#include <lemon/elevator.h>
+#include <limits>
+
+///\ingroup max_flow
+///\file
+///\brief Push-relabel algorithm for finding a feasible circulation.
+///
+namespace lemon {
+
+ /// \brief Default traits class of Circulation class.
+ ///
+ /// Default traits class of Circulation class.
+ ///
+ /// \tparam GR Type of the digraph the algorithm runs on.
+ /// \tparam LM The type of the lower bound map.
+ /// \tparam UM The type of the upper bound (capacity) map.
+ /// \tparam SM The type of the supply map.
+ template <typename GR, typename LM,
+ typename UM, typename SM>
+ struct CirculationDefaultTraits {
+
+ /// \brief The type of the digraph the algorithm runs on.
+ typedef GR Digraph;
+
+ /// \brief The type of the lower bound map.
+ ///
+ /// The type of the map that stores the lower bounds on the arcs.
+ /// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
+ typedef LM LowerMap;
+
+ /// \brief The type of the upper bound (capacity) map.
+ ///
+ /// The type of the map that stores the upper bounds (capacities)
+ /// on the arcs.
+ /// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
+ typedef UM UpperMap;
+
+ /// \brief The type of supply map.
+ ///
+ /// The type of the map that stores the signed supply values of the
+ /// nodes.
+ /// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
+ typedef SM SupplyMap;
+
+ /// \brief The type of the flow and supply values.
+ typedef typename SupplyMap::Value Value;
+
+ /// \brief The type of the map that stores the flow values.
+ ///
+ /// The type of the map that stores the flow values.
+ /// It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap"
+ /// concept.
+#ifdef DOXYGEN
+ typedef GR::ArcMap<Value> FlowMap;
+#else
+ typedef typename Digraph::template ArcMap<Value> FlowMap;
+#endif
+
+ /// \brief Instantiates a FlowMap.
+ ///
+ /// This function instantiates a \ref FlowMap.
+ /// \param digraph The digraph for which we would like to define
+ /// the flow map.
+ static FlowMap* createFlowMap(const Digraph& digraph) {
+ return new FlowMap(digraph);
+ }
+
+ /// \brief The elevator type used by the algorithm.
+ ///
+ /// The elevator type used by the algorithm.
+ ///
+ /// \sa Elevator, LinkedElevator
+#ifdef DOXYGEN
+ typedef lemon::Elevator<GR, GR::Node> Elevator;
+#else
+ typedef lemon::Elevator<Digraph, typename Digraph::Node> Elevator;
+#endif
+
+ /// \brief Instantiates an Elevator.
+ ///
+ /// This function instantiates an \ref Elevator.
+ /// \param digraph The digraph for which we would like to define
+ /// the elevator.
+ /// \param max_level The maximum level of the elevator.
+ static Elevator* createElevator(const Digraph& digraph, int max_level) {
+ return new Elevator(digraph, max_level);
+ }
+
+ /// \brief The tolerance used by the algorithm
+ ///
+ /// The tolerance used by the algorithm to handle inexact computation.
+ typedef lemon::Tolerance<Value> Tolerance;
+
+ };
+
+ /**
+ \brief Push-relabel algorithm for the network circulation problem.
+
+ \ingroup max_flow
+ This class implements a push-relabel algorithm for the \e network
+ \e circulation problem.
+ It is to find a feasible circulation when lower and upper bounds
+ are given for the flow values on the arcs and lower bounds are
+ given for the difference between the outgoing and incoming flow
+ at the nodes.
+
+ The exact formulation of this problem is the following.
+ Let \f$G=(V,A)\f$ be a digraph, \f$lower: A\rightarrow\mathbf{R}\f$
+ \f$upper: A\rightarrow\mathbf{R}\cup\{\infty\}\f$ denote the lower and
+ upper bounds on the arcs, for which \f$lower(uv) \leq upper(uv)\f$
+ holds for all \f$uv\in A\f$, and \f$sup: V\rightarrow\mathbf{R}\f$
+ denotes the signed supply values of the nodes.
+ If \f$sup(u)>0\f$, then \f$u\f$ is a supply node with \f$sup(u)\f$
+ supply, if \f$sup(u)<0\f$, then \f$u\f$ is a demand node with
+ \f$-sup(u)\f$ demand.
+ A feasible circulation is an \f$f: A\rightarrow\mathbf{R}\f$
+ solution of the following problem.
+
+ \f[ \sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu)
+ \geq sup(u) \quad \forall u\in V, \f]
+ \f[ lower(uv) \leq f(uv) \leq upper(uv) \quad \forall uv\in A. \f]
+
+ The sum of the supply values, i.e. \f$\sum_{u\in V} sup(u)\f$ must be
+ zero or negative in order to have a feasible solution (since the sum
+ of the expressions on the left-hand side of the inequalities is zero).
+ It means that the total demand must be greater or equal to the total
+ supply and all the supplies have to be carried out from the supply nodes,
+ but there could be demands that are not satisfied.
+ If \f$\sum_{u\in V} sup(u)\f$ is zero, then all the supply/demand
+ constraints have to be satisfied with equality, i.e. all demands
+ have to be satisfied and all supplies have to be used.
+
+ If you need the opposite inequalities in the supply/demand constraints
+ (i.e. the total demand is less than the total supply and all the demands
+ have to be satisfied while there could be supplies that are not used),
+ then you could easily transform the problem to the above form by reversing
+ the direction of the arcs and taking the negative of the supply values
+ (e.g. using \ref ReverseDigraph and \ref NegMap adaptors).
+
+ This algorithm either calculates a feasible circulation, or provides
+ a \ref barrier() "barrier", which prooves that a feasible soultion
+ cannot exist.
+
+ Note that this algorithm also provides a feasible solution for the
+ \ref min_cost_flow "minimum cost flow problem".
+
+ \tparam GR The type of the digraph the algorithm runs on.
+ \tparam LM The type of the lower bound map. The default
+ map type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
+ \tparam UM The type of the upper bound (capacity) map.
+ The default map type is \c LM.
+ \tparam SM The type of the supply map. The default map type is
+ \ref concepts::Digraph::NodeMap "GR::NodeMap<UM::Value>".
+ \tparam TR The traits class that defines various types used by the
+ algorithm. By default, it is \ref CirculationDefaultTraits
+ "CirculationDefaultTraits<GR, LM, UM, SM>".
+ In most cases, this parameter should not be set directly,
+ consider to use the named template parameters instead.
+ */
+#ifdef DOXYGEN
+template< typename GR,
+ typename LM,
+ typename UM,
+ typename SM,
+ typename TR >
+#else
+template< typename GR,
+ typename LM = typename GR::template ArcMap<int>,
+ typename UM = LM,
+ typename SM = typename GR::template NodeMap<typename UM::Value>,
+ typename TR = CirculationDefaultTraits<GR, LM, UM, SM> >
+#endif
+ class Circulation {
+ public:
+
+ /// \brief The \ref lemon::CirculationDefaultTraits "traits class"
+ /// of the algorithm.
+ typedef TR Traits;
+ ///The type of the digraph the algorithm runs on.
+ typedef typename Traits::Digraph Digraph;
+ ///The type of the flow and supply values.
+ typedef typename Traits::Value Value;
+
+ ///The type of the lower bound map.
+ typedef typename Traits::LowerMap LowerMap;
+ ///The type of the upper bound (capacity) map.
+ typedef typename Traits::UpperMap UpperMap;
+ ///The type of the supply map.
+ typedef typename Traits::SupplyMap SupplyMap;
+ ///The type of the flow map.
+ typedef typename Traits::FlowMap FlowMap;
+
+ ///The type of the elevator.
+ typedef typename Traits::Elevator Elevator;
+ ///The type of the tolerance.
+ typedef typename Traits::Tolerance Tolerance;
+
+ private:
+
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+
+ const Digraph &_g;
+ int _node_num;
+
+ const LowerMap *_lo;
+ const UpperMap *_up;
+ const SupplyMap *_supply;
+
+ FlowMap *_flow;
+ bool _local_flow;
+
+ Elevator* _level;
+ bool _local_level;
+
+ typedef typename Digraph::template NodeMap<Value> ExcessMap;
+ ExcessMap* _excess;
+
+ Tolerance _tol;
+ int _el;
+
+ public:
+
+ typedef Circulation Create;
+
+ ///\name Named Template Parameters
+
+ ///@{
+
+ template <typename T>
+ struct SetFlowMapTraits : public Traits {
+ typedef T FlowMap;
+ static FlowMap *createFlowMap(const Digraph&) {
+ LEMON_ASSERT(false, "FlowMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// FlowMap type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting FlowMap
+ /// type.
+ template <typename T>
+ struct SetFlowMap
+ : public Circulation<Digraph, LowerMap, UpperMap, SupplyMap,
+ SetFlowMapTraits<T> > {
+ typedef Circulation<Digraph, LowerMap, UpperMap, SupplyMap,
+ SetFlowMapTraits<T> > Create;
+ };
+
+ template <typename T>
+ struct SetElevatorTraits : public Traits {
+ typedef T Elevator;
+ static Elevator *createElevator(const Digraph&, int) {
+ LEMON_ASSERT(false, "Elevator is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// Elevator type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting Elevator
+ /// type. If this named parameter is used, then an external
+ /// elevator object must be passed to the algorithm using the
+ /// \ref elevator(Elevator&) "elevator()" function before calling
+ /// \ref run() or \ref init().
+ /// \sa SetStandardElevator
+ template <typename T>
+ struct SetElevator
+ : public Circulation<Digraph, LowerMap, UpperMap, SupplyMap,
+ SetElevatorTraits<T> > {
+ typedef Circulation<Digraph, LowerMap, UpperMap, SupplyMap,
+ SetElevatorTraits<T> > Create;
+ };
+
+ template <typename T>
+ struct SetStandardElevatorTraits : public Traits {
+ typedef T Elevator;
+ static Elevator *createElevator(const Digraph& digraph, int max_level) {
+ return new Elevator(digraph, max_level);
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// Elevator type with automatic allocation
+ ///
+ /// \ref named-templ-param "Named parameter" for setting Elevator
+ /// type with automatic allocation.
+ /// The Elevator should have standard constructor interface to be
+ /// able to automatically created by the algorithm (i.e. the
+ /// digraph and the maximum level should be passed to it).
+ /// However, an external elevator object could also be passed to the
+ /// algorithm with the \ref elevator(Elevator&) "elevator()" function
+ /// before calling \ref run() or \ref init().
+ /// \sa SetElevator
+ template <typename T>
+ struct SetStandardElevator
+ : public Circulation<Digraph, LowerMap, UpperMap, SupplyMap,
+ SetStandardElevatorTraits<T> > {
+ typedef Circulation<Digraph, LowerMap, UpperMap, SupplyMap,
+ SetStandardElevatorTraits<T> > Create;
+ };
+
+ /// @}
+
+ protected:
+
+ Circulation() {}
+
+ public:
+
+ /// Constructor.
+
+ /// The constructor of the class.
+ ///
+ /// \param graph The digraph the algorithm runs on.
+ /// \param lower The lower bounds for the flow values on the arcs.
+ /// \param upper The upper bounds (capacities) for the flow values
+ /// on the arcs.
+ /// \param supply The signed supply values of the nodes.
+ Circulation(const Digraph &graph, const LowerMap &lower,
+ const UpperMap &upper, const SupplyMap &supply)
+ : _g(graph), _lo(&lower), _up(&upper), _supply(&supply),
+ _flow(NULL), _local_flow(false), _level(NULL), _local_level(false),
+ _excess(NULL) {}
+
+ /// Destructor.
+ ~Circulation() {
+ destroyStructures();
+ }
+
+
+ private:
+
+ bool checkBoundMaps() {
+ for (ArcIt e(_g);e!=INVALID;++e) {
+ if (_tol.less((*_up)[e], (*_lo)[e])) return false;
+ }
+ return true;
+ }
+
+ void createStructures() {
+ _node_num = _el = countNodes(_g);
+
+ if (!_flow) {
+ _flow = Traits::createFlowMap(_g);
+ _local_flow = true;
+ }
+ if (!_level) {
+ _level = Traits::createElevator(_g, _node_num);
+ _local_level = true;
+ }
+ if (!_excess) {
+ _excess = new ExcessMap(_g);
+ }
+ }
+
+ void destroyStructures() {
+ if (_local_flow) {
+ delete _flow;
+ }
+ if (_local_level) {
+ delete _level;
+ }
+ if (_excess) {
+ delete _excess;
+ }
+ }
+
+ public:
+
+ /// Sets the lower bound map.
+
+ /// Sets the lower bound map.
+ /// \return <tt>(*this)</tt>
+ Circulation& lowerMap(const LowerMap& map) {
+ _lo = &map;
+ return *this;
+ }
+
+ /// Sets the upper bound (capacity) map.
+
+ /// Sets the upper bound (capacity) map.
+ /// \return <tt>(*this)</tt>
+ Circulation& upperMap(const UpperMap& map) {
+ _up = &map;
+ return *this;
+ }
+
+ /// Sets the supply map.
+
+ /// Sets the supply map.
+ /// \return <tt>(*this)</tt>
+ Circulation& supplyMap(const SupplyMap& map) {
+ _supply = &map;
+ return *this;
+ }
+
+ /// \brief Sets the flow map.
+ ///
+ /// Sets the flow map.
+ /// If you don't use this function before calling \ref run() or
+ /// \ref init(), an instance will be allocated automatically.
+ /// The destructor deallocates this automatically allocated map,
+ /// of course.
+ /// \return <tt>(*this)</tt>
+ Circulation& flowMap(FlowMap& map) {
+ if (_local_flow) {
+ delete _flow;
+ _local_flow = false;
+ }
+ _flow = &map;
+ return *this;
+ }
+
+ /// \brief Sets the elevator used by algorithm.
+ ///
+ /// Sets the elevator used by algorithm.
+ /// If you don't use this function before calling \ref run() or
+ /// \ref init(), an instance will be allocated automatically.
+ /// The destructor deallocates this automatically allocated elevator,
+ /// of course.
+ /// \return <tt>(*this)</tt>
+ Circulation& elevator(Elevator& elevator) {
+ if (_local_level) {
+ delete _level;
+ _local_level = false;
+ }
+ _level = &elevator;
+ return *this;
+ }
+
+ /// \brief Returns a const reference to the elevator.
+ ///
+ /// Returns a const reference to the elevator.
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ const Elevator& elevator() const {
+ return *_level;
+ }
+
+ /// \brief Sets the tolerance used by the algorithm.
+ ///
+ /// Sets the tolerance object used by the algorithm.
+ /// \return <tt>(*this)</tt>
+ Circulation& tolerance(const Tolerance& tolerance) {
+ _tol = tolerance;
+ return *this;
+ }
+
+ /// \brief Returns a const reference to the tolerance.
+ ///
+ /// Returns a const reference to the tolerance object used by
+ /// the algorithm.
+ const Tolerance& tolerance() const {
+ return _tol;
+ }
+
+ /// \name Execution Control
+ /// The simplest way to execute the algorithm is to call \ref run().\n
+ /// If you need better control on the initial solution or the execution,
+ /// you have to call one of the \ref init() functions first, then
+ /// the \ref start() function.
+
+ ///@{
+
+ /// Initializes the internal data structures.
+
+ /// Initializes the internal data structures and sets all flow values
+ /// to the lower bound.
+ void init()
+ {
+ LEMON_DEBUG(checkBoundMaps(),
+ "Upper bounds must be greater or equal to the lower bounds");
+
+ createStructures();
+
+ for(NodeIt n(_g);n!=INVALID;++n) {
+ (*_excess)[n] = (*_supply)[n];
+ }
+
+ for (ArcIt e(_g);e!=INVALID;++e) {
+ _flow->set(e, (*_lo)[e]);
+ (*_excess)[_g.target(e)] += (*_flow)[e];
+ (*_excess)[_g.source(e)] -= (*_flow)[e];
+ }
+
+ // global relabeling tested, but in general case it provides
+ // worse performance for random digraphs
+ _level->initStart();
+ for(NodeIt n(_g);n!=INVALID;++n)
+ _level->initAddItem(n);
+ _level->initFinish();
+ for(NodeIt n(_g);n!=INVALID;++n)
+ if(_tol.positive((*_excess)[n]))
+ _level->activate(n);
+ }
+
+ /// Initializes the internal data structures using a greedy approach.
+
+ /// Initializes the internal data structures using a greedy approach
+ /// to construct the initial solution.
+ void greedyInit()
+ {
+ LEMON_DEBUG(checkBoundMaps(),
+ "Upper bounds must be greater or equal to the lower bounds");
+
+ createStructures();
+
+ for(NodeIt n(_g);n!=INVALID;++n) {
+ (*_excess)[n] = (*_supply)[n];
+ }
+
+ for (ArcIt e(_g);e!=INVALID;++e) {
+ if (!_tol.less(-(*_excess)[_g.target(e)], (*_up)[e])) {
+ _flow->set(e, (*_up)[e]);
+ (*_excess)[_g.target(e)] += (*_up)[e];
+ (*_excess)[_g.source(e)] -= (*_up)[e];
+ } else if (_tol.less(-(*_excess)[_g.target(e)], (*_lo)[e])) {
+ _flow->set(e, (*_lo)[e]);
+ (*_excess)[_g.target(e)] += (*_lo)[e];
+ (*_excess)[_g.source(e)] -= (*_lo)[e];
+ } else {
+ Value fc = -(*_excess)[_g.target(e)];
+ _flow->set(e, fc);
+ (*_excess)[_g.target(e)] = 0;
+ (*_excess)[_g.source(e)] -= fc;
+ }
+ }
+
+ _level->initStart();
+ for(NodeIt n(_g);n!=INVALID;++n)
+ _level->initAddItem(n);
+ _level->initFinish();
+ for(NodeIt n(_g);n!=INVALID;++n)
+ if(_tol.positive((*_excess)[n]))
+ _level->activate(n);
+ }
+
+ ///Executes the algorithm
+
+ ///This function executes the algorithm.
+ ///
+ ///\return \c true if a feasible circulation is found.
+ ///
+ ///\sa barrier()
+ ///\sa barrierMap()
+ bool start()
+ {
+
+ Node act;
+ while((act=_level->highestActive())!=INVALID) {
+ int actlevel=(*_level)[act];
+ int mlevel=_node_num;
+ Value exc=(*_excess)[act];
+
+ for(OutArcIt e(_g,act);e!=INVALID; ++e) {
+ Node v = _g.target(e);
+ Value fc=(*_up)[e]-(*_flow)[e];
+ if(!_tol.positive(fc)) continue;
+ if((*_level)[v]<actlevel) {
+ if(!_tol.less(fc, exc)) {
+ _flow->set(e, (*_flow)[e] + exc);
+ (*_excess)[v] += exc;
+ if(!_level->active(v) && _tol.positive((*_excess)[v]))
+ _level->activate(v);
+ (*_excess)[act] = 0;
+ _level->deactivate(act);
+ goto next_l;
+ }
+ else {
+ _flow->set(e, (*_up)[e]);
+ (*_excess)[v] += fc;
+ if(!_level->active(v) && _tol.positive((*_excess)[v]))
+ _level->activate(v);
+ exc-=fc;
+ }
+ }
+ else if((*_level)[v]<mlevel) mlevel=(*_level)[v];
+ }
+ for(InArcIt e(_g,act);e!=INVALID; ++e) {
+ Node v = _g.source(e);
+ Value fc=(*_flow)[e]-(*_lo)[e];
+ if(!_tol.positive(fc)) continue;
+ if((*_level)[v]<actlevel) {
+ if(!_tol.less(fc, exc)) {
+ _flow->set(e, (*_flow)[e] - exc);
+ (*_excess)[v] += exc;
+ if(!_level->active(v) && _tol.positive((*_excess)[v]))
+ _level->activate(v);
+ (*_excess)[act] = 0;
+ _level->deactivate(act);
+ goto next_l;
+ }
+ else {
+ _flow->set(e, (*_lo)[e]);
+ (*_excess)[v] += fc;
+ if(!_level->active(v) && _tol.positive((*_excess)[v]))
+ _level->activate(v);
+ exc-=fc;
+ }
+ }
+ else if((*_level)[v]<mlevel) mlevel=(*_level)[v];
+ }
+
+ (*_excess)[act] = exc;
+ if(!_tol.positive(exc)) _level->deactivate(act);
+ else if(mlevel==_node_num) {
+ _level->liftHighestActiveToTop();
+ _el = _node_num;
+ return false;
+ }
+ else {
+ _level->liftHighestActive(mlevel+1);
+ if(_level->onLevel(actlevel)==0) {
+ _el = actlevel;
+ return false;
+ }
+ }
+ next_l:
+ ;
+ }
+ return true;
+ }
+
+ /// Runs the algorithm.
+
+ /// This function runs the algorithm.
+ ///
+ /// \return \c true if a feasible circulation is found.
+ ///
+ /// \note Apart from the return value, c.run() is just a shortcut of
+ /// the following code.
+ /// \code
+ /// c.greedyInit();
+ /// c.start();
+ /// \endcode
+ bool run() {
+ greedyInit();
+ return start();
+ }
+
+ /// @}
+
+ /// \name Query Functions
+ /// The results of the circulation algorithm can be obtained using
+ /// these functions.\n
+ /// Either \ref run() or \ref start() should be called before
+ /// using them.
+
+ ///@{
+
+ /// \brief Returns the flow value on the given arc.
+ ///
+ /// Returns the flow value on the given arc.
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ Value flow(const Arc& arc) const {
+ return (*_flow)[arc];
+ }
+
+ /// \brief Returns a const reference to the flow map.
+ ///
+ /// Returns a const reference to the arc map storing the found flow.
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ const FlowMap& flowMap() const {
+ return *_flow;
+ }
+
+ /**
+ \brief Returns \c true if the given node is in a barrier.
+
+ Barrier is a set \e B of nodes for which
+
+ \f[ \sum_{uv\in A: u\in B} upper(uv) -
+ \sum_{uv\in A: v\in B} lower(uv) < \sum_{v\in B} sup(v) \f]
+
+ holds. The existence of a set with this property prooves that a
+ feasible circualtion cannot exist.
+
+ This function returns \c true if the given node is in the found
+ barrier. If a feasible circulation is found, the function
+ gives back \c false for every node.
+
+ \pre Either \ref run() or \ref init() must be called before
+ using this function.
+
+ \sa barrierMap()
+ \sa checkBarrier()
+ */
+ bool barrier(const Node& node) const
+ {
+ return (*_level)[node] >= _el;
+ }
+
+ /// \brief Gives back a barrier.
+ ///
+ /// This function sets \c bar to the characteristic vector of the
+ /// found barrier. \c bar should be a \ref concepts::WriteMap "writable"
+ /// node map with \c bool (or convertible) value type.
+ ///
+ /// If a feasible circulation is found, the function gives back an
+ /// empty set, so \c bar[v] will be \c false for all nodes \c v.
+ ///
+ /// \note This function calls \ref barrier() for each node,
+ /// so it runs in O(n) time.
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ ///
+ /// \sa barrier()
+ /// \sa checkBarrier()
+ template<class BarrierMap>
+ void barrierMap(BarrierMap &bar) const
+ {
+ for(NodeIt n(_g);n!=INVALID;++n)
+ bar.set(n, (*_level)[n] >= _el);
+ }
+
+ /// @}
+
+ /// \name Checker Functions
+ /// The feasibility of the results can be checked using
+ /// these functions.\n
+ /// Either \ref run() or \ref start() should be called before
+ /// using them.
+
+ ///@{
+
+ ///Check if the found flow is a feasible circulation
+
+ ///Check if the found flow is a feasible circulation,
+ ///
+ bool checkFlow() const {
+ for(ArcIt e(_g);e!=INVALID;++e)
+ if((*_flow)[e]<(*_lo)[e]||(*_flow)[e]>(*_up)[e]) return false;
+ for(NodeIt n(_g);n!=INVALID;++n)
+ {
+ Value dif=-(*_supply)[n];
+ for(InArcIt e(_g,n);e!=INVALID;++e) dif-=(*_flow)[e];
+ for(OutArcIt e(_g,n);e!=INVALID;++e) dif+=(*_flow)[e];
+ if(_tol.negative(dif)) return false;
+ }
+ return true;
+ }
+
+ ///Check whether or not the last execution provides a barrier
+
+ ///Check whether or not the last execution provides a barrier.
+ ///\sa barrier()
+ ///\sa barrierMap()
+ bool checkBarrier() const
+ {
+ Value delta=0;
+ Value inf_cap = std::numeric_limits<Value>::has_infinity ?
+ std::numeric_limits<Value>::infinity() :
+ std::numeric_limits<Value>::max();
+ for(NodeIt n(_g);n!=INVALID;++n)
+ if(barrier(n))
+ delta-=(*_supply)[n];
+ for(ArcIt e(_g);e!=INVALID;++e)
+ {
+ Node s=_g.source(e);
+ Node t=_g.target(e);
+ if(barrier(s)&&!barrier(t)) {
+ if (_tol.less(inf_cap - (*_up)[e], delta)) return false;
+ delta+=(*_up)[e];
+ }
+ else if(barrier(t)&&!barrier(s)) delta-=(*_lo)[e];
+ }
+ return _tol.negative(delta);
+ }
+
+ /// @}
+
+ };
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/clp.cc b/extern/quadriflow/3rd/lemon-1.3.1/lemon/clp.cc
new file mode 100644
index 00000000000..7c0ea74f22c
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/clp.cc
@@ -0,0 +1,464 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/clp.h>
+#include <coin/ClpSimplex.hpp>
+
+namespace lemon {
+
+ ClpLp::ClpLp() {
+ _prob = new ClpSimplex();
+ _init_temporals();
+ messageLevel(MESSAGE_NOTHING);
+ }
+
+ ClpLp::ClpLp(const ClpLp& other) {
+ _prob = new ClpSimplex(*other._prob);
+ rows = other.rows;
+ cols = other.cols;
+ _init_temporals();
+ messageLevel(MESSAGE_NOTHING);
+ }
+
+ ClpLp::~ClpLp() {
+ delete _prob;
+ _clear_temporals();
+ }
+
+ void ClpLp::_init_temporals() {
+ _primal_ray = 0;
+ _dual_ray = 0;
+ }
+
+ void ClpLp::_clear_temporals() {
+ if (_primal_ray) {
+ delete[] _primal_ray;
+ _primal_ray = 0;
+ }
+ if (_dual_ray) {
+ delete[] _dual_ray;
+ _dual_ray = 0;
+ }
+ }
+
+ ClpLp* ClpLp::newSolver() const {
+ ClpLp* newlp = new ClpLp;
+ return newlp;
+ }
+
+ ClpLp* ClpLp::cloneSolver() const {
+ ClpLp* copylp = new ClpLp(*this);
+ return copylp;
+ }
+
+ const char* ClpLp::_solverName() const { return "ClpLp"; }
+
+ int ClpLp::_addCol() {
+ _prob->addColumn(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX, 0.0);
+ return _prob->numberColumns() - 1;
+ }
+
+ int ClpLp::_addRow() {
+ _prob->addRow(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX);
+ return _prob->numberRows() - 1;
+ }
+
+ int ClpLp::_addRow(Value l, ExprIterator b, ExprIterator e, Value u) {
+ std::vector<int> indexes;
+ std::vector<Value> values;
+
+ for(ExprIterator it = b; it != e; ++it) {
+ indexes.push_back(it->first);
+ values.push_back(it->second);
+ }
+
+ _prob->addRow(values.size(), &indexes.front(), &values.front(), l, u);
+ return _prob->numberRows() - 1;
+ }
+
+
+ void ClpLp::_eraseCol(int c) {
+ _col_names_ref.erase(_prob->getColumnName(c));
+ _prob->deleteColumns(1, &c);
+ }
+
+ void ClpLp::_eraseRow(int r) {
+ _row_names_ref.erase(_prob->getRowName(r));
+ _prob->deleteRows(1, &r);
+ }
+
+ void ClpLp::_eraseColId(int i) {
+ cols.eraseIndex(i);
+ cols.shiftIndices(i);
+ }
+
+ void ClpLp::_eraseRowId(int i) {
+ rows.eraseIndex(i);
+ rows.shiftIndices(i);
+ }
+
+ void ClpLp::_getColName(int c, std::string& name) const {
+ name = _prob->getColumnName(c);
+ }
+
+ void ClpLp::_setColName(int c, const std::string& name) {
+ _prob->setColumnName(c, const_cast<std::string&>(name));
+ _col_names_ref[name] = c;
+ }
+
+ int ClpLp::_colByName(const std::string& name) const {
+ std::map<std::string, int>::const_iterator it = _col_names_ref.find(name);
+ return it != _col_names_ref.end() ? it->second : -1;
+ }
+
+ void ClpLp::_getRowName(int r, std::string& name) const {
+ name = _prob->getRowName(r);
+ }
+
+ void ClpLp::_setRowName(int r, const std::string& name) {
+ _prob->setRowName(r, const_cast<std::string&>(name));
+ _row_names_ref[name] = r;
+ }
+
+ int ClpLp::_rowByName(const std::string& name) const {
+ std::map<std::string, int>::const_iterator it = _row_names_ref.find(name);
+ return it != _row_names_ref.end() ? it->second : -1;
+ }
+
+
+ void ClpLp::_setRowCoeffs(int ix, ExprIterator b, ExprIterator e) {
+ std::map<int, Value> coeffs;
+
+ int n = _prob->clpMatrix()->getNumCols();
+
+ const int* indices = _prob->clpMatrix()->getIndices();
+ const double* elements = _prob->clpMatrix()->getElements();
+
+ for (int i = 0; i < n; ++i) {
+ CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[i];
+ CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[i];
+
+ const int* it = std::lower_bound(indices + begin, indices + end, ix);
+ if (it != indices + end && *it == ix && elements[it - indices] != 0.0) {
+ coeffs[i] = 0.0;
+ }
+ }
+
+ for (ExprIterator it = b; it != e; ++it) {
+ coeffs[it->first] = it->second;
+ }
+
+ for (std::map<int, Value>::iterator it = coeffs.begin();
+ it != coeffs.end(); ++it) {
+ _prob->modifyCoefficient(ix, it->first, it->second);
+ }
+ }
+
+ void ClpLp::_getRowCoeffs(int ix, InsertIterator b) const {
+ int n = _prob->clpMatrix()->getNumCols();
+
+ const int* indices = _prob->clpMatrix()->getIndices();
+ const double* elements = _prob->clpMatrix()->getElements();
+
+ for (int i = 0; i < n; ++i) {
+ CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[i];
+ CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[i];
+
+ const int* it = std::lower_bound(indices + begin, indices + end, ix);
+ if (it != indices + end && *it == ix) {
+ *b = std::make_pair(i, elements[it - indices]);
+ }
+ }
+ }
+
+ void ClpLp::_setColCoeffs(int ix, ExprIterator b, ExprIterator e) {
+ std::map<int, Value> coeffs;
+
+ CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
+ CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
+
+ const int* indices = _prob->clpMatrix()->getIndices();
+ const double* elements = _prob->clpMatrix()->getElements();
+
+ for (CoinBigIndex i = begin; i != end; ++i) {
+ if (elements[i] != 0.0) {
+ coeffs[indices[i]] = 0.0;
+ }
+ }
+ for (ExprIterator it = b; it != e; ++it) {
+ coeffs[it->first] = it->second;
+ }
+ for (std::map<int, Value>::iterator it = coeffs.begin();
+ it != coeffs.end(); ++it) {
+ _prob->modifyCoefficient(it->first, ix, it->second);
+ }
+ }
+
+ void ClpLp::_getColCoeffs(int ix, InsertIterator b) const {
+ CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
+ CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
+
+ const int* indices = _prob->clpMatrix()->getIndices();
+ const double* elements = _prob->clpMatrix()->getElements();
+
+ for (CoinBigIndex i = begin; i != end; ++i) {
+ *b = std::make_pair(indices[i], elements[i]);
+ ++b;
+ }
+ }
+
+ void ClpLp::_setCoeff(int ix, int jx, Value value) {
+ _prob->modifyCoefficient(ix, jx, value);
+ }
+
+ ClpLp::Value ClpLp::_getCoeff(int ix, int jx) const {
+ CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
+ CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
+
+ const int* indices = _prob->clpMatrix()->getIndices();
+ const double* elements = _prob->clpMatrix()->getElements();
+
+ const int* it = std::lower_bound(indices + begin, indices + end, jx);
+ if (it != indices + end && *it == jx) {
+ return elements[it - indices];
+ } else {
+ return 0.0;
+ }
+ }
+
+ void ClpLp::_setColLowerBound(int i, Value lo) {
+ _prob->setColumnLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
+ }
+
+ ClpLp::Value ClpLp::_getColLowerBound(int i) const {
+ double val = _prob->getColLower()[i];
+ return val == - COIN_DBL_MAX ? - INF : val;
+ }
+
+ void ClpLp::_setColUpperBound(int i, Value up) {
+ _prob->setColumnUpper(i, up == INF ? COIN_DBL_MAX : up);
+ }
+
+ ClpLp::Value ClpLp::_getColUpperBound(int i) const {
+ double val = _prob->getColUpper()[i];
+ return val == COIN_DBL_MAX ? INF : val;
+ }
+
+ void ClpLp::_setRowLowerBound(int i, Value lo) {
+ _prob->setRowLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
+ }
+
+ ClpLp::Value ClpLp::_getRowLowerBound(int i) const {
+ double val = _prob->getRowLower()[i];
+ return val == - COIN_DBL_MAX ? - INF : val;
+ }
+
+ void ClpLp::_setRowUpperBound(int i, Value up) {
+ _prob->setRowUpper(i, up == INF ? COIN_DBL_MAX : up);
+ }
+
+ ClpLp::Value ClpLp::_getRowUpperBound(int i) const {
+ double val = _prob->getRowUpper()[i];
+ return val == COIN_DBL_MAX ? INF : val;
+ }
+
+ void ClpLp::_setObjCoeffs(ExprIterator b, ExprIterator e) {
+ int num = _prob->clpMatrix()->getNumCols();
+ for (int i = 0; i < num; ++i) {
+ _prob->setObjectiveCoefficient(i, 0.0);
+ }
+ for (ExprIterator it = b; it != e; ++it) {
+ _prob->setObjectiveCoefficient(it->first, it->second);
+ }
+ }
+
+ void ClpLp::_getObjCoeffs(InsertIterator b) const {
+ int num = _prob->clpMatrix()->getNumCols();
+ for (int i = 0; i < num; ++i) {
+ Value coef = _prob->getObjCoefficients()[i];
+ if (coef != 0.0) {
+ *b = std::make_pair(i, coef);
+ ++b;
+ }
+ }
+ }
+
+ void ClpLp::_setObjCoeff(int i, Value obj_coef) {
+ _prob->setObjectiveCoefficient(i, obj_coef);
+ }
+
+ ClpLp::Value ClpLp::_getObjCoeff(int i) const {
+ return _prob->getObjCoefficients()[i];
+ }
+
+ ClpLp::SolveExitStatus ClpLp::_solve() {
+ return _prob->primal() >= 0 ? SOLVED : UNSOLVED;
+ }
+
+ ClpLp::SolveExitStatus ClpLp::solvePrimal() {
+ return _prob->primal() >= 0 ? SOLVED : UNSOLVED;
+ }
+
+ ClpLp::SolveExitStatus ClpLp::solveDual() {
+ return _prob->dual() >= 0 ? SOLVED : UNSOLVED;
+ }
+
+ ClpLp::SolveExitStatus ClpLp::solveBarrier() {
+ return _prob->barrier() >= 0 ? SOLVED : UNSOLVED;
+ }
+
+ ClpLp::Value ClpLp::_getPrimal(int i) const {
+ return _prob->primalColumnSolution()[i];
+ }
+ ClpLp::Value ClpLp::_getPrimalValue() const {
+ return _prob->objectiveValue();
+ }
+
+ ClpLp::Value ClpLp::_getDual(int i) const {
+ return _prob->dualRowSolution()[i];
+ }
+
+ ClpLp::Value ClpLp::_getPrimalRay(int i) const {
+ if (!_primal_ray) {
+ _primal_ray = _prob->unboundedRay();
+ LEMON_ASSERT(_primal_ray != 0, "Primal ray is not provided");
+ }
+ return _primal_ray[i];
+ }
+
+ ClpLp::Value ClpLp::_getDualRay(int i) const {
+ if (!_dual_ray) {
+ _dual_ray = _prob->infeasibilityRay();
+ LEMON_ASSERT(_dual_ray != 0, "Dual ray is not provided");
+ }
+ return _dual_ray[i];
+ }
+
+ ClpLp::VarStatus ClpLp::_getColStatus(int i) const {
+ switch (_prob->getColumnStatus(i)) {
+ case ClpSimplex::basic:
+ return BASIC;
+ case ClpSimplex::isFree:
+ return FREE;
+ case ClpSimplex::atUpperBound:
+ return UPPER;
+ case ClpSimplex::atLowerBound:
+ return LOWER;
+ case ClpSimplex::isFixed:
+ return FIXED;
+ case ClpSimplex::superBasic:
+ return FREE;
+ default:
+ LEMON_ASSERT(false, "Wrong column status");
+ return VarStatus();
+ }
+ }
+
+ ClpLp::VarStatus ClpLp::_getRowStatus(int i) const {
+ switch (_prob->getColumnStatus(i)) {
+ case ClpSimplex::basic:
+ return BASIC;
+ case ClpSimplex::isFree:
+ return FREE;
+ case ClpSimplex::atUpperBound:
+ return UPPER;
+ case ClpSimplex::atLowerBound:
+ return LOWER;
+ case ClpSimplex::isFixed:
+ return FIXED;
+ case ClpSimplex::superBasic:
+ return FREE;
+ default:
+ LEMON_ASSERT(false, "Wrong row status");
+ return VarStatus();
+ }
+ }
+
+
+ ClpLp::ProblemType ClpLp::_getPrimalType() const {
+ if (_prob->isProvenOptimal()) {
+ return OPTIMAL;
+ } else if (_prob->isProvenPrimalInfeasible()) {
+ return INFEASIBLE;
+ } else if (_prob->isProvenDualInfeasible()) {
+ return UNBOUNDED;
+ } else {
+ return UNDEFINED;
+ }
+ }
+
+ ClpLp::ProblemType ClpLp::_getDualType() const {
+ if (_prob->isProvenOptimal()) {
+ return OPTIMAL;
+ } else if (_prob->isProvenDualInfeasible()) {
+ return INFEASIBLE;
+ } else if (_prob->isProvenPrimalInfeasible()) {
+ return INFEASIBLE;
+ } else {
+ return UNDEFINED;
+ }
+ }
+
+ void ClpLp::_setSense(ClpLp::Sense sense) {
+ switch (sense) {
+ case MIN:
+ _prob->setOptimizationDirection(1);
+ break;
+ case MAX:
+ _prob->setOptimizationDirection(-1);
+ break;
+ }
+ }
+
+ ClpLp::Sense ClpLp::_getSense() const {
+ double dir = _prob->optimizationDirection();
+ if (dir > 0.0) {
+ return MIN;
+ } else {
+ return MAX;
+ }
+ }
+
+ void ClpLp::_clear() {
+ delete _prob;
+ _prob = new ClpSimplex();
+ _col_names_ref.clear();
+ _clear_temporals();
+ }
+
+ void ClpLp::_messageLevel(MessageLevel level) {
+ switch (level) {
+ case MESSAGE_NOTHING:
+ _prob->setLogLevel(0);
+ break;
+ case MESSAGE_ERROR:
+ _prob->setLogLevel(1);
+ break;
+ case MESSAGE_WARNING:
+ _prob->setLogLevel(2);
+ break;
+ case MESSAGE_NORMAL:
+ _prob->setLogLevel(3);
+ break;
+ case MESSAGE_VERBOSE:
+ _prob->setLogLevel(4);
+ break;
+ }
+ }
+
+} //END OF NAMESPACE LEMON
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/clp.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/clp.h
new file mode 100644
index 00000000000..fd331ac1354
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/clp.h
@@ -0,0 +1,164 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_CLP_H
+#define LEMON_CLP_H
+
+///\file
+///\brief Header of the LEMON-CLP lp solver interface.
+
+#include <vector>
+#include <string>
+
+#include <lemon/lp_base.h>
+
+class ClpSimplex;
+
+namespace lemon {
+
+ /// \ingroup lp_group
+ ///
+ /// \brief Interface for the CLP solver
+ ///
+ /// This class implements an interface for the Clp LP solver. The
+ /// Clp library is an object oriented lp solver library developed at
+ /// the IBM. The CLP is part of the COIN-OR package and it can be
+ /// used with Common Public License.
+ class ClpLp : public LpSolver {
+ protected:
+
+ ClpSimplex* _prob;
+
+ std::map<std::string, int> _col_names_ref;
+ std::map<std::string, int> _row_names_ref;
+
+ public:
+
+ /// \e
+ ClpLp();
+ /// \e
+ ClpLp(const ClpLp&);
+ /// \e
+ ~ClpLp();
+
+ /// \e
+ virtual ClpLp* newSolver() const;
+ /// \e
+ virtual ClpLp* cloneSolver() const;
+
+ protected:
+
+ mutable double* _primal_ray;
+ mutable double* _dual_ray;
+
+ void _init_temporals();
+ void _clear_temporals();
+
+ protected:
+
+ virtual const char* _solverName() const;
+
+ virtual int _addCol();
+ virtual int _addRow();
+ virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
+
+ virtual void _eraseCol(int i);
+ virtual void _eraseRow(int i);
+
+ virtual void _eraseColId(int i);
+ virtual void _eraseRowId(int i);
+
+ virtual void _getColName(int col, std::string& name) const;
+ virtual void _setColName(int col, const std::string& name);
+ virtual int _colByName(const std::string& name) const;
+
+ virtual void _getRowName(int row, std::string& name) const;
+ virtual void _setRowName(int row, const std::string& name);
+ virtual int _rowByName(const std::string& name) const;
+
+ virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
+ virtual void _getRowCoeffs(int i, InsertIterator b) const;
+
+ virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
+ virtual void _getColCoeffs(int i, InsertIterator b) const;
+
+ virtual void _setCoeff(int row, int col, Value value);
+ virtual Value _getCoeff(int row, int col) const;
+
+ virtual void _setColLowerBound(int i, Value value);
+ virtual Value _getColLowerBound(int i) const;
+ virtual void _setColUpperBound(int i, Value value);
+ virtual Value _getColUpperBound(int i) const;
+
+ virtual void _setRowLowerBound(int i, Value value);
+ virtual Value _getRowLowerBound(int i) const;
+ virtual void _setRowUpperBound(int i, Value value);
+ virtual Value _getRowUpperBound(int i) const;
+
+ virtual void _setObjCoeffs(ExprIterator, ExprIterator);
+ virtual void _getObjCoeffs(InsertIterator) const;
+
+ virtual void _setObjCoeff(int i, Value obj_coef);
+ virtual Value _getObjCoeff(int i) const;
+
+ virtual void _setSense(Sense sense);
+ virtual Sense _getSense() const;
+
+ virtual SolveExitStatus _solve();
+
+ virtual Value _getPrimal(int i) const;
+ virtual Value _getDual(int i) const;
+
+ virtual Value _getPrimalValue() const;
+
+ virtual Value _getPrimalRay(int i) const;
+ virtual Value _getDualRay(int i) const;
+
+ virtual VarStatus _getColStatus(int i) const;
+ virtual VarStatus _getRowStatus(int i) const;
+
+ virtual ProblemType _getPrimalType() const;
+ virtual ProblemType _getDualType() const;
+
+ virtual void _clear();
+
+ virtual void _messageLevel(MessageLevel);
+
+ public:
+
+ ///Solves LP with primal simplex method.
+ SolveExitStatus solvePrimal();
+
+ ///Solves LP with dual simplex method.
+ SolveExitStatus solveDual();
+
+ ///Solves LP with barrier method.
+ SolveExitStatus solveBarrier();
+
+ ///Returns the constraint identifier understood by CLP.
+ int clpRow(Row r) const { return rows(id(r)); }
+
+ ///Returns the variable identifier understood by CLP.
+ int clpCol(Col c) const { return cols(id(c)); }
+
+ };
+
+} //END OF NAMESPACE LEMON
+
+#endif //LEMON_CLP_H
+
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/color.cc b/extern/quadriflow/3rd/lemon-1.3.1/lemon/color.cc
new file mode 100644
index 00000000000..a49167b5cc7
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/color.cc
@@ -0,0 +1,44 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\file
+///\brief Color constants
+
+#include<lemon/color.h>
+
+namespace lemon {
+
+ const Color WHITE(1,1,1);
+
+ const Color BLACK(0,0,0);
+ const Color RED(1,0,0);
+ const Color GREEN(0,1,0);
+ const Color BLUE(0,0,1);
+ const Color YELLOW(1,1,0);
+ const Color MAGENTA(1,0,1);
+ const Color CYAN(0,1,1);
+
+ const Color GREY(0,0,0);
+ const Color DARK_RED(.5,0,0);
+ const Color DARK_GREEN(0,.5,0);
+ const Color DARK_BLUE(0,0,.5);
+ const Color DARK_YELLOW(.5,.5,0);
+ const Color DARK_MAGENTA(.5,0,.5);
+ const Color DARK_CYAN(0,.5,.5);
+
+} //namespace lemon
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/color.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/color.h
new file mode 100644
index 00000000000..02357910ff7
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/color.h
@@ -0,0 +1,204 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_COLOR_H
+#define LEMON_COLOR_H
+
+#include<vector>
+#include<lemon/math.h>
+#include<lemon/maps.h>
+
+
+///\ingroup misc
+///\file
+///\brief Tools to manage RGB colors.
+
+namespace lemon {
+
+
+ /// \addtogroup misc
+ /// @{
+
+ ///Data structure representing RGB colors.
+
+ ///Data structure representing RGB colors.
+ class Color
+ {
+ double _r,_g,_b;
+ public:
+ ///Default constructor
+ Color() {}
+ ///Constructor
+ Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
+ ///Set the red component
+ double & red() {return _r;}
+ ///Return the red component
+ const double & red() const {return _r;}
+ ///Set the green component
+ double & green() {return _g;}
+ ///Return the green component
+ const double & green() const {return _g;}
+ ///Set the blue component
+ double & blue() {return _b;}
+ ///Return the blue component
+ const double & blue() const {return _b;}
+ ///Set the color components
+ void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
+ };
+
+ /// White color constant
+ extern const Color WHITE;
+ /// Black color constant
+ extern const Color BLACK;
+ /// Red color constant
+ extern const Color RED;
+ /// Green color constant
+ extern const Color GREEN;
+ /// Blue color constant
+ extern const Color BLUE;
+ /// Yellow color constant
+ extern const Color YELLOW;
+ /// Magenta color constant
+ extern const Color MAGENTA;
+ /// Cyan color constant
+ extern const Color CYAN;
+ /// Grey color constant
+ extern const Color GREY;
+ /// Dark red color constant
+ extern const Color DARK_RED;
+ /// Dark green color constant
+ extern const Color DARK_GREEN;
+ /// Drak blue color constant
+ extern const Color DARK_BLUE;
+ /// Dark yellow color constant
+ extern const Color DARK_YELLOW;
+ /// Dark magenta color constant
+ extern const Color DARK_MAGENTA;
+ /// Dark cyan color constant
+ extern const Color DARK_CYAN;
+
+ ///Map <tt>int</tt>s to different <tt>Color</tt>s
+
+ ///This map assigns one of the predefined \ref Color "Color"s to
+ ///each <tt>int</tt>. It is possible to change the colors as well as
+ ///their number. The integer range is cyclically mapped to the
+ ///provided set of colors.
+ ///
+ ///This is a true \ref concepts::ReferenceMap "reference map", so
+ ///you can also change the actual colors.
+
+ class Palette : public MapBase<int,Color>
+ {
+ std::vector<Color> colors;
+ public:
+ ///Constructor
+
+ ///Constructor.
+ ///\param have_white Indicates whether white is among the
+ ///provided initial colors (\c true) or not (\c false). If it is true,
+ ///white will be assigned to \c 0.
+ ///\param num The number of the allocated colors. If it is \c -1,
+ ///the default color configuration is set up (26 color plus optionaly the
+ ///white). If \c num is less then 26/27 then the default color
+ ///list is cut. Otherwise the color list is filled repeatedly with
+ ///the default color list. (The colors can be changed later on.)
+ Palette(bool have_white=false,int num=-1)
+ {
+ if (num==0) return;
+ do {
+ if(have_white) colors.push_back(Color(1,1,1));
+
+ colors.push_back(Color(0,0,0));
+ colors.push_back(Color(1,0,0));
+ colors.push_back(Color(0,1,0));
+ colors.push_back(Color(0,0,1));
+ colors.push_back(Color(1,1,0));
+ colors.push_back(Color(1,0,1));
+ colors.push_back(Color(0,1,1));
+
+ colors.push_back(Color(.5,0,0));
+ colors.push_back(Color(0,.5,0));
+ colors.push_back(Color(0,0,.5));
+ colors.push_back(Color(.5,.5,0));
+ colors.push_back(Color(.5,0,.5));
+ colors.push_back(Color(0,.5,.5));
+
+ colors.push_back(Color(.5,.5,.5));
+ colors.push_back(Color(1,.5,.5));
+ colors.push_back(Color(.5,1,.5));
+ colors.push_back(Color(.5,.5,1));
+ colors.push_back(Color(1,1,.5));
+ colors.push_back(Color(1,.5,1));
+ colors.push_back(Color(.5,1,1));
+
+ colors.push_back(Color(1,.5,0));
+ colors.push_back(Color(.5,1,0));
+ colors.push_back(Color(1,0,.5));
+ colors.push_back(Color(0,1,.5));
+ colors.push_back(Color(0,.5,1));
+ colors.push_back(Color(.5,0,1));
+ } while(int(colors.size())<num);
+ if(num>=0) colors.resize(num);
+ }
+ ///\e
+ Color &operator[](int i)
+ {
+ return colors[i%colors.size()];
+ }
+ ///\e
+ const Color &operator[](int i) const
+ {
+ return colors[i%colors.size()];
+ }
+ ///\e
+ void set(int i,const Color &c)
+ {
+ colors[i%colors.size()]=c;
+ }
+ ///Adds a new color to the end of the color list.
+ void add(const Color &c)
+ {
+ colors.push_back(c);
+ }
+
+ ///Sets the number of the existing colors.
+ void resize(int s) { colors.resize(s);}
+ ///Returns the number of the existing colors.
+ int size() const { return int(colors.size());}
+ };
+
+ ///Returns a visibly distinct \ref Color
+
+ ///Returns a \ref Color which is as different from the given parameter
+ ///as it is possible.
+ inline Color distantColor(const Color &c)
+ {
+ return Color(c.red()<.5?1:0,c.green()<.5?1:0,c.blue()<.5?1:0);
+ }
+ ///Returns black for light colors and white for the dark ones.
+
+ ///Returns black for light colors and white for the dark ones.
+ inline Color distantBW(const Color &c){
+ return (.2125*c.red()+.7154*c.green()+.0721*c.blue())<.5 ? WHITE : BLACK;
+ }
+
+ /// @}
+
+} //END OF NAMESPACE LEMON
+
+#endif // LEMON_COLOR_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/concept_check.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/concept_check.h
new file mode 100644
index 00000000000..38355b0f228
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/concept_check.h
@@ -0,0 +1,77 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+// The contents of this file was inspired by the concept checking
+// utility of the BOOST library (http://www.boost.org).
+
+///\file
+///\brief Basic utilities for concept checking.
+///
+
+#ifndef LEMON_CONCEPT_CHECK_H
+#define LEMON_CONCEPT_CHECK_H
+
+namespace lemon {
+
+ /*
+ "inline" is used for ignore_unused_variable_warning()
+ and function_requires() to make sure there is no
+ overtarget with g++.
+ */
+
+ template <class T> inline void ignore_unused_variable_warning(const T&) { }
+ template <class T1, class T2>
+ inline void ignore_unused_variable_warning(const T1&, const T2&) { }
+ template <class T1, class T2, class T3>
+ inline void ignore_unused_variable_warning(const T1&, const T2&,
+ const T3&) { }
+ template <class T1, class T2, class T3, class T4>
+ inline void ignore_unused_variable_warning(const T1&, const T2&,
+ const T3&, const T4&) { }
+ template <class T1, class T2, class T3, class T4, class T5>
+ inline void ignore_unused_variable_warning(const T1&, const T2&,
+ const T3&, const T4&,
+ const T5&) { }
+ template <class T1, class T2, class T3, class T4, class T5, class T6>
+ inline void ignore_unused_variable_warning(const T1&, const T2&,
+ const T3&, const T4&,
+ const T5&, const T6&) { }
+
+ ///\e
+ template <class Concept>
+ inline void function_requires()
+ {
+#if !defined(NDEBUG)
+ void (Concept::*x)() = & Concept::constraints;
+ ::lemon::ignore_unused_variable_warning(x);
+#endif
+ }
+
+ ///\e
+ template <typename Concept, typename Type>
+ inline void checkConcept() {
+#if !defined(NDEBUG)
+ typedef typename Concept::template Constraints<Type> ConceptCheck;
+ void (ConceptCheck::*x)() = & ConceptCheck::constraints;
+ ::lemon::ignore_unused_variable_warning(x);
+#endif
+ }
+
+} // namespace lemon
+
+#endif // LEMON_CONCEPT_CHECK_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/bpgraph.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/bpgraph.h
new file mode 100644
index 00000000000..2ebdeaf8b2f
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/bpgraph.h
@@ -0,0 +1,1029 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\ingroup graph_concepts
+///\file
+///\brief The concept of undirected graphs.
+
+#ifndef LEMON_CONCEPTS_BPGRAPH_H
+#define LEMON_CONCEPTS_BPGRAPH_H
+
+#include <lemon/concepts/graph_components.h>
+#include <lemon/concepts/maps.h>
+#include <lemon/concept_check.h>
+#include <lemon/core.h>
+
+namespace lemon {
+ namespace concepts {
+
+ /// \ingroup graph_concepts
+ ///
+ /// \brief Class describing the concept of undirected bipartite graphs.
+ ///
+ /// This class describes the common interface of all undirected
+ /// bipartite graphs.
+ ///
+ /// Like all concept classes, it only provides an interface
+ /// without any sensible implementation. So any general algorithm for
+ /// undirected bipartite graphs should compile with this class,
+ /// but it will not run properly, of course.
+ /// An actual graph implementation like \ref ListBpGraph or
+ /// \ref SmartBpGraph may have additional functionality.
+ ///
+ /// The bipartite graphs also fulfill the concept of \ref Graph
+ /// "undirected graphs". Bipartite graphs provide a bipartition of
+ /// the node set, namely a red and blue set of the nodes. The
+ /// nodes can be iterated with the RedNodeIt and BlueNodeIt in the
+ /// two node sets. With RedNodeMap and BlueNodeMap values can be
+ /// assigned to the nodes in the two sets.
+ ///
+ /// The edges of the graph cannot connect two nodes of the same
+ /// set. The edges inherent orientation is from the red nodes to
+ /// the blue nodes.
+ ///
+ /// \sa Graph
+ class BpGraph {
+ private:
+ /// BpGraphs are \e not copy constructible. Use bpGraphCopy instead.
+ BpGraph(const BpGraph&) {}
+ /// \brief Assignment of a graph to another one is \e not allowed.
+ /// Use bpGraphCopy instead.
+ void operator=(const BpGraph&) {}
+
+ public:
+ /// Default constructor.
+ BpGraph() {}
+
+ /// \brief Undirected graphs should be tagged with \c UndirectedTag.
+ ///
+ /// Undirected graphs should be tagged with \c UndirectedTag.
+ ///
+ /// This tag helps the \c enable_if technics to make compile time
+ /// specializations for undirected graphs.
+ typedef True UndirectedTag;
+
+ /// The node type of the graph
+
+ /// This class identifies a node of the graph. It also serves
+ /// as a base class of the node iterators,
+ /// thus they convert to this type.
+ class Node {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the object to an undefined value.
+ Node() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ Node(const Node&) { }
+
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the object to be invalid.
+ /// \sa Invalid for more details.
+ Node(Invalid) { }
+ /// Equality operator
+
+ /// Equality operator.
+ ///
+ /// Two iterators are equal if and only if they point to the
+ /// same object or both are \c INVALID.
+ bool operator==(Node) const { return true; }
+
+ /// Inequality operator
+
+ /// Inequality operator.
+ bool operator!=(Node) const { return true; }
+
+ /// Artificial ordering operator.
+
+ /// Artificial ordering operator.
+ ///
+ /// \note This operator only has to define some strict ordering of
+ /// the items; this order has nothing to do with the iteration
+ /// ordering of the items.
+ bool operator<(Node) const { return false; }
+
+ };
+
+ /// Class to represent red nodes.
+
+ /// This class represents the red nodes of the graph. It does
+ /// not supposed to be used directly, because the nodes can be
+ /// represented as Node instances. This class can be used as
+ /// template parameter for special map classes.
+ class RedNode : public Node {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the object to an undefined value.
+ RedNode() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ RedNode(const RedNode&) : Node() { }
+
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the object to be invalid.
+ /// \sa Invalid for more details.
+ RedNode(Invalid) { }
+
+ };
+
+ /// Class to represent blue nodes.
+
+ /// This class represents the blue nodes of the graph. It does
+ /// not supposed to be used directly, because the nodes can be
+ /// represented as Node instances. This class can be used as
+ /// template parameter for special map classes.
+ class BlueNode : public Node {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the object to an undefined value.
+ BlueNode() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ BlueNode(const BlueNode&) : Node() { }
+
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the object to be invalid.
+ /// \sa Invalid for more details.
+ BlueNode(Invalid) { }
+
+ };
+
+ /// Iterator class for the red nodes.
+
+ /// This iterator goes through each red node of the graph.
+ /// Its usage is quite simple, for example, you can count the number
+ /// of red nodes in a graph \c g of type \c %BpGraph like this:
+ ///\code
+ /// int count=0;
+ /// for (BpGraph::RedNodeIt n(g); n!=INVALID; ++n) ++count;
+ ///\endcode
+ class RedNodeIt : public RedNode {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the iterator to an undefined value.
+ RedNodeIt() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ RedNodeIt(const RedNodeIt& n) : RedNode(n) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ RedNodeIt(Invalid) { }
+ /// Sets the iterator to the first red node.
+
+ /// Sets the iterator to the first red node of the given
+ /// digraph.
+ explicit RedNodeIt(const BpGraph&) { }
+ /// Sets the iterator to the given red node.
+
+ /// Sets the iterator to the given red node of the given
+ /// digraph.
+ RedNodeIt(const BpGraph&, const RedNode&) { }
+ /// Next node.
+
+ /// Assign the iterator to the next red node.
+ ///
+ RedNodeIt& operator++() { return *this; }
+ };
+
+ /// Iterator class for the blue nodes.
+
+ /// This iterator goes through each blue node of the graph.
+ /// Its usage is quite simple, for example, you can count the number
+ /// of blue nodes in a graph \c g of type \c %BpGraph like this:
+ ///\code
+ /// int count=0;
+ /// for (BpGraph::BlueNodeIt n(g); n!=INVALID; ++n) ++count;
+ ///\endcode
+ class BlueNodeIt : public BlueNode {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the iterator to an undefined value.
+ BlueNodeIt() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ BlueNodeIt(const BlueNodeIt& n) : BlueNode(n) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ BlueNodeIt(Invalid) { }
+ /// Sets the iterator to the first blue node.
+
+ /// Sets the iterator to the first blue node of the given
+ /// digraph.
+ explicit BlueNodeIt(const BpGraph&) { }
+ /// Sets the iterator to the given blue node.
+
+ /// Sets the iterator to the given blue node of the given
+ /// digraph.
+ BlueNodeIt(const BpGraph&, const BlueNode&) { }
+ /// Next node.
+
+ /// Assign the iterator to the next blue node.
+ ///
+ BlueNodeIt& operator++() { return *this; }
+ };
+
+ /// Iterator class for the nodes.
+
+ /// This iterator goes through each node of the graph.
+ /// Its usage is quite simple, for example, you can count the number
+ /// of nodes in a graph \c g of type \c %BpGraph like this:
+ ///\code
+ /// int count=0;
+ /// for (BpGraph::NodeIt n(g); n!=INVALID; ++n) ++count;
+ ///\endcode
+ class NodeIt : public Node {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the iterator to an undefined value.
+ NodeIt() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ NodeIt(const NodeIt& n) : Node(n) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ NodeIt(Invalid) { }
+ /// Sets the iterator to the first node.
+
+ /// Sets the iterator to the first node of the given digraph.
+ ///
+ explicit NodeIt(const BpGraph&) { }
+ /// Sets the iterator to the given node.
+
+ /// Sets the iterator to the given node of the given digraph.
+ ///
+ NodeIt(const BpGraph&, const Node&) { }
+ /// Next node.
+
+ /// Assign the iterator to the next node.
+ ///
+ NodeIt& operator++() { return *this; }
+ };
+
+
+ /// The edge type of the graph
+
+ /// This class identifies an edge of the graph. It also serves
+ /// as a base class of the edge iterators,
+ /// thus they will convert to this type.
+ class Edge {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the object to an undefined value.
+ Edge() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ Edge(const Edge&) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the object to be invalid.
+ /// \sa Invalid for more details.
+ Edge(Invalid) { }
+ /// Equality operator
+
+ /// Equality operator.
+ ///
+ /// Two iterators are equal if and only if they point to the
+ /// same object or both are \c INVALID.
+ bool operator==(Edge) const { return true; }
+ /// Inequality operator
+
+ /// Inequality operator.
+ bool operator!=(Edge) const { return true; }
+
+ /// Artificial ordering operator.
+
+ /// Artificial ordering operator.
+ ///
+ /// \note This operator only has to define some strict ordering of
+ /// the edges; this order has nothing to do with the iteration
+ /// ordering of the edges.
+ bool operator<(Edge) const { return false; }
+ };
+
+ /// Iterator class for the edges.
+
+ /// This iterator goes through each edge of the graph.
+ /// Its usage is quite simple, for example, you can count the number
+ /// of edges in a graph \c g of type \c %BpGraph as follows:
+ ///\code
+ /// int count=0;
+ /// for(BpGraph::EdgeIt e(g); e!=INVALID; ++e) ++count;
+ ///\endcode
+ class EdgeIt : public Edge {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the iterator to an undefined value.
+ EdgeIt() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ EdgeIt(const EdgeIt& e) : Edge(e) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ EdgeIt(Invalid) { }
+ /// Sets the iterator to the first edge.
+
+ /// Sets the iterator to the first edge of the given graph.
+ ///
+ explicit EdgeIt(const BpGraph&) { }
+ /// Sets the iterator to the given edge.
+
+ /// Sets the iterator to the given edge of the given graph.
+ ///
+ EdgeIt(const BpGraph&, const Edge&) { }
+ /// Next edge
+
+ /// Assign the iterator to the next edge.
+ ///
+ EdgeIt& operator++() { return *this; }
+ };
+
+ /// Iterator class for the incident edges of a node.
+
+ /// This iterator goes trough the incident undirected edges
+ /// of a certain node of a graph.
+ /// Its usage is quite simple, for example, you can compute the
+ /// degree (i.e. the number of incident edges) of a node \c n
+ /// in a graph \c g of type \c %BpGraph as follows.
+ ///
+ ///\code
+ /// int count=0;
+ /// for(BpGraph::IncEdgeIt e(g, n); e!=INVALID; ++e) ++count;
+ ///\endcode
+ ///
+ /// \warning Loop edges will be iterated twice.
+ class IncEdgeIt : public Edge {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the iterator to an undefined value.
+ IncEdgeIt() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ IncEdgeIt(const IncEdgeIt& e) : Edge(e) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ IncEdgeIt(Invalid) { }
+ /// Sets the iterator to the first incident edge.
+
+ /// Sets the iterator to the first incident edge of the given node.
+ ///
+ IncEdgeIt(const BpGraph&, const Node&) { }
+ /// Sets the iterator to the given edge.
+
+ /// Sets the iterator to the given edge of the given graph.
+ ///
+ IncEdgeIt(const BpGraph&, const Edge&) { }
+ /// Next incident edge
+
+ /// Assign the iterator to the next incident edge
+ /// of the corresponding node.
+ IncEdgeIt& operator++() { return *this; }
+ };
+
+ /// The arc type of the graph
+
+ /// This class identifies a directed arc of the graph. It also serves
+ /// as a base class of the arc iterators,
+ /// thus they will convert to this type.
+ class Arc {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the object to an undefined value.
+ Arc() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ Arc(const Arc&) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the object to be invalid.
+ /// \sa Invalid for more details.
+ Arc(Invalid) { }
+ /// Equality operator
+
+ /// Equality operator.
+ ///
+ /// Two iterators are equal if and only if they point to the
+ /// same object or both are \c INVALID.
+ bool operator==(Arc) const { return true; }
+ /// Inequality operator
+
+ /// Inequality operator.
+ bool operator!=(Arc) const { return true; }
+
+ /// Artificial ordering operator.
+
+ /// Artificial ordering operator.
+ ///
+ /// \note This operator only has to define some strict ordering of
+ /// the arcs; this order has nothing to do with the iteration
+ /// ordering of the arcs.
+ bool operator<(Arc) const { return false; }
+
+ /// Converison to \c Edge
+
+ /// Converison to \c Edge.
+ ///
+ operator Edge() const { return Edge(); }
+ };
+
+ /// Iterator class for the arcs.
+
+ /// This iterator goes through each directed arc of the graph.
+ /// Its usage is quite simple, for example, you can count the number
+ /// of arcs in a graph \c g of type \c %BpGraph as follows:
+ ///\code
+ /// int count=0;
+ /// for(BpGraph::ArcIt a(g); a!=INVALID; ++a) ++count;
+ ///\endcode
+ class ArcIt : public Arc {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the iterator to an undefined value.
+ ArcIt() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ ArcIt(const ArcIt& e) : Arc(e) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ ArcIt(Invalid) { }
+ /// Sets the iterator to the first arc.
+
+ /// Sets the iterator to the first arc of the given graph.
+ ///
+ explicit ArcIt(const BpGraph &g)
+ {
+ ::lemon::ignore_unused_variable_warning(g);
+ }
+ /// Sets the iterator to the given arc.
+
+ /// Sets the iterator to the given arc of the given graph.
+ ///
+ ArcIt(const BpGraph&, const Arc&) { }
+ /// Next arc
+
+ /// Assign the iterator to the next arc.
+ ///
+ ArcIt& operator++() { return *this; }
+ };
+
+ /// Iterator class for the outgoing arcs of a node.
+
+ /// This iterator goes trough the \e outgoing directed arcs of a
+ /// certain node of a graph.
+ /// Its usage is quite simple, for example, you can count the number
+ /// of outgoing arcs of a node \c n
+ /// in a graph \c g of type \c %BpGraph as follows.
+ ///\code
+ /// int count=0;
+ /// for (Digraph::OutArcIt a(g, n); a!=INVALID; ++a) ++count;
+ ///\endcode
+ class OutArcIt : public Arc {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the iterator to an undefined value.
+ OutArcIt() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ OutArcIt(const OutArcIt& e) : Arc(e) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ OutArcIt(Invalid) { }
+ /// Sets the iterator to the first outgoing arc.
+
+ /// Sets the iterator to the first outgoing arc of the given node.
+ ///
+ OutArcIt(const BpGraph& n, const Node& g) {
+ ::lemon::ignore_unused_variable_warning(n);
+ ::lemon::ignore_unused_variable_warning(g);
+ }
+ /// Sets the iterator to the given arc.
+
+ /// Sets the iterator to the given arc of the given graph.
+ ///
+ OutArcIt(const BpGraph&, const Arc&) { }
+ /// Next outgoing arc
+
+ /// Assign the iterator to the next
+ /// outgoing arc of the corresponding node.
+ OutArcIt& operator++() { return *this; }
+ };
+
+ /// Iterator class for the incoming arcs of a node.
+
+ /// This iterator goes trough the \e incoming directed arcs of a
+ /// certain node of a graph.
+ /// Its usage is quite simple, for example, you can count the number
+ /// of incoming arcs of a node \c n
+ /// in a graph \c g of type \c %BpGraph as follows.
+ ///\code
+ /// int count=0;
+ /// for (Digraph::InArcIt a(g, n); a!=INVALID; ++a) ++count;
+ ///\endcode
+ class InArcIt : public Arc {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the iterator to an undefined value.
+ InArcIt() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ InArcIt(const InArcIt& e) : Arc(e) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ InArcIt(Invalid) { }
+ /// Sets the iterator to the first incoming arc.
+
+ /// Sets the iterator to the first incoming arc of the given node.
+ ///
+ InArcIt(const BpGraph& g, const Node& n) {
+ ::lemon::ignore_unused_variable_warning(n);
+ ::lemon::ignore_unused_variable_warning(g);
+ }
+ /// Sets the iterator to the given arc.
+
+ /// Sets the iterator to the given arc of the given graph.
+ ///
+ InArcIt(const BpGraph&, const Arc&) { }
+ /// Next incoming arc
+
+ /// Assign the iterator to the next
+ /// incoming arc of the corresponding node.
+ InArcIt& operator++() { return *this; }
+ };
+
+ /// \brief Standard graph map type for the nodes.
+ ///
+ /// Standard graph map type for the nodes.
+ /// It conforms to the ReferenceMap concept.
+ template<class T>
+ class NodeMap : public ReferenceMap<Node, T, T&, const T&>
+ {
+ public:
+
+ /// Constructor
+ explicit NodeMap(const BpGraph&) { }
+ /// Constructor with given initial value
+ NodeMap(const BpGraph&, T) { }
+
+ private:
+ ///Copy constructor
+ NodeMap(const NodeMap& nm) :
+ ReferenceMap<Node, T, T&, const T&>(nm) { }
+ ///Assignment operator
+ template <typename CMap>
+ NodeMap& operator=(const CMap&) {
+ checkConcept<ReadMap<Node, T>, CMap>();
+ return *this;
+ }
+ };
+
+ /// \brief Standard graph map type for the red nodes.
+ ///
+ /// Standard graph map type for the red nodes.
+ /// It conforms to the ReferenceMap concept.
+ template<class T>
+ class RedNodeMap : public ReferenceMap<Node, T, T&, const T&>
+ {
+ public:
+
+ /// Constructor
+ explicit RedNodeMap(const BpGraph&) { }
+ /// Constructor with given initial value
+ RedNodeMap(const BpGraph&, T) { }
+
+ private:
+ ///Copy constructor
+ RedNodeMap(const RedNodeMap& nm) :
+ ReferenceMap<Node, T, T&, const T&>(nm) { }
+ ///Assignment operator
+ template <typename CMap>
+ RedNodeMap& operator=(const CMap&) {
+ checkConcept<ReadMap<Node, T>, CMap>();
+ return *this;
+ }
+ };
+
+ /// \brief Standard graph map type for the blue nodes.
+ ///
+ /// Standard graph map type for the blue nodes.
+ /// It conforms to the ReferenceMap concept.
+ template<class T>
+ class BlueNodeMap : public ReferenceMap<Node, T, T&, const T&>
+ {
+ public:
+
+ /// Constructor
+ explicit BlueNodeMap(const BpGraph&) { }
+ /// Constructor with given initial value
+ BlueNodeMap(const BpGraph&, T) { }
+
+ private:
+ ///Copy constructor
+ BlueNodeMap(const BlueNodeMap& nm) :
+ ReferenceMap<Node, T, T&, const T&>(nm) { }
+ ///Assignment operator
+ template <typename CMap>
+ BlueNodeMap& operator=(const CMap&) {
+ checkConcept<ReadMap<Node, T>, CMap>();
+ return *this;
+ }
+ };
+
+ /// \brief Standard graph map type for the arcs.
+ ///
+ /// Standard graph map type for the arcs.
+ /// It conforms to the ReferenceMap concept.
+ template<class T>
+ class ArcMap : public ReferenceMap<Arc, T, T&, const T&>
+ {
+ public:
+
+ /// Constructor
+ explicit ArcMap(const BpGraph&) { }
+ /// Constructor with given initial value
+ ArcMap(const BpGraph&, T) { }
+
+ private:
+ ///Copy constructor
+ ArcMap(const ArcMap& em) :
+ ReferenceMap<Arc, T, T&, const T&>(em) { }
+ ///Assignment operator
+ template <typename CMap>
+ ArcMap& operator=(const CMap&) {
+ checkConcept<ReadMap<Arc, T>, CMap>();
+ return *this;
+ }
+ };
+
+ /// \brief Standard graph map type for the edges.
+ ///
+ /// Standard graph map type for the edges.
+ /// It conforms to the ReferenceMap concept.
+ template<class T>
+ class EdgeMap : public ReferenceMap<Edge, T, T&, const T&>
+ {
+ public:
+
+ /// Constructor
+ explicit EdgeMap(const BpGraph&) { }
+ /// Constructor with given initial value
+ EdgeMap(const BpGraph&, T) { }
+
+ private:
+ ///Copy constructor
+ EdgeMap(const EdgeMap& em) :
+ ReferenceMap<Edge, T, T&, const T&>(em) {}
+ ///Assignment operator
+ template <typename CMap>
+ EdgeMap& operator=(const CMap&) {
+ checkConcept<ReadMap<Edge, T>, CMap>();
+ return *this;
+ }
+ };
+
+ /// \brief Gives back %true for red nodes.
+ ///
+ /// Gives back %true for red nodes.
+ bool red(const Node&) const { return true; }
+
+ /// \brief Gives back %true for blue nodes.
+ ///
+ /// Gives back %true for blue nodes.
+ bool blue(const Node&) const { return true; }
+
+ /// \brief Converts the node to red node object.
+ ///
+ /// This function converts unsafely the node to red node
+ /// object. It should be called only if the node is from the red
+ /// partition or INVALID.
+ RedNode asRedNodeUnsafe(const Node&) const { return RedNode(); }
+
+ /// \brief Converts the node to blue node object.
+ ///
+ /// This function converts unsafely the node to blue node
+ /// object. It should be called only if the node is from the red
+ /// partition or INVALID.
+ BlueNode asBlueNodeUnsafe(const Node&) const { return BlueNode(); }
+
+ /// \brief Converts the node to red node object.
+ ///
+ /// This function converts safely the node to red node
+ /// object. If the node is not from the red partition, then it
+ /// returns INVALID.
+ RedNode asRedNode(const Node&) const { return RedNode(); }
+
+ /// \brief Converts the node to blue node object.
+ ///
+ /// This function converts unsafely the node to blue node
+ /// object. If the node is not from the blue partition, then it
+ /// returns INVALID.
+ BlueNode asBlueNode(const Node&) const { return BlueNode(); }
+
+ /// \brief Gives back the red end node of the edge.
+ ///
+ /// Gives back the red end node of the edge.
+ RedNode redNode(const Edge&) const { return RedNode(); }
+
+ /// \brief Gives back the blue end node of the edge.
+ ///
+ /// Gives back the blue end node of the edge.
+ BlueNode blueNode(const Edge&) const { return BlueNode(); }
+
+ /// \brief The first node of the edge.
+ ///
+ /// It is a synonim for the \c redNode().
+ Node u(Edge) const { return INVALID; }
+
+ /// \brief The second node of the edge.
+ ///
+ /// It is a synonim for the \c blueNode().
+ Node v(Edge) const { return INVALID; }
+
+ /// \brief The source node of the arc.
+ ///
+ /// Returns the source node of the given arc.
+ Node source(Arc) const { return INVALID; }
+
+ /// \brief The target node of the arc.
+ ///
+ /// Returns the target node of the given arc.
+ Node target(Arc) const { return INVALID; }
+
+ /// \brief The ID of the node.
+ ///
+ /// Returns the ID of the given node.
+ int id(Node) const { return -1; }
+
+ /// \brief The red ID of the node.
+ ///
+ /// Returns the red ID of the given node.
+ int id(RedNode) const { return -1; }
+
+ /// \brief The blue ID of the node.
+ ///
+ /// Returns the blue ID of the given node.
+ int id(BlueNode) const { return -1; }
+
+ /// \brief The ID of the edge.
+ ///
+ /// Returns the ID of the given edge.
+ int id(Edge) const { return -1; }
+
+ /// \brief The ID of the arc.
+ ///
+ /// Returns the ID of the given arc.
+ int id(Arc) const { return -1; }
+
+ /// \brief The node with the given ID.
+ ///
+ /// Returns the node with the given ID.
+ /// \pre The argument should be a valid node ID in the graph.
+ Node nodeFromId(int) const { return INVALID; }
+
+ /// \brief The edge with the given ID.
+ ///
+ /// Returns the edge with the given ID.
+ /// \pre The argument should be a valid edge ID in the graph.
+ Edge edgeFromId(int) const { return INVALID; }
+
+ /// \brief The arc with the given ID.
+ ///
+ /// Returns the arc with the given ID.
+ /// \pre The argument should be a valid arc ID in the graph.
+ Arc arcFromId(int) const { return INVALID; }
+
+ /// \brief An upper bound on the node IDs.
+ ///
+ /// Returns an upper bound on the node IDs.
+ int maxNodeId() const { return -1; }
+
+ /// \brief An upper bound on the red IDs.
+ ///
+ /// Returns an upper bound on the red IDs.
+ int maxRedId() const { return -1; }
+
+ /// \brief An upper bound on the blue IDs.
+ ///
+ /// Returns an upper bound on the blue IDs.
+ int maxBlueId() const { return -1; }
+
+ /// \brief An upper bound on the edge IDs.
+ ///
+ /// Returns an upper bound on the edge IDs.
+ int maxEdgeId() const { return -1; }
+
+ /// \brief An upper bound on the arc IDs.
+ ///
+ /// Returns an upper bound on the arc IDs.
+ int maxArcId() const { return -1; }
+
+ /// \brief The direction of the arc.
+ ///
+ /// Returns \c true if the given arc goes from a red node to a blue node.
+ bool direction(Arc) const { return true; }
+
+ /// \brief Direct the edge.
+ ///
+ /// Direct the given edge. The returned arc
+ /// represents the given edge and its direction comes
+ /// from the bool parameter. If it is \c true, then the source of the node
+ /// will be a red node.
+ Arc direct(Edge, bool) const {
+ return INVALID;
+ }
+
+ /// \brief Direct the edge.
+ ///
+ /// Direct the given edge. The returned arc represents the given
+ /// edge and its source node is the given node.
+ Arc direct(Edge, Node) const {
+ return INVALID;
+ }
+
+ /// \brief The oppositely directed arc.
+ ///
+ /// Returns the oppositely directed arc representing the same edge.
+ Arc oppositeArc(Arc) const { return INVALID; }
+
+ /// \brief The opposite node on the edge.
+ ///
+ /// Returns the opposite node on the given edge.
+ Node oppositeNode(Node, Edge) const { return INVALID; }
+
+ void first(Node&) const {}
+ void next(Node&) const {}
+
+ void firstRed(RedNode&) const {}
+ void nextRed(RedNode&) const {}
+
+ void firstBlue(BlueNode&) const {}
+ void nextBlue(BlueNode&) const {}
+
+ void first(Edge&) const {}
+ void next(Edge&) const {}
+
+ void first(Arc&) const {}
+ void next(Arc&) const {}
+
+ void firstOut(Arc&, Node) const {}
+ void nextOut(Arc&) const {}
+
+ void firstIn(Arc&, Node) const {}
+ void nextIn(Arc&) const {}
+
+ void firstInc(Edge &, bool &, const Node &) const {}
+ void nextInc(Edge &, bool &) const {}
+
+ // The second parameter is dummy.
+ Node fromId(int, Node) const { return INVALID; }
+ // The second parameter is dummy.
+ Edge fromId(int, Edge) const { return INVALID; }
+ // The second parameter is dummy.
+ Arc fromId(int, Arc) const { return INVALID; }
+
+ // Dummy parameter.
+ int maxId(Node) const { return -1; }
+ // Dummy parameter.
+ int maxId(RedNode) const { return -1; }
+ // Dummy parameter.
+ int maxId(BlueNode) const { return -1; }
+ // Dummy parameter.
+ int maxId(Edge) const { return -1; }
+ // Dummy parameter.
+ int maxId(Arc) const { return -1; }
+
+ /// \brief The base node of the iterator.
+ ///
+ /// Returns the base node of the given incident edge iterator.
+ Node baseNode(IncEdgeIt) const { return INVALID; }
+
+ /// \brief The running node of the iterator.
+ ///
+ /// Returns the running node of the given incident edge iterator.
+ Node runningNode(IncEdgeIt) const { return INVALID; }
+
+ /// \brief The base node of the iterator.
+ ///
+ /// Returns the base node of the given outgoing arc iterator
+ /// (i.e. the source node of the corresponding arc).
+ Node baseNode(OutArcIt) const { return INVALID; }
+
+ /// \brief The running node of the iterator.
+ ///
+ /// Returns the running node of the given outgoing arc iterator
+ /// (i.e. the target node of the corresponding arc).
+ Node runningNode(OutArcIt) const { return INVALID; }
+
+ /// \brief The base node of the iterator.
+ ///
+ /// Returns the base node of the given incoming arc iterator
+ /// (i.e. the target node of the corresponding arc).
+ Node baseNode(InArcIt) const { return INVALID; }
+
+ /// \brief The running node of the iterator.
+ ///
+ /// Returns the running node of the given incoming arc iterator
+ /// (i.e. the source node of the corresponding arc).
+ Node runningNode(InArcIt) const { return INVALID; }
+
+ template <typename _BpGraph>
+ struct Constraints {
+ void constraints() {
+ checkConcept<BaseBpGraphComponent, _BpGraph>();
+ checkConcept<IterableBpGraphComponent<>, _BpGraph>();
+ checkConcept<IDableBpGraphComponent<>, _BpGraph>();
+ checkConcept<MappableBpGraphComponent<>, _BpGraph>();
+ }
+ };
+
+ };
+
+ }
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/digraph.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/digraph.h
new file mode 100644
index 00000000000..dc3c36bbbc0
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/digraph.h
@@ -0,0 +1,491 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_CONCEPTS_DIGRAPH_H
+#define LEMON_CONCEPTS_DIGRAPH_H
+
+///\ingroup graph_concepts
+///\file
+///\brief The concept of directed graphs.
+
+#include <lemon/core.h>
+#include <lemon/concepts/maps.h>
+#include <lemon/concept_check.h>
+#include <lemon/concepts/graph_components.h>
+
+namespace lemon {
+ namespace concepts {
+
+ /// \ingroup graph_concepts
+ ///
+ /// \brief Class describing the concept of directed graphs.
+ ///
+ /// This class describes the common interface of all directed
+ /// graphs (digraphs).
+ ///
+ /// Like all concept classes, it only provides an interface
+ /// without any sensible implementation. So any general algorithm for
+ /// directed graphs should compile with this class, but it will not
+ /// run properly, of course.
+ /// An actual digraph implementation like \ref ListDigraph or
+ /// \ref SmartDigraph may have additional functionality.
+ ///
+ /// \sa Graph
+ class Digraph {
+ private:
+ /// Diraphs are \e not copy constructible. Use DigraphCopy instead.
+ Digraph(const Digraph &) {}
+ /// \brief Assignment of a digraph to another one is \e not allowed.
+ /// Use DigraphCopy instead.
+ void operator=(const Digraph &) {}
+
+ public:
+ /// Default constructor.
+ Digraph() { }
+
+ /// The node type of the digraph
+
+ /// This class identifies a node of the digraph. It also serves
+ /// as a base class of the node iterators,
+ /// thus they convert to this type.
+ class Node {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the object to an undefined value.
+ Node() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ Node(const Node&) { }
+
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the object to be invalid.
+ /// \sa Invalid for more details.
+ Node(Invalid) { }
+ /// Equality operator
+
+ /// Equality operator.
+ ///
+ /// Two iterators are equal if and only if they point to the
+ /// same object or both are \c INVALID.
+ bool operator==(Node) const { return true; }
+
+ /// Inequality operator
+
+ /// Inequality operator.
+ bool operator!=(Node) const { return true; }
+
+ /// Artificial ordering operator.
+
+ /// Artificial ordering operator.
+ ///
+ /// \note This operator only has to define some strict ordering of
+ /// the nodes; this order has nothing to do with the iteration
+ /// ordering of the nodes.
+ bool operator<(Node) const { return false; }
+ };
+
+ /// Iterator class for the nodes.
+
+ /// This iterator goes through each node of the digraph.
+ /// Its usage is quite simple, for example, you can count the number
+ /// of nodes in a digraph \c g of type \c %Digraph like this:
+ ///\code
+ /// int count=0;
+ /// for (Digraph::NodeIt n(g); n!=INVALID; ++n) ++count;
+ ///\endcode
+ class NodeIt : public Node {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the iterator to an undefined value.
+ NodeIt() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ NodeIt(const NodeIt& n) : Node(n) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ NodeIt(Invalid) { }
+ /// Sets the iterator to the first node.
+
+ /// Sets the iterator to the first node of the given digraph.
+ ///
+ explicit NodeIt(const Digraph&) { }
+ /// Sets the iterator to the given node.
+
+ /// Sets the iterator to the given node of the given digraph.
+ ///
+ NodeIt(const Digraph&, const Node&) { }
+ /// Next node.
+
+ /// Assign the iterator to the next node.
+ ///
+ NodeIt& operator++() { return *this; }
+ };
+
+
+ /// The arc type of the digraph
+
+ /// This class identifies an arc of the digraph. It also serves
+ /// as a base class of the arc iterators,
+ /// thus they will convert to this type.
+ class Arc {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the object to an undefined value.
+ Arc() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ Arc(const Arc&) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the object to be invalid.
+ /// \sa Invalid for more details.
+ Arc(Invalid) { }
+ /// Equality operator
+
+ /// Equality operator.
+ ///
+ /// Two iterators are equal if and only if they point to the
+ /// same object or both are \c INVALID.
+ bool operator==(Arc) const { return true; }
+ /// Inequality operator
+
+ /// Inequality operator.
+ bool operator!=(Arc) const { return true; }
+
+ /// Artificial ordering operator.
+
+ /// Artificial ordering operator.
+ ///
+ /// \note This operator only has to define some strict ordering of
+ /// the arcs; this order has nothing to do with the iteration
+ /// ordering of the arcs.
+ bool operator<(Arc) const { return false; }
+ };
+
+ /// Iterator class for the outgoing arcs of a node.
+
+ /// This iterator goes trough the \e outgoing arcs of a certain node
+ /// of a digraph.
+ /// Its usage is quite simple, for example, you can count the number
+ /// of outgoing arcs of a node \c n
+ /// in a digraph \c g of type \c %Digraph as follows.
+ ///\code
+ /// int count=0;
+ /// for (Digraph::OutArcIt a(g, n); a!=INVALID; ++a) ++count;
+ ///\endcode
+ class OutArcIt : public Arc {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the iterator to an undefined value.
+ OutArcIt() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ OutArcIt(const OutArcIt& e) : Arc(e) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ OutArcIt(Invalid) { }
+ /// Sets the iterator to the first outgoing arc.
+
+ /// Sets the iterator to the first outgoing arc of the given node.
+ ///
+ OutArcIt(const Digraph&, const Node&) { }
+ /// Sets the iterator to the given arc.
+
+ /// Sets the iterator to the given arc of the given digraph.
+ ///
+ OutArcIt(const Digraph&, const Arc&) { }
+ /// Next outgoing arc
+
+ /// Assign the iterator to the next
+ /// outgoing arc of the corresponding node.
+ OutArcIt& operator++() { return *this; }
+ };
+
+ /// Iterator class for the incoming arcs of a node.
+
+ /// This iterator goes trough the \e incoming arcs of a certain node
+ /// of a digraph.
+ /// Its usage is quite simple, for example, you can count the number
+ /// of incoming arcs of a node \c n
+ /// in a digraph \c g of type \c %Digraph as follows.
+ ///\code
+ /// int count=0;
+ /// for(Digraph::InArcIt a(g, n); a!=INVALID; ++a) ++count;
+ ///\endcode
+ class InArcIt : public Arc {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the iterator to an undefined value.
+ InArcIt() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ InArcIt(const InArcIt& e) : Arc(e) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ InArcIt(Invalid) { }
+ /// Sets the iterator to the first incoming arc.
+
+ /// Sets the iterator to the first incoming arc of the given node.
+ ///
+ InArcIt(const Digraph&, const Node&) { }
+ /// Sets the iterator to the given arc.
+
+ /// Sets the iterator to the given arc of the given digraph.
+ ///
+ InArcIt(const Digraph&, const Arc&) { }
+ /// Next incoming arc
+
+ /// Assign the iterator to the next
+ /// incoming arc of the corresponding node.
+ InArcIt& operator++() { return *this; }
+ };
+
+ /// Iterator class for the arcs.
+
+ /// This iterator goes through each arc of the digraph.
+ /// Its usage is quite simple, for example, you can count the number
+ /// of arcs in a digraph \c g of type \c %Digraph as follows:
+ ///\code
+ /// int count=0;
+ /// for(Digraph::ArcIt a(g); a!=INVALID; ++a) ++count;
+ ///\endcode
+ class ArcIt : public Arc {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the iterator to an undefined value.
+ ArcIt() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ ArcIt(const ArcIt& e) : Arc(e) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ ArcIt(Invalid) { }
+ /// Sets the iterator to the first arc.
+
+ /// Sets the iterator to the first arc of the given digraph.
+ ///
+ explicit ArcIt(const Digraph& g) {
+ ::lemon::ignore_unused_variable_warning(g);
+ }
+ /// Sets the iterator to the given arc.
+
+ /// Sets the iterator to the given arc of the given digraph.
+ ///
+ ArcIt(const Digraph&, const Arc&) { }
+ /// Next arc
+
+ /// Assign the iterator to the next arc.
+ ///
+ ArcIt& operator++() { return *this; }
+ };
+
+ /// \brief The source node of the arc.
+ ///
+ /// Returns the source node of the given arc.
+ Node source(Arc) const { return INVALID; }
+
+ /// \brief The target node of the arc.
+ ///
+ /// Returns the target node of the given arc.
+ Node target(Arc) const { return INVALID; }
+
+ /// \brief The ID of the node.
+ ///
+ /// Returns the ID of the given node.
+ int id(Node) const { return -1; }
+
+ /// \brief The ID of the arc.
+ ///
+ /// Returns the ID of the given arc.
+ int id(Arc) const { return -1; }
+
+ /// \brief The node with the given ID.
+ ///
+ /// Returns the node with the given ID.
+ /// \pre The argument should be a valid node ID in the digraph.
+ Node nodeFromId(int) const { return INVALID; }
+
+ /// \brief The arc with the given ID.
+ ///
+ /// Returns the arc with the given ID.
+ /// \pre The argument should be a valid arc ID in the digraph.
+ Arc arcFromId(int) const { return INVALID; }
+
+ /// \brief An upper bound on the node IDs.
+ ///
+ /// Returns an upper bound on the node IDs.
+ int maxNodeId() const { return -1; }
+
+ /// \brief An upper bound on the arc IDs.
+ ///
+ /// Returns an upper bound on the arc IDs.
+ int maxArcId() const { return -1; }
+
+ void first(Node&) const {}
+ void next(Node&) const {}
+
+ void first(Arc&) const {}
+ void next(Arc&) const {}
+
+
+ void firstIn(Arc&, const Node&) const {}
+ void nextIn(Arc&) const {}
+
+ void firstOut(Arc&, const Node&) const {}
+ void nextOut(Arc&) const {}
+
+ // The second parameter is dummy.
+ Node fromId(int, Node) const { return INVALID; }
+ // The second parameter is dummy.
+ Arc fromId(int, Arc) const { return INVALID; }
+
+ // Dummy parameter.
+ int maxId(Node) const { return -1; }
+ // Dummy parameter.
+ int maxId(Arc) const { return -1; }
+
+ /// \brief The opposite node on the arc.
+ ///
+ /// Returns the opposite node on the given arc.
+ Node oppositeNode(Node, Arc) const { return INVALID; }
+
+ /// \brief The base node of the iterator.
+ ///
+ /// Returns the base node of the given outgoing arc iterator
+ /// (i.e. the source node of the corresponding arc).
+ Node baseNode(OutArcIt) const { return INVALID; }
+
+ /// \brief The running node of the iterator.
+ ///
+ /// Returns the running node of the given outgoing arc iterator
+ /// (i.e. the target node of the corresponding arc).
+ Node runningNode(OutArcIt) const { return INVALID; }
+
+ /// \brief The base node of the iterator.
+ ///
+ /// Returns the base node of the given incoming arc iterator
+ /// (i.e. the target node of the corresponding arc).
+ Node baseNode(InArcIt) const { return INVALID; }
+
+ /// \brief The running node of the iterator.
+ ///
+ /// Returns the running node of the given incoming arc iterator
+ /// (i.e. the source node of the corresponding arc).
+ Node runningNode(InArcIt) const { return INVALID; }
+
+ /// \brief Standard graph map type for the nodes.
+ ///
+ /// Standard graph map type for the nodes.
+ /// It conforms to the ReferenceMap concept.
+ template<class T>
+ class NodeMap : public ReferenceMap<Node, T, T&, const T&> {
+ public:
+
+ /// Constructor
+ explicit NodeMap(const Digraph&) { }
+ /// Constructor with given initial value
+ NodeMap(const Digraph&, T) { }
+
+ private:
+ ///Copy constructor
+ NodeMap(const NodeMap& nm) :
+ ReferenceMap<Node, T, T&, const T&>(nm) { }
+ ///Assignment operator
+ template <typename CMap>
+ NodeMap& operator=(const CMap&) {
+ checkConcept<ReadMap<Node, T>, CMap>();
+ return *this;
+ }
+ };
+
+ /// \brief Standard graph map type for the arcs.
+ ///
+ /// Standard graph map type for the arcs.
+ /// It conforms to the ReferenceMap concept.
+ template<class T>
+ class ArcMap : public ReferenceMap<Arc, T, T&, const T&> {
+ public:
+
+ /// Constructor
+ explicit ArcMap(const Digraph&) { }
+ /// Constructor with given initial value
+ ArcMap(const Digraph&, T) { }
+
+ private:
+ ///Copy constructor
+ ArcMap(const ArcMap& em) :
+ ReferenceMap<Arc, T, T&, const T&>(em) { }
+ ///Assignment operator
+ template <typename CMap>
+ ArcMap& operator=(const CMap&) {
+ checkConcept<ReadMap<Arc, T>, CMap>();
+ return *this;
+ }
+ };
+
+ template <typename _Digraph>
+ struct Constraints {
+ void constraints() {
+ checkConcept<BaseDigraphComponent, _Digraph>();
+ checkConcept<IterableDigraphComponent<>, _Digraph>();
+ checkConcept<IDableDigraphComponent<>, _Digraph>();
+ checkConcept<MappableDigraphComponent<>, _Digraph>();
+ }
+ };
+
+ };
+
+ } //namespace concepts
+} //namespace lemon
+
+
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/graph.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/graph.h
new file mode 100644
index 00000000000..76e43da0680
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/graph.h
@@ -0,0 +1,788 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\ingroup graph_concepts
+///\file
+///\brief The concept of undirected graphs.
+
+#ifndef LEMON_CONCEPTS_GRAPH_H
+#define LEMON_CONCEPTS_GRAPH_H
+
+#include <lemon/concepts/graph_components.h>
+#include <lemon/concepts/maps.h>
+#include <lemon/concept_check.h>
+#include <lemon/core.h>
+
+namespace lemon {
+ namespace concepts {
+
+ /// \ingroup graph_concepts
+ ///
+ /// \brief Class describing the concept of undirected graphs.
+ ///
+ /// This class describes the common interface of all undirected
+ /// graphs.
+ ///
+ /// Like all concept classes, it only provides an interface
+ /// without any sensible implementation. So any general algorithm for
+ /// undirected graphs should compile with this class, but it will not
+ /// run properly, of course.
+ /// An actual graph implementation like \ref ListGraph or
+ /// \ref SmartGraph may have additional functionality.
+ ///
+ /// The undirected graphs also fulfill the concept of \ref Digraph
+ /// "directed graphs", since each edge can also be regarded as two
+ /// oppositely directed arcs.
+ /// Undirected graphs provide an Edge type for the undirected edges and
+ /// an Arc type for the directed arcs. The Arc type is convertible to
+ /// Edge or inherited from it, i.e. the corresponding edge can be
+ /// obtained from an arc.
+ /// EdgeIt and EdgeMap classes can be used for the edges, while ArcIt
+ /// and ArcMap classes can be used for the arcs (just like in digraphs).
+ /// Both InArcIt and OutArcIt iterates on the same edges but with
+ /// opposite direction. IncEdgeIt also iterates on the same edges
+ /// as OutArcIt and InArcIt, but it is not convertible to Arc,
+ /// only to Edge.
+ ///
+ /// In LEMON, each undirected edge has an inherent orientation.
+ /// Thus it can defined if an arc is forward or backward oriented in
+ /// an undirected graph with respect to this default oriantation of
+ /// the represented edge.
+ /// With the direction() and direct() functions the direction
+ /// of an arc can be obtained and set, respectively.
+ ///
+ /// Only nodes and edges can be added to or removed from an undirected
+ /// graph and the corresponding arcs are added or removed automatically.
+ ///
+ /// \sa Digraph
+ class Graph {
+ private:
+ /// Graphs are \e not copy constructible. Use GraphCopy instead.
+ Graph(const Graph&) {}
+ /// \brief Assignment of a graph to another one is \e not allowed.
+ /// Use GraphCopy instead.
+ void operator=(const Graph&) {}
+
+ public:
+ /// Default constructor.
+ Graph() {}
+
+ /// \brief Undirected graphs should be tagged with \c UndirectedTag.
+ ///
+ /// Undirected graphs should be tagged with \c UndirectedTag.
+ ///
+ /// This tag helps the \c enable_if technics to make compile time
+ /// specializations for undirected graphs.
+ typedef True UndirectedTag;
+
+ /// The node type of the graph
+
+ /// This class identifies a node of the graph. It also serves
+ /// as a base class of the node iterators,
+ /// thus they convert to this type.
+ class Node {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the object to an undefined value.
+ Node() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ Node(const Node&) { }
+
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the object to be invalid.
+ /// \sa Invalid for more details.
+ Node(Invalid) { }
+ /// Equality operator
+
+ /// Equality operator.
+ ///
+ /// Two iterators are equal if and only if they point to the
+ /// same object or both are \c INVALID.
+ bool operator==(Node) const { return true; }
+
+ /// Inequality operator
+
+ /// Inequality operator.
+ bool operator!=(Node) const { return true; }
+
+ /// Artificial ordering operator.
+
+ /// Artificial ordering operator.
+ ///
+ /// \note This operator only has to define some strict ordering of
+ /// the items; this order has nothing to do with the iteration
+ /// ordering of the items.
+ bool operator<(Node) const { return false; }
+
+ };
+
+ /// Iterator class for the nodes.
+
+ /// This iterator goes through each node of the graph.
+ /// Its usage is quite simple, for example, you can count the number
+ /// of nodes in a graph \c g of type \c %Graph like this:
+ ///\code
+ /// int count=0;
+ /// for (Graph::NodeIt n(g); n!=INVALID; ++n) ++count;
+ ///\endcode
+ class NodeIt : public Node {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the iterator to an undefined value.
+ NodeIt() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ NodeIt(const NodeIt& n) : Node(n) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ NodeIt(Invalid) { }
+ /// Sets the iterator to the first node.
+
+ /// Sets the iterator to the first node of the given digraph.
+ ///
+ explicit NodeIt(const Graph&) { }
+ /// Sets the iterator to the given node.
+
+ /// Sets the iterator to the given node of the given digraph.
+ ///
+ NodeIt(const Graph&, const Node&) { }
+ /// Next node.
+
+ /// Assign the iterator to the next node.
+ ///
+ NodeIt& operator++() { return *this; }
+ };
+
+
+ /// The edge type of the graph
+
+ /// This class identifies an edge of the graph. It also serves
+ /// as a base class of the edge iterators,
+ /// thus they will convert to this type.
+ class Edge {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the object to an undefined value.
+ Edge() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ Edge(const Edge&) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the object to be invalid.
+ /// \sa Invalid for more details.
+ Edge(Invalid) { }
+ /// Equality operator
+
+ /// Equality operator.
+ ///
+ /// Two iterators are equal if and only if they point to the
+ /// same object or both are \c INVALID.
+ bool operator==(Edge) const { return true; }
+ /// Inequality operator
+
+ /// Inequality operator.
+ bool operator!=(Edge) const { return true; }
+
+ /// Artificial ordering operator.
+
+ /// Artificial ordering operator.
+ ///
+ /// \note This operator only has to define some strict ordering of
+ /// the edges; this order has nothing to do with the iteration
+ /// ordering of the edges.
+ bool operator<(Edge) const { return false; }
+ };
+
+ /// Iterator class for the edges.
+
+ /// This iterator goes through each edge of the graph.
+ /// Its usage is quite simple, for example, you can count the number
+ /// of edges in a graph \c g of type \c %Graph as follows:
+ ///\code
+ /// int count=0;
+ /// for(Graph::EdgeIt e(g); e!=INVALID; ++e) ++count;
+ ///\endcode
+ class EdgeIt : public Edge {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the iterator to an undefined value.
+ EdgeIt() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ EdgeIt(const EdgeIt& e) : Edge(e) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ EdgeIt(Invalid) { }
+ /// Sets the iterator to the first edge.
+
+ /// Sets the iterator to the first edge of the given graph.
+ ///
+ explicit EdgeIt(const Graph&) { }
+ /// Sets the iterator to the given edge.
+
+ /// Sets the iterator to the given edge of the given graph.
+ ///
+ EdgeIt(const Graph&, const Edge&) { }
+ /// Next edge
+
+ /// Assign the iterator to the next edge.
+ ///
+ EdgeIt& operator++() { return *this; }
+ };
+
+ /// Iterator class for the incident edges of a node.
+
+ /// This iterator goes trough the incident undirected edges
+ /// of a certain node of a graph.
+ /// Its usage is quite simple, for example, you can compute the
+ /// degree (i.e. the number of incident edges) of a node \c n
+ /// in a graph \c g of type \c %Graph as follows.
+ ///
+ ///\code
+ /// int count=0;
+ /// for(Graph::IncEdgeIt e(g, n); e!=INVALID; ++e) ++count;
+ ///\endcode
+ ///
+ /// \warning Loop edges will be iterated twice.
+ class IncEdgeIt : public Edge {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the iterator to an undefined value.
+ IncEdgeIt() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ IncEdgeIt(const IncEdgeIt& e) : Edge(e) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ IncEdgeIt(Invalid) { }
+ /// Sets the iterator to the first incident edge.
+
+ /// Sets the iterator to the first incident edge of the given node.
+ ///
+ IncEdgeIt(const Graph&, const Node&) { }
+ /// Sets the iterator to the given edge.
+
+ /// Sets the iterator to the given edge of the given graph.
+ ///
+ IncEdgeIt(const Graph&, const Edge&) { }
+ /// Next incident edge
+
+ /// Assign the iterator to the next incident edge
+ /// of the corresponding node.
+ IncEdgeIt& operator++() { return *this; }
+ };
+
+ /// The arc type of the graph
+
+ /// This class identifies a directed arc of the graph. It also serves
+ /// as a base class of the arc iterators,
+ /// thus they will convert to this type.
+ class Arc {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the object to an undefined value.
+ Arc() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ Arc(const Arc&) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the object to be invalid.
+ /// \sa Invalid for more details.
+ Arc(Invalid) { }
+ /// Equality operator
+
+ /// Equality operator.
+ ///
+ /// Two iterators are equal if and only if they point to the
+ /// same object or both are \c INVALID.
+ bool operator==(Arc) const { return true; }
+ /// Inequality operator
+
+ /// Inequality operator.
+ bool operator!=(Arc) const { return true; }
+
+ /// Artificial ordering operator.
+
+ /// Artificial ordering operator.
+ ///
+ /// \note This operator only has to define some strict ordering of
+ /// the arcs; this order has nothing to do with the iteration
+ /// ordering of the arcs.
+ bool operator<(Arc) const { return false; }
+
+ /// Converison to \c Edge
+
+ /// Converison to \c Edge.
+ ///
+ operator Edge() const { return Edge(); }
+ };
+
+ /// Iterator class for the arcs.
+
+ /// This iterator goes through each directed arc of the graph.
+ /// Its usage is quite simple, for example, you can count the number
+ /// of arcs in a graph \c g of type \c %Graph as follows:
+ ///\code
+ /// int count=0;
+ /// for(Graph::ArcIt a(g); a!=INVALID; ++a) ++count;
+ ///\endcode
+ class ArcIt : public Arc {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the iterator to an undefined value.
+ ArcIt() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ ArcIt(const ArcIt& e) : Arc(e) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ ArcIt(Invalid) { }
+ /// Sets the iterator to the first arc.
+
+ /// Sets the iterator to the first arc of the given graph.
+ ///
+ explicit ArcIt(const Graph &g) {
+ ::lemon::ignore_unused_variable_warning(g);
+ }
+ /// Sets the iterator to the given arc.
+
+ /// Sets the iterator to the given arc of the given graph.
+ ///
+ ArcIt(const Graph&, const Arc&) { }
+ /// Next arc
+
+ /// Assign the iterator to the next arc.
+ ///
+ ArcIt& operator++() { return *this; }
+ };
+
+ /// Iterator class for the outgoing arcs of a node.
+
+ /// This iterator goes trough the \e outgoing directed arcs of a
+ /// certain node of a graph.
+ /// Its usage is quite simple, for example, you can count the number
+ /// of outgoing arcs of a node \c n
+ /// in a graph \c g of type \c %Graph as follows.
+ ///\code
+ /// int count=0;
+ /// for (Digraph::OutArcIt a(g, n); a!=INVALID; ++a) ++count;
+ ///\endcode
+ class OutArcIt : public Arc {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the iterator to an undefined value.
+ OutArcIt() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ OutArcIt(const OutArcIt& e) : Arc(e) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ OutArcIt(Invalid) { }
+ /// Sets the iterator to the first outgoing arc.
+
+ /// Sets the iterator to the first outgoing arc of the given node.
+ ///
+ OutArcIt(const Graph& n, const Node& g) {
+ ::lemon::ignore_unused_variable_warning(n);
+ ::lemon::ignore_unused_variable_warning(g);
+ }
+ /// Sets the iterator to the given arc.
+
+ /// Sets the iterator to the given arc of the given graph.
+ ///
+ OutArcIt(const Graph&, const Arc&) { }
+ /// Next outgoing arc
+
+ /// Assign the iterator to the next
+ /// outgoing arc of the corresponding node.
+ OutArcIt& operator++() { return *this; }
+ };
+
+ /// Iterator class for the incoming arcs of a node.
+
+ /// This iterator goes trough the \e incoming directed arcs of a
+ /// certain node of a graph.
+ /// Its usage is quite simple, for example, you can count the number
+ /// of incoming arcs of a node \c n
+ /// in a graph \c g of type \c %Graph as follows.
+ ///\code
+ /// int count=0;
+ /// for (Digraph::InArcIt a(g, n); a!=INVALID; ++a) ++count;
+ ///\endcode
+ class InArcIt : public Arc {
+ public:
+ /// Default constructor
+
+ /// Default constructor.
+ /// \warning It sets the iterator to an undefined value.
+ InArcIt() { }
+ /// Copy constructor.
+
+ /// Copy constructor.
+ ///
+ InArcIt(const InArcIt& e) : Arc(e) { }
+ /// %Invalid constructor \& conversion.
+
+ /// Initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ InArcIt(Invalid) { }
+ /// Sets the iterator to the first incoming arc.
+
+ /// Sets the iterator to the first incoming arc of the given node.
+ ///
+ InArcIt(const Graph& g, const Node& n) {
+ ::lemon::ignore_unused_variable_warning(n);
+ ::lemon::ignore_unused_variable_warning(g);
+ }
+ /// Sets the iterator to the given arc.
+
+ /// Sets the iterator to the given arc of the given graph.
+ ///
+ InArcIt(const Graph&, const Arc&) { }
+ /// Next incoming arc
+
+ /// Assign the iterator to the next
+ /// incoming arc of the corresponding node.
+ InArcIt& operator++() { return *this; }
+ };
+
+ /// \brief Standard graph map type for the nodes.
+ ///
+ /// Standard graph map type for the nodes.
+ /// It conforms to the ReferenceMap concept.
+ template<class T>
+ class NodeMap : public ReferenceMap<Node, T, T&, const T&>
+ {
+ public:
+
+ /// Constructor
+ explicit NodeMap(const Graph&) { }
+ /// Constructor with given initial value
+ NodeMap(const Graph&, T) { }
+
+ private:
+ ///Copy constructor
+ NodeMap(const NodeMap& nm) :
+ ReferenceMap<Node, T, T&, const T&>(nm) { }
+ ///Assignment operator
+ template <typename CMap>
+ NodeMap& operator=(const CMap&) {
+ checkConcept<ReadMap<Node, T>, CMap>();
+ return *this;
+ }
+ };
+
+ /// \brief Standard graph map type for the arcs.
+ ///
+ /// Standard graph map type for the arcs.
+ /// It conforms to the ReferenceMap concept.
+ template<class T>
+ class ArcMap : public ReferenceMap<Arc, T, T&, const T&>
+ {
+ public:
+
+ /// Constructor
+ explicit ArcMap(const Graph&) { }
+ /// Constructor with given initial value
+ ArcMap(const Graph&, T) { }
+
+ private:
+ ///Copy constructor
+ ArcMap(const ArcMap& em) :
+ ReferenceMap<Arc, T, T&, const T&>(em) { }
+ ///Assignment operator
+ template <typename CMap>
+ ArcMap& operator=(const CMap&) {
+ checkConcept<ReadMap<Arc, T>, CMap>();
+ return *this;
+ }
+ };
+
+ /// \brief Standard graph map type for the edges.
+ ///
+ /// Standard graph map type for the edges.
+ /// It conforms to the ReferenceMap concept.
+ template<class T>
+ class EdgeMap : public ReferenceMap<Edge, T, T&, const T&>
+ {
+ public:
+
+ /// Constructor
+ explicit EdgeMap(const Graph&) { }
+ /// Constructor with given initial value
+ EdgeMap(const Graph&, T) { }
+
+ private:
+ ///Copy constructor
+ EdgeMap(const EdgeMap& em) :
+ ReferenceMap<Edge, T, T&, const T&>(em) {}
+ ///Assignment operator
+ template <typename CMap>
+ EdgeMap& operator=(const CMap&) {
+ checkConcept<ReadMap<Edge, T>, CMap>();
+ return *this;
+ }
+ };
+
+ /// \brief The first node of the edge.
+ ///
+ /// Returns the first node of the given edge.
+ ///
+ /// Edges don't have source and target nodes, however, methods
+ /// u() and v() are used to query the two end-nodes of an edge.
+ /// The orientation of an edge that arises this way is called
+ /// the inherent direction, it is used to define the default
+ /// direction for the corresponding arcs.
+ /// \sa v()
+ /// \sa direction()
+ Node u(Edge) const { return INVALID; }
+
+ /// \brief The second node of the edge.
+ ///
+ /// Returns the second node of the given edge.
+ ///
+ /// Edges don't have source and target nodes, however, methods
+ /// u() and v() are used to query the two end-nodes of an edge.
+ /// The orientation of an edge that arises this way is called
+ /// the inherent direction, it is used to define the default
+ /// direction for the corresponding arcs.
+ /// \sa u()
+ /// \sa direction()
+ Node v(Edge) const { return INVALID; }
+
+ /// \brief The source node of the arc.
+ ///
+ /// Returns the source node of the given arc.
+ Node source(Arc) const { return INVALID; }
+
+ /// \brief The target node of the arc.
+ ///
+ /// Returns the target node of the given arc.
+ Node target(Arc) const { return INVALID; }
+
+ /// \brief The ID of the node.
+ ///
+ /// Returns the ID of the given node.
+ int id(Node) const { return -1; }
+
+ /// \brief The ID of the edge.
+ ///
+ /// Returns the ID of the given edge.
+ int id(Edge) const { return -1; }
+
+ /// \brief The ID of the arc.
+ ///
+ /// Returns the ID of the given arc.
+ int id(Arc) const { return -1; }
+
+ /// \brief The node with the given ID.
+ ///
+ /// Returns the node with the given ID.
+ /// \pre The argument should be a valid node ID in the graph.
+ Node nodeFromId(int) const { return INVALID; }
+
+ /// \brief The edge with the given ID.
+ ///
+ /// Returns the edge with the given ID.
+ /// \pre The argument should be a valid edge ID in the graph.
+ Edge edgeFromId(int) const { return INVALID; }
+
+ /// \brief The arc with the given ID.
+ ///
+ /// Returns the arc with the given ID.
+ /// \pre The argument should be a valid arc ID in the graph.
+ Arc arcFromId(int) const { return INVALID; }
+
+ /// \brief An upper bound on the node IDs.
+ ///
+ /// Returns an upper bound on the node IDs.
+ int maxNodeId() const { return -1; }
+
+ /// \brief An upper bound on the edge IDs.
+ ///
+ /// Returns an upper bound on the edge IDs.
+ int maxEdgeId() const { return -1; }
+
+ /// \brief An upper bound on the arc IDs.
+ ///
+ /// Returns an upper bound on the arc IDs.
+ int maxArcId() const { return -1; }
+
+ /// \brief The direction of the arc.
+ ///
+ /// Returns \c true if the direction of the given arc is the same as
+ /// the inherent orientation of the represented edge.
+ bool direction(Arc) const { return true; }
+
+ /// \brief Direct the edge.
+ ///
+ /// Direct the given edge. The returned arc
+ /// represents the given edge and its direction comes
+ /// from the bool parameter. If it is \c true, then the direction
+ /// of the arc is the same as the inherent orientation of the edge.
+ Arc direct(Edge, bool) const {
+ return INVALID;
+ }
+
+ /// \brief Direct the edge.
+ ///
+ /// Direct the given edge. The returned arc represents the given
+ /// edge and its source node is the given node.
+ Arc direct(Edge, Node) const {
+ return INVALID;
+ }
+
+ /// \brief The oppositely directed arc.
+ ///
+ /// Returns the oppositely directed arc representing the same edge.
+ Arc oppositeArc(Arc) const { return INVALID; }
+
+ /// \brief The opposite node on the edge.
+ ///
+ /// Returns the opposite node on the given edge.
+ Node oppositeNode(Node, Edge) const { return INVALID; }
+
+ void first(Node&) const {}
+ void next(Node&) const {}
+
+ void first(Edge&) const {}
+ void next(Edge&) const {}
+
+ void first(Arc&) const {}
+ void next(Arc&) const {}
+
+ void firstOut(Arc&, Node) const {}
+ void nextOut(Arc&) const {}
+
+ void firstIn(Arc&, Node) const {}
+ void nextIn(Arc&) const {}
+
+ void firstInc(Edge &, bool &, const Node &) const {}
+ void nextInc(Edge &, bool &) const {}
+
+ // The second parameter is dummy.
+ Node fromId(int, Node) const { return INVALID; }
+ // The second parameter is dummy.
+ Edge fromId(int, Edge) const { return INVALID; }
+ // The second parameter is dummy.
+ Arc fromId(int, Arc) const { return INVALID; }
+
+ // Dummy parameter.
+ int maxId(Node) const { return -1; }
+ // Dummy parameter.
+ int maxId(Edge) const { return -1; }
+ // Dummy parameter.
+ int maxId(Arc) const { return -1; }
+
+ /// \brief The base node of the iterator.
+ ///
+ /// Returns the base node of the given incident edge iterator.
+ Node baseNode(IncEdgeIt) const { return INVALID; }
+
+ /// \brief The running node of the iterator.
+ ///
+ /// Returns the running node of the given incident edge iterator.
+ Node runningNode(IncEdgeIt) const { return INVALID; }
+
+ /// \brief The base node of the iterator.
+ ///
+ /// Returns the base node of the given outgoing arc iterator
+ /// (i.e. the source node of the corresponding arc).
+ Node baseNode(OutArcIt) const { return INVALID; }
+
+ /// \brief The running node of the iterator.
+ ///
+ /// Returns the running node of the given outgoing arc iterator
+ /// (i.e. the target node of the corresponding arc).
+ Node runningNode(OutArcIt) const { return INVALID; }
+
+ /// \brief The base node of the iterator.
+ ///
+ /// Returns the base node of the given incoming arc iterator
+ /// (i.e. the target node of the corresponding arc).
+ Node baseNode(InArcIt) const { return INVALID; }
+
+ /// \brief The running node of the iterator.
+ ///
+ /// Returns the running node of the given incoming arc iterator
+ /// (i.e. the source node of the corresponding arc).
+ Node runningNode(InArcIt) const { return INVALID; }
+
+ template <typename _Graph>
+ struct Constraints {
+ void constraints() {
+ checkConcept<BaseGraphComponent, _Graph>();
+ checkConcept<IterableGraphComponent<>, _Graph>();
+ checkConcept<IDableGraphComponent<>, _Graph>();
+ checkConcept<MappableGraphComponent<>, _Graph>();
+ }
+ };
+
+ };
+
+ }
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/graph_components.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/graph_components.h
new file mode 100644
index 00000000000..9df28f37e61
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/graph_components.h
@@ -0,0 +1,2134 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\ingroup graph_concepts
+///\file
+///\brief The concepts of graph components.
+
+#ifndef LEMON_CONCEPTS_GRAPH_COMPONENTS_H
+#define LEMON_CONCEPTS_GRAPH_COMPONENTS_H
+
+#include <lemon/core.h>
+#include <lemon/concepts/maps.h>
+
+#include <lemon/bits/alteration_notifier.h>
+
+namespace lemon {
+ namespace concepts {
+
+ /// \brief Concept class for \c Node, \c Arc and \c Edge types.
+ ///
+ /// This class describes the concept of \c Node, \c Arc and \c Edge
+ /// subtypes of digraph and graph types.
+ ///
+ /// \note This class is a template class so that we can use it to
+ /// create graph skeleton classes. The reason for this is that \c Node
+ /// and \c Arc (or \c Edge) types should \e not derive from the same
+ /// base class. For \c Node you should instantiate it with character
+ /// \c 'n', for \c Arc with \c 'a' and for \c Edge with \c 'e'.
+#ifndef DOXYGEN
+ template <char sel = '0'>
+#endif
+ class GraphItem {
+ public:
+ /// \brief Default constructor.
+ ///
+ /// Default constructor.
+ /// \warning The default constructor is not required to set
+ /// the item to some well-defined value. So you should consider it
+ /// as uninitialized.
+ GraphItem() {}
+
+ /// \brief Copy constructor.
+ ///
+ /// Copy constructor.
+ GraphItem(const GraphItem &) {}
+
+ /// \brief Constructor for conversion from \c INVALID.
+ ///
+ /// Constructor for conversion from \c INVALID.
+ /// It initializes the item to be invalid.
+ /// \sa Invalid for more details.
+ GraphItem(Invalid) {}
+
+ /// \brief Assignment operator.
+ ///
+ /// Assignment operator for the item.
+ GraphItem& operator=(const GraphItem&) { return *this; }
+
+ /// \brief Assignment operator for INVALID.
+ ///
+ /// This operator makes the item invalid.
+ GraphItem& operator=(Invalid) { return *this; }
+
+ /// \brief Equality operator.
+ ///
+ /// Equality operator.
+ bool operator==(const GraphItem&) const { return false; }
+
+ /// \brief Inequality operator.
+ ///
+ /// Inequality operator.
+ bool operator!=(const GraphItem&) const { return false; }
+
+ /// \brief Ordering operator.
+ ///
+ /// This operator defines an ordering of the items.
+ /// It makes possible to use graph item types as key types in
+ /// associative containers (e.g. \c std::map).
+ ///
+ /// \note This operator only has to define some strict ordering of
+ /// the items; this order has nothing to do with the iteration
+ /// ordering of the items.
+ bool operator<(const GraphItem&) const { return false; }
+
+ template<typename _GraphItem>
+ struct Constraints {
+ void constraints() {
+ _GraphItem i1;
+ i1=INVALID;
+ _GraphItem i2 = i1;
+ _GraphItem i3 = INVALID;
+
+ i1 = i2 = i3;
+
+ bool b;
+ ::lemon::ignore_unused_variable_warning(b);
+
+ b = (ia == ib) && (ia != ib);
+ b = (ia == INVALID) && (ib != INVALID);
+ b = (ia < ib);
+ }
+
+ const _GraphItem &ia;
+ const _GraphItem &ib;
+ Constraints() {}
+ };
+ };
+
+ /// \brief Base skeleton class for directed graphs.
+ ///
+ /// This class describes the base interface of directed graph types.
+ /// All digraph %concepts have to conform to this class.
+ /// It just provides types for nodes and arcs and functions
+ /// to get the source and the target nodes of arcs.
+ class BaseDigraphComponent {
+ public:
+
+ typedef BaseDigraphComponent Digraph;
+
+ /// \brief Node class of the digraph.
+ ///
+ /// This class represents the nodes of the digraph.
+ typedef GraphItem<'n'> Node;
+
+ /// \brief Arc class of the digraph.
+ ///
+ /// This class represents the arcs of the digraph.
+ typedef GraphItem<'a'> Arc;
+
+ /// \brief Return the source node of an arc.
+ ///
+ /// This function returns the source node of an arc.
+ Node source(const Arc&) const { return INVALID; }
+
+ /// \brief Return the target node of an arc.
+ ///
+ /// This function returns the target node of an arc.
+ Node target(const Arc&) const { return INVALID; }
+
+ /// \brief Return the opposite node on the given arc.
+ ///
+ /// This function returns the opposite node on the given arc.
+ Node oppositeNode(const Node&, const Arc&) const {
+ return INVALID;
+ }
+
+ template <typename _Digraph>
+ struct Constraints {
+ typedef typename _Digraph::Node Node;
+ typedef typename _Digraph::Arc Arc;
+
+ void constraints() {
+ checkConcept<GraphItem<'n'>, Node>();
+ checkConcept<GraphItem<'a'>, Arc>();
+ {
+ Node n;
+ Arc e(INVALID);
+ n = digraph.source(e);
+ n = digraph.target(e);
+ n = digraph.oppositeNode(n, e);
+ }
+ }
+
+ const _Digraph& digraph;
+ Constraints() {}
+ };
+ };
+
+ /// \brief Base skeleton class for undirected graphs.
+ ///
+ /// This class describes the base interface of undirected graph types.
+ /// All graph %concepts have to conform to this class.
+ /// It extends the interface of \ref BaseDigraphComponent with an
+ /// \c Edge type and functions to get the end nodes of edges,
+ /// to convert from arcs to edges and to get both direction of edges.
+ class BaseGraphComponent : public BaseDigraphComponent {
+ public:
+
+ typedef BaseGraphComponent Graph;
+
+ typedef BaseDigraphComponent::Node Node;
+ typedef BaseDigraphComponent::Arc Arc;
+
+ /// \brief Undirected edge class of the graph.
+ ///
+ /// This class represents the undirected edges of the graph.
+ /// Undirected graphs can be used as directed graphs, each edge is
+ /// represented by two opposite directed arcs.
+ class Edge : public GraphItem<'e'> {
+ typedef GraphItem<'e'> Parent;
+
+ public:
+ /// \brief Default constructor.
+ ///
+ /// Default constructor.
+ /// \warning The default constructor is not required to set
+ /// the item to some well-defined value. So you should consider it
+ /// as uninitialized.
+ Edge() {}
+
+ /// \brief Copy constructor.
+ ///
+ /// Copy constructor.
+ Edge(const Edge &) : Parent() {}
+
+ /// \brief Constructor for conversion from \c INVALID.
+ ///
+ /// Constructor for conversion from \c INVALID.
+ /// It initializes the item to be invalid.
+ /// \sa Invalid for more details.
+ Edge(Invalid) {}
+
+ /// \brief Constructor for conversion from an arc.
+ ///
+ /// Constructor for conversion from an arc.
+ /// Besides the core graph item functionality each arc should
+ /// be convertible to the represented edge.
+ Edge(const Arc&) {}
+ };
+
+ /// \brief Return one end node of an edge.
+ ///
+ /// This function returns one end node of an edge.
+ Node u(const Edge&) const { return INVALID; }
+
+ /// \brief Return the other end node of an edge.
+ ///
+ /// This function returns the other end node of an edge.
+ Node v(const Edge&) const { return INVALID; }
+
+ /// \brief Return a directed arc related to an edge.
+ ///
+ /// This function returns a directed arc from its direction and the
+ /// represented edge.
+ Arc direct(const Edge&, bool) const { return INVALID; }
+
+ /// \brief Return a directed arc related to an edge.
+ ///
+ /// This function returns a directed arc from its source node and the
+ /// represented edge.
+ Arc direct(const Edge&, const Node&) const { return INVALID; }
+
+ /// \brief Return the direction of the arc.
+ ///
+ /// Returns the direction of the arc. Each arc represents an
+ /// edge with a direction. It gives back the
+ /// direction.
+ bool direction(const Arc&) const { return true; }
+
+ /// \brief Return the opposite arc.
+ ///
+ /// This function returns the opposite arc, i.e. the arc representing
+ /// the same edge and has opposite direction.
+ Arc oppositeArc(const Arc&) const { return INVALID; }
+
+ template <typename _Graph>
+ struct Constraints {
+ typedef typename _Graph::Node Node;
+ typedef typename _Graph::Arc Arc;
+ typedef typename _Graph::Edge Edge;
+
+ void constraints() {
+ checkConcept<BaseDigraphComponent, _Graph>();
+ checkConcept<GraphItem<'e'>, Edge>();
+ {
+ Node n;
+ Edge ue(INVALID);
+ Arc e;
+ n = graph.u(ue);
+ n = graph.v(ue);
+ e = graph.direct(ue, true);
+ e = graph.direct(ue, false);
+ e = graph.direct(ue, n);
+ e = graph.oppositeArc(e);
+ ue = e;
+ bool d = graph.direction(e);
+ ::lemon::ignore_unused_variable_warning(d);
+ }
+ }
+
+ const _Graph& graph;
+ Constraints() {}
+ };
+
+ };
+
+ /// \brief Base skeleton class for undirected bipartite graphs.
+ ///
+ /// This class describes the base interface of undirected
+ /// bipartite graph types. All bipartite graph %concepts have to
+ /// conform to this class. It extends the interface of \ref
+ /// BaseGraphComponent with an \c Edge type and functions to get
+ /// the end nodes of edges, to convert from arcs to edges and to
+ /// get both direction of edges.
+ class BaseBpGraphComponent : public BaseGraphComponent {
+ public:
+
+ typedef BaseBpGraphComponent BpGraph;
+
+ typedef BaseDigraphComponent::Node Node;
+ typedef BaseDigraphComponent::Arc Arc;
+
+ /// \brief Class to represent red nodes.
+ ///
+ /// This class represents the red nodes of the graph. The red
+ /// nodes can also be used as normal nodes.
+ class RedNode : public Node {
+ typedef Node Parent;
+
+ public:
+ /// \brief Default constructor.
+ ///
+ /// Default constructor.
+ /// \warning The default constructor is not required to set
+ /// the item to some well-defined value. So you should consider it
+ /// as uninitialized.
+ RedNode() {}
+
+ /// \brief Copy constructor.
+ ///
+ /// Copy constructor.
+ RedNode(const RedNode &) : Parent() {}
+
+ /// \brief Constructor for conversion from \c INVALID.
+ ///
+ /// Constructor for conversion from \c INVALID.
+ /// It initializes the item to be invalid.
+ /// \sa Invalid for more details.
+ RedNode(Invalid) {}
+ };
+
+ /// \brief Class to represent blue nodes.
+ ///
+ /// This class represents the blue nodes of the graph. The blue
+ /// nodes can also be used as normal nodes.
+ class BlueNode : public Node {
+ typedef Node Parent;
+
+ public:
+ /// \brief Default constructor.
+ ///
+ /// Default constructor.
+ /// \warning The default constructor is not required to set
+ /// the item to some well-defined value. So you should consider it
+ /// as uninitialized.
+ BlueNode() {}
+
+ /// \brief Copy constructor.
+ ///
+ /// Copy constructor.
+ BlueNode(const BlueNode &) : Parent() {}
+
+ /// \brief Constructor for conversion from \c INVALID.
+ ///
+ /// Constructor for conversion from \c INVALID.
+ /// It initializes the item to be invalid.
+ /// \sa Invalid for more details.
+ BlueNode(Invalid) {}
+
+ /// \brief Constructor for conversion from a node.
+ ///
+ /// Constructor for conversion from a node. The conversion can
+ /// be invalid, since the Node can be member of the red
+ /// set.
+ BlueNode(const Node&) {}
+ };
+
+ /// \brief Gives back %true for red nodes.
+ ///
+ /// Gives back %true for red nodes.
+ bool red(const Node&) const { return true; }
+
+ /// \brief Gives back %true for blue nodes.
+ ///
+ /// Gives back %true for blue nodes.
+ bool blue(const Node&) const { return true; }
+
+ /// \brief Gives back the red end node of the edge.
+ ///
+ /// Gives back the red end node of the edge.
+ RedNode redNode(const Edge&) const { return RedNode(); }
+
+ /// \brief Gives back the blue end node of the edge.
+ ///
+ /// Gives back the blue end node of the edge.
+ BlueNode blueNode(const Edge&) const { return BlueNode(); }
+
+ /// \brief Converts the node to red node object.
+ ///
+ /// This function converts unsafely the node to red node
+ /// object. It should be called only if the node is from the red
+ /// partition or INVALID.
+ RedNode asRedNodeUnsafe(const Node&) const { return RedNode(); }
+
+ /// \brief Converts the node to blue node object.
+ ///
+ /// This function converts unsafely the node to blue node
+ /// object. It should be called only if the node is from the red
+ /// partition or INVALID.
+ BlueNode asBlueNodeUnsafe(const Node&) const { return BlueNode(); }
+
+ /// \brief Converts the node to red node object.
+ ///
+ /// This function converts safely the node to red node
+ /// object. If the node is not from the red partition, then it
+ /// returns INVALID.
+ RedNode asRedNode(const Node&) const { return RedNode(); }
+
+ /// \brief Converts the node to blue node object.
+ ///
+ /// This function converts unsafely the node to blue node
+ /// object. If the node is not from the blue partition, then it
+ /// returns INVALID.
+ BlueNode asBlueNode(const Node&) const { return BlueNode(); }
+
+ template <typename _BpGraph>
+ struct Constraints {
+ typedef typename _BpGraph::Node Node;
+ typedef typename _BpGraph::RedNode RedNode;
+ typedef typename _BpGraph::BlueNode BlueNode;
+ typedef typename _BpGraph::Arc Arc;
+ typedef typename _BpGraph::Edge Edge;
+
+ void constraints() {
+ checkConcept<BaseGraphComponent, _BpGraph>();
+ checkConcept<GraphItem<'n'>, RedNode>();
+ checkConcept<GraphItem<'n'>, BlueNode>();
+ {
+ Node n;
+ RedNode rn;
+ BlueNode bn;
+ Node rnan = rn;
+ Node bnan = bn;
+ Edge e;
+ bool b;
+ b = bpgraph.red(rnan);
+ b = bpgraph.blue(bnan);
+ rn = bpgraph.redNode(e);
+ bn = bpgraph.blueNode(e);
+ rn = bpgraph.asRedNodeUnsafe(rnan);
+ bn = bpgraph.asBlueNodeUnsafe(bnan);
+ rn = bpgraph.asRedNode(rnan);
+ bn = bpgraph.asBlueNode(bnan);
+ ::lemon::ignore_unused_variable_warning(b);
+ }
+ }
+
+ const _BpGraph& bpgraph;
+ };
+
+ };
+
+ /// \brief Skeleton class for \e idable directed graphs.
+ ///
+ /// This class describes the interface of \e idable directed graphs.
+ /// It extends \ref BaseDigraphComponent with the core ID functions.
+ /// The ids of the items must be unique and immutable.
+ /// This concept is part of the Digraph concept.
+ template <typename BAS = BaseDigraphComponent>
+ class IDableDigraphComponent : public BAS {
+ public:
+
+ typedef BAS Base;
+ typedef typename Base::Node Node;
+ typedef typename Base::Arc Arc;
+
+ /// \brief Return a unique integer id for the given node.
+ ///
+ /// This function returns a unique integer id for the given node.
+ int id(const Node&) const { return -1; }
+
+ /// \brief Return the node by its unique id.
+ ///
+ /// This function returns the node by its unique id.
+ /// If the digraph does not contain a node with the given id,
+ /// then the result of the function is undefined.
+ Node nodeFromId(int) const { return INVALID; }
+
+ /// \brief Return a unique integer id for the given arc.
+ ///
+ /// This function returns a unique integer id for the given arc.
+ int id(const Arc&) const { return -1; }
+
+ /// \brief Return the arc by its unique id.
+ ///
+ /// This function returns the arc by its unique id.
+ /// If the digraph does not contain an arc with the given id,
+ /// then the result of the function is undefined.
+ Arc arcFromId(int) const { return INVALID; }
+
+ /// \brief Return an integer greater or equal to the maximum
+ /// node id.
+ ///
+ /// This function returns an integer greater or equal to the
+ /// maximum node id.
+ int maxNodeId() const { return -1; }
+
+ /// \brief Return an integer greater or equal to the maximum
+ /// arc id.
+ ///
+ /// This function returns an integer greater or equal to the
+ /// maximum arc id.
+ int maxArcId() const { return -1; }
+
+ template <typename _Digraph>
+ struct Constraints {
+
+ void constraints() {
+ checkConcept<Base, _Digraph >();
+ typename _Digraph::Node node;
+ node=INVALID;
+ int nid = digraph.id(node);
+ nid = digraph.id(node);
+ node = digraph.nodeFromId(nid);
+ typename _Digraph::Arc arc;
+ arc=INVALID;
+ int eid = digraph.id(arc);
+ eid = digraph.id(arc);
+ arc = digraph.arcFromId(eid);
+
+ nid = digraph.maxNodeId();
+ ::lemon::ignore_unused_variable_warning(nid);
+ eid = digraph.maxArcId();
+ ::lemon::ignore_unused_variable_warning(eid);
+ }
+
+ const _Digraph& digraph;
+ Constraints() {}
+ };
+ };
+
+ /// \brief Skeleton class for \e idable undirected graphs.
+ ///
+ /// This class describes the interface of \e idable undirected
+ /// graphs. It extends \ref IDableDigraphComponent with the core ID
+ /// functions of undirected graphs.
+ /// The ids of the items must be unique and immutable.
+ /// This concept is part of the Graph concept.
+ template <typename BAS = BaseGraphComponent>
+ class IDableGraphComponent : public IDableDigraphComponent<BAS> {
+ public:
+
+ typedef BAS Base;
+ typedef typename Base::Edge Edge;
+
+ using IDableDigraphComponent<Base>::id;
+
+ /// \brief Return a unique integer id for the given edge.
+ ///
+ /// This function returns a unique integer id for the given edge.
+ int id(const Edge&) const { return -1; }
+
+ /// \brief Return the edge by its unique id.
+ ///
+ /// This function returns the edge by its unique id.
+ /// If the graph does not contain an edge with the given id,
+ /// then the result of the function is undefined.
+ Edge edgeFromId(int) const { return INVALID; }
+
+ /// \brief Return an integer greater or equal to the maximum
+ /// edge id.
+ ///
+ /// This function returns an integer greater or equal to the
+ /// maximum edge id.
+ int maxEdgeId() const { return -1; }
+
+ template <typename _Graph>
+ struct Constraints {
+
+ void constraints() {
+ checkConcept<IDableDigraphComponent<Base>, _Graph >();
+ typename _Graph::Edge edge;
+ int ueid = graph.id(edge);
+ ueid = graph.id(edge);
+ edge = graph.edgeFromId(ueid);
+ ueid = graph.maxEdgeId();
+ ::lemon::ignore_unused_variable_warning(ueid);
+ }
+
+ const _Graph& graph;
+ Constraints() {}
+ };
+ };
+
+ /// \brief Skeleton class for \e idable undirected bipartite graphs.
+ ///
+ /// This class describes the interface of \e idable undirected
+ /// bipartite graphs. It extends \ref IDableGraphComponent with
+ /// the core ID functions of undirected bipartite graphs. Beside
+ /// the regular node ids, this class also provides ids within the
+ /// the red and blue sets of the nodes. This concept is part of
+ /// the BpGraph concept.
+ template <typename BAS = BaseBpGraphComponent>
+ class IDableBpGraphComponent : public IDableGraphComponent<BAS> {
+ public:
+
+ typedef BAS Base;
+ typedef IDableGraphComponent<BAS> Parent;
+ typedef typename Base::Node Node;
+ typedef typename Base::RedNode RedNode;
+ typedef typename Base::BlueNode BlueNode;
+
+ using Parent::id;
+
+ /// \brief Return a unique integer id for the given node in the red set.
+ ///
+ /// Return a unique integer id for the given node in the red set.
+ int id(const RedNode&) const { return -1; }
+
+ /// \brief Return a unique integer id for the given node in the blue set.
+ ///
+ /// Return a unique integer id for the given node in the blue set.
+ int id(const BlueNode&) const { return -1; }
+
+ /// \brief Return an integer greater or equal to the maximum
+ /// node id in the red set.
+ ///
+ /// Return an integer greater or equal to the maximum
+ /// node id in the red set.
+ int maxRedId() const { return -1; }
+
+ /// \brief Return an integer greater or equal to the maximum
+ /// node id in the blue set.
+ ///
+ /// Return an integer greater or equal to the maximum
+ /// node id in the blue set.
+ int maxBlueId() const { return -1; }
+
+ template <typename _BpGraph>
+ struct Constraints {
+
+ void constraints() {
+ checkConcept<IDableGraphComponent<Base>, _BpGraph>();
+ typename _BpGraph::Node node;
+ typename _BpGraph::RedNode red;
+ typename _BpGraph::BlueNode blue;
+ int rid = bpgraph.id(red);
+ int bid = bpgraph.id(blue);
+ rid = bpgraph.maxRedId();
+ bid = bpgraph.maxBlueId();
+ ::lemon::ignore_unused_variable_warning(rid);
+ ::lemon::ignore_unused_variable_warning(bid);
+ }
+
+ const _BpGraph& bpgraph;
+ };
+ };
+
+ /// \brief Concept class for \c NodeIt, \c ArcIt and \c EdgeIt types.
+ ///
+ /// This class describes the concept of \c NodeIt, \c ArcIt and
+ /// \c EdgeIt subtypes of digraph and graph types.
+ template <typename GR, typename Item>
+ class GraphItemIt : public Item {
+ public:
+ /// \brief Default constructor.
+ ///
+ /// Default constructor.
+ /// \warning The default constructor is not required to set
+ /// the iterator to some well-defined value. So you should consider it
+ /// as uninitialized.
+ GraphItemIt() {}
+
+ /// \brief Copy constructor.
+ ///
+ /// Copy constructor.
+ GraphItemIt(const GraphItemIt& it) : Item(it) {}
+
+ /// \brief Constructor that sets the iterator to the first item.
+ ///
+ /// Constructor that sets the iterator to the first item.
+ explicit GraphItemIt(const GR&) {}
+
+ /// \brief Constructor for conversion from \c INVALID.
+ ///
+ /// Constructor for conversion from \c INVALID.
+ /// It initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ GraphItemIt(Invalid) {}
+
+ /// \brief Assignment operator.
+ ///
+ /// Assignment operator for the iterator.
+ GraphItemIt& operator=(const GraphItemIt&) { return *this; }
+
+ /// \brief Increment the iterator.
+ ///
+ /// This operator increments the iterator, i.e. assigns it to the
+ /// next item.
+ GraphItemIt& operator++() { return *this; }
+
+ /// \brief Equality operator
+ ///
+ /// Equality operator.
+ /// Two iterators are equal if and only if they point to the
+ /// same object or both are invalid.
+ bool operator==(const GraphItemIt&) const { return true;}
+
+ /// \brief Inequality operator
+ ///
+ /// Inequality operator.
+ /// Two iterators are equal if and only if they point to the
+ /// same object or both are invalid.
+ bool operator!=(const GraphItemIt&) const { return true;}
+
+ template<typename _GraphItemIt>
+ struct Constraints {
+ void constraints() {
+ checkConcept<GraphItem<>, _GraphItemIt>();
+ _GraphItemIt it1(g);
+ _GraphItemIt it2;
+ _GraphItemIt it3 = it1;
+ _GraphItemIt it4 = INVALID;
+ ::lemon::ignore_unused_variable_warning(it3);
+ ::lemon::ignore_unused_variable_warning(it4);
+
+ it2 = ++it1;
+ ++it2 = it1;
+ ++(++it1);
+
+ Item bi = it1;
+ bi = it2;
+ }
+ const GR& g;
+ Constraints() {}
+ };
+ };
+
+ /// \brief Concept class for \c InArcIt, \c OutArcIt and
+ /// \c IncEdgeIt types.
+ ///
+ /// This class describes the concept of \c InArcIt, \c OutArcIt
+ /// and \c IncEdgeIt subtypes of digraph and graph types.
+ ///
+ /// \note Since these iterator classes do not inherit from the same
+ /// base class, there is an additional template parameter (selector)
+ /// \c sel. For \c InArcIt you should instantiate it with character
+ /// \c 'i', for \c OutArcIt with \c 'o' and for \c IncEdgeIt with \c 'e'.
+ template <typename GR,
+ typename Item = typename GR::Arc,
+ typename Base = typename GR::Node,
+ char sel = '0'>
+ class GraphIncIt : public Item {
+ public:
+ /// \brief Default constructor.
+ ///
+ /// Default constructor.
+ /// \warning The default constructor is not required to set
+ /// the iterator to some well-defined value. So you should consider it
+ /// as uninitialized.
+ GraphIncIt() {}
+
+ /// \brief Copy constructor.
+ ///
+ /// Copy constructor.
+ GraphIncIt(const GraphIncIt& it) : Item(it) {}
+
+ /// \brief Constructor that sets the iterator to the first
+ /// incoming or outgoing arc.
+ ///
+ /// Constructor that sets the iterator to the first arc
+ /// incoming to or outgoing from the given node.
+ explicit GraphIncIt(const GR&, const Base&) {}
+
+ /// \brief Constructor for conversion from \c INVALID.
+ ///
+ /// Constructor for conversion from \c INVALID.
+ /// It initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ GraphIncIt(Invalid) {}
+
+ /// \brief Assignment operator.
+ ///
+ /// Assignment operator for the iterator.
+ GraphIncIt& operator=(const GraphIncIt&) { return *this; }
+
+ /// \brief Increment the iterator.
+ ///
+ /// This operator increments the iterator, i.e. assigns it to the
+ /// next arc incoming to or outgoing from the given node.
+ GraphIncIt& operator++() { return *this; }
+
+ /// \brief Equality operator
+ ///
+ /// Equality operator.
+ /// Two iterators are equal if and only if they point to the
+ /// same object or both are invalid.
+ bool operator==(const GraphIncIt&) const { return true;}
+
+ /// \brief Inequality operator
+ ///
+ /// Inequality operator.
+ /// Two iterators are equal if and only if they point to the
+ /// same object or both are invalid.
+ bool operator!=(const GraphIncIt&) const { return true;}
+
+ template <typename _GraphIncIt>
+ struct Constraints {
+ void constraints() {
+ checkConcept<GraphItem<sel>, _GraphIncIt>();
+ _GraphIncIt it1(graph, node);
+ _GraphIncIt it2;
+ _GraphIncIt it3 = it1;
+ _GraphIncIt it4 = INVALID;
+ ::lemon::ignore_unused_variable_warning(it3);
+ ::lemon::ignore_unused_variable_warning(it4);
+
+ it2 = ++it1;
+ ++it2 = it1;
+ ++(++it1);
+ Item e = it1;
+ e = it2;
+ }
+ const Base& node;
+ const GR& graph;
+ Constraints() {}
+ };
+ };
+
+ /// \brief Skeleton class for iterable directed graphs.
+ ///
+ /// This class describes the interface of iterable directed
+ /// graphs. It extends \ref BaseDigraphComponent with the core
+ /// iterable interface.
+ /// This concept is part of the Digraph concept.
+ template <typename BAS = BaseDigraphComponent>
+ class IterableDigraphComponent : public BAS {
+
+ public:
+
+ typedef BAS Base;
+ typedef typename Base::Node Node;
+ typedef typename Base::Arc Arc;
+
+ typedef IterableDigraphComponent Digraph;
+
+ /// \name Base Iteration
+ ///
+ /// This interface provides functions for iteration on digraph items.
+ ///
+ /// @{
+
+ /// \brief Return the first node.
+ ///
+ /// This function gives back the first node in the iteration order.
+ void first(Node&) const {}
+
+ /// \brief Return the next node.
+ ///
+ /// This function gives back the next node in the iteration order.
+ void next(Node&) const {}
+
+ /// \brief Return the first arc.
+ ///
+ /// This function gives back the first arc in the iteration order.
+ void first(Arc&) const {}
+
+ /// \brief Return the next arc.
+ ///
+ /// This function gives back the next arc in the iteration order.
+ void next(Arc&) const {}
+
+ /// \brief Return the first arc incoming to the given node.
+ ///
+ /// This function gives back the first arc incoming to the
+ /// given node.
+ void firstIn(Arc&, const Node&) const {}
+
+ /// \brief Return the next arc incoming to the given node.
+ ///
+ /// This function gives back the next arc incoming to the
+ /// given node.
+ void nextIn(Arc&) const {}
+
+ /// \brief Return the first arc outgoing form the given node.
+ ///
+ /// This function gives back the first arc outgoing form the
+ /// given node.
+ void firstOut(Arc&, const Node&) const {}
+
+ /// \brief Return the next arc outgoing form the given node.
+ ///
+ /// This function gives back the next arc outgoing form the
+ /// given node.
+ void nextOut(Arc&) const {}
+
+ /// @}
+
+ /// \name Class Based Iteration
+ ///
+ /// This interface provides iterator classes for digraph items.
+ ///
+ /// @{
+
+ /// \brief This iterator goes through each node.
+ ///
+ /// This iterator goes through each node.
+ ///
+ typedef GraphItemIt<Digraph, Node> NodeIt;
+
+ /// \brief This iterator goes through each arc.
+ ///
+ /// This iterator goes through each arc.
+ ///
+ typedef GraphItemIt<Digraph, Arc> ArcIt;
+
+ /// \brief This iterator goes trough the incoming arcs of a node.
+ ///
+ /// This iterator goes trough the \e incoming arcs of a certain node
+ /// of a digraph.
+ typedef GraphIncIt<Digraph, Arc, Node, 'i'> InArcIt;
+
+ /// \brief This iterator goes trough the outgoing arcs of a node.
+ ///
+ /// This iterator goes trough the \e outgoing arcs of a certain node
+ /// of a digraph.
+ typedef GraphIncIt<Digraph, Arc, Node, 'o'> OutArcIt;
+
+ /// \brief The base node of the iterator.
+ ///
+ /// This function gives back the base node of the iterator.
+ /// It is always the target node of the pointed arc.
+ Node baseNode(const InArcIt&) const { return INVALID; }
+
+ /// \brief The running node of the iterator.
+ ///
+ /// This function gives back the running node of the iterator.
+ /// It is always the source node of the pointed arc.
+ Node runningNode(const InArcIt&) const { return INVALID; }
+
+ /// \brief The base node of the iterator.
+ ///
+ /// This function gives back the base node of the iterator.
+ /// It is always the source node of the pointed arc.
+ Node baseNode(const OutArcIt&) const { return INVALID; }
+
+ /// \brief The running node of the iterator.
+ ///
+ /// This function gives back the running node of the iterator.
+ /// It is always the target node of the pointed arc.
+ Node runningNode(const OutArcIt&) const { return INVALID; }
+
+ /// @}
+
+ template <typename _Digraph>
+ struct Constraints {
+ void constraints() {
+ checkConcept<Base, _Digraph>();
+
+ {
+ typename _Digraph::Node node(INVALID);
+ typename _Digraph::Arc arc(INVALID);
+ {
+ digraph.first(node);
+ digraph.next(node);
+ }
+ {
+ digraph.first(arc);
+ digraph.next(arc);
+ }
+ {
+ digraph.firstIn(arc, node);
+ digraph.nextIn(arc);
+ }
+ {
+ digraph.firstOut(arc, node);
+ digraph.nextOut(arc);
+ }
+ }
+
+ {
+ checkConcept<GraphItemIt<_Digraph, typename _Digraph::Arc>,
+ typename _Digraph::ArcIt >();
+ checkConcept<GraphItemIt<_Digraph, typename _Digraph::Node>,
+ typename _Digraph::NodeIt >();
+ checkConcept<GraphIncIt<_Digraph, typename _Digraph::Arc,
+ typename _Digraph::Node, 'i'>, typename _Digraph::InArcIt>();
+ checkConcept<GraphIncIt<_Digraph, typename _Digraph::Arc,
+ typename _Digraph::Node, 'o'>, typename _Digraph::OutArcIt>();
+
+ typename _Digraph::Node n;
+ const typename _Digraph::InArcIt iait(INVALID);
+ const typename _Digraph::OutArcIt oait(INVALID);
+ n = digraph.baseNode(iait);
+ n = digraph.runningNode(iait);
+ n = digraph.baseNode(oait);
+ n = digraph.runningNode(oait);
+ ::lemon::ignore_unused_variable_warning(n);
+ }
+ }
+
+ const _Digraph& digraph;
+ Constraints() {}
+ };
+ };
+
+ /// \brief Skeleton class for iterable undirected graphs.
+ ///
+ /// This class describes the interface of iterable undirected
+ /// graphs. It extends \ref IterableDigraphComponent with the core
+ /// iterable interface of undirected graphs.
+ /// This concept is part of the Graph concept.
+ template <typename BAS = BaseGraphComponent>
+ class IterableGraphComponent : public IterableDigraphComponent<BAS> {
+ public:
+
+ typedef BAS Base;
+ typedef typename Base::Node Node;
+ typedef typename Base::Arc Arc;
+ typedef typename Base::Edge Edge;
+
+
+ typedef IterableGraphComponent Graph;
+
+ /// \name Base Iteration
+ ///
+ /// This interface provides functions for iteration on edges.
+ ///
+ /// @{
+
+ using IterableDigraphComponent<Base>::first;
+ using IterableDigraphComponent<Base>::next;
+
+ /// \brief Return the first edge.
+ ///
+ /// This function gives back the first edge in the iteration order.
+ void first(Edge&) const {}
+
+ /// \brief Return the next edge.
+ ///
+ /// This function gives back the next edge in the iteration order.
+ void next(Edge&) const {}
+
+ /// \brief Return the first edge incident to the given node.
+ ///
+ /// This function gives back the first edge incident to the given
+ /// node. The bool parameter gives back the direction for which the
+ /// source node of the directed arc representing the edge is the
+ /// given node.
+ void firstInc(Edge&, bool&, const Node&) const {}
+
+ /// \brief Gives back the next of the edges from the
+ /// given node.
+ ///
+ /// This function gives back the next edge incident to the given
+ /// node. The bool parameter should be used as \c firstInc() use it.
+ void nextInc(Edge&, bool&) const {}
+
+ using IterableDigraphComponent<Base>::baseNode;
+ using IterableDigraphComponent<Base>::runningNode;
+
+ /// @}
+
+ /// \name Class Based Iteration
+ ///
+ /// This interface provides iterator classes for edges.
+ ///
+ /// @{
+
+ /// \brief This iterator goes through each edge.
+ ///
+ /// This iterator goes through each edge.
+ typedef GraphItemIt<Graph, Edge> EdgeIt;
+
+ /// \brief This iterator goes trough the incident edges of a
+ /// node.
+ ///
+ /// This iterator goes trough the incident edges of a certain
+ /// node of a graph.
+ typedef GraphIncIt<Graph, Edge, Node, 'e'> IncEdgeIt;
+
+ /// \brief The base node of the iterator.
+ ///
+ /// This function gives back the base node of the iterator.
+ Node baseNode(const IncEdgeIt&) const { return INVALID; }
+
+ /// \brief The running node of the iterator.
+ ///
+ /// This function gives back the running node of the iterator.
+ Node runningNode(const IncEdgeIt&) const { return INVALID; }
+
+ /// @}
+
+ template <typename _Graph>
+ struct Constraints {
+ void constraints() {
+ checkConcept<IterableDigraphComponent<Base>, _Graph>();
+
+ {
+ typename _Graph::Node node(INVALID);
+ typename _Graph::Edge edge(INVALID);
+ bool dir;
+ {
+ graph.first(edge);
+ graph.next(edge);
+ }
+ {
+ graph.firstInc(edge, dir, node);
+ graph.nextInc(edge, dir);
+ }
+
+ }
+
+ {
+ checkConcept<GraphItemIt<_Graph, typename _Graph::Edge>,
+ typename _Graph::EdgeIt >();
+ checkConcept<GraphIncIt<_Graph, typename _Graph::Edge,
+ typename _Graph::Node, 'e'>, typename _Graph::IncEdgeIt>();
+
+ typename _Graph::Node n;
+ const typename _Graph::IncEdgeIt ieit(INVALID);
+ n = graph.baseNode(ieit);
+ n = graph.runningNode(ieit);
+ }
+ }
+
+ const _Graph& graph;
+ Constraints() {}
+ };
+ };
+
+ /// \brief Skeleton class for iterable undirected bipartite graphs.
+ ///
+ /// This class describes the interface of iterable undirected
+ /// bipartite graphs. It extends \ref IterableGraphComponent with
+ /// the core iterable interface of undirected bipartite graphs.
+ /// This concept is part of the BpGraph concept.
+ template <typename BAS = BaseBpGraphComponent>
+ class IterableBpGraphComponent : public IterableGraphComponent<BAS> {
+ public:
+
+ typedef BAS Base;
+ typedef typename Base::Node Node;
+ typedef typename Base::RedNode RedNode;
+ typedef typename Base::BlueNode BlueNode;
+ typedef typename Base::Arc Arc;
+ typedef typename Base::Edge Edge;
+
+ typedef IterableBpGraphComponent BpGraph;
+
+ using IterableGraphComponent<BAS>::first;
+ using IterableGraphComponent<BAS>::next;
+
+ /// \name Base Iteration
+ ///
+ /// This interface provides functions for iteration on red and blue nodes.
+ ///
+ /// @{
+
+ /// \brief Return the first red node.
+ ///
+ /// This function gives back the first red node in the iteration order.
+ void first(RedNode&) const {}
+
+ /// \brief Return the next red node.
+ ///
+ /// This function gives back the next red node in the iteration order.
+ void next(RedNode&) const {}
+
+ /// \brief Return the first blue node.
+ ///
+ /// This function gives back the first blue node in the iteration order.
+ void first(BlueNode&) const {}
+
+ /// \brief Return the next blue node.
+ ///
+ /// This function gives back the next blue node in the iteration order.
+ void next(BlueNode&) const {}
+
+
+ /// @}
+
+ /// \name Class Based Iteration
+ ///
+ /// This interface provides iterator classes for red and blue nodes.
+ ///
+ /// @{
+
+ /// \brief This iterator goes through each red node.
+ ///
+ /// This iterator goes through each red node.
+ typedef GraphItemIt<BpGraph, RedNode> RedNodeIt;
+
+ /// \brief This iterator goes through each blue node.
+ ///
+ /// This iterator goes through each blue node.
+ typedef GraphItemIt<BpGraph, BlueNode> BlueNodeIt;
+
+ /// @}
+
+ template <typename _BpGraph>
+ struct Constraints {
+ void constraints() {
+ checkConcept<IterableGraphComponent<Base>, _BpGraph>();
+
+ typename _BpGraph::RedNode rn(INVALID);
+ bpgraph.first(rn);
+ bpgraph.next(rn);
+ typename _BpGraph::BlueNode bn(INVALID);
+ bpgraph.first(bn);
+ bpgraph.next(bn);
+
+ checkConcept<GraphItemIt<_BpGraph, typename _BpGraph::RedNode>,
+ typename _BpGraph::RedNodeIt>();
+ checkConcept<GraphItemIt<_BpGraph, typename _BpGraph::BlueNode>,
+ typename _BpGraph::BlueNodeIt>();
+ }
+
+ const _BpGraph& bpgraph;
+ };
+ };
+
+ /// \brief Skeleton class for alterable directed graphs.
+ ///
+ /// This class describes the interface of alterable directed
+ /// graphs. It extends \ref BaseDigraphComponent with the alteration
+ /// notifier interface. It implements
+ /// an observer-notifier pattern for each digraph item. More
+ /// obsevers can be registered into the notifier and whenever an
+ /// alteration occured in the digraph all the observers will be
+ /// notified about it.
+ template <typename BAS = BaseDigraphComponent>
+ class AlterableDigraphComponent : public BAS {
+ public:
+
+ typedef BAS Base;
+ typedef typename Base::Node Node;
+ typedef typename Base::Arc Arc;
+
+
+ /// Node alteration notifier class.
+ typedef AlterationNotifier<AlterableDigraphComponent, Node>
+ NodeNotifier;
+ /// Arc alteration notifier class.
+ typedef AlterationNotifier<AlterableDigraphComponent, Arc>
+ ArcNotifier;
+
+ mutable NodeNotifier node_notifier;
+ mutable ArcNotifier arc_notifier;
+
+ /// \brief Return the node alteration notifier.
+ ///
+ /// This function gives back the node alteration notifier.
+ NodeNotifier& notifier(Node) const {
+ return node_notifier;
+ }
+
+ /// \brief Return the arc alteration notifier.
+ ///
+ /// This function gives back the arc alteration notifier.
+ ArcNotifier& notifier(Arc) const {
+ return arc_notifier;
+ }
+
+ template <typename _Digraph>
+ struct Constraints {
+ void constraints() {
+ checkConcept<Base, _Digraph>();
+ typename _Digraph::NodeNotifier& nn
+ = digraph.notifier(typename _Digraph::Node());
+
+ typename _Digraph::ArcNotifier& en
+ = digraph.notifier(typename _Digraph::Arc());
+
+ ::lemon::ignore_unused_variable_warning(nn);
+ ::lemon::ignore_unused_variable_warning(en);
+ }
+
+ const _Digraph& digraph;
+ Constraints() {}
+ };
+ };
+
+ /// \brief Skeleton class for alterable undirected graphs.
+ ///
+ /// This class describes the interface of alterable undirected
+ /// graphs. It extends \ref AlterableDigraphComponent with the alteration
+ /// notifier interface of undirected graphs. It implements
+ /// an observer-notifier pattern for the edges. More
+ /// obsevers can be registered into the notifier and whenever an
+ /// alteration occured in the graph all the observers will be
+ /// notified about it.
+ template <typename BAS = BaseGraphComponent>
+ class AlterableGraphComponent : public AlterableDigraphComponent<BAS> {
+ public:
+
+ typedef BAS Base;
+ typedef AlterableDigraphComponent<Base> Parent;
+ typedef typename Base::Edge Edge;
+
+
+ /// Edge alteration notifier class.
+ typedef AlterationNotifier<AlterableGraphComponent, Edge>
+ EdgeNotifier;
+
+ mutable EdgeNotifier edge_notifier;
+
+ using Parent::notifier;
+
+ /// \brief Return the edge alteration notifier.
+ ///
+ /// This function gives back the edge alteration notifier.
+ EdgeNotifier& notifier(Edge) const {
+ return edge_notifier;
+ }
+
+ template <typename _Graph>
+ struct Constraints {
+ void constraints() {
+ checkConcept<AlterableDigraphComponent<Base>, _Graph>();
+ typename _Graph::EdgeNotifier& uen
+ = graph.notifier(typename _Graph::Edge());
+ ::lemon::ignore_unused_variable_warning(uen);
+ }
+
+ const _Graph& graph;
+ Constraints() {}
+ };
+ };
+
+ /// \brief Skeleton class for alterable undirected bipartite graphs.
+ ///
+ /// This class describes the interface of alterable undirected
+ /// bipartite graphs. It extends \ref AlterableGraphComponent with
+ /// the alteration notifier interface of bipartite graphs. It
+ /// implements an observer-notifier pattern for the red and blue
+ /// nodes. More obsevers can be registered into the notifier and
+ /// whenever an alteration occured in the graph all the observers
+ /// will be notified about it.
+ template <typename BAS = BaseBpGraphComponent>
+ class AlterableBpGraphComponent : public AlterableGraphComponent<BAS> {
+ public:
+
+ typedef BAS Base;
+ typedef AlterableGraphComponent<Base> Parent;
+ typedef typename Base::RedNode RedNode;
+ typedef typename Base::BlueNode BlueNode;
+
+
+ /// Red node alteration notifier class.
+ typedef AlterationNotifier<AlterableBpGraphComponent, RedNode>
+ RedNodeNotifier;
+
+ /// Blue node alteration notifier class.
+ typedef AlterationNotifier<AlterableBpGraphComponent, BlueNode>
+ BlueNodeNotifier;
+
+ mutable RedNodeNotifier red_node_notifier;
+ mutable BlueNodeNotifier blue_node_notifier;
+
+ using Parent::notifier;
+
+ /// \brief Return the red node alteration notifier.
+ ///
+ /// This function gives back the red node alteration notifier.
+ RedNodeNotifier& notifier(RedNode) const {
+ return red_node_notifier;
+ }
+
+ /// \brief Return the blue node alteration notifier.
+ ///
+ /// This function gives back the blue node alteration notifier.
+ BlueNodeNotifier& notifier(BlueNode) const {
+ return blue_node_notifier;
+ }
+
+ template <typename _BpGraph>
+ struct Constraints {
+ void constraints() {
+ checkConcept<AlterableGraphComponent<Base>, _BpGraph>();
+ typename _BpGraph::RedNodeNotifier& rnn
+ = bpgraph.notifier(typename _BpGraph::RedNode());
+ typename _BpGraph::BlueNodeNotifier& bnn
+ = bpgraph.notifier(typename _BpGraph::BlueNode());
+ ::lemon::ignore_unused_variable_warning(rnn);
+ ::lemon::ignore_unused_variable_warning(bnn);
+ }
+
+ const _BpGraph& bpgraph;
+ };
+ };
+
+ /// \brief Concept class for standard graph maps.
+ ///
+ /// This class describes the concept of standard graph maps, i.e.
+ /// the \c NodeMap, \c ArcMap and \c EdgeMap subtypes of digraph and
+ /// graph types, which can be used for associating data to graph items.
+ /// The standard graph maps must conform to the ReferenceMap concept.
+ template <typename GR, typename K, typename V>
+ class GraphMap : public ReferenceMap<K, V, V&, const V&> {
+ typedef ReferenceMap<K, V, V&, const V&> Parent;
+
+ public:
+
+ /// The key type of the map.
+ typedef K Key;
+ /// The value type of the map.
+ typedef V Value;
+ /// The reference type of the map.
+ typedef Value& Reference;
+ /// The const reference type of the map.
+ typedef const Value& ConstReference;
+
+ // The reference map tag.
+ typedef True ReferenceMapTag;
+
+ /// \brief Construct a new map.
+ ///
+ /// Construct a new map for the graph.
+ explicit GraphMap(const GR&) {}
+ /// \brief Construct a new map with default value.
+ ///
+ /// Construct a new map for the graph and initalize the values.
+ GraphMap(const GR&, const Value&) {}
+
+ private:
+ /// \brief Copy constructor.
+ ///
+ /// Copy Constructor.
+ GraphMap(const GraphMap&) : Parent() {}
+
+ /// \brief Assignment operator.
+ ///
+ /// Assignment operator. It does not mofify the underlying graph,
+ /// it just iterates on the current item set and set the map
+ /// with the value returned by the assigned map.
+ template <typename CMap>
+ GraphMap& operator=(const CMap&) {
+ checkConcept<ReadMap<Key, Value>, CMap>();
+ return *this;
+ }
+
+ public:
+ template<typename _Map>
+ struct Constraints {
+ void constraints() {
+ checkConcept
+ <ReferenceMap<Key, Value, Value&, const Value&>, _Map>();
+ _Map m1(g);
+ _Map m2(g,t);
+
+ // Copy constructor
+ // _Map m3(m);
+
+ // Assignment operator
+ // ReadMap<Key, Value> cmap;
+ // m3 = cmap;
+
+ ::lemon::ignore_unused_variable_warning(m1);
+ ::lemon::ignore_unused_variable_warning(m2);
+ // ::lemon::ignore_unused_variable_warning(m3);
+ }
+
+ const _Map &m;
+ const GR &g;
+ const typename GraphMap::Value &t;
+ Constraints() {}
+ };
+
+ };
+
+ /// \brief Skeleton class for mappable directed graphs.
+ ///
+ /// This class describes the interface of mappable directed graphs.
+ /// It extends \ref BaseDigraphComponent with the standard digraph
+ /// map classes, namely \c NodeMap and \c ArcMap.
+ /// This concept is part of the Digraph concept.
+ template <typename BAS = BaseDigraphComponent>
+ class MappableDigraphComponent : public BAS {
+ public:
+
+ typedef BAS Base;
+ typedef typename Base::Node Node;
+ typedef typename Base::Arc Arc;
+
+ typedef MappableDigraphComponent Digraph;
+
+ /// \brief Standard graph map for the nodes.
+ ///
+ /// Standard graph map for the nodes.
+ /// It conforms to the ReferenceMap concept.
+ template <typename V>
+ class NodeMap : public GraphMap<MappableDigraphComponent, Node, V> {
+ typedef GraphMap<MappableDigraphComponent, Node, V> Parent;
+
+ public:
+ /// \brief Construct a new map.
+ ///
+ /// Construct a new map for the digraph.
+ explicit NodeMap(const MappableDigraphComponent& digraph)
+ : Parent(digraph) {}
+
+ /// \brief Construct a new map with default value.
+ ///
+ /// Construct a new map for the digraph and initalize the values.
+ NodeMap(const MappableDigraphComponent& digraph, const V& value)
+ : Parent(digraph, value) {}
+
+ private:
+ /// \brief Copy constructor.
+ ///
+ /// Copy Constructor.
+ NodeMap(const NodeMap& nm) : Parent(nm) {}
+
+ /// \brief Assignment operator.
+ ///
+ /// Assignment operator.
+ template <typename CMap>
+ NodeMap& operator=(const CMap&) {
+ checkConcept<ReadMap<Node, V>, CMap>();
+ return *this;
+ }
+
+ };
+
+ /// \brief Standard graph map for the arcs.
+ ///
+ /// Standard graph map for the arcs.
+ /// It conforms to the ReferenceMap concept.
+ template <typename V>
+ class ArcMap : public GraphMap<MappableDigraphComponent, Arc, V> {
+ typedef GraphMap<MappableDigraphComponent, Arc, V> Parent;
+
+ public:
+ /// \brief Construct a new map.
+ ///
+ /// Construct a new map for the digraph.
+ explicit ArcMap(const MappableDigraphComponent& digraph)
+ : Parent(digraph) {}
+
+ /// \brief Construct a new map with default value.
+ ///
+ /// Construct a new map for the digraph and initalize the values.
+ ArcMap(const MappableDigraphComponent& digraph, const V& value)
+ : Parent(digraph, value) {}
+
+ private:
+ /// \brief Copy constructor.
+ ///
+ /// Copy Constructor.
+ ArcMap(const ArcMap& nm) : Parent(nm) {}
+
+ /// \brief Assignment operator.
+ ///
+ /// Assignment operator.
+ template <typename CMap>
+ ArcMap& operator=(const CMap&) {
+ checkConcept<ReadMap<Arc, V>, CMap>();
+ return *this;
+ }
+
+ };
+
+
+ template <typename _Digraph>
+ struct Constraints {
+
+ struct Dummy {
+ int value;
+ Dummy() : value(0) {}
+ Dummy(int _v) : value(_v) {}
+ };
+
+ void constraints() {
+ checkConcept<Base, _Digraph>();
+ { // int map test
+ typedef typename _Digraph::template NodeMap<int> IntNodeMap;
+ checkConcept<GraphMap<_Digraph, typename _Digraph::Node, int>,
+ IntNodeMap >();
+ } { // bool map test
+ typedef typename _Digraph::template NodeMap<bool> BoolNodeMap;
+ checkConcept<GraphMap<_Digraph, typename _Digraph::Node, bool>,
+ BoolNodeMap >();
+ } { // Dummy map test
+ typedef typename _Digraph::template NodeMap<Dummy> DummyNodeMap;
+ checkConcept<GraphMap<_Digraph, typename _Digraph::Node, Dummy>,
+ DummyNodeMap >();
+ }
+
+ { // int map test
+ typedef typename _Digraph::template ArcMap<int> IntArcMap;
+ checkConcept<GraphMap<_Digraph, typename _Digraph::Arc, int>,
+ IntArcMap >();
+ } { // bool map test
+ typedef typename _Digraph::template ArcMap<bool> BoolArcMap;
+ checkConcept<GraphMap<_Digraph, typename _Digraph::Arc, bool>,
+ BoolArcMap >();
+ } { // Dummy map test
+ typedef typename _Digraph::template ArcMap<Dummy> DummyArcMap;
+ checkConcept<GraphMap<_Digraph, typename _Digraph::Arc, Dummy>,
+ DummyArcMap >();
+ }
+ }
+
+ const _Digraph& digraph;
+ Constraints() {}
+ };
+ };
+
+ /// \brief Skeleton class for mappable undirected graphs.
+ ///
+ /// This class describes the interface of mappable undirected graphs.
+ /// It extends \ref MappableDigraphComponent with the standard graph
+ /// map class for edges (\c EdgeMap).
+ /// This concept is part of the Graph concept.
+ template <typename BAS = BaseGraphComponent>
+ class MappableGraphComponent : public MappableDigraphComponent<BAS> {
+ public:
+
+ typedef BAS Base;
+ typedef typename Base::Edge Edge;
+
+ typedef MappableGraphComponent Graph;
+
+ /// \brief Standard graph map for the edges.
+ ///
+ /// Standard graph map for the edges.
+ /// It conforms to the ReferenceMap concept.
+ template <typename V>
+ class EdgeMap : public GraphMap<MappableGraphComponent, Edge, V> {
+ typedef GraphMap<MappableGraphComponent, Edge, V> Parent;
+
+ public:
+ /// \brief Construct a new map.
+ ///
+ /// Construct a new map for the graph.
+ explicit EdgeMap(const MappableGraphComponent& graph)
+ : Parent(graph) {}
+
+ /// \brief Construct a new map with default value.
+ ///
+ /// Construct a new map for the graph and initalize the values.
+ EdgeMap(const MappableGraphComponent& graph, const V& value)
+ : Parent(graph, value) {}
+
+ private:
+ /// \brief Copy constructor.
+ ///
+ /// Copy Constructor.
+ EdgeMap(const EdgeMap& nm) : Parent(nm) {}
+
+ /// \brief Assignment operator.
+ ///
+ /// Assignment operator.
+ template <typename CMap>
+ EdgeMap& operator=(const CMap&) {
+ checkConcept<ReadMap<Edge, V>, CMap>();
+ return *this;
+ }
+
+ };
+
+
+ template <typename _Graph>
+ struct Constraints {
+
+ struct Dummy {
+ int value;
+ Dummy() : value(0) {}
+ Dummy(int _v) : value(_v) {}
+ };
+
+ void constraints() {
+ checkConcept<MappableDigraphComponent<Base>, _Graph>();
+
+ { // int map test
+ typedef typename _Graph::template EdgeMap<int> IntEdgeMap;
+ checkConcept<GraphMap<_Graph, typename _Graph::Edge, int>,
+ IntEdgeMap >();
+ } { // bool map test
+ typedef typename _Graph::template EdgeMap<bool> BoolEdgeMap;
+ checkConcept<GraphMap<_Graph, typename _Graph::Edge, bool>,
+ BoolEdgeMap >();
+ } { // Dummy map test
+ typedef typename _Graph::template EdgeMap<Dummy> DummyEdgeMap;
+ checkConcept<GraphMap<_Graph, typename _Graph::Edge, Dummy>,
+ DummyEdgeMap >();
+ }
+ }
+
+ const _Graph& graph;
+ Constraints() {}
+ };
+ };
+
+ /// \brief Skeleton class for mappable undirected bipartite graphs.
+ ///
+ /// This class describes the interface of mappable undirected
+ /// bipartite graphs. It extends \ref MappableGraphComponent with
+ /// the standard graph map class for red and blue nodes (\c
+ /// RedNodeMap and BlueNodeMap). This concept is part of the
+ /// BpGraph concept.
+ template <typename BAS = BaseBpGraphComponent>
+ class MappableBpGraphComponent : public MappableGraphComponent<BAS> {
+ public:
+
+ typedef BAS Base;
+ typedef typename Base::Node Node;
+
+ typedef MappableBpGraphComponent BpGraph;
+
+ /// \brief Standard graph map for the red nodes.
+ ///
+ /// Standard graph map for the red nodes.
+ /// It conforms to the ReferenceMap concept.
+ template <typename V>
+ class RedNodeMap : public GraphMap<MappableBpGraphComponent, Node, V> {
+ typedef GraphMap<MappableBpGraphComponent, Node, V> Parent;
+
+ public:
+ /// \brief Construct a new map.
+ ///
+ /// Construct a new map for the graph.
+ explicit RedNodeMap(const MappableBpGraphComponent& graph)
+ : Parent(graph) {}
+
+ /// \brief Construct a new map with default value.
+ ///
+ /// Construct a new map for the graph and initalize the values.
+ RedNodeMap(const MappableBpGraphComponent& graph, const V& value)
+ : Parent(graph, value) {}
+
+ private:
+ /// \brief Copy constructor.
+ ///
+ /// Copy Constructor.
+ RedNodeMap(const RedNodeMap& nm) : Parent(nm) {}
+
+ /// \brief Assignment operator.
+ ///
+ /// Assignment operator.
+ template <typename CMap>
+ RedNodeMap& operator=(const CMap&) {
+ checkConcept<ReadMap<Node, V>, CMap>();
+ return *this;
+ }
+
+ };
+
+ /// \brief Standard graph map for the blue nodes.
+ ///
+ /// Standard graph map for the blue nodes.
+ /// It conforms to the ReferenceMap concept.
+ template <typename V>
+ class BlueNodeMap : public GraphMap<MappableBpGraphComponent, Node, V> {
+ typedef GraphMap<MappableBpGraphComponent, Node, V> Parent;
+
+ public:
+ /// \brief Construct a new map.
+ ///
+ /// Construct a new map for the graph.
+ explicit BlueNodeMap(const MappableBpGraphComponent& graph)
+ : Parent(graph) {}
+
+ /// \brief Construct a new map with default value.
+ ///
+ /// Construct a new map for the graph and initalize the values.
+ BlueNodeMap(const MappableBpGraphComponent& graph, const V& value)
+ : Parent(graph, value) {}
+
+ private:
+ /// \brief Copy constructor.
+ ///
+ /// Copy Constructor.
+ BlueNodeMap(const BlueNodeMap& nm) : Parent(nm) {}
+
+ /// \brief Assignment operator.
+ ///
+ /// Assignment operator.
+ template <typename CMap>
+ BlueNodeMap& operator=(const CMap&) {
+ checkConcept<ReadMap<Node, V>, CMap>();
+ return *this;
+ }
+
+ };
+
+
+ template <typename _BpGraph>
+ struct Constraints {
+
+ struct Dummy {
+ int value;
+ Dummy() : value(0) {}
+ Dummy(int _v) : value(_v) {}
+ };
+
+ void constraints() {
+ checkConcept<MappableGraphComponent<Base>, _BpGraph>();
+
+ { // int map test
+ typedef typename _BpGraph::template RedNodeMap<int>
+ IntRedNodeMap;
+ checkConcept<GraphMap<_BpGraph, typename _BpGraph::RedNode, int>,
+ IntRedNodeMap >();
+ } { // bool map test
+ typedef typename _BpGraph::template RedNodeMap<bool>
+ BoolRedNodeMap;
+ checkConcept<GraphMap<_BpGraph, typename _BpGraph::RedNode, bool>,
+ BoolRedNodeMap >();
+ } { // Dummy map test
+ typedef typename _BpGraph::template RedNodeMap<Dummy>
+ DummyRedNodeMap;
+ checkConcept<GraphMap<_BpGraph, typename _BpGraph::RedNode, Dummy>,
+ DummyRedNodeMap >();
+ }
+
+ { // int map test
+ typedef typename _BpGraph::template BlueNodeMap<int>
+ IntBlueNodeMap;
+ checkConcept<GraphMap<_BpGraph, typename _BpGraph::BlueNode, int>,
+ IntBlueNodeMap >();
+ } { // bool map test
+ typedef typename _BpGraph::template BlueNodeMap<bool>
+ BoolBlueNodeMap;
+ checkConcept<GraphMap<_BpGraph, typename _BpGraph::BlueNode, bool>,
+ BoolBlueNodeMap >();
+ } { // Dummy map test
+ typedef typename _BpGraph::template BlueNodeMap<Dummy>
+ DummyBlueNodeMap;
+ checkConcept<GraphMap<_BpGraph, typename _BpGraph::BlueNode, Dummy>,
+ DummyBlueNodeMap >();
+ }
+ }
+
+ const _BpGraph& bpgraph;
+ };
+ };
+
+ /// \brief Skeleton class for extendable directed graphs.
+ ///
+ /// This class describes the interface of extendable directed graphs.
+ /// It extends \ref BaseDigraphComponent with functions for adding
+ /// nodes and arcs to the digraph.
+ /// This concept requires \ref AlterableDigraphComponent.
+ template <typename BAS = BaseDigraphComponent>
+ class ExtendableDigraphComponent : public BAS {
+ public:
+ typedef BAS Base;
+
+ typedef typename Base::Node Node;
+ typedef typename Base::Arc Arc;
+
+ /// \brief Add a new node to the digraph.
+ ///
+ /// This function adds a new node to the digraph.
+ Node addNode() {
+ return INVALID;
+ }
+
+ /// \brief Add a new arc connecting the given two nodes.
+ ///
+ /// This function adds a new arc connecting the given two nodes
+ /// of the digraph.
+ Arc addArc(const Node&, const Node&) {
+ return INVALID;
+ }
+
+ template <typename _Digraph>
+ struct Constraints {
+ void constraints() {
+ checkConcept<Base, _Digraph>();
+ typename _Digraph::Node node_a, node_b;
+ node_a = digraph.addNode();
+ node_b = digraph.addNode();
+ typename _Digraph::Arc arc;
+ arc = digraph.addArc(node_a, node_b);
+ }
+
+ _Digraph& digraph;
+ Constraints() {}
+ };
+ };
+
+ /// \brief Skeleton class for extendable undirected graphs.
+ ///
+ /// This class describes the interface of extendable undirected graphs.
+ /// It extends \ref BaseGraphComponent with functions for adding
+ /// nodes and edges to the graph.
+ /// This concept requires \ref AlterableGraphComponent.
+ template <typename BAS = BaseGraphComponent>
+ class ExtendableGraphComponent : public BAS {
+ public:
+
+ typedef BAS Base;
+ typedef typename Base::Node Node;
+ typedef typename Base::Edge Edge;
+
+ /// \brief Add a new node to the digraph.
+ ///
+ /// This function adds a new node to the digraph.
+ Node addNode() {
+ return INVALID;
+ }
+
+ /// \brief Add a new edge connecting the given two nodes.
+ ///
+ /// This function adds a new edge connecting the given two nodes
+ /// of the graph.
+ Edge addEdge(const Node&, const Node&) {
+ return INVALID;
+ }
+
+ template <typename _Graph>
+ struct Constraints {
+ void constraints() {
+ checkConcept<Base, _Graph>();
+ typename _Graph::Node node_a, node_b;
+ node_a = graph.addNode();
+ node_b = graph.addNode();
+ typename _Graph::Edge edge;
+ edge = graph.addEdge(node_a, node_b);
+ }
+
+ _Graph& graph;
+ Constraints() {}
+ };
+ };
+
+ /// \brief Skeleton class for extendable undirected bipartite graphs.
+ ///
+ /// This class describes the interface of extendable undirected
+ /// bipartite graphs. It extends \ref BaseGraphComponent with
+ /// functions for adding nodes and edges to the graph. This
+ /// concept requires \ref AlterableBpGraphComponent.
+ template <typename BAS = BaseBpGraphComponent>
+ class ExtendableBpGraphComponent : public BAS {
+ public:
+
+ typedef BAS Base;
+ typedef typename Base::Node Node;
+ typedef typename Base::RedNode RedNode;
+ typedef typename Base::BlueNode BlueNode;
+ typedef typename Base::Edge Edge;
+
+ /// \brief Add a new red node to the digraph.
+ ///
+ /// This function adds a red new node to the digraph.
+ RedNode addRedNode() {
+ return INVALID;
+ }
+
+ /// \brief Add a new blue node to the digraph.
+ ///
+ /// This function adds a blue new node to the digraph.
+ BlueNode addBlueNode() {
+ return INVALID;
+ }
+
+ /// \brief Add a new edge connecting the given two nodes.
+ ///
+ /// This function adds a new edge connecting the given two nodes
+ /// of the graph. The first node has to be a red node, and the
+ /// second one a blue node.
+ Edge addEdge(const RedNode&, const BlueNode&) {
+ return INVALID;
+ }
+ Edge addEdge(const BlueNode&, const RedNode&) {
+ return INVALID;
+ }
+
+ template <typename _BpGraph>
+ struct Constraints {
+ void constraints() {
+ checkConcept<Base, _BpGraph>();
+ typename _BpGraph::RedNode red_node;
+ typename _BpGraph::BlueNode blue_node;
+ red_node = bpgraph.addRedNode();
+ blue_node = bpgraph.addBlueNode();
+ typename _BpGraph::Edge edge;
+ edge = bpgraph.addEdge(red_node, blue_node);
+ edge = bpgraph.addEdge(blue_node, red_node);
+ }
+
+ _BpGraph& bpgraph;
+ };
+ };
+
+ /// \brief Skeleton class for erasable directed graphs.
+ ///
+ /// This class describes the interface of erasable directed graphs.
+ /// It extends \ref BaseDigraphComponent with functions for removing
+ /// nodes and arcs from the digraph.
+ /// This concept requires \ref AlterableDigraphComponent.
+ template <typename BAS = BaseDigraphComponent>
+ class ErasableDigraphComponent : public BAS {
+ public:
+
+ typedef BAS Base;
+ typedef typename Base::Node Node;
+ typedef typename Base::Arc Arc;
+
+ /// \brief Erase a node from the digraph.
+ ///
+ /// This function erases the given node from the digraph and all arcs
+ /// connected to the node.
+ void erase(const Node&) {}
+
+ /// \brief Erase an arc from the digraph.
+ ///
+ /// This function erases the given arc from the digraph.
+ void erase(const Arc&) {}
+
+ template <typename _Digraph>
+ struct Constraints {
+ void constraints() {
+ checkConcept<Base, _Digraph>();
+ const typename _Digraph::Node node(INVALID);
+ digraph.erase(node);
+ const typename _Digraph::Arc arc(INVALID);
+ digraph.erase(arc);
+ }
+
+ _Digraph& digraph;
+ Constraints() {}
+ };
+ };
+
+ /// \brief Skeleton class for erasable undirected graphs.
+ ///
+ /// This class describes the interface of erasable undirected graphs.
+ /// It extends \ref BaseGraphComponent with functions for removing
+ /// nodes and edges from the graph.
+ /// This concept requires \ref AlterableGraphComponent.
+ template <typename BAS = BaseGraphComponent>
+ class ErasableGraphComponent : public BAS {
+ public:
+
+ typedef BAS Base;
+ typedef typename Base::Node Node;
+ typedef typename Base::Edge Edge;
+
+ /// \brief Erase a node from the graph.
+ ///
+ /// This function erases the given node from the graph and all edges
+ /// connected to the node.
+ void erase(const Node&) {}
+
+ /// \brief Erase an edge from the digraph.
+ ///
+ /// This function erases the given edge from the digraph.
+ void erase(const Edge&) {}
+
+ template <typename _Graph>
+ struct Constraints {
+ void constraints() {
+ checkConcept<Base, _Graph>();
+ const typename _Graph::Node node(INVALID);
+ graph.erase(node);
+ const typename _Graph::Edge edge(INVALID);
+ graph.erase(edge);
+ }
+
+ _Graph& graph;
+ Constraints() {}
+ };
+ };
+
+ /// \brief Skeleton class for erasable undirected graphs.
+ ///
+ /// This class describes the interface of erasable undirected
+ /// bipartite graphs. It extends \ref BaseBpGraphComponent with
+ /// functions for removing nodes and edges from the graph. This
+ /// concept requires \ref AlterableBpGraphComponent.
+ template <typename BAS = BaseBpGraphComponent>
+ class ErasableBpGraphComponent : public ErasableGraphComponent<BAS> {};
+
+ /// \brief Skeleton class for clearable directed graphs.
+ ///
+ /// This class describes the interface of clearable directed graphs.
+ /// It extends \ref BaseDigraphComponent with a function for clearing
+ /// the digraph.
+ /// This concept requires \ref AlterableDigraphComponent.
+ template <typename BAS = BaseDigraphComponent>
+ class ClearableDigraphComponent : public BAS {
+ public:
+
+ typedef BAS Base;
+
+ /// \brief Erase all nodes and arcs from the digraph.
+ ///
+ /// This function erases all nodes and arcs from the digraph.
+ void clear() {}
+
+ template <typename _Digraph>
+ struct Constraints {
+ void constraints() {
+ checkConcept<Base, _Digraph>();
+ digraph.clear();
+ }
+
+ _Digraph& digraph;
+ Constraints() {}
+ };
+ };
+
+ /// \brief Skeleton class for clearable undirected graphs.
+ ///
+ /// This class describes the interface of clearable undirected graphs.
+ /// It extends \ref BaseGraphComponent with a function for clearing
+ /// the graph.
+ /// This concept requires \ref AlterableGraphComponent.
+ template <typename BAS = BaseGraphComponent>
+ class ClearableGraphComponent : public ClearableDigraphComponent<BAS> {};
+
+ /// \brief Skeleton class for clearable undirected biparite graphs.
+ ///
+ /// This class describes the interface of clearable undirected
+ /// bipartite graphs. It extends \ref BaseBpGraphComponent with a
+ /// function for clearing the graph. This concept requires \ref
+ /// AlterableBpGraphComponent.
+ template <typename BAS = BaseBpGraphComponent>
+ class ClearableBpGraphComponent : public ClearableGraphComponent<BAS> {};
+
+ }
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/heap.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/heap.h
new file mode 100644
index 00000000000..8c7a2512144
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/heap.h
@@ -0,0 +1,324 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_CONCEPTS_HEAP_H
+#define LEMON_CONCEPTS_HEAP_H
+
+///\ingroup concept
+///\file
+///\brief The concept of heaps.
+
+#include <lemon/core.h>
+#include <lemon/concept_check.h>
+
+namespace lemon {
+
+ namespace concepts {
+
+ /// \addtogroup concept
+ /// @{
+
+ /// \brief The heap concept.
+ ///
+ /// This concept class describes the main interface of heaps.
+ /// The various \ref heaps "heap structures" are efficient
+ /// implementations of the abstract data type \e priority \e queue.
+ /// They store items with specified values called \e priorities
+ /// in such a way that finding and removing the item with minimum
+ /// priority are efficient. The basic operations are adding and
+ /// erasing items, changing the priority of an item, etc.
+ ///
+ /// Heaps are crucial in several algorithms, such as Dijkstra and Prim.
+ /// Any class that conforms to this concept can be used easily in such
+ /// algorithms.
+ ///
+ /// \tparam PR Type of the priorities of the items.
+ /// \tparam IM A read-writable item map with \c int values, used
+ /// internally to handle the cross references.
+ /// \tparam CMP A functor class for comparing the priorities.
+ /// The default is \c std::less<PR>.
+#ifdef DOXYGEN
+ template <typename PR, typename IM, typename CMP>
+#else
+ template <typename PR, typename IM, typename CMP = std::less<PR> >
+#endif
+ class Heap {
+ public:
+
+ /// Type of the item-int map.
+ typedef IM ItemIntMap;
+ /// Type of the priorities.
+ typedef PR Prio;
+ /// Type of the items stored in the heap.
+ typedef typename ItemIntMap::Key Item;
+
+ /// \brief Type to represent the states of the items.
+ ///
+ /// Each item has a state associated to it. It can be "in heap",
+ /// "pre-heap" or "post-heap". The latter two are indifferent from the
+ /// heap's point of view, but may be useful to the user.
+ ///
+ /// The item-int map must be initialized in such way that it assigns
+ /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
+ enum State {
+ IN_HEAP = 0, ///< = 0. The "in heap" state constant.
+ PRE_HEAP = -1, ///< = -1. The "pre-heap" state constant.
+ POST_HEAP = -2 ///< = -2. The "post-heap" state constant.
+ };
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// \param map A map that assigns \c int values to keys of type
+ /// \c Item. It is used internally by the heap implementations to
+ /// handle the cross references. The assigned value must be
+ /// \c PRE_HEAP (<tt>-1</tt>) for each item.
+#ifdef DOXYGEN
+ explicit Heap(ItemIntMap &map) {}
+#else
+ explicit Heap(ItemIntMap&) {}
+#endif
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// \param map A map that assigns \c int values to keys of type
+ /// \c Item. It is used internally by the heap implementations to
+ /// handle the cross references. The assigned value must be
+ /// \c PRE_HEAP (<tt>-1</tt>) for each item.
+ /// \param comp The function object used for comparing the priorities.
+#ifdef DOXYGEN
+ explicit Heap(ItemIntMap &map, const CMP &comp) {}
+#else
+ explicit Heap(ItemIntMap&, const CMP&) {}
+#endif
+
+ /// \brief The number of items stored in the heap.
+ ///
+ /// This function returns the number of items stored in the heap.
+ int size() const { return 0; }
+
+ /// \brief Check if the heap is empty.
+ ///
+ /// This function returns \c true if the heap is empty.
+ bool empty() const { return false; }
+
+ /// \brief Make the heap empty.
+ ///
+ /// This functon makes the heap empty.
+ /// It does not change the cross reference map. If you want to reuse
+ /// a heap that is not surely empty, you should first clear it and
+ /// then you should set the cross reference map to \c PRE_HEAP
+ /// for each item.
+ void clear() {}
+
+ /// \brief Insert an item into the heap with the given priority.
+ ///
+ /// This function inserts the given item into the heap with the
+ /// given priority.
+ /// \param i The item to insert.
+ /// \param p The priority of the item.
+ /// \pre \e i must not be stored in the heap.
+#ifdef DOXYGEN
+ void push(const Item &i, const Prio &p) {}
+#else
+ void push(const Item&, const Prio&) {}
+#endif
+
+ /// \brief Return the item having minimum priority.
+ ///
+ /// This function returns the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ Item top() const { return Item(); }
+
+ /// \brief The minimum priority.
+ ///
+ /// This function returns the minimum priority.
+ /// \pre The heap must be non-empty.
+ Prio prio() const { return Prio(); }
+
+ /// \brief Remove the item having minimum priority.
+ ///
+ /// This function removes the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ void pop() {}
+
+ /// \brief Remove the given item from the heap.
+ ///
+ /// This function removes the given item from the heap if it is
+ /// already stored.
+ /// \param i The item to delete.
+ /// \pre \e i must be in the heap.
+#ifdef DOXYGEN
+ void erase(const Item &i) {}
+#else
+ void erase(const Item&) {}
+#endif
+
+ /// \brief The priority of the given item.
+ ///
+ /// This function returns the priority of the given item.
+ /// \param i The item.
+ /// \pre \e i must be in the heap.
+#ifdef DOXYGEN
+ Prio operator[](const Item &i) const {}
+#else
+ Prio operator[](const Item&) const { return Prio(); }
+#endif
+
+ /// \brief Set the priority of an item or insert it, if it is
+ /// not stored in the heap.
+ ///
+ /// This method sets the priority of the given item if it is
+ /// already stored in the heap. Otherwise it inserts the given
+ /// item into the heap with the given priority.
+ ///
+ /// \param i The item.
+ /// \param p The priority.
+#ifdef DOXYGEN
+ void set(const Item &i, const Prio &p) {}
+#else
+ void set(const Item&, const Prio&) {}
+#endif
+
+ /// \brief Decrease the priority of an item to the given value.
+ ///
+ /// This function decreases the priority of an item to the given value.
+ /// \param i The item.
+ /// \param p The priority.
+ /// \pre \e i must be stored in the heap with priority at least \e p.
+#ifdef DOXYGEN
+ void decrease(const Item &i, const Prio &p) {}
+#else
+ void decrease(const Item&, const Prio&) {}
+#endif
+
+ /// \brief Increase the priority of an item to the given value.
+ ///
+ /// This function increases the priority of an item to the given value.
+ /// \param i The item.
+ /// \param p The priority.
+ /// \pre \e i must be stored in the heap with priority at most \e p.
+#ifdef DOXYGEN
+ void increase(const Item &i, const Prio &p) {}
+#else
+ void increase(const Item&, const Prio&) {}
+#endif
+
+ /// \brief Return the state of an item.
+ ///
+ /// This method returns \c PRE_HEAP if the given item has never
+ /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
+ /// and \c POST_HEAP otherwise.
+ /// In the latter case it is possible that the item will get back
+ /// to the heap again.
+ /// \param i The item.
+#ifdef DOXYGEN
+ State state(const Item &i) const {}
+#else
+ State state(const Item&) const { return PRE_HEAP; }
+#endif
+
+ /// \brief Set the state of an item in the heap.
+ ///
+ /// This function sets the state of the given item in the heap.
+ /// It can be used to manually clear the heap when it is important
+ /// to achive better time complexity.
+ /// \param i The item.
+ /// \param st The state. It should not be \c IN_HEAP.
+#ifdef DOXYGEN
+ void state(const Item& i, State st) {}
+#else
+ void state(const Item&, State) {}
+#endif
+
+
+ template <typename _Heap>
+ struct Constraints {
+ public:
+ void constraints() {
+ typedef typename _Heap::Item OwnItem;
+ typedef typename _Heap::Prio OwnPrio;
+ typedef typename _Heap::State OwnState;
+
+ Item item;
+ Prio prio;
+ item=Item();
+ prio=Prio();
+ ::lemon::ignore_unused_variable_warning(item);
+ ::lemon::ignore_unused_variable_warning(prio);
+
+ OwnItem own_item;
+ OwnPrio own_prio;
+ OwnState own_state;
+ own_item=Item();
+ own_prio=Prio();
+ ::lemon::ignore_unused_variable_warning(own_item);
+ ::lemon::ignore_unused_variable_warning(own_prio);
+ ::lemon::ignore_unused_variable_warning(own_state);
+
+ _Heap heap1(map);
+ _Heap heap2 = heap1;
+ ::lemon::ignore_unused_variable_warning(heap1);
+ ::lemon::ignore_unused_variable_warning(heap2);
+
+ int s = heap.size();
+ ::lemon::ignore_unused_variable_warning(s);
+ bool e = heap.empty();
+ ::lemon::ignore_unused_variable_warning(e);
+
+ prio = heap.prio();
+ item = heap.top();
+ prio = heap[item];
+ own_prio = heap.prio();
+ own_item = heap.top();
+ own_prio = heap[own_item];
+
+ heap.push(item, prio);
+ heap.push(own_item, own_prio);
+ heap.pop();
+
+ heap.set(item, prio);
+ heap.decrease(item, prio);
+ heap.increase(item, prio);
+ heap.set(own_item, own_prio);
+ heap.decrease(own_item, own_prio);
+ heap.increase(own_item, own_prio);
+
+ heap.erase(item);
+ heap.erase(own_item);
+ heap.clear();
+
+ own_state = heap.state(own_item);
+ heap.state(own_item, own_state);
+
+ own_state = _Heap::PRE_HEAP;
+ own_state = _Heap::IN_HEAP;
+ own_state = _Heap::POST_HEAP;
+ }
+
+ _Heap& heap;
+ ItemIntMap& map;
+ Constraints() {}
+ };
+ };
+
+ /// @}
+ } // namespace lemon
+}
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/maps.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/maps.h
new file mode 100644
index 00000000000..88b66b51118
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/maps.h
@@ -0,0 +1,223 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_CONCEPTS_MAPS_H
+#define LEMON_CONCEPTS_MAPS_H
+
+#include <lemon/core.h>
+#include <lemon/concept_check.h>
+
+///\ingroup map_concepts
+///\file
+///\brief The concept of maps.
+
+namespace lemon {
+
+ namespace concepts {
+
+ /// \addtogroup map_concepts
+ /// @{
+
+ /// Readable map concept
+
+ /// Readable map concept.
+ ///
+ template<typename K, typename T>
+ class ReadMap
+ {
+ public:
+ /// The key type of the map.
+ typedef K Key;
+ /// \brief The value type of the map.
+ /// (The type of objects associated with the keys).
+ typedef T Value;
+
+ /// Returns the value associated with the given key.
+ Value operator[](const Key &) const {
+ return *(static_cast<Value *>(0)+1);
+ }
+
+ template<typename _ReadMap>
+ struct Constraints {
+ void constraints() {
+ Value val = m[key];
+ val = m[key];
+ typename _ReadMap::Value own_val = m[own_key];
+ own_val = m[own_key];
+
+ ::lemon::ignore_unused_variable_warning(key);
+ ::lemon::ignore_unused_variable_warning(val);
+ ::lemon::ignore_unused_variable_warning(own_key);
+ ::lemon::ignore_unused_variable_warning(own_val);
+ }
+ const Key& key;
+ const typename _ReadMap::Key& own_key;
+ const _ReadMap& m;
+ Constraints() {}
+ };
+
+ };
+
+
+ /// Writable map concept
+
+ /// Writable map concept.
+ ///
+ template<typename K, typename T>
+ class WriteMap
+ {
+ public:
+ /// The key type of the map.
+ typedef K Key;
+ /// \brief The value type of the map.
+ /// (The type of objects associated with the keys).
+ typedef T Value;
+
+ /// Sets the value associated with the given key.
+ void set(const Key &, const Value &) {}
+
+ /// Default constructor.
+ WriteMap() {}
+
+ template <typename _WriteMap>
+ struct Constraints {
+ void constraints() {
+ m.set(key, val);
+ m.set(own_key, own_val);
+
+ ::lemon::ignore_unused_variable_warning(key);
+ ::lemon::ignore_unused_variable_warning(val);
+ ::lemon::ignore_unused_variable_warning(own_key);
+ ::lemon::ignore_unused_variable_warning(own_val);
+ }
+ const Key& key;
+ const Value& val;
+ const typename _WriteMap::Key& own_key;
+ const typename _WriteMap::Value& own_val;
+ _WriteMap& m;
+ Constraints() {}
+ };
+ };
+
+ /// Read/writable map concept
+
+ /// Read/writable map concept.
+ ///
+ template<typename K, typename T>
+ class ReadWriteMap : public ReadMap<K,T>,
+ public WriteMap<K,T>
+ {
+ public:
+ /// The key type of the map.
+ typedef K Key;
+ /// \brief The value type of the map.
+ /// (The type of objects associated with the keys).
+ typedef T Value;
+
+ /// Returns the value associated with the given key.
+ Value operator[](const Key &) const {
+ Value *r = 0;
+ return *r;
+ }
+
+ /// Sets the value associated with the given key.
+ void set(const Key &, const Value &) {}
+
+ template<typename _ReadWriteMap>
+ struct Constraints {
+ void constraints() {
+ checkConcept<ReadMap<K, T>, _ReadWriteMap >();
+ checkConcept<WriteMap<K, T>, _ReadWriteMap >();
+ }
+ };
+ };
+
+
+ /// Dereferable map concept
+
+ /// Dereferable map concept.
+ ///
+ template<typename K, typename T, typename R, typename CR>
+ class ReferenceMap : public ReadWriteMap<K,T>
+ {
+ public:
+ /// Tag for reference maps.
+ typedef True ReferenceMapTag;
+ /// The key type of the map.
+ typedef K Key;
+ /// \brief The value type of the map.
+ /// (The type of objects associated with the keys).
+ typedef T Value;
+ /// The reference type of the map.
+ typedef R Reference;
+ /// The const reference type of the map.
+ typedef CR ConstReference;
+
+ public:
+
+ /// Returns a reference to the value associated with the given key.
+ Reference operator[](const Key &) {
+ Value *r = 0;
+ return *r;
+ }
+
+ /// Returns a const reference to the value associated with the given key.
+ ConstReference operator[](const Key &) const {
+ Value *r = 0;
+ return *r;
+ }
+
+ /// Sets the value associated with the given key.
+ void set(const Key &k,const Value &t) { operator[](k)=t; }
+
+ template<typename _ReferenceMap>
+ struct Constraints {
+ typename enable_if<typename _ReferenceMap::ReferenceMapTag, void>::type
+ constraints() {
+ checkConcept<ReadWriteMap<K, T>, _ReferenceMap >();
+ ref = m[key];
+ m[key] = val;
+ m[key] = ref;
+ m[key] = cref;
+ own_ref = m[own_key];
+ m[own_key] = own_val;
+ m[own_key] = own_ref;
+ m[own_key] = own_cref;
+ m[key] = m[own_key];
+ m[own_key] = m[key];
+ }
+ const Key& key;
+ Value& val;
+ Reference ref;
+ ConstReference cref;
+ const typename _ReferenceMap::Key& own_key;
+ typename _ReferenceMap::Value& own_val;
+ typename _ReferenceMap::Reference own_ref;
+ typename _ReferenceMap::ConstReference own_cref;
+ _ReferenceMap& m;
+ Constraints() {}
+ };
+ };
+
+ // @}
+
+ } //namespace concepts
+
+} //namespace lemon
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/path.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/path.h
new file mode 100644
index 00000000000..18e4b01803d
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/concepts/path.h
@@ -0,0 +1,312 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\ingroup concept
+///\file
+///\brief The concept of paths
+///
+
+#ifndef LEMON_CONCEPTS_PATH_H
+#define LEMON_CONCEPTS_PATH_H
+
+#include <lemon/core.h>
+#include <lemon/concept_check.h>
+
+namespace lemon {
+ namespace concepts {
+
+ /// \addtogroup concept
+ /// @{
+
+ /// \brief A skeleton structure for representing directed paths in
+ /// a digraph.
+ ///
+ /// A skeleton structure for representing directed paths in a
+ /// digraph.
+ /// In a sense, a path can be treated as a list of arcs.
+ /// LEMON path types just store this list. As a consequence, they cannot
+ /// enumerate the nodes on the path directly and a zero length path
+ /// cannot store its source node.
+ ///
+ /// The arcs of a path should be stored in the order of their directions,
+ /// i.e. the target node of each arc should be the same as the source
+ /// node of the next arc. This consistency could be checked using
+ /// \ref checkPath().
+ /// The source and target nodes of a (consistent) path can be obtained
+ /// using \ref pathSource() and \ref pathTarget().
+ ///
+ /// A path can be constructed from another path of any type using the
+ /// copy constructor or the assignment operator.
+ ///
+ /// \tparam GR The digraph type in which the path is.
+ template <typename GR>
+ class Path {
+ public:
+
+ /// Type of the underlying digraph.
+ typedef GR Digraph;
+ /// Arc type of the underlying digraph.
+ typedef typename Digraph::Arc Arc;
+
+ class ArcIt;
+
+ /// \brief Default constructor
+ Path() {}
+
+ /// \brief Template copy constructor
+ template <typename CPath>
+ Path(const CPath& cpath) {}
+
+ /// \brief Template assigment operator
+ template <typename CPath>
+ Path& operator=(const CPath& cpath) {
+ ::lemon::ignore_unused_variable_warning(cpath);
+ return *this;
+ }
+
+ /// Length of the path, i.e. the number of arcs on the path.
+ int length() const { return 0;}
+
+ /// Returns whether the path is empty.
+ bool empty() const { return true;}
+
+ /// Resets the path to an empty path.
+ void clear() {}
+
+ /// \brief LEMON style iterator for enumerating the arcs of a path.
+ ///
+ /// LEMON style iterator class for enumerating the arcs of a path.
+ class ArcIt {
+ public:
+ /// Default constructor
+ ArcIt() {}
+ /// Invalid constructor
+ ArcIt(Invalid) {}
+ /// Sets the iterator to the first arc of the given path
+ ArcIt(const Path &) {}
+
+ /// Conversion to \c Arc
+ operator Arc() const { return INVALID; }
+
+ /// Next arc
+ ArcIt& operator++() {return *this;}
+
+ /// Comparison operator
+ bool operator==(const ArcIt&) const {return true;}
+ /// Comparison operator
+ bool operator!=(const ArcIt&) const {return true;}
+ /// Comparison operator
+ bool operator<(const ArcIt&) const {return false;}
+
+ };
+
+ template <typename _Path>
+ struct Constraints {
+ void constraints() {
+ Path<Digraph> pc;
+ _Path p, pp(pc);
+ int l = p.length();
+ int e = p.empty();
+ p.clear();
+
+ p = pc;
+
+ typename _Path::ArcIt id, ii(INVALID), i(p);
+
+ ++i;
+ typename Digraph::Arc ed = i;
+
+ e = (i == ii);
+ e = (i != ii);
+ e = (i < ii);
+
+ ::lemon::ignore_unused_variable_warning(l);
+ ::lemon::ignore_unused_variable_warning(pp);
+ ::lemon::ignore_unused_variable_warning(e);
+ ::lemon::ignore_unused_variable_warning(id);
+ ::lemon::ignore_unused_variable_warning(ii);
+ ::lemon::ignore_unused_variable_warning(ed);
+ }
+ };
+
+ };
+
+ namespace _path_bits {
+
+ template <typename _Digraph, typename _Path, typename RevPathTag = void>
+ struct PathDumperConstraints {
+ void constraints() {
+ int l = p.length();
+ int e = p.empty();
+
+ typename _Path::ArcIt id, i(p);
+
+ ++i;
+ typename _Digraph::Arc ed = i;
+
+ e = (i == INVALID);
+ e = (i != INVALID);
+
+ ::lemon::ignore_unused_variable_warning(l);
+ ::lemon::ignore_unused_variable_warning(e);
+ ::lemon::ignore_unused_variable_warning(id);
+ ::lemon::ignore_unused_variable_warning(ed);
+ }
+ _Path& p;
+ PathDumperConstraints() {}
+ };
+
+ template <typename _Digraph, typename _Path>
+ struct PathDumperConstraints<
+ _Digraph, _Path,
+ typename enable_if<typename _Path::RevPathTag, void>::type
+ > {
+ void constraints() {
+ int l = p.length();
+ int e = p.empty();
+
+ typename _Path::RevArcIt id, i(p);
+
+ ++i;
+ typename _Digraph::Arc ed = i;
+
+ e = (i == INVALID);
+ e = (i != INVALID);
+
+ ::lemon::ignore_unused_variable_warning(l);
+ ::lemon::ignore_unused_variable_warning(e);
+ ::lemon::ignore_unused_variable_warning(id);
+ ::lemon::ignore_unused_variable_warning(ed);
+ }
+ _Path& p;
+ PathDumperConstraints() {}
+ };
+
+ }
+
+
+ /// \brief A skeleton structure for path dumpers.
+ ///
+ /// A skeleton structure for path dumpers. The path dumpers are
+ /// the generalization of the paths, they can enumerate the arcs
+ /// of the path either in forward or in backward order.
+ /// These classes are typically not used directly, they are rather
+ /// used to be assigned to a real path type.
+ ///
+ /// The main purpose of this concept is that the shortest path
+ /// algorithms can enumerate the arcs easily in reverse order.
+ /// In LEMON, such algorithms give back a (reverse) path dumper that
+ /// can be assigned to a real path. The dumpers can be implemented as
+ /// an adaptor class to the predecessor map.
+ ///
+ /// \tparam GR The digraph type in which the path is.
+ template <typename GR>
+ class PathDumper {
+ public:
+
+ /// Type of the underlying digraph.
+ typedef GR Digraph;
+ /// Arc type of the underlying digraph.
+ typedef typename Digraph::Arc Arc;
+
+ /// Length of the path, i.e. the number of arcs on the path.
+ int length() const { return 0;}
+
+ /// Returns whether the path is empty.
+ bool empty() const { return true;}
+
+ /// \brief Forward or reverse dumping
+ ///
+ /// If this tag is defined to be \c True, then reverse dumping
+ /// is provided in the path dumper. In this case, \c RevArcIt
+ /// iterator should be implemented instead of \c ArcIt iterator.
+ typedef False RevPathTag;
+
+ /// \brief LEMON style iterator for enumerating the arcs of a path.
+ ///
+ /// LEMON style iterator class for enumerating the arcs of a path.
+ class ArcIt {
+ public:
+ /// Default constructor
+ ArcIt() {}
+ /// Invalid constructor
+ ArcIt(Invalid) {}
+ /// Sets the iterator to the first arc of the given path
+ ArcIt(const PathDumper&) {}
+
+ /// Conversion to \c Arc
+ operator Arc() const { return INVALID; }
+
+ /// Next arc
+ ArcIt& operator++() {return *this;}
+
+ /// Comparison operator
+ bool operator==(const ArcIt&) const {return true;}
+ /// Comparison operator
+ bool operator!=(const ArcIt&) const {return true;}
+ /// Comparison operator
+ bool operator<(const ArcIt&) const {return false;}
+
+ };
+
+ /// \brief LEMON style iterator for enumerating the arcs of a path
+ /// in reverse direction.
+ ///
+ /// LEMON style iterator class for enumerating the arcs of a path
+ /// in reverse direction.
+ class RevArcIt {
+ public:
+ /// Default constructor
+ RevArcIt() {}
+ /// Invalid constructor
+ RevArcIt(Invalid) {}
+ /// Sets the iterator to the last arc of the given path
+ RevArcIt(const PathDumper &) {}
+
+ /// Conversion to \c Arc
+ operator Arc() const { return INVALID; }
+
+ /// Next arc
+ RevArcIt& operator++() {return *this;}
+
+ /// Comparison operator
+ bool operator==(const RevArcIt&) const {return true;}
+ /// Comparison operator
+ bool operator!=(const RevArcIt&) const {return true;}
+ /// Comparison operator
+ bool operator<(const RevArcIt&) const {return false;}
+
+ };
+
+ template <typename _Path>
+ struct Constraints {
+ void constraints() {
+ function_requires<_path_bits::
+ PathDumperConstraints<Digraph, _Path> >();
+ }
+ };
+
+ };
+
+
+ ///@}
+ }
+
+} // namespace lemon
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/config.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/config.h
new file mode 100644
index 00000000000..b9699a223fb
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/config.h
@@ -0,0 +1,22 @@
+#define LEMON_VERSION ""
+/* #undef LEMON_HAVE_LONG_LONG */
+
+/* #undef LEMON_HAVE_LP */
+/* #undef LEMON_HAVE_MIP */
+/* #undef LEMON_HAVE_GLPK */
+/* #undef LEMON_HAVE_CPLEX */
+/* #undef LEMON_HAVE_SOPLEX */
+/* #undef LEMON_HAVE_CLP */
+/* #undef LEMON_HAVE_CBC */
+
+#define _LEMON_CPLEX 1
+#define _LEMON_CLP 2
+#define _LEMON_GLPK 3
+#define _LEMON_SOPLEX 4
+#define _LEMON_CBC 5
+
+/* #undef LEMON_DEFAULT_LP */
+/* #undef LEMON_DEFAULT_MIP */
+
+/* #undef LEMON_USE_PTHREAD */
+/* #undef LEMON_USE_WIN32_THREADS */
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/config.h.in b/extern/quadriflow/3rd/lemon-1.3.1/lemon/config.h.in
new file mode 100644
index 00000000000..37d8c04d733
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/config.h.in
@@ -0,0 +1,22 @@
+#define LEMON_VERSION "@PROJECT_VERSION@"
+#cmakedefine LEMON_HAVE_LONG_LONG 1
+
+#cmakedefine LEMON_HAVE_LP 1
+#cmakedefine LEMON_HAVE_MIP 1
+#cmakedefine LEMON_HAVE_GLPK 1
+#cmakedefine LEMON_HAVE_CPLEX 1
+#cmakedefine LEMON_HAVE_SOPLEX 1
+#cmakedefine LEMON_HAVE_CLP 1
+#cmakedefine LEMON_HAVE_CBC 1
+
+#define _LEMON_CPLEX 1
+#define _LEMON_CLP 2
+#define _LEMON_GLPK 3
+#define _LEMON_SOPLEX 4
+#define _LEMON_CBC 5
+
+#cmakedefine LEMON_DEFAULT_LP _LEMON_@LEMON_DEFAULT_LP@
+#cmakedefine LEMON_DEFAULT_MIP _LEMON_@LEMON_DEFAULT_MIP@
+
+#cmakedefine LEMON_USE_PTHREAD 1
+#cmakedefine LEMON_USE_WIN32_THREADS 1
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/connectivity.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/connectivity.h
new file mode 100644
index 00000000000..6bd85a18818
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/connectivity.h
@@ -0,0 +1,1688 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_CONNECTIVITY_H
+#define LEMON_CONNECTIVITY_H
+
+#include <lemon/dfs.h>
+#include <lemon/bfs.h>
+#include <lemon/core.h>
+#include <lemon/maps.h>
+#include <lemon/adaptors.h>
+
+#include <lemon/concepts/digraph.h>
+#include <lemon/concepts/graph.h>
+#include <lemon/concept_check.h>
+
+#include <stack>
+#include <functional>
+
+/// \ingroup graph_properties
+/// \file
+/// \brief Connectivity algorithms
+///
+/// Connectivity algorithms
+
+namespace lemon {
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Check whether an undirected graph is connected.
+ ///
+ /// This function checks whether the given undirected graph is connected,
+ /// i.e. there is a path between any two nodes in the graph.
+ ///
+ /// \return \c true if the graph is connected.
+ /// \note By definition, the empty graph is connected.
+ ///
+ /// \see countConnectedComponents(), connectedComponents()
+ /// \see stronglyConnected()
+ template <typename Graph>
+ bool connected(const Graph& graph) {
+ checkConcept<concepts::Graph, Graph>();
+ typedef typename Graph::NodeIt NodeIt;
+ if (NodeIt(graph) == INVALID) return true;
+ Dfs<Graph> dfs(graph);
+ dfs.run(NodeIt(graph));
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Count the number of connected components of an undirected graph
+ ///
+ /// This function counts the number of connected components of the given
+ /// undirected graph.
+ ///
+ /// The connected components are the classes of an equivalence relation
+ /// on the nodes of an undirected graph. Two nodes are in the same class
+ /// if they are connected with a path.
+ ///
+ /// \return The number of connected components.
+ /// \note By definition, the empty graph consists
+ /// of zero connected components.
+ ///
+ /// \see connected(), connectedComponents()
+ template <typename Graph>
+ int countConnectedComponents(const Graph &graph) {
+ checkConcept<concepts::Graph, Graph>();
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Arc Arc;
+
+ typedef NullMap<Node, Arc> PredMap;
+ typedef NullMap<Node, int> DistMap;
+
+ int compNum = 0;
+ typename Bfs<Graph>::
+ template SetPredMap<PredMap>::
+ template SetDistMap<DistMap>::
+ Create bfs(graph);
+
+ PredMap predMap;
+ bfs.predMap(predMap);
+
+ DistMap distMap;
+ bfs.distMap(distMap);
+
+ bfs.init();
+ for(typename Graph::NodeIt n(graph); n != INVALID; ++n) {
+ if (!bfs.reached(n)) {
+ bfs.addSource(n);
+ bfs.start();
+ ++compNum;
+ }
+ }
+ return compNum;
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Find the connected components of an undirected graph
+ ///
+ /// This function finds the connected components of the given undirected
+ /// graph.
+ ///
+ /// The connected components are the classes of an equivalence relation
+ /// on the nodes of an undirected graph. Two nodes are in the same class
+ /// if they are connected with a path.
+ ///
+ /// \image html connected_components.png
+ /// \image latex connected_components.eps "Connected components" width=\textwidth
+ ///
+ /// \param graph The undirected graph.
+ /// \retval compMap A writable node map. The values will be set from 0 to
+ /// the number of the connected components minus one. Each value of the map
+ /// will be set exactly once, and the values of a certain component will be
+ /// set continuously.
+ /// \return The number of connected components.
+ /// \note By definition, the empty graph consists
+ /// of zero connected components.
+ ///
+ /// \see connected(), countConnectedComponents()
+ template <class Graph, class NodeMap>
+ int connectedComponents(const Graph &graph, NodeMap &compMap) {
+ checkConcept<concepts::Graph, Graph>();
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Arc Arc;
+ checkConcept<concepts::WriteMap<Node, int>, NodeMap>();
+
+ typedef NullMap<Node, Arc> PredMap;
+ typedef NullMap<Node, int> DistMap;
+
+ int compNum = 0;
+ typename Bfs<Graph>::
+ template SetPredMap<PredMap>::
+ template SetDistMap<DistMap>::
+ Create bfs(graph);
+
+ PredMap predMap;
+ bfs.predMap(predMap);
+
+ DistMap distMap;
+ bfs.distMap(distMap);
+
+ bfs.init();
+ for(typename Graph::NodeIt n(graph); n != INVALID; ++n) {
+ if(!bfs.reached(n)) {
+ bfs.addSource(n);
+ while (!bfs.emptyQueue()) {
+ compMap.set(bfs.nextNode(), compNum);
+ bfs.processNextNode();
+ }
+ ++compNum;
+ }
+ }
+ return compNum;
+ }
+
+ namespace _connectivity_bits {
+
+ template <typename Digraph, typename Iterator >
+ struct LeaveOrderVisitor : public DfsVisitor<Digraph> {
+ public:
+ typedef typename Digraph::Node Node;
+ LeaveOrderVisitor(Iterator it) : _it(it) {}
+
+ void leave(const Node& node) {
+ *(_it++) = node;
+ }
+
+ private:
+ Iterator _it;
+ };
+
+ template <typename Digraph, typename Map>
+ struct FillMapVisitor : public DfsVisitor<Digraph> {
+ public:
+ typedef typename Digraph::Node Node;
+ typedef typename Map::Value Value;
+
+ FillMapVisitor(Map& map, Value& value)
+ : _map(map), _value(value) {}
+
+ void reach(const Node& node) {
+ _map.set(node, _value);
+ }
+ private:
+ Map& _map;
+ Value& _value;
+ };
+
+ template <typename Digraph, typename ArcMap>
+ struct StronglyConnectedCutArcsVisitor : public DfsVisitor<Digraph> {
+ public:
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::Arc Arc;
+
+ StronglyConnectedCutArcsVisitor(const Digraph& digraph,
+ ArcMap& cutMap,
+ int& cutNum)
+ : _digraph(digraph), _cutMap(cutMap), _cutNum(cutNum),
+ _compMap(digraph, -1), _num(-1) {
+ }
+
+ void start(const Node&) {
+ ++_num;
+ }
+
+ void reach(const Node& node) {
+ _compMap.set(node, _num);
+ }
+
+ void examine(const Arc& arc) {
+ if (_compMap[_digraph.source(arc)] !=
+ _compMap[_digraph.target(arc)]) {
+ _cutMap.set(arc, true);
+ ++_cutNum;
+ }
+ }
+ private:
+ const Digraph& _digraph;
+ ArcMap& _cutMap;
+ int& _cutNum;
+
+ typename Digraph::template NodeMap<int> _compMap;
+ int _num;
+ };
+
+ }
+
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Check whether a directed graph is strongly connected.
+ ///
+ /// This function checks whether the given directed graph is strongly
+ /// connected, i.e. any two nodes of the digraph are
+ /// connected with directed paths in both direction.
+ ///
+ /// \return \c true if the digraph is strongly connected.
+ /// \note By definition, the empty digraph is strongly connected.
+ ///
+ /// \see countStronglyConnectedComponents(), stronglyConnectedComponents()
+ /// \see connected()
+ template <typename Digraph>
+ bool stronglyConnected(const Digraph& digraph) {
+ checkConcept<concepts::Digraph, Digraph>();
+
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::NodeIt NodeIt;
+
+ typename Digraph::Node source = NodeIt(digraph);
+ if (source == INVALID) return true;
+
+ using namespace _connectivity_bits;
+
+ typedef DfsVisitor<Digraph> Visitor;
+ Visitor visitor;
+
+ DfsVisit<Digraph, Visitor> dfs(digraph, visitor);
+ dfs.init();
+ dfs.addSource(source);
+ dfs.start();
+
+ for (NodeIt it(digraph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ return false;
+ }
+ }
+
+ typedef ReverseDigraph<const Digraph> RDigraph;
+ typedef typename RDigraph::NodeIt RNodeIt;
+ RDigraph rdigraph(digraph);
+
+ typedef DfsVisitor<RDigraph> RVisitor;
+ RVisitor rvisitor;
+
+ DfsVisit<RDigraph, RVisitor> rdfs(rdigraph, rvisitor);
+ rdfs.init();
+ rdfs.addSource(source);
+ rdfs.start();
+
+ for (RNodeIt it(rdigraph); it != INVALID; ++it) {
+ if (!rdfs.reached(it)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Count the number of strongly connected components of a
+ /// directed graph
+ ///
+ /// This function counts the number of strongly connected components of
+ /// the given directed graph.
+ ///
+ /// The strongly connected components are the classes of an
+ /// equivalence relation on the nodes of a digraph. Two nodes are in
+ /// the same class if they are connected with directed paths in both
+ /// direction.
+ ///
+ /// \return The number of strongly connected components.
+ /// \note By definition, the empty digraph has zero
+ /// strongly connected components.
+ ///
+ /// \see stronglyConnected(), stronglyConnectedComponents()
+ template <typename Digraph>
+ int countStronglyConnectedComponents(const Digraph& digraph) {
+ checkConcept<concepts::Digraph, Digraph>();
+
+ using namespace _connectivity_bits;
+
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::NodeIt NodeIt;
+ typedef typename Digraph::ArcIt ArcIt;
+
+ typedef std::vector<Node> Container;
+ typedef typename Container::iterator Iterator;
+
+ Container nodes(countNodes(digraph));
+ typedef LeaveOrderVisitor<Digraph, Iterator> Visitor;
+ Visitor visitor(nodes.begin());
+
+ DfsVisit<Digraph, Visitor> dfs(digraph, visitor);
+ dfs.init();
+ for (NodeIt it(digraph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
+
+ typedef typename Container::reverse_iterator RIterator;
+ typedef ReverseDigraph<const Digraph> RDigraph;
+
+ RDigraph rdigraph(digraph);
+
+ typedef DfsVisitor<Digraph> RVisitor;
+ RVisitor rvisitor;
+
+ DfsVisit<RDigraph, RVisitor> rdfs(rdigraph, rvisitor);
+
+ int compNum = 0;
+
+ rdfs.init();
+ for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
+ if (!rdfs.reached(*it)) {
+ rdfs.addSource(*it);
+ rdfs.start();
+ ++compNum;
+ }
+ }
+ return compNum;
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Find the strongly connected components of a directed graph
+ ///
+ /// This function finds the strongly connected components of the given
+ /// directed graph. In addition, the numbering of the components will
+ /// satisfy that there is no arc going from a higher numbered component
+ /// to a lower one (i.e. it provides a topological order of the components).
+ ///
+ /// The strongly connected components are the classes of an
+ /// equivalence relation on the nodes of a digraph. Two nodes are in
+ /// the same class if they are connected with directed paths in both
+ /// direction.
+ ///
+ /// \image html strongly_connected_components.png
+ /// \image latex strongly_connected_components.eps "Strongly connected components" width=\textwidth
+ ///
+ /// \param digraph The digraph.
+ /// \retval compMap A writable node map. The values will be set from 0 to
+ /// the number of the strongly connected components minus one. Each value
+ /// of the map will be set exactly once, and the values of a certain
+ /// component will be set continuously.
+ /// \return The number of strongly connected components.
+ /// \note By definition, the empty digraph has zero
+ /// strongly connected components.
+ ///
+ /// \see stronglyConnected(), countStronglyConnectedComponents()
+ template <typename Digraph, typename NodeMap>
+ int stronglyConnectedComponents(const Digraph& digraph, NodeMap& compMap) {
+ checkConcept<concepts::Digraph, Digraph>();
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::NodeIt NodeIt;
+ checkConcept<concepts::WriteMap<Node, int>, NodeMap>();
+
+ using namespace _connectivity_bits;
+
+ typedef std::vector<Node> Container;
+ typedef typename Container::iterator Iterator;
+
+ Container nodes(countNodes(digraph));
+ typedef LeaveOrderVisitor<Digraph, Iterator> Visitor;
+ Visitor visitor(nodes.begin());
+
+ DfsVisit<Digraph, Visitor> dfs(digraph, visitor);
+ dfs.init();
+ for (NodeIt it(digraph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
+
+ typedef typename Container::reverse_iterator RIterator;
+ typedef ReverseDigraph<const Digraph> RDigraph;
+
+ RDigraph rdigraph(digraph);
+
+ int compNum = 0;
+
+ typedef FillMapVisitor<RDigraph, NodeMap> RVisitor;
+ RVisitor rvisitor(compMap, compNum);
+
+ DfsVisit<RDigraph, RVisitor> rdfs(rdigraph, rvisitor);
+
+ rdfs.init();
+ for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
+ if (!rdfs.reached(*it)) {
+ rdfs.addSource(*it);
+ rdfs.start();
+ ++compNum;
+ }
+ }
+ return compNum;
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Find the cut arcs of the strongly connected components.
+ ///
+ /// This function finds the cut arcs of the strongly connected components
+ /// of the given digraph.
+ ///
+ /// The strongly connected components are the classes of an
+ /// equivalence relation on the nodes of a digraph. Two nodes are in
+ /// the same class if they are connected with directed paths in both
+ /// direction.
+ /// The strongly connected components are separated by the cut arcs.
+ ///
+ /// \param digraph The digraph.
+ /// \retval cutMap A writable arc map. The values will be set to \c true
+ /// for the cut arcs (exactly once for each cut arc), and will not be
+ /// changed for other arcs.
+ /// \return The number of cut arcs.
+ ///
+ /// \see stronglyConnected(), stronglyConnectedComponents()
+ template <typename Digraph, typename ArcMap>
+ int stronglyConnectedCutArcs(const Digraph& digraph, ArcMap& cutMap) {
+ checkConcept<concepts::Digraph, Digraph>();
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::NodeIt NodeIt;
+ checkConcept<concepts::WriteMap<Arc, bool>, ArcMap>();
+
+ using namespace _connectivity_bits;
+
+ typedef std::vector<Node> Container;
+ typedef typename Container::iterator Iterator;
+
+ Container nodes(countNodes(digraph));
+ typedef LeaveOrderVisitor<Digraph, Iterator> Visitor;
+ Visitor visitor(nodes.begin());
+
+ DfsVisit<Digraph, Visitor> dfs(digraph, visitor);
+ dfs.init();
+ for (NodeIt it(digraph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
+
+ typedef typename Container::reverse_iterator RIterator;
+ typedef ReverseDigraph<const Digraph> RDigraph;
+
+ RDigraph rdigraph(digraph);
+
+ int cutNum = 0;
+
+ typedef StronglyConnectedCutArcsVisitor<RDigraph, ArcMap> RVisitor;
+ RVisitor rvisitor(rdigraph, cutMap, cutNum);
+
+ DfsVisit<RDigraph, RVisitor> rdfs(rdigraph, rvisitor);
+
+ rdfs.init();
+ for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
+ if (!rdfs.reached(*it)) {
+ rdfs.addSource(*it);
+ rdfs.start();
+ }
+ }
+ return cutNum;
+ }
+
+ namespace _connectivity_bits {
+
+ template <typename Digraph>
+ class CountBiNodeConnectedComponentsVisitor : public DfsVisitor<Digraph> {
+ public:
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::Edge Edge;
+
+ CountBiNodeConnectedComponentsVisitor(const Digraph& graph, int &compNum)
+ : _graph(graph), _compNum(compNum),
+ _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
+
+ void start(const Node& node) {
+ _predMap.set(node, INVALID);
+ }
+
+ void reach(const Node& node) {
+ _numMap.set(node, _num);
+ _retMap.set(node, _num);
+ ++_num;
+ }
+
+ void discover(const Arc& edge) {
+ _predMap.set(_graph.target(edge), _graph.source(edge));
+ }
+
+ void examine(const Arc& edge) {
+ if (_graph.source(edge) == _graph.target(edge) &&
+ _graph.direction(edge)) {
+ ++_compNum;
+ return;
+ }
+ if (_predMap[_graph.source(edge)] == _graph.target(edge)) {
+ return;
+ }
+ if (_retMap[_graph.source(edge)] > _numMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _numMap[_graph.target(edge)]);
+ }
+ }
+
+ void backtrack(const Arc& edge) {
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
+ }
+ if (_numMap[_graph.source(edge)] <= _retMap[_graph.target(edge)]) {
+ ++_compNum;
+ }
+ }
+
+ private:
+ const Digraph& _graph;
+ int& _compNum;
+
+ typename Digraph::template NodeMap<int> _numMap;
+ typename Digraph::template NodeMap<int> _retMap;
+ typename Digraph::template NodeMap<Node> _predMap;
+ int _num;
+ };
+
+ template <typename Digraph, typename ArcMap>
+ class BiNodeConnectedComponentsVisitor : public DfsVisitor<Digraph> {
+ public:
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::Edge Edge;
+
+ BiNodeConnectedComponentsVisitor(const Digraph& graph,
+ ArcMap& compMap, int &compNum)
+ : _graph(graph), _compMap(compMap), _compNum(compNum),
+ _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
+
+ void start(const Node& node) {
+ _predMap.set(node, INVALID);
+ }
+
+ void reach(const Node& node) {
+ _numMap.set(node, _num);
+ _retMap.set(node, _num);
+ ++_num;
+ }
+
+ void discover(const Arc& edge) {
+ Node target = _graph.target(edge);
+ _predMap.set(target, edge);
+ _edgeStack.push(edge);
+ }
+
+ void examine(const Arc& edge) {
+ Node source = _graph.source(edge);
+ Node target = _graph.target(edge);
+ if (source == target && _graph.direction(edge)) {
+ _compMap.set(edge, _compNum);
+ ++_compNum;
+ return;
+ }
+ if (_numMap[target] < _numMap[source]) {
+ if (_predMap[source] != _graph.oppositeArc(edge)) {
+ _edgeStack.push(edge);
+ }
+ }
+ if (_predMap[source] != INVALID &&
+ target == _graph.source(_predMap[source])) {
+ return;
+ }
+ if (_retMap[source] > _numMap[target]) {
+ _retMap.set(source, _numMap[target]);
+ }
+ }
+
+ void backtrack(const Arc& edge) {
+ Node source = _graph.source(edge);
+ Node target = _graph.target(edge);
+ if (_retMap[source] > _retMap[target]) {
+ _retMap.set(source, _retMap[target]);
+ }
+ if (_numMap[source] <= _retMap[target]) {
+ while (_edgeStack.top() != edge) {
+ _compMap.set(_edgeStack.top(), _compNum);
+ _edgeStack.pop();
+ }
+ _compMap.set(edge, _compNum);
+ _edgeStack.pop();
+ ++_compNum;
+ }
+ }
+
+ private:
+ const Digraph& _graph;
+ ArcMap& _compMap;
+ int& _compNum;
+
+ typename Digraph::template NodeMap<int> _numMap;
+ typename Digraph::template NodeMap<int> _retMap;
+ typename Digraph::template NodeMap<Arc> _predMap;
+ std::stack<Edge> _edgeStack;
+ int _num;
+ };
+
+
+ template <typename Digraph, typename NodeMap>
+ class BiNodeConnectedCutNodesVisitor : public DfsVisitor<Digraph> {
+ public:
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::Edge Edge;
+
+ BiNodeConnectedCutNodesVisitor(const Digraph& graph, NodeMap& cutMap,
+ int& cutNum)
+ : _graph(graph), _cutMap(cutMap), _cutNum(cutNum),
+ _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
+
+ void start(const Node& node) {
+ _predMap.set(node, INVALID);
+ rootCut = false;
+ }
+
+ void reach(const Node& node) {
+ _numMap.set(node, _num);
+ _retMap.set(node, _num);
+ ++_num;
+ }
+
+ void discover(const Arc& edge) {
+ _predMap.set(_graph.target(edge), _graph.source(edge));
+ }
+
+ void examine(const Arc& edge) {
+ if (_graph.source(edge) == _graph.target(edge) &&
+ _graph.direction(edge)) {
+ if (!_cutMap[_graph.source(edge)]) {
+ _cutMap.set(_graph.source(edge), true);
+ ++_cutNum;
+ }
+ return;
+ }
+ if (_predMap[_graph.source(edge)] == _graph.target(edge)) return;
+ if (_retMap[_graph.source(edge)] > _numMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _numMap[_graph.target(edge)]);
+ }
+ }
+
+ void backtrack(const Arc& edge) {
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
+ }
+ if (_numMap[_graph.source(edge)] <= _retMap[_graph.target(edge)]) {
+ if (_predMap[_graph.source(edge)] != INVALID) {
+ if (!_cutMap[_graph.source(edge)]) {
+ _cutMap.set(_graph.source(edge), true);
+ ++_cutNum;
+ }
+ } else if (rootCut) {
+ if (!_cutMap[_graph.source(edge)]) {
+ _cutMap.set(_graph.source(edge), true);
+ ++_cutNum;
+ }
+ } else {
+ rootCut = true;
+ }
+ }
+ }
+
+ private:
+ const Digraph& _graph;
+ NodeMap& _cutMap;
+ int& _cutNum;
+
+ typename Digraph::template NodeMap<int> _numMap;
+ typename Digraph::template NodeMap<int> _retMap;
+ typename Digraph::template NodeMap<Node> _predMap;
+ std::stack<Edge> _edgeStack;
+ int _num;
+ bool rootCut;
+ };
+
+ }
+
+ template <typename Graph>
+ int countBiNodeConnectedComponents(const Graph& graph);
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Check whether an undirected graph is bi-node-connected.
+ ///
+ /// This function checks whether the given undirected graph is
+ /// bi-node-connected, i.e. a connected graph without articulation
+ /// node.
+ ///
+ /// \return \c true if the graph bi-node-connected.
+ ///
+ /// \note By definition,
+ /// \li a graph consisting of zero or one node is bi-node-connected,
+ /// \li a graph consisting of two isolated nodes
+ /// is \e not bi-node-connected and
+ /// \li a graph consisting of two nodes connected by an edge
+ /// is bi-node-connected.
+ ///
+ /// \see countBiNodeConnectedComponents(), biNodeConnectedComponents()
+ template <typename Graph>
+ bool biNodeConnected(const Graph& graph) {
+ bool hasNonIsolated = false, hasIsolated = false;
+ for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
+ if (typename Graph::OutArcIt(graph, n) == INVALID) {
+ if (hasIsolated || hasNonIsolated) {
+ return false;
+ } else {
+ hasIsolated = true;
+ }
+ } else {
+ if (hasIsolated) {
+ return false;
+ } else {
+ hasNonIsolated = true;
+ }
+ }
+ }
+ return countBiNodeConnectedComponents(graph) <= 1;
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Count the number of bi-node-connected components of an
+ /// undirected graph.
+ ///
+ /// This function counts the number of bi-node-connected components of
+ /// the given undirected graph.
+ ///
+ /// The bi-node-connected components are the classes of an equivalence
+ /// relation on the edges of a undirected graph. Two edges are in the
+ /// same class if they are on same circle.
+ ///
+ /// \return The number of bi-node-connected components.
+ ///
+ /// \see biNodeConnected(), biNodeConnectedComponents()
+ template <typename Graph>
+ int countBiNodeConnectedComponents(const Graph& graph) {
+ checkConcept<concepts::Graph, Graph>();
+ typedef typename Graph::NodeIt NodeIt;
+
+ using namespace _connectivity_bits;
+
+ typedef CountBiNodeConnectedComponentsVisitor<Graph> Visitor;
+
+ int compNum = 0;
+ Visitor visitor(graph, compNum);
+
+ DfsVisit<Graph, Visitor> dfs(graph, visitor);
+ dfs.init();
+
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
+ return compNum;
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Find the bi-node-connected components of an undirected graph.
+ ///
+ /// This function finds the bi-node-connected components of the given
+ /// undirected graph.
+ ///
+ /// The bi-node-connected components are the classes of an equivalence
+ /// relation on the edges of a undirected graph. Two edges are in the
+ /// same class if they are on same circle.
+ ///
+ /// \image html node_biconnected_components.png
+ /// \image latex node_biconnected_components.eps "bi-node-connected components" width=\textwidth
+ ///
+ /// \param graph The undirected graph.
+ /// \retval compMap A writable edge map. The values will be set from 0
+ /// to the number of the bi-node-connected components minus one. Each
+ /// value of the map will be set exactly once, and the values of a
+ /// certain component will be set continuously.
+ /// \return The number of bi-node-connected components.
+ ///
+ /// \see biNodeConnected(), countBiNodeConnectedComponents()
+ template <typename Graph, typename EdgeMap>
+ int biNodeConnectedComponents(const Graph& graph,
+ EdgeMap& compMap) {
+ checkConcept<concepts::Graph, Graph>();
+ typedef typename Graph::NodeIt NodeIt;
+ typedef typename Graph::Edge Edge;
+ checkConcept<concepts::WriteMap<Edge, int>, EdgeMap>();
+
+ using namespace _connectivity_bits;
+
+ typedef BiNodeConnectedComponentsVisitor<Graph, EdgeMap> Visitor;
+
+ int compNum = 0;
+ Visitor visitor(graph, compMap, compNum);
+
+ DfsVisit<Graph, Visitor> dfs(graph, visitor);
+ dfs.init();
+
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
+ return compNum;
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Find the bi-node-connected cut nodes in an undirected graph.
+ ///
+ /// This function finds the bi-node-connected cut nodes in the given
+ /// undirected graph.
+ ///
+ /// The bi-node-connected components are the classes of an equivalence
+ /// relation on the edges of a undirected graph. Two edges are in the
+ /// same class if they are on same circle.
+ /// The bi-node-connected components are separted by the cut nodes of
+ /// the components.
+ ///
+ /// \param graph The undirected graph.
+ /// \retval cutMap A writable node map. The values will be set to
+ /// \c true for the nodes that separate two or more components
+ /// (exactly once for each cut node), and will not be changed for
+ /// other nodes.
+ /// \return The number of the cut nodes.
+ ///
+ /// \see biNodeConnected(), biNodeConnectedComponents()
+ template <typename Graph, typename NodeMap>
+ int biNodeConnectedCutNodes(const Graph& graph, NodeMap& cutMap) {
+ checkConcept<concepts::Graph, Graph>();
+ typedef typename Graph::Node Node;
+ typedef typename Graph::NodeIt NodeIt;
+ checkConcept<concepts::WriteMap<Node, bool>, NodeMap>();
+
+ using namespace _connectivity_bits;
+
+ typedef BiNodeConnectedCutNodesVisitor<Graph, NodeMap> Visitor;
+
+ int cutNum = 0;
+ Visitor visitor(graph, cutMap, cutNum);
+
+ DfsVisit<Graph, Visitor> dfs(graph, visitor);
+ dfs.init();
+
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
+ return cutNum;
+ }
+
+ namespace _connectivity_bits {
+
+ template <typename Digraph>
+ class CountBiEdgeConnectedComponentsVisitor : public DfsVisitor<Digraph> {
+ public:
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::Edge Edge;
+
+ CountBiEdgeConnectedComponentsVisitor(const Digraph& graph, int &compNum)
+ : _graph(graph), _compNum(compNum),
+ _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
+
+ void start(const Node& node) {
+ _predMap.set(node, INVALID);
+ }
+
+ void reach(const Node& node) {
+ _numMap.set(node, _num);
+ _retMap.set(node, _num);
+ ++_num;
+ }
+
+ void leave(const Node& node) {
+ if (_numMap[node] <= _retMap[node]) {
+ ++_compNum;
+ }
+ }
+
+ void discover(const Arc& edge) {
+ _predMap.set(_graph.target(edge), edge);
+ }
+
+ void examine(const Arc& edge) {
+ if (_predMap[_graph.source(edge)] == _graph.oppositeArc(edge)) {
+ return;
+ }
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
+ }
+ }
+
+ void backtrack(const Arc& edge) {
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
+ }
+ }
+
+ private:
+ const Digraph& _graph;
+ int& _compNum;
+
+ typename Digraph::template NodeMap<int> _numMap;
+ typename Digraph::template NodeMap<int> _retMap;
+ typename Digraph::template NodeMap<Arc> _predMap;
+ int _num;
+ };
+
+ template <typename Digraph, typename NodeMap>
+ class BiEdgeConnectedComponentsVisitor : public DfsVisitor<Digraph> {
+ public:
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::Edge Edge;
+
+ BiEdgeConnectedComponentsVisitor(const Digraph& graph,
+ NodeMap& compMap, int &compNum)
+ : _graph(graph), _compMap(compMap), _compNum(compNum),
+ _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
+
+ void start(const Node& node) {
+ _predMap.set(node, INVALID);
+ }
+
+ void reach(const Node& node) {
+ _numMap.set(node, _num);
+ _retMap.set(node, _num);
+ _nodeStack.push(node);
+ ++_num;
+ }
+
+ void leave(const Node& node) {
+ if (_numMap[node] <= _retMap[node]) {
+ while (_nodeStack.top() != node) {
+ _compMap.set(_nodeStack.top(), _compNum);
+ _nodeStack.pop();
+ }
+ _compMap.set(node, _compNum);
+ _nodeStack.pop();
+ ++_compNum;
+ }
+ }
+
+ void discover(const Arc& edge) {
+ _predMap.set(_graph.target(edge), edge);
+ }
+
+ void examine(const Arc& edge) {
+ if (_predMap[_graph.source(edge)] == _graph.oppositeArc(edge)) {
+ return;
+ }
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
+ }
+ }
+
+ void backtrack(const Arc& edge) {
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
+ }
+ }
+
+ private:
+ const Digraph& _graph;
+ NodeMap& _compMap;
+ int& _compNum;
+
+ typename Digraph::template NodeMap<int> _numMap;
+ typename Digraph::template NodeMap<int> _retMap;
+ typename Digraph::template NodeMap<Arc> _predMap;
+ std::stack<Node> _nodeStack;
+ int _num;
+ };
+
+
+ template <typename Digraph, typename ArcMap>
+ class BiEdgeConnectedCutEdgesVisitor : public DfsVisitor<Digraph> {
+ public:
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::Edge Edge;
+
+ BiEdgeConnectedCutEdgesVisitor(const Digraph& graph,
+ ArcMap& cutMap, int &cutNum)
+ : _graph(graph), _cutMap(cutMap), _cutNum(cutNum),
+ _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
+
+ void start(const Node& node) {
+ _predMap[node] = INVALID;
+ }
+
+ void reach(const Node& node) {
+ _numMap.set(node, _num);
+ _retMap.set(node, _num);
+ ++_num;
+ }
+
+ void leave(const Node& node) {
+ if (_numMap[node] <= _retMap[node]) {
+ if (_predMap[node] != INVALID) {
+ _cutMap.set(_predMap[node], true);
+ ++_cutNum;
+ }
+ }
+ }
+
+ void discover(const Arc& edge) {
+ _predMap.set(_graph.target(edge), edge);
+ }
+
+ void examine(const Arc& edge) {
+ if (_predMap[_graph.source(edge)] == _graph.oppositeArc(edge)) {
+ return;
+ }
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
+ }
+ }
+
+ void backtrack(const Arc& edge) {
+ if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
+ _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
+ }
+ }
+
+ private:
+ const Digraph& _graph;
+ ArcMap& _cutMap;
+ int& _cutNum;
+
+ typename Digraph::template NodeMap<int> _numMap;
+ typename Digraph::template NodeMap<int> _retMap;
+ typename Digraph::template NodeMap<Arc> _predMap;
+ int _num;
+ };
+ }
+
+ template <typename Graph>
+ int countBiEdgeConnectedComponents(const Graph& graph);
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Check whether an undirected graph is bi-edge-connected.
+ ///
+ /// This function checks whether the given undirected graph is
+ /// bi-edge-connected, i.e. any two nodes are connected with at least
+ /// two edge-disjoint paths.
+ ///
+ /// \return \c true if the graph is bi-edge-connected.
+ /// \note By definition, the empty graph is bi-edge-connected.
+ ///
+ /// \see countBiEdgeConnectedComponents(), biEdgeConnectedComponents()
+ template <typename Graph>
+ bool biEdgeConnected(const Graph& graph) {
+ return countBiEdgeConnectedComponents(graph) <= 1;
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Count the number of bi-edge-connected components of an
+ /// undirected graph.
+ ///
+ /// This function counts the number of bi-edge-connected components of
+ /// the given undirected graph.
+ ///
+ /// The bi-edge-connected components are the classes of an equivalence
+ /// relation on the nodes of an undirected graph. Two nodes are in the
+ /// same class if they are connected with at least two edge-disjoint
+ /// paths.
+ ///
+ /// \return The number of bi-edge-connected components.
+ ///
+ /// \see biEdgeConnected(), biEdgeConnectedComponents()
+ template <typename Graph>
+ int countBiEdgeConnectedComponents(const Graph& graph) {
+ checkConcept<concepts::Graph, Graph>();
+ typedef typename Graph::NodeIt NodeIt;
+
+ using namespace _connectivity_bits;
+
+ typedef CountBiEdgeConnectedComponentsVisitor<Graph> Visitor;
+
+ int compNum = 0;
+ Visitor visitor(graph, compNum);
+
+ DfsVisit<Graph, Visitor> dfs(graph, visitor);
+ dfs.init();
+
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
+ return compNum;
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Find the bi-edge-connected components of an undirected graph.
+ ///
+ /// This function finds the bi-edge-connected components of the given
+ /// undirected graph.
+ ///
+ /// The bi-edge-connected components are the classes of an equivalence
+ /// relation on the nodes of an undirected graph. Two nodes are in the
+ /// same class if they are connected with at least two edge-disjoint
+ /// paths.
+ ///
+ /// \image html edge_biconnected_components.png
+ /// \image latex edge_biconnected_components.eps "bi-edge-connected components" width=\textwidth
+ ///
+ /// \param graph The undirected graph.
+ /// \retval compMap A writable node map. The values will be set from 0 to
+ /// the number of the bi-edge-connected components minus one. Each value
+ /// of the map will be set exactly once, and the values of a certain
+ /// component will be set continuously.
+ /// \return The number of bi-edge-connected components.
+ ///
+ /// \see biEdgeConnected(), countBiEdgeConnectedComponents()
+ template <typename Graph, typename NodeMap>
+ int biEdgeConnectedComponents(const Graph& graph, NodeMap& compMap) {
+ checkConcept<concepts::Graph, Graph>();
+ typedef typename Graph::NodeIt NodeIt;
+ typedef typename Graph::Node Node;
+ checkConcept<concepts::WriteMap<Node, int>, NodeMap>();
+
+ using namespace _connectivity_bits;
+
+ typedef BiEdgeConnectedComponentsVisitor<Graph, NodeMap> Visitor;
+
+ int compNum = 0;
+ Visitor visitor(graph, compMap, compNum);
+
+ DfsVisit<Graph, Visitor> dfs(graph, visitor);
+ dfs.init();
+
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
+ return compNum;
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Find the bi-edge-connected cut edges in an undirected graph.
+ ///
+ /// This function finds the bi-edge-connected cut edges in the given
+ /// undirected graph.
+ ///
+ /// The bi-edge-connected components are the classes of an equivalence
+ /// relation on the nodes of an undirected graph. Two nodes are in the
+ /// same class if they are connected with at least two edge-disjoint
+ /// paths.
+ /// The bi-edge-connected components are separted by the cut edges of
+ /// the components.
+ ///
+ /// \param graph The undirected graph.
+ /// \retval cutMap A writable edge map. The values will be set to \c true
+ /// for the cut edges (exactly once for each cut edge), and will not be
+ /// changed for other edges.
+ /// \return The number of cut edges.
+ ///
+ /// \see biEdgeConnected(), biEdgeConnectedComponents()
+ template <typename Graph, typename EdgeMap>
+ int biEdgeConnectedCutEdges(const Graph& graph, EdgeMap& cutMap) {
+ checkConcept<concepts::Graph, Graph>();
+ typedef typename Graph::NodeIt NodeIt;
+ typedef typename Graph::Edge Edge;
+ checkConcept<concepts::WriteMap<Edge, bool>, EdgeMap>();
+
+ using namespace _connectivity_bits;
+
+ typedef BiEdgeConnectedCutEdgesVisitor<Graph, EdgeMap> Visitor;
+
+ int cutNum = 0;
+ Visitor visitor(graph, cutMap, cutNum);
+
+ DfsVisit<Graph, Visitor> dfs(graph, visitor);
+ dfs.init();
+
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
+ return cutNum;
+ }
+
+
+ namespace _connectivity_bits {
+
+ template <typename Digraph, typename IntNodeMap>
+ class TopologicalSortVisitor : public DfsVisitor<Digraph> {
+ public:
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::Arc edge;
+
+ TopologicalSortVisitor(IntNodeMap& order, int num)
+ : _order(order), _num(num) {}
+
+ void leave(const Node& node) {
+ _order.set(node, --_num);
+ }
+
+ private:
+ IntNodeMap& _order;
+ int _num;
+ };
+
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Check whether a digraph is DAG.
+ ///
+ /// This function checks whether the given digraph is DAG, i.e.
+ /// \e Directed \e Acyclic \e Graph.
+ /// \return \c true if there is no directed cycle in the digraph.
+ /// \see acyclic()
+ template <typename Digraph>
+ bool dag(const Digraph& digraph) {
+
+ checkConcept<concepts::Digraph, Digraph>();
+
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::NodeIt NodeIt;
+ typedef typename Digraph::Arc Arc;
+
+ typedef typename Digraph::template NodeMap<bool> ProcessedMap;
+
+ typename Dfs<Digraph>::template SetProcessedMap<ProcessedMap>::
+ Create dfs(digraph);
+
+ ProcessedMap processed(digraph);
+ dfs.processedMap(processed);
+
+ dfs.init();
+ for (NodeIt it(digraph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ while (!dfs.emptyQueue()) {
+ Arc arc = dfs.nextArc();
+ Node target = digraph.target(arc);
+ if (dfs.reached(target) && !processed[target]) {
+ return false;
+ }
+ dfs.processNextArc();
+ }
+ }
+ }
+ return true;
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Sort the nodes of a DAG into topolgical order.
+ ///
+ /// This function sorts the nodes of the given acyclic digraph (DAG)
+ /// into topolgical order.
+ ///
+ /// \param digraph The digraph, which must be DAG.
+ /// \retval order A writable node map. The values will be set from 0 to
+ /// the number of the nodes in the digraph minus one. Each value of the
+ /// map will be set exactly once, and the values will be set descending
+ /// order.
+ ///
+ /// \see dag(), checkedTopologicalSort()
+ template <typename Digraph, typename NodeMap>
+ void topologicalSort(const Digraph& digraph, NodeMap& order) {
+ using namespace _connectivity_bits;
+
+ checkConcept<concepts::Digraph, Digraph>();
+ checkConcept<concepts::WriteMap<typename Digraph::Node, int>, NodeMap>();
+
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::NodeIt NodeIt;
+ typedef typename Digraph::Arc Arc;
+
+ TopologicalSortVisitor<Digraph, NodeMap>
+ visitor(order, countNodes(digraph));
+
+ DfsVisit<Digraph, TopologicalSortVisitor<Digraph, NodeMap> >
+ dfs(digraph, visitor);
+
+ dfs.init();
+ for (NodeIt it(digraph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ dfs.start();
+ }
+ }
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Sort the nodes of a DAG into topolgical order.
+ ///
+ /// This function sorts the nodes of the given acyclic digraph (DAG)
+ /// into topolgical order and also checks whether the given digraph
+ /// is DAG.
+ ///
+ /// \param digraph The digraph.
+ /// \retval order A readable and writable node map. The values will be
+ /// set from 0 to the number of the nodes in the digraph minus one.
+ /// Each value of the map will be set exactly once, and the values will
+ /// be set descending order.
+ /// \return \c false if the digraph is not DAG.
+ ///
+ /// \see dag(), topologicalSort()
+ template <typename Digraph, typename NodeMap>
+ bool checkedTopologicalSort(const Digraph& digraph, NodeMap& order) {
+ using namespace _connectivity_bits;
+
+ checkConcept<concepts::Digraph, Digraph>();
+ checkConcept<concepts::ReadWriteMap<typename Digraph::Node, int>,
+ NodeMap>();
+
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::NodeIt NodeIt;
+ typedef typename Digraph::Arc Arc;
+
+ for (NodeIt it(digraph); it != INVALID; ++it) {
+ order.set(it, -1);
+ }
+
+ TopologicalSortVisitor<Digraph, NodeMap>
+ visitor(order, countNodes(digraph));
+
+ DfsVisit<Digraph, TopologicalSortVisitor<Digraph, NodeMap> >
+ dfs(digraph, visitor);
+
+ dfs.init();
+ for (NodeIt it(digraph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ while (!dfs.emptyQueue()) {
+ Arc arc = dfs.nextArc();
+ Node target = digraph.target(arc);
+ if (dfs.reached(target) && order[target] == -1) {
+ return false;
+ }
+ dfs.processNextArc();
+ }
+ }
+ }
+ return true;
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Check whether an undirected graph is acyclic.
+ ///
+ /// This function checks whether the given undirected graph is acyclic.
+ /// \return \c true if there is no cycle in the graph.
+ /// \see dag()
+ template <typename Graph>
+ bool acyclic(const Graph& graph) {
+ checkConcept<concepts::Graph, Graph>();
+ typedef typename Graph::Node Node;
+ typedef typename Graph::NodeIt NodeIt;
+ typedef typename Graph::Arc Arc;
+ Dfs<Graph> dfs(graph);
+ dfs.init();
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ dfs.addSource(it);
+ while (!dfs.emptyQueue()) {
+ Arc arc = dfs.nextArc();
+ Node source = graph.source(arc);
+ Node target = graph.target(arc);
+ if (dfs.reached(target) &&
+ dfs.predArc(source) != graph.oppositeArc(arc)) {
+ return false;
+ }
+ dfs.processNextArc();
+ }
+ }
+ }
+ return true;
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Check whether an undirected graph is tree.
+ ///
+ /// This function checks whether the given undirected graph is tree.
+ /// \return \c true if the graph is acyclic and connected.
+ /// \see acyclic(), connected()
+ template <typename Graph>
+ bool tree(const Graph& graph) {
+ checkConcept<concepts::Graph, Graph>();
+ typedef typename Graph::Node Node;
+ typedef typename Graph::NodeIt NodeIt;
+ typedef typename Graph::Arc Arc;
+ if (NodeIt(graph) == INVALID) return true;
+ Dfs<Graph> dfs(graph);
+ dfs.init();
+ dfs.addSource(NodeIt(graph));
+ while (!dfs.emptyQueue()) {
+ Arc arc = dfs.nextArc();
+ Node source = graph.source(arc);
+ Node target = graph.target(arc);
+ if (dfs.reached(target) &&
+ dfs.predArc(source) != graph.oppositeArc(arc)) {
+ return false;
+ }
+ dfs.processNextArc();
+ }
+ for (NodeIt it(graph); it != INVALID; ++it) {
+ if (!dfs.reached(it)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ namespace _connectivity_bits {
+
+ template <typename Digraph>
+ class BipartiteVisitor : public BfsVisitor<Digraph> {
+ public:
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::Node Node;
+
+ BipartiteVisitor(const Digraph& graph, bool& bipartite)
+ : _graph(graph), _part(graph), _bipartite(bipartite) {}
+
+ void start(const Node& node) {
+ _part[node] = true;
+ }
+ void discover(const Arc& edge) {
+ _part.set(_graph.target(edge), !_part[_graph.source(edge)]);
+ }
+ void examine(const Arc& edge) {
+ _bipartite = _bipartite &&
+ _part[_graph.target(edge)] != _part[_graph.source(edge)];
+ }
+
+ private:
+
+ const Digraph& _graph;
+ typename Digraph::template NodeMap<bool> _part;
+ bool& _bipartite;
+ };
+
+ template <typename Digraph, typename PartMap>
+ class BipartitePartitionsVisitor : public BfsVisitor<Digraph> {
+ public:
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::Node Node;
+
+ BipartitePartitionsVisitor(const Digraph& graph,
+ PartMap& part, bool& bipartite)
+ : _graph(graph), _part(part), _bipartite(bipartite) {}
+
+ void start(const Node& node) {
+ _part.set(node, true);
+ }
+ void discover(const Arc& edge) {
+ _part.set(_graph.target(edge), !_part[_graph.source(edge)]);
+ }
+ void examine(const Arc& edge) {
+ _bipartite = _bipartite &&
+ _part[_graph.target(edge)] != _part[_graph.source(edge)];
+ }
+
+ private:
+
+ const Digraph& _graph;
+ PartMap& _part;
+ bool& _bipartite;
+ };
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Check whether an undirected graph is bipartite.
+ ///
+ /// The function checks whether the given undirected graph is bipartite.
+ /// \return \c true if the graph is bipartite.
+ ///
+ /// \see bipartitePartitions()
+ template<typename Graph>
+ bool bipartite(const Graph &graph){
+ using namespace _connectivity_bits;
+
+ checkConcept<concepts::Graph, Graph>();
+
+ typedef typename Graph::NodeIt NodeIt;
+ typedef typename Graph::ArcIt ArcIt;
+
+ bool bipartite = true;
+
+ BipartiteVisitor<Graph>
+ visitor(graph, bipartite);
+ BfsVisit<Graph, BipartiteVisitor<Graph> >
+ bfs(graph, visitor);
+ bfs.init();
+ for(NodeIt it(graph); it != INVALID; ++it) {
+ if(!bfs.reached(it)){
+ bfs.addSource(it);
+ while (!bfs.emptyQueue()) {
+ bfs.processNextNode();
+ if (!bipartite) return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Find the bipartite partitions of an undirected graph.
+ ///
+ /// This function checks whether the given undirected graph is bipartite
+ /// and gives back the bipartite partitions.
+ ///
+ /// \image html bipartite_partitions.png
+ /// \image latex bipartite_partitions.eps "Bipartite partititions" width=\textwidth
+ ///
+ /// \param graph The undirected graph.
+ /// \retval partMap A writable node map of \c bool (or convertible) value
+ /// type. The values will be set to \c true for one component and
+ /// \c false for the other one.
+ /// \return \c true if the graph is bipartite, \c false otherwise.
+ ///
+ /// \see bipartite()
+ template<typename Graph, typename NodeMap>
+ bool bipartitePartitions(const Graph &graph, NodeMap &partMap){
+ using namespace _connectivity_bits;
+
+ checkConcept<concepts::Graph, Graph>();
+ checkConcept<concepts::WriteMap<typename Graph::Node, bool>, NodeMap>();
+
+ typedef typename Graph::Node Node;
+ typedef typename Graph::NodeIt NodeIt;
+ typedef typename Graph::ArcIt ArcIt;
+
+ bool bipartite = true;
+
+ BipartitePartitionsVisitor<Graph, NodeMap>
+ visitor(graph, partMap, bipartite);
+ BfsVisit<Graph, BipartitePartitionsVisitor<Graph, NodeMap> >
+ bfs(graph, visitor);
+ bfs.init();
+ for(NodeIt it(graph); it != INVALID; ++it) {
+ if(!bfs.reached(it)){
+ bfs.addSource(it);
+ while (!bfs.emptyQueue()) {
+ bfs.processNextNode();
+ if (!bipartite) return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Check whether the given graph contains no loop arcs/edges.
+ ///
+ /// This function returns \c true if there are no loop arcs/edges in
+ /// the given graph. It works for both directed and undirected graphs.
+ template <typename Graph>
+ bool loopFree(const Graph& graph) {
+ for (typename Graph::ArcIt it(graph); it != INVALID; ++it) {
+ if (graph.source(it) == graph.target(it)) return false;
+ }
+ return true;
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Check whether the given graph contains no parallel arcs/edges.
+ ///
+ /// This function returns \c true if there are no parallel arcs/edges in
+ /// the given graph. It works for both directed and undirected graphs.
+ template <typename Graph>
+ bool parallelFree(const Graph& graph) {
+ typename Graph::template NodeMap<int> reached(graph, 0);
+ int cnt = 1;
+ for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
+ for (typename Graph::OutArcIt a(graph, n); a != INVALID; ++a) {
+ if (reached[graph.target(a)] == cnt) return false;
+ reached[graph.target(a)] = cnt;
+ }
+ ++cnt;
+ }
+ return true;
+ }
+
+ /// \ingroup graph_properties
+ ///
+ /// \brief Check whether the given graph is simple.
+ ///
+ /// This function returns \c true if the given graph is simple, i.e.
+ /// it contains no loop arcs/edges and no parallel arcs/edges.
+ /// The function works for both directed and undirected graphs.
+ /// \see loopFree(), parallelFree()
+ template <typename Graph>
+ bool simpleGraph(const Graph& graph) {
+ typename Graph::template NodeMap<int> reached(graph, 0);
+ int cnt = 1;
+ for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
+ reached[n] = cnt;
+ for (typename Graph::OutArcIt a(graph, n); a != INVALID; ++a) {
+ if (reached[graph.target(a)] == cnt) return false;
+ reached[graph.target(a)] = cnt;
+ }
+ ++cnt;
+ }
+ return true;
+ }
+
+} //namespace lemon
+
+#endif //LEMON_CONNECTIVITY_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/core.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/core.h
new file mode 100644
index 00000000000..507943db1c3
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/core.h
@@ -0,0 +1,2506 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_CORE_H
+#define LEMON_CORE_H
+
+#include <vector>
+#include <algorithm>
+
+#include <lemon/config.h>
+#include <lemon/bits/enable_if.h>
+#include <lemon/bits/traits.h>
+#include <lemon/assert.h>
+
+// Disable the following warnings when compiling with MSVC:
+// C4250: 'class1' : inherits 'class2::member' via dominance
+// C4355: 'this' : used in base member initializer list
+// C4503: 'function' : decorated name length exceeded, name was truncated
+// C4800: 'type' : forcing value to bool 'true' or 'false' (performance warning)
+// C4996: 'function': was declared deprecated
+#ifdef _MSC_VER
+#pragma warning( disable : 4250 4355 4503 4800 4996 )
+#endif
+
+#ifdef __GNUC__
+#define GCC_VERSION (__GNUC__ * 10000 \
+ + __GNUC_MINOR__ * 100 \
+ + __GNUC_PATCHLEVEL__)
+#endif
+
+#if GCC_VERSION >= 40800
+// Needed by the [DI]GRAPH_TYPEDEFS marcos for gcc 4.8
+#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
+#endif
+
+///\file
+///\brief LEMON core utilities.
+///
+///This header file contains core utilities for LEMON.
+///It is automatically included by all graph types, therefore it usually
+///do not have to be included directly.
+
+namespace lemon {
+
+ /// \brief Dummy type to make it easier to create invalid iterators.
+ ///
+ /// Dummy type to make it easier to create invalid iterators.
+ /// See \ref INVALID for the usage.
+ struct Invalid {
+ public:
+ bool operator==(Invalid) { return true; }
+ bool operator!=(Invalid) { return false; }
+ bool operator< (Invalid) { return false; }
+ };
+
+ /// \brief Invalid iterators.
+ ///
+ /// \ref Invalid is a global type that converts to each iterator
+ /// in such a way that the value of the target iterator will be invalid.
+#ifdef LEMON_ONLY_TEMPLATES
+ const Invalid INVALID = Invalid();
+#else
+ extern const Invalid INVALID;
+#endif
+
+ /// \addtogroup gutils
+ /// @{
+
+ ///Create convenience typedefs for the digraph types and iterators
+
+ ///This \c \#define creates convenient type definitions for the following
+ ///types of \c Digraph: \c Node, \c NodeIt, \c Arc, \c ArcIt, \c InArcIt,
+ ///\c OutArcIt, \c BoolNodeMap, \c IntNodeMap, \c DoubleNodeMap,
+ ///\c BoolArcMap, \c IntArcMap, \c DoubleArcMap.
+ ///
+ ///\note If the graph type is a dependent type, ie. the graph type depend
+ ///on a template parameter, then use \c TEMPLATE_DIGRAPH_TYPEDEFS()
+ ///macro.
+#define DIGRAPH_TYPEDEFS(Digraph) \
+ typedef Digraph::Node Node; \
+ typedef Digraph::NodeIt NodeIt; \
+ typedef Digraph::Arc Arc; \
+ typedef Digraph::ArcIt ArcIt; \
+ typedef Digraph::InArcIt InArcIt; \
+ typedef Digraph::OutArcIt OutArcIt; \
+ typedef Digraph::NodeMap<bool> BoolNodeMap; \
+ typedef Digraph::NodeMap<int> IntNodeMap; \
+ typedef Digraph::NodeMap<double> DoubleNodeMap; \
+ typedef Digraph::ArcMap<bool> BoolArcMap; \
+ typedef Digraph::ArcMap<int> IntArcMap; \
+ typedef Digraph::ArcMap<double> DoubleArcMap
+
+ ///Create convenience typedefs for the digraph types and iterators
+
+ ///\see DIGRAPH_TYPEDEFS
+ ///
+ ///\note Use this macro, if the graph type is a dependent type,
+ ///ie. the graph type depend on a template parameter.
+#define TEMPLATE_DIGRAPH_TYPEDEFS(Digraph) \
+ typedef typename Digraph::Node Node; \
+ typedef typename Digraph::NodeIt NodeIt; \
+ typedef typename Digraph::Arc Arc; \
+ typedef typename Digraph::ArcIt ArcIt; \
+ typedef typename Digraph::InArcIt InArcIt; \
+ typedef typename Digraph::OutArcIt OutArcIt; \
+ typedef typename Digraph::template NodeMap<bool> BoolNodeMap; \
+ typedef typename Digraph::template NodeMap<int> IntNodeMap; \
+ typedef typename Digraph::template NodeMap<double> DoubleNodeMap; \
+ typedef typename Digraph::template ArcMap<bool> BoolArcMap; \
+ typedef typename Digraph::template ArcMap<int> IntArcMap; \
+ typedef typename Digraph::template ArcMap<double> DoubleArcMap
+
+ ///Create convenience typedefs for the graph types and iterators
+
+ ///This \c \#define creates the same convenient type definitions as defined
+ ///by \ref DIGRAPH_TYPEDEFS(Graph) and six more, namely it creates
+ ///\c Edge, \c EdgeIt, \c IncEdgeIt, \c BoolEdgeMap, \c IntEdgeMap,
+ ///\c DoubleEdgeMap.
+ ///
+ ///\note If the graph type is a dependent type, ie. the graph type depend
+ ///on a template parameter, then use \c TEMPLATE_GRAPH_TYPEDEFS()
+ ///macro.
+#define GRAPH_TYPEDEFS(Graph) \
+ DIGRAPH_TYPEDEFS(Graph); \
+ typedef Graph::Edge Edge; \
+ typedef Graph::EdgeIt EdgeIt; \
+ typedef Graph::IncEdgeIt IncEdgeIt; \
+ typedef Graph::EdgeMap<bool> BoolEdgeMap; \
+ typedef Graph::EdgeMap<int> IntEdgeMap; \
+ typedef Graph::EdgeMap<double> DoubleEdgeMap
+
+ ///Create convenience typedefs for the graph types and iterators
+
+ ///\see GRAPH_TYPEDEFS
+ ///
+ ///\note Use this macro, if the graph type is a dependent type,
+ ///ie. the graph type depend on a template parameter.
+#define TEMPLATE_GRAPH_TYPEDEFS(Graph) \
+ TEMPLATE_DIGRAPH_TYPEDEFS(Graph); \
+ typedef typename Graph::Edge Edge; \
+ typedef typename Graph::EdgeIt EdgeIt; \
+ typedef typename Graph::IncEdgeIt IncEdgeIt; \
+ typedef typename Graph::template EdgeMap<bool> BoolEdgeMap; \
+ typedef typename Graph::template EdgeMap<int> IntEdgeMap; \
+ typedef typename Graph::template EdgeMap<double> DoubleEdgeMap
+
+ ///Create convenience typedefs for the bipartite graph types and iterators
+
+ ///This \c \#define creates the same convenient type definitions as
+ ///defined by \ref GRAPH_TYPEDEFS(BpGraph) and ten more, namely it
+ ///creates \c RedNode, \c RedNodeIt, \c BoolRedNodeMap,
+ ///\c IntRedNodeMap, \c DoubleRedNodeMap, \c BlueNode, \c BlueNodeIt,
+ ///\c BoolBlueNodeMap, \c IntBlueNodeMap, \c DoubleBlueNodeMap.
+ ///
+ ///\note If the graph type is a dependent type, ie. the graph type depend
+ ///on a template parameter, then use \c TEMPLATE_BPGRAPH_TYPEDEFS()
+ ///macro.
+#define BPGRAPH_TYPEDEFS(BpGraph) \
+ GRAPH_TYPEDEFS(BpGraph); \
+ typedef BpGraph::RedNode RedNode; \
+ typedef BpGraph::RedNodeIt RedNodeIt; \
+ typedef BpGraph::RedNodeMap<bool> BoolRedNodeMap; \
+ typedef BpGraph::RedNodeMap<int> IntRedNodeMap; \
+ typedef BpGraph::RedNodeMap<double> DoubleRedNodeMap; \
+ typedef BpGraph::BlueNode BlueNode; \
+ typedef BpGraph::BlueNodeIt BlueNodeIt; \
+ typedef BpGraph::BlueNodeMap<bool> BoolBlueNodeMap; \
+ typedef BpGraph::BlueNodeMap<int> IntBlueNodeMap; \
+ typedef BpGraph::BlueNodeMap<double> DoubleBlueNodeMap
+
+ ///Create convenience typedefs for the bipartite graph types and iterators
+
+ ///\see BPGRAPH_TYPEDEFS
+ ///
+ ///\note Use this macro, if the graph type is a dependent type,
+ ///ie. the graph type depend on a template parameter.
+#define TEMPLATE_BPGRAPH_TYPEDEFS(BpGraph) \
+ TEMPLATE_GRAPH_TYPEDEFS(BpGraph); \
+ typedef typename BpGraph::RedNode RedNode; \
+ typedef typename BpGraph::RedNodeIt RedNodeIt; \
+ typedef typename BpGraph::template RedNodeMap<bool> BoolRedNodeMap; \
+ typedef typename BpGraph::template RedNodeMap<int> IntRedNodeMap; \
+ typedef typename BpGraph::template RedNodeMap<double> DoubleRedNodeMap; \
+ typedef typename BpGraph::BlueNode BlueNode; \
+ typedef typename BpGraph::BlueNodeIt BlueNodeIt; \
+ typedef typename BpGraph::template BlueNodeMap<bool> BoolBlueNodeMap; \
+ typedef typename BpGraph::template BlueNodeMap<int> IntBlueNodeMap; \
+ typedef typename BpGraph::template BlueNodeMap<double> DoubleBlueNodeMap
+
+ /// \brief Function to count the items in a graph.
+ ///
+ /// This function counts the items (nodes, arcs etc.) in a graph.
+ /// The complexity of the function is linear because
+ /// it iterates on all of the items.
+ template <typename Graph, typename Item>
+ inline int countItems(const Graph& g) {
+ typedef typename ItemSetTraits<Graph, Item>::ItemIt ItemIt;
+ int num = 0;
+ for (ItemIt it(g); it != INVALID; ++it) {
+ ++num;
+ }
+ return num;
+ }
+
+ // Node counting:
+
+ namespace _core_bits {
+
+ template <typename Graph, typename Enable = void>
+ struct CountNodesSelector {
+ static int count(const Graph &g) {
+ return countItems<Graph, typename Graph::Node>(g);
+ }
+ };
+
+ template <typename Graph>
+ struct CountNodesSelector<
+ Graph, typename
+ enable_if<typename Graph::NodeNumTag, void>::type>
+ {
+ static int count(const Graph &g) {
+ return g.nodeNum();
+ }
+ };
+ }
+
+ /// \brief Function to count the nodes in the graph.
+ ///
+ /// This function counts the nodes in the graph.
+ /// The complexity of the function is <em>O</em>(<em>n</em>), but for some
+ /// graph structures it is specialized to run in <em>O</em>(1).
+ ///
+ /// \note If the graph contains a \c nodeNum() member function and a
+ /// \c NodeNumTag tag then this function calls directly the member
+ /// function to query the cardinality of the node set.
+ template <typename Graph>
+ inline int countNodes(const Graph& g) {
+ return _core_bits::CountNodesSelector<Graph>::count(g);
+ }
+
+ namespace _graph_utils_bits {
+
+ template <typename Graph, typename Enable = void>
+ struct CountRedNodesSelector {
+ static int count(const Graph &g) {
+ return countItems<Graph, typename Graph::RedNode>(g);
+ }
+ };
+
+ template <typename Graph>
+ struct CountRedNodesSelector<
+ Graph, typename
+ enable_if<typename Graph::NodeNumTag, void>::type>
+ {
+ static int count(const Graph &g) {
+ return g.redNum();
+ }
+ };
+ }
+
+ /// \brief Function to count the red nodes in the graph.
+ ///
+ /// This function counts the red nodes in the graph.
+ /// The complexity of the function is O(n) but for some
+ /// graph structures it is specialized to run in O(1).
+ ///
+ /// If the graph contains a \e redNum() member function and a
+ /// \e NodeNumTag tag then this function calls directly the member
+ /// function to query the cardinality of the node set.
+ template <typename Graph>
+ inline int countRedNodes(const Graph& g) {
+ return _graph_utils_bits::CountRedNodesSelector<Graph>::count(g);
+ }
+
+ namespace _graph_utils_bits {
+
+ template <typename Graph, typename Enable = void>
+ struct CountBlueNodesSelector {
+ static int count(const Graph &g) {
+ return countItems<Graph, typename Graph::BlueNode>(g);
+ }
+ };
+
+ template <typename Graph>
+ struct CountBlueNodesSelector<
+ Graph, typename
+ enable_if<typename Graph::NodeNumTag, void>::type>
+ {
+ static int count(const Graph &g) {
+ return g.blueNum();
+ }
+ };
+ }
+
+ /// \brief Function to count the blue nodes in the graph.
+ ///
+ /// This function counts the blue nodes in the graph.
+ /// The complexity of the function is O(n) but for some
+ /// graph structures it is specialized to run in O(1).
+ ///
+ /// If the graph contains a \e blueNum() member function and a
+ /// \e NodeNumTag tag then this function calls directly the member
+ /// function to query the cardinality of the node set.
+ template <typename Graph>
+ inline int countBlueNodes(const Graph& g) {
+ return _graph_utils_bits::CountBlueNodesSelector<Graph>::count(g);
+ }
+
+ // Arc counting:
+
+ namespace _core_bits {
+
+ template <typename Graph, typename Enable = void>
+ struct CountArcsSelector {
+ static int count(const Graph &g) {
+ return countItems<Graph, typename Graph::Arc>(g);
+ }
+ };
+
+ template <typename Graph>
+ struct CountArcsSelector<
+ Graph,
+ typename enable_if<typename Graph::ArcNumTag, void>::type>
+ {
+ static int count(const Graph &g) {
+ return g.arcNum();
+ }
+ };
+ }
+
+ /// \brief Function to count the arcs in the graph.
+ ///
+ /// This function counts the arcs in the graph.
+ /// The complexity of the function is <em>O</em>(<em>m</em>), but for some
+ /// graph structures it is specialized to run in <em>O</em>(1).
+ ///
+ /// \note If the graph contains a \c arcNum() member function and a
+ /// \c ArcNumTag tag then this function calls directly the member
+ /// function to query the cardinality of the arc set.
+ template <typename Graph>
+ inline int countArcs(const Graph& g) {
+ return _core_bits::CountArcsSelector<Graph>::count(g);
+ }
+
+ // Edge counting:
+
+ namespace _core_bits {
+
+ template <typename Graph, typename Enable = void>
+ struct CountEdgesSelector {
+ static int count(const Graph &g) {
+ return countItems<Graph, typename Graph::Edge>(g);
+ }
+ };
+
+ template <typename Graph>
+ struct CountEdgesSelector<
+ Graph,
+ typename enable_if<typename Graph::EdgeNumTag, void>::type>
+ {
+ static int count(const Graph &g) {
+ return g.edgeNum();
+ }
+ };
+ }
+
+ /// \brief Function to count the edges in the graph.
+ ///
+ /// This function counts the edges in the graph.
+ /// The complexity of the function is <em>O</em>(<em>m</em>), but for some
+ /// graph structures it is specialized to run in <em>O</em>(1).
+ ///
+ /// \note If the graph contains a \c edgeNum() member function and a
+ /// \c EdgeNumTag tag then this function calls directly the member
+ /// function to query the cardinality of the edge set.
+ template <typename Graph>
+ inline int countEdges(const Graph& g) {
+ return _core_bits::CountEdgesSelector<Graph>::count(g);
+
+ }
+
+
+ template <typename Graph, typename DegIt>
+ inline int countNodeDegree(const Graph& _g, const typename Graph::Node& _n) {
+ int num = 0;
+ for (DegIt it(_g, _n); it != INVALID; ++it) {
+ ++num;
+ }
+ return num;
+ }
+
+ /// \brief Function to count the number of the out-arcs from node \c n.
+ ///
+ /// This function counts the number of the out-arcs from node \c n
+ /// in the graph \c g.
+ template <typename Graph>
+ inline int countOutArcs(const Graph& g, const typename Graph::Node& n) {
+ return countNodeDegree<Graph, typename Graph::OutArcIt>(g, n);
+ }
+
+ /// \brief Function to count the number of the in-arcs to node \c n.
+ ///
+ /// This function counts the number of the in-arcs to node \c n
+ /// in the graph \c g.
+ template <typename Graph>
+ inline int countInArcs(const Graph& g, const typename Graph::Node& n) {
+ return countNodeDegree<Graph, typename Graph::InArcIt>(g, n);
+ }
+
+ /// \brief Function to count the number of the inc-edges to node \c n.
+ ///
+ /// This function counts the number of the inc-edges to node \c n
+ /// in the undirected graph \c g.
+ template <typename Graph>
+ inline int countIncEdges(const Graph& g, const typename Graph::Node& n) {
+ return countNodeDegree<Graph, typename Graph::IncEdgeIt>(g, n);
+ }
+
+ namespace _core_bits {
+
+ template <typename Digraph, typename Item, typename RefMap>
+ class MapCopyBase {
+ public:
+ virtual void copy(const Digraph& from, const RefMap& refMap) = 0;
+
+ virtual ~MapCopyBase() {}
+ };
+
+ template <typename Digraph, typename Item, typename RefMap,
+ typename FromMap, typename ToMap>
+ class MapCopy : public MapCopyBase<Digraph, Item, RefMap> {
+ public:
+
+ MapCopy(const FromMap& map, ToMap& tmap)
+ : _map(map), _tmap(tmap) {}
+
+ virtual void copy(const Digraph& digraph, const RefMap& refMap) {
+ typedef typename ItemSetTraits<Digraph, Item>::ItemIt ItemIt;
+ for (ItemIt it(digraph); it != INVALID; ++it) {
+ _tmap.set(refMap[it], _map[it]);
+ }
+ }
+
+ private:
+ const FromMap& _map;
+ ToMap& _tmap;
+ };
+
+ template <typename Digraph, typename Item, typename RefMap, typename It>
+ class ItemCopy : public MapCopyBase<Digraph, Item, RefMap> {
+ public:
+
+ ItemCopy(const Item& item, It& it) : _item(item), _it(it) {}
+
+ virtual void copy(const Digraph&, const RefMap& refMap) {
+ _it = refMap[_item];
+ }
+
+ private:
+ Item _item;
+ It& _it;
+ };
+
+ template <typename Digraph, typename Item, typename RefMap, typename Ref>
+ class RefCopy : public MapCopyBase<Digraph, Item, RefMap> {
+ public:
+
+ RefCopy(Ref& map) : _map(map) {}
+
+ virtual void copy(const Digraph& digraph, const RefMap& refMap) {
+ typedef typename ItemSetTraits<Digraph, Item>::ItemIt ItemIt;
+ for (ItemIt it(digraph); it != INVALID; ++it) {
+ _map.set(it, refMap[it]);
+ }
+ }
+
+ private:
+ Ref& _map;
+ };
+
+ template <typename Digraph, typename Item, typename RefMap,
+ typename CrossRef>
+ class CrossRefCopy : public MapCopyBase<Digraph, Item, RefMap> {
+ public:
+
+ CrossRefCopy(CrossRef& cmap) : _cmap(cmap) {}
+
+ virtual void copy(const Digraph& digraph, const RefMap& refMap) {
+ typedef typename ItemSetTraits<Digraph, Item>::ItemIt ItemIt;
+ for (ItemIt it(digraph); it != INVALID; ++it) {
+ _cmap.set(refMap[it], it);
+ }
+ }
+
+ private:
+ CrossRef& _cmap;
+ };
+
+ template <typename Digraph, typename Enable = void>
+ struct DigraphCopySelector {
+ template <typename From, typename NodeRefMap, typename ArcRefMap>
+ static void copy(const From& from, Digraph &to,
+ NodeRefMap& nodeRefMap, ArcRefMap& arcRefMap) {
+ to.clear();
+ for (typename From::NodeIt it(from); it != INVALID; ++it) {
+ nodeRefMap[it] = to.addNode();
+ }
+ for (typename From::ArcIt it(from); it != INVALID; ++it) {
+ arcRefMap[it] = to.addArc(nodeRefMap[from.source(it)],
+ nodeRefMap[from.target(it)]);
+ }
+ }
+ };
+
+ template <typename Digraph>
+ struct DigraphCopySelector<
+ Digraph,
+ typename enable_if<typename Digraph::BuildTag, void>::type>
+ {
+ template <typename From, typename NodeRefMap, typename ArcRefMap>
+ static void copy(const From& from, Digraph &to,
+ NodeRefMap& nodeRefMap, ArcRefMap& arcRefMap) {
+ to.build(from, nodeRefMap, arcRefMap);
+ }
+ };
+
+ template <typename Graph, typename Enable = void>
+ struct GraphCopySelector {
+ template <typename From, typename NodeRefMap, typename EdgeRefMap>
+ static void copy(const From& from, Graph &to,
+ NodeRefMap& nodeRefMap, EdgeRefMap& edgeRefMap) {
+ to.clear();
+ for (typename From::NodeIt it(from); it != INVALID; ++it) {
+ nodeRefMap[it] = to.addNode();
+ }
+ for (typename From::EdgeIt it(from); it != INVALID; ++it) {
+ edgeRefMap[it] = to.addEdge(nodeRefMap[from.u(it)],
+ nodeRefMap[from.v(it)]);
+ }
+ }
+ };
+
+ template <typename Graph>
+ struct GraphCopySelector<
+ Graph,
+ typename enable_if<typename Graph::BuildTag, void>::type>
+ {
+ template <typename From, typename NodeRefMap, typename EdgeRefMap>
+ static void copy(const From& from, Graph &to,
+ NodeRefMap& nodeRefMap,
+ EdgeRefMap& edgeRefMap) {
+ to.build(from, nodeRefMap, edgeRefMap);
+ }
+ };
+
+ template <typename BpGraph, typename Enable = void>
+ struct BpGraphCopySelector {
+ template <typename From, typename RedNodeRefMap,
+ typename BlueNodeRefMap, typename EdgeRefMap>
+ static void copy(const From& from, BpGraph &to,
+ RedNodeRefMap& redNodeRefMap,
+ BlueNodeRefMap& blueNodeRefMap,
+ EdgeRefMap& edgeRefMap) {
+ to.clear();
+ for (typename From::RedNodeIt it(from); it != INVALID; ++it) {
+ redNodeRefMap[it] = to.addRedNode();
+ }
+ for (typename From::BlueNodeIt it(from); it != INVALID; ++it) {
+ blueNodeRefMap[it] = to.addBlueNode();
+ }
+ for (typename From::EdgeIt it(from); it != INVALID; ++it) {
+ edgeRefMap[it] = to.addEdge(redNodeRefMap[from.redNode(it)],
+ blueNodeRefMap[from.blueNode(it)]);
+ }
+ }
+ };
+
+ template <typename BpGraph>
+ struct BpGraphCopySelector<
+ BpGraph,
+ typename enable_if<typename BpGraph::BuildTag, void>::type>
+ {
+ template <typename From, typename RedNodeRefMap,
+ typename BlueNodeRefMap, typename EdgeRefMap>
+ static void copy(const From& from, BpGraph &to,
+ RedNodeRefMap& redNodeRefMap,
+ BlueNodeRefMap& blueNodeRefMap,
+ EdgeRefMap& edgeRefMap) {
+ to.build(from, redNodeRefMap, blueNodeRefMap, edgeRefMap);
+ }
+ };
+
+ }
+
+ /// \brief Check whether a graph is undirected.
+ ///
+ /// This function returns \c true if the given graph is undirected.
+#ifdef DOXYGEN
+ template <typename GR>
+ bool undirected(const GR& g) { return false; }
+#else
+ template <typename GR>
+ typename enable_if<UndirectedTagIndicator<GR>, bool>::type
+ undirected(const GR&) {
+ return true;
+ }
+ template <typename GR>
+ typename disable_if<UndirectedTagIndicator<GR>, bool>::type
+ undirected(const GR&) {
+ return false;
+ }
+#endif
+
+ /// \brief Class to copy a digraph.
+ ///
+ /// Class to copy a digraph to another digraph (duplicate a digraph). The
+ /// simplest way of using it is through the \c digraphCopy() function.
+ ///
+ /// This class not only make a copy of a digraph, but it can create
+ /// references and cross references between the nodes and arcs of
+ /// the two digraphs, and it can copy maps to use with the newly created
+ /// digraph.
+ ///
+ /// To make a copy from a digraph, first an instance of DigraphCopy
+ /// should be created, then the data belongs to the digraph should
+ /// assigned to copy. In the end, the \c run() member should be
+ /// called.
+ ///
+ /// The next code copies a digraph with several data:
+ ///\code
+ /// DigraphCopy<OrigGraph, NewGraph> cg(orig_graph, new_graph);
+ /// // Create references for the nodes
+ /// OrigGraph::NodeMap<NewGraph::Node> nr(orig_graph);
+ /// cg.nodeRef(nr);
+ /// // Create cross references (inverse) for the arcs
+ /// NewGraph::ArcMap<OrigGraph::Arc> acr(new_graph);
+ /// cg.arcCrossRef(acr);
+ /// // Copy an arc map
+ /// OrigGraph::ArcMap<double> oamap(orig_graph);
+ /// NewGraph::ArcMap<double> namap(new_graph);
+ /// cg.arcMap(oamap, namap);
+ /// // Copy a node
+ /// OrigGraph::Node on;
+ /// NewGraph::Node nn;
+ /// cg.node(on, nn);
+ /// // Execute copying
+ /// cg.run();
+ ///\endcode
+ template <typename From, typename To>
+ class DigraphCopy {
+ private:
+
+ typedef typename From::Node Node;
+ typedef typename From::NodeIt NodeIt;
+ typedef typename From::Arc Arc;
+ typedef typename From::ArcIt ArcIt;
+
+ typedef typename To::Node TNode;
+ typedef typename To::Arc TArc;
+
+ typedef typename From::template NodeMap<TNode> NodeRefMap;
+ typedef typename From::template ArcMap<TArc> ArcRefMap;
+
+ public:
+
+ /// \brief Constructor of DigraphCopy.
+ ///
+ /// Constructor of DigraphCopy for copying the content of the
+ /// \c from digraph into the \c to digraph.
+ DigraphCopy(const From& from, To& to)
+ : _from(from), _to(to) {}
+
+ /// \brief Destructor of DigraphCopy
+ ///
+ /// Destructor of DigraphCopy.
+ ~DigraphCopy() {
+ for (int i = 0; i < int(_node_maps.size()); ++i) {
+ delete _node_maps[i];
+ }
+ for (int i = 0; i < int(_arc_maps.size()); ++i) {
+ delete _arc_maps[i];
+ }
+
+ }
+
+ /// \brief Copy the node references into the given map.
+ ///
+ /// This function copies the node references into the given map.
+ /// The parameter should be a map, whose key type is the Node type of
+ /// the source digraph, while the value type is the Node type of the
+ /// destination digraph.
+ template <typename NodeRef>
+ DigraphCopy& nodeRef(NodeRef& map) {
+ _node_maps.push_back(new _core_bits::RefCopy<From, Node,
+ NodeRefMap, NodeRef>(map));
+ return *this;
+ }
+
+ /// \brief Copy the node cross references into the given map.
+ ///
+ /// This function copies the node cross references (reverse references)
+ /// into the given map. The parameter should be a map, whose key type
+ /// is the Node type of the destination digraph, while the value type is
+ /// the Node type of the source digraph.
+ template <typename NodeCrossRef>
+ DigraphCopy& nodeCrossRef(NodeCrossRef& map) {
+ _node_maps.push_back(new _core_bits::CrossRefCopy<From, Node,
+ NodeRefMap, NodeCrossRef>(map));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given node map.
+ ///
+ /// This function makes a copy of the given node map for the newly
+ /// created digraph.
+ /// The key type of the new map \c tmap should be the Node type of the
+ /// destination digraph, and the key type of the original map \c map
+ /// should be the Node type of the source digraph.
+ template <typename FromMap, typename ToMap>
+ DigraphCopy& nodeMap(const FromMap& map, ToMap& tmap) {
+ _node_maps.push_back(new _core_bits::MapCopy<From, Node,
+ NodeRefMap, FromMap, ToMap>(map, tmap));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given node.
+ ///
+ /// This function makes a copy of the given node.
+ DigraphCopy& node(const Node& node, TNode& tnode) {
+ _node_maps.push_back(new _core_bits::ItemCopy<From, Node,
+ NodeRefMap, TNode>(node, tnode));
+ return *this;
+ }
+
+ /// \brief Copy the arc references into the given map.
+ ///
+ /// This function copies the arc references into the given map.
+ /// The parameter should be a map, whose key type is the Arc type of
+ /// the source digraph, while the value type is the Arc type of the
+ /// destination digraph.
+ template <typename ArcRef>
+ DigraphCopy& arcRef(ArcRef& map) {
+ _arc_maps.push_back(new _core_bits::RefCopy<From, Arc,
+ ArcRefMap, ArcRef>(map));
+ return *this;
+ }
+
+ /// \brief Copy the arc cross references into the given map.
+ ///
+ /// This function copies the arc cross references (reverse references)
+ /// into the given map. The parameter should be a map, whose key type
+ /// is the Arc type of the destination digraph, while the value type is
+ /// the Arc type of the source digraph.
+ template <typename ArcCrossRef>
+ DigraphCopy& arcCrossRef(ArcCrossRef& map) {
+ _arc_maps.push_back(new _core_bits::CrossRefCopy<From, Arc,
+ ArcRefMap, ArcCrossRef>(map));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given arc map.
+ ///
+ /// This function makes a copy of the given arc map for the newly
+ /// created digraph.
+ /// The key type of the new map \c tmap should be the Arc type of the
+ /// destination digraph, and the key type of the original map \c map
+ /// should be the Arc type of the source digraph.
+ template <typename FromMap, typename ToMap>
+ DigraphCopy& arcMap(const FromMap& map, ToMap& tmap) {
+ _arc_maps.push_back(new _core_bits::MapCopy<From, Arc,
+ ArcRefMap, FromMap, ToMap>(map, tmap));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given arc.
+ ///
+ /// This function makes a copy of the given arc.
+ DigraphCopy& arc(const Arc& arc, TArc& tarc) {
+ _arc_maps.push_back(new _core_bits::ItemCopy<From, Arc,
+ ArcRefMap, TArc>(arc, tarc));
+ return *this;
+ }
+
+ /// \brief Execute copying.
+ ///
+ /// This function executes the copying of the digraph along with the
+ /// copying of the assigned data.
+ void run() {
+ NodeRefMap nodeRefMap(_from);
+ ArcRefMap arcRefMap(_from);
+ _core_bits::DigraphCopySelector<To>::
+ copy(_from, _to, nodeRefMap, arcRefMap);
+ for (int i = 0; i < int(_node_maps.size()); ++i) {
+ _node_maps[i]->copy(_from, nodeRefMap);
+ }
+ for (int i = 0; i < int(_arc_maps.size()); ++i) {
+ _arc_maps[i]->copy(_from, arcRefMap);
+ }
+ }
+
+ protected:
+
+ const From& _from;
+ To& _to;
+
+ std::vector<_core_bits::MapCopyBase<From, Node, NodeRefMap>* >
+ _node_maps;
+
+ std::vector<_core_bits::MapCopyBase<From, Arc, ArcRefMap>* >
+ _arc_maps;
+
+ };
+
+ /// \brief Copy a digraph to another digraph.
+ ///
+ /// This function copies a digraph to another digraph.
+ /// The complete usage of it is detailed in the DigraphCopy class, but
+ /// a short example shows a basic work:
+ ///\code
+ /// digraphCopy(src, trg).nodeRef(nr).arcCrossRef(acr).run();
+ ///\endcode
+ ///
+ /// After the copy the \c nr map will contain the mapping from the
+ /// nodes of the \c from digraph to the nodes of the \c to digraph and
+ /// \c acr will contain the mapping from the arcs of the \c to digraph
+ /// to the arcs of the \c from digraph.
+ ///
+ /// \see DigraphCopy
+ template <typename From, typename To>
+ DigraphCopy<From, To> digraphCopy(const From& from, To& to) {
+ return DigraphCopy<From, To>(from, to);
+ }
+
+ /// \brief Class to copy a graph.
+ ///
+ /// Class to copy a graph to another graph (duplicate a graph). The
+ /// simplest way of using it is through the \c graphCopy() function.
+ ///
+ /// This class not only make a copy of a graph, but it can create
+ /// references and cross references between the nodes, edges and arcs of
+ /// the two graphs, and it can copy maps for using with the newly created
+ /// graph.
+ ///
+ /// To make a copy from a graph, first an instance of GraphCopy
+ /// should be created, then the data belongs to the graph should
+ /// assigned to copy. In the end, the \c run() member should be
+ /// called.
+ ///
+ /// The next code copies a graph with several data:
+ ///\code
+ /// GraphCopy<OrigGraph, NewGraph> cg(orig_graph, new_graph);
+ /// // Create references for the nodes
+ /// OrigGraph::NodeMap<NewGraph::Node> nr(orig_graph);
+ /// cg.nodeRef(nr);
+ /// // Create cross references (inverse) for the edges
+ /// NewGraph::EdgeMap<OrigGraph::Edge> ecr(new_graph);
+ /// cg.edgeCrossRef(ecr);
+ /// // Copy an edge map
+ /// OrigGraph::EdgeMap<double> oemap(orig_graph);
+ /// NewGraph::EdgeMap<double> nemap(new_graph);
+ /// cg.edgeMap(oemap, nemap);
+ /// // Copy a node
+ /// OrigGraph::Node on;
+ /// NewGraph::Node nn;
+ /// cg.node(on, nn);
+ /// // Execute copying
+ /// cg.run();
+ ///\endcode
+ template <typename From, typename To>
+ class GraphCopy {
+ private:
+
+ typedef typename From::Node Node;
+ typedef typename From::NodeIt NodeIt;
+ typedef typename From::Arc Arc;
+ typedef typename From::ArcIt ArcIt;
+ typedef typename From::Edge Edge;
+ typedef typename From::EdgeIt EdgeIt;
+
+ typedef typename To::Node TNode;
+ typedef typename To::Arc TArc;
+ typedef typename To::Edge TEdge;
+
+ typedef typename From::template NodeMap<TNode> NodeRefMap;
+ typedef typename From::template EdgeMap<TEdge> EdgeRefMap;
+
+ struct ArcRefMap {
+ ArcRefMap(const From& from, const To& to,
+ const EdgeRefMap& edge_ref, const NodeRefMap& node_ref)
+ : _from(from), _to(to),
+ _edge_ref(edge_ref), _node_ref(node_ref) {}
+
+ typedef typename From::Arc Key;
+ typedef typename To::Arc Value;
+
+ Value operator[](const Key& key) const {
+ bool forward = _from.u(key) != _from.v(key) ?
+ _node_ref[_from.source(key)] ==
+ _to.source(_to.direct(_edge_ref[key], true)) :
+ _from.direction(key);
+ return _to.direct(_edge_ref[key], forward);
+ }
+
+ const From& _from;
+ const To& _to;
+ const EdgeRefMap& _edge_ref;
+ const NodeRefMap& _node_ref;
+ };
+
+ public:
+
+ /// \brief Constructor of GraphCopy.
+ ///
+ /// Constructor of GraphCopy for copying the content of the
+ /// \c from graph into the \c to graph.
+ GraphCopy(const From& from, To& to)
+ : _from(from), _to(to) {}
+
+ /// \brief Destructor of GraphCopy
+ ///
+ /// Destructor of GraphCopy.
+ ~GraphCopy() {
+ for (int i = 0; i < int(_node_maps.size()); ++i) {
+ delete _node_maps[i];
+ }
+ for (int i = 0; i < int(_arc_maps.size()); ++i) {
+ delete _arc_maps[i];
+ }
+ for (int i = 0; i < int(_edge_maps.size()); ++i) {
+ delete _edge_maps[i];
+ }
+ }
+
+ /// \brief Copy the node references into the given map.
+ ///
+ /// This function copies the node references into the given map.
+ /// The parameter should be a map, whose key type is the Node type of
+ /// the source graph, while the value type is the Node type of the
+ /// destination graph.
+ template <typename NodeRef>
+ GraphCopy& nodeRef(NodeRef& map) {
+ _node_maps.push_back(new _core_bits::RefCopy<From, Node,
+ NodeRefMap, NodeRef>(map));
+ return *this;
+ }
+
+ /// \brief Copy the node cross references into the given map.
+ ///
+ /// This function copies the node cross references (reverse references)
+ /// into the given map. The parameter should be a map, whose key type
+ /// is the Node type of the destination graph, while the value type is
+ /// the Node type of the source graph.
+ template <typename NodeCrossRef>
+ GraphCopy& nodeCrossRef(NodeCrossRef& map) {
+ _node_maps.push_back(new _core_bits::CrossRefCopy<From, Node,
+ NodeRefMap, NodeCrossRef>(map));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given node map.
+ ///
+ /// This function makes a copy of the given node map for the newly
+ /// created graph.
+ /// The key type of the new map \c tmap should be the Node type of the
+ /// destination graph, and the key type of the original map \c map
+ /// should be the Node type of the source graph.
+ template <typename FromMap, typename ToMap>
+ GraphCopy& nodeMap(const FromMap& map, ToMap& tmap) {
+ _node_maps.push_back(new _core_bits::MapCopy<From, Node,
+ NodeRefMap, FromMap, ToMap>(map, tmap));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given node.
+ ///
+ /// This function makes a copy of the given node.
+ GraphCopy& node(const Node& node, TNode& tnode) {
+ _node_maps.push_back(new _core_bits::ItemCopy<From, Node,
+ NodeRefMap, TNode>(node, tnode));
+ return *this;
+ }
+
+ /// \brief Copy the arc references into the given map.
+ ///
+ /// This function copies the arc references into the given map.
+ /// The parameter should be a map, whose key type is the Arc type of
+ /// the source graph, while the value type is the Arc type of the
+ /// destination graph.
+ template <typename ArcRef>
+ GraphCopy& arcRef(ArcRef& map) {
+ _arc_maps.push_back(new _core_bits::RefCopy<From, Arc,
+ ArcRefMap, ArcRef>(map));
+ return *this;
+ }
+
+ /// \brief Copy the arc cross references into the given map.
+ ///
+ /// This function copies the arc cross references (reverse references)
+ /// into the given map. The parameter should be a map, whose key type
+ /// is the Arc type of the destination graph, while the value type is
+ /// the Arc type of the source graph.
+ template <typename ArcCrossRef>
+ GraphCopy& arcCrossRef(ArcCrossRef& map) {
+ _arc_maps.push_back(new _core_bits::CrossRefCopy<From, Arc,
+ ArcRefMap, ArcCrossRef>(map));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given arc map.
+ ///
+ /// This function makes a copy of the given arc map for the newly
+ /// created graph.
+ /// The key type of the new map \c tmap should be the Arc type of the
+ /// destination graph, and the key type of the original map \c map
+ /// should be the Arc type of the source graph.
+ template <typename FromMap, typename ToMap>
+ GraphCopy& arcMap(const FromMap& map, ToMap& tmap) {
+ _arc_maps.push_back(new _core_bits::MapCopy<From, Arc,
+ ArcRefMap, FromMap, ToMap>(map, tmap));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given arc.
+ ///
+ /// This function makes a copy of the given arc.
+ GraphCopy& arc(const Arc& arc, TArc& tarc) {
+ _arc_maps.push_back(new _core_bits::ItemCopy<From, Arc,
+ ArcRefMap, TArc>(arc, tarc));
+ return *this;
+ }
+
+ /// \brief Copy the edge references into the given map.
+ ///
+ /// This function copies the edge references into the given map.
+ /// The parameter should be a map, whose key type is the Edge type of
+ /// the source graph, while the value type is the Edge type of the
+ /// destination graph.
+ template <typename EdgeRef>
+ GraphCopy& edgeRef(EdgeRef& map) {
+ _edge_maps.push_back(new _core_bits::RefCopy<From, Edge,
+ EdgeRefMap, EdgeRef>(map));
+ return *this;
+ }
+
+ /// \brief Copy the edge cross references into the given map.
+ ///
+ /// This function copies the edge cross references (reverse references)
+ /// into the given map. The parameter should be a map, whose key type
+ /// is the Edge type of the destination graph, while the value type is
+ /// the Edge type of the source graph.
+ template <typename EdgeCrossRef>
+ GraphCopy& edgeCrossRef(EdgeCrossRef& map) {
+ _edge_maps.push_back(new _core_bits::CrossRefCopy<From,
+ Edge, EdgeRefMap, EdgeCrossRef>(map));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given edge map.
+ ///
+ /// This function makes a copy of the given edge map for the newly
+ /// created graph.
+ /// The key type of the new map \c tmap should be the Edge type of the
+ /// destination graph, and the key type of the original map \c map
+ /// should be the Edge type of the source graph.
+ template <typename FromMap, typename ToMap>
+ GraphCopy& edgeMap(const FromMap& map, ToMap& tmap) {
+ _edge_maps.push_back(new _core_bits::MapCopy<From, Edge,
+ EdgeRefMap, FromMap, ToMap>(map, tmap));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given edge.
+ ///
+ /// This function makes a copy of the given edge.
+ GraphCopy& edge(const Edge& edge, TEdge& tedge) {
+ _edge_maps.push_back(new _core_bits::ItemCopy<From, Edge,
+ EdgeRefMap, TEdge>(edge, tedge));
+ return *this;
+ }
+
+ /// \brief Execute copying.
+ ///
+ /// This function executes the copying of the graph along with the
+ /// copying of the assigned data.
+ void run() {
+ NodeRefMap nodeRefMap(_from);
+ EdgeRefMap edgeRefMap(_from);
+ ArcRefMap arcRefMap(_from, _to, edgeRefMap, nodeRefMap);
+ _core_bits::GraphCopySelector<To>::
+ copy(_from, _to, nodeRefMap, edgeRefMap);
+ for (int i = 0; i < int(_node_maps.size()); ++i) {
+ _node_maps[i]->copy(_from, nodeRefMap);
+ }
+ for (int i = 0; i < int(_edge_maps.size()); ++i) {
+ _edge_maps[i]->copy(_from, edgeRefMap);
+ }
+ for (int i = 0; i < int(_arc_maps.size()); ++i) {
+ _arc_maps[i]->copy(_from, arcRefMap);
+ }
+ }
+
+ private:
+
+ const From& _from;
+ To& _to;
+
+ std::vector<_core_bits::MapCopyBase<From, Node, NodeRefMap>* >
+ _node_maps;
+
+ std::vector<_core_bits::MapCopyBase<From, Arc, ArcRefMap>* >
+ _arc_maps;
+
+ std::vector<_core_bits::MapCopyBase<From, Edge, EdgeRefMap>* >
+ _edge_maps;
+
+ };
+
+ /// \brief Copy a graph to another graph.
+ ///
+ /// This function copies a graph to another graph.
+ /// The complete usage of it is detailed in the GraphCopy class,
+ /// but a short example shows a basic work:
+ ///\code
+ /// graphCopy(src, trg).nodeRef(nr).edgeCrossRef(ecr).run();
+ ///\endcode
+ ///
+ /// After the copy the \c nr map will contain the mapping from the
+ /// nodes of the \c from graph to the nodes of the \c to graph and
+ /// \c ecr will contain the mapping from the edges of the \c to graph
+ /// to the edges of the \c from graph.
+ ///
+ /// \see GraphCopy
+ template <typename From, typename To>
+ GraphCopy<From, To>
+ graphCopy(const From& from, To& to) {
+ return GraphCopy<From, To>(from, to);
+ }
+
+ /// \brief Class to copy a bipartite graph.
+ ///
+ /// Class to copy a bipartite graph to another graph (duplicate a
+ /// graph). The simplest way of using it is through the
+ /// \c bpGraphCopy() function.
+ ///
+ /// This class not only make a copy of a bipartite graph, but it can
+ /// create references and cross references between the nodes, edges
+ /// and arcs of the two graphs, and it can copy maps for using with
+ /// the newly created graph.
+ ///
+ /// To make a copy from a graph, first an instance of BpGraphCopy
+ /// should be created, then the data belongs to the graph should
+ /// assigned to copy. In the end, the \c run() member should be
+ /// called.
+ ///
+ /// The next code copies a graph with several data:
+ ///\code
+ /// BpGraphCopy<OrigBpGraph, NewBpGraph> cg(orig_graph, new_graph);
+ /// // Create references for the nodes
+ /// OrigBpGraph::NodeMap<NewBpGraph::Node> nr(orig_graph);
+ /// cg.nodeRef(nr);
+ /// // Create cross references (inverse) for the edges
+ /// NewBpGraph::EdgeMap<OrigBpGraph::Edge> ecr(new_graph);
+ /// cg.edgeCrossRef(ecr);
+ /// // Copy a red node map
+ /// OrigBpGraph::RedNodeMap<double> ormap(orig_graph);
+ /// NewBpGraph::RedNodeMap<double> nrmap(new_graph);
+ /// cg.redNodeMap(ormap, nrmap);
+ /// // Copy a node
+ /// OrigBpGraph::Node on;
+ /// NewBpGraph::Node nn;
+ /// cg.node(on, nn);
+ /// // Execute copying
+ /// cg.run();
+ ///\endcode
+ template <typename From, typename To>
+ class BpGraphCopy {
+ private:
+
+ typedef typename From::Node Node;
+ typedef typename From::RedNode RedNode;
+ typedef typename From::BlueNode BlueNode;
+ typedef typename From::NodeIt NodeIt;
+ typedef typename From::Arc Arc;
+ typedef typename From::ArcIt ArcIt;
+ typedef typename From::Edge Edge;
+ typedef typename From::EdgeIt EdgeIt;
+
+ typedef typename To::Node TNode;
+ typedef typename To::RedNode TRedNode;
+ typedef typename To::BlueNode TBlueNode;
+ typedef typename To::Arc TArc;
+ typedef typename To::Edge TEdge;
+
+ typedef typename From::template RedNodeMap<TRedNode> RedNodeRefMap;
+ typedef typename From::template BlueNodeMap<TBlueNode> BlueNodeRefMap;
+ typedef typename From::template EdgeMap<TEdge> EdgeRefMap;
+
+ struct NodeRefMap {
+ NodeRefMap(const From& from, const RedNodeRefMap& red_node_ref,
+ const BlueNodeRefMap& blue_node_ref)
+ : _from(from), _red_node_ref(red_node_ref),
+ _blue_node_ref(blue_node_ref) {}
+
+ typedef typename From::Node Key;
+ typedef typename To::Node Value;
+
+ Value operator[](const Key& key) const {
+ if (_from.red(key)) {
+ return _red_node_ref[_from.asRedNodeUnsafe(key)];
+ } else {
+ return _blue_node_ref[_from.asBlueNodeUnsafe(key)];
+ }
+ }
+
+ const From& _from;
+ const RedNodeRefMap& _red_node_ref;
+ const BlueNodeRefMap& _blue_node_ref;
+ };
+
+ struct ArcRefMap {
+ ArcRefMap(const From& from, const To& to, const EdgeRefMap& edge_ref)
+ : _from(from), _to(to), _edge_ref(edge_ref) {}
+
+ typedef typename From::Arc Key;
+ typedef typename To::Arc Value;
+
+ Value operator[](const Key& key) const {
+ return _to.direct(_edge_ref[key], _from.direction(key));
+ }
+
+ const From& _from;
+ const To& _to;
+ const EdgeRefMap& _edge_ref;
+ };
+
+ public:
+
+ /// \brief Constructor of BpGraphCopy.
+ ///
+ /// Constructor of BpGraphCopy for copying the content of the
+ /// \c from graph into the \c to graph.
+ BpGraphCopy(const From& from, To& to)
+ : _from(from), _to(to) {}
+
+ /// \brief Destructor of BpGraphCopy
+ ///
+ /// Destructor of BpGraphCopy.
+ ~BpGraphCopy() {
+ for (int i = 0; i < int(_node_maps.size()); ++i) {
+ delete _node_maps[i];
+ }
+ for (int i = 0; i < int(_red_maps.size()); ++i) {
+ delete _red_maps[i];
+ }
+ for (int i = 0; i < int(_blue_maps.size()); ++i) {
+ delete _blue_maps[i];
+ }
+ for (int i = 0; i < int(_arc_maps.size()); ++i) {
+ delete _arc_maps[i];
+ }
+ for (int i = 0; i < int(_edge_maps.size()); ++i) {
+ delete _edge_maps[i];
+ }
+ }
+
+ /// \brief Copy the node references into the given map.
+ ///
+ /// This function copies the node references into the given map.
+ /// The parameter should be a map, whose key type is the Node type of
+ /// the source graph, while the value type is the Node type of the
+ /// destination graph.
+ template <typename NodeRef>
+ BpGraphCopy& nodeRef(NodeRef& map) {
+ _node_maps.push_back(new _core_bits::RefCopy<From, Node,
+ NodeRefMap, NodeRef>(map));
+ return *this;
+ }
+
+ /// \brief Copy the node cross references into the given map.
+ ///
+ /// This function copies the node cross references (reverse references)
+ /// into the given map. The parameter should be a map, whose key type
+ /// is the Node type of the destination graph, while the value type is
+ /// the Node type of the source graph.
+ template <typename NodeCrossRef>
+ BpGraphCopy& nodeCrossRef(NodeCrossRef& map) {
+ _node_maps.push_back(new _core_bits::CrossRefCopy<From, Node,
+ NodeRefMap, NodeCrossRef>(map));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given node map.
+ ///
+ /// This function makes a copy of the given node map for the newly
+ /// created graph.
+ /// The key type of the new map \c tmap should be the Node type of the
+ /// destination graph, and the key type of the original map \c map
+ /// should be the Node type of the source graph.
+ template <typename FromMap, typename ToMap>
+ BpGraphCopy& nodeMap(const FromMap& map, ToMap& tmap) {
+ _node_maps.push_back(new _core_bits::MapCopy<From, Node,
+ NodeRefMap, FromMap, ToMap>(map, tmap));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given node.
+ ///
+ /// This function makes a copy of the given node.
+ BpGraphCopy& node(const Node& node, TNode& tnode) {
+ _node_maps.push_back(new _core_bits::ItemCopy<From, Node,
+ NodeRefMap, TNode>(node, tnode));
+ return *this;
+ }
+
+ /// \brief Copy the red node references into the given map.
+ ///
+ /// This function copies the red node references into the given
+ /// map. The parameter should be a map, whose key type is the
+ /// Node type of the source graph with the red item set, while the
+ /// value type is the Node type of the destination graph.
+ template <typename RedRef>
+ BpGraphCopy& redRef(RedRef& map) {
+ _red_maps.push_back(new _core_bits::RefCopy<From, RedNode,
+ RedNodeRefMap, RedRef>(map));
+ return *this;
+ }
+
+ /// \brief Copy the red node cross references into the given map.
+ ///
+ /// This function copies the red node cross references (reverse
+ /// references) into the given map. The parameter should be a map,
+ /// whose key type is the Node type of the destination graph with
+ /// the red item set, while the value type is the Node type of the
+ /// source graph.
+ template <typename RedCrossRef>
+ BpGraphCopy& redCrossRef(RedCrossRef& map) {
+ _red_maps.push_back(new _core_bits::CrossRefCopy<From, RedNode,
+ RedNodeRefMap, RedCrossRef>(map));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given red node map.
+ ///
+ /// This function makes a copy of the given red node map for the newly
+ /// created graph.
+ /// The key type of the new map \c tmap should be the Node type of
+ /// the destination graph with the red items, and the key type of
+ /// the original map \c map should be the Node type of the source
+ /// graph.
+ template <typename FromMap, typename ToMap>
+ BpGraphCopy& redNodeMap(const FromMap& map, ToMap& tmap) {
+ _red_maps.push_back(new _core_bits::MapCopy<From, RedNode,
+ RedNodeRefMap, FromMap, ToMap>(map, tmap));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given red node.
+ ///
+ /// This function makes a copy of the given red node.
+ BpGraphCopy& redNode(const RedNode& node, TRedNode& tnode) {
+ _red_maps.push_back(new _core_bits::ItemCopy<From, RedNode,
+ RedNodeRefMap, TRedNode>(node, tnode));
+ return *this;
+ }
+
+ /// \brief Copy the blue node references into the given map.
+ ///
+ /// This function copies the blue node references into the given
+ /// map. The parameter should be a map, whose key type is the
+ /// Node type of the source graph with the blue item set, while the
+ /// value type is the Node type of the destination graph.
+ template <typename BlueRef>
+ BpGraphCopy& blueRef(BlueRef& map) {
+ _blue_maps.push_back(new _core_bits::RefCopy<From, BlueNode,
+ BlueNodeRefMap, BlueRef>(map));
+ return *this;
+ }
+
+ /// \brief Copy the blue node cross references into the given map.
+ ///
+ /// This function copies the blue node cross references (reverse
+ /// references) into the given map. The parameter should be a map,
+ /// whose key type is the Node type of the destination graph with
+ /// the blue item set, while the value type is the Node type of the
+ /// source graph.
+ template <typename BlueCrossRef>
+ BpGraphCopy& blueCrossRef(BlueCrossRef& map) {
+ _blue_maps.push_back(new _core_bits::CrossRefCopy<From, BlueNode,
+ BlueNodeRefMap, BlueCrossRef>(map));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given blue node map.
+ ///
+ /// This function makes a copy of the given blue node map for the newly
+ /// created graph.
+ /// The key type of the new map \c tmap should be the Node type of
+ /// the destination graph with the blue items, and the key type of
+ /// the original map \c map should be the Node type of the source
+ /// graph.
+ template <typename FromMap, typename ToMap>
+ BpGraphCopy& blueNodeMap(const FromMap& map, ToMap& tmap) {
+ _blue_maps.push_back(new _core_bits::MapCopy<From, BlueNode,
+ BlueNodeRefMap, FromMap, ToMap>(map, tmap));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given blue node.
+ ///
+ /// This function makes a copy of the given blue node.
+ BpGraphCopy& blueNode(const BlueNode& node, TBlueNode& tnode) {
+ _blue_maps.push_back(new _core_bits::ItemCopy<From, BlueNode,
+ BlueNodeRefMap, TBlueNode>(node, tnode));
+ return *this;
+ }
+
+ /// \brief Copy the arc references into the given map.
+ ///
+ /// This function copies the arc references into the given map.
+ /// The parameter should be a map, whose key type is the Arc type of
+ /// the source graph, while the value type is the Arc type of the
+ /// destination graph.
+ template <typename ArcRef>
+ BpGraphCopy& arcRef(ArcRef& map) {
+ _arc_maps.push_back(new _core_bits::RefCopy<From, Arc,
+ ArcRefMap, ArcRef>(map));
+ return *this;
+ }
+
+ /// \brief Copy the arc cross references into the given map.
+ ///
+ /// This function copies the arc cross references (reverse references)
+ /// into the given map. The parameter should be a map, whose key type
+ /// is the Arc type of the destination graph, while the value type is
+ /// the Arc type of the source graph.
+ template <typename ArcCrossRef>
+ BpGraphCopy& arcCrossRef(ArcCrossRef& map) {
+ _arc_maps.push_back(new _core_bits::CrossRefCopy<From, Arc,
+ ArcRefMap, ArcCrossRef>(map));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given arc map.
+ ///
+ /// This function makes a copy of the given arc map for the newly
+ /// created graph.
+ /// The key type of the new map \c tmap should be the Arc type of the
+ /// destination graph, and the key type of the original map \c map
+ /// should be the Arc type of the source graph.
+ template <typename FromMap, typename ToMap>
+ BpGraphCopy& arcMap(const FromMap& map, ToMap& tmap) {
+ _arc_maps.push_back(new _core_bits::MapCopy<From, Arc,
+ ArcRefMap, FromMap, ToMap>(map, tmap));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given arc.
+ ///
+ /// This function makes a copy of the given arc.
+ BpGraphCopy& arc(const Arc& arc, TArc& tarc) {
+ _arc_maps.push_back(new _core_bits::ItemCopy<From, Arc,
+ ArcRefMap, TArc>(arc, tarc));
+ return *this;
+ }
+
+ /// \brief Copy the edge references into the given map.
+ ///
+ /// This function copies the edge references into the given map.
+ /// The parameter should be a map, whose key type is the Edge type of
+ /// the source graph, while the value type is the Edge type of the
+ /// destination graph.
+ template <typename EdgeRef>
+ BpGraphCopy& edgeRef(EdgeRef& map) {
+ _edge_maps.push_back(new _core_bits::RefCopy<From, Edge,
+ EdgeRefMap, EdgeRef>(map));
+ return *this;
+ }
+
+ /// \brief Copy the edge cross references into the given map.
+ ///
+ /// This function copies the edge cross references (reverse references)
+ /// into the given map. The parameter should be a map, whose key type
+ /// is the Edge type of the destination graph, while the value type is
+ /// the Edge type of the source graph.
+ template <typename EdgeCrossRef>
+ BpGraphCopy& edgeCrossRef(EdgeCrossRef& map) {
+ _edge_maps.push_back(new _core_bits::CrossRefCopy<From,
+ Edge, EdgeRefMap, EdgeCrossRef>(map));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given edge map.
+ ///
+ /// This function makes a copy of the given edge map for the newly
+ /// created graph.
+ /// The key type of the new map \c tmap should be the Edge type of the
+ /// destination graph, and the key type of the original map \c map
+ /// should be the Edge type of the source graph.
+ template <typename FromMap, typename ToMap>
+ BpGraphCopy& edgeMap(const FromMap& map, ToMap& tmap) {
+ _edge_maps.push_back(new _core_bits::MapCopy<From, Edge,
+ EdgeRefMap, FromMap, ToMap>(map, tmap));
+ return *this;
+ }
+
+ /// \brief Make a copy of the given edge.
+ ///
+ /// This function makes a copy of the given edge.
+ BpGraphCopy& edge(const Edge& edge, TEdge& tedge) {
+ _edge_maps.push_back(new _core_bits::ItemCopy<From, Edge,
+ EdgeRefMap, TEdge>(edge, tedge));
+ return *this;
+ }
+
+ /// \brief Execute copying.
+ ///
+ /// This function executes the copying of the graph along with the
+ /// copying of the assigned data.
+ void run() {
+ RedNodeRefMap redNodeRefMap(_from);
+ BlueNodeRefMap blueNodeRefMap(_from);
+ NodeRefMap nodeRefMap(_from, redNodeRefMap, blueNodeRefMap);
+ EdgeRefMap edgeRefMap(_from);
+ ArcRefMap arcRefMap(_from, _to, edgeRefMap);
+ _core_bits::BpGraphCopySelector<To>::
+ copy(_from, _to, redNodeRefMap, blueNodeRefMap, edgeRefMap);
+ for (int i = 0; i < int(_node_maps.size()); ++i) {
+ _node_maps[i]->copy(_from, nodeRefMap);
+ }
+ for (int i = 0; i < int(_red_maps.size()); ++i) {
+ _red_maps[i]->copy(_from, redNodeRefMap);
+ }
+ for (int i = 0; i < int(_blue_maps.size()); ++i) {
+ _blue_maps[i]->copy(_from, blueNodeRefMap);
+ }
+ for (int i = 0; i < int(_edge_maps.size()); ++i) {
+ _edge_maps[i]->copy(_from, edgeRefMap);
+ }
+ for (int i = 0; i < int(_arc_maps.size()); ++i) {
+ _arc_maps[i]->copy(_from, arcRefMap);
+ }
+ }
+
+ private:
+
+ const From& _from;
+ To& _to;
+
+ std::vector<_core_bits::MapCopyBase<From, Node, NodeRefMap>* >
+ _node_maps;
+
+ std::vector<_core_bits::MapCopyBase<From, RedNode, RedNodeRefMap>* >
+ _red_maps;
+
+ std::vector<_core_bits::MapCopyBase<From, BlueNode, BlueNodeRefMap>* >
+ _blue_maps;
+
+ std::vector<_core_bits::MapCopyBase<From, Arc, ArcRefMap>* >
+ _arc_maps;
+
+ std::vector<_core_bits::MapCopyBase<From, Edge, EdgeRefMap>* >
+ _edge_maps;
+
+ };
+
+ /// \brief Copy a graph to another graph.
+ ///
+ /// This function copies a graph to another graph.
+ /// The complete usage of it is detailed in the BpGraphCopy class,
+ /// but a short example shows a basic work:
+ ///\code
+ /// graphCopy(src, trg).nodeRef(nr).edgeCrossRef(ecr).run();
+ ///\endcode
+ ///
+ /// After the copy the \c nr map will contain the mapping from the
+ /// nodes of the \c from graph to the nodes of the \c to graph and
+ /// \c ecr will contain the mapping from the edges of the \c to graph
+ /// to the edges of the \c from graph.
+ ///
+ /// \see BpGraphCopy
+ template <typename From, typename To>
+ BpGraphCopy<From, To>
+ bpGraphCopy(const From& from, To& to) {
+ return BpGraphCopy<From, To>(from, to);
+ }
+
+ namespace _core_bits {
+
+ template <typename Graph, typename Enable = void>
+ struct FindArcSelector {
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Arc Arc;
+ static Arc find(const Graph &g, Node u, Node v, Arc e) {
+ if (e == INVALID) {
+ g.firstOut(e, u);
+ } else {
+ g.nextOut(e);
+ }
+ while (e != INVALID && g.target(e) != v) {
+ g.nextOut(e);
+ }
+ return e;
+ }
+ };
+
+ template <typename Graph>
+ struct FindArcSelector<
+ Graph,
+ typename enable_if<typename Graph::FindArcTag, void>::type>
+ {
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Arc Arc;
+ static Arc find(const Graph &g, Node u, Node v, Arc prev) {
+ return g.findArc(u, v, prev);
+ }
+ };
+ }
+
+ /// \brief Find an arc between two nodes of a digraph.
+ ///
+ /// This function finds an arc from node \c u to node \c v in the
+ /// digraph \c g.
+ ///
+ /// If \c prev is \ref INVALID (this is the default value), then
+ /// it finds the first arc from \c u to \c v. Otherwise it looks for
+ /// the next arc from \c u to \c v after \c prev.
+ /// \return The found arc or \ref INVALID if there is no such an arc.
+ ///
+ /// Thus you can iterate through each arc from \c u to \c v as it follows.
+ ///\code
+ /// for(Arc e = findArc(g,u,v); e != INVALID; e = findArc(g,u,v,e)) {
+ /// ...
+ /// }
+ ///\endcode
+ ///
+ /// \note \ref ConArcIt provides iterator interface for the same
+ /// functionality.
+ ///
+ ///\sa ConArcIt
+ ///\sa ArcLookUp, AllArcLookUp, DynArcLookUp
+ template <typename Graph>
+ inline typename Graph::Arc
+ findArc(const Graph &g, typename Graph::Node u, typename Graph::Node v,
+ typename Graph::Arc prev = INVALID) {
+ return _core_bits::FindArcSelector<Graph>::find(g, u, v, prev);
+ }
+
+ /// \brief Iterator for iterating on parallel arcs connecting the same nodes.
+ ///
+ /// Iterator for iterating on parallel arcs connecting the same nodes. It is
+ /// a higher level interface for the \ref findArc() function. You can
+ /// use it the following way:
+ ///\code
+ /// for (ConArcIt<Graph> it(g, src, trg); it != INVALID; ++it) {
+ /// ...
+ /// }
+ ///\endcode
+ ///
+ ///\sa findArc()
+ ///\sa ArcLookUp, AllArcLookUp, DynArcLookUp
+ template <typename GR>
+ class ConArcIt : public GR::Arc {
+ typedef typename GR::Arc Parent;
+
+ public:
+
+ typedef typename GR::Arc Arc;
+ typedef typename GR::Node Node;
+
+ /// \brief Constructor.
+ ///
+ /// Construct a new ConArcIt iterating on the arcs that
+ /// connects nodes \c u and \c v.
+ ConArcIt(const GR& g, Node u, Node v) : _graph(g) {
+ Parent::operator=(findArc(_graph, u, v));
+ }
+
+ /// \brief Constructor.
+ ///
+ /// Construct a new ConArcIt that continues the iterating from arc \c a.
+ ConArcIt(const GR& g, Arc a) : Parent(a), _graph(g) {}
+
+ /// \brief Increment operator.
+ ///
+ /// It increments the iterator and gives back the next arc.
+ ConArcIt& operator++() {
+ Parent::operator=(findArc(_graph, _graph.source(*this),
+ _graph.target(*this), *this));
+ return *this;
+ }
+ private:
+ const GR& _graph;
+ };
+
+ namespace _core_bits {
+
+ template <typename Graph, typename Enable = void>
+ struct FindEdgeSelector {
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Edge Edge;
+ static Edge find(const Graph &g, Node u, Node v, Edge e) {
+ bool b;
+ if (u != v) {
+ if (e == INVALID) {
+ g.firstInc(e, b, u);
+ } else {
+ b = g.u(e) == u;
+ g.nextInc(e, b);
+ }
+ while (e != INVALID && (b ? g.v(e) : g.u(e)) != v) {
+ g.nextInc(e, b);
+ }
+ } else {
+ if (e == INVALID) {
+ g.firstInc(e, b, u);
+ } else {
+ b = true;
+ g.nextInc(e, b);
+ }
+ while (e != INVALID && (!b || g.v(e) != v)) {
+ g.nextInc(e, b);
+ }
+ }
+ return e;
+ }
+ };
+
+ template <typename Graph>
+ struct FindEdgeSelector<
+ Graph,
+ typename enable_if<typename Graph::FindEdgeTag, void>::type>
+ {
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Edge Edge;
+ static Edge find(const Graph &g, Node u, Node v, Edge prev) {
+ return g.findEdge(u, v, prev);
+ }
+ };
+ }
+
+ /// \brief Find an edge between two nodes of a graph.
+ ///
+ /// This function finds an edge from node \c u to node \c v in graph \c g.
+ /// If node \c u and node \c v is equal then each loop edge
+ /// will be enumerated once.
+ ///
+ /// If \c prev is \ref INVALID (this is the default value), then
+ /// it finds the first edge from \c u to \c v. Otherwise it looks for
+ /// the next edge from \c u to \c v after \c prev.
+ /// \return The found edge or \ref INVALID if there is no such an edge.
+ ///
+ /// Thus you can iterate through each edge between \c u and \c v
+ /// as it follows.
+ ///\code
+ /// for(Edge e = findEdge(g,u,v); e != INVALID; e = findEdge(g,u,v,e)) {
+ /// ...
+ /// }
+ ///\endcode
+ ///
+ /// \note \ref ConEdgeIt provides iterator interface for the same
+ /// functionality.
+ ///
+ ///\sa ConEdgeIt
+ template <typename Graph>
+ inline typename Graph::Edge
+ findEdge(const Graph &g, typename Graph::Node u, typename Graph::Node v,
+ typename Graph::Edge p = INVALID) {
+ return _core_bits::FindEdgeSelector<Graph>::find(g, u, v, p);
+ }
+
+ /// \brief Iterator for iterating on parallel edges connecting the same nodes.
+ ///
+ /// Iterator for iterating on parallel edges connecting the same nodes.
+ /// It is a higher level interface for the findEdge() function. You can
+ /// use it the following way:
+ ///\code
+ /// for (ConEdgeIt<Graph> it(g, u, v); it != INVALID; ++it) {
+ /// ...
+ /// }
+ ///\endcode
+ ///
+ ///\sa findEdge()
+ template <typename GR>
+ class ConEdgeIt : public GR::Edge {
+ typedef typename GR::Edge Parent;
+
+ public:
+
+ typedef typename GR::Edge Edge;
+ typedef typename GR::Node Node;
+
+ /// \brief Constructor.
+ ///
+ /// Construct a new ConEdgeIt iterating on the edges that
+ /// connects nodes \c u and \c v.
+ ConEdgeIt(const GR& g, Node u, Node v) : _graph(g), _u(u), _v(v) {
+ Parent::operator=(findEdge(_graph, _u, _v));
+ }
+
+ /// \brief Constructor.
+ ///
+ /// Construct a new ConEdgeIt that continues iterating from edge \c e.
+ ConEdgeIt(const GR& g, Edge e) : Parent(e), _graph(g) {}
+
+ /// \brief Increment operator.
+ ///
+ /// It increments the iterator and gives back the next edge.
+ ConEdgeIt& operator++() {
+ Parent::operator=(findEdge(_graph, _u, _v, *this));
+ return *this;
+ }
+ private:
+ const GR& _graph;
+ Node _u, _v;
+ };
+
+
+ ///Dynamic arc look-up between given endpoints.
+
+ ///Using this class, you can find an arc in a digraph from a given
+ ///source to a given target in amortized time <em>O</em>(log<em>d</em>),
+ ///where <em>d</em> is the out-degree of the source node.
+ ///
+ ///It is possible to find \e all parallel arcs between two nodes with
+ ///the \c operator() member.
+ ///
+ ///This is a dynamic data structure. Consider to use \ref ArcLookUp or
+ ///\ref AllArcLookUp if your digraph is not changed so frequently.
+ ///
+ ///This class uses a self-adjusting binary search tree, the Splay tree
+ ///of Sleator and Tarjan to guarantee the logarithmic amortized
+ ///time bound for arc look-ups. This class also guarantees the
+ ///optimal time bound in a constant factor for any distribution of
+ ///queries.
+ ///
+ ///\tparam GR The type of the underlying digraph.
+ ///
+ ///\sa ArcLookUp
+ ///\sa AllArcLookUp
+ template <typename GR>
+ class DynArcLookUp
+ : protected ItemSetTraits<GR, typename GR::Arc>::ItemNotifier::ObserverBase
+ {
+ typedef typename ItemSetTraits<GR, typename GR::Arc>
+ ::ItemNotifier::ObserverBase Parent;
+
+ TEMPLATE_DIGRAPH_TYPEDEFS(GR);
+
+ public:
+
+ /// The Digraph type
+ typedef GR Digraph;
+
+ protected:
+
+ class AutoNodeMap : public ItemSetTraits<GR, Node>::template Map<Arc>::Type
+ {
+ typedef typename ItemSetTraits<GR, Node>::template Map<Arc>::Type Parent;
+
+ public:
+
+ AutoNodeMap(const GR& digraph) : Parent(digraph, INVALID) {}
+
+ virtual void add(const Node& node) {
+ Parent::add(node);
+ Parent::set(node, INVALID);
+ }
+
+ virtual void add(const std::vector<Node>& nodes) {
+ Parent::add(nodes);
+ for (int i = 0; i < int(nodes.size()); ++i) {
+ Parent::set(nodes[i], INVALID);
+ }
+ }
+
+ virtual void build() {
+ Parent::build();
+ Node it;
+ typename Parent::Notifier* nf = Parent::notifier();
+ for (nf->first(it); it != INVALID; nf->next(it)) {
+ Parent::set(it, INVALID);
+ }
+ }
+ };
+
+ class ArcLess {
+ const Digraph &g;
+ public:
+ ArcLess(const Digraph &_g) : g(_g) {}
+ bool operator()(Arc a,Arc b) const
+ {
+ return g.target(a)<g.target(b);
+ }
+ };
+
+ protected:
+
+ const Digraph &_g;
+ AutoNodeMap _head;
+ typename Digraph::template ArcMap<Arc> _parent;
+ typename Digraph::template ArcMap<Arc> _left;
+ typename Digraph::template ArcMap<Arc> _right;
+
+ public:
+
+ ///Constructor
+
+ ///Constructor.
+ ///
+ ///It builds up the search database.
+ DynArcLookUp(const Digraph &g)
+ : _g(g),_head(g),_parent(g),_left(g),_right(g)
+ {
+ Parent::attach(_g.notifier(typename Digraph::Arc()));
+ refresh();
+ }
+
+ protected:
+
+ virtual void add(const Arc& arc) {
+ insert(arc);
+ }
+
+ virtual void add(const std::vector<Arc>& arcs) {
+ for (int i = 0; i < int(arcs.size()); ++i) {
+ insert(arcs[i]);
+ }
+ }
+
+ virtual void erase(const Arc& arc) {
+ remove(arc);
+ }
+
+ virtual void erase(const std::vector<Arc>& arcs) {
+ for (int i = 0; i < int(arcs.size()); ++i) {
+ remove(arcs[i]);
+ }
+ }
+
+ virtual void build() {
+ refresh();
+ }
+
+ virtual void clear() {
+ for(NodeIt n(_g);n!=INVALID;++n) {
+ _head[n] = INVALID;
+ }
+ }
+
+ void insert(Arc arc) {
+ Node s = _g.source(arc);
+ Node t = _g.target(arc);
+ _left[arc] = INVALID;
+ _right[arc] = INVALID;
+
+ Arc e = _head[s];
+ if (e == INVALID) {
+ _head[s] = arc;
+ _parent[arc] = INVALID;
+ return;
+ }
+ while (true) {
+ if (t < _g.target(e)) {
+ if (_left[e] == INVALID) {
+ _left[e] = arc;
+ _parent[arc] = e;
+ splay(arc);
+ return;
+ } else {
+ e = _left[e];
+ }
+ } else {
+ if (_right[e] == INVALID) {
+ _right[e] = arc;
+ _parent[arc] = e;
+ splay(arc);
+ return;
+ } else {
+ e = _right[e];
+ }
+ }
+ }
+ }
+
+ void remove(Arc arc) {
+ if (_left[arc] == INVALID) {
+ if (_right[arc] != INVALID) {
+ _parent[_right[arc]] = _parent[arc];
+ }
+ if (_parent[arc] != INVALID) {
+ if (_left[_parent[arc]] == arc) {
+ _left[_parent[arc]] = _right[arc];
+ } else {
+ _right[_parent[arc]] = _right[arc];
+ }
+ } else {
+ _head[_g.source(arc)] = _right[arc];
+ }
+ } else if (_right[arc] == INVALID) {
+ _parent[_left[arc]] = _parent[arc];
+ if (_parent[arc] != INVALID) {
+ if (_left[_parent[arc]] == arc) {
+ _left[_parent[arc]] = _left[arc];
+ } else {
+ _right[_parent[arc]] = _left[arc];
+ }
+ } else {
+ _head[_g.source(arc)] = _left[arc];
+ }
+ } else {
+ Arc e = _left[arc];
+ if (_right[e] != INVALID) {
+ e = _right[e];
+ while (_right[e] != INVALID) {
+ e = _right[e];
+ }
+ Arc s = _parent[e];
+ _right[_parent[e]] = _left[e];
+ if (_left[e] != INVALID) {
+ _parent[_left[e]] = _parent[e];
+ }
+
+ _left[e] = _left[arc];
+ _parent[_left[arc]] = e;
+ _right[e] = _right[arc];
+ _parent[_right[arc]] = e;
+
+ _parent[e] = _parent[arc];
+ if (_parent[arc] != INVALID) {
+ if (_left[_parent[arc]] == arc) {
+ _left[_parent[arc]] = e;
+ } else {
+ _right[_parent[arc]] = e;
+ }
+ }
+ splay(s);
+ } else {
+ _right[e] = _right[arc];
+ _parent[_right[arc]] = e;
+ _parent[e] = _parent[arc];
+
+ if (_parent[arc] != INVALID) {
+ if (_left[_parent[arc]] == arc) {
+ _left[_parent[arc]] = e;
+ } else {
+ _right[_parent[arc]] = e;
+ }
+ } else {
+ _head[_g.source(arc)] = e;
+ }
+ }
+ }
+ }
+
+ Arc refreshRec(std::vector<Arc> &v,int a,int b)
+ {
+ int m=(a+b)/2;
+ Arc me=v[m];
+ if (a < m) {
+ Arc left = refreshRec(v,a,m-1);
+ _left[me] = left;
+ _parent[left] = me;
+ } else {
+ _left[me] = INVALID;
+ }
+ if (m < b) {
+ Arc right = refreshRec(v,m+1,b);
+ _right[me] = right;
+ _parent[right] = me;
+ } else {
+ _right[me] = INVALID;
+ }
+ return me;
+ }
+
+ void refresh() {
+ for(NodeIt n(_g);n!=INVALID;++n) {
+ std::vector<Arc> v;
+ for(OutArcIt a(_g,n);a!=INVALID;++a) v.push_back(a);
+ if (!v.empty()) {
+ std::sort(v.begin(),v.end(),ArcLess(_g));
+ Arc head = refreshRec(v,0,v.size()-1);
+ _head[n] = head;
+ _parent[head] = INVALID;
+ }
+ else _head[n] = INVALID;
+ }
+ }
+
+ void zig(Arc v) {
+ Arc w = _parent[v];
+ _parent[v] = _parent[w];
+ _parent[w] = v;
+ _left[w] = _right[v];
+ _right[v] = w;
+ if (_parent[v] != INVALID) {
+ if (_right[_parent[v]] == w) {
+ _right[_parent[v]] = v;
+ } else {
+ _left[_parent[v]] = v;
+ }
+ }
+ if (_left[w] != INVALID){
+ _parent[_left[w]] = w;
+ }
+ }
+
+ void zag(Arc v) {
+ Arc w = _parent[v];
+ _parent[v] = _parent[w];
+ _parent[w] = v;
+ _right[w] = _left[v];
+ _left[v] = w;
+ if (_parent[v] != INVALID){
+ if (_left[_parent[v]] == w) {
+ _left[_parent[v]] = v;
+ } else {
+ _right[_parent[v]] = v;
+ }
+ }
+ if (_right[w] != INVALID){
+ _parent[_right[w]] = w;
+ }
+ }
+
+ void splay(Arc v) {
+ while (_parent[v] != INVALID) {
+ if (v == _left[_parent[v]]) {
+ if (_parent[_parent[v]] == INVALID) {
+ zig(v);
+ } else {
+ if (_parent[v] == _left[_parent[_parent[v]]]) {
+ zig(_parent[v]);
+ zig(v);
+ } else {
+ zig(v);
+ zag(v);
+ }
+ }
+ } else {
+ if (_parent[_parent[v]] == INVALID) {
+ zag(v);
+ } else {
+ if (_parent[v] == _left[_parent[_parent[v]]]) {
+ zag(v);
+ zig(v);
+ } else {
+ zag(_parent[v]);
+ zag(v);
+ }
+ }
+ }
+ }
+ _head[_g.source(v)] = v;
+ }
+
+
+ public:
+
+ ///Find an arc between two nodes.
+
+ ///Find an arc between two nodes.
+ ///\param s The source node.
+ ///\param t The target node.
+ ///\param p The previous arc between \c s and \c t. It it is INVALID or
+ ///not given, the operator finds the first appropriate arc.
+ ///\return An arc from \c s to \c t after \c p or
+ ///\ref INVALID if there is no more.
+ ///
+ ///For example, you can count the number of arcs from \c u to \c v in the
+ ///following way.
+ ///\code
+ ///DynArcLookUp<ListDigraph> ae(g);
+ ///...
+ ///int n = 0;
+ ///for(Arc a = ae(u,v); a != INVALID; a = ae(u,v,a)) n++;
+ ///\endcode
+ ///
+ ///Finding the arcs take at most <em>O</em>(log<em>d</em>)
+ ///amortized time, specifically, the time complexity of the lookups
+ ///is equal to the optimal search tree implementation for the
+ ///current query distribution in a constant factor.
+ ///
+ ///\note This is a dynamic data structure, therefore the data
+ ///structure is updated after each graph alteration. Thus although
+ ///this data structure is theoretically faster than \ref ArcLookUp
+ ///and \ref AllArcLookUp, it often provides worse performance than
+ ///them.
+ Arc operator()(Node s, Node t, Arc p = INVALID) const {
+ if (p == INVALID) {
+ Arc a = _head[s];
+ if (a == INVALID) return INVALID;
+ Arc r = INVALID;
+ while (true) {
+ if (_g.target(a) < t) {
+ if (_right[a] == INVALID) {
+ const_cast<DynArcLookUp&>(*this).splay(a);
+ return r;
+ } else {
+ a = _right[a];
+ }
+ } else {
+ if (_g.target(a) == t) {
+ r = a;
+ }
+ if (_left[a] == INVALID) {
+ const_cast<DynArcLookUp&>(*this).splay(a);
+ return r;
+ } else {
+ a = _left[a];
+ }
+ }
+ }
+ } else {
+ Arc a = p;
+ if (_right[a] != INVALID) {
+ a = _right[a];
+ while (_left[a] != INVALID) {
+ a = _left[a];
+ }
+ const_cast<DynArcLookUp&>(*this).splay(a);
+ } else {
+ while (_parent[a] != INVALID && _right[_parent[a]] == a) {
+ a = _parent[a];
+ }
+ if (_parent[a] == INVALID) {
+ return INVALID;
+ } else {
+ a = _parent[a];
+ const_cast<DynArcLookUp&>(*this).splay(a);
+ }
+ }
+ if (_g.target(a) == t) return a;
+ else return INVALID;
+ }
+ }
+
+ };
+
+ ///Fast arc look-up between given endpoints.
+
+ ///Using this class, you can find an arc in a digraph from a given
+ ///source to a given target in time <em>O</em>(log<em>d</em>),
+ ///where <em>d</em> is the out-degree of the source node.
+ ///
+ ///It is not possible to find \e all parallel arcs between two nodes.
+ ///Use \ref AllArcLookUp for this purpose.
+ ///
+ ///\warning This class is static, so you should call refresh() (or at
+ ///least refresh(Node)) to refresh this data structure whenever the
+ ///digraph changes. This is a time consuming (superlinearly proportional
+ ///(<em>O</em>(<em>m</em> log<em>m</em>)) to the number of arcs).
+ ///
+ ///\tparam GR The type of the underlying digraph.
+ ///
+ ///\sa DynArcLookUp
+ ///\sa AllArcLookUp
+ template<class GR>
+ class ArcLookUp
+ {
+ TEMPLATE_DIGRAPH_TYPEDEFS(GR);
+
+ public:
+
+ /// The Digraph type
+ typedef GR Digraph;
+
+ protected:
+ const Digraph &_g;
+ typename Digraph::template NodeMap<Arc> _head;
+ typename Digraph::template ArcMap<Arc> _left;
+ typename Digraph::template ArcMap<Arc> _right;
+
+ class ArcLess {
+ const Digraph &g;
+ public:
+ ArcLess(const Digraph &_g) : g(_g) {}
+ bool operator()(Arc a,Arc b) const
+ {
+ return g.target(a)<g.target(b);
+ }
+ };
+
+ public:
+
+ ///Constructor
+
+ ///Constructor.
+ ///
+ ///It builds up the search database, which remains valid until the digraph
+ ///changes.
+ ArcLookUp(const Digraph &g) :_g(g),_head(g),_left(g),_right(g) {refresh();}
+
+ private:
+ Arc refreshRec(std::vector<Arc> &v,int a,int b)
+ {
+ int m=(a+b)/2;
+ Arc me=v[m];
+ _left[me] = a<m?refreshRec(v,a,m-1):INVALID;
+ _right[me] = m<b?refreshRec(v,m+1,b):INVALID;
+ return me;
+ }
+ public:
+ ///Refresh the search data structure at a node.
+
+ ///Build up the search database of node \c n.
+ ///
+ ///It runs in time <em>O</em>(<em>d</em> log<em>d</em>), where <em>d</em>
+ ///is the number of the outgoing arcs of \c n.
+ void refresh(Node n)
+ {
+ std::vector<Arc> v;
+ for(OutArcIt e(_g,n);e!=INVALID;++e) v.push_back(e);
+ if(v.size()) {
+ std::sort(v.begin(),v.end(),ArcLess(_g));
+ _head[n]=refreshRec(v,0,v.size()-1);
+ }
+ else _head[n]=INVALID;
+ }
+ ///Refresh the full data structure.
+
+ ///Build up the full search database. In fact, it simply calls
+ ///\ref refresh(Node) "refresh(n)" for each node \c n.
+ ///
+ ///It runs in time <em>O</em>(<em>m</em> log<em>D</em>), where <em>m</em> is
+ ///the number of the arcs in the digraph and <em>D</em> is the maximum
+ ///out-degree of the digraph.
+ void refresh()
+ {
+ for(NodeIt n(_g);n!=INVALID;++n) refresh(n);
+ }
+
+ ///Find an arc between two nodes.
+
+ ///Find an arc between two nodes in time <em>O</em>(log<em>d</em>),
+ ///where <em>d</em> is the number of outgoing arcs of \c s.
+ ///\param s The source node.
+ ///\param t The target node.
+ ///\return An arc from \c s to \c t if there exists,
+ ///\ref INVALID otherwise.
+ ///
+ ///\warning If you change the digraph, refresh() must be called before using
+ ///this operator. If you change the outgoing arcs of
+ ///a single node \c n, then \ref refresh(Node) "refresh(n)" is enough.
+ Arc operator()(Node s, Node t) const
+ {
+ Arc e;
+ for(e=_head[s];
+ e!=INVALID&&_g.target(e)!=t;
+ e = t < _g.target(e)?_left[e]:_right[e]) ;
+ return e;
+ }
+
+ };
+
+ ///Fast look-up of all arcs between given endpoints.
+
+ ///This class is the same as \ref ArcLookUp, with the addition
+ ///that it makes it possible to find all parallel arcs between given
+ ///endpoints.
+ ///
+ ///\warning This class is static, so you should call refresh() (or at
+ ///least refresh(Node)) to refresh this data structure whenever the
+ ///digraph changes. This is a time consuming (superlinearly proportional
+ ///(<em>O</em>(<em>m</em> log<em>m</em>)) to the number of arcs).
+ ///
+ ///\tparam GR The type of the underlying digraph.
+ ///
+ ///\sa DynArcLookUp
+ ///\sa ArcLookUp
+ template<class GR>
+ class AllArcLookUp : public ArcLookUp<GR>
+ {
+ using ArcLookUp<GR>::_g;
+ using ArcLookUp<GR>::_right;
+ using ArcLookUp<GR>::_left;
+ using ArcLookUp<GR>::_head;
+
+ TEMPLATE_DIGRAPH_TYPEDEFS(GR);
+
+ typename GR::template ArcMap<Arc> _next;
+
+ Arc refreshNext(Arc head,Arc next=INVALID)
+ {
+ if(head==INVALID) return next;
+ else {
+ next=refreshNext(_right[head],next);
+ _next[head]=( next!=INVALID && _g.target(next)==_g.target(head))
+ ? next : INVALID;
+ return refreshNext(_left[head],head);
+ }
+ }
+
+ void refreshNext()
+ {
+ for(NodeIt n(_g);n!=INVALID;++n) refreshNext(_head[n]);
+ }
+
+ public:
+
+ /// The Digraph type
+ typedef GR Digraph;
+
+ ///Constructor
+
+ ///Constructor.
+ ///
+ ///It builds up the search database, which remains valid until the digraph
+ ///changes.
+ AllArcLookUp(const Digraph &g) : ArcLookUp<GR>(g), _next(g) {refreshNext();}
+
+ ///Refresh the data structure at a node.
+
+ ///Build up the search database of node \c n.
+ ///
+ ///It runs in time <em>O</em>(<em>d</em> log<em>d</em>), where <em>d</em> is
+ ///the number of the outgoing arcs of \c n.
+ void refresh(Node n)
+ {
+ ArcLookUp<GR>::refresh(n);
+ refreshNext(_head[n]);
+ }
+
+ ///Refresh the full data structure.
+
+ ///Build up the full search database. In fact, it simply calls
+ ///\ref refresh(Node) "refresh(n)" for each node \c n.
+ ///
+ ///It runs in time <em>O</em>(<em>m</em> log<em>D</em>), where <em>m</em> is
+ ///the number of the arcs in the digraph and <em>D</em> is the maximum
+ ///out-degree of the digraph.
+ void refresh()
+ {
+ for(NodeIt n(_g);n!=INVALID;++n) refresh(_head[n]);
+ }
+
+ ///Find an arc between two nodes.
+
+ ///Find an arc between two nodes.
+ ///\param s The source node.
+ ///\param t The target node.
+ ///\param prev The previous arc between \c s and \c t. It it is INVALID or
+ ///not given, the operator finds the first appropriate arc.
+ ///\return An arc from \c s to \c t after \c prev or
+ ///\ref INVALID if there is no more.
+ ///
+ ///For example, you can count the number of arcs from \c u to \c v in the
+ ///following way.
+ ///\code
+ ///AllArcLookUp<ListDigraph> ae(g);
+ ///...
+ ///int n = 0;
+ ///for(Arc a = ae(u,v); a != INVALID; a=ae(u,v,a)) n++;
+ ///\endcode
+ ///
+ ///Finding the first arc take <em>O</em>(log<em>d</em>) time,
+ ///where <em>d</em> is the number of outgoing arcs of \c s. Then the
+ ///consecutive arcs are found in constant time.
+ ///
+ ///\warning If you change the digraph, refresh() must be called before using
+ ///this operator. If you change the outgoing arcs of
+ ///a single node \c n, then \ref refresh(Node) "refresh(n)" is enough.
+ ///
+ Arc operator()(Node s, Node t, Arc prev=INVALID) const
+ {
+ if(prev==INVALID)
+ {
+ Arc f=INVALID;
+ Arc e;
+ for(e=_head[s];
+ e!=INVALID&&_g.target(e)!=t;
+ e = t < _g.target(e)?_left[e]:_right[e]) ;
+ while(e!=INVALID)
+ if(_g.target(e)==t)
+ {
+ f = e;
+ e = _left[e];
+ }
+ else e = _right[e];
+ return f;
+ }
+ else return _next[prev];
+ }
+
+ };
+
+ /// @}
+
+} //namespace lemon
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/cost_scaling.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/cost_scaling.h
new file mode 100644
index 00000000000..efecdfe77c7
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/cost_scaling.h
@@ -0,0 +1,1607 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_COST_SCALING_H
+#define LEMON_COST_SCALING_H
+
+/// \ingroup min_cost_flow_algs
+/// \file
+/// \brief Cost scaling algorithm for finding a minimum cost flow.
+
+#include <vector>
+#include <deque>
+#include <limits>
+
+#include <lemon/core.h>
+#include <lemon/maps.h>
+#include <lemon/math.h>
+#include <lemon/static_graph.h>
+#include <lemon/circulation.h>
+#include <lemon/bellman_ford.h>
+
+namespace lemon {
+
+ /// \brief Default traits class of CostScaling algorithm.
+ ///
+ /// Default traits class of CostScaling algorithm.
+ /// \tparam GR Digraph type.
+ /// \tparam V The number type used for flow amounts, capacity bounds
+ /// and supply values. By default it is \c int.
+ /// \tparam C The number type used for costs and potentials.
+ /// By default it is the same as \c V.
+#ifdef DOXYGEN
+ template <typename GR, typename V = int, typename C = V>
+#else
+ template < typename GR, typename V = int, typename C = V,
+ bool integer = std::numeric_limits<C>::is_integer >
+#endif
+ struct CostScalingDefaultTraits
+ {
+ /// The type of the digraph
+ typedef GR Digraph;
+ /// The type of the flow amounts, capacity bounds and supply values
+ typedef V Value;
+ /// The type of the arc costs
+ typedef C Cost;
+
+ /// \brief The large cost type used for internal computations
+ ///
+ /// The large cost type used for internal computations.
+ /// It is \c long \c long if the \c Cost type is integer,
+ /// otherwise it is \c double.
+ /// \c Cost must be convertible to \c LargeCost.
+ typedef double LargeCost;
+ };
+
+ // Default traits class for integer cost types
+ template <typename GR, typename V, typename C>
+ struct CostScalingDefaultTraits<GR, V, C, true>
+ {
+ typedef GR Digraph;
+ typedef V Value;
+ typedef C Cost;
+#ifdef LEMON_HAVE_LONG_LONG
+ typedef long long LargeCost;
+#else
+ typedef long LargeCost;
+#endif
+ };
+
+
+ /// \addtogroup min_cost_flow_algs
+ /// @{
+
+ /// \brief Implementation of the Cost Scaling algorithm for
+ /// finding a \ref min_cost_flow "minimum cost flow".
+ ///
+ /// \ref CostScaling implements a cost scaling algorithm that performs
+ /// push/augment and relabel operations for finding a \ref min_cost_flow
+ /// "minimum cost flow" \cite amo93networkflows,
+ /// \cite goldberg90approximation,
+ /// \cite goldberg97efficient, \cite bunnagel98efficient.
+ /// It is a highly efficient primal-dual solution method, which
+ /// can be viewed as the generalization of the \ref Preflow
+ /// "preflow push-relabel" algorithm for the maximum flow problem.
+ /// It is a polynomial algorithm, its running time complexity is
+ /// \f$O(n^2m\log(nK))\f$, where <i>K</i> denotes the maximum arc cost.
+ ///
+ /// In general, \ref NetworkSimplex and \ref CostScaling are the fastest
+ /// implementations available in LEMON for solving this problem.
+ /// (For more information, see \ref min_cost_flow_algs "the module page".)
+ ///
+ /// Most of the parameters of the problem (except for the digraph)
+ /// can be given using separate functions, and the algorithm can be
+ /// executed using the \ref run() function. If some parameters are not
+ /// specified, then default values will be used.
+ ///
+ /// \tparam GR The digraph type the algorithm runs on.
+ /// \tparam V The number type used for flow amounts, capacity bounds
+ /// and supply values in the algorithm. By default, it is \c int.
+ /// \tparam C The number type used for costs and potentials in the
+ /// algorithm. By default, it is the same as \c V.
+ /// \tparam TR The traits class that defines various types used by the
+ /// algorithm. By default, it is \ref CostScalingDefaultTraits
+ /// "CostScalingDefaultTraits<GR, V, C>".
+ /// In most cases, this parameter should not be set directly,
+ /// consider to use the named template parameters instead.
+ ///
+ /// \warning Both \c V and \c C must be signed number types.
+ /// \warning All input data (capacities, supply values, and costs) must
+ /// be integer.
+ /// \warning This algorithm does not support negative costs for
+ /// arcs having infinite upper bound.
+ ///
+ /// \note %CostScaling provides three different internal methods,
+ /// from which the most efficient one is used by default.
+ /// For more information, see \ref Method.
+#ifdef DOXYGEN
+ template <typename GR, typename V, typename C, typename TR>
+#else
+ template < typename GR, typename V = int, typename C = V,
+ typename TR = CostScalingDefaultTraits<GR, V, C> >
+#endif
+ class CostScaling
+ {
+ public:
+
+ /// The type of the digraph
+ typedef typename TR::Digraph Digraph;
+ /// The type of the flow amounts, capacity bounds and supply values
+ typedef typename TR::Value Value;
+ /// The type of the arc costs
+ typedef typename TR::Cost Cost;
+
+ /// \brief The large cost type
+ ///
+ /// The large cost type used for internal computations.
+ /// By default, it is \c long \c long if the \c Cost type is integer,
+ /// otherwise it is \c double.
+ typedef typename TR::LargeCost LargeCost;
+
+ /// \brief The \ref lemon::CostScalingDefaultTraits "traits class"
+ /// of the algorithm
+ typedef TR Traits;
+
+ public:
+
+ /// \brief Problem type constants for the \c run() function.
+ ///
+ /// Enum type containing the problem type constants that can be
+ /// returned by the \ref run() function of the algorithm.
+ enum ProblemType {
+ /// The problem has no feasible solution (flow).
+ INFEASIBLE,
+ /// The problem has optimal solution (i.e. it is feasible and
+ /// bounded), and the algorithm has found optimal flow and node
+ /// potentials (primal and dual solutions).
+ OPTIMAL,
+ /// The digraph contains an arc of negative cost and infinite
+ /// upper bound. It means that the objective function is unbounded
+ /// on that arc, however, note that it could actually be bounded
+ /// over the feasible flows, but this algroithm cannot handle
+ /// these cases.
+ UNBOUNDED
+ };
+
+ /// \brief Constants for selecting the internal method.
+ ///
+ /// Enum type containing constants for selecting the internal method
+ /// for the \ref run() function.
+ ///
+ /// \ref CostScaling provides three internal methods that differ mainly
+ /// in their base operations, which are used in conjunction with the
+ /// relabel operation.
+ /// By default, the so called \ref PARTIAL_AUGMENT
+ /// "Partial Augment-Relabel" method is used, which turned out to be
+ /// the most efficient and the most robust on various test inputs.
+ /// However, the other methods can be selected using the \ref run()
+ /// function with the proper parameter.
+ enum Method {
+ /// Local push operations are used, i.e. flow is moved only on one
+ /// admissible arc at once.
+ PUSH,
+ /// Augment operations are used, i.e. flow is moved on admissible
+ /// paths from a node with excess to a node with deficit.
+ AUGMENT,
+ /// Partial augment operations are used, i.e. flow is moved on
+ /// admissible paths started from a node with excess, but the
+ /// lengths of these paths are limited. This method can be viewed
+ /// as a combined version of the previous two operations.
+ PARTIAL_AUGMENT
+ };
+
+ private:
+
+ TEMPLATE_DIGRAPH_TYPEDEFS(GR);
+
+ typedef std::vector<int> IntVector;
+ typedef std::vector<Value> ValueVector;
+ typedef std::vector<Cost> CostVector;
+ typedef std::vector<LargeCost> LargeCostVector;
+ typedef std::vector<char> BoolVector;
+ // Note: vector<char> is used instead of vector<bool>
+ // for efficiency reasons
+
+ private:
+
+ template <typename KT, typename VT>
+ class StaticVectorMap {
+ public:
+ typedef KT Key;
+ typedef VT Value;
+
+ StaticVectorMap(std::vector<Value>& v) : _v(v) {}
+
+ const Value& operator[](const Key& key) const {
+ return _v[StaticDigraph::id(key)];
+ }
+
+ Value& operator[](const Key& key) {
+ return _v[StaticDigraph::id(key)];
+ }
+
+ void set(const Key& key, const Value& val) {
+ _v[StaticDigraph::id(key)] = val;
+ }
+
+ private:
+ std::vector<Value>& _v;
+ };
+
+ typedef StaticVectorMap<StaticDigraph::Arc, LargeCost> LargeCostArcMap;
+
+ private:
+
+ // Data related to the underlying digraph
+ const GR &_graph;
+ int _node_num;
+ int _arc_num;
+ int _res_node_num;
+ int _res_arc_num;
+ int _root;
+
+ // Parameters of the problem
+ bool _has_lower;
+ Value _sum_supply;
+ int _sup_node_num;
+
+ // Data structures for storing the digraph
+ IntNodeMap _node_id;
+ IntArcMap _arc_idf;
+ IntArcMap _arc_idb;
+ IntVector _first_out;
+ BoolVector _forward;
+ IntVector _source;
+ IntVector _target;
+ IntVector _reverse;
+
+ // Node and arc data
+ ValueVector _lower;
+ ValueVector _upper;
+ CostVector _scost;
+ ValueVector _supply;
+
+ ValueVector _res_cap;
+ LargeCostVector _cost;
+ LargeCostVector _pi;
+ ValueVector _excess;
+ IntVector _next_out;
+ std::deque<int> _active_nodes;
+
+ // Data for scaling
+ LargeCost _epsilon;
+ int _alpha;
+
+ IntVector _buckets;
+ IntVector _bucket_next;
+ IntVector _bucket_prev;
+ IntVector _rank;
+ int _max_rank;
+
+ public:
+
+ /// \brief Constant for infinite upper bounds (capacities).
+ ///
+ /// Constant for infinite upper bounds (capacities).
+ /// It is \c std::numeric_limits<Value>::infinity() if available,
+ /// \c std::numeric_limits<Value>::max() otherwise.
+ const Value INF;
+
+ public:
+
+ /// \name Named Template Parameters
+ /// @{
+
+ template <typename T>
+ struct SetLargeCostTraits : public Traits {
+ typedef T LargeCost;
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// \c LargeCost type.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting \c LargeCost
+ /// type, which is used for internal computations in the algorithm.
+ /// \c Cost must be convertible to \c LargeCost.
+ template <typename T>
+ struct SetLargeCost
+ : public CostScaling<GR, V, C, SetLargeCostTraits<T> > {
+ typedef CostScaling<GR, V, C, SetLargeCostTraits<T> > Create;
+ };
+
+ /// @}
+
+ protected:
+
+ CostScaling() {}
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// The constructor of the class.
+ ///
+ /// \param graph The digraph the algorithm runs on.
+ CostScaling(const GR& graph) :
+ _graph(graph), _node_id(graph), _arc_idf(graph), _arc_idb(graph),
+ INF(std::numeric_limits<Value>::has_infinity ?
+ std::numeric_limits<Value>::infinity() :
+ std::numeric_limits<Value>::max())
+ {
+ // Check the number types
+ LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
+ "The flow type of CostScaling must be signed");
+ LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
+ "The cost type of CostScaling must be signed");
+
+ // Reset data structures
+ reset();
+ }
+
+ /// \name Parameters
+ /// The parameters of the algorithm can be specified using these
+ /// functions.
+
+ /// @{
+
+ /// \brief Set the lower bounds on the arcs.
+ ///
+ /// This function sets the lower bounds on the arcs.
+ /// If it is not used before calling \ref run(), the lower bounds
+ /// will be set to zero on all arcs.
+ ///
+ /// \param map An arc map storing the lower bounds.
+ /// Its \c Value type must be convertible to the \c Value type
+ /// of the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ template <typename LowerMap>
+ CostScaling& lowerMap(const LowerMap& map) {
+ _has_lower = true;
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ _lower[_arc_idf[a]] = map[a];
+ }
+ return *this;
+ }
+
+ /// \brief Set the upper bounds (capacities) on the arcs.
+ ///
+ /// This function sets the upper bounds (capacities) on the arcs.
+ /// If it is not used before calling \ref run(), the upper bounds
+ /// will be set to \ref INF on all arcs (i.e. the flow value will be
+ /// unbounded from above).
+ ///
+ /// \param map An arc map storing the upper bounds.
+ /// Its \c Value type must be convertible to the \c Value type
+ /// of the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ template<typename UpperMap>
+ CostScaling& upperMap(const UpperMap& map) {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ _upper[_arc_idf[a]] = map[a];
+ }
+ return *this;
+ }
+
+ /// \brief Set the costs of the arcs.
+ ///
+ /// This function sets the costs of the arcs.
+ /// If it is not used before calling \ref run(), the costs
+ /// will be set to \c 1 on all arcs.
+ ///
+ /// \param map An arc map storing the costs.
+ /// Its \c Value type must be convertible to the \c Cost type
+ /// of the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ template<typename CostMap>
+ CostScaling& costMap(const CostMap& map) {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ _scost[_arc_idf[a]] = map[a];
+ _scost[_arc_idb[a]] = -map[a];
+ }
+ return *this;
+ }
+
+ /// \brief Set the supply values of the nodes.
+ ///
+ /// This function sets the supply values of the nodes.
+ /// If neither this function nor \ref stSupply() is used before
+ /// calling \ref run(), the supply of each node will be set to zero.
+ ///
+ /// \param map A node map storing the supply values.
+ /// Its \c Value type must be convertible to the \c Value type
+ /// of the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ template<typename SupplyMap>
+ CostScaling& supplyMap(const SupplyMap& map) {
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ _supply[_node_id[n]] = map[n];
+ }
+ return *this;
+ }
+
+ /// \brief Set single source and target nodes and a supply value.
+ ///
+ /// This function sets a single source node and a single target node
+ /// and the required flow value.
+ /// If neither this function nor \ref supplyMap() is used before
+ /// calling \ref run(), the supply of each node will be set to zero.
+ ///
+ /// Using this function has the same effect as using \ref supplyMap()
+ /// with a map in which \c k is assigned to \c s, \c -k is
+ /// assigned to \c t and all other nodes have zero supply value.
+ ///
+ /// \param s The source node.
+ /// \param t The target node.
+ /// \param k The required amount of flow from node \c s to node \c t
+ /// (i.e. the supply of \c s and the demand of \c t).
+ ///
+ /// \return <tt>(*this)</tt>
+ CostScaling& stSupply(const Node& s, const Node& t, Value k) {
+ for (int i = 0; i != _res_node_num; ++i) {
+ _supply[i] = 0;
+ }
+ _supply[_node_id[s]] = k;
+ _supply[_node_id[t]] = -k;
+ return *this;
+ }
+
+ /// @}
+
+ /// \name Execution control
+ /// The algorithm can be executed using \ref run().
+
+ /// @{
+
+ /// \brief Run the algorithm.
+ ///
+ /// This function runs the algorithm.
+ /// The paramters can be specified using functions \ref lowerMap(),
+ /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply().
+ /// For example,
+ /// \code
+ /// CostScaling<ListDigraph> cs(graph);
+ /// cs.lowerMap(lower).upperMap(upper).costMap(cost)
+ /// .supplyMap(sup).run();
+ /// \endcode
+ ///
+ /// This function can be called more than once. All the given parameters
+ /// are kept for the next call, unless \ref resetParams() or \ref reset()
+ /// is used, thus only the modified parameters have to be set again.
+ /// If the underlying digraph was also modified after the construction
+ /// of the class (or the last \ref reset() call), then the \ref reset()
+ /// function must be called.
+ ///
+ /// \param method The internal method that will be used in the
+ /// algorithm. For more information, see \ref Method.
+ /// \param factor The cost scaling factor. It must be at least two.
+ ///
+ /// \return \c INFEASIBLE if no feasible flow exists,
+ /// \n \c OPTIMAL if the problem has optimal solution
+ /// (i.e. it is feasible and bounded), and the algorithm has found
+ /// optimal flow and node potentials (primal and dual solutions),
+ /// \n \c UNBOUNDED if the digraph contains an arc of negative cost
+ /// and infinite upper bound. It means that the objective function
+ /// is unbounded on that arc, however, note that it could actually be
+ /// bounded over the feasible flows, but this algroithm cannot handle
+ /// these cases.
+ ///
+ /// \see ProblemType, Method
+ /// \see resetParams(), reset()
+ ProblemType run(Method method = PARTIAL_AUGMENT, int factor = 16) {
+ LEMON_ASSERT(factor >= 2, "The scaling factor must be at least 2");
+ _alpha = factor;
+ ProblemType pt = init();
+ if (pt != OPTIMAL) return pt;
+ start(method);
+ return OPTIMAL;
+ }
+
+ /// \brief Reset all the parameters that have been given before.
+ ///
+ /// This function resets all the paramaters that have been given
+ /// before using functions \ref lowerMap(), \ref upperMap(),
+ /// \ref costMap(), \ref supplyMap(), \ref stSupply().
+ ///
+ /// It is useful for multiple \ref run() calls. Basically, all the given
+ /// parameters are kept for the next \ref run() call, unless
+ /// \ref resetParams() or \ref reset() is used.
+ /// If the underlying digraph was also modified after the construction
+ /// of the class or the last \ref reset() call, then the \ref reset()
+ /// function must be used, otherwise \ref resetParams() is sufficient.
+ ///
+ /// For example,
+ /// \code
+ /// CostScaling<ListDigraph> cs(graph);
+ ///
+ /// // First run
+ /// cs.lowerMap(lower).upperMap(upper).costMap(cost)
+ /// .supplyMap(sup).run();
+ ///
+ /// // Run again with modified cost map (resetParams() is not called,
+ /// // so only the cost map have to be set again)
+ /// cost[e] += 100;
+ /// cs.costMap(cost).run();
+ ///
+ /// // Run again from scratch using resetParams()
+ /// // (the lower bounds will be set to zero on all arcs)
+ /// cs.resetParams();
+ /// cs.upperMap(capacity).costMap(cost)
+ /// .supplyMap(sup).run();
+ /// \endcode
+ ///
+ /// \return <tt>(*this)</tt>
+ ///
+ /// \see reset(), run()
+ CostScaling& resetParams() {
+ for (int i = 0; i != _res_node_num; ++i) {
+ _supply[i] = 0;
+ }
+ int limit = _first_out[_root];
+ for (int j = 0; j != limit; ++j) {
+ _lower[j] = 0;
+ _upper[j] = INF;
+ _scost[j] = _forward[j] ? 1 : -1;
+ }
+ for (int j = limit; j != _res_arc_num; ++j) {
+ _lower[j] = 0;
+ _upper[j] = INF;
+ _scost[j] = 0;
+ _scost[_reverse[j]] = 0;
+ }
+ _has_lower = false;
+ return *this;
+ }
+
+ /// \brief Reset the internal data structures and all the parameters
+ /// that have been given before.
+ ///
+ /// This function resets the internal data structures and all the
+ /// paramaters that have been given before using functions \ref lowerMap(),
+ /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply().
+ ///
+ /// It is useful for multiple \ref run() calls. By default, all the given
+ /// parameters are kept for the next \ref run() call, unless
+ /// \ref resetParams() or \ref reset() is used.
+ /// If the underlying digraph was also modified after the construction
+ /// of the class or the last \ref reset() call, then the \ref reset()
+ /// function must be used, otherwise \ref resetParams() is sufficient.
+ ///
+ /// See \ref resetParams() for examples.
+ ///
+ /// \return <tt>(*this)</tt>
+ ///
+ /// \see resetParams(), run()
+ CostScaling& reset() {
+ // Resize vectors
+ _node_num = countNodes(_graph);
+ _arc_num = countArcs(_graph);
+ _res_node_num = _node_num + 1;
+ _res_arc_num = 2 * (_arc_num + _node_num);
+ _root = _node_num;
+
+ _first_out.resize(_res_node_num + 1);
+ _forward.resize(_res_arc_num);
+ _source.resize(_res_arc_num);
+ _target.resize(_res_arc_num);
+ _reverse.resize(_res_arc_num);
+
+ _lower.resize(_res_arc_num);
+ _upper.resize(_res_arc_num);
+ _scost.resize(_res_arc_num);
+ _supply.resize(_res_node_num);
+
+ _res_cap.resize(_res_arc_num);
+ _cost.resize(_res_arc_num);
+ _pi.resize(_res_node_num);
+ _excess.resize(_res_node_num);
+ _next_out.resize(_res_node_num);
+
+ // Copy the graph
+ int i = 0, j = 0, k = 2 * _arc_num + _node_num;
+ for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
+ _node_id[n] = i;
+ }
+ i = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
+ _first_out[i] = j;
+ for (OutArcIt a(_graph, n); a != INVALID; ++a, ++j) {
+ _arc_idf[a] = j;
+ _forward[j] = true;
+ _source[j] = i;
+ _target[j] = _node_id[_graph.runningNode(a)];
+ }
+ for (InArcIt a(_graph, n); a != INVALID; ++a, ++j) {
+ _arc_idb[a] = j;
+ _forward[j] = false;
+ _source[j] = i;
+ _target[j] = _node_id[_graph.runningNode(a)];
+ }
+ _forward[j] = false;
+ _source[j] = i;
+ _target[j] = _root;
+ _reverse[j] = k;
+ _forward[k] = true;
+ _source[k] = _root;
+ _target[k] = i;
+ _reverse[k] = j;
+ ++j; ++k;
+ }
+ _first_out[i] = j;
+ _first_out[_res_node_num] = k;
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ int fi = _arc_idf[a];
+ int bi = _arc_idb[a];
+ _reverse[fi] = bi;
+ _reverse[bi] = fi;
+ }
+
+ // Reset parameters
+ resetParams();
+ return *this;
+ }
+
+ /// @}
+
+ /// \name Query Functions
+ /// The results of the algorithm can be obtained using these
+ /// functions.\n
+ /// The \ref run() function must be called before using them.
+
+ /// @{
+
+ /// \brief Return the total cost of the found flow.
+ ///
+ /// This function returns the total cost of the found flow.
+ /// Its complexity is O(m).
+ ///
+ /// \note The return type of the function can be specified as a
+ /// template parameter. For example,
+ /// \code
+ /// cs.totalCost<double>();
+ /// \endcode
+ /// It is useful if the total cost cannot be stored in the \c Cost
+ /// type of the algorithm, which is the default return type of the
+ /// function.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ template <typename Number>
+ Number totalCost() const {
+ Number c = 0;
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ int i = _arc_idb[a];
+ c += static_cast<Number>(_res_cap[i]) *
+ (-static_cast<Number>(_scost[i]));
+ }
+ return c;
+ }
+
+#ifndef DOXYGEN
+ Cost totalCost() const {
+ return totalCost<Cost>();
+ }
+#endif
+
+ /// \brief Return the flow on the given arc.
+ ///
+ /// This function returns the flow on the given arc.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ Value flow(const Arc& a) const {
+ return _res_cap[_arc_idb[a]];
+ }
+
+ /// \brief Copy the flow values (the primal solution) into the
+ /// given map.
+ ///
+ /// This function copies the flow value on each arc into the given
+ /// map. The \c Value type of the algorithm must be convertible to
+ /// the \c Value type of the map.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ template <typename FlowMap>
+ void flowMap(FlowMap &map) const {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ map.set(a, _res_cap[_arc_idb[a]]);
+ }
+ }
+
+ /// \brief Return the potential (dual value) of the given node.
+ ///
+ /// This function returns the potential (dual value) of the
+ /// given node.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ Cost potential(const Node& n) const {
+ return static_cast<Cost>(_pi[_node_id[n]]);
+ }
+
+ /// \brief Copy the potential values (the dual solution) into the
+ /// given map.
+ ///
+ /// This function copies the potential (dual value) of each node
+ /// into the given map.
+ /// The \c Cost type of the algorithm must be convertible to the
+ /// \c Value type of the map.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ template <typename PotentialMap>
+ void potentialMap(PotentialMap &map) const {
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ map.set(n, static_cast<Cost>(_pi[_node_id[n]]));
+ }
+ }
+
+ /// @}
+
+ private:
+
+ // Initialize the algorithm
+ ProblemType init() {
+ if (_res_node_num <= 1) return INFEASIBLE;
+
+ // Check the sum of supply values
+ _sum_supply = 0;
+ for (int i = 0; i != _root; ++i) {
+ _sum_supply += _supply[i];
+ }
+ if (_sum_supply > 0) return INFEASIBLE;
+
+ // Check lower and upper bounds
+ LEMON_DEBUG(checkBoundMaps(),
+ "Upper bounds must be greater or equal to the lower bounds");
+
+
+ // Initialize vectors
+ for (int i = 0; i != _res_node_num; ++i) {
+ _pi[i] = 0;
+ _excess[i] = _supply[i];
+ }
+
+ // Remove infinite upper bounds and check negative arcs
+ const Value MAX = std::numeric_limits<Value>::max();
+ int last_out;
+ if (_has_lower) {
+ for (int i = 0; i != _root; ++i) {
+ last_out = _first_out[i+1];
+ for (int j = _first_out[i]; j != last_out; ++j) {
+ if (_forward[j]) {
+ Value c = _scost[j] < 0 ? _upper[j] : _lower[j];
+ if (c >= MAX) return UNBOUNDED;
+ _excess[i] -= c;
+ _excess[_target[j]] += c;
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i != _root; ++i) {
+ last_out = _first_out[i+1];
+ for (int j = _first_out[i]; j != last_out; ++j) {
+ if (_forward[j] && _scost[j] < 0) {
+ Value c = _upper[j];
+ if (c >= MAX) return UNBOUNDED;
+ _excess[i] -= c;
+ _excess[_target[j]] += c;
+ }
+ }
+ }
+ }
+ Value ex, max_cap = 0;
+ for (int i = 0; i != _res_node_num; ++i) {
+ ex = _excess[i];
+ _excess[i] = 0;
+ if (ex < 0) max_cap -= ex;
+ }
+ for (int j = 0; j != _res_arc_num; ++j) {
+ if (_upper[j] >= MAX) _upper[j] = max_cap;
+ }
+
+ // Initialize the large cost vector and the epsilon parameter
+ _epsilon = 0;
+ LargeCost lc;
+ for (int i = 0; i != _root; ++i) {
+ last_out = _first_out[i+1];
+ for (int j = _first_out[i]; j != last_out; ++j) {
+ lc = static_cast<LargeCost>(_scost[j]) * _res_node_num * _alpha;
+ _cost[j] = lc;
+ if (lc > _epsilon) _epsilon = lc;
+ }
+ }
+ _epsilon /= _alpha;
+
+ // Initialize maps for Circulation and remove non-zero lower bounds
+ ConstMap<Arc, Value> low(0);
+ typedef typename Digraph::template ArcMap<Value> ValueArcMap;
+ typedef typename Digraph::template NodeMap<Value> ValueNodeMap;
+ ValueArcMap cap(_graph), flow(_graph);
+ ValueNodeMap sup(_graph);
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ sup[n] = _supply[_node_id[n]];
+ }
+ if (_has_lower) {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ int j = _arc_idf[a];
+ Value c = _lower[j];
+ cap[a] = _upper[j] - c;
+ sup[_graph.source(a)] -= c;
+ sup[_graph.target(a)] += c;
+ }
+ } else {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ cap[a] = _upper[_arc_idf[a]];
+ }
+ }
+
+ _sup_node_num = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if (sup[n] > 0) ++_sup_node_num;
+ }
+
+ // Find a feasible flow using Circulation
+ Circulation<Digraph, ConstMap<Arc, Value>, ValueArcMap, ValueNodeMap>
+ circ(_graph, low, cap, sup);
+ if (!circ.flowMap(flow).run()) return INFEASIBLE;
+
+ // Set residual capacities and handle GEQ supply type
+ if (_sum_supply < 0) {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ Value fa = flow[a];
+ _res_cap[_arc_idf[a]] = cap[a] - fa;
+ _res_cap[_arc_idb[a]] = fa;
+ sup[_graph.source(a)] -= fa;
+ sup[_graph.target(a)] += fa;
+ }
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ _excess[_node_id[n]] = sup[n];
+ }
+ for (int a = _first_out[_root]; a != _res_arc_num; ++a) {
+ int u = _target[a];
+ int ra = _reverse[a];
+ _res_cap[a] = -_sum_supply + 1;
+ _res_cap[ra] = -_excess[u];
+ _cost[a] = 0;
+ _cost[ra] = 0;
+ _excess[u] = 0;
+ }
+ } else {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ Value fa = flow[a];
+ _res_cap[_arc_idf[a]] = cap[a] - fa;
+ _res_cap[_arc_idb[a]] = fa;
+ }
+ for (int a = _first_out[_root]; a != _res_arc_num; ++a) {
+ int ra = _reverse[a];
+ _res_cap[a] = 0;
+ _res_cap[ra] = 0;
+ _cost[a] = 0;
+ _cost[ra] = 0;
+ }
+ }
+
+ // Initialize data structures for buckets
+ _max_rank = _alpha * _res_node_num;
+ _buckets.resize(_max_rank);
+ _bucket_next.resize(_res_node_num + 1);
+ _bucket_prev.resize(_res_node_num + 1);
+ _rank.resize(_res_node_num + 1);
+
+ return OPTIMAL;
+ }
+
+ // Check if the upper bound is greater than or equal to the lower bound
+ // on each forward arc.
+ bool checkBoundMaps() {
+ for (int j = 0; j != _res_arc_num; ++j) {
+ if (_forward[j] && _upper[j] < _lower[j]) return false;
+ }
+ return true;
+ }
+
+ // Execute the algorithm and transform the results
+ void start(Method method) {
+ const int MAX_PARTIAL_PATH_LENGTH = 4;
+
+ switch (method) {
+ case PUSH:
+ startPush();
+ break;
+ case AUGMENT:
+ startAugment(_res_node_num - 1);
+ break;
+ case PARTIAL_AUGMENT:
+ startAugment(MAX_PARTIAL_PATH_LENGTH);
+ break;
+ }
+
+ // Compute node potentials (dual solution)
+ for (int i = 0; i != _res_node_num; ++i) {
+ _pi[i] = static_cast<Cost>(_pi[i] / (_res_node_num * _alpha));
+ }
+ bool optimal = true;
+ for (int i = 0; optimal && i != _res_node_num; ++i) {
+ LargeCost pi_i = _pi[i];
+ int last_out = _first_out[i+1];
+ for (int j = _first_out[i]; j != last_out; ++j) {
+ if (_res_cap[j] > 0 && _scost[j] + pi_i - _pi[_target[j]] < 0) {
+ optimal = false;
+ break;
+ }
+ }
+ }
+
+ if (!optimal) {
+ // Compute node potentials for the original costs with BellmanFord
+ // (if it is necessary)
+ typedef std::pair<int, int> IntPair;
+ StaticDigraph sgr;
+ std::vector<IntPair> arc_vec;
+ std::vector<LargeCost> cost_vec;
+ LargeCostArcMap cost_map(cost_vec);
+
+ arc_vec.clear();
+ cost_vec.clear();
+ for (int j = 0; j != _res_arc_num; ++j) {
+ if (_res_cap[j] > 0) {
+ int u = _source[j], v = _target[j];
+ arc_vec.push_back(IntPair(u, v));
+ cost_vec.push_back(_scost[j] + _pi[u] - _pi[v]);
+ }
+ }
+ sgr.build(_res_node_num, arc_vec.begin(), arc_vec.end());
+
+ typename BellmanFord<StaticDigraph, LargeCostArcMap>::Create
+ bf(sgr, cost_map);
+ bf.init(0);
+ bf.start();
+
+ for (int i = 0; i != _res_node_num; ++i) {
+ _pi[i] += bf.dist(sgr.node(i));
+ }
+ }
+
+ // Shift potentials to meet the requirements of the GEQ type
+ // optimality conditions
+ LargeCost max_pot = _pi[_root];
+ for (int i = 0; i != _res_node_num; ++i) {
+ if (_pi[i] > max_pot) max_pot = _pi[i];
+ }
+ if (max_pot != 0) {
+ for (int i = 0; i != _res_node_num; ++i) {
+ _pi[i] -= max_pot;
+ }
+ }
+
+ // Handle non-zero lower bounds
+ if (_has_lower) {
+ int limit = _first_out[_root];
+ for (int j = 0; j != limit; ++j) {
+ if (_forward[j]) _res_cap[_reverse[j]] += _lower[j];
+ }
+ }
+ }
+
+ // Initialize a cost scaling phase
+ void initPhase() {
+ // Saturate arcs not satisfying the optimality condition
+ for (int u = 0; u != _res_node_num; ++u) {
+ int last_out = _first_out[u+1];
+ LargeCost pi_u = _pi[u];
+ for (int a = _first_out[u]; a != last_out; ++a) {
+ Value delta = _res_cap[a];
+ if (delta > 0) {
+ int v = _target[a];
+ if (_cost[a] + pi_u - _pi[v] < 0) {
+ _excess[u] -= delta;
+ _excess[v] += delta;
+ _res_cap[a] = 0;
+ _res_cap[_reverse[a]] += delta;
+ }
+ }
+ }
+ }
+
+ // Find active nodes (i.e. nodes with positive excess)
+ for (int u = 0; u != _res_node_num; ++u) {
+ if (_excess[u] > 0) _active_nodes.push_back(u);
+ }
+
+ // Initialize the next arcs
+ for (int u = 0; u != _res_node_num; ++u) {
+ _next_out[u] = _first_out[u];
+ }
+ }
+
+ // Price (potential) refinement heuristic
+ bool priceRefinement() {
+
+ // Stack for stroing the topological order
+ IntVector stack(_res_node_num);
+ int stack_top;
+
+ // Perform phases
+ while (topologicalSort(stack, stack_top)) {
+
+ // Compute node ranks in the acyclic admissible network and
+ // store the nodes in buckets
+ for (int i = 0; i != _res_node_num; ++i) {
+ _rank[i] = 0;
+ }
+ const int bucket_end = _root + 1;
+ for (int r = 0; r != _max_rank; ++r) {
+ _buckets[r] = bucket_end;
+ }
+ int top_rank = 0;
+ for ( ; stack_top >= 0; --stack_top) {
+ int u = stack[stack_top], v;
+ int rank_u = _rank[u];
+
+ LargeCost rc, pi_u = _pi[u];
+ int last_out = _first_out[u+1];
+ for (int a = _first_out[u]; a != last_out; ++a) {
+ if (_res_cap[a] > 0) {
+ v = _target[a];
+ rc = _cost[a] + pi_u - _pi[v];
+ if (rc < 0) {
+ LargeCost nrc = static_cast<LargeCost>((-rc - 0.5) / _epsilon);
+ if (nrc < LargeCost(_max_rank)) {
+ int new_rank_v = rank_u + static_cast<int>(nrc);
+ if (new_rank_v > _rank[v]) {
+ _rank[v] = new_rank_v;
+ }
+ }
+ }
+ }
+ }
+
+ if (rank_u > 0) {
+ top_rank = std::max(top_rank, rank_u);
+ int bfirst = _buckets[rank_u];
+ _bucket_next[u] = bfirst;
+ _bucket_prev[bfirst] = u;
+ _buckets[rank_u] = u;
+ }
+ }
+
+ // Check if the current flow is epsilon-optimal
+ if (top_rank == 0) {
+ return true;
+ }
+
+ // Process buckets in top-down order
+ for (int rank = top_rank; rank > 0; --rank) {
+ while (_buckets[rank] != bucket_end) {
+ // Remove the first node from the current bucket
+ int u = _buckets[rank];
+ _buckets[rank] = _bucket_next[u];
+
+ // Search the outgoing arcs of u
+ LargeCost rc, pi_u = _pi[u];
+ int last_out = _first_out[u+1];
+ int v, old_rank_v, new_rank_v;
+ for (int a = _first_out[u]; a != last_out; ++a) {
+ if (_res_cap[a] > 0) {
+ v = _target[a];
+ old_rank_v = _rank[v];
+
+ if (old_rank_v < rank) {
+
+ // Compute the new rank of node v
+ rc = _cost[a] + pi_u - _pi[v];
+ if (rc < 0) {
+ new_rank_v = rank;
+ } else {
+ LargeCost nrc = rc / _epsilon;
+ new_rank_v = 0;
+ if (nrc < LargeCost(_max_rank)) {
+ new_rank_v = rank - 1 - static_cast<int>(nrc);
+ }
+ }
+
+ // Change the rank of node v
+ if (new_rank_v > old_rank_v) {
+ _rank[v] = new_rank_v;
+
+ // Remove v from its old bucket
+ if (old_rank_v > 0) {
+ if (_buckets[old_rank_v] == v) {
+ _buckets[old_rank_v] = _bucket_next[v];
+ } else {
+ int pv = _bucket_prev[v], nv = _bucket_next[v];
+ _bucket_next[pv] = nv;
+ _bucket_prev[nv] = pv;
+ }
+ }
+
+ // Insert v into its new bucket
+ int nv = _buckets[new_rank_v];
+ _bucket_next[v] = nv;
+ _bucket_prev[nv] = v;
+ _buckets[new_rank_v] = v;
+ }
+ }
+ }
+ }
+
+ // Refine potential of node u
+ _pi[u] -= rank * _epsilon;
+ }
+ }
+
+ }
+
+ return false;
+ }
+
+ // Find and cancel cycles in the admissible network and
+ // determine topological order using DFS
+ bool topologicalSort(IntVector &stack, int &stack_top) {
+ const int MAX_CYCLE_CANCEL = 1;
+
+ BoolVector reached(_res_node_num, false);
+ BoolVector processed(_res_node_num, false);
+ IntVector pred(_res_node_num);
+ for (int i = 0; i != _res_node_num; ++i) {
+ _next_out[i] = _first_out[i];
+ }
+ stack_top = -1;
+
+ int cycle_cnt = 0;
+ for (int start = 0; start != _res_node_num; ++start) {
+ if (reached[start]) continue;
+
+ // Start DFS search from this start node
+ pred[start] = -1;
+ int tip = start, v;
+ while (true) {
+ // Check the outgoing arcs of the current tip node
+ reached[tip] = true;
+ LargeCost pi_tip = _pi[tip];
+ int a, last_out = _first_out[tip+1];
+ for (a = _next_out[tip]; a != last_out; ++a) {
+ if (_res_cap[a] > 0) {
+ v = _target[a];
+ if (_cost[a] + pi_tip - _pi[v] < 0) {
+ if (!reached[v]) {
+ // A new node is reached
+ reached[v] = true;
+ pred[v] = tip;
+ _next_out[tip] = a;
+ tip = v;
+ a = _next_out[tip];
+ last_out = _first_out[tip+1];
+ break;
+ }
+ else if (!processed[v]) {
+ // A cycle is found
+ ++cycle_cnt;
+ _next_out[tip] = a;
+
+ // Find the minimum residual capacity along the cycle
+ Value d, delta = _res_cap[a];
+ int u, delta_node = tip;
+ for (u = tip; u != v; ) {
+ u = pred[u];
+ d = _res_cap[_next_out[u]];
+ if (d <= delta) {
+ delta = d;
+ delta_node = u;
+ }
+ }
+
+ // Augment along the cycle
+ _res_cap[a] -= delta;
+ _res_cap[_reverse[a]] += delta;
+ for (u = tip; u != v; ) {
+ u = pred[u];
+ int ca = _next_out[u];
+ _res_cap[ca] -= delta;
+ _res_cap[_reverse[ca]] += delta;
+ }
+
+ // Check the maximum number of cycle canceling
+ if (cycle_cnt >= MAX_CYCLE_CANCEL) {
+ return false;
+ }
+
+ // Roll back search to delta_node
+ if (delta_node != tip) {
+ for (u = tip; u != delta_node; u = pred[u]) {
+ reached[u] = false;
+ }
+ tip = delta_node;
+ a = _next_out[tip] + 1;
+ last_out = _first_out[tip+1];
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Step back to the previous node
+ if (a == last_out) {
+ processed[tip] = true;
+ stack[++stack_top] = tip;
+ tip = pred[tip];
+ if (tip < 0) {
+ // Finish DFS from the current start node
+ break;
+ }
+ ++_next_out[tip];
+ }
+ }
+
+ }
+
+ return (cycle_cnt == 0);
+ }
+
+ // Global potential update heuristic
+ void globalUpdate() {
+ const int bucket_end = _root + 1;
+
+ // Initialize buckets
+ for (int r = 0; r != _max_rank; ++r) {
+ _buckets[r] = bucket_end;
+ }
+ Value total_excess = 0;
+ int b0 = bucket_end;
+ for (int i = 0; i != _res_node_num; ++i) {
+ if (_excess[i] < 0) {
+ _rank[i] = 0;
+ _bucket_next[i] = b0;
+ _bucket_prev[b0] = i;
+ b0 = i;
+ } else {
+ total_excess += _excess[i];
+ _rank[i] = _max_rank;
+ }
+ }
+ if (total_excess == 0) return;
+ _buckets[0] = b0;
+
+ // Search the buckets
+ int r = 0;
+ for ( ; r != _max_rank; ++r) {
+ while (_buckets[r] != bucket_end) {
+ // Remove the first node from the current bucket
+ int u = _buckets[r];
+ _buckets[r] = _bucket_next[u];
+
+ // Search the incoming arcs of u
+ LargeCost pi_u = _pi[u];
+ int last_out = _first_out[u+1];
+ for (int a = _first_out[u]; a != last_out; ++a) {
+ int ra = _reverse[a];
+ if (_res_cap[ra] > 0) {
+ int v = _source[ra];
+ int old_rank_v = _rank[v];
+ if (r < old_rank_v) {
+ // Compute the new rank of v
+ LargeCost nrc = (_cost[ra] + _pi[v] - pi_u) / _epsilon;
+ int new_rank_v = old_rank_v;
+ if (nrc < LargeCost(_max_rank)) {
+ new_rank_v = r + 1 + static_cast<int>(nrc);
+ }
+
+ // Change the rank of v
+ if (new_rank_v < old_rank_v) {
+ _rank[v] = new_rank_v;
+ _next_out[v] = _first_out[v];
+
+ // Remove v from its old bucket
+ if (old_rank_v < _max_rank) {
+ if (_buckets[old_rank_v] == v) {
+ _buckets[old_rank_v] = _bucket_next[v];
+ } else {
+ int pv = _bucket_prev[v], nv = _bucket_next[v];
+ _bucket_next[pv] = nv;
+ _bucket_prev[nv] = pv;
+ }
+ }
+
+ // Insert v into its new bucket
+ int nv = _buckets[new_rank_v];
+ _bucket_next[v] = nv;
+ _bucket_prev[nv] = v;
+ _buckets[new_rank_v] = v;
+ }
+ }
+ }
+ }
+
+ // Finish search if there are no more active nodes
+ if (_excess[u] > 0) {
+ total_excess -= _excess[u];
+ if (total_excess <= 0) break;
+ }
+ }
+ if (total_excess <= 0) break;
+ }
+
+ // Relabel nodes
+ for (int u = 0; u != _res_node_num; ++u) {
+ int k = std::min(_rank[u], r);
+ if (k > 0) {
+ _pi[u] -= _epsilon * k;
+ _next_out[u] = _first_out[u];
+ }
+ }
+ }
+
+ /// Execute the algorithm performing augment and relabel operations
+ void startAugment(int max_length) {
+ // Paramters for heuristics
+ const int PRICE_REFINEMENT_LIMIT = 2;
+ const double GLOBAL_UPDATE_FACTOR = 1.0;
+ const int global_update_skip = static_cast<int>(GLOBAL_UPDATE_FACTOR *
+ (_res_node_num + _sup_node_num * _sup_node_num));
+ int next_global_update_limit = global_update_skip;
+
+ // Perform cost scaling phases
+ IntVector path;
+ BoolVector path_arc(_res_arc_num, false);
+ int relabel_cnt = 0;
+ int eps_phase_cnt = 0;
+ for ( ; _epsilon >= 1; _epsilon = _epsilon < _alpha && _epsilon > 1 ?
+ 1 : _epsilon / _alpha )
+ {
+ ++eps_phase_cnt;
+
+ // Price refinement heuristic
+ if (eps_phase_cnt >= PRICE_REFINEMENT_LIMIT) {
+ if (priceRefinement()) continue;
+ }
+
+ // Initialize current phase
+ initPhase();
+
+ // Perform partial augment and relabel operations
+ while (true) {
+ // Select an active node (FIFO selection)
+ while (_active_nodes.size() > 0 &&
+ _excess[_active_nodes.front()] <= 0) {
+ _active_nodes.pop_front();
+ }
+ if (_active_nodes.size() == 0) break;
+ int start = _active_nodes.front();
+
+ // Find an augmenting path from the start node
+ int tip = start;
+ while (int(path.size()) < max_length && _excess[tip] >= 0) {
+ int u;
+ LargeCost rc, min_red_cost = std::numeric_limits<LargeCost>::max();
+ LargeCost pi_tip = _pi[tip];
+ int last_out = _first_out[tip+1];
+ for (int a = _next_out[tip]; a != last_out; ++a) {
+ if (_res_cap[a] > 0) {
+ u = _target[a];
+ rc = _cost[a] + pi_tip - _pi[u];
+ if (rc < 0) {
+ path.push_back(a);
+ _next_out[tip] = a;
+ if (path_arc[a]) {
+ goto augment; // a cycle is found, stop path search
+ }
+ tip = u;
+ path_arc[a] = true;
+ goto next_step;
+ }
+ else if (rc < min_red_cost) {
+ min_red_cost = rc;
+ }
+ }
+ }
+
+ // Relabel tip node
+ if (tip != start) {
+ int ra = _reverse[path.back()];
+ min_red_cost =
+ std::min(min_red_cost, _cost[ra] + pi_tip - _pi[_target[ra]]);
+ }
+ last_out = _next_out[tip];
+ for (int a = _first_out[tip]; a != last_out; ++a) {
+ if (_res_cap[a] > 0) {
+ rc = _cost[a] + pi_tip - _pi[_target[a]];
+ if (rc < min_red_cost) {
+ min_red_cost = rc;
+ }
+ }
+ }
+ _pi[tip] -= min_red_cost + _epsilon;
+ _next_out[tip] = _first_out[tip];
+ ++relabel_cnt;
+
+ // Step back
+ if (tip != start) {
+ int pa = path.back();
+ path_arc[pa] = false;
+ tip = _source[pa];
+ path.pop_back();
+ }
+
+ next_step: ;
+ }
+
+ // Augment along the found path (as much flow as possible)
+ augment:
+ Value delta;
+ int pa, u, v = start;
+ for (int i = 0; i != int(path.size()); ++i) {
+ pa = path[i];
+ u = v;
+ v = _target[pa];
+ path_arc[pa] = false;
+ delta = std::min(_res_cap[pa], _excess[u]);
+ _res_cap[pa] -= delta;
+ _res_cap[_reverse[pa]] += delta;
+ _excess[u] -= delta;
+ _excess[v] += delta;
+ if (_excess[v] > 0 && _excess[v] <= delta) {
+ _active_nodes.push_back(v);
+ }
+ }
+ path.clear();
+
+ // Global update heuristic
+ if (relabel_cnt >= next_global_update_limit) {
+ globalUpdate();
+ next_global_update_limit += global_update_skip;
+ }
+ }
+
+ }
+
+ }
+
+ /// Execute the algorithm performing push and relabel operations
+ void startPush() {
+ // Paramters for heuristics
+ const int PRICE_REFINEMENT_LIMIT = 2;
+ const double GLOBAL_UPDATE_FACTOR = 2.0;
+
+ const int global_update_skip = static_cast<int>(GLOBAL_UPDATE_FACTOR *
+ (_res_node_num + _sup_node_num * _sup_node_num));
+ int next_global_update_limit = global_update_skip;
+
+ // Perform cost scaling phases
+ BoolVector hyper(_res_node_num, false);
+ LargeCostVector hyper_cost(_res_node_num);
+ int relabel_cnt = 0;
+ int eps_phase_cnt = 0;
+ for ( ; _epsilon >= 1; _epsilon = _epsilon < _alpha && _epsilon > 1 ?
+ 1 : _epsilon / _alpha )
+ {
+ ++eps_phase_cnt;
+
+ // Price refinement heuristic
+ if (eps_phase_cnt >= PRICE_REFINEMENT_LIMIT) {
+ if (priceRefinement()) continue;
+ }
+
+ // Initialize current phase
+ initPhase();
+
+ // Perform push and relabel operations
+ while (_active_nodes.size() > 0) {
+ LargeCost min_red_cost, rc, pi_n;
+ Value delta;
+ int n, t, a, last_out = _res_arc_num;
+
+ next_node:
+ // Select an active node (FIFO selection)
+ n = _active_nodes.front();
+ last_out = _first_out[n+1];
+ pi_n = _pi[n];
+
+ // Perform push operations if there are admissible arcs
+ if (_excess[n] > 0) {
+ for (a = _next_out[n]; a != last_out; ++a) {
+ if (_res_cap[a] > 0 &&
+ _cost[a] + pi_n - _pi[_target[a]] < 0) {
+ delta = std::min(_res_cap[a], _excess[n]);
+ t = _target[a];
+
+ // Push-look-ahead heuristic
+ Value ahead = -_excess[t];
+ int last_out_t = _first_out[t+1];
+ LargeCost pi_t = _pi[t];
+ for (int ta = _next_out[t]; ta != last_out_t; ++ta) {
+ if (_res_cap[ta] > 0 &&
+ _cost[ta] + pi_t - _pi[_target[ta]] < 0)
+ ahead += _res_cap[ta];
+ if (ahead >= delta) break;
+ }
+ if (ahead < 0) ahead = 0;
+
+ // Push flow along the arc
+ if (ahead < delta && !hyper[t]) {
+ _res_cap[a] -= ahead;
+ _res_cap[_reverse[a]] += ahead;
+ _excess[n] -= ahead;
+ _excess[t] += ahead;
+ _active_nodes.push_front(t);
+ hyper[t] = true;
+ hyper_cost[t] = _cost[a] + pi_n - pi_t;
+ _next_out[n] = a;
+ goto next_node;
+ } else {
+ _res_cap[a] -= delta;
+ _res_cap[_reverse[a]] += delta;
+ _excess[n] -= delta;
+ _excess[t] += delta;
+ if (_excess[t] > 0 && _excess[t] <= delta)
+ _active_nodes.push_back(t);
+ }
+
+ if (_excess[n] == 0) {
+ _next_out[n] = a;
+ goto remove_nodes;
+ }
+ }
+ }
+ _next_out[n] = a;
+ }
+
+ // Relabel the node if it is still active (or hyper)
+ if (_excess[n] > 0 || hyper[n]) {
+ min_red_cost = hyper[n] ? -hyper_cost[n] :
+ std::numeric_limits<LargeCost>::max();
+ for (int a = _first_out[n]; a != last_out; ++a) {
+ if (_res_cap[a] > 0) {
+ rc = _cost[a] + pi_n - _pi[_target[a]];
+ if (rc < min_red_cost) {
+ min_red_cost = rc;
+ }
+ }
+ }
+ _pi[n] -= min_red_cost + _epsilon;
+ _next_out[n] = _first_out[n];
+ hyper[n] = false;
+ ++relabel_cnt;
+ }
+
+ // Remove nodes that are not active nor hyper
+ remove_nodes:
+ while ( _active_nodes.size() > 0 &&
+ _excess[_active_nodes.front()] <= 0 &&
+ !hyper[_active_nodes.front()] ) {
+ _active_nodes.pop_front();
+ }
+
+ // Global update heuristic
+ if (relabel_cnt >= next_global_update_limit) {
+ globalUpdate();
+ for (int u = 0; u != _res_node_num; ++u)
+ hyper[u] = false;
+ next_global_update_limit += global_update_skip;
+ }
+ }
+ }
+ }
+
+ }; //class CostScaling
+
+ ///@}
+
+} //namespace lemon
+
+#endif //LEMON_COST_SCALING_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/counter.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/counter.h
new file mode 100644
index 00000000000..a0049918929
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/counter.h
@@ -0,0 +1,249 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_COUNTER_H
+#define LEMON_COUNTER_H
+
+#include <string>
+#include <iostream>
+
+///\ingroup timecount
+///\file
+///\brief Tools for counting steps and events
+
+namespace lemon
+{
+
+ template<class P> class _NoSubCounter;
+
+ template<class P>
+ class _SubCounter
+ {
+ P &_parent;
+ std::string _title;
+ std::ostream &_os;
+ int count;
+ public:
+
+ typedef _SubCounter<_SubCounter<P> > SubCounter;
+ typedef _NoSubCounter<_SubCounter<P> > NoSubCounter;
+
+ _SubCounter(P &parent)
+ : _parent(parent), _title(), _os(std::cerr), count(0) {}
+ _SubCounter(P &parent,std::string title,std::ostream &os=std::cerr)
+ : _parent(parent), _title(title), _os(os), count(0) {}
+ _SubCounter(P &parent,const char *title,std::ostream &os=std::cerr)
+ : _parent(parent), _title(title), _os(os), count(0) {}
+ ~_SubCounter() {
+ _os << _title << count <<std::endl;
+ _parent+=count;
+ }
+ _SubCounter &operator++() { count++; return *this;}
+ int operator++(int) { return count++; }
+ _SubCounter &operator--() { count--; return *this;}
+ int operator--(int) { return count--; }
+ _SubCounter &operator+=(int c) { count+=c; return *this;}
+ _SubCounter &operator-=(int c) { count-=c; return *this;}
+ operator int() {return count;}
+ };
+
+ template<class P>
+ class _NoSubCounter
+ {
+ P &_parent;
+ public:
+ typedef _NoSubCounter<_NoSubCounter<P> > SubCounter;
+ typedef _NoSubCounter<_NoSubCounter<P> > NoSubCounter;
+
+ _NoSubCounter(P &parent) :_parent(parent) {}
+ _NoSubCounter(P &parent,std::string,std::ostream &)
+ :_parent(parent) {}
+ _NoSubCounter(P &parent,std::string)
+ :_parent(parent) {}
+ _NoSubCounter(P &parent,const char *,std::ostream &)
+ :_parent(parent) {}
+ _NoSubCounter(P &parent,const char *)
+ :_parent(parent) {}
+ ~_NoSubCounter() {}
+ _NoSubCounter &operator++() { ++_parent; return *this;}
+ int operator++(int) { _parent++; return 0;}
+ _NoSubCounter &operator--() { --_parent; return *this;}
+ int operator--(int) { _parent--; return 0;}
+ _NoSubCounter &operator+=(int c) { _parent+=c; return *this;}
+ _NoSubCounter &operator-=(int c) { _parent-=c; return *this;}
+ operator int() {return 0;}
+ };
+
+
+ /// \addtogroup timecount
+ /// @{
+
+ /// A counter class
+
+ /// This class makes it easier to count certain events (e.g. for debug
+ /// reasons).
+ /// You can increment or decrement the counter using \c operator++,
+ /// \c operator--, \c operator+= and \c operator-=. You can also
+ /// define subcounters for the different phases of the algorithm or
+ /// for different types of operations.
+ /// A report containing the given title and the value of the counter
+ /// is automatically printed on destruction.
+ ///
+ /// The following example shows the usage of counters and subcounters.
+ /// \code
+ /// // Bubble sort
+ /// std::vector<T> v;
+ /// ...
+ /// Counter op("Operations: ");
+ /// Counter::SubCounter as(op, "Assignments: ");
+ /// Counter::SubCounter co(op, "Comparisons: ");
+ /// for (int i = v.size()-1; i > 0; --i) {
+ /// for (int j = 0; j < i; ++j) {
+ /// if (v[j] > v[j+1]) {
+ /// T tmp = v[j];
+ /// v[j] = v[j+1];
+ /// v[j+1] = tmp;
+ /// as += 3; // three assignments
+ /// }
+ /// ++co; // one comparison
+ /// }
+ /// }
+ /// \endcode
+ ///
+ /// This code prints out something like that:
+ /// \code
+ /// Comparisons: 45
+ /// Assignments: 57
+ /// Operations: 102
+ /// \endcode
+ ///
+ /// \sa NoCounter
+ class Counter
+ {
+ std::string _title;
+ std::ostream &_os;
+ int count;
+ public:
+
+ /// SubCounter class
+
+ /// This class can be used to setup subcounters for a \ref Counter
+ /// to have finer reports. A subcounter provides exactly the same
+ /// operations as the main \ref Counter, but it also increments and
+ /// decrements the value of its parent.
+ /// Subcounters can also have subcounters.
+ ///
+ /// The parent counter must be given as the first parameter of the
+ /// constructor. Apart from that a title and an \c ostream object
+ /// can also be given just like for the main \ref Counter.
+ ///
+ /// A report containing the given title and the value of the
+ /// subcounter is automatically printed on destruction. If you
+ /// would like to turn off this report, use \ref NoSubCounter
+ /// instead.
+ ///
+ /// \sa NoSubCounter
+ typedef _SubCounter<Counter> SubCounter;
+
+ /// SubCounter class without printing report on destruction
+
+ /// This class can be used to setup subcounters for a \ref Counter.
+ /// It is the same as \ref SubCounter but it does not print report
+ /// on destruction. (It modifies the value of its parent, so 'No'
+ /// only means 'do not print'.)
+ ///
+ /// Replacing \ref SubCounter "SubCounter"s with \ref NoSubCounter
+ /// "NoSubCounter"s makes it possible to turn off reporting
+ /// subcounter values without actually removing the definitions
+ /// and the increment or decrement operators.
+ ///
+ /// \sa SubCounter
+ typedef _NoSubCounter<Counter> NoSubCounter;
+
+ /// Constructor.
+ Counter() : _title(), _os(std::cerr), count(0) {}
+ /// Constructor.
+ Counter(std::string title,std::ostream &os=std::cerr)
+ : _title(title), _os(os), count(0) {}
+ /// Constructor.
+ Counter(const char *title,std::ostream &os=std::cerr)
+ : _title(title), _os(os), count(0) {}
+ /// Destructor. Prints the given title and the value of the counter.
+ ~Counter() {
+ _os << _title << count <<std::endl;
+ }
+ ///\e
+ Counter &operator++() { count++; return *this;}
+ ///\e
+ int operator++(int) { return count++;}
+ ///\e
+ Counter &operator--() { count--; return *this;}
+ ///\e
+ int operator--(int) { return count--;}
+ ///\e
+ Counter &operator+=(int c) { count+=c; return *this;}
+ ///\e
+ Counter &operator-=(int c) { count-=c; return *this;}
+ /// Resets the counter to the given value.
+
+ /// Resets the counter to the given value.
+ /// \note This function does not reset the values of
+ /// \ref SubCounter "SubCounter"s but it resets \ref NoSubCounter
+ /// "NoSubCounter"s along with the main counter.
+ void reset(int c=0) {count=c;}
+ /// Returns the value of the counter.
+ operator int() {return count;}
+ };
+
+ /// 'Do nothing' version of Counter.
+
+ /// This class can be used in the same way as \ref Counter, but it
+ /// does not count at all and does not print report on destruction.
+ ///
+ /// Replacing a \ref Counter with a \ref NoCounter makes it possible
+ /// to turn off all counting and reporting (SubCounters should also
+ /// be replaced with NoSubCounters), so it does not affect the
+ /// efficiency of the program at all.
+ ///
+ /// \sa Counter
+ class NoCounter
+ {
+ public:
+ typedef _NoSubCounter<NoCounter> SubCounter;
+ typedef _NoSubCounter<NoCounter> NoSubCounter;
+
+ NoCounter() {}
+ NoCounter(std::string,std::ostream &) {}
+ NoCounter(const char *,std::ostream &) {}
+ NoCounter(std::string) {}
+ NoCounter(const char *) {}
+ NoCounter &operator++() { return *this; }
+ int operator++(int) { return 0; }
+ NoCounter &operator--() { return *this; }
+ int operator--(int) { return 0; }
+ NoCounter &operator+=(int) { return *this;}
+ NoCounter &operator-=(int) { return *this;}
+ void reset(int) {}
+ void reset() {}
+ operator int() {return 0;}
+ };
+
+ ///@}
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/cplex.cc b/extern/quadriflow/3rd/lemon-1.3.1/lemon/cplex.cc
new file mode 100644
index 00000000000..029a3efc500
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/cplex.cc
@@ -0,0 +1,994 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+#include <vector>
+#include <cstring>
+
+#include <lemon/cplex.h>
+
+extern "C" {
+#include <ilcplex/cplex.h>
+}
+
+
+///\file
+///\brief Implementation of the LEMON-CPLEX lp solver interface.
+namespace lemon {
+
+ CplexEnv::LicenseError::LicenseError(int status) {
+ if (!CPXgeterrorstring(0, status, _message)) {
+ std::strcpy(_message, "Cplex unknown error");
+ }
+ }
+
+ CplexEnv::CplexEnv() {
+ int status;
+ _cnt = new int;
+ (*_cnt) = 1;
+ _env = CPXopenCPLEX(&status);
+ if (_env == 0) {
+ delete _cnt;
+ _cnt = 0;
+ throw LicenseError(status);
+ }
+ }
+
+ CplexEnv::CplexEnv(const CplexEnv& other) {
+ _env = other._env;
+ _cnt = other._cnt;
+ ++(*_cnt);
+ }
+
+ CplexEnv& CplexEnv::operator=(const CplexEnv& other) {
+ _env = other._env;
+ _cnt = other._cnt;
+ ++(*_cnt);
+ return *this;
+ }
+
+ CplexEnv::~CplexEnv() {
+ --(*_cnt);
+ if (*_cnt == 0) {
+ delete _cnt;
+ CPXcloseCPLEX(&_env);
+ }
+ }
+
+ CplexBase::CplexBase() : LpBase() {
+ int status;
+ _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
+ messageLevel(MESSAGE_NOTHING);
+ }
+
+ CplexBase::CplexBase(const CplexEnv& env)
+ : LpBase(), _env(env) {
+ int status;
+ _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
+ messageLevel(MESSAGE_NOTHING);
+ }
+
+ CplexBase::CplexBase(const CplexBase& cplex)
+ : LpBase() {
+ int status;
+ _prob = CPXcloneprob(cplexEnv(), cplex._prob, &status);
+ rows = cplex.rows;
+ cols = cplex.cols;
+ messageLevel(MESSAGE_NOTHING);
+ }
+
+ CplexBase::~CplexBase() {
+ CPXfreeprob(cplexEnv(),&_prob);
+ }
+
+ int CplexBase::_addCol() {
+ int i = CPXgetnumcols(cplexEnv(), _prob);
+ double lb = -INF, ub = INF;
+ CPXnewcols(cplexEnv(), _prob, 1, 0, &lb, &ub, 0, 0);
+ return i;
+ }
+
+
+ int CplexBase::_addRow() {
+ int i = CPXgetnumrows(cplexEnv(), _prob);
+ const double ub = INF;
+ const char s = 'L';
+ CPXnewrows(cplexEnv(), _prob, 1, &ub, &s, 0, 0);
+ return i;
+ }
+
+ int CplexBase::_addRow(Value lb, ExprIterator b,
+ ExprIterator e, Value ub) {
+ int i = CPXgetnumrows(cplexEnv(), _prob);
+ if (lb == -INF) {
+ const char s = 'L';
+ CPXnewrows(cplexEnv(), _prob, 1, &ub, &s, 0, 0);
+ } else if (ub == INF) {
+ const char s = 'G';
+ CPXnewrows(cplexEnv(), _prob, 1, &lb, &s, 0, 0);
+ } else if (lb == ub){
+ const char s = 'E';
+ CPXnewrows(cplexEnv(), _prob, 1, &lb, &s, 0, 0);
+ } else {
+ const char s = 'R';
+ double len = ub - lb;
+ CPXnewrows(cplexEnv(), _prob, 1, &lb, &s, &len, 0);
+ }
+
+ std::vector<int> indices;
+ std::vector<int> rowlist;
+ std::vector<Value> values;
+
+ for(ExprIterator it=b; it!=e; ++it) {
+ indices.push_back(it->first);
+ values.push_back(it->second);
+ rowlist.push_back(i);
+ }
+
+ CPXchgcoeflist(cplexEnv(), _prob, values.size(),
+ &rowlist.front(), &indices.front(), &values.front());
+
+ return i;
+ }
+
+ void CplexBase::_eraseCol(int i) {
+ CPXdelcols(cplexEnv(), _prob, i, i);
+ }
+
+ void CplexBase::_eraseRow(int i) {
+ CPXdelrows(cplexEnv(), _prob, i, i);
+ }
+
+ void CplexBase::_eraseColId(int i) {
+ cols.eraseIndex(i);
+ cols.shiftIndices(i);
+ }
+ void CplexBase::_eraseRowId(int i) {
+ rows.eraseIndex(i);
+ rows.shiftIndices(i);
+ }
+
+ void CplexBase::_getColName(int col, std::string &name) const {
+ int size;
+ CPXgetcolname(cplexEnv(), _prob, 0, 0, 0, &size, col, col);
+ if (size == 0) {
+ name.clear();
+ return;
+ }
+
+ size *= -1;
+ std::vector<char> buf(size);
+ char *cname;
+ int tmp;
+ CPXgetcolname(cplexEnv(), _prob, &cname, &buf.front(), size,
+ &tmp, col, col);
+ name = cname;
+ }
+
+ void CplexBase::_setColName(int col, const std::string &name) {
+ char *cname;
+ cname = const_cast<char*>(name.c_str());
+ CPXchgcolname(cplexEnv(), _prob, 1, &col, &cname);
+ }
+
+ int CplexBase::_colByName(const std::string& name) const {
+ int index;
+ if (CPXgetcolindex(cplexEnv(), _prob,
+ const_cast<char*>(name.c_str()), &index) == 0) {
+ return index;
+ }
+ return -1;
+ }
+
+ void CplexBase::_getRowName(int row, std::string &name) const {
+ int size;
+ CPXgetrowname(cplexEnv(), _prob, 0, 0, 0, &size, row, row);
+ if (size == 0) {
+ name.clear();
+ return;
+ }
+
+ size *= -1;
+ std::vector<char> buf(size);
+ char *cname;
+ int tmp;
+ CPXgetrowname(cplexEnv(), _prob, &cname, &buf.front(), size,
+ &tmp, row, row);
+ name = cname;
+ }
+
+ void CplexBase::_setRowName(int row, const std::string &name) {
+ char *cname;
+ cname = const_cast<char*>(name.c_str());
+ CPXchgrowname(cplexEnv(), _prob, 1, &row, &cname);
+ }
+
+ int CplexBase::_rowByName(const std::string& name) const {
+ int index;
+ if (CPXgetrowindex(cplexEnv(), _prob,
+ const_cast<char*>(name.c_str()), &index) == 0) {
+ return index;
+ }
+ return -1;
+ }
+
+ void CplexBase::_setRowCoeffs(int i, ExprIterator b,
+ ExprIterator e)
+ {
+ std::vector<int> indices;
+ std::vector<int> rowlist;
+ std::vector<Value> values;
+
+ for(ExprIterator it=b; it!=e; ++it) {
+ indices.push_back(it->first);
+ values.push_back(it->second);
+ rowlist.push_back(i);
+ }
+
+ CPXchgcoeflist(cplexEnv(), _prob, values.size(),
+ &rowlist.front(), &indices.front(), &values.front());
+ }
+
+ void CplexBase::_getRowCoeffs(int i, InsertIterator b) const {
+ int tmp1, tmp2, tmp3, length;
+ CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
+
+ length = -length;
+ std::vector<int> indices(length);
+ std::vector<double> values(length);
+
+ CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2,
+ &indices.front(), &values.front(),
+ length, &tmp3, i, i);
+
+ for (int i = 0; i < length; ++i) {
+ *b = std::make_pair(indices[i], values[i]);
+ ++b;
+ }
+ }
+
+ void CplexBase::_setColCoeffs(int i, ExprIterator b, ExprIterator e) {
+ std::vector<int> indices;
+ std::vector<int> collist;
+ std::vector<Value> values;
+
+ for(ExprIterator it=b; it!=e; ++it) {
+ indices.push_back(it->first);
+ values.push_back(it->second);
+ collist.push_back(i);
+ }
+
+ CPXchgcoeflist(cplexEnv(), _prob, values.size(),
+ &indices.front(), &collist.front(), &values.front());
+ }
+
+ void CplexBase::_getColCoeffs(int i, InsertIterator b) const {
+
+ int tmp1, tmp2, tmp3, length;
+ CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
+
+ length = -length;
+ std::vector<int> indices(length);
+ std::vector<double> values(length);
+
+ CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2,
+ &indices.front(), &values.front(),
+ length, &tmp3, i, i);
+
+ for (int i = 0; i < length; ++i) {
+ *b = std::make_pair(indices[i], values[i]);
+ ++b;
+ }
+
+ }
+
+ void CplexBase::_setCoeff(int row, int col, Value value) {
+ CPXchgcoef(cplexEnv(), _prob, row, col, value);
+ }
+
+ CplexBase::Value CplexBase::_getCoeff(int row, int col) const {
+ CplexBase::Value value;
+ CPXgetcoef(cplexEnv(), _prob, row, col, &value);
+ return value;
+ }
+
+ void CplexBase::_setColLowerBound(int i, Value value) {
+ const char s = 'L';
+ CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
+ }
+
+ CplexBase::Value CplexBase::_getColLowerBound(int i) const {
+ CplexBase::Value res;
+ CPXgetlb(cplexEnv(), _prob, &res, i, i);
+ return res <= -CPX_INFBOUND ? -INF : res;
+ }
+
+ void CplexBase::_setColUpperBound(int i, Value value)
+ {
+ const char s = 'U';
+ CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
+ }
+
+ CplexBase::Value CplexBase::_getColUpperBound(int i) const {
+ CplexBase::Value res;
+ CPXgetub(cplexEnv(), _prob, &res, i, i);
+ return res >= CPX_INFBOUND ? INF : res;
+ }
+
+ CplexBase::Value CplexBase::_getRowLowerBound(int i) const {
+ char s;
+ CPXgetsense(cplexEnv(), _prob, &s, i, i);
+ CplexBase::Value res;
+
+ switch (s) {
+ case 'G':
+ case 'R':
+ case 'E':
+ CPXgetrhs(cplexEnv(), _prob, &res, i, i);
+ return res <= -CPX_INFBOUND ? -INF : res;
+ default:
+ return -INF;
+ }
+ }
+
+ CplexBase::Value CplexBase::_getRowUpperBound(int i) const {
+ char s;
+ CPXgetsense(cplexEnv(), _prob, &s, i, i);
+ CplexBase::Value res;
+
+ switch (s) {
+ case 'L':
+ case 'E':
+ CPXgetrhs(cplexEnv(), _prob, &res, i, i);
+ return res >= CPX_INFBOUND ? INF : res;
+ case 'R':
+ CPXgetrhs(cplexEnv(), _prob, &res, i, i);
+ {
+ double rng;
+ CPXgetrngval(cplexEnv(), _prob, &rng, i, i);
+ res += rng;
+ }
+ return res >= CPX_INFBOUND ? INF : res;
+ default:
+ return INF;
+ }
+ }
+
+ //This is easier to implement
+ void CplexBase::_set_row_bounds(int i, Value lb, Value ub) {
+ if (lb == -INF) {
+ const char s = 'L';
+ CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
+ CPXchgrhs(cplexEnv(), _prob, 1, &i, &ub);
+ } else if (ub == INF) {
+ const char s = 'G';
+ CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
+ CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
+ } else if (lb == ub){
+ const char s = 'E';
+ CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
+ CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
+ } else {
+ const char s = 'R';
+ CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
+ CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
+ double len = ub - lb;
+ CPXchgrngval(cplexEnv(), _prob, 1, &i, &len);
+ }
+ }
+
+ void CplexBase::_setRowLowerBound(int i, Value lb)
+ {
+ LEMON_ASSERT(lb != INF, "Invalid bound");
+ _set_row_bounds(i, lb, CplexBase::_getRowUpperBound(i));
+ }
+
+ void CplexBase::_setRowUpperBound(int i, Value ub)
+ {
+
+ LEMON_ASSERT(ub != -INF, "Invalid bound");
+ _set_row_bounds(i, CplexBase::_getRowLowerBound(i), ub);
+ }
+
+ void CplexBase::_setObjCoeffs(ExprIterator b, ExprIterator e)
+ {
+ std::vector<int> indices;
+ std::vector<Value> values;
+ for(ExprIterator it=b; it!=e; ++it) {
+ indices.push_back(it->first);
+ values.push_back(it->second);
+ }
+ CPXchgobj(cplexEnv(), _prob, values.size(),
+ &indices.front(), &values.front());
+
+ }
+
+ void CplexBase::_getObjCoeffs(InsertIterator b) const
+ {
+ int num = CPXgetnumcols(cplexEnv(), _prob);
+ std::vector<Value> x(num);
+
+ CPXgetobj(cplexEnv(), _prob, &x.front(), 0, num - 1);
+ for (int i = 0; i < num; ++i) {
+ if (x[i] != 0.0) {
+ *b = std::make_pair(i, x[i]);
+ ++b;
+ }
+ }
+ }
+
+ void CplexBase::_setObjCoeff(int i, Value obj_coef)
+ {
+ CPXchgobj(cplexEnv(), _prob, 1, &i, &obj_coef);
+ }
+
+ CplexBase::Value CplexBase::_getObjCoeff(int i) const
+ {
+ Value x;
+ CPXgetobj(cplexEnv(), _prob, &x, i, i);
+ return x;
+ }
+
+ void CplexBase::_setSense(CplexBase::Sense sense) {
+ switch (sense) {
+ case MIN:
+ CPXchgobjsen(cplexEnv(), _prob, CPX_MIN);
+ break;
+ case MAX:
+ CPXchgobjsen(cplexEnv(), _prob, CPX_MAX);
+ break;
+ }
+ }
+
+ CplexBase::Sense CplexBase::_getSense() const {
+ switch (CPXgetobjsen(cplexEnv(), _prob)) {
+ case CPX_MIN:
+ return MIN;
+ case CPX_MAX:
+ return MAX;
+ default:
+ LEMON_ASSERT(false, "Invalid sense");
+ return CplexBase::Sense();
+ }
+ }
+
+ void CplexBase::_clear() {
+ CPXfreeprob(cplexEnv(),&_prob);
+ int status;
+ _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
+ }
+
+ void CplexBase::_messageLevel(MessageLevel level) {
+ switch (level) {
+ case MESSAGE_NOTHING:
+ _message_enabled = false;
+ break;
+ case MESSAGE_ERROR:
+ case MESSAGE_WARNING:
+ case MESSAGE_NORMAL:
+ case MESSAGE_VERBOSE:
+ _message_enabled = true;
+ break;
+ }
+ }
+
+ void CplexBase::_applyMessageLevel() {
+ CPXsetintparam(cplexEnv(), CPX_PARAM_SCRIND,
+ _message_enabled ? CPX_ON : CPX_OFF);
+ }
+
+ void CplexBase::_write(std::string file, std::string format) const
+ {
+ if(format == "MPS" || format == "LP")
+ CPXwriteprob(cplexEnv(), cplexLp(), file.c_str(), format.c_str());
+ else if(format == "SOL")
+ CPXsolwrite(cplexEnv(), cplexLp(), file.c_str());
+ else throw UnsupportedFormatError(format);
+ }
+
+
+
+ // CplexLp members
+
+ CplexLp::CplexLp()
+ : LpBase(), LpSolver(), CplexBase() {}
+
+ CplexLp::CplexLp(const CplexEnv& env)
+ : LpBase(), LpSolver(), CplexBase(env) {}
+
+ CplexLp::CplexLp(const CplexLp& other)
+ : LpBase(), LpSolver(), CplexBase(other) {}
+
+ CplexLp::~CplexLp() {}
+
+ CplexLp* CplexLp::newSolver() const { return new CplexLp; }
+ CplexLp* CplexLp::cloneSolver() const {return new CplexLp(*this); }
+
+ const char* CplexLp::_solverName() const { return "CplexLp"; }
+
+ void CplexLp::_clear_temporals() {
+ _col_status.clear();
+ _row_status.clear();
+ _primal_ray.clear();
+ _dual_ray.clear();
+ }
+
+ // The routine returns zero unless an error occurred during the
+ // optimization. Examples of errors include exhausting available
+ // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
+ // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
+ // user-specified CPLEX limit, or proving the model infeasible or
+ // unbounded, are not considered errors. Note that a zero return
+ // value does not necessarily mean that a solution exists. Use query
+ // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
+ // further information about the status of the optimization.
+ CplexLp::SolveExitStatus CplexLp::convertStatus(int status) {
+#if CPX_VERSION >= 800
+ if (status == 0) {
+ switch (CPXgetstat(cplexEnv(), _prob)) {
+ case CPX_STAT_OPTIMAL:
+ case CPX_STAT_INFEASIBLE:
+ case CPX_STAT_UNBOUNDED:
+ return SOLVED;
+ default:
+ return UNSOLVED;
+ }
+ } else {
+ return UNSOLVED;
+ }
+#else
+ if (status == 0) {
+ //We want to exclude some cases
+ switch (CPXgetstat(cplexEnv(), _prob)) {
+ case CPX_OBJ_LIM:
+ case CPX_IT_LIM_FEAS:
+ case CPX_IT_LIM_INFEAS:
+ case CPX_TIME_LIM_FEAS:
+ case CPX_TIME_LIM_INFEAS:
+ return UNSOLVED;
+ default:
+ return SOLVED;
+ }
+ } else {
+ return UNSOLVED;
+ }
+#endif
+ }
+
+ CplexLp::SolveExitStatus CplexLp::_solve() {
+ _clear_temporals();
+ _applyMessageLevel();
+ return convertStatus(CPXlpopt(cplexEnv(), _prob));
+ }
+
+ CplexLp::SolveExitStatus CplexLp::solvePrimal() {
+ _clear_temporals();
+ _applyMessageLevel();
+ return convertStatus(CPXprimopt(cplexEnv(), _prob));
+ }
+
+ CplexLp::SolveExitStatus CplexLp::solveDual() {
+ _clear_temporals();
+ _applyMessageLevel();
+ return convertStatus(CPXdualopt(cplexEnv(), _prob));
+ }
+
+ CplexLp::SolveExitStatus CplexLp::solveBarrier() {
+ _clear_temporals();
+ _applyMessageLevel();
+ return convertStatus(CPXbaropt(cplexEnv(), _prob));
+ }
+
+ CplexLp::Value CplexLp::_getPrimal(int i) const {
+ Value x;
+ CPXgetx(cplexEnv(), _prob, &x, i, i);
+ return x;
+ }
+
+ CplexLp::Value CplexLp::_getDual(int i) const {
+ Value y;
+ CPXgetpi(cplexEnv(), _prob, &y, i, i);
+ return y;
+ }
+
+ CplexLp::Value CplexLp::_getPrimalValue() const {
+ Value objval;
+ CPXgetobjval(cplexEnv(), _prob, &objval);
+ return objval;
+ }
+
+ CplexLp::VarStatus CplexLp::_getColStatus(int i) const {
+ if (_col_status.empty()) {
+ _col_status.resize(CPXgetnumcols(cplexEnv(), _prob));
+ CPXgetbase(cplexEnv(), _prob, &_col_status.front(), 0);
+ }
+ switch (_col_status[i]) {
+ case CPX_BASIC:
+ return BASIC;
+ case CPX_FREE_SUPER:
+ return FREE;
+ case CPX_AT_LOWER:
+ return LOWER;
+ case CPX_AT_UPPER:
+ return UPPER;
+ default:
+ LEMON_ASSERT(false, "Wrong column status");
+ return CplexLp::VarStatus();
+ }
+ }
+
+ CplexLp::VarStatus CplexLp::_getRowStatus(int i) const {
+ if (_row_status.empty()) {
+ _row_status.resize(CPXgetnumrows(cplexEnv(), _prob));
+ CPXgetbase(cplexEnv(), _prob, 0, &_row_status.front());
+ }
+ switch (_row_status[i]) {
+ case CPX_BASIC:
+ return BASIC;
+ case CPX_AT_LOWER:
+ {
+ char s;
+ CPXgetsense(cplexEnv(), _prob, &s, i, i);
+ return s != 'L' ? LOWER : UPPER;
+ }
+ case CPX_AT_UPPER:
+ return UPPER;
+ default:
+ LEMON_ASSERT(false, "Wrong row status");
+ return CplexLp::VarStatus();
+ }
+ }
+
+ CplexLp::Value CplexLp::_getPrimalRay(int i) const {
+ if (_primal_ray.empty()) {
+ _primal_ray.resize(CPXgetnumcols(cplexEnv(), _prob));
+ CPXgetray(cplexEnv(), _prob, &_primal_ray.front());
+ }
+ return _primal_ray[i];
+ }
+
+ CplexLp::Value CplexLp::_getDualRay(int i) const {
+ if (_dual_ray.empty()) {
+
+ }
+ return _dual_ray[i];
+ }
+
+ // Cplex 7.0 status values
+ // This table lists the statuses, returned by the CPXgetstat()
+ // routine, for solutions to LP problems or mixed integer problems. If
+ // no solution exists, the return value is zero.
+
+ // For Simplex, Barrier
+ // 1 CPX_OPTIMAL
+ // Optimal solution found
+ // 2 CPX_INFEASIBLE
+ // Problem infeasible
+ // 3 CPX_UNBOUNDED
+ // Problem unbounded
+ // 4 CPX_OBJ_LIM
+ // Objective limit exceeded in Phase II
+ // 5 CPX_IT_LIM_FEAS
+ // Iteration limit exceeded in Phase II
+ // 6 CPX_IT_LIM_INFEAS
+ // Iteration limit exceeded in Phase I
+ // 7 CPX_TIME_LIM_FEAS
+ // Time limit exceeded in Phase II
+ // 8 CPX_TIME_LIM_INFEAS
+ // Time limit exceeded in Phase I
+ // 9 CPX_NUM_BEST_FEAS
+ // Problem non-optimal, singularities in Phase II
+ // 10 CPX_NUM_BEST_INFEAS
+ // Problem non-optimal, singularities in Phase I
+ // 11 CPX_OPTIMAL_INFEAS
+ // Optimal solution found, unscaled infeasibilities
+ // 12 CPX_ABORT_FEAS
+ // Aborted in Phase II
+ // 13 CPX_ABORT_INFEAS
+ // Aborted in Phase I
+ // 14 CPX_ABORT_DUAL_INFEAS
+ // Aborted in barrier, dual infeasible
+ // 15 CPX_ABORT_PRIM_INFEAS
+ // Aborted in barrier, primal infeasible
+ // 16 CPX_ABORT_PRIM_DUAL_INFEAS
+ // Aborted in barrier, primal and dual infeasible
+ // 17 CPX_ABORT_PRIM_DUAL_FEAS
+ // Aborted in barrier, primal and dual feasible
+ // 18 CPX_ABORT_CROSSOVER
+ // Aborted in crossover
+ // 19 CPX_INForUNBD
+ // Infeasible or unbounded
+ // 20 CPX_PIVOT
+ // User pivot used
+ //
+ // Pending return values
+ // ??case CPX_ABORT_DUAL_INFEAS
+ // ??case CPX_ABORT_CROSSOVER
+ // ??case CPX_INForUNBD
+ // ??case CPX_PIVOT
+
+ //Some more interesting stuff:
+
+ // CPX_PARAM_PROBMETHOD 1062 int LPMETHOD
+ // 0 Automatic
+ // 1 Primal Simplex
+ // 2 Dual Simplex
+ // 3 Network Simplex
+ // 4 Standard Barrier
+ // Default: 0
+ // Description: Method for linear optimization.
+ // Determines which algorithm is used when CPXlpopt() (or "optimize"
+ // in the Interactive Optimizer) is called. Currently the behavior of
+ // the "Automatic" setting is that CPLEX simply invokes the dual
+ // simplex method, but this capability may be expanded in the future
+ // so that CPLEX chooses the method based on problem characteristics
+#if CPX_VERSION < 900
+ void statusSwitch(CPXENVptr cplexEnv(),int& stat){
+ int lpmethod;
+ CPXgetintparam (cplexEnv(),CPX_PARAM_PROBMETHOD,&lpmethod);
+ if (lpmethod==2){
+ if (stat==CPX_UNBOUNDED){
+ stat=CPX_INFEASIBLE;
+ }
+ else{
+ if (stat==CPX_INFEASIBLE)
+ stat=CPX_UNBOUNDED;
+ }
+ }
+ }
+#else
+ void statusSwitch(CPXENVptr,int&){}
+#endif
+
+ CplexLp::ProblemType CplexLp::_getPrimalType() const {
+ // Unboundedness not treated well: the following is from cplex 9.0 doc
+ // About Unboundedness
+
+ // The treatment of models that are unbounded involves a few
+ // subtleties. Specifically, a declaration of unboundedness means that
+ // ILOG CPLEX has determined that the model has an unbounded
+ // ray. Given any feasible solution x with objective z, a multiple of
+ // the unbounded ray can be added to x to give a feasible solution
+ // with objective z-1 (or z+1 for maximization models). Thus, if a
+ // feasible solution exists, then the optimal objective is
+ // unbounded. Note that ILOG CPLEX has not necessarily concluded that
+ // a feasible solution exists. Users can call the routine CPXsolninfo
+ // to determine whether ILOG CPLEX has also concluded that the model
+ // has a feasible solution.
+
+ int stat = CPXgetstat(cplexEnv(), _prob);
+#if CPX_VERSION >= 800
+ switch (stat)
+ {
+ case CPX_STAT_OPTIMAL:
+ return OPTIMAL;
+ case CPX_STAT_UNBOUNDED:
+ return UNBOUNDED;
+ case CPX_STAT_INFEASIBLE:
+ return INFEASIBLE;
+ default:
+ return UNDEFINED;
+ }
+#else
+ statusSwitch(cplexEnv(),stat);
+ //CPXgetstat(cplexEnv(), _prob);
+ switch (stat) {
+ case 0:
+ return UNDEFINED; //Undefined
+ case CPX_OPTIMAL://Optimal
+ return OPTIMAL;
+ case CPX_UNBOUNDED://Unbounded
+ return INFEASIBLE;//In case of dual simplex
+ //return UNBOUNDED;
+ case CPX_INFEASIBLE://Infeasible
+ // case CPX_IT_LIM_INFEAS:
+ // case CPX_TIME_LIM_INFEAS:
+ // case CPX_NUM_BEST_INFEAS:
+ // case CPX_OPTIMAL_INFEAS:
+ // case CPX_ABORT_INFEAS:
+ // case CPX_ABORT_PRIM_INFEAS:
+ // case CPX_ABORT_PRIM_DUAL_INFEAS:
+ return UNBOUNDED;//In case of dual simplex
+ //return INFEASIBLE;
+ // case CPX_OBJ_LIM:
+ // case CPX_IT_LIM_FEAS:
+ // case CPX_TIME_LIM_FEAS:
+ // case CPX_NUM_BEST_FEAS:
+ // case CPX_ABORT_FEAS:
+ // case CPX_ABORT_PRIM_DUAL_FEAS:
+ // return FEASIBLE;
+ default:
+ return UNDEFINED; //Everything else comes here
+ //FIXME error
+ }
+#endif
+ }
+
+ // Cplex 9.0 status values
+ // CPX_STAT_ABORT_DUAL_OBJ_LIM
+ // CPX_STAT_ABORT_IT_LIM
+ // CPX_STAT_ABORT_OBJ_LIM
+ // CPX_STAT_ABORT_PRIM_OBJ_LIM
+ // CPX_STAT_ABORT_TIME_LIM
+ // CPX_STAT_ABORT_USER
+ // CPX_STAT_FEASIBLE_RELAXED
+ // CPX_STAT_INFEASIBLE
+ // CPX_STAT_INForUNBD
+ // CPX_STAT_NUM_BEST
+ // CPX_STAT_OPTIMAL
+ // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
+ // CPX_STAT_OPTIMAL_INFEAS
+ // CPX_STAT_OPTIMAL_RELAXED
+ // CPX_STAT_UNBOUNDED
+
+ CplexLp::ProblemType CplexLp::_getDualType() const {
+ int stat = CPXgetstat(cplexEnv(), _prob);
+#if CPX_VERSION >= 800
+ switch (stat) {
+ case CPX_STAT_OPTIMAL:
+ return OPTIMAL;
+ case CPX_STAT_UNBOUNDED:
+ return INFEASIBLE;
+ default:
+ return UNDEFINED;
+ }
+#else
+ statusSwitch(cplexEnv(),stat);
+ switch (stat) {
+ case 0:
+ return UNDEFINED; //Undefined
+ case CPX_OPTIMAL://Optimal
+ return OPTIMAL;
+ case CPX_UNBOUNDED:
+ return INFEASIBLE;
+ default:
+ return UNDEFINED; //Everything else comes here
+ //FIXME error
+ }
+#endif
+ }
+
+ // CplexMip members
+
+ CplexMip::CplexMip()
+ : LpBase(), MipSolver(), CplexBase() {
+
+#if CPX_VERSION < 800
+ CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP);
+#else
+ CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MILP);
+#endif
+ }
+
+ CplexMip::CplexMip(const CplexEnv& env)
+ : LpBase(), MipSolver(), CplexBase(env) {
+
+#if CPX_VERSION < 800
+ CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP);
+#else
+ CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MILP);
+#endif
+
+ }
+
+ CplexMip::CplexMip(const CplexMip& other)
+ : LpBase(), MipSolver(), CplexBase(other) {}
+
+ CplexMip::~CplexMip() {}
+
+ CplexMip* CplexMip::newSolver() const { return new CplexMip; }
+ CplexMip* CplexMip::cloneSolver() const {return new CplexMip(*this); }
+
+ const char* CplexMip::_solverName() const { return "CplexMip"; }
+
+ void CplexMip::_setColType(int i, CplexMip::ColTypes col_type) {
+
+ // Note If a variable is to be changed to binary, a call to CPXchgbds
+ // should also be made to change the bounds to 0 and 1.
+
+ switch (col_type){
+ case INTEGER: {
+ const char t = 'I';
+ CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
+ } break;
+ case REAL: {
+ const char t = 'C';
+ CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
+ } break;
+ default:
+ break;
+ }
+ }
+
+ CplexMip::ColTypes CplexMip::_getColType(int i) const {
+ char t;
+ CPXgetctype (cplexEnv(), _prob, &t, i, i);
+ switch (t) {
+ case 'I':
+ return INTEGER;
+ case 'C':
+ return REAL;
+ default:
+ LEMON_ASSERT(false, "Invalid column type");
+ return ColTypes();
+ }
+
+ }
+
+ CplexMip::SolveExitStatus CplexMip::_solve() {
+ int status;
+ _applyMessageLevel();
+ status = CPXmipopt (cplexEnv(), _prob);
+ if (status==0)
+ return SOLVED;
+ else
+ return UNSOLVED;
+
+ }
+
+
+ CplexMip::ProblemType CplexMip::_getType() const {
+
+ int stat = CPXgetstat(cplexEnv(), _prob);
+
+ //Fortunately, MIP statuses did not change for cplex 8.0
+ switch (stat) {
+ case CPXMIP_OPTIMAL:
+ // Optimal integer solution has been found.
+ case CPXMIP_OPTIMAL_TOL:
+ // Optimal soluton with the tolerance defined by epgap or epagap has
+ // been found.
+ return OPTIMAL;
+ //This also exists in later issues
+ // case CPXMIP_UNBOUNDED:
+ //return UNBOUNDED;
+ case CPXMIP_INFEASIBLE:
+ return INFEASIBLE;
+ default:
+ return UNDEFINED;
+ }
+ //Unboundedness not treated well: the following is from cplex 9.0 doc
+ // About Unboundedness
+
+ // The treatment of models that are unbounded involves a few
+ // subtleties. Specifically, a declaration of unboundedness means that
+ // ILOG CPLEX has determined that the model has an unbounded
+ // ray. Given any feasible solution x with objective z, a multiple of
+ // the unbounded ray can be added to x to give a feasible solution
+ // with objective z-1 (or z+1 for maximization models). Thus, if a
+ // feasible solution exists, then the optimal objective is
+ // unbounded. Note that ILOG CPLEX has not necessarily concluded that
+ // a feasible solution exists. Users can call the routine CPXsolninfo
+ // to determine whether ILOG CPLEX has also concluded that the model
+ // has a feasible solution.
+ }
+
+ CplexMip::Value CplexMip::_getSol(int i) const {
+ Value x;
+ CPXgetmipx(cplexEnv(), _prob, &x, i, i);
+ return x;
+ }
+
+ CplexMip::Value CplexMip::_getSolValue() const {
+ Value objval;
+ CPXgetmipobjval(cplexEnv(), _prob, &objval);
+ return objval;
+ }
+
+} //namespace lemon
+
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/cplex.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/cplex.h
new file mode 100644
index 00000000000..c17e7926ad6
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/cplex.h
@@ -0,0 +1,292 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_CPLEX_H
+#define LEMON_CPLEX_H
+
+///\file
+///\brief Header of the LEMON-CPLEX lp solver interface.
+
+#include <lemon/lp_base.h>
+
+struct cpxenv;
+struct cpxlp;
+
+namespace lemon {
+
+ /// \brief Reference counted wrapper around cpxenv pointer
+ ///
+ /// The cplex uses environment object which is responsible for
+ /// checking the proper license usage. This class provides a simple
+ /// interface for share the environment object between different
+ /// problems.
+ class CplexEnv {
+ friend class CplexBase;
+ private:
+ cpxenv* _env;
+ mutable int* _cnt;
+
+ public:
+
+ /// \brief This exception is thrown when the license check is not
+ /// sufficient
+ class LicenseError : public Exception {
+ friend class CplexEnv;
+ private:
+
+ LicenseError(int status);
+ char _message[510];
+
+ public:
+
+ /// The short error message
+ virtual const char* what() const throw() {
+ return _message;
+ }
+ };
+
+ /// Constructor
+ CplexEnv();
+ /// Shallow copy constructor
+ CplexEnv(const CplexEnv&);
+ /// Shallow assignement
+ CplexEnv& operator=(const CplexEnv&);
+ /// Destructor
+ virtual ~CplexEnv();
+
+ protected:
+
+ cpxenv* cplexEnv() { return _env; }
+ const cpxenv* cplexEnv() const { return _env; }
+ };
+
+ /// \brief Base interface for the CPLEX LP and MIP solver
+ ///
+ /// This class implements the common interface of the CPLEX LP and
+ /// MIP solvers.
+ /// \ingroup lp_group
+ class CplexBase : virtual public LpBase {
+ protected:
+
+ CplexEnv _env;
+ cpxlp* _prob;
+
+ CplexBase();
+ CplexBase(const CplexEnv&);
+ CplexBase(const CplexBase &);
+ virtual ~CplexBase();
+
+ virtual int _addCol();
+ virtual int _addRow();
+ virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
+
+ virtual void _eraseCol(int i);
+ virtual void _eraseRow(int i);
+
+ virtual void _eraseColId(int i);
+ virtual void _eraseRowId(int i);
+
+ virtual void _getColName(int col, std::string& name) const;
+ virtual void _setColName(int col, const std::string& name);
+ virtual int _colByName(const std::string& name) const;
+
+ virtual void _getRowName(int row, std::string& name) const;
+ virtual void _setRowName(int row, const std::string& name);
+ virtual int _rowByName(const std::string& name) const;
+
+ virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
+ virtual void _getRowCoeffs(int i, InsertIterator b) const;
+
+ virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
+ virtual void _getColCoeffs(int i, InsertIterator b) const;
+
+ virtual void _setCoeff(int row, int col, Value value);
+ virtual Value _getCoeff(int row, int col) const;
+
+ virtual void _setColLowerBound(int i, Value value);
+ virtual Value _getColLowerBound(int i) const;
+
+ virtual void _setColUpperBound(int i, Value value);
+ virtual Value _getColUpperBound(int i) const;
+
+ private:
+ void _set_row_bounds(int i, Value lb, Value ub);
+ protected:
+
+ virtual void _setRowLowerBound(int i, Value value);
+ virtual Value _getRowLowerBound(int i) const;
+
+ virtual void _setRowUpperBound(int i, Value value);
+ virtual Value _getRowUpperBound(int i) const;
+
+ virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
+ virtual void _getObjCoeffs(InsertIterator b) const;
+
+ virtual void _setObjCoeff(int i, Value obj_coef);
+ virtual Value _getObjCoeff(int i) const;
+
+ virtual void _setSense(Sense sense);
+ virtual Sense _getSense() const;
+
+ virtual void _clear();
+
+ virtual void _messageLevel(MessageLevel level);
+ void _applyMessageLevel();
+
+ bool _message_enabled;
+
+ void _write(std::string file, std::string format) const;
+
+ public:
+
+ /// Returns the used \c CplexEnv instance
+ const CplexEnv& env() const { return _env; }
+
+ /// \brief Returns the const cpxenv pointer
+ ///
+ /// \note The cpxenv might be destructed with the solver.
+ const cpxenv* cplexEnv() const { return _env.cplexEnv(); }
+
+ /// \brief Returns the const cpxenv pointer
+ ///
+ /// \note The cpxenv might be destructed with the solver.
+ cpxenv* cplexEnv() { return _env.cplexEnv(); }
+
+ /// Returns the cplex problem object
+ cpxlp* cplexLp() { return _prob; }
+ /// Returns the cplex problem object
+ const cpxlp* cplexLp() const { return _prob; }
+
+#ifdef DOXYGEN
+ /// Write the problem or the solution to a file in the given format
+
+ /// This function writes the problem or the solution
+ /// to a file in the given format.
+ /// Trying to write in an unsupported format will trigger
+ /// \ref lemon::LpBase::UnsupportedFormatError "UnsupportedFormatError".
+ /// \param file The file path
+ /// \param format The output file format.
+ /// Supportted formats are "MPS", "LP" and "SOL".
+ void write(std::string file, std::string format = "MPS") const {}
+#endif
+
+ };
+
+ /// \brief Interface for the CPLEX LP solver
+ ///
+ /// This class implements an interface for the CPLEX LP solver.
+ ///\ingroup lp_group
+ class CplexLp : public LpSolver, public CplexBase {
+ public:
+ /// \e
+ CplexLp();
+ /// \e
+ CplexLp(const CplexEnv&);
+ /// \e
+ CplexLp(const CplexLp&);
+ /// \e
+ virtual ~CplexLp();
+
+ /// \e
+ virtual CplexLp* cloneSolver() const;
+ /// \e
+ virtual CplexLp* newSolver() const;
+
+ private:
+
+ // these values cannot retrieved element by element
+ mutable std::vector<int> _col_status;
+ mutable std::vector<int> _row_status;
+
+ mutable std::vector<Value> _primal_ray;
+ mutable std::vector<Value> _dual_ray;
+
+ void _clear_temporals();
+
+ SolveExitStatus convertStatus(int status);
+
+ protected:
+
+ virtual const char* _solverName() const;
+
+ virtual SolveExitStatus _solve();
+ virtual Value _getPrimal(int i) const;
+ virtual Value _getDual(int i) const;
+ virtual Value _getPrimalValue() const;
+
+ virtual VarStatus _getColStatus(int i) const;
+ virtual VarStatus _getRowStatus(int i) const;
+
+ virtual Value _getPrimalRay(int i) const;
+ virtual Value _getDualRay(int i) const;
+
+ virtual ProblemType _getPrimalType() const;
+ virtual ProblemType _getDualType() const;
+
+ public:
+
+ /// Solve with primal simplex method
+ SolveExitStatus solvePrimal();
+
+ /// Solve with dual simplex method
+ SolveExitStatus solveDual();
+
+ /// Solve with barrier method
+ SolveExitStatus solveBarrier();
+
+ };
+
+ /// \brief Interface for the CPLEX MIP solver
+ ///
+ /// This class implements an interface for the CPLEX MIP solver.
+ ///\ingroup lp_group
+ class CplexMip : public MipSolver, public CplexBase {
+ public:
+ /// \e
+ CplexMip();
+ /// \e
+ CplexMip(const CplexEnv&);
+ /// \e
+ CplexMip(const CplexMip&);
+ /// \e
+ virtual ~CplexMip();
+
+ /// \e
+ virtual CplexMip* cloneSolver() const;
+ /// \e
+ virtual CplexMip* newSolver() const;
+
+ protected:
+
+
+ virtual const char* _solverName() const;
+
+ virtual ColTypes _getColType(int col) const;
+ virtual void _setColType(int col, ColTypes col_type);
+
+ virtual SolveExitStatus _solve();
+ virtual ProblemType _getType() const;
+ virtual Value _getSol(int i) const;
+ virtual Value _getSolValue() const;
+
+ };
+
+} //END OF NAMESPACE LEMON
+
+#endif //LEMON_CPLEX_H
+
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/cycle_canceling.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/cycle_canceling.h
new file mode 100644
index 00000000000..646d299e3ec
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/cycle_canceling.h
@@ -0,0 +1,1230 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_CYCLE_CANCELING_H
+#define LEMON_CYCLE_CANCELING_H
+
+/// \ingroup min_cost_flow_algs
+/// \file
+/// \brief Cycle-canceling algorithms for finding a minimum cost flow.
+
+#include <vector>
+#include <limits>
+
+#include <lemon/core.h>
+#include <lemon/maps.h>
+#include <lemon/path.h>
+#include <lemon/math.h>
+#include <lemon/static_graph.h>
+#include <lemon/adaptors.h>
+#include <lemon/circulation.h>
+#include <lemon/bellman_ford.h>
+#include <lemon/howard_mmc.h>
+#include <lemon/hartmann_orlin_mmc.h>
+
+namespace lemon {
+
+ /// \addtogroup min_cost_flow_algs
+ /// @{
+
+ /// \brief Implementation of cycle-canceling algorithms for
+ /// finding a \ref min_cost_flow "minimum cost flow".
+ ///
+ /// \ref CycleCanceling implements three different cycle-canceling
+ /// algorithms for finding a \ref min_cost_flow "minimum cost flow"
+ /// \cite amo93networkflows, \cite klein67primal,
+ /// \cite goldberg89cyclecanceling.
+ /// The most efficent one is the \ref CANCEL_AND_TIGHTEN
+ /// "Cancel-and-Tighten" algorithm, thus it is the default method.
+ /// It runs in strongly polynomial time \f$O(n^2 m^2 \log n)\f$,
+ /// but in practice, it is typically orders of magnitude slower than
+ /// the scaling algorithms and \ref NetworkSimplex.
+ /// (For more information, see \ref min_cost_flow_algs "the module page".)
+ ///
+ /// Most of the parameters of the problem (except for the digraph)
+ /// can be given using separate functions, and the algorithm can be
+ /// executed using the \ref run() function. If some parameters are not
+ /// specified, then default values will be used.
+ ///
+ /// \tparam GR The digraph type the algorithm runs on.
+ /// \tparam V The number type used for flow amounts, capacity bounds
+ /// and supply values in the algorithm. By default, it is \c int.
+ /// \tparam C The number type used for costs and potentials in the
+ /// algorithm. By default, it is the same as \c V.
+ ///
+ /// \warning Both \c V and \c C must be signed number types.
+ /// \warning All input data (capacities, supply values, and costs) must
+ /// be integer.
+ /// \warning This algorithm does not support negative costs for
+ /// arcs having infinite upper bound.
+ ///
+ /// \note For more information about the three available methods,
+ /// see \ref Method.
+#ifdef DOXYGEN
+ template <typename GR, typename V, typename C>
+#else
+ template <typename GR, typename V = int, typename C = V>
+#endif
+ class CycleCanceling
+ {
+ public:
+
+ /// The type of the digraph
+ typedef GR Digraph;
+ /// The type of the flow amounts, capacity bounds and supply values
+ typedef V Value;
+ /// The type of the arc costs
+ typedef C Cost;
+
+ public:
+
+ /// \brief Problem type constants for the \c run() function.
+ ///
+ /// Enum type containing the problem type constants that can be
+ /// returned by the \ref run() function of the algorithm.
+ enum ProblemType {
+ /// The problem has no feasible solution (flow).
+ INFEASIBLE,
+ /// The problem has optimal solution (i.e. it is feasible and
+ /// bounded), and the algorithm has found optimal flow and node
+ /// potentials (primal and dual solutions).
+ OPTIMAL,
+ /// The digraph contains an arc of negative cost and infinite
+ /// upper bound. It means that the objective function is unbounded
+ /// on that arc, however, note that it could actually be bounded
+ /// over the feasible flows, but this algroithm cannot handle
+ /// these cases.
+ UNBOUNDED
+ };
+
+ /// \brief Constants for selecting the used method.
+ ///
+ /// Enum type containing constants for selecting the used method
+ /// for the \ref run() function.
+ ///
+ /// \ref CycleCanceling provides three different cycle-canceling
+ /// methods. By default, \ref CANCEL_AND_TIGHTEN "Cancel-and-Tighten"
+ /// is used, which is by far the most efficient and the most robust.
+ /// However, the other methods can be selected using the \ref run()
+ /// function with the proper parameter.
+ enum Method {
+ /// A simple cycle-canceling method, which uses the
+ /// \ref BellmanFord "Bellman-Ford" algorithm for detecting negative
+ /// cycles in the residual network.
+ /// The number of Bellman-Ford iterations is bounded by a successively
+ /// increased limit.
+ SIMPLE_CYCLE_CANCELING,
+ /// The "Minimum Mean Cycle-Canceling" algorithm, which is a
+ /// well-known strongly polynomial method
+ /// \cite goldberg89cyclecanceling. It improves along a
+ /// \ref min_mean_cycle "minimum mean cycle" in each iteration.
+ /// Its running time complexity is \f$O(n^2 m^3 \log n)\f$.
+ MINIMUM_MEAN_CYCLE_CANCELING,
+ /// The "Cancel-and-Tighten" algorithm, which can be viewed as an
+ /// improved version of the previous method
+ /// \cite goldberg89cyclecanceling.
+ /// It is faster both in theory and in practice, its running time
+ /// complexity is \f$O(n^2 m^2 \log n)\f$.
+ CANCEL_AND_TIGHTEN
+ };
+
+ private:
+
+ TEMPLATE_DIGRAPH_TYPEDEFS(GR);
+
+ typedef std::vector<int> IntVector;
+ typedef std::vector<double> DoubleVector;
+ typedef std::vector<Value> ValueVector;
+ typedef std::vector<Cost> CostVector;
+ typedef std::vector<char> BoolVector;
+ // Note: vector<char> is used instead of vector<bool> for efficiency reasons
+
+ private:
+
+ template <typename KT, typename VT>
+ class StaticVectorMap {
+ public:
+ typedef KT Key;
+ typedef VT Value;
+
+ StaticVectorMap(std::vector<Value>& v) : _v(v) {}
+
+ const Value& operator[](const Key& key) const {
+ return _v[StaticDigraph::id(key)];
+ }
+
+ Value& operator[](const Key& key) {
+ return _v[StaticDigraph::id(key)];
+ }
+
+ void set(const Key& key, const Value& val) {
+ _v[StaticDigraph::id(key)] = val;
+ }
+
+ private:
+ std::vector<Value>& _v;
+ };
+
+ typedef StaticVectorMap<StaticDigraph::Node, Cost> CostNodeMap;
+ typedef StaticVectorMap<StaticDigraph::Arc, Cost> CostArcMap;
+
+ private:
+
+
+ // Data related to the underlying digraph
+ const GR &_graph;
+ int _node_num;
+ int _arc_num;
+ int _res_node_num;
+ int _res_arc_num;
+ int _root;
+
+ // Parameters of the problem
+ bool _has_lower;
+ Value _sum_supply;
+
+ // Data structures for storing the digraph
+ IntNodeMap _node_id;
+ IntArcMap _arc_idf;
+ IntArcMap _arc_idb;
+ IntVector _first_out;
+ BoolVector _forward;
+ IntVector _source;
+ IntVector _target;
+ IntVector _reverse;
+
+ // Node and arc data
+ ValueVector _lower;
+ ValueVector _upper;
+ CostVector _cost;
+ ValueVector _supply;
+
+ ValueVector _res_cap;
+ CostVector _pi;
+
+ // Data for a StaticDigraph structure
+ typedef std::pair<int, int> IntPair;
+ StaticDigraph _sgr;
+ std::vector<IntPair> _arc_vec;
+ std::vector<Cost> _cost_vec;
+ IntVector _id_vec;
+ CostArcMap _cost_map;
+ CostNodeMap _pi_map;
+
+ public:
+
+ /// \brief Constant for infinite upper bounds (capacities).
+ ///
+ /// Constant for infinite upper bounds (capacities).
+ /// It is \c std::numeric_limits<Value>::infinity() if available,
+ /// \c std::numeric_limits<Value>::max() otherwise.
+ const Value INF;
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// The constructor of the class.
+ ///
+ /// \param graph The digraph the algorithm runs on.
+ CycleCanceling(const GR& graph) :
+ _graph(graph), _node_id(graph), _arc_idf(graph), _arc_idb(graph),
+ _cost_map(_cost_vec), _pi_map(_pi),
+ INF(std::numeric_limits<Value>::has_infinity ?
+ std::numeric_limits<Value>::infinity() :
+ std::numeric_limits<Value>::max())
+ {
+ // Check the number types
+ LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
+ "The flow type of CycleCanceling must be signed");
+ LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
+ "The cost type of CycleCanceling must be signed");
+
+ // Reset data structures
+ reset();
+ }
+
+ /// \name Parameters
+ /// The parameters of the algorithm can be specified using these
+ /// functions.
+
+ /// @{
+
+ /// \brief Set the lower bounds on the arcs.
+ ///
+ /// This function sets the lower bounds on the arcs.
+ /// If it is not used before calling \ref run(), the lower bounds
+ /// will be set to zero on all arcs.
+ ///
+ /// \param map An arc map storing the lower bounds.
+ /// Its \c Value type must be convertible to the \c Value type
+ /// of the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ template <typename LowerMap>
+ CycleCanceling& lowerMap(const LowerMap& map) {
+ _has_lower = true;
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ _lower[_arc_idf[a]] = map[a];
+ }
+ return *this;
+ }
+
+ /// \brief Set the upper bounds (capacities) on the arcs.
+ ///
+ /// This function sets the upper bounds (capacities) on the arcs.
+ /// If it is not used before calling \ref run(), the upper bounds
+ /// will be set to \ref INF on all arcs (i.e. the flow value will be
+ /// unbounded from above).
+ ///
+ /// \param map An arc map storing the upper bounds.
+ /// Its \c Value type must be convertible to the \c Value type
+ /// of the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ template<typename UpperMap>
+ CycleCanceling& upperMap(const UpperMap& map) {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ _upper[_arc_idf[a]] = map[a];
+ }
+ return *this;
+ }
+
+ /// \brief Set the costs of the arcs.
+ ///
+ /// This function sets the costs of the arcs.
+ /// If it is not used before calling \ref run(), the costs
+ /// will be set to \c 1 on all arcs.
+ ///
+ /// \param map An arc map storing the costs.
+ /// Its \c Value type must be convertible to the \c Cost type
+ /// of the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ template<typename CostMap>
+ CycleCanceling& costMap(const CostMap& map) {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ _cost[_arc_idf[a]] = map[a];
+ _cost[_arc_idb[a]] = -map[a];
+ }
+ return *this;
+ }
+
+ /// \brief Set the supply values of the nodes.
+ ///
+ /// This function sets the supply values of the nodes.
+ /// If neither this function nor \ref stSupply() is used before
+ /// calling \ref run(), the supply of each node will be set to zero.
+ ///
+ /// \param map A node map storing the supply values.
+ /// Its \c Value type must be convertible to the \c Value type
+ /// of the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ template<typename SupplyMap>
+ CycleCanceling& supplyMap(const SupplyMap& map) {
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ _supply[_node_id[n]] = map[n];
+ }
+ return *this;
+ }
+
+ /// \brief Set single source and target nodes and a supply value.
+ ///
+ /// This function sets a single source node and a single target node
+ /// and the required flow value.
+ /// If neither this function nor \ref supplyMap() is used before
+ /// calling \ref run(), the supply of each node will be set to zero.
+ ///
+ /// Using this function has the same effect as using \ref supplyMap()
+ /// with a map in which \c k is assigned to \c s, \c -k is
+ /// assigned to \c t and all other nodes have zero supply value.
+ ///
+ /// \param s The source node.
+ /// \param t The target node.
+ /// \param k The required amount of flow from node \c s to node \c t
+ /// (i.e. the supply of \c s and the demand of \c t).
+ ///
+ /// \return <tt>(*this)</tt>
+ CycleCanceling& stSupply(const Node& s, const Node& t, Value k) {
+ for (int i = 0; i != _res_node_num; ++i) {
+ _supply[i] = 0;
+ }
+ _supply[_node_id[s]] = k;
+ _supply[_node_id[t]] = -k;
+ return *this;
+ }
+
+ /// @}
+
+ /// \name Execution control
+ /// The algorithm can be executed using \ref run().
+
+ /// @{
+
+ /// \brief Run the algorithm.
+ ///
+ /// This function runs the algorithm.
+ /// The paramters can be specified using functions \ref lowerMap(),
+ /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply().
+ /// For example,
+ /// \code
+ /// CycleCanceling<ListDigraph> cc(graph);
+ /// cc.lowerMap(lower).upperMap(upper).costMap(cost)
+ /// .supplyMap(sup).run();
+ /// \endcode
+ ///
+ /// This function can be called more than once. All the given parameters
+ /// are kept for the next call, unless \ref resetParams() or \ref reset()
+ /// is used, thus only the modified parameters have to be set again.
+ /// If the underlying digraph was also modified after the construction
+ /// of the class (or the last \ref reset() call), then the \ref reset()
+ /// function must be called.
+ ///
+ /// \param method The cycle-canceling method that will be used.
+ /// For more information, see \ref Method.
+ ///
+ /// \return \c INFEASIBLE if no feasible flow exists,
+ /// \n \c OPTIMAL if the problem has optimal solution
+ /// (i.e. it is feasible and bounded), and the algorithm has found
+ /// optimal flow and node potentials (primal and dual solutions),
+ /// \n \c UNBOUNDED if the digraph contains an arc of negative cost
+ /// and infinite upper bound. It means that the objective function
+ /// is unbounded on that arc, however, note that it could actually be
+ /// bounded over the feasible flows, but this algroithm cannot handle
+ /// these cases.
+ ///
+ /// \see ProblemType, Method
+ /// \see resetParams(), reset()
+ ProblemType run(Method method = CANCEL_AND_TIGHTEN) {
+ ProblemType pt = init();
+ if (pt != OPTIMAL) return pt;
+ start(method);
+ return OPTIMAL;
+ }
+
+ /// \brief Reset all the parameters that have been given before.
+ ///
+ /// This function resets all the paramaters that have been given
+ /// before using functions \ref lowerMap(), \ref upperMap(),
+ /// \ref costMap(), \ref supplyMap(), \ref stSupply().
+ ///
+ /// It is useful for multiple \ref run() calls. Basically, all the given
+ /// parameters are kept for the next \ref run() call, unless
+ /// \ref resetParams() or \ref reset() is used.
+ /// If the underlying digraph was also modified after the construction
+ /// of the class or the last \ref reset() call, then the \ref reset()
+ /// function must be used, otherwise \ref resetParams() is sufficient.
+ ///
+ /// For example,
+ /// \code
+ /// CycleCanceling<ListDigraph> cs(graph);
+ ///
+ /// // First run
+ /// cc.lowerMap(lower).upperMap(upper).costMap(cost)
+ /// .supplyMap(sup).run();
+ ///
+ /// // Run again with modified cost map (resetParams() is not called,
+ /// // so only the cost map have to be set again)
+ /// cost[e] += 100;
+ /// cc.costMap(cost).run();
+ ///
+ /// // Run again from scratch using resetParams()
+ /// // (the lower bounds will be set to zero on all arcs)
+ /// cc.resetParams();
+ /// cc.upperMap(capacity).costMap(cost)
+ /// .supplyMap(sup).run();
+ /// \endcode
+ ///
+ /// \return <tt>(*this)</tt>
+ ///
+ /// \see reset(), run()
+ CycleCanceling& resetParams() {
+ for (int i = 0; i != _res_node_num; ++i) {
+ _supply[i] = 0;
+ }
+ int limit = _first_out[_root];
+ for (int j = 0; j != limit; ++j) {
+ _lower[j] = 0;
+ _upper[j] = INF;
+ _cost[j] = _forward[j] ? 1 : -1;
+ }
+ for (int j = limit; j != _res_arc_num; ++j) {
+ _lower[j] = 0;
+ _upper[j] = INF;
+ _cost[j] = 0;
+ _cost[_reverse[j]] = 0;
+ }
+ _has_lower = false;
+ return *this;
+ }
+
+ /// \brief Reset the internal data structures and all the parameters
+ /// that have been given before.
+ ///
+ /// This function resets the internal data structures and all the
+ /// paramaters that have been given before using functions \ref lowerMap(),
+ /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply().
+ ///
+ /// It is useful for multiple \ref run() calls. Basically, all the given
+ /// parameters are kept for the next \ref run() call, unless
+ /// \ref resetParams() or \ref reset() is used.
+ /// If the underlying digraph was also modified after the construction
+ /// of the class or the last \ref reset() call, then the \ref reset()
+ /// function must be used, otherwise \ref resetParams() is sufficient.
+ ///
+ /// See \ref resetParams() for examples.
+ ///
+ /// \return <tt>(*this)</tt>
+ ///
+ /// \see resetParams(), run()
+ CycleCanceling& reset() {
+ // Resize vectors
+ _node_num = countNodes(_graph);
+ _arc_num = countArcs(_graph);
+ _res_node_num = _node_num + 1;
+ _res_arc_num = 2 * (_arc_num + _node_num);
+ _root = _node_num;
+
+ _first_out.resize(_res_node_num + 1);
+ _forward.resize(_res_arc_num);
+ _source.resize(_res_arc_num);
+ _target.resize(_res_arc_num);
+ _reverse.resize(_res_arc_num);
+
+ _lower.resize(_res_arc_num);
+ _upper.resize(_res_arc_num);
+ _cost.resize(_res_arc_num);
+ _supply.resize(_res_node_num);
+
+ _res_cap.resize(_res_arc_num);
+ _pi.resize(_res_node_num);
+
+ _arc_vec.reserve(_res_arc_num);
+ _cost_vec.reserve(_res_arc_num);
+ _id_vec.reserve(_res_arc_num);
+
+ // Copy the graph
+ int i = 0, j = 0, k = 2 * _arc_num + _node_num;
+ for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
+ _node_id[n] = i;
+ }
+ i = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
+ _first_out[i] = j;
+ for (OutArcIt a(_graph, n); a != INVALID; ++a, ++j) {
+ _arc_idf[a] = j;
+ _forward[j] = true;
+ _source[j] = i;
+ _target[j] = _node_id[_graph.runningNode(a)];
+ }
+ for (InArcIt a(_graph, n); a != INVALID; ++a, ++j) {
+ _arc_idb[a] = j;
+ _forward[j] = false;
+ _source[j] = i;
+ _target[j] = _node_id[_graph.runningNode(a)];
+ }
+ _forward[j] = false;
+ _source[j] = i;
+ _target[j] = _root;
+ _reverse[j] = k;
+ _forward[k] = true;
+ _source[k] = _root;
+ _target[k] = i;
+ _reverse[k] = j;
+ ++j; ++k;
+ }
+ _first_out[i] = j;
+ _first_out[_res_node_num] = k;
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ int fi = _arc_idf[a];
+ int bi = _arc_idb[a];
+ _reverse[fi] = bi;
+ _reverse[bi] = fi;
+ }
+
+ // Reset parameters
+ resetParams();
+ return *this;
+ }
+
+ /// @}
+
+ /// \name Query Functions
+ /// The results of the algorithm can be obtained using these
+ /// functions.\n
+ /// The \ref run() function must be called before using them.
+
+ /// @{
+
+ /// \brief Return the total cost of the found flow.
+ ///
+ /// This function returns the total cost of the found flow.
+ /// Its complexity is O(m).
+ ///
+ /// \note The return type of the function can be specified as a
+ /// template parameter. For example,
+ /// \code
+ /// cc.totalCost<double>();
+ /// \endcode
+ /// It is useful if the total cost cannot be stored in the \c Cost
+ /// type of the algorithm, which is the default return type of the
+ /// function.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ template <typename Number>
+ Number totalCost() const {
+ Number c = 0;
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ int i = _arc_idb[a];
+ c += static_cast<Number>(_res_cap[i]) *
+ (-static_cast<Number>(_cost[i]));
+ }
+ return c;
+ }
+
+#ifndef DOXYGEN
+ Cost totalCost() const {
+ return totalCost<Cost>();
+ }
+#endif
+
+ /// \brief Return the flow on the given arc.
+ ///
+ /// This function returns the flow on the given arc.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ Value flow(const Arc& a) const {
+ return _res_cap[_arc_idb[a]];
+ }
+
+ /// \brief Copy the flow values (the primal solution) into the
+ /// given map.
+ ///
+ /// This function copies the flow value on each arc into the given
+ /// map. The \c Value type of the algorithm must be convertible to
+ /// the \c Value type of the map.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ template <typename FlowMap>
+ void flowMap(FlowMap &map) const {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ map.set(a, _res_cap[_arc_idb[a]]);
+ }
+ }
+
+ /// \brief Return the potential (dual value) of the given node.
+ ///
+ /// This function returns the potential (dual value) of the
+ /// given node.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ Cost potential(const Node& n) const {
+ return static_cast<Cost>(_pi[_node_id[n]]);
+ }
+
+ /// \brief Copy the potential values (the dual solution) into the
+ /// given map.
+ ///
+ /// This function copies the potential (dual value) of each node
+ /// into the given map.
+ /// The \c Cost type of the algorithm must be convertible to the
+ /// \c Value type of the map.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ template <typename PotentialMap>
+ void potentialMap(PotentialMap &map) const {
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ map.set(n, static_cast<Cost>(_pi[_node_id[n]]));
+ }
+ }
+
+ /// @}
+
+ private:
+
+ // Initialize the algorithm
+ ProblemType init() {
+ if (_res_node_num <= 1) return INFEASIBLE;
+
+ // Check the sum of supply values
+ _sum_supply = 0;
+ for (int i = 0; i != _root; ++i) {
+ _sum_supply += _supply[i];
+ }
+ if (_sum_supply > 0) return INFEASIBLE;
+
+ // Check lower and upper bounds
+ LEMON_DEBUG(checkBoundMaps(),
+ "Upper bounds must be greater or equal to the lower bounds");
+
+
+ // Initialize vectors
+ for (int i = 0; i != _res_node_num; ++i) {
+ _pi[i] = 0;
+ }
+ ValueVector excess(_supply);
+
+ // Remove infinite upper bounds and check negative arcs
+ const Value MAX = std::numeric_limits<Value>::max();
+ int last_out;
+ if (_has_lower) {
+ for (int i = 0; i != _root; ++i) {
+ last_out = _first_out[i+1];
+ for (int j = _first_out[i]; j != last_out; ++j) {
+ if (_forward[j]) {
+ Value c = _cost[j] < 0 ? _upper[j] : _lower[j];
+ if (c >= MAX) return UNBOUNDED;
+ excess[i] -= c;
+ excess[_target[j]] += c;
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i != _root; ++i) {
+ last_out = _first_out[i+1];
+ for (int j = _first_out[i]; j != last_out; ++j) {
+ if (_forward[j] && _cost[j] < 0) {
+ Value c = _upper[j];
+ if (c >= MAX) return UNBOUNDED;
+ excess[i] -= c;
+ excess[_target[j]] += c;
+ }
+ }
+ }
+ }
+ Value ex, max_cap = 0;
+ for (int i = 0; i != _res_node_num; ++i) {
+ ex = excess[i];
+ if (ex < 0) max_cap -= ex;
+ }
+ for (int j = 0; j != _res_arc_num; ++j) {
+ if (_upper[j] >= MAX) _upper[j] = max_cap;
+ }
+
+ // Initialize maps for Circulation and remove non-zero lower bounds
+ ConstMap<Arc, Value> low(0);
+ typedef typename Digraph::template ArcMap<Value> ValueArcMap;
+ typedef typename Digraph::template NodeMap<Value> ValueNodeMap;
+ ValueArcMap cap(_graph), flow(_graph);
+ ValueNodeMap sup(_graph);
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ sup[n] = _supply[_node_id[n]];
+ }
+ if (_has_lower) {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ int j = _arc_idf[a];
+ Value c = _lower[j];
+ cap[a] = _upper[j] - c;
+ sup[_graph.source(a)] -= c;
+ sup[_graph.target(a)] += c;
+ }
+ } else {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ cap[a] = _upper[_arc_idf[a]];
+ }
+ }
+
+ // Find a feasible flow using Circulation
+ Circulation<Digraph, ConstMap<Arc, Value>, ValueArcMap, ValueNodeMap>
+ circ(_graph, low, cap, sup);
+ if (!circ.flowMap(flow).run()) return INFEASIBLE;
+
+ // Set residual capacities and handle GEQ supply type
+ if (_sum_supply < 0) {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ Value fa = flow[a];
+ _res_cap[_arc_idf[a]] = cap[a] - fa;
+ _res_cap[_arc_idb[a]] = fa;
+ sup[_graph.source(a)] -= fa;
+ sup[_graph.target(a)] += fa;
+ }
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ excess[_node_id[n]] = sup[n];
+ }
+ for (int a = _first_out[_root]; a != _res_arc_num; ++a) {
+ int u = _target[a];
+ int ra = _reverse[a];
+ _res_cap[a] = -_sum_supply + 1;
+ _res_cap[ra] = -excess[u];
+ _cost[a] = 0;
+ _cost[ra] = 0;
+ }
+ } else {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ Value fa = flow[a];
+ _res_cap[_arc_idf[a]] = cap[a] - fa;
+ _res_cap[_arc_idb[a]] = fa;
+ }
+ for (int a = _first_out[_root]; a != _res_arc_num; ++a) {
+ int ra = _reverse[a];
+ _res_cap[a] = 1;
+ _res_cap[ra] = 0;
+ _cost[a] = 0;
+ _cost[ra] = 0;
+ }
+ }
+
+ return OPTIMAL;
+ }
+
+ // Check if the upper bound is greater than or equal to the lower bound
+ // on each forward arc.
+ bool checkBoundMaps() {
+ for (int j = 0; j != _res_arc_num; ++j) {
+ if (_forward[j] && _upper[j] < _lower[j]) return false;
+ }
+ return true;
+ }
+
+ // Build a StaticDigraph structure containing the current
+ // residual network
+ void buildResidualNetwork() {
+ _arc_vec.clear();
+ _cost_vec.clear();
+ _id_vec.clear();
+ for (int j = 0; j != _res_arc_num; ++j) {
+ if (_res_cap[j] > 0) {
+ _arc_vec.push_back(IntPair(_source[j], _target[j]));
+ _cost_vec.push_back(_cost[j]);
+ _id_vec.push_back(j);
+ }
+ }
+ _sgr.build(_res_node_num, _arc_vec.begin(), _arc_vec.end());
+ }
+
+ // Execute the algorithm and transform the results
+ void start(Method method) {
+ // Execute the algorithm
+ switch (method) {
+ case SIMPLE_CYCLE_CANCELING:
+ startSimpleCycleCanceling();
+ break;
+ case MINIMUM_MEAN_CYCLE_CANCELING:
+ startMinMeanCycleCanceling();
+ break;
+ case CANCEL_AND_TIGHTEN:
+ startCancelAndTighten();
+ break;
+ }
+
+ // Compute node potentials
+ if (method != SIMPLE_CYCLE_CANCELING) {
+ buildResidualNetwork();
+ typename BellmanFord<StaticDigraph, CostArcMap>
+ ::template SetDistMap<CostNodeMap>::Create bf(_sgr, _cost_map);
+ bf.distMap(_pi_map);
+ bf.init(0);
+ bf.start();
+ }
+
+ // Handle non-zero lower bounds
+ if (_has_lower) {
+ int limit = _first_out[_root];
+ for (int j = 0; j != limit; ++j) {
+ if (_forward[j]) _res_cap[_reverse[j]] += _lower[j];
+ }
+ }
+ }
+
+ // Execute the "Simple Cycle Canceling" method
+ void startSimpleCycleCanceling() {
+ // Constants for computing the iteration limits
+ const int BF_FIRST_LIMIT = 2;
+ const double BF_LIMIT_FACTOR = 1.5;
+
+ typedef StaticVectorMap<StaticDigraph::Arc, Value> FilterMap;
+ typedef FilterArcs<StaticDigraph, FilterMap> ResDigraph;
+ typedef StaticVectorMap<StaticDigraph::Node, StaticDigraph::Arc> PredMap;
+ typedef typename BellmanFord<ResDigraph, CostArcMap>
+ ::template SetDistMap<CostNodeMap>
+ ::template SetPredMap<PredMap>::Create BF;
+
+ // Build the residual network
+ _arc_vec.clear();
+ _cost_vec.clear();
+ for (int j = 0; j != _res_arc_num; ++j) {
+ _arc_vec.push_back(IntPair(_source[j], _target[j]));
+ _cost_vec.push_back(_cost[j]);
+ }
+ _sgr.build(_res_node_num, _arc_vec.begin(), _arc_vec.end());
+
+ FilterMap filter_map(_res_cap);
+ ResDigraph rgr(_sgr, filter_map);
+ std::vector<int> cycle;
+ std::vector<StaticDigraph::Arc> pred(_res_arc_num);
+ PredMap pred_map(pred);
+ BF bf(rgr, _cost_map);
+ bf.distMap(_pi_map).predMap(pred_map);
+
+ int length_bound = BF_FIRST_LIMIT;
+ bool optimal = false;
+ while (!optimal) {
+ bf.init(0);
+ int iter_num = 0;
+ bool cycle_found = false;
+ while (!cycle_found) {
+ // Perform some iterations of the Bellman-Ford algorithm
+ int curr_iter_num = iter_num + length_bound <= _node_num ?
+ length_bound : _node_num - iter_num;
+ iter_num += curr_iter_num;
+ int real_iter_num = curr_iter_num;
+ for (int i = 0; i < curr_iter_num; ++i) {
+ if (bf.processNextWeakRound()) {
+ real_iter_num = i;
+ break;
+ }
+ }
+ if (real_iter_num < curr_iter_num) {
+ // Optimal flow is found
+ optimal = true;
+ break;
+ } else {
+ // Search for node disjoint negative cycles
+ std::vector<int> state(_res_node_num, 0);
+ int id = 0;
+ for (int u = 0; u != _res_node_num; ++u) {
+ if (state[u] != 0) continue;
+ ++id;
+ int v = u;
+ for (; v != -1 && state[v] == 0; v = pred[v] == INVALID ?
+ -1 : rgr.id(rgr.source(pred[v]))) {
+ state[v] = id;
+ }
+ if (v != -1 && state[v] == id) {
+ // A negative cycle is found
+ cycle_found = true;
+ cycle.clear();
+ StaticDigraph::Arc a = pred[v];
+ Value d, delta = _res_cap[rgr.id(a)];
+ cycle.push_back(rgr.id(a));
+ while (rgr.id(rgr.source(a)) != v) {
+ a = pred_map[rgr.source(a)];
+ d = _res_cap[rgr.id(a)];
+ if (d < delta) delta = d;
+ cycle.push_back(rgr.id(a));
+ }
+
+ // Augment along the cycle
+ for (int i = 0; i < int(cycle.size()); ++i) {
+ int j = cycle[i];
+ _res_cap[j] -= delta;
+ _res_cap[_reverse[j]] += delta;
+ }
+ }
+ }
+ }
+
+ // Increase iteration limit if no cycle is found
+ if (!cycle_found) {
+ length_bound = static_cast<int>(length_bound * BF_LIMIT_FACTOR);
+ }
+ }
+ }
+ }
+
+ // Execute the "Minimum Mean Cycle Canceling" method
+ void startMinMeanCycleCanceling() {
+ typedef Path<StaticDigraph> SPath;
+ typedef typename SPath::ArcIt SPathArcIt;
+ typedef typename HowardMmc<StaticDigraph, CostArcMap>
+ ::template SetPath<SPath>::Create HwMmc;
+ typedef typename HartmannOrlinMmc<StaticDigraph, CostArcMap>
+ ::template SetPath<SPath>::Create HoMmc;
+
+ const double HW_ITER_LIMIT_FACTOR = 1.0;
+ const int HW_ITER_LIMIT_MIN_VALUE = 5;
+
+ const int hw_iter_limit =
+ std::max(static_cast<int>(HW_ITER_LIMIT_FACTOR * _node_num),
+ HW_ITER_LIMIT_MIN_VALUE);
+
+ SPath cycle;
+ HwMmc hw_mmc(_sgr, _cost_map);
+ hw_mmc.cycle(cycle);
+ buildResidualNetwork();
+ while (true) {
+
+ typename HwMmc::TerminationCause hw_tc =
+ hw_mmc.findCycleMean(hw_iter_limit);
+ if (hw_tc == HwMmc::ITERATION_LIMIT) {
+ // Howard's algorithm reached the iteration limit, start a
+ // strongly polynomial algorithm instead
+ HoMmc ho_mmc(_sgr, _cost_map);
+ ho_mmc.cycle(cycle);
+ // Find a minimum mean cycle (Hartmann-Orlin algorithm)
+ if (!(ho_mmc.findCycleMean() && ho_mmc.cycleCost() < 0)) break;
+ ho_mmc.findCycle();
+ } else {
+ // Find a minimum mean cycle (Howard algorithm)
+ if (!(hw_tc == HwMmc::OPTIMAL && hw_mmc.cycleCost() < 0)) break;
+ hw_mmc.findCycle();
+ }
+
+ // Compute delta value
+ Value delta = INF;
+ for (SPathArcIt a(cycle); a != INVALID; ++a) {
+ Value d = _res_cap[_id_vec[_sgr.id(a)]];
+ if (d < delta) delta = d;
+ }
+
+ // Augment along the cycle
+ for (SPathArcIt a(cycle); a != INVALID; ++a) {
+ int j = _id_vec[_sgr.id(a)];
+ _res_cap[j] -= delta;
+ _res_cap[_reverse[j]] += delta;
+ }
+
+ // Rebuild the residual network
+ buildResidualNetwork();
+ }
+ }
+
+ // Execute the "Cancel-and-Tighten" method
+ void startCancelAndTighten() {
+ // Constants for the min mean cycle computations
+ const double LIMIT_FACTOR = 1.0;
+ const int MIN_LIMIT = 5;
+ const double HW_ITER_LIMIT_FACTOR = 1.0;
+ const int HW_ITER_LIMIT_MIN_VALUE = 5;
+
+ const int hw_iter_limit =
+ std::max(static_cast<int>(HW_ITER_LIMIT_FACTOR * _node_num),
+ HW_ITER_LIMIT_MIN_VALUE);
+
+ // Contruct auxiliary data vectors
+ DoubleVector pi(_res_node_num, 0.0);
+ IntVector level(_res_node_num);
+ BoolVector reached(_res_node_num);
+ BoolVector processed(_res_node_num);
+ IntVector pred_node(_res_node_num);
+ IntVector pred_arc(_res_node_num);
+ std::vector<int> stack(_res_node_num);
+ std::vector<int> proc_vector(_res_node_num);
+
+ // Initialize epsilon
+ double epsilon = 0;
+ for (int a = 0; a != _res_arc_num; ++a) {
+ if (_res_cap[a] > 0 && -_cost[a] > epsilon)
+ epsilon = -_cost[a];
+ }
+
+ // Start phases
+ Tolerance<double> tol;
+ tol.epsilon(1e-6);
+ int limit = int(LIMIT_FACTOR * std::sqrt(double(_res_node_num)));
+ if (limit < MIN_LIMIT) limit = MIN_LIMIT;
+ int iter = limit;
+ while (epsilon * _res_node_num >= 1) {
+ // Find and cancel cycles in the admissible network using DFS
+ for (int u = 0; u != _res_node_num; ++u) {
+ reached[u] = false;
+ processed[u] = false;
+ }
+ int stack_head = -1;
+ int proc_head = -1;
+ for (int start = 0; start != _res_node_num; ++start) {
+ if (reached[start]) continue;
+
+ // New start node
+ reached[start] = true;
+ pred_arc[start] = -1;
+ pred_node[start] = -1;
+
+ // Find the first admissible outgoing arc
+ double p = pi[start];
+ int a = _first_out[start];
+ int last_out = _first_out[start+1];
+ for (; a != last_out && (_res_cap[a] == 0 ||
+ !tol.negative(_cost[a] + p - pi[_target[a]])); ++a) ;
+ if (a == last_out) {
+ processed[start] = true;
+ proc_vector[++proc_head] = start;
+ continue;
+ }
+ stack[++stack_head] = a;
+
+ while (stack_head >= 0) {
+ int sa = stack[stack_head];
+ int u = _source[sa];
+ int v = _target[sa];
+
+ if (!reached[v]) {
+ // A new node is reached
+ reached[v] = true;
+ pred_node[v] = u;
+ pred_arc[v] = sa;
+ p = pi[v];
+ a = _first_out[v];
+ last_out = _first_out[v+1];
+ for (; a != last_out && (_res_cap[a] == 0 ||
+ !tol.negative(_cost[a] + p - pi[_target[a]])); ++a) ;
+ stack[++stack_head] = a == last_out ? -1 : a;
+ } else {
+ if (!processed[v]) {
+ // A cycle is found
+ int n, w = u;
+ Value d, delta = _res_cap[sa];
+ for (n = u; n != v; n = pred_node[n]) {
+ d = _res_cap[pred_arc[n]];
+ if (d <= delta) {
+ delta = d;
+ w = pred_node[n];
+ }
+ }
+
+ // Augment along the cycle
+ _res_cap[sa] -= delta;
+ _res_cap[_reverse[sa]] += delta;
+ for (n = u; n != v; n = pred_node[n]) {
+ int pa = pred_arc[n];
+ _res_cap[pa] -= delta;
+ _res_cap[_reverse[pa]] += delta;
+ }
+ for (n = u; stack_head > 0 && n != w; n = pred_node[n]) {
+ --stack_head;
+ reached[n] = false;
+ }
+ u = w;
+ }
+ v = u;
+
+ // Find the next admissible outgoing arc
+ p = pi[v];
+ a = stack[stack_head] + 1;
+ last_out = _first_out[v+1];
+ for (; a != last_out && (_res_cap[a] == 0 ||
+ !tol.negative(_cost[a] + p - pi[_target[a]])); ++a) ;
+ stack[stack_head] = a == last_out ? -1 : a;
+ }
+
+ while (stack_head >= 0 && stack[stack_head] == -1) {
+ processed[v] = true;
+ proc_vector[++proc_head] = v;
+ if (--stack_head >= 0) {
+ // Find the next admissible outgoing arc
+ v = _source[stack[stack_head]];
+ p = pi[v];
+ a = stack[stack_head] + 1;
+ last_out = _first_out[v+1];
+ for (; a != last_out && (_res_cap[a] == 0 ||
+ !tol.negative(_cost[a] + p - pi[_target[a]])); ++a) ;
+ stack[stack_head] = a == last_out ? -1 : a;
+ }
+ }
+ }
+ }
+
+ // Tighten potentials and epsilon
+ if (--iter > 0) {
+ for (int u = 0; u != _res_node_num; ++u) {
+ level[u] = 0;
+ }
+ for (int i = proc_head; i > 0; --i) {
+ int u = proc_vector[i];
+ double p = pi[u];
+ int l = level[u] + 1;
+ int last_out = _first_out[u+1];
+ for (int a = _first_out[u]; a != last_out; ++a) {
+ int v = _target[a];
+ if (_res_cap[a] > 0 && tol.negative(_cost[a] + p - pi[v]) &&
+ l > level[v]) level[v] = l;
+ }
+ }
+
+ // Modify potentials
+ double q = std::numeric_limits<double>::max();
+ for (int u = 0; u != _res_node_num; ++u) {
+ int lu = level[u];
+ double p, pu = pi[u];
+ int last_out = _first_out[u+1];
+ for (int a = _first_out[u]; a != last_out; ++a) {
+ if (_res_cap[a] == 0) continue;
+ int v = _target[a];
+ int ld = lu - level[v];
+ if (ld > 0) {
+ p = (_cost[a] + pu - pi[v] + epsilon) / (ld + 1);
+ if (p < q) q = p;
+ }
+ }
+ }
+ for (int u = 0; u != _res_node_num; ++u) {
+ pi[u] -= q * level[u];
+ }
+
+ // Modify epsilon
+ epsilon = 0;
+ for (int u = 0; u != _res_node_num; ++u) {
+ double curr, pu = pi[u];
+ int last_out = _first_out[u+1];
+ for (int a = _first_out[u]; a != last_out; ++a) {
+ if (_res_cap[a] == 0) continue;
+ curr = _cost[a] + pu - pi[_target[a]];
+ if (-curr > epsilon) epsilon = -curr;
+ }
+ }
+ } else {
+ typedef HowardMmc<StaticDigraph, CostArcMap> HwMmc;
+ typedef HartmannOrlinMmc<StaticDigraph, CostArcMap> HoMmc;
+ typedef typename BellmanFord<StaticDigraph, CostArcMap>
+ ::template SetDistMap<CostNodeMap>::Create BF;
+
+ // Set epsilon to the minimum cycle mean
+ Cost cycle_cost = 0;
+ int cycle_size = 1;
+ buildResidualNetwork();
+ HwMmc hw_mmc(_sgr, _cost_map);
+ if (hw_mmc.findCycleMean(hw_iter_limit) == HwMmc::ITERATION_LIMIT) {
+ // Howard's algorithm reached the iteration limit, start a
+ // strongly polynomial algorithm instead
+ HoMmc ho_mmc(_sgr, _cost_map);
+ ho_mmc.findCycleMean();
+ epsilon = -ho_mmc.cycleMean();
+ cycle_cost = ho_mmc.cycleCost();
+ cycle_size = ho_mmc.cycleSize();
+ } else {
+ // Set epsilon
+ epsilon = -hw_mmc.cycleMean();
+ cycle_cost = hw_mmc.cycleCost();
+ cycle_size = hw_mmc.cycleSize();
+ }
+
+ // Compute feasible potentials for the current epsilon
+ for (int i = 0; i != int(_cost_vec.size()); ++i) {
+ _cost_vec[i] = cycle_size * _cost_vec[i] - cycle_cost;
+ }
+ BF bf(_sgr, _cost_map);
+ bf.distMap(_pi_map);
+ bf.init(0);
+ bf.start();
+ for (int u = 0; u != _res_node_num; ++u) {
+ pi[u] = static_cast<double>(_pi[u]) / cycle_size;
+ }
+
+ iter = limit;
+ }
+ }
+ }
+
+ }; //class CycleCanceling
+
+ ///@}
+
+} //namespace lemon
+
+#endif //LEMON_CYCLE_CANCELING_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/dfs.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/dfs.h
new file mode 100644
index 00000000000..6e9e84a4892
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/dfs.h
@@ -0,0 +1,1637 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_DFS_H
+#define LEMON_DFS_H
+
+///\ingroup search
+///\file
+///\brief DFS algorithm.
+
+#include <lemon/list_graph.h>
+#include <lemon/bits/path_dump.h>
+#include <lemon/core.h>
+#include <lemon/error.h>
+#include <lemon/maps.h>
+#include <lemon/path.h>
+
+namespace lemon {
+
+ ///Default traits class of Dfs class.
+
+ ///Default traits class of Dfs class.
+ ///\tparam GR Digraph type.
+ template<class GR>
+ struct DfsDefaultTraits
+ {
+ ///The type of the digraph the algorithm runs on.
+ typedef GR Digraph;
+
+ ///\brief The type of the map that stores the predecessor
+ ///arcs of the %DFS paths.
+ ///
+ ///The type of the map that stores the predecessor
+ ///arcs of the %DFS paths.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ typedef typename Digraph::template NodeMap<typename Digraph::Arc> PredMap;
+ ///Instantiates a \c PredMap.
+
+ ///This function instantiates a \ref PredMap.
+ ///\param g is the digraph, to which we would like to define the
+ ///\ref PredMap.
+ static PredMap *createPredMap(const Digraph &g)
+ {
+ return new PredMap(g);
+ }
+
+ ///The type of the map that indicates which nodes are processed.
+
+ ///The type of the map that indicates which nodes are processed.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ ///By default, it is a NullMap.
+ typedef NullMap<typename Digraph::Node,bool> ProcessedMap;
+ ///Instantiates a \c ProcessedMap.
+
+ ///This function instantiates a \ref ProcessedMap.
+ ///\param g is the digraph, to which
+ ///we would like to define the \ref ProcessedMap.
+#ifdef DOXYGEN
+ static ProcessedMap *createProcessedMap(const Digraph &g)
+#else
+ static ProcessedMap *createProcessedMap(const Digraph &)
+#endif
+ {
+ return new ProcessedMap();
+ }
+
+ ///The type of the map that indicates which nodes are reached.
+
+ ///The type of the map that indicates which nodes are reached.
+ ///It must conform to
+ ///the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
+ typedef typename Digraph::template NodeMap<bool> ReachedMap;
+ ///Instantiates a \c ReachedMap.
+
+ ///This function instantiates a \ref ReachedMap.
+ ///\param g is the digraph, to which
+ ///we would like to define the \ref ReachedMap.
+ static ReachedMap *createReachedMap(const Digraph &g)
+ {
+ return new ReachedMap(g);
+ }
+
+ ///The type of the map that stores the distances of the nodes.
+
+ ///The type of the map that stores the distances of the nodes.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ typedef typename Digraph::template NodeMap<int> DistMap;
+ ///Instantiates a \c DistMap.
+
+ ///This function instantiates a \ref DistMap.
+ ///\param g is the digraph, to which we would like to define the
+ ///\ref DistMap.
+ static DistMap *createDistMap(const Digraph &g)
+ {
+ return new DistMap(g);
+ }
+ };
+
+ ///%DFS algorithm class.
+
+ ///\ingroup search
+ ///This class provides an efficient implementation of the %DFS algorithm.
+ ///
+ ///There is also a \ref dfs() "function-type interface" for the DFS
+ ///algorithm, which is convenient in the simplier cases and it can be
+ ///used easier.
+ ///
+ ///\tparam GR The type of the digraph the algorithm runs on.
+ ///The default type is \ref ListDigraph.
+ ///\tparam TR The traits class that defines various types used by the
+ ///algorithm. By default, it is \ref DfsDefaultTraits
+ ///"DfsDefaultTraits<GR>".
+ ///In most cases, this parameter should not be set directly,
+ ///consider to use the named template parameters instead.
+#ifdef DOXYGEN
+ template <typename GR,
+ typename TR>
+#else
+ template <typename GR=ListDigraph,
+ typename TR=DfsDefaultTraits<GR> >
+#endif
+ class Dfs {
+ public:
+
+ ///The type of the digraph the algorithm runs on.
+ typedef typename TR::Digraph Digraph;
+
+ ///\brief The type of the map that stores the predecessor arcs of the
+ ///DFS paths.
+ typedef typename TR::PredMap PredMap;
+ ///The type of the map that stores the distances of the nodes.
+ typedef typename TR::DistMap DistMap;
+ ///The type of the map that indicates which nodes are reached.
+ typedef typename TR::ReachedMap ReachedMap;
+ ///The type of the map that indicates which nodes are processed.
+ typedef typename TR::ProcessedMap ProcessedMap;
+ ///The type of the paths.
+ typedef PredMapPath<Digraph, PredMap> Path;
+
+ ///The \ref lemon::DfsDefaultTraits "traits class" of the algorithm.
+ typedef TR Traits;
+
+ private:
+
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::NodeIt NodeIt;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::OutArcIt OutArcIt;
+
+ //Pointer to the underlying digraph.
+ const Digraph *G;
+ //Pointer to the map of predecessor arcs.
+ PredMap *_pred;
+ //Indicates if _pred is locally allocated (true) or not.
+ bool local_pred;
+ //Pointer to the map of distances.
+ DistMap *_dist;
+ //Indicates if _dist is locally allocated (true) or not.
+ bool local_dist;
+ //Pointer to the map of reached status of the nodes.
+ ReachedMap *_reached;
+ //Indicates if _reached is locally allocated (true) or not.
+ bool local_reached;
+ //Pointer to the map of processed status of the nodes.
+ ProcessedMap *_processed;
+ //Indicates if _processed is locally allocated (true) or not.
+ bool local_processed;
+
+ std::vector<typename Digraph::OutArcIt> _stack;
+ int _stack_head;
+
+ //Creates the maps if necessary.
+ void create_maps()
+ {
+ if(!_pred) {
+ local_pred = true;
+ _pred = Traits::createPredMap(*G);
+ }
+ if(!_dist) {
+ local_dist = true;
+ _dist = Traits::createDistMap(*G);
+ }
+ if(!_reached) {
+ local_reached = true;
+ _reached = Traits::createReachedMap(*G);
+ }
+ if(!_processed) {
+ local_processed = true;
+ _processed = Traits::createProcessedMap(*G);
+ }
+ }
+
+ protected:
+
+ Dfs() {}
+
+ public:
+
+ typedef Dfs Create;
+
+ ///\name Named Template Parameters
+
+ ///@{
+
+ template <class T>
+ struct SetPredMapTraits : public Traits {
+ typedef T PredMap;
+ static PredMap *createPredMap(const Digraph &)
+ {
+ LEMON_ASSERT(false, "PredMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///\c PredMap type.
+ ///
+ ///\ref named-templ-param "Named parameter" for setting
+ ///\c PredMap type.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ template <class T>
+ struct SetPredMap : public Dfs<Digraph, SetPredMapTraits<T> > {
+ typedef Dfs<Digraph, SetPredMapTraits<T> > Create;
+ };
+
+ template <class T>
+ struct SetDistMapTraits : public Traits {
+ typedef T DistMap;
+ static DistMap *createDistMap(const Digraph &)
+ {
+ LEMON_ASSERT(false, "DistMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///\c DistMap type.
+ ///
+ ///\ref named-templ-param "Named parameter" for setting
+ ///\c DistMap type.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ template <class T>
+ struct SetDistMap : public Dfs< Digraph, SetDistMapTraits<T> > {
+ typedef Dfs<Digraph, SetDistMapTraits<T> > Create;
+ };
+
+ template <class T>
+ struct SetReachedMapTraits : public Traits {
+ typedef T ReachedMap;
+ static ReachedMap *createReachedMap(const Digraph &)
+ {
+ LEMON_ASSERT(false, "ReachedMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///\c ReachedMap type.
+ ///
+ ///\ref named-templ-param "Named parameter" for setting
+ ///\c ReachedMap type.
+ ///It must conform to
+ ///the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
+ template <class T>
+ struct SetReachedMap : public Dfs< Digraph, SetReachedMapTraits<T> > {
+ typedef Dfs< Digraph, SetReachedMapTraits<T> > Create;
+ };
+
+ template <class T>
+ struct SetProcessedMapTraits : public Traits {
+ typedef T ProcessedMap;
+ static ProcessedMap *createProcessedMap(const Digraph &)
+ {
+ LEMON_ASSERT(false, "ProcessedMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///\c ProcessedMap type.
+ ///
+ ///\ref named-templ-param "Named parameter" for setting
+ ///\c ProcessedMap type.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ template <class T>
+ struct SetProcessedMap : public Dfs< Digraph, SetProcessedMapTraits<T> > {
+ typedef Dfs< Digraph, SetProcessedMapTraits<T> > Create;
+ };
+
+ struct SetStandardProcessedMapTraits : public Traits {
+ typedef typename Digraph::template NodeMap<bool> ProcessedMap;
+ static ProcessedMap *createProcessedMap(const Digraph &g)
+ {
+ return new ProcessedMap(g);
+ }
+ };
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///\c ProcessedMap type to be <tt>Digraph::NodeMap<bool></tt>.
+ ///
+ ///\ref named-templ-param "Named parameter" for setting
+ ///\c ProcessedMap type to be <tt>Digraph::NodeMap<bool></tt>.
+ ///If you don't set it explicitly, it will be automatically allocated.
+ struct SetStandardProcessedMap :
+ public Dfs< Digraph, SetStandardProcessedMapTraits > {
+ typedef Dfs< Digraph, SetStandardProcessedMapTraits > Create;
+ };
+
+ ///@}
+
+ public:
+
+ ///Constructor.
+
+ ///Constructor.
+ ///\param g The digraph the algorithm runs on.
+ Dfs(const Digraph &g) :
+ G(&g),
+ _pred(NULL), local_pred(false),
+ _dist(NULL), local_dist(false),
+ _reached(NULL), local_reached(false),
+ _processed(NULL), local_processed(false)
+ { }
+
+ ///Destructor.
+ ~Dfs()
+ {
+ if(local_pred) delete _pred;
+ if(local_dist) delete _dist;
+ if(local_reached) delete _reached;
+ if(local_processed) delete _processed;
+ }
+
+ ///Sets the map that stores the predecessor arcs.
+
+ ///Sets the map that stores the predecessor arcs.
+ ///If you don't use this function before calling \ref run(Node) "run()"
+ ///or \ref init(), an instance will be allocated automatically.
+ ///The destructor deallocates this automatically allocated map,
+ ///of course.
+ ///\return <tt> (*this) </tt>
+ Dfs &predMap(PredMap &m)
+ {
+ if(local_pred) {
+ delete _pred;
+ local_pred=false;
+ }
+ _pred = &m;
+ return *this;
+ }
+
+ ///Sets the map that indicates which nodes are reached.
+
+ ///Sets the map that indicates which nodes are reached.
+ ///If you don't use this function before calling \ref run(Node) "run()"
+ ///or \ref init(), an instance will be allocated automatically.
+ ///The destructor deallocates this automatically allocated map,
+ ///of course.
+ ///\return <tt> (*this) </tt>
+ Dfs &reachedMap(ReachedMap &m)
+ {
+ if(local_reached) {
+ delete _reached;
+ local_reached=false;
+ }
+ _reached = &m;
+ return *this;
+ }
+
+ ///Sets the map that indicates which nodes are processed.
+
+ ///Sets the map that indicates which nodes are processed.
+ ///If you don't use this function before calling \ref run(Node) "run()"
+ ///or \ref init(), an instance will be allocated automatically.
+ ///The destructor deallocates this automatically allocated map,
+ ///of course.
+ ///\return <tt> (*this) </tt>
+ Dfs &processedMap(ProcessedMap &m)
+ {
+ if(local_processed) {
+ delete _processed;
+ local_processed=false;
+ }
+ _processed = &m;
+ return *this;
+ }
+
+ ///Sets the map that stores the distances of the nodes.
+
+ ///Sets the map that stores the distances of the nodes calculated by
+ ///the algorithm.
+ ///If you don't use this function before calling \ref run(Node) "run()"
+ ///or \ref init(), an instance will be allocated automatically.
+ ///The destructor deallocates this automatically allocated map,
+ ///of course.
+ ///\return <tt> (*this) </tt>
+ Dfs &distMap(DistMap &m)
+ {
+ if(local_dist) {
+ delete _dist;
+ local_dist=false;
+ }
+ _dist = &m;
+ return *this;
+ }
+
+ public:
+
+ ///\name Execution Control
+ ///The simplest way to execute the DFS algorithm is to use one of the
+ ///member functions called \ref run(Node) "run()".\n
+ ///If you need better control on the execution, you have to call
+ ///\ref init() first, then you can add a source node with \ref addSource()
+ ///and perform the actual computation with \ref start().
+ ///This procedure can be repeated if there are nodes that have not
+ ///been reached.
+
+ ///@{
+
+ ///\brief Initializes the internal data structures.
+ ///
+ ///Initializes the internal data structures.
+ void init()
+ {
+ create_maps();
+ _stack.resize(countNodes(*G));
+ _stack_head=-1;
+ for ( NodeIt u(*G) ; u!=INVALID ; ++u ) {
+ _pred->set(u,INVALID);
+ _reached->set(u,false);
+ _processed->set(u,false);
+ }
+ }
+
+ ///Adds a new source node.
+
+ ///Adds a new source node to the set of nodes to be processed.
+ ///
+ ///\pre The stack must be empty. Otherwise the algorithm gives
+ ///wrong results. (One of the outgoing arcs of all the source nodes
+ ///except for the last one will not be visited and distances will
+ ///also be wrong.)
+ void addSource(Node s)
+ {
+ LEMON_DEBUG(emptyQueue(), "The stack is not empty.");
+ if(!(*_reached)[s])
+ {
+ _reached->set(s,true);
+ _pred->set(s,INVALID);
+ OutArcIt e(*G,s);
+ if(e!=INVALID) {
+ _stack[++_stack_head]=e;
+ _dist->set(s,_stack_head);
+ }
+ else {
+ _processed->set(s,true);
+ _dist->set(s,0);
+ }
+ }
+ }
+
+ ///Processes the next arc.
+
+ ///Processes the next arc.
+ ///
+ ///\return The processed arc.
+ ///
+ ///\pre The stack must not be empty.
+ Arc processNextArc()
+ {
+ Node m;
+ Arc e=_stack[_stack_head];
+ if(!(*_reached)[m=G->target(e)]) {
+ _pred->set(m,e);
+ _reached->set(m,true);
+ ++_stack_head;
+ _stack[_stack_head] = OutArcIt(*G, m);
+ _dist->set(m,_stack_head);
+ }
+ else {
+ m=G->source(e);
+ ++_stack[_stack_head];
+ }
+ while(_stack_head>=0 && _stack[_stack_head]==INVALID) {
+ _processed->set(m,true);
+ --_stack_head;
+ if(_stack_head>=0) {
+ m=G->source(_stack[_stack_head]);
+ ++_stack[_stack_head];
+ }
+ }
+ return e;
+ }
+
+ ///Next arc to be processed.
+
+ ///Next arc to be processed.
+ ///
+ ///\return The next arc to be processed or \c INVALID if the stack
+ ///is empty.
+ OutArcIt nextArc() const
+ {
+ return _stack_head>=0?_stack[_stack_head]:INVALID;
+ }
+
+ ///Returns \c false if there are nodes to be processed.
+
+ ///Returns \c false if there are nodes to be processed
+ ///in the queue (stack).
+ bool emptyQueue() const { return _stack_head<0; }
+
+ ///Returns the number of the nodes to be processed.
+
+ ///Returns the number of the nodes to be processed
+ ///in the queue (stack).
+ int queueSize() const { return _stack_head+1; }
+
+ ///Executes the algorithm.
+
+ ///Executes the algorithm.
+ ///
+ ///This method runs the %DFS algorithm from the root node
+ ///in order to compute the DFS path to each node.
+ ///
+ /// The algorithm computes
+ ///- the %DFS tree,
+ ///- the distance of each node from the root in the %DFS tree.
+ ///
+ ///\pre init() must be called and a root node should be
+ ///added with addSource() before using this function.
+ ///
+ ///\note <tt>d.start()</tt> is just a shortcut of the following code.
+ ///\code
+ /// while ( !d.emptyQueue() ) {
+ /// d.processNextArc();
+ /// }
+ ///\endcode
+ void start()
+ {
+ while ( !emptyQueue() ) processNextArc();
+ }
+
+ ///Executes the algorithm until the given target node is reached.
+
+ ///Executes the algorithm until the given target node is reached.
+ ///
+ ///This method runs the %DFS algorithm from the root node
+ ///in order to compute the DFS path to \c t.
+ ///
+ ///The algorithm computes
+ ///- the %DFS path to \c t,
+ ///- the distance of \c t from the root in the %DFS tree.
+ ///
+ ///\pre init() must be called and a root node should be
+ ///added with addSource() before using this function.
+ void start(Node t)
+ {
+ while ( !emptyQueue() && !(*_reached)[t] )
+ processNextArc();
+ }
+
+ ///Executes the algorithm until a condition is met.
+
+ ///Executes the algorithm until a condition is met.
+ ///
+ ///This method runs the %DFS algorithm from the root node
+ ///until an arc \c a with <tt>am[a]</tt> true is found.
+ ///
+ ///\param am A \c bool (or convertible) arc map. The algorithm
+ ///will stop when it reaches an arc \c a with <tt>am[a]</tt> true.
+ ///
+ ///\return The reached arc \c a with <tt>am[a]</tt> true or
+ ///\c INVALID if no such arc was found.
+ ///
+ ///\pre init() must be called and a root node should be
+ ///added with addSource() before using this function.
+ ///
+ ///\warning Contrary to \ref Bfs and \ref Dijkstra, \c am is an arc map,
+ ///not a node map.
+ template<class ArcBoolMap>
+ Arc start(const ArcBoolMap &am)
+ {
+ while ( !emptyQueue() && !am[_stack[_stack_head]] )
+ processNextArc();
+ return emptyQueue() ? INVALID : _stack[_stack_head];
+ }
+
+ ///Runs the algorithm from the given source node.
+
+ ///This method runs the %DFS algorithm from node \c s
+ ///in order to compute the DFS path to each node.
+ ///
+ ///The algorithm computes
+ ///- the %DFS tree,
+ ///- the distance of each node from the root in the %DFS tree.
+ ///
+ ///\note <tt>d.run(s)</tt> is just a shortcut of the following code.
+ ///\code
+ /// d.init();
+ /// d.addSource(s);
+ /// d.start();
+ ///\endcode
+ void run(Node s) {
+ init();
+ addSource(s);
+ start();
+ }
+
+ ///Finds the %DFS path between \c s and \c t.
+
+ ///This method runs the %DFS algorithm from node \c s
+ ///in order to compute the DFS path to node \c t
+ ///(it stops searching when \c t is processed)
+ ///
+ ///\return \c true if \c t is reachable form \c s.
+ ///
+ ///\note Apart from the return value, <tt>d.run(s,t)</tt> is
+ ///just a shortcut of the following code.
+ ///\code
+ /// d.init();
+ /// d.addSource(s);
+ /// d.start(t);
+ ///\endcode
+ bool run(Node s,Node t) {
+ init();
+ addSource(s);
+ start(t);
+ return reached(t);
+ }
+
+ ///Runs the algorithm to visit all nodes in the digraph.
+
+ ///This method runs the %DFS algorithm in order to visit all nodes
+ ///in the digraph.
+ ///
+ ///\note <tt>d.run()</tt> is just a shortcut of the following code.
+ ///\code
+ /// d.init();
+ /// for (NodeIt n(digraph); n != INVALID; ++n) {
+ /// if (!d.reached(n)) {
+ /// d.addSource(n);
+ /// d.start();
+ /// }
+ /// }
+ ///\endcode
+ void run() {
+ init();
+ for (NodeIt it(*G); it != INVALID; ++it) {
+ if (!reached(it)) {
+ addSource(it);
+ start();
+ }
+ }
+ }
+
+ ///@}
+
+ ///\name Query Functions
+ ///The results of the DFS algorithm can be obtained using these
+ ///functions.\n
+ ///Either \ref run(Node) "run()" or \ref start() should be called
+ ///before using them.
+
+ ///@{
+
+ ///The DFS path to the given node.
+
+ ///Returns the DFS path to the given node from the root(s).
+ ///
+ ///\warning \c t should be reached from the root(s).
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ Path path(Node t) const { return Path(*G, *_pred, t); }
+
+ ///The distance of the given node from the root(s).
+
+ ///Returns the distance of the given node from the root(s).
+ ///
+ ///\warning If node \c v is not reached from the root(s), then
+ ///the return value of this function is undefined.
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ int dist(Node v) const { return (*_dist)[v]; }
+
+ ///Returns the 'previous arc' of the %DFS tree for the given node.
+
+ ///This function returns the 'previous arc' of the %DFS tree for the
+ ///node \c v, i.e. it returns the last arc of a %DFS path from a
+ ///root to \c v. It is \c INVALID if \c v is not reached from the
+ ///root(s) or if \c v is a root.
+ ///
+ ///The %DFS tree used here is equal to the %DFS tree used in
+ ///\ref predNode() and \ref predMap().
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ Arc predArc(Node v) const { return (*_pred)[v];}
+
+ ///Returns the 'previous node' of the %DFS tree for the given node.
+
+ ///This function returns the 'previous node' of the %DFS
+ ///tree for the node \c v, i.e. it returns the last but one node
+ ///of a %DFS path from a root to \c v. It is \c INVALID
+ ///if \c v is not reached from the root(s) or if \c v is a root.
+ ///
+ ///The %DFS tree used here is equal to the %DFS tree used in
+ ///\ref predArc() and \ref predMap().
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID:
+ G->source((*_pred)[v]); }
+
+ ///\brief Returns a const reference to the node map that stores the
+ ///distances of the nodes.
+ ///
+ ///Returns a const reference to the node map that stores the
+ ///distances of the nodes calculated by the algorithm.
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ const DistMap &distMap() const { return *_dist;}
+
+ ///\brief Returns a const reference to the node map that stores the
+ ///predecessor arcs.
+ ///
+ ///Returns a const reference to the node map that stores the predecessor
+ ///arcs, which form the DFS tree (forest).
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ const PredMap &predMap() const { return *_pred;}
+
+ ///Checks if the given node. node is reached from the root(s).
+
+ ///Returns \c true if \c v is reached from the root(s).
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ bool reached(Node v) const { return (*_reached)[v]; }
+
+ ///@}
+ };
+
+ ///Default traits class of dfs() function.
+
+ ///Default traits class of dfs() function.
+ ///\tparam GR Digraph type.
+ template<class GR>
+ struct DfsWizardDefaultTraits
+ {
+ ///The type of the digraph the algorithm runs on.
+ typedef GR Digraph;
+
+ ///\brief The type of the map that stores the predecessor
+ ///arcs of the %DFS paths.
+ ///
+ ///The type of the map that stores the predecessor
+ ///arcs of the %DFS paths.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ typedef typename Digraph::template NodeMap<typename Digraph::Arc> PredMap;
+ ///Instantiates a PredMap.
+
+ ///This function instantiates a PredMap.
+ ///\param g is the digraph, to which we would like to define the
+ ///PredMap.
+ static PredMap *createPredMap(const Digraph &g)
+ {
+ return new PredMap(g);
+ }
+
+ ///The type of the map that indicates which nodes are processed.
+
+ ///The type of the map that indicates which nodes are processed.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ ///By default, it is a NullMap.
+ typedef NullMap<typename Digraph::Node,bool> ProcessedMap;
+ ///Instantiates a ProcessedMap.
+
+ ///This function instantiates a ProcessedMap.
+ ///\param g is the digraph, to which
+ ///we would like to define the ProcessedMap.
+#ifdef DOXYGEN
+ static ProcessedMap *createProcessedMap(const Digraph &g)
+#else
+ static ProcessedMap *createProcessedMap(const Digraph &)
+#endif
+ {
+ return new ProcessedMap();
+ }
+
+ ///The type of the map that indicates which nodes are reached.
+
+ ///The type of the map that indicates which nodes are reached.
+ ///It must conform to
+ ///the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
+ typedef typename Digraph::template NodeMap<bool> ReachedMap;
+ ///Instantiates a ReachedMap.
+
+ ///This function instantiates a ReachedMap.
+ ///\param g is the digraph, to which
+ ///we would like to define the ReachedMap.
+ static ReachedMap *createReachedMap(const Digraph &g)
+ {
+ return new ReachedMap(g);
+ }
+
+ ///The type of the map that stores the distances of the nodes.
+
+ ///The type of the map that stores the distances of the nodes.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ typedef typename Digraph::template NodeMap<int> DistMap;
+ ///Instantiates a DistMap.
+
+ ///This function instantiates a DistMap.
+ ///\param g is the digraph, to which we would like to define
+ ///the DistMap
+ static DistMap *createDistMap(const Digraph &g)
+ {
+ return new DistMap(g);
+ }
+
+ ///The type of the DFS paths.
+
+ ///The type of the DFS paths.
+ ///It must conform to the \ref concepts::Path "Path" concept.
+ typedef lemon::Path<Digraph> Path;
+ };
+
+ /// Default traits class used by DfsWizard
+
+ /// Default traits class used by DfsWizard.
+ /// \tparam GR The type of the digraph.
+ template<class GR>
+ class DfsWizardBase : public DfsWizardDefaultTraits<GR>
+ {
+
+ typedef DfsWizardDefaultTraits<GR> Base;
+ protected:
+ //The type of the nodes in the digraph.
+ typedef typename Base::Digraph::Node Node;
+
+ //Pointer to the digraph the algorithm runs on.
+ void *_g;
+ //Pointer to the map of reached nodes.
+ void *_reached;
+ //Pointer to the map of processed nodes.
+ void *_processed;
+ //Pointer to the map of predecessors arcs.
+ void *_pred;
+ //Pointer to the map of distances.
+ void *_dist;
+ //Pointer to the DFS path to the target node.
+ void *_path;
+ //Pointer to the distance of the target node.
+ int *_di;
+
+ public:
+ /// Constructor.
+
+ /// This constructor does not require parameters, it initiates
+ /// all of the attributes to \c 0.
+ DfsWizardBase() : _g(0), _reached(0), _processed(0), _pred(0),
+ _dist(0), _path(0), _di(0) {}
+
+ /// Constructor.
+
+ /// This constructor requires one parameter,
+ /// others are initiated to \c 0.
+ /// \param g The digraph the algorithm runs on.
+ DfsWizardBase(const GR &g) :
+ _g(reinterpret_cast<void*>(const_cast<GR*>(&g))),
+ _reached(0), _processed(0), _pred(0), _dist(0), _path(0), _di(0) {}
+
+ };
+
+ /// Auxiliary class for the function-type interface of DFS algorithm.
+
+ /// This auxiliary class is created to implement the
+ /// \ref dfs() "function-type interface" of \ref Dfs algorithm.
+ /// It does not have own \ref run(Node) "run()" method, it uses the
+ /// functions and features of the plain \ref Dfs.
+ ///
+ /// This class should only be used through the \ref dfs() function,
+ /// which makes it easier to use the algorithm.
+ ///
+ /// \tparam TR The traits class that defines various types used by the
+ /// algorithm.
+ template<class TR>
+ class DfsWizard : public TR
+ {
+ typedef TR Base;
+
+ typedef typename TR::Digraph Digraph;
+
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::NodeIt NodeIt;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::OutArcIt OutArcIt;
+
+ typedef typename TR::PredMap PredMap;
+ typedef typename TR::DistMap DistMap;
+ typedef typename TR::ReachedMap ReachedMap;
+ typedef typename TR::ProcessedMap ProcessedMap;
+ typedef typename TR::Path Path;
+
+ public:
+
+ /// Constructor.
+ DfsWizard() : TR() {}
+
+ /// Constructor that requires parameters.
+
+ /// Constructor that requires parameters.
+ /// These parameters will be the default values for the traits class.
+ /// \param g The digraph the algorithm runs on.
+ DfsWizard(const Digraph &g) :
+ TR(g) {}
+
+ ///Copy constructor
+ DfsWizard(const TR &b) : TR(b) {}
+
+ ~DfsWizard() {}
+
+ ///Runs DFS algorithm from the given source node.
+
+ ///This method runs DFS algorithm from node \c s
+ ///in order to compute the DFS path to each node.
+ void run(Node s)
+ {
+ Dfs<Digraph,TR> alg(*reinterpret_cast<const Digraph*>(Base::_g));
+ if (Base::_pred)
+ alg.predMap(*reinterpret_cast<PredMap*>(Base::_pred));
+ if (Base::_dist)
+ alg.distMap(*reinterpret_cast<DistMap*>(Base::_dist));
+ if (Base::_reached)
+ alg.reachedMap(*reinterpret_cast<ReachedMap*>(Base::_reached));
+ if (Base::_processed)
+ alg.processedMap(*reinterpret_cast<ProcessedMap*>(Base::_processed));
+ if (s!=INVALID)
+ alg.run(s);
+ else
+ alg.run();
+ }
+
+ ///Finds the DFS path between \c s and \c t.
+
+ ///This method runs DFS algorithm from node \c s
+ ///in order to compute the DFS path to node \c t
+ ///(it stops searching when \c t is processed).
+ ///
+ ///\return \c true if \c t is reachable form \c s.
+ bool run(Node s, Node t)
+ {
+ Dfs<Digraph,TR> alg(*reinterpret_cast<const Digraph*>(Base::_g));
+ if (Base::_pred)
+ alg.predMap(*reinterpret_cast<PredMap*>(Base::_pred));
+ if (Base::_dist)
+ alg.distMap(*reinterpret_cast<DistMap*>(Base::_dist));
+ if (Base::_reached)
+ alg.reachedMap(*reinterpret_cast<ReachedMap*>(Base::_reached));
+ if (Base::_processed)
+ alg.processedMap(*reinterpret_cast<ProcessedMap*>(Base::_processed));
+ alg.run(s,t);
+ if (Base::_path)
+ *reinterpret_cast<Path*>(Base::_path) = alg.path(t);
+ if (Base::_di)
+ *Base::_di = alg.dist(t);
+ return alg.reached(t);
+ }
+
+ ///Runs DFS algorithm to visit all nodes in the digraph.
+
+ ///This method runs DFS algorithm in order to visit all nodes
+ ///in the digraph.
+ void run()
+ {
+ run(INVALID);
+ }
+
+ template<class T>
+ struct SetPredMapBase : public Base {
+ typedef T PredMap;
+ static PredMap *createPredMap(const Digraph &) { return 0; };
+ SetPredMapBase(const TR &b) : TR(b) {}
+ };
+
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///the predecessor map.
+ ///
+ ///\ref named-templ-param "Named parameter" function for setting
+ ///the map that stores the predecessor arcs of the nodes.
+ template<class T>
+ DfsWizard<SetPredMapBase<T> > predMap(const T &t)
+ {
+ Base::_pred=reinterpret_cast<void*>(const_cast<T*>(&t));
+ return DfsWizard<SetPredMapBase<T> >(*this);
+ }
+
+ template<class T>
+ struct SetReachedMapBase : public Base {
+ typedef T ReachedMap;
+ static ReachedMap *createReachedMap(const Digraph &) { return 0; };
+ SetReachedMapBase(const TR &b) : TR(b) {}
+ };
+
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///the reached map.
+ ///
+ ///\ref named-templ-param "Named parameter" function for setting
+ ///the map that indicates which nodes are reached.
+ template<class T>
+ DfsWizard<SetReachedMapBase<T> > reachedMap(const T &t)
+ {
+ Base::_reached=reinterpret_cast<void*>(const_cast<T*>(&t));
+ return DfsWizard<SetReachedMapBase<T> >(*this);
+ }
+
+ template<class T>
+ struct SetDistMapBase : public Base {
+ typedef T DistMap;
+ static DistMap *createDistMap(const Digraph &) { return 0; };
+ SetDistMapBase(const TR &b) : TR(b) {}
+ };
+
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///the distance map.
+ ///
+ ///\ref named-templ-param "Named parameter" function for setting
+ ///the map that stores the distances of the nodes calculated
+ ///by the algorithm.
+ template<class T>
+ DfsWizard<SetDistMapBase<T> > distMap(const T &t)
+ {
+ Base::_dist=reinterpret_cast<void*>(const_cast<T*>(&t));
+ return DfsWizard<SetDistMapBase<T> >(*this);
+ }
+
+ template<class T>
+ struct SetProcessedMapBase : public Base {
+ typedef T ProcessedMap;
+ static ProcessedMap *createProcessedMap(const Digraph &) { return 0; };
+ SetProcessedMapBase(const TR &b) : TR(b) {}
+ };
+
+ ///\brief \ref named-func-param "Named parameter" for setting
+ ///the processed map.
+ ///
+ ///\ref named-templ-param "Named parameter" function for setting
+ ///the map that indicates which nodes are processed.
+ template<class T>
+ DfsWizard<SetProcessedMapBase<T> > processedMap(const T &t)
+ {
+ Base::_processed=reinterpret_cast<void*>(const_cast<T*>(&t));
+ return DfsWizard<SetProcessedMapBase<T> >(*this);
+ }
+
+ template<class T>
+ struct SetPathBase : public Base {
+ typedef T Path;
+ SetPathBase(const TR &b) : TR(b) {}
+ };
+ ///\brief \ref named-func-param "Named parameter"
+ ///for getting the DFS path to the target node.
+ ///
+ ///\ref named-func-param "Named parameter"
+ ///for getting the DFS path to the target node.
+ template<class T>
+ DfsWizard<SetPathBase<T> > path(const T &t)
+ {
+ Base::_path=reinterpret_cast<void*>(const_cast<T*>(&t));
+ return DfsWizard<SetPathBase<T> >(*this);
+ }
+
+ ///\brief \ref named-func-param "Named parameter"
+ ///for getting the distance of the target node.
+ ///
+ ///\ref named-func-param "Named parameter"
+ ///for getting the distance of the target node.
+ DfsWizard dist(const int &d)
+ {
+ Base::_di=const_cast<int*>(&d);
+ return *this;
+ }
+
+ };
+
+ ///Function-type interface for DFS algorithm.
+
+ ///\ingroup search
+ ///Function-type interface for DFS algorithm.
+ ///
+ ///This function also has several \ref named-func-param "named parameters",
+ ///they are declared as the members of class \ref DfsWizard.
+ ///The following examples show how to use these parameters.
+ ///\code
+ /// // Compute the DFS tree
+ /// dfs(g).predMap(preds).distMap(dists).run(s);
+ ///
+ /// // Compute the DFS path from s to t
+ /// bool reached = dfs(g).path(p).dist(d).run(s,t);
+ ///\endcode
+ ///\warning Don't forget to put the \ref DfsWizard::run(Node) "run()"
+ ///to the end of the parameter list.
+ ///\sa DfsWizard
+ ///\sa Dfs
+ template<class GR>
+ DfsWizard<DfsWizardBase<GR> >
+ dfs(const GR &digraph)
+ {
+ return DfsWizard<DfsWizardBase<GR> >(digraph);
+ }
+
+#ifdef DOXYGEN
+ /// \brief Visitor class for DFS.
+ ///
+ /// This class defines the interface of the DfsVisit events, and
+ /// it could be the base of a real visitor class.
+ template <typename GR>
+ struct DfsVisitor {
+ typedef GR Digraph;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::Node Node;
+ /// \brief Called for the source node of the DFS.
+ ///
+ /// This function is called for the source node of the DFS.
+ void start(const Node& node) {}
+ /// \brief Called when the source node is leaved.
+ ///
+ /// This function is called when the source node is leaved.
+ void stop(const Node& node) {}
+ /// \brief Called when a node is reached first time.
+ ///
+ /// This function is called when a node is reached first time.
+ void reach(const Node& node) {}
+ /// \brief Called when an arc reaches a new node.
+ ///
+ /// This function is called when the DFS finds an arc whose target node
+ /// is not reached yet.
+ void discover(const Arc& arc) {}
+ /// \brief Called when an arc is examined but its target node is
+ /// already discovered.
+ ///
+ /// This function is called when an arc is examined but its target node is
+ /// already discovered.
+ void examine(const Arc& arc) {}
+ /// \brief Called when the DFS steps back from a node.
+ ///
+ /// This function is called when the DFS steps back from a node.
+ void leave(const Node& node) {}
+ /// \brief Called when the DFS steps back on an arc.
+ ///
+ /// This function is called when the DFS steps back on an arc.
+ void backtrack(const Arc& arc) {}
+ };
+#else
+ template <typename GR>
+ struct DfsVisitor {
+ typedef GR Digraph;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::Node Node;
+ void start(const Node&) {}
+ void stop(const Node&) {}
+ void reach(const Node&) {}
+ void discover(const Arc&) {}
+ void examine(const Arc&) {}
+ void leave(const Node&) {}
+ void backtrack(const Arc&) {}
+
+ template <typename _Visitor>
+ struct Constraints {
+ void constraints() {
+ Arc arc;
+ Node node;
+ visitor.start(node);
+ visitor.stop(arc);
+ visitor.reach(node);
+ visitor.discover(arc);
+ visitor.examine(arc);
+ visitor.leave(node);
+ visitor.backtrack(arc);
+ }
+ _Visitor& visitor;
+ Constraints() {}
+ };
+ };
+#endif
+
+ /// \brief Default traits class of DfsVisit class.
+ ///
+ /// Default traits class of DfsVisit class.
+ /// \tparam _Digraph The type of the digraph the algorithm runs on.
+ template<class GR>
+ struct DfsVisitDefaultTraits {
+
+ /// \brief The type of the digraph the algorithm runs on.
+ typedef GR Digraph;
+
+ /// \brief The type of the map that indicates which nodes are reached.
+ ///
+ /// The type of the map that indicates which nodes are reached.
+ /// It must conform to the
+ /// \ref concepts::ReadWriteMap "ReadWriteMap" concept.
+ typedef typename Digraph::template NodeMap<bool> ReachedMap;
+
+ /// \brief Instantiates a ReachedMap.
+ ///
+ /// This function instantiates a ReachedMap.
+ /// \param digraph is the digraph, to which
+ /// we would like to define the ReachedMap.
+ static ReachedMap *createReachedMap(const Digraph &digraph) {
+ return new ReachedMap(digraph);
+ }
+
+ };
+
+ /// \ingroup search
+ ///
+ /// \brief DFS algorithm class with visitor interface.
+ ///
+ /// This class provides an efficient implementation of the DFS algorithm
+ /// with visitor interface.
+ ///
+ /// The DfsVisit class provides an alternative interface to the Dfs
+ /// class. It works with callback mechanism, the DfsVisit object calls
+ /// the member functions of the \c Visitor class on every DFS event.
+ ///
+ /// This interface of the DFS algorithm should be used in special cases
+ /// when extra actions have to be performed in connection with certain
+ /// events of the DFS algorithm. Otherwise consider to use Dfs or dfs()
+ /// instead.
+ ///
+ /// \tparam GR The type of the digraph the algorithm runs on.
+ /// The default type is \ref ListDigraph.
+ /// The value of GR is not used directly by \ref DfsVisit,
+ /// it is only passed to \ref DfsVisitDefaultTraits.
+ /// \tparam VS The Visitor type that is used by the algorithm.
+ /// \ref DfsVisitor "DfsVisitor<GR>" is an empty visitor, which
+ /// does not observe the DFS events. If you want to observe the DFS
+ /// events, you should implement your own visitor class.
+ /// \tparam TR The traits class that defines various types used by the
+ /// algorithm. By default, it is \ref DfsVisitDefaultTraits
+ /// "DfsVisitDefaultTraits<GR>".
+ /// In most cases, this parameter should not be set directly,
+ /// consider to use the named template parameters instead.
+#ifdef DOXYGEN
+ template <typename GR, typename VS, typename TR>
+#else
+ template <typename GR = ListDigraph,
+ typename VS = DfsVisitor<GR>,
+ typename TR = DfsVisitDefaultTraits<GR> >
+#endif
+ class DfsVisit {
+ public:
+
+ ///The traits class.
+ typedef TR Traits;
+
+ ///The type of the digraph the algorithm runs on.
+ typedef typename Traits::Digraph Digraph;
+
+ ///The visitor type used by the algorithm.
+ typedef VS Visitor;
+
+ ///The type of the map that indicates which nodes are reached.
+ typedef typename Traits::ReachedMap ReachedMap;
+
+ private:
+
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::NodeIt NodeIt;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::OutArcIt OutArcIt;
+
+ //Pointer to the underlying digraph.
+ const Digraph *_digraph;
+ //Pointer to the visitor object.
+ Visitor *_visitor;
+ //Pointer to the map of reached status of the nodes.
+ ReachedMap *_reached;
+ //Indicates if _reached is locally allocated (true) or not.
+ bool local_reached;
+
+ std::vector<typename Digraph::Arc> _stack;
+ int _stack_head;
+
+ //Creates the maps if necessary.
+ void create_maps() {
+ if(!_reached) {
+ local_reached = true;
+ _reached = Traits::createReachedMap(*_digraph);
+ }
+ }
+
+ protected:
+
+ DfsVisit() {}
+
+ public:
+
+ typedef DfsVisit Create;
+
+ /// \name Named Template Parameters
+
+ ///@{
+ template <class T>
+ struct SetReachedMapTraits : public Traits {
+ typedef T ReachedMap;
+ static ReachedMap *createReachedMap(const Digraph &digraph) {
+ LEMON_ASSERT(false, "ReachedMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// ReachedMap type.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting ReachedMap type.
+ template <class T>
+ struct SetReachedMap : public DfsVisit< Digraph, Visitor,
+ SetReachedMapTraits<T> > {
+ typedef DfsVisit< Digraph, Visitor, SetReachedMapTraits<T> > Create;
+ };
+ ///@}
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ ///
+ /// \param digraph The digraph the algorithm runs on.
+ /// \param visitor The visitor object of the algorithm.
+ DfsVisit(const Digraph& digraph, Visitor& visitor)
+ : _digraph(&digraph), _visitor(&visitor),
+ _reached(0), local_reached(false) {}
+
+ /// \brief Destructor.
+ ~DfsVisit() {
+ if(local_reached) delete _reached;
+ }
+
+ /// \brief Sets the map that indicates which nodes are reached.
+ ///
+ /// Sets the map that indicates which nodes are reached.
+ /// If you don't use this function before calling \ref run(Node) "run()"
+ /// or \ref init(), an instance will be allocated automatically.
+ /// The destructor deallocates this automatically allocated map,
+ /// of course.
+ /// \return <tt> (*this) </tt>
+ DfsVisit &reachedMap(ReachedMap &m) {
+ if(local_reached) {
+ delete _reached;
+ local_reached=false;
+ }
+ _reached = &m;
+ return *this;
+ }
+
+ public:
+
+ /// \name Execution Control
+ /// The simplest way to execute the DFS algorithm is to use one of the
+ /// member functions called \ref run(Node) "run()".\n
+ /// If you need better control on the execution, you have to call
+ /// \ref init() first, then you can add a source node with \ref addSource()
+ /// and perform the actual computation with \ref start().
+ /// This procedure can be repeated if there are nodes that have not
+ /// been reached.
+
+ /// @{
+
+ /// \brief Initializes the internal data structures.
+ ///
+ /// Initializes the internal data structures.
+ void init() {
+ create_maps();
+ _stack.resize(countNodes(*_digraph));
+ _stack_head = -1;
+ for (NodeIt u(*_digraph) ; u != INVALID ; ++u) {
+ _reached->set(u, false);
+ }
+ }
+
+ /// \brief Adds a new source node.
+ ///
+ /// Adds a new source node to the set of nodes to be processed.
+ ///
+ /// \pre The stack must be empty. Otherwise the algorithm gives
+ /// wrong results. (One of the outgoing arcs of all the source nodes
+ /// except for the last one will not be visited and distances will
+ /// also be wrong.)
+ void addSource(Node s)
+ {
+ LEMON_DEBUG(emptyQueue(), "The stack is not empty.");
+ if(!(*_reached)[s]) {
+ _reached->set(s,true);
+ _visitor->start(s);
+ _visitor->reach(s);
+ Arc e;
+ _digraph->firstOut(e, s);
+ if (e != INVALID) {
+ _stack[++_stack_head] = e;
+ } else {
+ _visitor->leave(s);
+ _visitor->stop(s);
+ }
+ }
+ }
+
+ /// \brief Processes the next arc.
+ ///
+ /// Processes the next arc.
+ ///
+ /// \return The processed arc.
+ ///
+ /// \pre The stack must not be empty.
+ Arc processNextArc() {
+ Arc e = _stack[_stack_head];
+ Node m = _digraph->target(e);
+ if(!(*_reached)[m]) {
+ _visitor->discover(e);
+ _visitor->reach(m);
+ _reached->set(m, true);
+ _digraph->firstOut(_stack[++_stack_head], m);
+ } else {
+ _visitor->examine(e);
+ m = _digraph->source(e);
+ _digraph->nextOut(_stack[_stack_head]);
+ }
+ while (_stack_head>=0 && _stack[_stack_head] == INVALID) {
+ _visitor->leave(m);
+ --_stack_head;
+ if (_stack_head >= 0) {
+ _visitor->backtrack(_stack[_stack_head]);
+ m = _digraph->source(_stack[_stack_head]);
+ _digraph->nextOut(_stack[_stack_head]);
+ } else {
+ _visitor->stop(m);
+ }
+ }
+ return e;
+ }
+
+ /// \brief Next arc to be processed.
+ ///
+ /// Next arc to be processed.
+ ///
+ /// \return The next arc to be processed or INVALID if the stack is
+ /// empty.
+ Arc nextArc() const {
+ return _stack_head >= 0 ? _stack[_stack_head] : INVALID;
+ }
+
+ /// \brief Returns \c false if there are nodes
+ /// to be processed.
+ ///
+ /// Returns \c false if there are nodes
+ /// to be processed in the queue (stack).
+ bool emptyQueue() const { return _stack_head < 0; }
+
+ /// \brief Returns the number of the nodes to be processed.
+ ///
+ /// Returns the number of the nodes to be processed in the queue (stack).
+ int queueSize() const { return _stack_head + 1; }
+
+ /// \brief Executes the algorithm.
+ ///
+ /// Executes the algorithm.
+ ///
+ /// This method runs the %DFS algorithm from the root node
+ /// in order to compute the %DFS path to each node.
+ ///
+ /// The algorithm computes
+ /// - the %DFS tree,
+ /// - the distance of each node from the root in the %DFS tree.
+ ///
+ /// \pre init() must be called and a root node should be
+ /// added with addSource() before using this function.
+ ///
+ /// \note <tt>d.start()</tt> is just a shortcut of the following code.
+ /// \code
+ /// while ( !d.emptyQueue() ) {
+ /// d.processNextArc();
+ /// }
+ /// \endcode
+ void start() {
+ while ( !emptyQueue() ) processNextArc();
+ }
+
+ /// \brief Executes the algorithm until the given target node is reached.
+ ///
+ /// Executes the algorithm until the given target node is reached.
+ ///
+ /// This method runs the %DFS algorithm from the root node
+ /// in order to compute the DFS path to \c t.
+ ///
+ /// The algorithm computes
+ /// - the %DFS path to \c t,
+ /// - the distance of \c t from the root in the %DFS tree.
+ ///
+ /// \pre init() must be called and a root node should be added
+ /// with addSource() before using this function.
+ void start(Node t) {
+ while ( !emptyQueue() && !(*_reached)[t] )
+ processNextArc();
+ }
+
+ /// \brief Executes the algorithm until a condition is met.
+ ///
+ /// Executes the algorithm until a condition is met.
+ ///
+ /// This method runs the %DFS algorithm from the root node
+ /// until an arc \c a with <tt>am[a]</tt> true is found.
+ ///
+ /// \param am A \c bool (or convertible) arc map. The algorithm
+ /// will stop when it reaches an arc \c a with <tt>am[a]</tt> true.
+ ///
+ /// \return The reached arc \c a with <tt>am[a]</tt> true or
+ /// \c INVALID if no such arc was found.
+ ///
+ /// \pre init() must be called and a root node should be added
+ /// with addSource() before using this function.
+ ///
+ /// \warning Contrary to \ref Bfs and \ref Dijkstra, \c am is an arc map,
+ /// not a node map.
+ template <typename AM>
+ Arc start(const AM &am) {
+ while ( !emptyQueue() && !am[_stack[_stack_head]] )
+ processNextArc();
+ return emptyQueue() ? INVALID : _stack[_stack_head];
+ }
+
+ /// \brief Runs the algorithm from the given source node.
+ ///
+ /// This method runs the %DFS algorithm from node \c s.
+ /// in order to compute the DFS path to each node.
+ ///
+ /// The algorithm computes
+ /// - the %DFS tree,
+ /// - the distance of each node from the root in the %DFS tree.
+ ///
+ /// \note <tt>d.run(s)</tt> is just a shortcut of the following code.
+ ///\code
+ /// d.init();
+ /// d.addSource(s);
+ /// d.start();
+ ///\endcode
+ void run(Node s) {
+ init();
+ addSource(s);
+ start();
+ }
+
+ /// \brief Finds the %DFS path between \c s and \c t.
+
+ /// This method runs the %DFS algorithm from node \c s
+ /// in order to compute the DFS path to node \c t
+ /// (it stops searching when \c t is processed).
+ ///
+ /// \return \c true if \c t is reachable form \c s.
+ ///
+ /// \note Apart from the return value, <tt>d.run(s,t)</tt> is
+ /// just a shortcut of the following code.
+ ///\code
+ /// d.init();
+ /// d.addSource(s);
+ /// d.start(t);
+ ///\endcode
+ bool run(Node s,Node t) {
+ init();
+ addSource(s);
+ start(t);
+ return reached(t);
+ }
+
+ /// \brief Runs the algorithm to visit all nodes in the digraph.
+
+ /// This method runs the %DFS algorithm in order to visit all nodes
+ /// in the digraph.
+ ///
+ /// \note <tt>d.run()</tt> is just a shortcut of the following code.
+ ///\code
+ /// d.init();
+ /// for (NodeIt n(digraph); n != INVALID; ++n) {
+ /// if (!d.reached(n)) {
+ /// d.addSource(n);
+ /// d.start();
+ /// }
+ /// }
+ ///\endcode
+ void run() {
+ init();
+ for (NodeIt it(*_digraph); it != INVALID; ++it) {
+ if (!reached(it)) {
+ addSource(it);
+ start();
+ }
+ }
+ }
+
+ ///@}
+
+ /// \name Query Functions
+ /// The results of the DFS algorithm can be obtained using these
+ /// functions.\n
+ /// Either \ref run(Node) "run()" or \ref start() should be called
+ /// before using them.
+
+ ///@{
+
+ /// \brief Checks if the given node is reached from the root(s).
+ ///
+ /// Returns \c true if \c v is reached from the root(s).
+ ///
+ /// \pre Either \ref run(Node) "run()" or \ref init()
+ /// must be called before using this function.
+ bool reached(Node v) const { return (*_reached)[v]; }
+
+ ///@}
+
+ };
+
+} //END OF NAMESPACE LEMON
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/dheap.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/dheap.h
new file mode 100644
index 00000000000..a3ab62525aa
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/dheap.h
@@ -0,0 +1,352 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_DHEAP_H
+#define LEMON_DHEAP_H
+
+///\ingroup heaps
+///\file
+///\brief D-ary heap implementation.
+
+#include <vector>
+#include <utility>
+#include <functional>
+
+namespace lemon {
+
+ /// \ingroup heaps
+ ///
+ ///\brief D-ary heap data structure.
+ ///
+ /// This class implements the \e D-ary \e heap data structure.
+ /// It fully conforms to the \ref concepts::Heap "heap concept".
+ ///
+ /// The \ref DHeap "D-ary heap" is a generalization of the
+ /// \ref BinHeap "binary heap" structure, its nodes have at most
+ /// \c D children, instead of two.
+ /// \ref BinHeap and \ref QuadHeap are specialized implementations
+ /// of this structure for <tt>D=2</tt> and <tt>D=4</tt>, respectively.
+ ///
+ /// \tparam PR Type of the priorities of the items.
+ /// \tparam IM A read-writable item map with \c int values, used
+ /// internally to handle the cross references.
+ /// \tparam D The degree of the heap, each node have at most \e D
+ /// children. The default is 16. Powers of two are suggested to use
+ /// so that the multiplications and divisions needed to traverse the
+ /// nodes of the heap could be performed faster.
+ /// \tparam CMP A functor class for comparing the priorities.
+ /// The default is \c std::less<PR>.
+ ///
+ ///\sa BinHeap
+ ///\sa FouraryHeap
+#ifdef DOXYGEN
+ template <typename PR, typename IM, int D, typename CMP>
+#else
+ template <typename PR, typename IM, int D = 16,
+ typename CMP = std::less<PR> >
+#endif
+ class DHeap {
+ public:
+ /// Type of the item-int map.
+ typedef IM ItemIntMap;
+ /// Type of the priorities.
+ typedef PR Prio;
+ /// Type of the items stored in the heap.
+ typedef typename ItemIntMap::Key Item;
+ /// Type of the item-priority pairs.
+ typedef std::pair<Item,Prio> Pair;
+ /// Functor type for comparing the priorities.
+ typedef CMP Compare;
+
+ /// \brief Type to represent the states of the items.
+ ///
+ /// Each item has a state associated to it. It can be "in heap",
+ /// "pre-heap" or "post-heap". The latter two are indifferent from the
+ /// heap's point of view, but may be useful to the user.
+ ///
+ /// The item-int map must be initialized in such way that it assigns
+ /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
+ enum State {
+ IN_HEAP = 0, ///< = 0.
+ PRE_HEAP = -1, ///< = -1.
+ POST_HEAP = -2 ///< = -2.
+ };
+
+ private:
+ std::vector<Pair> _data;
+ Compare _comp;
+ ItemIntMap &_iim;
+
+ public:
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// \param map A map that assigns \c int values to the items.
+ /// It is used internally to handle the cross references.
+ /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
+ explicit DHeap(ItemIntMap &map) : _iim(map) {}
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// \param map A map that assigns \c int values to the items.
+ /// It is used internally to handle the cross references.
+ /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
+ /// \param comp The function object used for comparing the priorities.
+ DHeap(ItemIntMap &map, const Compare &comp)
+ : _iim(map), _comp(comp) {}
+
+ /// \brief The number of items stored in the heap.
+ ///
+ /// This function returns the number of items stored in the heap.
+ int size() const { return _data.size(); }
+
+ /// \brief Check if the heap is empty.
+ ///
+ /// This function returns \c true if the heap is empty.
+ bool empty() const { return _data.empty(); }
+
+ /// \brief Make the heap empty.
+ ///
+ /// This functon makes the heap empty.
+ /// It does not change the cross reference map. If you want to reuse
+ /// a heap that is not surely empty, you should first clear it and
+ /// then you should set the cross reference map to \c PRE_HEAP
+ /// for each item.
+ void clear() { _data.clear(); }
+
+ private:
+ int parent(int i) { return (i-1)/D; }
+ int firstChild(int i) { return D*i+1; }
+
+ bool less(const Pair &p1, const Pair &p2) const {
+ return _comp(p1.second, p2.second);
+ }
+
+ void bubbleUp(int hole, Pair p) {
+ int par = parent(hole);
+ while( hole>0 && less(p,_data[par]) ) {
+ move(_data[par],hole);
+ hole = par;
+ par = parent(hole);
+ }
+ move(p, hole);
+ }
+
+ void bubbleDown(int hole, Pair p, int length) {
+ if( length>1 ) {
+ int child = firstChild(hole);
+ while( child+D<=length ) {
+ int min=child;
+ for (int i=1; i<D; ++i) {
+ if( less(_data[child+i], _data[min]) )
+ min=child+i;
+ }
+ if( !less(_data[min], p) )
+ goto ok;
+ move(_data[min], hole);
+ hole = min;
+ child = firstChild(hole);
+ }
+ if ( child<length ) {
+ int min = child;
+ while (++child < length) {
+ if( less(_data[child], _data[min]) )
+ min=child;
+ }
+ if( less(_data[min], p) ) {
+ move(_data[min], hole);
+ hole = min;
+ }
+ }
+ }
+ ok:
+ move(p, hole);
+ }
+
+ void move(const Pair &p, int i) {
+ _data[i] = p;
+ _iim.set(p.first, i);
+ }
+
+ public:
+ /// \brief Insert a pair of item and priority into the heap.
+ ///
+ /// This function inserts \c p.first to the heap with priority
+ /// \c p.second.
+ /// \param p The pair to insert.
+ /// \pre \c p.first must not be stored in the heap.
+ void push(const Pair &p) {
+ int n = _data.size();
+ _data.resize(n+1);
+ bubbleUp(n, p);
+ }
+
+ /// \brief Insert an item into the heap with the given priority.
+ ///
+ /// This function inserts the given item into the heap with the
+ /// given priority.
+ /// \param i The item to insert.
+ /// \param p The priority of the item.
+ /// \pre \e i must not be stored in the heap.
+ void push(const Item &i, const Prio &p) { push(Pair(i,p)); }
+
+ /// \brief Return the item having minimum priority.
+ ///
+ /// This function returns the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ Item top() const { return _data[0].first; }
+
+ /// \brief The minimum priority.
+ ///
+ /// This function returns the minimum priority.
+ /// \pre The heap must be non-empty.
+ Prio prio() const { return _data[0].second; }
+
+ /// \brief Remove the item having minimum priority.
+ ///
+ /// This function removes the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ void pop() {
+ int n = _data.size()-1;
+ _iim.set(_data[0].first, POST_HEAP);
+ if (n>0) bubbleDown(0, _data[n], n);
+ _data.pop_back();
+ }
+
+ /// \brief Remove the given item from the heap.
+ ///
+ /// This function removes the given item from the heap if it is
+ /// already stored.
+ /// \param i The item to delete.
+ /// \pre \e i must be in the heap.
+ void erase(const Item &i) {
+ int h = _iim[i];
+ int n = _data.size()-1;
+ _iim.set(_data[h].first, POST_HEAP);
+ if( h<n ) {
+ if( less(_data[parent(h)], _data[n]) )
+ bubbleDown(h, _data[n], n);
+ else
+ bubbleUp(h, _data[n]);
+ }
+ _data.pop_back();
+ }
+
+ /// \brief The priority of the given item.
+ ///
+ /// This function returns the priority of the given item.
+ /// \param i The item.
+ /// \pre \e i must be in the heap.
+ Prio operator[](const Item &i) const {
+ int idx = _iim[i];
+ return _data[idx].second;
+ }
+
+ /// \brief Set the priority of an item or insert it, if it is
+ /// not stored in the heap.
+ ///
+ /// This method sets the priority of the given item if it is
+ /// already stored in the heap. Otherwise it inserts the given
+ /// item into the heap with the given priority.
+ /// \param i The item.
+ /// \param p The priority.
+ void set(const Item &i, const Prio &p) {
+ int idx = _iim[i];
+ if( idx<0 )
+ push(i,p);
+ else if( _comp(p, _data[idx].second) )
+ bubbleUp(idx, Pair(i,p));
+ else
+ bubbleDown(idx, Pair(i,p), _data.size());
+ }
+
+ /// \brief Decrease the priority of an item to the given value.
+ ///
+ /// This function decreases the priority of an item to the given value.
+ /// \param i The item.
+ /// \param p The priority.
+ /// \pre \e i must be stored in the heap with priority at least \e p.
+ void decrease(const Item &i, const Prio &p) {
+ int idx = _iim[i];
+ bubbleUp(idx, Pair(i,p));
+ }
+
+ /// \brief Increase the priority of an item to the given value.
+ ///
+ /// This function increases the priority of an item to the given value.
+ /// \param i The item.
+ /// \param p The priority.
+ /// \pre \e i must be stored in the heap with priority at most \e p.
+ void increase(const Item &i, const Prio &p) {
+ int idx = _iim[i];
+ bubbleDown(idx, Pair(i,p), _data.size());
+ }
+
+ /// \brief Return the state of an item.
+ ///
+ /// This method returns \c PRE_HEAP if the given item has never
+ /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
+ /// and \c POST_HEAP otherwise.
+ /// In the latter case it is possible that the item will get back
+ /// to the heap again.
+ /// \param i The item.
+ State state(const Item &i) const {
+ int s = _iim[i];
+ if (s>=0) s=0;
+ return State(s);
+ }
+
+ /// \brief Set the state of an item in the heap.
+ ///
+ /// This function sets the state of the given item in the heap.
+ /// It can be used to manually clear the heap when it is important
+ /// to achive better time complexity.
+ /// \param i The item.
+ /// \param st The state. It should not be \c IN_HEAP.
+ void state(const Item& i, State st) {
+ switch (st) {
+ case POST_HEAP:
+ case PRE_HEAP:
+ if (state(i) == IN_HEAP) erase(i);
+ _iim[i] = st;
+ break;
+ case IN_HEAP:
+ break;
+ }
+ }
+
+ /// \brief Replace an item in the heap.
+ ///
+ /// This function replaces item \c i with item \c j.
+ /// Item \c i must be in the heap, while \c j must be out of the heap.
+ /// After calling this method, item \c i will be out of the
+ /// heap and \c j will be in the heap with the same prioriority
+ /// as item \c i had before.
+ void replace(const Item& i, const Item& j) {
+ int idx=_iim[i];
+ _iim.set(i, _iim[j]);
+ _iim.set(j, idx);
+ _data[idx].first=j;
+ }
+
+ }; // class DHeap
+
+} // namespace lemon
+
+#endif // LEMON_DHEAP_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/dijkstra.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/dijkstra.h
new file mode 100644
index 00000000000..1564a03e6ec
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/dijkstra.h
@@ -0,0 +1,1303 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_DIJKSTRA_H
+#define LEMON_DIJKSTRA_H
+
+///\ingroup shortest_path
+///\file
+///\brief Dijkstra algorithm.
+
+#include <limits>
+#include <lemon/list_graph.h>
+#include <lemon/bin_heap.h>
+#include <lemon/bits/path_dump.h>
+#include <lemon/core.h>
+#include <lemon/error.h>
+#include <lemon/maps.h>
+#include <lemon/path.h>
+
+namespace lemon {
+
+ /// \brief Default operation traits for the Dijkstra algorithm class.
+ ///
+ /// This operation traits class defines all computational operations and
+ /// constants which are used in the Dijkstra algorithm.
+ template <typename V>
+ struct DijkstraDefaultOperationTraits {
+ /// \e
+ typedef V Value;
+ /// \brief Gives back the zero value of the type.
+ static Value zero() {
+ return static_cast<Value>(0);
+ }
+ /// \brief Gives back the sum of the given two elements.
+ static Value plus(const Value& left, const Value& right) {
+ return left + right;
+ }
+ /// \brief Gives back true only if the first value is less than the second.
+ static bool less(const Value& left, const Value& right) {
+ return left < right;
+ }
+ };
+
+ ///Default traits class of Dijkstra class.
+
+ ///Default traits class of Dijkstra class.
+ ///\tparam GR The type of the digraph.
+ ///\tparam LEN The type of the length map.
+ template<typename GR, typename LEN>
+ struct DijkstraDefaultTraits
+ {
+ ///The type of the digraph the algorithm runs on.
+ typedef GR Digraph;
+
+ ///The type of the map that stores the arc lengths.
+
+ ///The type of the map that stores the arc lengths.
+ ///It must conform to the \ref concepts::ReadMap "ReadMap" concept.
+ typedef LEN LengthMap;
+ ///The type of the arc lengths.
+ typedef typename LEN::Value Value;
+
+ /// Operation traits for %Dijkstra algorithm.
+
+ /// This class defines the operations that are used in the algorithm.
+ /// \see DijkstraDefaultOperationTraits
+ typedef DijkstraDefaultOperationTraits<Value> OperationTraits;
+
+ /// The cross reference type used by the heap.
+
+ /// The cross reference type used by the heap.
+ /// Usually it is \c Digraph::NodeMap<int>.
+ typedef typename Digraph::template NodeMap<int> HeapCrossRef;
+ ///Instantiates a \c HeapCrossRef.
+
+ ///This function instantiates a \ref HeapCrossRef.
+ /// \param g is the digraph, to which we would like to define the
+ /// \ref HeapCrossRef.
+ static HeapCrossRef *createHeapCrossRef(const Digraph &g)
+ {
+ return new HeapCrossRef(g);
+ }
+
+ ///The heap type used by the %Dijkstra algorithm.
+
+ ///The heap type used by the Dijkstra algorithm.
+ ///
+ ///\sa BinHeap
+ ///\sa Dijkstra
+ typedef BinHeap<typename LEN::Value, HeapCrossRef, std::less<Value> > Heap;
+ ///Instantiates a \c Heap.
+
+ ///This function instantiates a \ref Heap.
+ static Heap *createHeap(HeapCrossRef& r)
+ {
+ return new Heap(r);
+ }
+
+ ///\brief The type of the map that stores the predecessor
+ ///arcs of the shortest paths.
+ ///
+ ///The type of the map that stores the predecessor
+ ///arcs of the shortest paths.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ typedef typename Digraph::template NodeMap<typename Digraph::Arc> PredMap;
+ ///Instantiates a \c PredMap.
+
+ ///This function instantiates a \ref PredMap.
+ ///\param g is the digraph, to which we would like to define the
+ ///\ref PredMap.
+ static PredMap *createPredMap(const Digraph &g)
+ {
+ return new PredMap(g);
+ }
+
+ ///The type of the map that indicates which nodes are processed.
+
+ ///The type of the map that indicates which nodes are processed.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ ///By default, it is a NullMap.
+ typedef NullMap<typename Digraph::Node,bool> ProcessedMap;
+ ///Instantiates a \c ProcessedMap.
+
+ ///This function instantiates a \ref ProcessedMap.
+ ///\param g is the digraph, to which
+ ///we would like to define the \ref ProcessedMap.
+#ifdef DOXYGEN
+ static ProcessedMap *createProcessedMap(const Digraph &g)
+#else
+ static ProcessedMap *createProcessedMap(const Digraph &)
+#endif
+ {
+ return new ProcessedMap();
+ }
+
+ ///The type of the map that stores the distances of the nodes.
+
+ ///The type of the map that stores the distances of the nodes.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ typedef typename Digraph::template NodeMap<typename LEN::Value> DistMap;
+ ///Instantiates a \c DistMap.
+
+ ///This function instantiates a \ref DistMap.
+ ///\param g is the digraph, to which we would like to define
+ ///the \ref DistMap.
+ static DistMap *createDistMap(const Digraph &g)
+ {
+ return new DistMap(g);
+ }
+ };
+
+ ///%Dijkstra algorithm class.
+
+ /// \ingroup shortest_path
+ ///This class provides an efficient implementation of the %Dijkstra algorithm.
+ ///
+ ///The %Dijkstra algorithm solves the single-source shortest path problem
+ ///when all arc lengths are non-negative. If there are negative lengths,
+ ///the BellmanFord algorithm should be used instead.
+ ///
+ ///The arc lengths are passed to the algorithm using a
+ ///\ref concepts::ReadMap "ReadMap",
+ ///so it is easy to change it to any kind of length.
+ ///The type of the length is determined by the
+ ///\ref concepts::ReadMap::Value "Value" of the length map.
+ ///It is also possible to change the underlying priority heap.
+ ///
+ ///There is also a \ref dijkstra() "function-type interface" for the
+ ///%Dijkstra algorithm, which is convenient in the simplier cases and
+ ///it can be used easier.
+ ///
+ ///\tparam GR The type of the digraph the algorithm runs on.
+ ///The default type is \ref ListDigraph.
+ ///\tparam LEN A \ref concepts::ReadMap "readable" arc map that specifies
+ ///the lengths of the arcs.
+ ///It is read once for each arc, so the map may involve in
+ ///relatively time consuming process to compute the arc lengths if
+ ///it is necessary. The default map type is \ref
+ ///concepts::Digraph::ArcMap "GR::ArcMap<int>".
+ ///\tparam TR The traits class that defines various types used by the
+ ///algorithm. By default, it is \ref DijkstraDefaultTraits
+ ///"DijkstraDefaultTraits<GR, LEN>".
+ ///In most cases, this parameter should not be set directly,
+ ///consider to use the named template parameters instead.
+#ifdef DOXYGEN
+ template <typename GR, typename LEN, typename TR>
+#else
+ template <typename GR=ListDigraph,
+ typename LEN=typename GR::template ArcMap<int>,
+ typename TR=DijkstraDefaultTraits<GR,LEN> >
+#endif
+ class Dijkstra {
+ public:
+
+ ///The type of the digraph the algorithm runs on.
+ typedef typename TR::Digraph Digraph;
+
+ ///The type of the arc lengths.
+ typedef typename TR::Value Value;
+ ///The type of the map that stores the arc lengths.
+ typedef typename TR::LengthMap LengthMap;
+ ///\brief The type of the map that stores the predecessor arcs of the
+ ///shortest paths.
+ typedef typename TR::PredMap PredMap;
+ ///The type of the map that stores the distances of the nodes.
+ typedef typename TR::DistMap DistMap;
+ ///The type of the map that indicates which nodes are processed.
+ typedef typename TR::ProcessedMap ProcessedMap;
+ ///The type of the paths.
+ typedef PredMapPath<Digraph, PredMap> Path;
+ ///The cross reference type used for the current heap.
+ typedef typename TR::HeapCrossRef HeapCrossRef;
+ ///The heap type used by the algorithm.
+ typedef typename TR::Heap Heap;
+ /// \brief The \ref lemon::DijkstraDefaultOperationTraits
+ /// "operation traits class" of the algorithm.
+ typedef typename TR::OperationTraits OperationTraits;
+
+ ///The \ref lemon::DijkstraDefaultTraits "traits class" of the algorithm.
+ typedef TR Traits;
+
+ private:
+
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::NodeIt NodeIt;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::OutArcIt OutArcIt;
+
+ //Pointer to the underlying digraph.
+ const Digraph *G;
+ //Pointer to the length map.
+ const LengthMap *_length;
+ //Pointer to the map of predecessors arcs.
+ PredMap *_pred;
+ //Indicates if _pred is locally allocated (true) or not.
+ bool local_pred;
+ //Pointer to the map of distances.
+ DistMap *_dist;
+ //Indicates if _dist is locally allocated (true) or not.
+ bool local_dist;
+ //Pointer to the map of processed status of the nodes.
+ ProcessedMap *_processed;
+ //Indicates if _processed is locally allocated (true) or not.
+ bool local_processed;
+ //Pointer to the heap cross references.
+ HeapCrossRef *_heap_cross_ref;
+ //Indicates if _heap_cross_ref is locally allocated (true) or not.
+ bool local_heap_cross_ref;
+ //Pointer to the heap.
+ Heap *_heap;
+ //Indicates if _heap is locally allocated (true) or not.
+ bool local_heap;
+
+ //Creates the maps if necessary.
+ void create_maps()
+ {
+ if(!_pred) {
+ local_pred = true;
+ _pred = Traits::createPredMap(*G);
+ }
+ if(!_dist) {
+ local_dist = true;
+ _dist = Traits::createDistMap(*G);
+ }
+ if(!_processed) {
+ local_processed = true;
+ _processed = Traits::createProcessedMap(*G);
+ }
+ if (!_heap_cross_ref) {
+ local_heap_cross_ref = true;
+ _heap_cross_ref = Traits::createHeapCrossRef(*G);
+ }
+ if (!_heap) {
+ local_heap = true;
+ _heap = Traits::createHeap(*_heap_cross_ref);
+ }
+ }
+
+ public:
+
+ typedef Dijkstra Create;
+
+ ///\name Named Template Parameters
+
+ ///@{
+
+ template <class T>
+ struct SetPredMapTraits : public Traits {
+ typedef T PredMap;
+ static PredMap *createPredMap(const Digraph &)
+ {
+ LEMON_ASSERT(false, "PredMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///\c PredMap type.
+ ///
+ ///\ref named-templ-param "Named parameter" for setting
+ ///\c PredMap type.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ template <class T>
+ struct SetPredMap
+ : public Dijkstra< Digraph, LengthMap, SetPredMapTraits<T> > {
+ typedef Dijkstra< Digraph, LengthMap, SetPredMapTraits<T> > Create;
+ };
+
+ template <class T>
+ struct SetDistMapTraits : public Traits {
+ typedef T DistMap;
+ static DistMap *createDistMap(const Digraph &)
+ {
+ LEMON_ASSERT(false, "DistMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///\c DistMap type.
+ ///
+ ///\ref named-templ-param "Named parameter" for setting
+ ///\c DistMap type.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ template <class T>
+ struct SetDistMap
+ : public Dijkstra< Digraph, LengthMap, SetDistMapTraits<T> > {
+ typedef Dijkstra< Digraph, LengthMap, SetDistMapTraits<T> > Create;
+ };
+
+ template <class T>
+ struct SetProcessedMapTraits : public Traits {
+ typedef T ProcessedMap;
+ static ProcessedMap *createProcessedMap(const Digraph &)
+ {
+ LEMON_ASSERT(false, "ProcessedMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///\c ProcessedMap type.
+ ///
+ ///\ref named-templ-param "Named parameter" for setting
+ ///\c ProcessedMap type.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ template <class T>
+ struct SetProcessedMap
+ : public Dijkstra< Digraph, LengthMap, SetProcessedMapTraits<T> > {
+ typedef Dijkstra< Digraph, LengthMap, SetProcessedMapTraits<T> > Create;
+ };
+
+ struct SetStandardProcessedMapTraits : public Traits {
+ typedef typename Digraph::template NodeMap<bool> ProcessedMap;
+ static ProcessedMap *createProcessedMap(const Digraph &g)
+ {
+ return new ProcessedMap(g);
+ }
+ };
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///\c ProcessedMap type to be <tt>Digraph::NodeMap<bool></tt>.
+ ///
+ ///\ref named-templ-param "Named parameter" for setting
+ ///\c ProcessedMap type to be <tt>Digraph::NodeMap<bool></tt>.
+ ///If you don't set it explicitly, it will be automatically allocated.
+ struct SetStandardProcessedMap
+ : public Dijkstra< Digraph, LengthMap, SetStandardProcessedMapTraits > {
+ typedef Dijkstra< Digraph, LengthMap, SetStandardProcessedMapTraits >
+ Create;
+ };
+
+ template <class H, class CR>
+ struct SetHeapTraits : public Traits {
+ typedef CR HeapCrossRef;
+ typedef H Heap;
+ static HeapCrossRef *createHeapCrossRef(const Digraph &) {
+ LEMON_ASSERT(false, "HeapCrossRef is not initialized");
+ return 0; // ignore warnings
+ }
+ static Heap *createHeap(HeapCrossRef &)
+ {
+ LEMON_ASSERT(false, "Heap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///heap and cross reference types
+ ///
+ ///\ref named-templ-param "Named parameter" for setting heap and cross
+ ///reference types. If this named parameter is used, then external
+ ///heap and cross reference objects must be passed to the algorithm
+ ///using the \ref heap() function before calling \ref run(Node) "run()"
+ ///or \ref init().
+ ///\sa SetStandardHeap
+ template <class H, class CR = typename Digraph::template NodeMap<int> >
+ struct SetHeap
+ : public Dijkstra< Digraph, LengthMap, SetHeapTraits<H, CR> > {
+ typedef Dijkstra< Digraph, LengthMap, SetHeapTraits<H, CR> > Create;
+ };
+
+ template <class H, class CR>
+ struct SetStandardHeapTraits : public Traits {
+ typedef CR HeapCrossRef;
+ typedef H Heap;
+ static HeapCrossRef *createHeapCrossRef(const Digraph &G) {
+ return new HeapCrossRef(G);
+ }
+ static Heap *createHeap(HeapCrossRef &R)
+ {
+ return new Heap(R);
+ }
+ };
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///heap and cross reference types with automatic allocation
+ ///
+ ///\ref named-templ-param "Named parameter" for setting heap and cross
+ ///reference types with automatic allocation.
+ ///They should have standard constructor interfaces to be able to
+ ///automatically created by the algorithm (i.e. the digraph should be
+ ///passed to the constructor of the cross reference and the cross
+ ///reference should be passed to the constructor of the heap).
+ ///However, external heap and cross reference objects could also be
+ ///passed to the algorithm using the \ref heap() function before
+ ///calling \ref run(Node) "run()" or \ref init().
+ ///\sa SetHeap
+ template <class H, class CR = typename Digraph::template NodeMap<int> >
+ struct SetStandardHeap
+ : public Dijkstra< Digraph, LengthMap, SetStandardHeapTraits<H, CR> > {
+ typedef Dijkstra< Digraph, LengthMap, SetStandardHeapTraits<H, CR> >
+ Create;
+ };
+
+ template <class T>
+ struct SetOperationTraitsTraits : public Traits {
+ typedef T OperationTraits;
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ ///\c OperationTraits type
+ ///
+ ///\ref named-templ-param "Named parameter" for setting
+ ///\c OperationTraits type.
+ /// For more information, see \ref DijkstraDefaultOperationTraits.
+ template <class T>
+ struct SetOperationTraits
+ : public Dijkstra<Digraph, LengthMap, SetOperationTraitsTraits<T> > {
+ typedef Dijkstra<Digraph, LengthMap, SetOperationTraitsTraits<T> >
+ Create;
+ };
+
+ ///@}
+
+ protected:
+
+ Dijkstra() {}
+
+ public:
+
+ ///Constructor.
+
+ ///Constructor.
+ ///\param g The digraph the algorithm runs on.
+ ///\param length The length map used by the algorithm.
+ Dijkstra(const Digraph& g, const LengthMap& length) :
+ G(&g), _length(&length),
+ _pred(NULL), local_pred(false),
+ _dist(NULL), local_dist(false),
+ _processed(NULL), local_processed(false),
+ _heap_cross_ref(NULL), local_heap_cross_ref(false),
+ _heap(NULL), local_heap(false)
+ { }
+
+ ///Destructor.
+ ~Dijkstra()
+ {
+ if(local_pred) delete _pred;
+ if(local_dist) delete _dist;
+ if(local_processed) delete _processed;
+ if(local_heap_cross_ref) delete _heap_cross_ref;
+ if(local_heap) delete _heap;
+ }
+
+ ///Sets the length map.
+
+ ///Sets the length map.
+ ///\return <tt> (*this) </tt>
+ Dijkstra &lengthMap(const LengthMap &m)
+ {
+ _length = &m;
+ return *this;
+ }
+
+ ///Sets the map that stores the predecessor arcs.
+
+ ///Sets the map that stores the predecessor arcs.
+ ///If you don't use this function before calling \ref run(Node) "run()"
+ ///or \ref init(), an instance will be allocated automatically.
+ ///The destructor deallocates this automatically allocated map,
+ ///of course.
+ ///\return <tt> (*this) </tt>
+ Dijkstra &predMap(PredMap &m)
+ {
+ if(local_pred) {
+ delete _pred;
+ local_pred=false;
+ }
+ _pred = &m;
+ return *this;
+ }
+
+ ///Sets the map that indicates which nodes are processed.
+
+ ///Sets the map that indicates which nodes are processed.
+ ///If you don't use this function before calling \ref run(Node) "run()"
+ ///or \ref init(), an instance will be allocated automatically.
+ ///The destructor deallocates this automatically allocated map,
+ ///of course.
+ ///\return <tt> (*this) </tt>
+ Dijkstra &processedMap(ProcessedMap &m)
+ {
+ if(local_processed) {
+ delete _processed;
+ local_processed=false;
+ }
+ _processed = &m;
+ return *this;
+ }
+
+ ///Sets the map that stores the distances of the nodes.
+
+ ///Sets the map that stores the distances of the nodes calculated by the
+ ///algorithm.
+ ///If you don't use this function before calling \ref run(Node) "run()"
+ ///or \ref init(), an instance will be allocated automatically.
+ ///The destructor deallocates this automatically allocated map,
+ ///of course.
+ ///\return <tt> (*this) </tt>
+ Dijkstra &distMap(DistMap &m)
+ {
+ if(local_dist) {
+ delete _dist;
+ local_dist=false;
+ }
+ _dist = &m;
+ return *this;
+ }
+
+ ///Sets the heap and the cross reference used by algorithm.
+
+ ///Sets the heap and the cross reference used by algorithm.
+ ///If you don't use this function before calling \ref run(Node) "run()"
+ ///or \ref init(), heap and cross reference instances will be
+ ///allocated automatically.
+ ///The destructor deallocates these automatically allocated objects,
+ ///of course.
+ ///\return <tt> (*this) </tt>
+ Dijkstra &heap(Heap& hp, HeapCrossRef &cr)
+ {
+ if(local_heap_cross_ref) {
+ delete _heap_cross_ref;
+ local_heap_cross_ref=false;
+ }
+ _heap_cross_ref = &cr;
+ if(local_heap) {
+ delete _heap;
+ local_heap=false;
+ }
+ _heap = &hp;
+ return *this;
+ }
+
+ private:
+
+ void finalizeNodeData(Node v,Value dst)
+ {
+ _processed->set(v,true);
+ _dist->set(v, dst);
+ }
+
+ public:
+
+ ///\name Execution Control
+ ///The simplest way to execute the %Dijkstra algorithm is to use
+ ///one of the member functions called \ref run(Node) "run()".\n
+ ///If you need better control on the execution, you have to call
+ ///\ref init() first, then you can add several source nodes with
+ ///\ref addSource(). Finally the actual path computation can be
+ ///performed with one of the \ref start() functions.
+
+ ///@{
+
+ ///\brief Initializes the internal data structures.
+ ///
+ ///Initializes the internal data structures.
+ void init()
+ {
+ create_maps();
+ _heap->clear();
+ for ( NodeIt u(*G) ; u!=INVALID ; ++u ) {
+ _pred->set(u,INVALID);
+ _processed->set(u,false);
+ _heap_cross_ref->set(u,Heap::PRE_HEAP);
+ }
+ }
+
+ ///Adds a new source node.
+
+ ///Adds a new source node to the priority heap.
+ ///The optional second parameter is the initial distance of the node.
+ ///
+ ///The function checks if the node has already been added to the heap and
+ ///it is pushed to the heap only if either it was not in the heap
+ ///or the shortest path found till then is shorter than \c dst.
+ void addSource(Node s,Value dst=OperationTraits::zero())
+ {
+ if(_heap->state(s) != Heap::IN_HEAP) {
+ _heap->push(s,dst);
+ } else if(OperationTraits::less((*_heap)[s], dst)) {
+ _heap->set(s,dst);
+ _pred->set(s,INVALID);
+ }
+ }
+
+ ///Processes the next node in the priority heap
+
+ ///Processes the next node in the priority heap.
+ ///
+ ///\return The processed node.
+ ///
+ ///\warning The priority heap must not be empty.
+ Node processNextNode()
+ {
+ Node v=_heap->top();
+ Value oldvalue=_heap->prio();
+ _heap->pop();
+ finalizeNodeData(v,oldvalue);
+
+ for(OutArcIt e(*G,v); e!=INVALID; ++e) {
+ Node w=G->target(e);
+ switch(_heap->state(w)) {
+ case Heap::PRE_HEAP:
+ _heap->push(w,OperationTraits::plus(oldvalue, (*_length)[e]));
+ _pred->set(w,e);
+ break;
+ case Heap::IN_HEAP:
+ {
+ Value newvalue = OperationTraits::plus(oldvalue, (*_length)[e]);
+ if ( OperationTraits::less(newvalue, (*_heap)[w]) ) {
+ _heap->decrease(w, newvalue);
+ _pred->set(w,e);
+ }
+ }
+ break;
+ case Heap::POST_HEAP:
+ break;
+ }
+ }
+ return v;
+ }
+
+ ///The next node to be processed.
+
+ ///Returns the next node to be processed or \c INVALID if the
+ ///priority heap is empty.
+ Node nextNode() const
+ {
+ return !_heap->empty()?_heap->top():INVALID;
+ }
+
+ ///Returns \c false if there are nodes to be processed.
+
+ ///Returns \c false if there are nodes to be processed
+ ///in the priority heap.
+ bool emptyQueue() const { return _heap->empty(); }
+
+ ///Returns the number of the nodes to be processed.
+
+ ///Returns the number of the nodes to be processed
+ ///in the priority heap.
+ int queueSize() const { return _heap->size(); }
+
+ ///Executes the algorithm.
+
+ ///Executes the algorithm.
+ ///
+ ///This method runs the %Dijkstra algorithm from the root node(s)
+ ///in order to compute the shortest path to each node.
+ ///
+ ///The algorithm computes
+ ///- the shortest path tree (forest),
+ ///- the distance of each node from the root(s).
+ ///
+ ///\pre init() must be called and at least one root node should be
+ ///added with addSource() before using this function.
+ ///
+ ///\note <tt>d.start()</tt> is just a shortcut of the following code.
+ ///\code
+ /// while ( !d.emptyQueue() ) {
+ /// d.processNextNode();
+ /// }
+ ///\endcode
+ void start()
+ {
+ while ( !emptyQueue() ) processNextNode();
+ }
+
+ ///Executes the algorithm until the given target node is processed.
+
+ ///Executes the algorithm until the given target node is processed.
+ ///
+ ///This method runs the %Dijkstra algorithm from the root node(s)
+ ///in order to compute the shortest path to \c t.
+ ///
+ ///The algorithm computes
+ ///- the shortest path to \c t,
+ ///- the distance of \c t from the root(s).
+ ///
+ ///\pre init() must be called and at least one root node should be
+ ///added with addSource() before using this function.
+ void start(Node t)
+ {
+ while ( !_heap->empty() && _heap->top()!=t ) processNextNode();
+ if ( !_heap->empty() ) {
+ finalizeNodeData(_heap->top(),_heap->prio());
+ _heap->pop();
+ }
+ }
+
+ ///Executes the algorithm until a condition is met.
+
+ ///Executes the algorithm until a condition is met.
+ ///
+ ///This method runs the %Dijkstra algorithm from the root node(s) in
+ ///order to compute the shortest path to a node \c v with
+ /// <tt>nm[v]</tt> true, if such a node can be found.
+ ///
+ ///\param nm A \c bool (or convertible) node map. The algorithm
+ ///will stop when it reaches a node \c v with <tt>nm[v]</tt> true.
+ ///
+ ///\return The reached node \c v with <tt>nm[v]</tt> true or
+ ///\c INVALID if no such node was found.
+ ///
+ ///\pre init() must be called and at least one root node should be
+ ///added with addSource() before using this function.
+ template<class NodeBoolMap>
+ Node start(const NodeBoolMap &nm)
+ {
+ while ( !_heap->empty() && !nm[_heap->top()] ) processNextNode();
+ if ( _heap->empty() ) return INVALID;
+ finalizeNodeData(_heap->top(),_heap->prio());
+ return _heap->top();
+ }
+
+ ///Runs the algorithm from the given source node.
+
+ ///This method runs the %Dijkstra algorithm from node \c s
+ ///in order to compute the shortest path to each node.
+ ///
+ ///The algorithm computes
+ ///- the shortest path tree,
+ ///- the distance of each node from the root.
+ ///
+ ///\note <tt>d.run(s)</tt> is just a shortcut of the following code.
+ ///\code
+ /// d.init();
+ /// d.addSource(s);
+ /// d.start();
+ ///\endcode
+ void run(Node s) {
+ init();
+ addSource(s);
+ start();
+ }
+
+ ///Finds the shortest path between \c s and \c t.
+
+ ///This method runs the %Dijkstra algorithm from node \c s
+ ///in order to compute the shortest path to node \c t
+ ///(it stops searching when \c t is processed).
+ ///
+ ///\return \c true if \c t is reachable form \c s.
+ ///
+ ///\note Apart from the return value, <tt>d.run(s,t)</tt> is just a
+ ///shortcut of the following code.
+ ///\code
+ /// d.init();
+ /// d.addSource(s);
+ /// d.start(t);
+ ///\endcode
+ bool run(Node s,Node t) {
+ init();
+ addSource(s);
+ start(t);
+ return (*_heap_cross_ref)[t] == Heap::POST_HEAP;
+ }
+
+ ///@}
+
+ ///\name Query Functions
+ ///The results of the %Dijkstra algorithm can be obtained using these
+ ///functions.\n
+ ///Either \ref run(Node) "run()" or \ref init() should be called
+ ///before using them.
+
+ ///@{
+
+ ///The shortest path to the given node.
+
+ ///Returns the shortest path to the given node from the root(s).
+ ///
+ ///\warning \c t should be reached from the root(s).
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ Path path(Node t) const { return Path(*G, *_pred, t); }
+
+ ///The distance of the given node from the root(s).
+
+ ///Returns the distance of the given node from the root(s).
+ ///
+ ///\warning If node \c v is not reached from the root(s), then
+ ///the return value of this function is undefined.
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ Value dist(Node v) const { return (*_dist)[v]; }
+
+ ///\brief Returns the 'previous arc' of the shortest path tree for
+ ///the given node.
+ ///
+ ///This function returns the 'previous arc' of the shortest path
+ ///tree for the node \c v, i.e. it returns the last arc of a
+ ///shortest path from a root to \c v. It is \c INVALID if \c v
+ ///is not reached from the root(s) or if \c v is a root.
+ ///
+ ///The shortest path tree used here is equal to the shortest path
+ ///tree used in \ref predNode() and \ref predMap().
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ Arc predArc(Node v) const { return (*_pred)[v]; }
+
+ ///\brief Returns the 'previous node' of the shortest path tree for
+ ///the given node.
+ ///
+ ///This function returns the 'previous node' of the shortest path
+ ///tree for the node \c v, i.e. it returns the last but one node
+ ///of a shortest path from a root to \c v. It is \c INVALID
+ ///if \c v is not reached from the root(s) or if \c v is a root.
+ ///
+ ///The shortest path tree used here is equal to the shortest path
+ ///tree used in \ref predArc() and \ref predMap().
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID:
+ G->source((*_pred)[v]); }
+
+ ///\brief Returns a const reference to the node map that stores the
+ ///distances of the nodes.
+ ///
+ ///Returns a const reference to the node map that stores the distances
+ ///of the nodes calculated by the algorithm.
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ const DistMap &distMap() const { return *_dist;}
+
+ ///\brief Returns a const reference to the node map that stores the
+ ///predecessor arcs.
+ ///
+ ///Returns a const reference to the node map that stores the predecessor
+ ///arcs, which form the shortest path tree (forest).
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ const PredMap &predMap() const { return *_pred;}
+
+ ///Checks if the given node is reached from the root(s).
+
+ ///Returns \c true if \c v is reached from the root(s).
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ bool reached(Node v) const { return (*_heap_cross_ref)[v] !=
+ Heap::PRE_HEAP; }
+
+ ///Checks if a node is processed.
+
+ ///Returns \c true if \c v is processed, i.e. the shortest
+ ///path to \c v has already found.
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function.
+ bool processed(Node v) const { return (*_heap_cross_ref)[v] ==
+ Heap::POST_HEAP; }
+
+ ///The current distance of the given node from the root(s).
+
+ ///Returns the current distance of the given node from the root(s).
+ ///It may be decreased in the following processes.
+ ///
+ ///\pre Either \ref run(Node) "run()" or \ref init()
+ ///must be called before using this function and
+ ///node \c v must be reached but not necessarily processed.
+ Value currentDist(Node v) const {
+ return processed(v) ? (*_dist)[v] : (*_heap)[v];
+ }
+
+ ///@}
+ };
+
+
+ ///Default traits class of dijkstra() function.
+
+ ///Default traits class of dijkstra() function.
+ ///\tparam GR The type of the digraph.
+ ///\tparam LEN The type of the length map.
+ template<class GR, class LEN>
+ struct DijkstraWizardDefaultTraits
+ {
+ ///The type of the digraph the algorithm runs on.
+ typedef GR Digraph;
+ ///The type of the map that stores the arc lengths.
+
+ ///The type of the map that stores the arc lengths.
+ ///It must conform to the \ref concepts::ReadMap "ReadMap" concept.
+ typedef LEN LengthMap;
+ ///The type of the arc lengths.
+ typedef typename LEN::Value Value;
+
+ /// Operation traits for Dijkstra algorithm.
+
+ /// This class defines the operations that are used in the algorithm.
+ /// \see DijkstraDefaultOperationTraits
+ typedef DijkstraDefaultOperationTraits<Value> OperationTraits;
+
+ /// The cross reference type used by the heap.
+
+ /// The cross reference type used by the heap.
+ /// Usually it is \c Digraph::NodeMap<int>.
+ typedef typename Digraph::template NodeMap<int> HeapCrossRef;
+ ///Instantiates a \ref HeapCrossRef.
+
+ ///This function instantiates a \ref HeapCrossRef.
+ /// \param g is the digraph, to which we would like to define the
+ /// HeapCrossRef.
+ static HeapCrossRef *createHeapCrossRef(const Digraph &g)
+ {
+ return new HeapCrossRef(g);
+ }
+
+ ///The heap type used by the Dijkstra algorithm.
+
+ ///The heap type used by the Dijkstra algorithm.
+ ///
+ ///\sa BinHeap
+ ///\sa Dijkstra
+ typedef BinHeap<Value, typename Digraph::template NodeMap<int>,
+ std::less<Value> > Heap;
+
+ ///Instantiates a \ref Heap.
+
+ ///This function instantiates a \ref Heap.
+ /// \param r is the HeapCrossRef which is used.
+ static Heap *createHeap(HeapCrossRef& r)
+ {
+ return new Heap(r);
+ }
+
+ ///\brief The type of the map that stores the predecessor
+ ///arcs of the shortest paths.
+ ///
+ ///The type of the map that stores the predecessor
+ ///arcs of the shortest paths.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ typedef typename Digraph::template NodeMap<typename Digraph::Arc> PredMap;
+ ///Instantiates a PredMap.
+
+ ///This function instantiates a PredMap.
+ ///\param g is the digraph, to which we would like to define the
+ ///PredMap.
+ static PredMap *createPredMap(const Digraph &g)
+ {
+ return new PredMap(g);
+ }
+
+ ///The type of the map that indicates which nodes are processed.
+
+ ///The type of the map that indicates which nodes are processed.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ ///By default, it is a NullMap.
+ typedef NullMap<typename Digraph::Node,bool> ProcessedMap;
+ ///Instantiates a ProcessedMap.
+
+ ///This function instantiates a ProcessedMap.
+ ///\param g is the digraph, to which
+ ///we would like to define the ProcessedMap.
+#ifdef DOXYGEN
+ static ProcessedMap *createProcessedMap(const Digraph &g)
+#else
+ static ProcessedMap *createProcessedMap(const Digraph &)
+#endif
+ {
+ return new ProcessedMap();
+ }
+
+ ///The type of the map that stores the distances of the nodes.
+
+ ///The type of the map that stores the distances of the nodes.
+ ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ typedef typename Digraph::template NodeMap<typename LEN::Value> DistMap;
+ ///Instantiates a DistMap.
+
+ ///This function instantiates a DistMap.
+ ///\param g is the digraph, to which we would like to define
+ ///the DistMap
+ static DistMap *createDistMap(const Digraph &g)
+ {
+ return new DistMap(g);
+ }
+
+ ///The type of the shortest paths.
+
+ ///The type of the shortest paths.
+ ///It must conform to the \ref concepts::Path "Path" concept.
+ typedef lemon::Path<Digraph> Path;
+ };
+
+ /// Default traits class used by DijkstraWizard
+
+ /// Default traits class used by DijkstraWizard.
+ /// \tparam GR The type of the digraph.
+ /// \tparam LEN The type of the length map.
+ template<typename GR, typename LEN>
+ class DijkstraWizardBase : public DijkstraWizardDefaultTraits<GR,LEN>
+ {
+ typedef DijkstraWizardDefaultTraits<GR,LEN> Base;
+ protected:
+ //The type of the nodes in the digraph.
+ typedef typename Base::Digraph::Node Node;
+
+ //Pointer to the digraph the algorithm runs on.
+ void *_g;
+ //Pointer to the length map.
+ void *_length;
+ //Pointer to the map of processed nodes.
+ void *_processed;
+ //Pointer to the map of predecessors arcs.
+ void *_pred;
+ //Pointer to the map of distances.
+ void *_dist;
+ //Pointer to the shortest path to the target node.
+ void *_path;
+ //Pointer to the distance of the target node.
+ void *_di;
+
+ public:
+ /// Constructor.
+
+ /// This constructor does not require parameters, therefore it initiates
+ /// all of the attributes to \c 0.
+ DijkstraWizardBase() : _g(0), _length(0), _processed(0), _pred(0),
+ _dist(0), _path(0), _di(0) {}
+
+ /// Constructor.
+
+ /// This constructor requires two parameters,
+ /// others are initiated to \c 0.
+ /// \param g The digraph the algorithm runs on.
+ /// \param l The length map.
+ DijkstraWizardBase(const GR &g,const LEN &l) :
+ _g(reinterpret_cast<void*>(const_cast<GR*>(&g))),
+ _length(reinterpret_cast<void*>(const_cast<LEN*>(&l))),
+ _processed(0), _pred(0), _dist(0), _path(0), _di(0) {}
+
+ };
+
+ /// Auxiliary class for the function-type interface of Dijkstra algorithm.
+
+ /// This auxiliary class is created to implement the
+ /// \ref dijkstra() "function-type interface" of \ref Dijkstra algorithm.
+ /// It does not have own \ref run(Node) "run()" method, it uses the
+ /// functions and features of the plain \ref Dijkstra.
+ ///
+ /// This class should only be used through the \ref dijkstra() function,
+ /// which makes it easier to use the algorithm.
+ ///
+ /// \tparam TR The traits class that defines various types used by the
+ /// algorithm.
+ template<class TR>
+ class DijkstraWizard : public TR
+ {
+ typedef TR Base;
+
+ typedef typename TR::Digraph Digraph;
+
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::NodeIt NodeIt;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::OutArcIt OutArcIt;
+
+ typedef typename TR::LengthMap LengthMap;
+ typedef typename LengthMap::Value Value;
+ typedef typename TR::PredMap PredMap;
+ typedef typename TR::DistMap DistMap;
+ typedef typename TR::ProcessedMap ProcessedMap;
+ typedef typename TR::Path Path;
+ typedef typename TR::Heap Heap;
+
+ public:
+
+ /// Constructor.
+ DijkstraWizard() : TR() {}
+
+ /// Constructor that requires parameters.
+
+ /// Constructor that requires parameters.
+ /// These parameters will be the default values for the traits class.
+ /// \param g The digraph the algorithm runs on.
+ /// \param l The length map.
+ DijkstraWizard(const Digraph &g, const LengthMap &l) :
+ TR(g,l) {}
+
+ ///Copy constructor
+ DijkstraWizard(const TR &b) : TR(b) {}
+
+ ~DijkstraWizard() {}
+
+ ///Runs Dijkstra algorithm from the given source node.
+
+ ///This method runs %Dijkstra algorithm from the given source node
+ ///in order to compute the shortest path to each node.
+ void run(Node s)
+ {
+ Dijkstra<Digraph,LengthMap,TR>
+ dijk(*reinterpret_cast<const Digraph*>(Base::_g),
+ *reinterpret_cast<const LengthMap*>(Base::_length));
+ if (Base::_pred)
+ dijk.predMap(*reinterpret_cast<PredMap*>(Base::_pred));
+ if (Base::_dist)
+ dijk.distMap(*reinterpret_cast<DistMap*>(Base::_dist));
+ if (Base::_processed)
+ dijk.processedMap(*reinterpret_cast<ProcessedMap*>(Base::_processed));
+ dijk.run(s);
+ }
+
+ ///Finds the shortest path between \c s and \c t.
+
+ ///This method runs the %Dijkstra algorithm from node \c s
+ ///in order to compute the shortest path to node \c t
+ ///(it stops searching when \c t is processed).
+ ///
+ ///\return \c true if \c t is reachable form \c s.
+ bool run(Node s, Node t)
+ {
+ Dijkstra<Digraph,LengthMap,TR>
+ dijk(*reinterpret_cast<const Digraph*>(Base::_g),
+ *reinterpret_cast<const LengthMap*>(Base::_length));
+ if (Base::_pred)
+ dijk.predMap(*reinterpret_cast<PredMap*>(Base::_pred));
+ if (Base::_dist)
+ dijk.distMap(*reinterpret_cast<DistMap*>(Base::_dist));
+ if (Base::_processed)
+ dijk.processedMap(*reinterpret_cast<ProcessedMap*>(Base::_processed));
+ dijk.run(s,t);
+ if (Base::_path)
+ *reinterpret_cast<Path*>(Base::_path) = dijk.path(t);
+ if (Base::_di)
+ *reinterpret_cast<Value*>(Base::_di) = dijk.dist(t);
+ return dijk.reached(t);
+ }
+
+ template<class T>
+ struct SetPredMapBase : public Base {
+ typedef T PredMap;
+ static PredMap *createPredMap(const Digraph &) { return 0; };
+ SetPredMapBase(const TR &b) : TR(b) {}
+ };
+
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///the predecessor map.
+ ///
+ ///\ref named-templ-param "Named parameter" function for setting
+ ///the map that stores the predecessor arcs of the nodes.
+ template<class T>
+ DijkstraWizard<SetPredMapBase<T> > predMap(const T &t)
+ {
+ Base::_pred=reinterpret_cast<void*>(const_cast<T*>(&t));
+ return DijkstraWizard<SetPredMapBase<T> >(*this);
+ }
+
+ template<class T>
+ struct SetDistMapBase : public Base {
+ typedef T DistMap;
+ static DistMap *createDistMap(const Digraph &) { return 0; };
+ SetDistMapBase(const TR &b) : TR(b) {}
+ };
+
+ ///\brief \ref named-templ-param "Named parameter" for setting
+ ///the distance map.
+ ///
+ ///\ref named-templ-param "Named parameter" function for setting
+ ///the map that stores the distances of the nodes calculated
+ ///by the algorithm.
+ template<class T>
+ DijkstraWizard<SetDistMapBase<T> > distMap(const T &t)
+ {
+ Base::_dist=reinterpret_cast<void*>(const_cast<T*>(&t));
+ return DijkstraWizard<SetDistMapBase<T> >(*this);
+ }
+
+ template<class T>
+ struct SetProcessedMapBase : public Base {
+ typedef T ProcessedMap;
+ static ProcessedMap *createProcessedMap(const Digraph &) { return 0; };
+ SetProcessedMapBase(const TR &b) : TR(b) {}
+ };
+
+ ///\brief \ref named-func-param "Named parameter" for setting
+ ///the processed map.
+ ///
+ ///\ref named-templ-param "Named parameter" function for setting
+ ///the map that indicates which nodes are processed.
+ template<class T>
+ DijkstraWizard<SetProcessedMapBase<T> > processedMap(const T &t)
+ {
+ Base::_processed=reinterpret_cast<void*>(const_cast<T*>(&t));
+ return DijkstraWizard<SetProcessedMapBase<T> >(*this);
+ }
+
+ template<class T>
+ struct SetPathBase : public Base {
+ typedef T Path;
+ SetPathBase(const TR &b) : TR(b) {}
+ };
+
+ ///\brief \ref named-func-param "Named parameter"
+ ///for getting the shortest path to the target node.
+ ///
+ ///\ref named-func-param "Named parameter"
+ ///for getting the shortest path to the target node.
+ template<class T>
+ DijkstraWizard<SetPathBase<T> > path(const T &t)
+ {
+ Base::_path=reinterpret_cast<void*>(const_cast<T*>(&t));
+ return DijkstraWizard<SetPathBase<T> >(*this);
+ }
+
+ ///\brief \ref named-func-param "Named parameter"
+ ///for getting the distance of the target node.
+ ///
+ ///\ref named-func-param "Named parameter"
+ ///for getting the distance of the target node.
+ DijkstraWizard dist(const Value &d)
+ {
+ Base::_di=reinterpret_cast<void*>(const_cast<Value*>(&d));
+ return *this;
+ }
+
+ };
+
+ ///Function-type interface for Dijkstra algorithm.
+
+ /// \ingroup shortest_path
+ ///Function-type interface for Dijkstra algorithm.
+ ///
+ ///This function also has several \ref named-func-param "named parameters",
+ ///they are declared as the members of class \ref DijkstraWizard.
+ ///The following examples show how to use these parameters.
+ ///\code
+ /// // Compute shortest path from node s to each node
+ /// dijkstra(g,length).predMap(preds).distMap(dists).run(s);
+ ///
+ /// // Compute shortest path from s to t
+ /// bool reached = dijkstra(g,length).path(p).dist(d).run(s,t);
+ ///\endcode
+ ///\warning Don't forget to put the \ref DijkstraWizard::run(Node) "run()"
+ ///to the end of the parameter list.
+ ///\sa DijkstraWizard
+ ///\sa Dijkstra
+ template<typename GR, typename LEN>
+ DijkstraWizard<DijkstraWizardBase<GR,LEN> >
+ dijkstra(const GR &digraph, const LEN &length)
+ {
+ return DijkstraWizard<DijkstraWizardBase<GR,LEN> >(digraph,length);
+ }
+
+} //END OF NAMESPACE LEMON
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/dim2.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/dim2.h
new file mode 100644
index 00000000000..0b14221060f
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/dim2.h
@@ -0,0 +1,726 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_DIM2_H
+#define LEMON_DIM2_H
+
+#include <iostream>
+#include <algorithm>
+
+///\ingroup geomdat
+///\file
+///\brief A simple two dimensional vector and a bounding box implementation
+
+namespace lemon {
+
+ ///Tools for handling two dimensional coordinates
+
+ ///This namespace is a storage of several
+ ///tools for handling two dimensional coordinates
+ namespace dim2 {
+
+ /// \addtogroup geomdat
+ /// @{
+
+ /// Two dimensional vector (plain vector)
+
+ /// A simple two dimensional vector (plain vector) implementation
+ /// with the usual vector operations.
+ template<typename T>
+ class Point {
+
+ public:
+
+ typedef T Value;
+
+ ///First coordinate
+ T x;
+ ///Second coordinate
+ T y;
+
+ ///Default constructor
+ Point() {}
+
+ ///Construct an instance from coordinates
+ Point(T a, T b) : x(a), y(b) { }
+
+ ///Returns the dimension of the vector (i.e. returns 2).
+
+ ///The dimension of the vector.
+ ///This function always returns 2.
+ int size() const { return 2; }
+
+ ///Subscripting operator
+
+ ///\c p[0] is \c p.x and \c p[1] is \c p.y
+ ///
+ T& operator[](int idx) { return idx == 0 ? x : y; }
+
+ ///Const subscripting operator
+
+ ///\c p[0] is \c p.x and \c p[1] is \c p.y
+ ///
+ const T& operator[](int idx) const { return idx == 0 ? x : y; }
+
+ ///Conversion constructor
+ template<class TT> Point(const Point<TT> &p) : x(p.x), y(p.y) {}
+
+ ///Give back the square of the norm of the vector
+ T normSquare() const {
+ return x*x+y*y;
+ }
+
+ ///Increment the left hand side by \c u
+ Point<T>& operator +=(const Point<T>& u) {
+ x += u.x;
+ y += u.y;
+ return *this;
+ }
+
+ ///Decrement the left hand side by \c u
+ Point<T>& operator -=(const Point<T>& u) {
+ x -= u.x;
+ y -= u.y;
+ return *this;
+ }
+
+ ///Multiply the left hand side with a scalar
+ Point<T>& operator *=(const T &u) {
+ x *= u;
+ y *= u;
+ return *this;
+ }
+
+ ///Divide the left hand side by a scalar
+ Point<T>& operator /=(const T &u) {
+ x /= u;
+ y /= u;
+ return *this;
+ }
+
+ ///Return the scalar product of two vectors
+ T operator *(const Point<T>& u) const {
+ return x*u.x+y*u.y;
+ }
+
+ ///Return the sum of two vectors
+ Point<T> operator+(const Point<T> &u) const {
+ Point<T> b=*this;
+ return b+=u;
+ }
+
+ ///Return the negative of the vector
+ Point<T> operator-() const {
+ Point<T> b=*this;
+ b.x=-b.x; b.y=-b.y;
+ return b;
+ }
+
+ ///Return the difference of two vectors
+ Point<T> operator-(const Point<T> &u) const {
+ Point<T> b=*this;
+ return b-=u;
+ }
+
+ ///Return a vector multiplied by a scalar
+ Point<T> operator*(const T &u) const {
+ Point<T> b=*this;
+ return b*=u;
+ }
+
+ ///Return a vector divided by a scalar
+ Point<T> operator/(const T &u) const {
+ Point<T> b=*this;
+ return b/=u;
+ }
+
+ ///Test equality
+ bool operator==(const Point<T> &u) const {
+ return (x==u.x) && (y==u.y);
+ }
+
+ ///Test inequality
+ bool operator!=(Point u) const {
+ return (x!=u.x) || (y!=u.y);
+ }
+
+ };
+
+ ///Return a Point
+
+ ///Return a Point.
+ ///\relates Point
+ template <typename T>
+ inline Point<T> makePoint(const T& x, const T& y) {
+ return Point<T>(x, y);
+ }
+
+ ///Return a vector multiplied by a scalar
+
+ ///Return a vector multiplied by a scalar.
+ ///\relates Point
+ template<typename T> Point<T> operator*(const T &u,const Point<T> &x) {
+ return x*u;
+ }
+
+ ///Read a plain vector from a stream
+
+ ///Read a plain vector from a stream.
+ ///\relates Point
+ ///
+ template<typename T>
+ inline std::istream& operator>>(std::istream &is, Point<T> &z) {
+ char c;
+ if (is >> c) {
+ if (c != '(') is.putback(c);
+ } else {
+ is.clear();
+ }
+ if (!(is >> z.x)) return is;
+ if (is >> c) {
+ if (c != ',') is.putback(c);
+ } else {
+ is.clear();
+ }
+ if (!(is >> z.y)) return is;
+ if (is >> c) {
+ if (c != ')') is.putback(c);
+ } else {
+ is.clear();
+ }
+ return is;
+ }
+
+ ///Write a plain vector to a stream
+
+ ///Write a plain vector to a stream.
+ ///\relates Point
+ ///
+ template<typename T>
+ inline std::ostream& operator<<(std::ostream &os, const Point<T>& z)
+ {
+ os << "(" << z.x << "," << z.y << ")";
+ return os;
+ }
+
+ ///Rotate by 90 degrees
+
+ ///Returns the parameter rotated by 90 degrees in positive direction.
+ ///\relates Point
+ ///
+ template<typename T>
+ inline Point<T> rot90(const Point<T> &z)
+ {
+ return Point<T>(-z.y,z.x);
+ }
+
+ ///Rotate by 180 degrees
+
+ ///Returns the parameter rotated by 180 degrees.
+ ///\relates Point
+ ///
+ template<typename T>
+ inline Point<T> rot180(const Point<T> &z)
+ {
+ return Point<T>(-z.x,-z.y);
+ }
+
+ ///Rotate by 270 degrees
+
+ ///Returns the parameter rotated by 90 degrees in negative direction.
+ ///\relates Point
+ ///
+ template<typename T>
+ inline Point<T> rot270(const Point<T> &z)
+ {
+ return Point<T>(z.y,-z.x);
+ }
+
+
+
+ /// Bounding box of plain vectors (points).
+
+ /// A class to calculate or store the bounding box of plain vectors
+ /// (\ref Point "points").
+ template<typename T>
+ class Box {
+ Point<T> _bottom_left, _top_right;
+ bool _empty;
+ public:
+
+ ///Default constructor: creates an empty box
+ Box() { _empty = true; }
+
+ ///Construct a box from one point
+ Box(Point<T> a) {
+ _bottom_left = _top_right = a;
+ _empty = false;
+ }
+
+ ///Construct a box from two points
+
+ ///Construct a box from two points.
+ ///\param a The bottom left corner.
+ ///\param b The top right corner.
+ ///\warning The coordinates of the bottom left corner must be no more
+ ///than those of the top right one.
+ Box(Point<T> a,Point<T> b)
+ {
+ _bottom_left = a;
+ _top_right = b;
+ _empty = false;
+ }
+
+ ///Construct a box from four numbers
+
+ ///Construct a box from four numbers.
+ ///\param l The left side of the box.
+ ///\param b The bottom of the box.
+ ///\param r The right side of the box.
+ ///\param t The top of the box.
+ ///\warning The left side must be no more than the right side and
+ ///bottom must be no more than the top.
+ Box(T l,T b,T r,T t)
+ {
+ _bottom_left=Point<T>(l,b);
+ _top_right=Point<T>(r,t);
+ _empty = false;
+ }
+
+ ///Return \c true if the box is empty.
+
+ ///Return \c true if the box is empty (i.e. return \c false
+ ///if at least one point was added to the box or the coordinates of
+ ///the box were set).
+ ///
+ ///The coordinates of an empty box are not defined.
+ bool empty() const {
+ return _empty;
+ }
+
+ ///Make the box empty
+ void clear() {
+ _empty = true;
+ }
+
+ ///Give back the bottom left corner of the box
+
+ ///Give back the bottom left corner of the box.
+ ///If the box is empty, then the return value is not defined.
+ Point<T> bottomLeft() const {
+ return _bottom_left;
+ }
+
+ ///Set the bottom left corner of the box
+
+ ///Set the bottom left corner of the box.
+ ///\pre The box must not be empty.
+ void bottomLeft(Point<T> p) {
+ _bottom_left = p;
+ }
+
+ ///Give back the top right corner of the box
+
+ ///Give back the top right corner of the box.
+ ///If the box is empty, then the return value is not defined.
+ Point<T> topRight() const {
+ return _top_right;
+ }
+
+ ///Set the top right corner of the box
+
+ ///Set the top right corner of the box.
+ ///\pre The box must not be empty.
+ void topRight(Point<T> p) {
+ _top_right = p;
+ }
+
+ ///Give back the bottom right corner of the box
+
+ ///Give back the bottom right corner of the box.
+ ///If the box is empty, then the return value is not defined.
+ Point<T> bottomRight() const {
+ return Point<T>(_top_right.x,_bottom_left.y);
+ }
+
+ ///Set the bottom right corner of the box
+
+ ///Set the bottom right corner of the box.
+ ///\pre The box must not be empty.
+ void bottomRight(Point<T> p) {
+ _top_right.x = p.x;
+ _bottom_left.y = p.y;
+ }
+
+ ///Give back the top left corner of the box
+
+ ///Give back the top left corner of the box.
+ ///If the box is empty, then the return value is not defined.
+ Point<T> topLeft() const {
+ return Point<T>(_bottom_left.x,_top_right.y);
+ }
+
+ ///Set the top left corner of the box
+
+ ///Set the top left corner of the box.
+ ///\pre The box must not be empty.
+ void topLeft(Point<T> p) {
+ _top_right.y = p.y;
+ _bottom_left.x = p.x;
+ }
+
+ ///Give back the bottom of the box
+
+ ///Give back the bottom of the box.
+ ///If the box is empty, then the return value is not defined.
+ T bottom() const {
+ return _bottom_left.y;
+ }
+
+ ///Set the bottom of the box
+
+ ///Set the bottom of the box.
+ ///\pre The box must not be empty.
+ void bottom(T t) {
+ _bottom_left.y = t;
+ }
+
+ ///Give back the top of the box
+
+ ///Give back the top of the box.
+ ///If the box is empty, then the return value is not defined.
+ T top() const {
+ return _top_right.y;
+ }
+
+ ///Set the top of the box
+
+ ///Set the top of the box.
+ ///\pre The box must not be empty.
+ void top(T t) {
+ _top_right.y = t;
+ }
+
+ ///Give back the left side of the box
+
+ ///Give back the left side of the box.
+ ///If the box is empty, then the return value is not defined.
+ T left() const {
+ return _bottom_left.x;
+ }
+
+ ///Set the left side of the box
+
+ ///Set the left side of the box.
+ ///\pre The box must not be empty.
+ void left(T t) {
+ _bottom_left.x = t;
+ }
+
+ /// Give back the right side of the box
+
+ /// Give back the right side of the box.
+ ///If the box is empty, then the return value is not defined.
+ T right() const {
+ return _top_right.x;
+ }
+
+ ///Set the right side of the box
+
+ ///Set the right side of the box.
+ ///\pre The box must not be empty.
+ void right(T t) {
+ _top_right.x = t;
+ }
+
+ ///Give back the height of the box
+
+ ///Give back the height of the box.
+ ///If the box is empty, then the return value is not defined.
+ T height() const {
+ return _top_right.y-_bottom_left.y;
+ }
+
+ ///Give back the width of the box
+
+ ///Give back the width of the box.
+ ///If the box is empty, then the return value is not defined.
+ T width() const {
+ return _top_right.x-_bottom_left.x;
+ }
+
+ ///Checks whether a point is inside the box
+ bool inside(const Point<T>& u) const {
+ if (_empty)
+ return false;
+ else {
+ return ( (u.x-_bottom_left.x)*(_top_right.x-u.x) >= 0 &&
+ (u.y-_bottom_left.y)*(_top_right.y-u.y) >= 0 );
+ }
+ }
+
+ ///Increments the box with a point
+
+ ///Increments the box with a point.
+ ///
+ Box& add(const Point<T>& u){
+ if (_empty) {
+ _bottom_left = _top_right = u;
+ _empty = false;
+ }
+ else {
+ if (_bottom_left.x > u.x) _bottom_left.x = u.x;
+ if (_bottom_left.y > u.y) _bottom_left.y = u.y;
+ if (_top_right.x < u.x) _top_right.x = u.x;
+ if (_top_right.y < u.y) _top_right.y = u.y;
+ }
+ return *this;
+ }
+
+ ///Increments the box to contain another box
+
+ ///Increments the box to contain another box.
+ ///
+ Box& add(const Box &u){
+ if ( !u.empty() ){
+ add(u._bottom_left);
+ add(u._top_right);
+ }
+ return *this;
+ }
+
+ ///Intersection of two boxes
+
+ ///Intersection of two boxes.
+ ///
+ Box operator&(const Box& u) const {
+ Box b;
+ if (_empty || u._empty) {
+ b._empty = true;
+ } else {
+ b._bottom_left.x = std::max(_bottom_left.x, u._bottom_left.x);
+ b._bottom_left.y = std::max(_bottom_left.y, u._bottom_left.y);
+ b._top_right.x = std::min(_top_right.x, u._top_right.x);
+ b._top_right.y = std::min(_top_right.y, u._top_right.y);
+ b._empty = b._bottom_left.x > b._top_right.x ||
+ b._bottom_left.y > b._top_right.y;
+ }
+ return b;
+ }
+
+ };//class Box
+
+
+ ///Read a box from a stream
+
+ ///Read a box from a stream.
+ ///\relates Box
+ template<typename T>
+ inline std::istream& operator>>(std::istream &is, Box<T>& b) {
+ char c;
+ Point<T> p;
+ if (is >> c) {
+ if (c != '(') is.putback(c);
+ } else {
+ is.clear();
+ }
+ if (!(is >> p)) return is;
+ b.bottomLeft(p);
+ if (is >> c) {
+ if (c != ',') is.putback(c);
+ } else {
+ is.clear();
+ }
+ if (!(is >> p)) return is;
+ b.topRight(p);
+ if (is >> c) {
+ if (c != ')') is.putback(c);
+ } else {
+ is.clear();
+ }
+ return is;
+ }
+
+ ///Write a box to a stream
+
+ ///Write a box to a stream.
+ ///\relates Box
+ template<typename T>
+ inline std::ostream& operator<<(std::ostream &os, const Box<T>& b)
+ {
+ os << "(" << b.bottomLeft() << "," << b.topRight() << ")";
+ return os;
+ }
+
+ ///Map of x-coordinates of a <tt>Point</tt>-map
+
+ ///Map of x-coordinates of a \ref Point "Point"-map.
+ ///
+ template<class M>
+ class XMap
+ {
+ M& _map;
+ public:
+
+ typedef typename M::Value::Value Value;
+ typedef typename M::Key Key;
+ ///\e
+ XMap(M& map) : _map(map) {}
+ Value operator[](Key k) const {return _map[k].x;}
+ void set(Key k,Value v) {_map.set(k,typename M::Value(v,_map[k].y));}
+ };
+
+ ///Returns an XMap class
+
+ ///This function just returns an XMap class.
+ ///\relates XMap
+ template<class M>
+ inline XMap<M> xMap(M &m)
+ {
+ return XMap<M>(m);
+ }
+
+ template<class M>
+ inline XMap<M> xMap(const M &m)
+ {
+ return XMap<M>(m);
+ }
+
+ ///Constant (read only) version of XMap
+
+ ///Constant (read only) version of XMap.
+ ///
+ template<class M>
+ class ConstXMap
+ {
+ const M& _map;
+ public:
+
+ typedef typename M::Value::Value Value;
+ typedef typename M::Key Key;
+ ///\e
+ ConstXMap(const M &map) : _map(map) {}
+ Value operator[](Key k) const {return _map[k].x;}
+ };
+
+ ///Returns a ConstXMap class
+
+ ///This function just returns a ConstXMap class.
+ ///\relates ConstXMap
+ template<class M>
+ inline ConstXMap<M> xMap(const M &m)
+ {
+ return ConstXMap<M>(m);
+ }
+
+ ///Map of y-coordinates of a <tt>Point</tt>-map
+
+ ///Map of y-coordinates of a \ref Point "Point"-map.
+ ///
+ template<class M>
+ class YMap
+ {
+ M& _map;
+ public:
+
+ typedef typename M::Value::Value Value;
+ typedef typename M::Key Key;
+ ///\e
+ YMap(M& map) : _map(map) {}
+ Value operator[](Key k) const {return _map[k].y;}
+ void set(Key k,Value v) {_map.set(k,typename M::Value(_map[k].x,v));}
+ };
+
+ ///Returns a YMap class
+
+ ///This function just returns a YMap class.
+ ///\relates YMap
+ template<class M>
+ inline YMap<M> yMap(M &m)
+ {
+ return YMap<M>(m);
+ }
+
+ template<class M>
+ inline YMap<M> yMap(const M &m)
+ {
+ return YMap<M>(m);
+ }
+
+ ///Constant (read only) version of YMap
+
+ ///Constant (read only) version of YMap.
+ ///
+ template<class M>
+ class ConstYMap
+ {
+ const M& _map;
+ public:
+
+ typedef typename M::Value::Value Value;
+ typedef typename M::Key Key;
+ ///\e
+ ConstYMap(const M &map) : _map(map) {}
+ Value operator[](Key k) const {return _map[k].y;}
+ };
+
+ ///Returns a ConstYMap class
+
+ ///This function just returns a ConstYMap class.
+ ///\relates ConstYMap
+ template<class M>
+ inline ConstYMap<M> yMap(const M &m)
+ {
+ return ConstYMap<M>(m);
+ }
+
+
+ ///\brief Map of the normSquare() of a <tt>Point</tt>-map
+ ///
+ ///Map of the \ref Point::normSquare() "normSquare()"
+ ///of a \ref Point "Point"-map.
+ template<class M>
+ class NormSquareMap
+ {
+ const M& _map;
+ public:
+
+ typedef typename M::Value::Value Value;
+ typedef typename M::Key Key;
+ ///\e
+ NormSquareMap(const M &map) : _map(map) {}
+ Value operator[](Key k) const {return _map[k].normSquare();}
+ };
+
+ ///Returns a NormSquareMap class
+
+ ///This function just returns a NormSquareMap class.
+ ///\relates NormSquareMap
+ template<class M>
+ inline NormSquareMap<M> normSquareMap(const M &m)
+ {
+ return NormSquareMap<M>(m);
+ }
+
+ /// @}
+
+ } //namespce dim2
+
+} //namespace lemon
+
+#endif //LEMON_DIM2_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/dimacs.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/dimacs.h
new file mode 100644
index 00000000000..616879ffa5e
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/dimacs.h
@@ -0,0 +1,448 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_DIMACS_H
+#define LEMON_DIMACS_H
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <limits>
+#include <lemon/maps.h>
+#include <lemon/error.h>
+/// \ingroup dimacs_group
+/// \file
+/// \brief DIMACS file format reader.
+
+namespace lemon {
+
+ /// \addtogroup dimacs_group
+ /// @{
+
+ /// DIMACS file type descriptor.
+ struct DimacsDescriptor
+ {
+ ///\brief DIMACS file type enum
+ ///
+ ///DIMACS file type enum.
+ enum Type {
+ NONE, ///< Undefined type.
+ MIN, ///< DIMACS file type for minimum cost flow problems.
+ MAX, ///< DIMACS file type for maximum flow problems.
+ SP, ///< DIMACS file type for shostest path problems.
+ MAT ///< DIMACS file type for plain graphs and matching problems.
+ };
+ ///The file type
+ Type type;
+ ///The number of nodes in the graph
+ int nodeNum;
+ ///The number of edges in the graph
+ int edgeNum;
+ int lineShift;
+ ///Constructor. It sets the type to \c NONE.
+ DimacsDescriptor() : type(NONE) {}
+ };
+
+ ///Discover the type of a DIMACS file
+
+ ///This function starts seeking the beginning of the given file for the
+ ///problem type and size info.
+ ///The found data is returned in a special struct that can be evaluated
+ ///and passed to the appropriate reader function.
+ DimacsDescriptor dimacsType(std::istream& is)
+ {
+ DimacsDescriptor r;
+ std::string problem,str;
+ char c;
+ r.lineShift=0;
+ while (is >> c)
+ switch(c)
+ {
+ case 'p':
+ if(is >> problem >> r.nodeNum >> r.edgeNum)
+ {
+ getline(is, str);
+ r.lineShift++;
+ if(problem=="min") r.type=DimacsDescriptor::MIN;
+ else if(problem=="max") r.type=DimacsDescriptor::MAX;
+ else if(problem=="sp") r.type=DimacsDescriptor::SP;
+ else if(problem=="mat") r.type=DimacsDescriptor::MAT;
+ else throw FormatError("Unknown problem type");
+ return r;
+ }
+ else
+ {
+ throw FormatError("Missing or wrong problem type declaration.");
+ }
+ break;
+ case 'c':
+ getline(is, str);
+ r.lineShift++;
+ break;
+ default:
+ throw FormatError("Unknown DIMACS declaration.");
+ }
+ throw FormatError("Missing problem type declaration.");
+ }
+
+
+ /// \brief DIMACS minimum cost flow reader function.
+ ///
+ /// This function reads a minimum cost flow instance from DIMACS format,
+ /// i.e. from a DIMACS file having a line starting with
+ /// \code
+ /// p min
+ /// \endcode
+ /// At the beginning, \c g is cleared by \c g.clear(). The supply
+ /// amount of the nodes are written to the \c supply node map
+ /// (they are signed values). The lower bounds, capacities and costs
+ /// of the arcs are written to the \c lower, \c capacity and \c cost
+ /// arc maps.
+ ///
+ /// If the capacity of an arc is less than the lower bound, it will
+ /// be set to "infinite" instead. The actual value of "infinite" is
+ /// contolled by the \c infty parameter. If it is 0 (the default value),
+ /// \c std::numeric_limits<Capacity>::infinity() will be used if available,
+ /// \c std::numeric_limits<Capacity>::max() otherwise. If \c infty is set to
+ /// a non-zero value, that value will be used as "infinite".
+ ///
+ /// If the file type was previously evaluated by dimacsType(), then
+ /// the descriptor struct should be given by the \c dest parameter.
+ template <typename Digraph, typename LowerMap,
+ typename CapacityMap, typename CostMap,
+ typename SupplyMap>
+ void readDimacsMin(std::istream& is,
+ Digraph &g,
+ LowerMap& lower,
+ CapacityMap& capacity,
+ CostMap& cost,
+ SupplyMap& supply,
+ typename CapacityMap::Value infty = 0,
+ DimacsDescriptor desc=DimacsDescriptor())
+ {
+ g.clear();
+ std::vector<typename Digraph::Node> nodes;
+ typename Digraph::Arc e;
+ std::string problem, str;
+ char c;
+ int i, j;
+ if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
+ if(desc.type!=DimacsDescriptor::MIN)
+ throw FormatError("Problem type mismatch");
+
+ nodes.resize(desc.nodeNum + 1);
+ for (int k = 1; k <= desc.nodeNum; ++k) {
+ nodes[k] = g.addNode();
+ supply.set(nodes[k], 0);
+ }
+
+ typename SupplyMap::Value sup;
+ typename CapacityMap::Value low;
+ typename CapacityMap::Value cap;
+ typename CostMap::Value co;
+ typedef typename CapacityMap::Value Capacity;
+ if(infty==0)
+ infty = std::numeric_limits<Capacity>::has_infinity ?
+ std::numeric_limits<Capacity>::infinity() :
+ std::numeric_limits<Capacity>::max();
+
+ while (is >> c) {
+ switch (c) {
+ case 'c': // comment line
+ getline(is, str);
+ break;
+ case 'n': // node definition line
+ is >> i >> sup;
+ getline(is, str);
+ supply.set(nodes[i], sup);
+ break;
+ case 'a': // arc definition line
+ is >> i >> j >> low >> cap >> co;
+ getline(is, str);
+ e = g.addArc(nodes[i], nodes[j]);
+ lower.set(e, low);
+ if (cap >= low)
+ capacity.set(e, cap);
+ else
+ capacity.set(e, infty);
+ cost.set(e, co);
+ break;
+ }
+ }
+ }
+
+ template<typename Digraph, typename CapacityMap>
+ void _readDimacs(std::istream& is,
+ Digraph &g,
+ CapacityMap& capacity,
+ typename Digraph::Node &s,
+ typename Digraph::Node &t,
+ typename CapacityMap::Value infty = 0,
+ DimacsDescriptor desc=DimacsDescriptor()) {
+ g.clear();
+ s=t=INVALID;
+ std::vector<typename Digraph::Node> nodes;
+ typename Digraph::Arc e;
+ char c, d;
+ int i, j;
+ typename CapacityMap::Value _cap;
+ std::string str;
+ nodes.resize(desc.nodeNum + 1);
+ for (int k = 1; k <= desc.nodeNum; ++k) {
+ nodes[k] = g.addNode();
+ }
+ typedef typename CapacityMap::Value Capacity;
+
+ if(infty==0)
+ infty = std::numeric_limits<Capacity>::has_infinity ?
+ std::numeric_limits<Capacity>::infinity() :
+ std::numeric_limits<Capacity>::max();
+
+ while (is >> c) {
+ switch (c) {
+ case 'c': // comment line
+ getline(is, str);
+ break;
+ case 'n': // node definition line
+ if (desc.type==DimacsDescriptor::SP) { // shortest path problem
+ is >> i;
+ getline(is, str);
+ s = nodes[i];
+ }
+ if (desc.type==DimacsDescriptor::MAX) { // max flow problem
+ is >> i >> d;
+ getline(is, str);
+ if (d == 's') s = nodes[i];
+ if (d == 't') t = nodes[i];
+ }
+ break;
+ case 'a': // arc definition line
+ if (desc.type==DimacsDescriptor::SP) {
+ is >> i >> j >> _cap;
+ getline(is, str);
+ e = g.addArc(nodes[i], nodes[j]);
+ capacity.set(e, _cap);
+ }
+ else if (desc.type==DimacsDescriptor::MAX) {
+ is >> i >> j >> _cap;
+ getline(is, str);
+ e = g.addArc(nodes[i], nodes[j]);
+ if (_cap >= 0)
+ capacity.set(e, _cap);
+ else
+ capacity.set(e, infty);
+ }
+ else {
+ is >> i >> j;
+ getline(is, str);
+ g.addArc(nodes[i], nodes[j]);
+ }
+ break;
+ }
+ }
+ }
+
+ /// \brief DIMACS maximum flow reader function.
+ ///
+ /// This function reads a maximum flow instance from DIMACS format,
+ /// i.e. from a DIMACS file having a line starting with
+ /// \code
+ /// p max
+ /// \endcode
+ /// At the beginning, \c g is cleared by \c g.clear(). The arc
+ /// capacities are written to the \c capacity arc map and \c s and
+ /// \c t are set to the source and the target nodes.
+ ///
+ /// If the capacity of an arc is negative, it will
+ /// be set to "infinite" instead. The actual value of "infinite" is
+ /// contolled by the \c infty parameter. If it is 0 (the default value),
+ /// \c std::numeric_limits<Capacity>::infinity() will be used if available,
+ /// \c std::numeric_limits<Capacity>::max() otherwise. If \c infty is set to
+ /// a non-zero value, that value will be used as "infinite".
+ ///
+ /// If the file type was previously evaluated by dimacsType(), then
+ /// the descriptor struct should be given by the \c dest parameter.
+ template<typename Digraph, typename CapacityMap>
+ void readDimacsMax(std::istream& is,
+ Digraph &g,
+ CapacityMap& capacity,
+ typename Digraph::Node &s,
+ typename Digraph::Node &t,
+ typename CapacityMap::Value infty = 0,
+ DimacsDescriptor desc=DimacsDescriptor()) {
+ if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
+ if(desc.type!=DimacsDescriptor::MAX)
+ throw FormatError("Problem type mismatch");
+ _readDimacs(is,g,capacity,s,t,infty,desc);
+ }
+
+ /// \brief DIMACS shortest path reader function.
+ ///
+ /// This function reads a shortest path instance from DIMACS format,
+ /// i.e. from a DIMACS file having a line starting with
+ /// \code
+ /// p sp
+ /// \endcode
+ /// At the beginning, \c g is cleared by \c g.clear(). The arc
+ /// lengths are written to the \c length arc map and \c s is set to the
+ /// source node.
+ ///
+ /// If the file type was previously evaluated by dimacsType(), then
+ /// the descriptor struct should be given by the \c dest parameter.
+ template<typename Digraph, typename LengthMap>
+ void readDimacsSp(std::istream& is,
+ Digraph &g,
+ LengthMap& length,
+ typename Digraph::Node &s,
+ DimacsDescriptor desc=DimacsDescriptor()) {
+ typename Digraph::Node t;
+ if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
+ if(desc.type!=DimacsDescriptor::SP)
+ throw FormatError("Problem type mismatch");
+ _readDimacs(is, g, length, s, t, 0, desc);
+ }
+
+ /// \brief DIMACS capacitated digraph reader function.
+ ///
+ /// This function reads an arc capacitated digraph instance from
+ /// DIMACS 'max' or 'sp' format.
+ /// At the beginning, \c g is cleared by \c g.clear()
+ /// and the arc capacities/lengths are written to the \c capacity
+ /// arc map.
+ ///
+ /// In case of the 'max' format, if the capacity of an arc is negative,
+ /// it will
+ /// be set to "infinite" instead. The actual value of "infinite" is
+ /// contolled by the \c infty parameter. If it is 0 (the default value),
+ /// \c std::numeric_limits<Capacity>::infinity() will be used if available,
+ /// \c std::numeric_limits<Capacity>::max() otherwise. If \c infty is set to
+ /// a non-zero value, that value will be used as "infinite".
+ ///
+ /// If the file type was previously evaluated by dimacsType(), then
+ /// the descriptor struct should be given by the \c dest parameter.
+ template<typename Digraph, typename CapacityMap>
+ void readDimacsCap(std::istream& is,
+ Digraph &g,
+ CapacityMap& capacity,
+ typename CapacityMap::Value infty = 0,
+ DimacsDescriptor desc=DimacsDescriptor()) {
+ typename Digraph::Node u,v;
+ if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
+ if(desc.type!=DimacsDescriptor::MAX || desc.type!=DimacsDescriptor::SP)
+ throw FormatError("Problem type mismatch");
+ _readDimacs(is, g, capacity, u, v, infty, desc);
+ }
+
+ template<typename Graph>
+ typename enable_if<lemon::UndirectedTagIndicator<Graph>,void>::type
+ _addArcEdge(Graph &g, typename Graph::Node s, typename Graph::Node t,
+ dummy<0> = 0)
+ {
+ g.addEdge(s,t);
+ }
+ template<typename Graph>
+ typename disable_if<lemon::UndirectedTagIndicator<Graph>,void>::type
+ _addArcEdge(Graph &g, typename Graph::Node s, typename Graph::Node t,
+ dummy<1> = 1)
+ {
+ g.addArc(s,t);
+ }
+
+ /// \brief DIMACS plain (di)graph reader function.
+ ///
+ /// This function reads a plain (di)graph without any designated nodes
+ /// and maps (e.g. a matching instance) from DIMACS format, i.e. from
+ /// DIMACS files having a line starting with
+ /// \code
+ /// p mat
+ /// \endcode
+ /// At the beginning, \c g is cleared by \c g.clear().
+ ///
+ /// If the file type was previously evaluated by dimacsType(), then
+ /// the descriptor struct should be given by the \c dest parameter.
+ template<typename Graph>
+ void readDimacsMat(std::istream& is, Graph &g,
+ DimacsDescriptor desc=DimacsDescriptor())
+ {
+ if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
+ if(desc.type!=DimacsDescriptor::MAT)
+ throw FormatError("Problem type mismatch");
+
+ g.clear();
+ std::vector<typename Graph::Node> nodes;
+ char c;
+ int i, j;
+ std::string str;
+ nodes.resize(desc.nodeNum + 1);
+ for (int k = 1; k <= desc.nodeNum; ++k) {
+ nodes[k] = g.addNode();
+ }
+
+ while (is >> c) {
+ switch (c) {
+ case 'c': // comment line
+ getline(is, str);
+ break;
+ case 'n': // node definition line
+ break;
+ case 'a': // arc definition line
+ is >> i >> j;
+ getline(is, str);
+ _addArcEdge(g,nodes[i], nodes[j]);
+ break;
+ }
+ }
+ }
+
+ /// DIMACS plain digraph writer function.
+ ///
+ /// This function writes a digraph without any designated nodes and
+ /// maps into DIMACS format, i.e. into DIMACS file having a line
+ /// starting with
+ /// \code
+ /// p mat
+ /// \endcode
+ /// If \c comment is not empty, then it will be printed in the first line
+ /// prefixed by 'c'.
+ template<typename Digraph>
+ void writeDimacsMat(std::ostream& os, const Digraph &g,
+ std::string comment="") {
+ typedef typename Digraph::NodeIt NodeIt;
+ typedef typename Digraph::ArcIt ArcIt;
+
+ if(!comment.empty())
+ os << "c " << comment << std::endl;
+ os << "p mat " << g.nodeNum() << " " << g.arcNum() << std::endl;
+
+ typename Digraph::template NodeMap<int> nodes(g);
+ int i = 1;
+ for(NodeIt v(g); v != INVALID; ++v) {
+ nodes.set(v, i);
+ ++i;
+ }
+ for(ArcIt e(g); e != INVALID; ++e) {
+ os << "a " << nodes[g.source(e)] << " " << nodes[g.target(e)]
+ << std::endl;
+ }
+ }
+
+ /// @}
+
+} //namespace lemon
+
+#endif //LEMON_DIMACS_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/edge_set.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/edge_set.h
new file mode 100644
index 00000000000..399b7a266f0
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/edge_set.h
@@ -0,0 +1,1420 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_EDGE_SET_H
+#define LEMON_EDGE_SET_H
+
+#include <lemon/core.h>
+#include <lemon/bits/edge_set_extender.h>
+
+/// \ingroup graphs
+/// \file
+/// \brief ArcSet and EdgeSet classes.
+///
+/// Graphs which use another graph's node-set as own.
+namespace lemon {
+
+ template <typename GR>
+ class ListArcSetBase {
+ public:
+
+ typedef typename GR::Node Node;
+ typedef typename GR::NodeIt NodeIt;
+
+ protected:
+
+ struct NodeT {
+ int first_out, first_in;
+ NodeT() : first_out(-1), first_in(-1) {}
+ };
+
+ typedef typename ItemSetTraits<GR, Node>::
+ template Map<NodeT>::Type NodesImplBase;
+
+ NodesImplBase* _nodes;
+
+ struct ArcT {
+ Node source, target;
+ int next_out, next_in;
+ int prev_out, prev_in;
+ ArcT() : prev_out(-1), prev_in(-1) {}
+ };
+
+ std::vector<ArcT> arcs;
+
+ int first_arc;
+ int first_free_arc;
+
+ const GR* _graph;
+
+ void initalize(const GR& graph, NodesImplBase& nodes) {
+ _graph = &graph;
+ _nodes = &nodes;
+ }
+
+ public:
+
+ class Arc {
+ friend class ListArcSetBase<GR>;
+ protected:
+ Arc(int _id) : id(_id) {}
+ int id;
+ public:
+ Arc() {}
+ Arc(Invalid) : id(-1) {}
+ bool operator==(const Arc& arc) const { return id == arc.id; }
+ bool operator!=(const Arc& arc) const { return id != arc.id; }
+ bool operator<(const Arc& arc) const { return id < arc.id; }
+ };
+
+ ListArcSetBase() : first_arc(-1), first_free_arc(-1) {}
+
+ Node addNode() {
+ LEMON_ASSERT(false,
+ "This graph structure does not support node insertion");
+ return INVALID; // avoid warning
+ }
+
+ Arc addArc(const Node& u, const Node& v) {
+ int n;
+ if (first_free_arc == -1) {
+ n = arcs.size();
+ arcs.push_back(ArcT());
+ } else {
+ n = first_free_arc;
+ first_free_arc = arcs[first_free_arc].next_in;
+ }
+ arcs[n].next_in = (*_nodes)[v].first_in;
+ if ((*_nodes)[v].first_in != -1) {
+ arcs[(*_nodes)[v].first_in].prev_in = n;
+ }
+ (*_nodes)[v].first_in = n;
+ arcs[n].next_out = (*_nodes)[u].first_out;
+ if ((*_nodes)[u].first_out != -1) {
+ arcs[(*_nodes)[u].first_out].prev_out = n;
+ }
+ (*_nodes)[u].first_out = n;
+ arcs[n].source = u;
+ arcs[n].target = v;
+ return Arc(n);
+ }
+
+ void erase(const Arc& arc) {
+ int n = arc.id;
+ if (arcs[n].prev_in != -1) {
+ arcs[arcs[n].prev_in].next_in = arcs[n].next_in;
+ } else {
+ (*_nodes)[arcs[n].target].first_in = arcs[n].next_in;
+ }
+ if (arcs[n].next_in != -1) {
+ arcs[arcs[n].next_in].prev_in = arcs[n].prev_in;
+ }
+
+ if (arcs[n].prev_out != -1) {
+ arcs[arcs[n].prev_out].next_out = arcs[n].next_out;
+ } else {
+ (*_nodes)[arcs[n].source].first_out = arcs[n].next_out;
+ }
+ if (arcs[n].next_out != -1) {
+ arcs[arcs[n].next_out].prev_out = arcs[n].prev_out;
+ }
+
+ }
+
+ void clear() {
+ Node node;
+ for (first(node); node != INVALID; next(node)) {
+ (*_nodes)[node].first_in = -1;
+ (*_nodes)[node].first_out = -1;
+ }
+ arcs.clear();
+ first_arc = -1;
+ first_free_arc = -1;
+ }
+
+ void first(Node& node) const {
+ _graph->first(node);
+ }
+
+ void next(Node& node) const {
+ _graph->next(node);
+ }
+
+ void first(Arc& arc) const {
+ Node node;
+ first(node);
+ while (node != INVALID && (*_nodes)[node].first_in == -1) {
+ next(node);
+ }
+ arc.id = (node == INVALID) ? -1 : (*_nodes)[node].first_in;
+ }
+
+ void next(Arc& arc) const {
+ if (arcs[arc.id].next_in != -1) {
+ arc.id = arcs[arc.id].next_in;
+ } else {
+ Node node = arcs[arc.id].target;
+ next(node);
+ while (node != INVALID && (*_nodes)[node].first_in == -1) {
+ next(node);
+ }
+ arc.id = (node == INVALID) ? -1 : (*_nodes)[node].first_in;
+ }
+ }
+
+ void firstOut(Arc& arc, const Node& node) const {
+ arc.id = (*_nodes)[node].first_out;
+ }
+
+ void nextOut(Arc& arc) const {
+ arc.id = arcs[arc.id].next_out;
+ }
+
+ void firstIn(Arc& arc, const Node& node) const {
+ arc.id = (*_nodes)[node].first_in;
+ }
+
+ void nextIn(Arc& arc) const {
+ arc.id = arcs[arc.id].next_in;
+ }
+
+ int id(const Node& node) const { return _graph->id(node); }
+ int id(const Arc& arc) const { return arc.id; }
+
+ Node nodeFromId(int ix) const { return _graph->nodeFromId(ix); }
+ Arc arcFromId(int ix) const { return Arc(ix); }
+
+ int maxNodeId() const { return _graph->maxNodeId(); };
+ int maxArcId() const { return arcs.size() - 1; }
+
+ Node source(const Arc& arc) const { return arcs[arc.id].source;}
+ Node target(const Arc& arc) const { return arcs[arc.id].target;}
+
+ typedef typename ItemSetTraits<GR, Node>::ItemNotifier NodeNotifier;
+
+ NodeNotifier& notifier(Node) const {
+ return _graph->notifier(Node());
+ }
+
+ template <typename V>
+ class NodeMap : public GR::template NodeMap<V> {
+ typedef typename GR::template NodeMap<V> Parent;
+
+ public:
+
+ explicit NodeMap(const ListArcSetBase<GR>& arcset)
+ : Parent(*arcset._graph) {}
+
+ NodeMap(const ListArcSetBase<GR>& arcset, const V& value)
+ : Parent(*arcset._graph, value) {}
+
+ NodeMap& operator=(const NodeMap& cmap) {
+ return operator=<NodeMap>(cmap);
+ }
+
+ template <typename CMap>
+ NodeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ };
+
+ /// \ingroup graphs
+ ///
+ /// \brief Digraph using a node set of another digraph or graph and
+ /// an own arc set.
+ ///
+ /// This structure can be used to establish another directed graph
+ /// over a node set of an existing one. This class uses the same
+ /// Node type as the underlying graph, and each valid node of the
+ /// original graph is valid in this arc set, therefore the node
+ /// objects of the original graph can be used directly with this
+ /// class. The node handling functions (id handling, observing, and
+ /// iterators) works equivalently as in the original graph.
+ ///
+ /// This implementation is based on doubly-linked lists, from each
+ /// node the outgoing and the incoming arcs make up lists, therefore
+ /// one arc can be erased in constant time. It also makes possible,
+ /// that node can be removed from the underlying graph, in this case
+ /// all arcs incident to the given node is erased from the arc set.
+ ///
+ /// This class fully conforms to the \ref concepts::Digraph
+ /// "Digraph" concept.
+ /// It provides only linear time counting for nodes and arcs.
+ ///
+ /// \param GR The type of the graph which shares its node set with
+ /// this class. Its interface must conform to the
+ /// \ref concepts::Digraph "Digraph" or \ref concepts::Graph "Graph"
+ /// concept.
+ template <typename GR>
+ class ListArcSet : public ArcSetExtender<ListArcSetBase<GR> > {
+ typedef ArcSetExtender<ListArcSetBase<GR> > Parent;
+
+ public:
+
+ typedef typename Parent::Node Node;
+ typedef typename Parent::Arc Arc;
+
+ typedef typename Parent::NodesImplBase NodesImplBase;
+
+ void eraseNode(const Node& node) {
+ Arc arc;
+ Parent::firstOut(arc, node);
+ while (arc != INVALID ) {
+ erase(arc);
+ Parent::firstOut(arc, node);
+ }
+
+ Parent::firstIn(arc, node);
+ while (arc != INVALID ) {
+ erase(arc);
+ Parent::firstIn(arc, node);
+ }
+ }
+
+ void clearNodes() {
+ Parent::clear();
+ }
+
+ class NodesImpl : public NodesImplBase {
+ typedef NodesImplBase Parent;
+
+ public:
+ NodesImpl(const GR& graph, ListArcSet& arcset)
+ : Parent(graph), _arcset(arcset) {}
+
+ virtual ~NodesImpl() {}
+
+ protected:
+
+ virtual void erase(const Node& node) {
+ _arcset.eraseNode(node);
+ Parent::erase(node);
+ }
+ virtual void erase(const std::vector<Node>& nodes) {
+ for (int i = 0; i < int(nodes.size()); ++i) {
+ _arcset.eraseNode(nodes[i]);
+ }
+ Parent::erase(nodes);
+ }
+ virtual void clear() {
+ _arcset.clearNodes();
+ Parent::clear();
+ }
+
+ private:
+ ListArcSet& _arcset;
+ };
+
+ NodesImpl _nodes;
+
+ public:
+
+ /// \brief Constructor of the ArcSet.
+ ///
+ /// Constructor of the ArcSet.
+ ListArcSet(const GR& graph) : _nodes(graph, *this) {
+ Parent::initalize(graph, _nodes);
+ }
+
+ /// \brief Add a new arc to the digraph.
+ ///
+ /// Add a new arc to the digraph with source node \c s
+ /// and target node \c t.
+ /// \return The new arc.
+ Arc addArc(const Node& s, const Node& t) {
+ return Parent::addArc(s, t);
+ }
+
+ /// \brief Erase an arc from the digraph.
+ ///
+ /// Erase an arc \c a from the digraph.
+ void erase(const Arc& a) {
+ return Parent::erase(a);
+ }
+
+ };
+
+ template <typename GR>
+ class ListEdgeSetBase {
+ public:
+
+ typedef typename GR::Node Node;
+ typedef typename GR::NodeIt NodeIt;
+
+ protected:
+
+ struct NodeT {
+ int first_out;
+ NodeT() : first_out(-1) {}
+ };
+
+ typedef typename ItemSetTraits<GR, Node>::
+ template Map<NodeT>::Type NodesImplBase;
+
+ NodesImplBase* _nodes;
+
+ struct ArcT {
+ Node target;
+ int prev_out, next_out;
+ ArcT() : prev_out(-1), next_out(-1) {}
+ };
+
+ std::vector<ArcT> arcs;
+
+ int first_arc;
+ int first_free_arc;
+
+ const GR* _graph;
+
+ void initalize(const GR& graph, NodesImplBase& nodes) {
+ _graph = &graph;
+ _nodes = &nodes;
+ }
+
+ public:
+
+ class Edge {
+ friend class ListEdgeSetBase;
+ protected:
+
+ int id;
+ explicit Edge(int _id) { id = _id;}
+
+ public:
+ Edge() {}
+ Edge (Invalid) { id = -1; }
+ bool operator==(const Edge& arc) const {return id == arc.id;}
+ bool operator!=(const Edge& arc) const {return id != arc.id;}
+ bool operator<(const Edge& arc) const {return id < arc.id;}
+ };
+
+ class Arc {
+ friend class ListEdgeSetBase;
+ protected:
+ Arc(int _id) : id(_id) {}
+ int id;
+ public:
+ operator Edge() const { return edgeFromId(id / 2); }
+
+ Arc() {}
+ Arc(Invalid) : id(-1) {}
+ bool operator==(const Arc& arc) const { return id == arc.id; }
+ bool operator!=(const Arc& arc) const { return id != arc.id; }
+ bool operator<(const Arc& arc) const { return id < arc.id; }
+ };
+
+ ListEdgeSetBase() : first_arc(-1), first_free_arc(-1) {}
+
+ Node addNode() {
+ LEMON_ASSERT(false,
+ "This graph structure does not support node insertion");
+ return INVALID; // avoid warning
+ }
+
+ Edge addEdge(const Node& u, const Node& v) {
+ int n;
+
+ if (first_free_arc == -1) {
+ n = arcs.size();
+ arcs.push_back(ArcT());
+ arcs.push_back(ArcT());
+ } else {
+ n = first_free_arc;
+ first_free_arc = arcs[n].next_out;
+ }
+
+ arcs[n].target = u;
+ arcs[n | 1].target = v;
+
+ arcs[n].next_out = (*_nodes)[v].first_out;
+ if ((*_nodes)[v].first_out != -1) {
+ arcs[(*_nodes)[v].first_out].prev_out = n;
+ }
+ (*_nodes)[v].first_out = n;
+ arcs[n].prev_out = -1;
+
+ if ((*_nodes)[u].first_out != -1) {
+ arcs[(*_nodes)[u].first_out].prev_out = (n | 1);
+ }
+ arcs[n | 1].next_out = (*_nodes)[u].first_out;
+ (*_nodes)[u].first_out = (n | 1);
+ arcs[n | 1].prev_out = -1;
+
+ return Edge(n / 2);
+ }
+
+ void erase(const Edge& arc) {
+ int n = arc.id * 2;
+
+ if (arcs[n].next_out != -1) {
+ arcs[arcs[n].next_out].prev_out = arcs[n].prev_out;
+ }
+
+ if (arcs[n].prev_out != -1) {
+ arcs[arcs[n].prev_out].next_out = arcs[n].next_out;
+ } else {
+ (*_nodes)[arcs[n | 1].target].first_out = arcs[n].next_out;
+ }
+
+ if (arcs[n | 1].next_out != -1) {
+ arcs[arcs[n | 1].next_out].prev_out = arcs[n | 1].prev_out;
+ }
+
+ if (arcs[n | 1].prev_out != -1) {
+ arcs[arcs[n | 1].prev_out].next_out = arcs[n | 1].next_out;
+ } else {
+ (*_nodes)[arcs[n].target].first_out = arcs[n | 1].next_out;
+ }
+
+ arcs[n].next_out = first_free_arc;
+ first_free_arc = n;
+
+ }
+
+ void clear() {
+ Node node;
+ for (first(node); node != INVALID; next(node)) {
+ (*_nodes)[node].first_out = -1;
+ }
+ arcs.clear();
+ first_arc = -1;
+ first_free_arc = -1;
+ }
+
+ void first(Node& node) const {
+ _graph->first(node);
+ }
+
+ void next(Node& node) const {
+ _graph->next(node);
+ }
+
+ void first(Arc& arc) const {
+ Node node;
+ first(node);
+ while (node != INVALID && (*_nodes)[node].first_out == -1) {
+ next(node);
+ }
+ arc.id = (node == INVALID) ? -1 : (*_nodes)[node].first_out;
+ }
+
+ void next(Arc& arc) const {
+ if (arcs[arc.id].next_out != -1) {
+ arc.id = arcs[arc.id].next_out;
+ } else {
+ Node node = arcs[arc.id ^ 1].target;
+ next(node);
+ while(node != INVALID && (*_nodes)[node].first_out == -1) {
+ next(node);
+ }
+ arc.id = (node == INVALID) ? -1 : (*_nodes)[node].first_out;
+ }
+ }
+
+ void first(Edge& edge) const {
+ Node node;
+ first(node);
+ while (node != INVALID) {
+ edge.id = (*_nodes)[node].first_out;
+ while ((edge.id & 1) != 1) {
+ edge.id = arcs[edge.id].next_out;
+ }
+ if (edge.id != -1) {
+ edge.id /= 2;
+ return;
+ }
+ next(node);
+ }
+ edge.id = -1;
+ }
+
+ void next(Edge& edge) const {
+ Node node = arcs[edge.id * 2].target;
+ edge.id = arcs[(edge.id * 2) | 1].next_out;
+ while ((edge.id & 1) != 1) {
+ edge.id = arcs[edge.id].next_out;
+ }
+ if (edge.id != -1) {
+ edge.id /= 2;
+ return;
+ }
+ next(node);
+ while (node != INVALID) {
+ edge.id = (*_nodes)[node].first_out;
+ while ((edge.id & 1) != 1) {
+ edge.id = arcs[edge.id].next_out;
+ }
+ if (edge.id != -1) {
+ edge.id /= 2;
+ return;
+ }
+ next(node);
+ }
+ edge.id = -1;
+ }
+
+ void firstOut(Arc& arc, const Node& node) const {
+ arc.id = (*_nodes)[node].first_out;
+ }
+
+ void nextOut(Arc& arc) const {
+ arc.id = arcs[arc.id].next_out;
+ }
+
+ void firstIn(Arc& arc, const Node& node) const {
+ arc.id = (((*_nodes)[node].first_out) ^ 1);
+ if (arc.id == -2) arc.id = -1;
+ }
+
+ void nextIn(Arc& arc) const {
+ arc.id = ((arcs[arc.id ^ 1].next_out) ^ 1);
+ if (arc.id == -2) arc.id = -1;
+ }
+
+ void firstInc(Edge &arc, bool& dir, const Node& node) const {
+ int de = (*_nodes)[node].first_out;
+ if (de != -1 ) {
+ arc.id = de / 2;
+ dir = ((de & 1) == 1);
+ } else {
+ arc.id = -1;
+ dir = true;
+ }
+ }
+ void nextInc(Edge &arc, bool& dir) const {
+ int de = (arcs[(arc.id * 2) | (dir ? 1 : 0)].next_out);
+ if (de != -1 ) {
+ arc.id = de / 2;
+ dir = ((de & 1) == 1);
+ } else {
+ arc.id = -1;
+ dir = true;
+ }
+ }
+
+ static bool direction(Arc arc) {
+ return (arc.id & 1) == 1;
+ }
+
+ static Arc direct(Edge edge, bool dir) {
+ return Arc(edge.id * 2 + (dir ? 1 : 0));
+ }
+
+ int id(const Node& node) const { return _graph->id(node); }
+ static int id(Arc e) { return e.id; }
+ static int id(Edge e) { return e.id; }
+
+ Node nodeFromId(int id) const { return _graph->nodeFromId(id); }
+ static Arc arcFromId(int id) { return Arc(id);}
+ static Edge edgeFromId(int id) { return Edge(id);}
+
+ int maxNodeId() const { return _graph->maxNodeId(); };
+ int maxEdgeId() const { return arcs.size() / 2 - 1; }
+ int maxArcId() const { return arcs.size()-1; }
+
+ Node source(Arc e) const { return arcs[e.id ^ 1].target; }
+ Node target(Arc e) const { return arcs[e.id].target; }
+
+ Node u(Edge e) const { return arcs[2 * e.id].target; }
+ Node v(Edge e) const { return arcs[2 * e.id + 1].target; }
+
+ typedef typename ItemSetTraits<GR, Node>::ItemNotifier NodeNotifier;
+
+ NodeNotifier& notifier(Node) const {
+ return _graph->notifier(Node());
+ }
+
+ template <typename V>
+ class NodeMap : public GR::template NodeMap<V> {
+ typedef typename GR::template NodeMap<V> Parent;
+
+ public:
+
+ explicit NodeMap(const ListEdgeSetBase<GR>& arcset)
+ : Parent(*arcset._graph) {}
+
+ NodeMap(const ListEdgeSetBase<GR>& arcset, const V& value)
+ : Parent(*arcset._graph, value) {}
+
+ NodeMap& operator=(const NodeMap& cmap) {
+ return operator=<NodeMap>(cmap);
+ }
+
+ template <typename CMap>
+ NodeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ };
+
+ /// \ingroup graphs
+ ///
+ /// \brief Graph using a node set of another digraph or graph and an
+ /// own edge set.
+ ///
+ /// This structure can be used to establish another graph over a
+ /// node set of an existing one. This class uses the same Node type
+ /// as the underlying graph, and each valid node of the original
+ /// graph is valid in this arc set, therefore the node objects of
+ /// the original graph can be used directly with this class. The
+ /// node handling functions (id handling, observing, and iterators)
+ /// works equivalently as in the original graph.
+ ///
+ /// This implementation is based on doubly-linked lists, from each
+ /// node the incident edges make up lists, therefore one edge can be
+ /// erased in constant time. It also makes possible, that node can
+ /// be removed from the underlying graph, in this case all edges
+ /// incident to the given node is erased from the arc set.
+ ///
+ /// This class fully conforms to the \ref concepts::Graph "Graph"
+ /// concept.
+ /// It provides only linear time counting for nodes, edges and arcs.
+ ///
+ /// \param GR The type of the graph which shares its node set
+ /// with this class. Its interface must conform to the
+ /// \ref concepts::Digraph "Digraph" or \ref concepts::Graph "Graph"
+ /// concept.
+ template <typename GR>
+ class ListEdgeSet : public EdgeSetExtender<ListEdgeSetBase<GR> > {
+ typedef EdgeSetExtender<ListEdgeSetBase<GR> > Parent;
+
+ public:
+
+ typedef typename Parent::Node Node;
+ typedef typename Parent::Arc Arc;
+ typedef typename Parent::Edge Edge;
+
+ typedef typename Parent::NodesImplBase NodesImplBase;
+
+ void eraseNode(const Node& node) {
+ Arc arc;
+ Parent::firstOut(arc, node);
+ while (arc != INVALID ) {
+ erase(arc);
+ Parent::firstOut(arc, node);
+ }
+
+ }
+
+ void clearNodes() {
+ Parent::clear();
+ }
+
+ class NodesImpl : public NodesImplBase {
+ typedef NodesImplBase Parent;
+
+ public:
+ NodesImpl(const GR& graph, ListEdgeSet& arcset)
+ : Parent(graph), _arcset(arcset) {}
+
+ virtual ~NodesImpl() {}
+
+ protected:
+
+ virtual void erase(const Node& node) {
+ _arcset.eraseNode(node);
+ Parent::erase(node);
+ }
+ virtual void erase(const std::vector<Node>& nodes) {
+ for (int i = 0; i < int(nodes.size()); ++i) {
+ _arcset.eraseNode(nodes[i]);
+ }
+ Parent::erase(nodes);
+ }
+ virtual void clear() {
+ _arcset.clearNodes();
+ Parent::clear();
+ }
+
+ private:
+ ListEdgeSet& _arcset;
+ };
+
+ NodesImpl _nodes;
+
+ public:
+
+ /// \brief Constructor of the EdgeSet.
+ ///
+ /// Constructor of the EdgeSet.
+ ListEdgeSet(const GR& graph) : _nodes(graph, *this) {
+ Parent::initalize(graph, _nodes);
+ }
+
+ /// \brief Add a new edge to the graph.
+ ///
+ /// Add a new edge to the graph with node \c u
+ /// and node \c v endpoints.
+ /// \return The new edge.
+ Edge addEdge(const Node& u, const Node& v) {
+ return Parent::addEdge(u, v);
+ }
+
+ /// \brief Erase an edge from the graph.
+ ///
+ /// Erase the edge \c e from the graph.
+ void erase(const Edge& e) {
+ return Parent::erase(e);
+ }
+
+ };
+
+ template <typename GR>
+ class SmartArcSetBase {
+ public:
+
+ typedef typename GR::Node Node;
+ typedef typename GR::NodeIt NodeIt;
+
+ protected:
+
+ struct NodeT {
+ int first_out, first_in;
+ NodeT() : first_out(-1), first_in(-1) {}
+ };
+
+ typedef typename ItemSetTraits<GR, Node>::
+ template Map<NodeT>::Type NodesImplBase;
+
+ NodesImplBase* _nodes;
+
+ struct ArcT {
+ Node source, target;
+ int next_out, next_in;
+ ArcT() {}
+ };
+
+ std::vector<ArcT> arcs;
+
+ const GR* _graph;
+
+ void initalize(const GR& graph, NodesImplBase& nodes) {
+ _graph = &graph;
+ _nodes = &nodes;
+ }
+
+ public:
+
+ class Arc {
+ friend class SmartArcSetBase<GR>;
+ protected:
+ Arc(int _id) : id(_id) {}
+ int id;
+ public:
+ Arc() {}
+ Arc(Invalid) : id(-1) {}
+ bool operator==(const Arc& arc) const { return id == arc.id; }
+ bool operator!=(const Arc& arc) const { return id != arc.id; }
+ bool operator<(const Arc& arc) const { return id < arc.id; }
+ };
+
+ SmartArcSetBase() {}
+
+ Node addNode() {
+ LEMON_ASSERT(false,
+ "This graph structure does not support node insertion");
+ return INVALID; // avoid warning
+ }
+
+ Arc addArc(const Node& u, const Node& v) {
+ int n = arcs.size();
+ arcs.push_back(ArcT());
+ arcs[n].next_in = (*_nodes)[v].first_in;
+ (*_nodes)[v].first_in = n;
+ arcs[n].next_out = (*_nodes)[u].first_out;
+ (*_nodes)[u].first_out = n;
+ arcs[n].source = u;
+ arcs[n].target = v;
+ return Arc(n);
+ }
+
+ void clear() {
+ Node node;
+ for (first(node); node != INVALID; next(node)) {
+ (*_nodes)[node].first_in = -1;
+ (*_nodes)[node].first_out = -1;
+ }
+ arcs.clear();
+ }
+
+ void first(Node& node) const {
+ _graph->first(node);
+ }
+
+ void next(Node& node) const {
+ _graph->next(node);
+ }
+
+ void first(Arc& arc) const {
+ arc.id = arcs.size() - 1;
+ }
+
+ static void next(Arc& arc) {
+ --arc.id;
+ }
+
+ void firstOut(Arc& arc, const Node& node) const {
+ arc.id = (*_nodes)[node].first_out;
+ }
+
+ void nextOut(Arc& arc) const {
+ arc.id = arcs[arc.id].next_out;
+ }
+
+ void firstIn(Arc& arc, const Node& node) const {
+ arc.id = (*_nodes)[node].first_in;
+ }
+
+ void nextIn(Arc& arc) const {
+ arc.id = arcs[arc.id].next_in;
+ }
+
+ int id(const Node& node) const { return _graph->id(node); }
+ int id(const Arc& arc) const { return arc.id; }
+
+ Node nodeFromId(int ix) const { return _graph->nodeFromId(ix); }
+ Arc arcFromId(int ix) const { return Arc(ix); }
+
+ int maxNodeId() const { return _graph->maxNodeId(); };
+ int maxArcId() const { return arcs.size() - 1; }
+
+ Node source(const Arc& arc) const { return arcs[arc.id].source;}
+ Node target(const Arc& arc) const { return arcs[arc.id].target;}
+
+ typedef typename ItemSetTraits<GR, Node>::ItemNotifier NodeNotifier;
+
+ NodeNotifier& notifier(Node) const {
+ return _graph->notifier(Node());
+ }
+
+ template <typename V>
+ class NodeMap : public GR::template NodeMap<V> {
+ typedef typename GR::template NodeMap<V> Parent;
+
+ public:
+
+ explicit NodeMap(const SmartArcSetBase<GR>& arcset)
+ : Parent(*arcset._graph) { }
+
+ NodeMap(const SmartArcSetBase<GR>& arcset, const V& value)
+ : Parent(*arcset._graph, value) { }
+
+ NodeMap& operator=(const NodeMap& cmap) {
+ return operator=<NodeMap>(cmap);
+ }
+
+ template <typename CMap>
+ NodeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ };
+
+
+ /// \ingroup graphs
+ ///
+ /// \brief Digraph using a node set of another digraph or graph and
+ /// an own arc set.
+ ///
+ /// This structure can be used to establish another directed graph
+ /// over a node set of an existing one. This class uses the same
+ /// Node type as the underlying graph, and each valid node of the
+ /// original graph is valid in this arc set, therefore the node
+ /// objects of the original graph can be used directly with this
+ /// class. The node handling functions (id handling, observing, and
+ /// iterators) works equivalently as in the original graph.
+ ///
+ /// \param GR The type of the graph which shares its node set with
+ /// this class. Its interface must conform to the
+ /// \ref concepts::Digraph "Digraph" or \ref concepts::Graph "Graph"
+ /// concept.
+ ///
+ /// This implementation is slightly faster than the \c ListArcSet,
+ /// because it uses continuous storage for arcs and it uses just
+ /// single-linked lists for enumerate outgoing and incoming
+ /// arcs. Therefore the arcs cannot be erased from the arc sets.
+ ///
+ /// This class fully conforms to the \ref concepts::Digraph "Digraph"
+ /// concept.
+ /// It provides only linear time counting for nodes and arcs.
+ ///
+ /// \warning If a node is erased from the underlying graph and this
+ /// node is the source or target of one arc in the arc set, then
+ /// the arc set is invalidated, and it cannot be used anymore. The
+ /// validity can be checked with the \c valid() member function.
+ template <typename GR>
+ class SmartArcSet : public ArcSetExtender<SmartArcSetBase<GR> > {
+ typedef ArcSetExtender<SmartArcSetBase<GR> > Parent;
+
+ public:
+
+ typedef typename Parent::Node Node;
+ typedef typename Parent::Arc Arc;
+
+ protected:
+
+ typedef typename Parent::NodesImplBase NodesImplBase;
+
+ void eraseNode(const Node& node) {
+ if (typename Parent::InArcIt(*this, node) == INVALID &&
+ typename Parent::OutArcIt(*this, node) == INVALID) {
+ return;
+ }
+ throw typename NodesImplBase::Notifier::ImmediateDetach();
+ }
+
+ void clearNodes() {
+ Parent::clear();
+ }
+
+ class NodesImpl : public NodesImplBase {
+ typedef NodesImplBase Parent;
+
+ public:
+ NodesImpl(const GR& graph, SmartArcSet& arcset)
+ : Parent(graph), _arcset(arcset) {}
+
+ virtual ~NodesImpl() {}
+
+ bool attached() const {
+ return Parent::attached();
+ }
+
+ protected:
+
+ virtual void erase(const Node& node) {
+ try {
+ _arcset.eraseNode(node);
+ Parent::erase(node);
+ } catch (const typename NodesImplBase::Notifier::ImmediateDetach&) {
+ Parent::clear();
+ throw;
+ }
+ }
+ virtual void erase(const std::vector<Node>& nodes) {
+ try {
+ for (int i = 0; i < int(nodes.size()); ++i) {
+ _arcset.eraseNode(nodes[i]);
+ }
+ Parent::erase(nodes);
+ } catch (const typename NodesImplBase::Notifier::ImmediateDetach&) {
+ Parent::clear();
+ throw;
+ }
+ }
+ virtual void clear() {
+ _arcset.clearNodes();
+ Parent::clear();
+ }
+
+ private:
+ SmartArcSet& _arcset;
+ };
+
+ NodesImpl _nodes;
+
+ public:
+
+ /// \brief Constructor of the ArcSet.
+ ///
+ /// Constructor of the ArcSet.
+ SmartArcSet(const GR& graph) : _nodes(graph, *this) {
+ Parent::initalize(graph, _nodes);
+ }
+
+ /// \brief Add a new arc to the digraph.
+ ///
+ /// Add a new arc to the digraph with source node \c s
+ /// and target node \c t.
+ /// \return The new arc.
+ Arc addArc(const Node& s, const Node& t) {
+ return Parent::addArc(s, t);
+ }
+
+ /// \brief Validity check
+ ///
+ /// This functions gives back false if the ArcSet is
+ /// invalidated. It occurs when a node in the underlying graph is
+ /// erased and it is not isolated in the ArcSet.
+ bool valid() const {
+ return _nodes.attached();
+ }
+
+ };
+
+
+ template <typename GR>
+ class SmartEdgeSetBase {
+ public:
+
+ typedef typename GR::Node Node;
+ typedef typename GR::NodeIt NodeIt;
+
+ protected:
+
+ struct NodeT {
+ int first_out;
+ NodeT() : first_out(-1) {}
+ };
+
+ typedef typename ItemSetTraits<GR, Node>::
+ template Map<NodeT>::Type NodesImplBase;
+
+ NodesImplBase* _nodes;
+
+ struct ArcT {
+ Node target;
+ int next_out;
+ ArcT() {}
+ };
+
+ std::vector<ArcT> arcs;
+
+ const GR* _graph;
+
+ void initalize(const GR& graph, NodesImplBase& nodes) {
+ _graph = &graph;
+ _nodes = &nodes;
+ }
+
+ public:
+
+ class Edge {
+ friend class SmartEdgeSetBase;
+ protected:
+
+ int id;
+ explicit Edge(int _id) { id = _id;}
+
+ public:
+ Edge() {}
+ Edge (Invalid) { id = -1; }
+ bool operator==(const Edge& arc) const {return id == arc.id;}
+ bool operator!=(const Edge& arc) const {return id != arc.id;}
+ bool operator<(const Edge& arc) const {return id < arc.id;}
+ };
+
+ class Arc {
+ friend class SmartEdgeSetBase;
+ protected:
+ Arc(int _id) : id(_id) {}
+ int id;
+ public:
+ operator Edge() const { return edgeFromId(id / 2); }
+
+ Arc() {}
+ Arc(Invalid) : id(-1) {}
+ bool operator==(const Arc& arc) const { return id == arc.id; }
+ bool operator!=(const Arc& arc) const { return id != arc.id; }
+ bool operator<(const Arc& arc) const { return id < arc.id; }
+ };
+
+ SmartEdgeSetBase() {}
+
+ Node addNode() {
+ LEMON_ASSERT(false,
+ "This graph structure does not support node insertion");
+ return INVALID; // avoid warning
+ }
+
+ Edge addEdge(const Node& u, const Node& v) {
+ int n = arcs.size();
+ arcs.push_back(ArcT());
+ arcs.push_back(ArcT());
+
+ arcs[n].target = u;
+ arcs[n | 1].target = v;
+
+ arcs[n].next_out = (*_nodes)[v].first_out;
+ (*_nodes)[v].first_out = n;
+
+ arcs[n | 1].next_out = (*_nodes)[u].first_out;
+ (*_nodes)[u].first_out = (n | 1);
+
+ return Edge(n / 2);
+ }
+
+ void clear() {
+ Node node;
+ for (first(node); node != INVALID; next(node)) {
+ (*_nodes)[node].first_out = -1;
+ }
+ arcs.clear();
+ }
+
+ void first(Node& node) const {
+ _graph->first(node);
+ }
+
+ void next(Node& node) const {
+ _graph->next(node);
+ }
+
+ void first(Arc& arc) const {
+ arc.id = arcs.size() - 1;
+ }
+
+ static void next(Arc& arc) {
+ --arc.id;
+ }
+
+ void first(Edge& arc) const {
+ arc.id = arcs.size() / 2 - 1;
+ }
+
+ static void next(Edge& arc) {
+ --arc.id;
+ }
+
+ void firstOut(Arc& arc, const Node& node) const {
+ arc.id = (*_nodes)[node].first_out;
+ }
+
+ void nextOut(Arc& arc) const {
+ arc.id = arcs[arc.id].next_out;
+ }
+
+ void firstIn(Arc& arc, const Node& node) const {
+ arc.id = (((*_nodes)[node].first_out) ^ 1);
+ if (arc.id == -2) arc.id = -1;
+ }
+
+ void nextIn(Arc& arc) const {
+ arc.id = ((arcs[arc.id ^ 1].next_out) ^ 1);
+ if (arc.id == -2) arc.id = -1;
+ }
+
+ void firstInc(Edge &arc, bool& dir, const Node& node) const {
+ int de = (*_nodes)[node].first_out;
+ if (de != -1 ) {
+ arc.id = de / 2;
+ dir = ((de & 1) == 1);
+ } else {
+ arc.id = -1;
+ dir = true;
+ }
+ }
+ void nextInc(Edge &arc, bool& dir) const {
+ int de = (arcs[(arc.id * 2) | (dir ? 1 : 0)].next_out);
+ if (de != -1 ) {
+ arc.id = de / 2;
+ dir = ((de & 1) == 1);
+ } else {
+ arc.id = -1;
+ dir = true;
+ }
+ }
+
+ static bool direction(Arc arc) {
+ return (arc.id & 1) == 1;
+ }
+
+ static Arc direct(Edge edge, bool dir) {
+ return Arc(edge.id * 2 + (dir ? 1 : 0));
+ }
+
+ int id(Node node) const { return _graph->id(node); }
+ static int id(Arc arc) { return arc.id; }
+ static int id(Edge arc) { return arc.id; }
+
+ Node nodeFromId(int id) const { return _graph->nodeFromId(id); }
+ static Arc arcFromId(int id) { return Arc(id); }
+ static Edge edgeFromId(int id) { return Edge(id);}
+
+ int maxNodeId() const { return _graph->maxNodeId(); };
+ int maxArcId() const { return arcs.size() - 1; }
+ int maxEdgeId() const { return arcs.size() / 2 - 1; }
+
+ Node source(Arc e) const { return arcs[e.id ^ 1].target; }
+ Node target(Arc e) const { return arcs[e.id].target; }
+
+ Node u(Edge e) const { return arcs[2 * e.id].target; }
+ Node v(Edge e) const { return arcs[2 * e.id + 1].target; }
+
+ typedef typename ItemSetTraits<GR, Node>::ItemNotifier NodeNotifier;
+
+ NodeNotifier& notifier(Node) const {
+ return _graph->notifier(Node());
+ }
+
+ template <typename V>
+ class NodeMap : public GR::template NodeMap<V> {
+ typedef typename GR::template NodeMap<V> Parent;
+
+ public:
+
+ explicit NodeMap(const SmartEdgeSetBase<GR>& arcset)
+ : Parent(*arcset._graph) { }
+
+ NodeMap(const SmartEdgeSetBase<GR>& arcset, const V& value)
+ : Parent(*arcset._graph, value) { }
+
+ NodeMap& operator=(const NodeMap& cmap) {
+ return operator=<NodeMap>(cmap);
+ }
+
+ template <typename CMap>
+ NodeMap& operator=(const CMap& cmap) {
+ Parent::operator=(cmap);
+ return *this;
+ }
+ };
+
+ };
+
+ /// \ingroup graphs
+ ///
+ /// \brief Graph using a node set of another digraph or graph and an
+ /// own edge set.
+ ///
+ /// This structure can be used to establish another graph over a
+ /// node set of an existing one. This class uses the same Node type
+ /// as the underlying graph, and each valid node of the original
+ /// graph is valid in this arc set, therefore the node objects of
+ /// the original graph can be used directly with this class. The
+ /// node handling functions (id handling, observing, and iterators)
+ /// works equivalently as in the original graph.
+ ///
+ /// \param GR The type of the graph which shares its node set
+ /// with this class. Its interface must conform to the
+ /// \ref concepts::Digraph "Digraph" or \ref concepts::Graph "Graph"
+ /// concept.
+ ///
+ /// This implementation is slightly faster than the \c ListEdgeSet,
+ /// because it uses continuous storage for edges and it uses just
+ /// single-linked lists for enumerate incident edges. Therefore the
+ /// edges cannot be erased from the edge sets.
+ ///
+ /// This class fully conforms to the \ref concepts::Graph "Graph"
+ /// concept.
+ /// It provides only linear time counting for nodes, edges and arcs.
+ ///
+ /// \warning If a node is erased from the underlying graph and this
+ /// node is incident to one edge in the edge set, then the edge set
+ /// is invalidated, and it cannot be used anymore. The validity can
+ /// be checked with the \c valid() member function.
+ template <typename GR>
+ class SmartEdgeSet : public EdgeSetExtender<SmartEdgeSetBase<GR> > {
+ typedef EdgeSetExtender<SmartEdgeSetBase<GR> > Parent;
+
+ public:
+
+ typedef typename Parent::Node Node;
+ typedef typename Parent::Arc Arc;
+ typedef typename Parent::Edge Edge;
+
+ protected:
+
+ typedef typename Parent::NodesImplBase NodesImplBase;
+
+ void eraseNode(const Node& node) {
+ if (typename Parent::IncEdgeIt(*this, node) == INVALID) {
+ return;
+ }
+ throw typename NodesImplBase::Notifier::ImmediateDetach();
+ }
+
+ void clearNodes() {
+ Parent::clear();
+ }
+
+ class NodesImpl : public NodesImplBase {
+ typedef NodesImplBase Parent;
+
+ public:
+ NodesImpl(const GR& graph, SmartEdgeSet& arcset)
+ : Parent(graph), _arcset(arcset) {}
+
+ virtual ~NodesImpl() {}
+
+ bool attached() const {
+ return Parent::attached();
+ }
+
+ protected:
+
+ virtual void erase(const Node& node) {
+ try {
+ _arcset.eraseNode(node);
+ Parent::erase(node);
+ } catch (const typename NodesImplBase::Notifier::ImmediateDetach&) {
+ Parent::clear();
+ throw;
+ }
+ }
+ virtual void erase(const std::vector<Node>& nodes) {
+ try {
+ for (int i = 0; i < int(nodes.size()); ++i) {
+ _arcset.eraseNode(nodes[i]);
+ }
+ Parent::erase(nodes);
+ } catch (const typename NodesImplBase::Notifier::ImmediateDetach&) {
+ Parent::clear();
+ throw;
+ }
+ }
+ virtual void clear() {
+ _arcset.clearNodes();
+ Parent::clear();
+ }
+
+ private:
+ SmartEdgeSet& _arcset;
+ };
+
+ NodesImpl _nodes;
+
+ public:
+
+ /// \brief Constructor of the EdgeSet.
+ ///
+ /// Constructor of the EdgeSet.
+ SmartEdgeSet(const GR& graph) : _nodes(graph, *this) {
+ Parent::initalize(graph, _nodes);
+ }
+
+ /// \brief Add a new edge to the graph.
+ ///
+ /// Add a new edge to the graph with node \c u
+ /// and node \c v endpoints.
+ /// \return The new edge.
+ Edge addEdge(const Node& u, const Node& v) {
+ return Parent::addEdge(u, v);
+ }
+
+ /// \brief Validity check
+ ///
+ /// This functions gives back false if the EdgeSet is
+ /// invalidated. It occurs when a node in the underlying graph is
+ /// erased and it is not isolated in the EdgeSet.
+ bool valid() const {
+ return _nodes.attached();
+ }
+
+ };
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/edmonds_karp.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/edmonds_karp.h
new file mode 100644
index 00000000000..92af3cba313
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/edmonds_karp.h
@@ -0,0 +1,556 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_EDMONDS_KARP_H
+#define LEMON_EDMONDS_KARP_H
+
+/// \file
+/// \ingroup max_flow
+/// \brief Implementation of the Edmonds-Karp algorithm.
+
+#include <lemon/tolerance.h>
+#include <vector>
+
+namespace lemon {
+
+ /// \brief Default traits class of EdmondsKarp class.
+ ///
+ /// Default traits class of EdmondsKarp class.
+ /// \param GR Digraph type.
+ /// \param CAP Type of capacity map.
+ template <typename GR, typename CAP>
+ struct EdmondsKarpDefaultTraits {
+
+ /// \brief The digraph type the algorithm runs on.
+ typedef GR Digraph;
+
+ /// \brief The type of the map that stores the arc capacities.
+ ///
+ /// The type of the map that stores the arc capacities.
+ /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
+ typedef CAP CapacityMap;
+
+ /// \brief The type of the flow values.
+ typedef typename CapacityMap::Value Value;
+
+ /// \brief The type of the map that stores the flow values.
+ ///
+ /// The type of the map that stores the flow values.
+ /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
+#ifdef DOXYGEN
+ typedef GR::ArcMap<Value> FlowMap;
+#else
+ typedef typename Digraph::template ArcMap<Value> FlowMap;
+#endif
+
+ /// \brief Instantiates a FlowMap.
+ ///
+ /// This function instantiates a \ref FlowMap.
+ /// \param digraph The digraph for which we would like to define
+ /// the flow map.
+ static FlowMap* createFlowMap(const Digraph& digraph) {
+ return new FlowMap(digraph);
+ }
+
+ /// \brief The tolerance used by the algorithm
+ ///
+ /// The tolerance used by the algorithm to handle inexact computation.
+ typedef lemon::Tolerance<Value> Tolerance;
+
+ };
+
+ /// \ingroup max_flow
+ ///
+ /// \brief Edmonds-Karp algorithms class.
+ ///
+ /// This class provides an implementation of the \e Edmonds-Karp \e
+ /// algorithm producing a \ref max_flow "flow of maximum value" in a
+ /// digraph \cite clrs01algorithms, \cite amo93networkflows,
+ /// \cite edmondskarp72theoretical.
+ /// The Edmonds-Karp algorithm is slower than the Preflow
+ /// algorithm, but it has an advantage of the step-by-step execution
+ /// control with feasible flow solutions. The \e source node, the \e
+ /// target node, the \e capacity of the arcs and the \e starting \e
+ /// flow value of the arcs should be passed to the algorithm
+ /// through the constructor.
+ ///
+ /// The time complexity of the algorithm is \f$ O(nm^2) \f$ in
+ /// worst case. Always try the Preflow algorithm instead of this if
+ /// you just want to compute the optimal flow.
+ ///
+ /// \tparam GR The type of the digraph the algorithm runs on.
+ /// \tparam CAP The type of the capacity map. The default map
+ /// type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
+ /// \tparam TR The traits class that defines various types used by the
+ /// algorithm. By default, it is \ref EdmondsKarpDefaultTraits
+ /// "EdmondsKarpDefaultTraits<GR, CAP>".
+ /// In most cases, this parameter should not be set directly,
+ /// consider to use the named template parameters instead.
+
+#ifdef DOXYGEN
+ template <typename GR, typename CAP, typename TR>
+#else
+ template <typename GR,
+ typename CAP = typename GR::template ArcMap<int>,
+ typename TR = EdmondsKarpDefaultTraits<GR, CAP> >
+#endif
+ class EdmondsKarp {
+ public:
+
+ /// \brief The \ref lemon::EdmondsKarpDefaultTraits "traits class"
+ /// of the algorithm.
+ typedef TR Traits;
+ /// The type of the digraph the algorithm runs on.
+ typedef typename Traits::Digraph Digraph;
+ /// The type of the capacity map.
+ typedef typename Traits::CapacityMap CapacityMap;
+ /// The type of the flow values.
+ typedef typename Traits::Value Value;
+
+ /// The type of the flow map.
+ typedef typename Traits::FlowMap FlowMap;
+ /// The type of the tolerance.
+ typedef typename Traits::Tolerance Tolerance;
+
+ private:
+
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+ typedef typename Digraph::template NodeMap<Arc> PredMap;
+
+ const Digraph& _graph;
+ const CapacityMap* _capacity;
+
+ Node _source, _target;
+
+ FlowMap* _flow;
+ bool _local_flow;
+
+ PredMap* _pred;
+ std::vector<Node> _queue;
+
+ Tolerance _tolerance;
+ Value _flow_value;
+
+ void createStructures() {
+ if (!_flow) {
+ _flow = Traits::createFlowMap(_graph);
+ _local_flow = true;
+ }
+ if (!_pred) {
+ _pred = new PredMap(_graph);
+ }
+ _queue.resize(countNodes(_graph));
+ }
+
+ void destroyStructures() {
+ if (_local_flow) {
+ delete _flow;
+ }
+ if (_pred) {
+ delete _pred;
+ }
+ }
+
+ public:
+
+ typedef EdmondsKarp Create;
+
+ ///\name Named template parameters
+
+ ///@{
+
+ template <typename T>
+ struct SetFlowMapTraits : public Traits {
+ typedef T FlowMap;
+ static FlowMap *createFlowMap(const Digraph&) {
+ LEMON_ASSERT(false, "FlowMap is not initialized");
+ return 0;
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// FlowMap type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting FlowMap
+ /// type
+ template <typename T>
+ struct SetFlowMap
+ : public EdmondsKarp<Digraph, CapacityMap, SetFlowMapTraits<T> > {
+ typedef EdmondsKarp<Digraph, CapacityMap, SetFlowMapTraits<T> > Create;
+ };
+
+ /// @}
+
+ protected:
+
+ EdmondsKarp() {}
+
+ public:
+
+ /// \brief The constructor of the class.
+ ///
+ /// The constructor of the class.
+ /// \param digraph The digraph the algorithm runs on.
+ /// \param capacity The capacity of the arcs.
+ /// \param source The source node.
+ /// \param target The target node.
+ EdmondsKarp(const Digraph& digraph, const CapacityMap& capacity,
+ Node source, Node target)
+ : _graph(digraph), _capacity(&capacity), _source(source), _target(target),
+ _flow(0), _local_flow(false), _pred(0), _tolerance(), _flow_value()
+ {
+ LEMON_ASSERT(_source != _target,
+ "Flow source and target are the same nodes.");
+ }
+
+ /// \brief Destructor.
+ ///
+ /// Destructor.
+ ~EdmondsKarp() {
+ destroyStructures();
+ }
+
+ /// \brief Sets the capacity map.
+ ///
+ /// Sets the capacity map.
+ /// \return <tt>(*this)</tt>
+ EdmondsKarp& capacityMap(const CapacityMap& map) {
+ _capacity = &map;
+ return *this;
+ }
+
+ /// \brief Sets the flow map.
+ ///
+ /// Sets the flow map.
+ /// If you don't use this function before calling \ref run() or
+ /// \ref init(), an instance will be allocated automatically.
+ /// The destructor deallocates this automatically allocated map,
+ /// of course.
+ /// \return <tt>(*this)</tt>
+ EdmondsKarp& flowMap(FlowMap& map) {
+ if (_local_flow) {
+ delete _flow;
+ _local_flow = false;
+ }
+ _flow = &map;
+ return *this;
+ }
+
+ /// \brief Sets the source node.
+ ///
+ /// Sets the source node.
+ /// \return <tt>(*this)</tt>
+ EdmondsKarp& source(const Node& node) {
+ _source = node;
+ return *this;
+ }
+
+ /// \brief Sets the target node.
+ ///
+ /// Sets the target node.
+ /// \return <tt>(*this)</tt>
+ EdmondsKarp& target(const Node& node) {
+ _target = node;
+ return *this;
+ }
+
+ /// \brief Sets the tolerance used by algorithm.
+ ///
+ /// Sets the tolerance used by algorithm.
+ /// \return <tt>(*this)</tt>
+ EdmondsKarp& tolerance(const Tolerance& tolerance) {
+ _tolerance = tolerance;
+ return *this;
+ }
+
+ /// \brief Returns a const reference to the tolerance.
+ ///
+ /// Returns a const reference to the tolerance object used by
+ /// the algorithm.
+ const Tolerance& tolerance() const {
+ return _tolerance;
+ }
+
+ /// \name Execution control
+ /// The simplest way to execute the algorithm is to use \ref run().\n
+ /// If you need better control on the initial solution or the execution,
+ /// you have to call one of the \ref init() functions first, then
+ /// \ref start() or multiple times the \ref augment() function.
+
+ ///@{
+
+ /// \brief Initializes the algorithm.
+ ///
+ /// Initializes the internal data structures and sets the initial
+ /// flow to zero on each arc.
+ void init() {
+ createStructures();
+ for (ArcIt it(_graph); it != INVALID; ++it) {
+ _flow->set(it, 0);
+ }
+ _flow_value = 0;
+ }
+
+ /// \brief Initializes the algorithm using the given flow map.
+ ///
+ /// Initializes the internal data structures and sets the initial
+ /// flow to the given \c flowMap. The \c flowMap should
+ /// contain a feasible flow, i.e. at each node excluding the source
+ /// and the target, the incoming flow should be equal to the
+ /// outgoing flow.
+ template <typename FlowMap>
+ void init(const FlowMap& flowMap) {
+ createStructures();
+ for (ArcIt e(_graph); e != INVALID; ++e) {
+ _flow->set(e, flowMap[e]);
+ }
+ _flow_value = 0;
+ for (OutArcIt jt(_graph, _source); jt != INVALID; ++jt) {
+ _flow_value += (*_flow)[jt];
+ }
+ for (InArcIt jt(_graph, _source); jt != INVALID; ++jt) {
+ _flow_value -= (*_flow)[jt];
+ }
+ }
+
+ /// \brief Initializes the algorithm using the given flow map.
+ ///
+ /// Initializes the internal data structures and sets the initial
+ /// flow to the given \c flowMap. The \c flowMap should
+ /// contain a feasible flow, i.e. at each node excluding the source
+ /// and the target, the incoming flow should be equal to the
+ /// outgoing flow.
+ /// \return \c false when the given \c flowMap does not contain a
+ /// feasible flow.
+ template <typename FlowMap>
+ bool checkedInit(const FlowMap& flowMap) {
+ createStructures();
+ for (ArcIt e(_graph); e != INVALID; ++e) {
+ _flow->set(e, flowMap[e]);
+ }
+ for (NodeIt it(_graph); it != INVALID; ++it) {
+ if (it == _source || it == _target) continue;
+ Value outFlow = 0;
+ for (OutArcIt jt(_graph, it); jt != INVALID; ++jt) {
+ outFlow += (*_flow)[jt];
+ }
+ Value inFlow = 0;
+ for (InArcIt jt(_graph, it); jt != INVALID; ++jt) {
+ inFlow += (*_flow)[jt];
+ }
+ if (_tolerance.different(outFlow, inFlow)) {
+ return false;
+ }
+ }
+ for (ArcIt it(_graph); it != INVALID; ++it) {
+ if (_tolerance.less((*_flow)[it], 0)) return false;
+ if (_tolerance.less((*_capacity)[it], (*_flow)[it])) return false;
+ }
+ _flow_value = 0;
+ for (OutArcIt jt(_graph, _source); jt != INVALID; ++jt) {
+ _flow_value += (*_flow)[jt];
+ }
+ for (InArcIt jt(_graph, _source); jt != INVALID; ++jt) {
+ _flow_value -= (*_flow)[jt];
+ }
+ return true;
+ }
+
+ /// \brief Augments the solution along a shortest path.
+ ///
+ /// Augments the solution along a shortest path. This function searches a
+ /// shortest path between the source and the target
+ /// in the residual digraph by the Bfs algoritm.
+ /// Then it increases the flow on this path with the minimal residual
+ /// capacity on the path. If there is no such path, it gives back
+ /// false.
+ /// \return \c false when the augmenting did not success, i.e. the
+ /// current flow is a feasible and optimal solution.
+ bool augment() {
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ _pred->set(n, INVALID);
+ }
+
+ int first = 0, last = 1;
+
+ _queue[0] = _source;
+ _pred->set(_source, OutArcIt(_graph, _source));
+
+ while (first != last && (*_pred)[_target] == INVALID) {
+ Node n = _queue[first++];
+
+ for (OutArcIt e(_graph, n); e != INVALID; ++e) {
+ Value rem = (*_capacity)[e] - (*_flow)[e];
+ Node t = _graph.target(e);
+ if (_tolerance.positive(rem) && (*_pred)[t] == INVALID) {
+ _pred->set(t, e);
+ _queue[last++] = t;
+ }
+ }
+ for (InArcIt e(_graph, n); e != INVALID; ++e) {
+ Value rem = (*_flow)[e];
+ Node t = _graph.source(e);
+ if (_tolerance.positive(rem) && (*_pred)[t] == INVALID) {
+ _pred->set(t, e);
+ _queue[last++] = t;
+ }
+ }
+ }
+
+ if ((*_pred)[_target] != INVALID) {
+ Node n = _target;
+ Arc e = (*_pred)[n];
+
+ Value prem = (*_capacity)[e] - (*_flow)[e];
+ n = _graph.source(e);
+ while (n != _source) {
+ e = (*_pred)[n];
+ if (_graph.target(e) == n) {
+ Value rem = (*_capacity)[e] - (*_flow)[e];
+ if (rem < prem) prem = rem;
+ n = _graph.source(e);
+ } else {
+ Value rem = (*_flow)[e];
+ if (rem < prem) prem = rem;
+ n = _graph.target(e);
+ }
+ }
+
+ n = _target;
+ e = (*_pred)[n];
+
+ _flow->set(e, (*_flow)[e] + prem);
+ n = _graph.source(e);
+ while (n != _source) {
+ e = (*_pred)[n];
+ if (_graph.target(e) == n) {
+ _flow->set(e, (*_flow)[e] + prem);
+ n = _graph.source(e);
+ } else {
+ _flow->set(e, (*_flow)[e] - prem);
+ n = _graph.target(e);
+ }
+ }
+
+ _flow_value += prem;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /// \brief Executes the algorithm
+ ///
+ /// Executes the algorithm by performing augmenting phases until the
+ /// optimal solution is reached.
+ /// \pre One of the \ref init() functions must be called before
+ /// using this function.
+ void start() {
+ while (augment()) {}
+ }
+
+ /// \brief Runs the algorithm.
+ ///
+ /// Runs the Edmonds-Karp algorithm.
+ /// \note ek.run() is just a shortcut of the following code.
+ ///\code
+ /// ek.init();
+ /// ek.start();
+ ///\endcode
+ void run() {
+ init();
+ start();
+ }
+
+ /// @}
+
+ /// \name Query Functions
+ /// The result of the Edmonds-Karp algorithm can be obtained using these
+ /// functions.\n
+ /// Either \ref run() or \ref start() should be called before using them.
+
+ ///@{
+
+ /// \brief Returns the value of the maximum flow.
+ ///
+ /// Returns the value of the maximum flow found by the algorithm.
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ Value flowValue() const {
+ return _flow_value;
+ }
+
+ /// \brief Returns the flow value on the given arc.
+ ///
+ /// Returns the flow value on the given arc.
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ Value flow(const Arc& arc) const {
+ return (*_flow)[arc];
+ }
+
+ /// \brief Returns a const reference to the flow map.
+ ///
+ /// Returns a const reference to the arc map storing the found flow.
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ const FlowMap& flowMap() const {
+ return *_flow;
+ }
+
+ /// \brief Returns \c true when the node is on the source side of the
+ /// minimum cut.
+ ///
+ /// Returns true when the node is on the source side of the found
+ /// minimum cut.
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ bool minCut(const Node& node) const {
+ return ((*_pred)[node] != INVALID) || node == _source;
+ }
+
+ /// \brief Gives back a minimum value cut.
+ ///
+ /// Sets \c cutMap to the characteristic vector of a minimum value
+ /// cut. \c cutMap should be a \ref concepts::WriteMap "writable"
+ /// node map with \c bool (or convertible) value type.
+ ///
+ /// \note This function calls \ref minCut() for each node, so it runs in
+ /// O(n) time.
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ template <typename CutMap>
+ void minCutMap(CutMap& cutMap) const {
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ cutMap.set(n, (*_pred)[n] != INVALID);
+ }
+ cutMap.set(_source, true);
+ }
+
+ /// @}
+
+ };
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/elevator.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/elevator.h
new file mode 100644
index 00000000000..e4adcd59982
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/elevator.h
@@ -0,0 +1,982 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_ELEVATOR_H
+#define LEMON_ELEVATOR_H
+
+///\ingroup auxdat
+///\file
+///\brief Elevator class
+///
+///Elevator class implements an efficient data structure
+///for labeling items in push-relabel type algorithms.
+///
+
+#include <lemon/core.h>
+#include <lemon/bits/traits.h>
+
+namespace lemon {
+
+ ///Class for handling "labels" in push-relabel type algorithms.
+
+ ///A class for handling "labels" in push-relabel type algorithms.
+ ///
+ ///\ingroup auxdat
+ ///Using this class you can assign "labels" (nonnegative integer numbers)
+ ///to the edges or nodes of a graph, manipulate and query them through
+ ///operations typically arising in "push-relabel" type algorithms.
+ ///
+ ///Each item is either \em active or not, and you can also choose a
+ ///highest level active item.
+ ///
+ ///\sa LinkedElevator
+ ///
+ ///\param GR Type of the underlying graph.
+ ///\param Item Type of the items the data is assigned to (\c GR::Node,
+ ///\c GR::Arc or \c GR::Edge).
+ template<class GR, class Item>
+ class Elevator
+ {
+ public:
+
+ typedef Item Key;
+ typedef int Value;
+
+ private:
+
+ typedef Item *Vit;
+ typedef typename ItemSetTraits<GR,Item>::template Map<Vit>::Type VitMap;
+ typedef typename ItemSetTraits<GR,Item>::template Map<int>::Type IntMap;
+
+ const GR &_g;
+ int _max_level;
+ int _item_num;
+ VitMap _where;
+ IntMap _level;
+ std::vector<Item> _items;
+ std::vector<Vit> _first;
+ std::vector<Vit> _last_active;
+
+ int _highest_active;
+
+ void copy(Item i, Vit p)
+ {
+ _where[*p=i] = p;
+ }
+ void copy(Vit s, Vit p)
+ {
+ if(s!=p)
+ {
+ Item i=*s;
+ *p=i;
+ _where[i] = p;
+ }
+ }
+ void swap(Vit i, Vit j)
+ {
+ Item ti=*i;
+ Vit ct = _where[ti];
+ _where[ti] = _where[*i=*j];
+ _where[*j] = ct;
+ *j=ti;
+ }
+
+ public:
+
+ ///Constructor with given maximum level.
+
+ ///Constructor with given maximum level.
+ ///
+ ///\param graph The underlying graph.
+ ///\param max_level The maximum allowed level.
+ ///Set the range of the possible labels to <tt>[0..max_level]</tt>.
+ Elevator(const GR &graph,int max_level) :
+ _g(graph),
+ _max_level(max_level),
+ _item_num(_max_level),
+ _where(graph),
+ _level(graph,0),
+ _items(_max_level),
+ _first(_max_level+2),
+ _last_active(_max_level+2),
+ _highest_active(-1) {}
+ ///Constructor.
+
+ ///Constructor.
+ ///
+ ///\param graph The underlying graph.
+ ///Set the range of the possible labels to <tt>[0..max_level]</tt>,
+ ///where \c max_level is equal to the number of labeled items in the graph.
+ Elevator(const GR &graph) :
+ _g(graph),
+ _max_level(countItems<GR, Item>(graph)),
+ _item_num(_max_level),
+ _where(graph),
+ _level(graph,0),
+ _items(_max_level),
+ _first(_max_level+2),
+ _last_active(_max_level+2),
+ _highest_active(-1)
+ {
+ }
+
+ ///Activate item \c i.
+
+ ///Activate item \c i.
+ ///\pre Item \c i shouldn't be active before.
+ void activate(Item i)
+ {
+ const int l=_level[i];
+ swap(_where[i],++_last_active[l]);
+ if(l>_highest_active) _highest_active=l;
+ }
+
+ ///Deactivate item \c i.
+
+ ///Deactivate item \c i.
+ ///\pre Item \c i must be active before.
+ void deactivate(Item i)
+ {
+ swap(_where[i],_last_active[_level[i]]--);
+ while(_highest_active>=0 &&
+ _last_active[_highest_active]<_first[_highest_active])
+ _highest_active--;
+ }
+
+ ///Query whether item \c i is active
+ bool active(Item i) const { return _where[i]<=_last_active[_level[i]]; }
+
+ ///Return the level of item \c i.
+ int operator[](Item i) const { return _level[i]; }
+
+ ///Return the number of items on level \c l.
+ int onLevel(int l) const
+ {
+ return _first[l+1]-_first[l];
+ }
+ ///Return true if level \c l is empty.
+ bool emptyLevel(int l) const
+ {
+ return _first[l+1]-_first[l]==0;
+ }
+ ///Return the number of items above level \c l.
+ int aboveLevel(int l) const
+ {
+ return _first[_max_level+1]-_first[l+1];
+ }
+ ///Return the number of active items on level \c l.
+ int activesOnLevel(int l) const
+ {
+ return _last_active[l]-_first[l]+1;
+ }
+ ///Return true if there is no active item on level \c l.
+ bool activeFree(int l) const
+ {
+ return _last_active[l]<_first[l];
+ }
+ ///Return the maximum allowed level.
+ int maxLevel() const
+ {
+ return _max_level;
+ }
+
+ ///\name Highest Active Item
+ ///Functions for working with the highest level
+ ///active item.
+
+ ///@{
+
+ ///Return a highest level active item.
+
+ ///Return a highest level active item or INVALID if there is no active
+ ///item.
+ Item highestActive() const
+ {
+ return _highest_active>=0?*_last_active[_highest_active]:INVALID;
+ }
+
+ ///Return the highest active level.
+
+ ///Return the level of the highest active item or -1 if there is no active
+ ///item.
+ int highestActiveLevel() const
+ {
+ return _highest_active;
+ }
+
+ ///Lift the highest active item by one.
+
+ ///Lift the item returned by highestActive() by one.
+ ///
+ void liftHighestActive()
+ {
+ Item it = *_last_active[_highest_active];
+ ++_level[it];
+ swap(_last_active[_highest_active]--,_last_active[_highest_active+1]);
+ --_first[++_highest_active];
+ }
+
+ ///Lift the highest active item to the given level.
+
+ ///Lift the item returned by highestActive() to level \c new_level.
+ ///
+ ///\warning \c new_level must be strictly higher
+ ///than the current level.
+ ///
+ void liftHighestActive(int new_level)
+ {
+ const Item li = *_last_active[_highest_active];
+
+ copy(--_first[_highest_active+1],_last_active[_highest_active]--);
+ for(int l=_highest_active+1;l<new_level;l++)
+ {
+ copy(--_first[l+1],_first[l]);
+ --_last_active[l];
+ }
+ copy(li,_first[new_level]);
+ _level[li] = new_level;
+ _highest_active=new_level;
+ }
+
+ ///Lift the highest active item to the top level.
+
+ ///Lift the item returned by highestActive() to the top level and
+ ///deactivate it.
+ void liftHighestActiveToTop()
+ {
+ const Item li = *_last_active[_highest_active];
+
+ copy(--_first[_highest_active+1],_last_active[_highest_active]--);
+ for(int l=_highest_active+1;l<_max_level;l++)
+ {
+ copy(--_first[l+1],_first[l]);
+ --_last_active[l];
+ }
+ copy(li,_first[_max_level]);
+ --_last_active[_max_level];
+ _level[li] = _max_level;
+
+ while(_highest_active>=0 &&
+ _last_active[_highest_active]<_first[_highest_active])
+ _highest_active--;
+ }
+
+ ///@}
+
+ ///\name Active Item on Certain Level
+ ///Functions for working with the active items.
+
+ ///@{
+
+ ///Return an active item on level \c l.
+
+ ///Return an active item on level \c l or \ref INVALID if there is no such
+ ///an item. (\c l must be from the range [0...\c max_level].
+ Item activeOn(int l) const
+ {
+ return _last_active[l]>=_first[l]?*_last_active[l]:INVALID;
+ }
+
+ ///Lift the active item returned by \c activeOn(level) by one.
+
+ ///Lift the active item returned by \ref activeOn() "activeOn(level)"
+ ///by one.
+ Item liftActiveOn(int level)
+ {
+ Item it =*_last_active[level];
+ ++_level[it];
+ swap(_last_active[level]--, --_first[level+1]);
+ if (level+1>_highest_active) ++_highest_active;
+ }
+
+ ///Lift the active item returned by \c activeOn(level) to the given level.
+
+ ///Lift the active item returned by \ref activeOn() "activeOn(level)"
+ ///to the given level.
+ void liftActiveOn(int level, int new_level)
+ {
+ const Item ai = *_last_active[level];
+
+ copy(--_first[level+1], _last_active[level]--);
+ for(int l=level+1;l<new_level;l++)
+ {
+ copy(_last_active[l],_first[l]);
+ copy(--_first[l+1], _last_active[l]--);
+ }
+ copy(ai,_first[new_level]);
+ _level[ai] = new_level;
+ if (new_level>_highest_active) _highest_active=new_level;
+ }
+
+ ///Lift the active item returned by \c activeOn(level) to the top level.
+
+ ///Lift the active item returned by \ref activeOn() "activeOn(level)"
+ ///to the top level and deactivate it.
+ void liftActiveToTop(int level)
+ {
+ const Item ai = *_last_active[level];
+
+ copy(--_first[level+1],_last_active[level]--);
+ for(int l=level+1;l<_max_level;l++)
+ {
+ copy(_last_active[l],_first[l]);
+ copy(--_first[l+1], _last_active[l]--);
+ }
+ copy(ai,_first[_max_level]);
+ --_last_active[_max_level];
+ _level[ai] = _max_level;
+
+ if (_highest_active==level) {
+ while(_highest_active>=0 &&
+ _last_active[_highest_active]<_first[_highest_active])
+ _highest_active--;
+ }
+ }
+
+ ///@}
+
+ ///Lift an active item to a higher level.
+
+ ///Lift an active item to a higher level.
+ ///\param i The item to be lifted. It must be active.
+ ///\param new_level The new level of \c i. It must be strictly higher
+ ///than the current level.
+ ///
+ void lift(Item i, int new_level)
+ {
+ const int lo = _level[i];
+ const Vit w = _where[i];
+
+ copy(_last_active[lo],w);
+ copy(--_first[lo+1],_last_active[lo]--);
+ for(int l=lo+1;l<new_level;l++)
+ {
+ copy(_last_active[l],_first[l]);
+ copy(--_first[l+1],_last_active[l]--);
+ }
+ copy(i,_first[new_level]);
+ _level[i] = new_level;
+ if(new_level>_highest_active) _highest_active=new_level;
+ }
+
+ ///Move an inactive item to the top but one level (in a dirty way).
+
+ ///This function moves an inactive item from the top level to the top
+ ///but one level (in a dirty way).
+ ///\warning It makes the underlying datastructure corrupt, so use it
+ ///only if you really know what it is for.
+ ///\pre The item is on the top level.
+ void dirtyTopButOne(Item i) {
+ _level[i] = _max_level - 1;
+ }
+
+ ///Lift all items on and above the given level to the top level.
+
+ ///This function lifts all items on and above level \c l to the top
+ ///level and deactivates them.
+ void liftToTop(int l)
+ {
+ const Vit f=_first[l];
+ const Vit tl=_first[_max_level];
+ for(Vit i=f;i!=tl;++i)
+ _level[*i] = _max_level;
+ for(int i=l;i<=_max_level;i++)
+ {
+ _first[i]=f;
+ _last_active[i]=f-1;
+ }
+ for(_highest_active=l-1;
+ _highest_active>=0 &&
+ _last_active[_highest_active]<_first[_highest_active];
+ _highest_active--) ;
+ }
+
+ private:
+ int _init_lev;
+ Vit _init_num;
+
+ public:
+
+ ///\name Initialization
+ ///Using these functions you can initialize the levels of the items.
+ ///\n
+ ///The initialization must be started with calling \c initStart().
+ ///Then the items should be listed level by level starting with the
+ ///lowest one (level 0) using \c initAddItem() and \c initNewLevel().
+ ///Finally \c initFinish() must be called.
+ ///The items not listed are put on the highest level.
+ ///@{
+
+ ///Start the initialization process.
+ void initStart()
+ {
+ _init_lev=0;
+ _init_num=&_items[0];
+ _first[0]=&_items[0];
+ _last_active[0]=&_items[0]-1;
+ Vit n=&_items[0];
+ for(typename ItemSetTraits<GR,Item>::ItemIt i(_g);i!=INVALID;++i)
+ {
+ *n=i;
+ _where[i] = n;
+ _level[i] = _max_level;
+ ++n;
+ }
+ }
+
+ ///Add an item to the current level.
+ void initAddItem(Item i)
+ {
+ swap(_where[i],_init_num);
+ _level[i] = _init_lev;
+ ++_init_num;
+ }
+
+ ///Start a new level.
+
+ ///Start a new level.
+ ///It shouldn't be used before the items on level 0 are listed.
+ void initNewLevel()
+ {
+ _init_lev++;
+ _first[_init_lev]=_init_num;
+ _last_active[_init_lev]=_init_num-1;
+ }
+
+ ///Finalize the initialization process.
+ void initFinish()
+ {
+ for(_init_lev++;_init_lev<=_max_level;_init_lev++)
+ {
+ _first[_init_lev]=_init_num;
+ _last_active[_init_lev]=_init_num-1;
+ }
+ _first[_max_level+1]=&_items[0]+_item_num;
+ _last_active[_max_level+1]=&_items[0]+_item_num-1;
+ _highest_active = -1;
+ }
+
+ ///@}
+
+ };
+
+ ///Class for handling "labels" in push-relabel type algorithms.
+
+ ///A class for handling "labels" in push-relabel type algorithms.
+ ///
+ ///\ingroup auxdat
+ ///Using this class you can assign "labels" (nonnegative integer numbers)
+ ///to the edges or nodes of a graph, manipulate and query them through
+ ///operations typically arising in "push-relabel" type algorithms.
+ ///
+ ///Each item is either \em active or not, and you can also choose a
+ ///highest level active item.
+ ///
+ ///\sa Elevator
+ ///
+ ///\param GR Type of the underlying graph.
+ ///\param Item Type of the items the data is assigned to (\c GR::Node,
+ ///\c GR::Arc or \c GR::Edge).
+ template <class GR, class Item>
+ class LinkedElevator {
+ public:
+
+ typedef Item Key;
+ typedef int Value;
+
+ private:
+
+ typedef typename ItemSetTraits<GR,Item>::
+ template Map<Item>::Type ItemMap;
+ typedef typename ItemSetTraits<GR,Item>::
+ template Map<int>::Type IntMap;
+ typedef typename ItemSetTraits<GR,Item>::
+ template Map<bool>::Type BoolMap;
+
+ const GR &_graph;
+ int _max_level;
+ int _item_num;
+ std::vector<Item> _first, _last;
+ ItemMap _prev, _next;
+ int _highest_active;
+ IntMap _level;
+ BoolMap _active;
+
+ public:
+ ///Constructor with given maximum level.
+
+ ///Constructor with given maximum level.
+ ///
+ ///\param graph The underlying graph.
+ ///\param max_level The maximum allowed level.
+ ///Set the range of the possible labels to <tt>[0..max_level]</tt>.
+ LinkedElevator(const GR& graph, int max_level)
+ : _graph(graph), _max_level(max_level), _item_num(_max_level),
+ _first(_max_level + 1), _last(_max_level + 1),
+ _prev(graph), _next(graph),
+ _highest_active(-1), _level(graph), _active(graph) {}
+
+ ///Constructor.
+
+ ///Constructor.
+ ///
+ ///\param graph The underlying graph.
+ ///Set the range of the possible labels to <tt>[0..max_level]</tt>,
+ ///where \c max_level is equal to the number of labeled items in the graph.
+ LinkedElevator(const GR& graph)
+ : _graph(graph), _max_level(countItems<GR, Item>(graph)),
+ _item_num(_max_level),
+ _first(_max_level + 1), _last(_max_level + 1),
+ _prev(graph, INVALID), _next(graph, INVALID),
+ _highest_active(-1), _level(graph), _active(graph) {}
+
+
+ ///Activate item \c i.
+
+ ///Activate item \c i.
+ ///\pre Item \c i shouldn't be active before.
+ void activate(Item i) {
+ _active[i] = true;
+
+ int level = _level[i];
+ if (level > _highest_active) {
+ _highest_active = level;
+ }
+
+ if (_prev[i] == INVALID || _active[_prev[i]]) return;
+ //unlace
+ _next[_prev[i]] = _next[i];
+ if (_next[i] != INVALID) {
+ _prev[_next[i]] = _prev[i];
+ } else {
+ _last[level] = _prev[i];
+ }
+ //lace
+ _next[i] = _first[level];
+ _prev[_first[level]] = i;
+ _prev[i] = INVALID;
+ _first[level] = i;
+
+ }
+
+ ///Deactivate item \c i.
+
+ ///Deactivate item \c i.
+ ///\pre Item \c i must be active before.
+ void deactivate(Item i) {
+ _active[i] = false;
+ int level = _level[i];
+
+ if (_next[i] == INVALID || !_active[_next[i]])
+ goto find_highest_level;
+
+ //unlace
+ _prev[_next[i]] = _prev[i];
+ if (_prev[i] != INVALID) {
+ _next[_prev[i]] = _next[i];
+ } else {
+ _first[_level[i]] = _next[i];
+ }
+ //lace
+ _prev[i] = _last[level];
+ _next[_last[level]] = i;
+ _next[i] = INVALID;
+ _last[level] = i;
+
+ find_highest_level:
+ if (level == _highest_active) {
+ while (_highest_active >= 0 && activeFree(_highest_active))
+ --_highest_active;
+ }
+ }
+
+ ///Query whether item \c i is active
+ bool active(Item i) const { return _active[i]; }
+
+ ///Return the level of item \c i.
+ int operator[](Item i) const { return _level[i]; }
+
+ ///Return the number of items on level \c l.
+ int onLevel(int l) const {
+ int num = 0;
+ Item n = _first[l];
+ while (n != INVALID) {
+ ++num;
+ n = _next[n];
+ }
+ return num;
+ }
+
+ ///Return true if the level is empty.
+ bool emptyLevel(int l) const {
+ return _first[l] == INVALID;
+ }
+
+ ///Return the number of items above level \c l.
+ int aboveLevel(int l) const {
+ int num = 0;
+ for (int level = l + 1; level < _max_level; ++level)
+ num += onLevel(level);
+ return num;
+ }
+
+ ///Return the number of active items on level \c l.
+ int activesOnLevel(int l) const {
+ int num = 0;
+ Item n = _first[l];
+ while (n != INVALID && _active[n]) {
+ ++num;
+ n = _next[n];
+ }
+ return num;
+ }
+
+ ///Return true if there is no active item on level \c l.
+ bool activeFree(int l) const {
+ return _first[l] == INVALID || !_active[_first[l]];
+ }
+
+ ///Return the maximum allowed level.
+ int maxLevel() const {
+ return _max_level;
+ }
+
+ ///\name Highest Active Item
+ ///Functions for working with the highest level
+ ///active item.
+
+ ///@{
+
+ ///Return a highest level active item.
+
+ ///Return a highest level active item or INVALID if there is no active
+ ///item.
+ Item highestActive() const {
+ return _highest_active >= 0 ? _first[_highest_active] : INVALID;
+ }
+
+ ///Return the highest active level.
+
+ ///Return the level of the highest active item or -1 if there is no active
+ ///item.
+ int highestActiveLevel() const {
+ return _highest_active;
+ }
+
+ ///Lift the highest active item by one.
+
+ ///Lift the item returned by highestActive() by one.
+ ///
+ void liftHighestActive() {
+ Item i = _first[_highest_active];
+ if (_next[i] != INVALID) {
+ _prev[_next[i]] = INVALID;
+ _first[_highest_active] = _next[i];
+ } else {
+ _first[_highest_active] = INVALID;
+ _last[_highest_active] = INVALID;
+ }
+ _level[i] = ++_highest_active;
+ if (_first[_highest_active] == INVALID) {
+ _first[_highest_active] = i;
+ _last[_highest_active] = i;
+ _prev[i] = INVALID;
+ _next[i] = INVALID;
+ } else {
+ _prev[_first[_highest_active]] = i;
+ _next[i] = _first[_highest_active];
+ _first[_highest_active] = i;
+ }
+ }
+
+ ///Lift the highest active item to the given level.
+
+ ///Lift the item returned by highestActive() to level \c new_level.
+ ///
+ ///\warning \c new_level must be strictly higher
+ ///than the current level.
+ ///
+ void liftHighestActive(int new_level) {
+ Item i = _first[_highest_active];
+ if (_next[i] != INVALID) {
+ _prev[_next[i]] = INVALID;
+ _first[_highest_active] = _next[i];
+ } else {
+ _first[_highest_active] = INVALID;
+ _last[_highest_active] = INVALID;
+ }
+ _level[i] = _highest_active = new_level;
+ if (_first[_highest_active] == INVALID) {
+ _first[_highest_active] = _last[_highest_active] = i;
+ _prev[i] = INVALID;
+ _next[i] = INVALID;
+ } else {
+ _prev[_first[_highest_active]] = i;
+ _next[i] = _first[_highest_active];
+ _first[_highest_active] = i;
+ }
+ }
+
+ ///Lift the highest active item to the top level.
+
+ ///Lift the item returned by highestActive() to the top level and
+ ///deactivate it.
+ void liftHighestActiveToTop() {
+ Item i = _first[_highest_active];
+ _level[i] = _max_level;
+ if (_next[i] != INVALID) {
+ _prev[_next[i]] = INVALID;
+ _first[_highest_active] = _next[i];
+ } else {
+ _first[_highest_active] = INVALID;
+ _last[_highest_active] = INVALID;
+ }
+ while (_highest_active >= 0 && activeFree(_highest_active))
+ --_highest_active;
+ }
+
+ ///@}
+
+ ///\name Active Item on Certain Level
+ ///Functions for working with the active items.
+
+ ///@{
+
+ ///Return an active item on level \c l.
+
+ ///Return an active item on level \c l or \ref INVALID if there is no such
+ ///an item. (\c l must be from the range [0...\c max_level].
+ Item activeOn(int l) const
+ {
+ return _active[_first[l]] ? _first[l] : INVALID;
+ }
+
+ ///Lift the active item returned by \c activeOn(l) by one.
+
+ ///Lift the active item returned by \ref activeOn() "activeOn(l)"
+ ///by one.
+ Item liftActiveOn(int l)
+ {
+ Item i = _first[l];
+ if (_next[i] != INVALID) {
+ _prev[_next[i]] = INVALID;
+ _first[l] = _next[i];
+ } else {
+ _first[l] = INVALID;
+ _last[l] = INVALID;
+ }
+ _level[i] = ++l;
+ if (_first[l] == INVALID) {
+ _first[l] = _last[l] = i;
+ _prev[i] = INVALID;
+ _next[i] = INVALID;
+ } else {
+ _prev[_first[l]] = i;
+ _next[i] = _first[l];
+ _first[l] = i;
+ }
+ if (_highest_active < l) {
+ _highest_active = l;
+ }
+ }
+
+ ///Lift the active item returned by \c activeOn(l) to the given level.
+
+ ///Lift the active item returned by \ref activeOn() "activeOn(l)"
+ ///to the given level.
+ void liftActiveOn(int l, int new_level)
+ {
+ Item i = _first[l];
+ if (_next[i] != INVALID) {
+ _prev[_next[i]] = INVALID;
+ _first[l] = _next[i];
+ } else {
+ _first[l] = INVALID;
+ _last[l] = INVALID;
+ }
+ _level[i] = l = new_level;
+ if (_first[l] == INVALID) {
+ _first[l] = _last[l] = i;
+ _prev[i] = INVALID;
+ _next[i] = INVALID;
+ } else {
+ _prev[_first[l]] = i;
+ _next[i] = _first[l];
+ _first[l] = i;
+ }
+ if (_highest_active < l) {
+ _highest_active = l;
+ }
+ }
+
+ ///Lift the active item returned by \c activeOn(l) to the top level.
+
+ ///Lift the active item returned by \ref activeOn() "activeOn(l)"
+ ///to the top level and deactivate it.
+ void liftActiveToTop(int l)
+ {
+ Item i = _first[l];
+ if (_next[i] != INVALID) {
+ _prev[_next[i]] = INVALID;
+ _first[l] = _next[i];
+ } else {
+ _first[l] = INVALID;
+ _last[l] = INVALID;
+ }
+ _level[i] = _max_level;
+ if (l == _highest_active) {
+ while (_highest_active >= 0 && activeFree(_highest_active))
+ --_highest_active;
+ }
+ }
+
+ ///@}
+
+ /// \brief Lift an active item to a higher level.
+ ///
+ /// Lift an active item to a higher level.
+ /// \param i The item to be lifted. It must be active.
+ /// \param new_level The new level of \c i. It must be strictly higher
+ /// than the current level.
+ ///
+ void lift(Item i, int new_level) {
+ if (_next[i] != INVALID) {
+ _prev[_next[i]] = _prev[i];
+ } else {
+ _last[new_level] = _prev[i];
+ }
+ if (_prev[i] != INVALID) {
+ _next[_prev[i]] = _next[i];
+ } else {
+ _first[new_level] = _next[i];
+ }
+ _level[i] = new_level;
+ if (_first[new_level] == INVALID) {
+ _first[new_level] = _last[new_level] = i;
+ _prev[i] = INVALID;
+ _next[i] = INVALID;
+ } else {
+ _prev[_first[new_level]] = i;
+ _next[i] = _first[new_level];
+ _first[new_level] = i;
+ }
+ if (_highest_active < new_level) {
+ _highest_active = new_level;
+ }
+ }
+
+ ///Move an inactive item to the top but one level (in a dirty way).
+
+ ///This function moves an inactive item from the top level to the top
+ ///but one level (in a dirty way).
+ ///\warning It makes the underlying datastructure corrupt, so use it
+ ///only if you really know what it is for.
+ ///\pre The item is on the top level.
+ void dirtyTopButOne(Item i) {
+ _level[i] = _max_level - 1;
+ }
+
+ ///Lift all items on and above the given level to the top level.
+
+ ///This function lifts all items on and above level \c l to the top
+ ///level and deactivates them.
+ void liftToTop(int l) {
+ for (int i = l + 1; _first[i] != INVALID; ++i) {
+ Item n = _first[i];
+ while (n != INVALID) {
+ _level[n] = _max_level;
+ n = _next[n];
+ }
+ _first[i] = INVALID;
+ _last[i] = INVALID;
+ }
+ if (_highest_active > l - 1) {
+ _highest_active = l - 1;
+ while (_highest_active >= 0 && activeFree(_highest_active))
+ --_highest_active;
+ }
+ }
+
+ private:
+
+ int _init_level;
+
+ public:
+
+ ///\name Initialization
+ ///Using these functions you can initialize the levels of the items.
+ ///\n
+ ///The initialization must be started with calling \c initStart().
+ ///Then the items should be listed level by level starting with the
+ ///lowest one (level 0) using \c initAddItem() and \c initNewLevel().
+ ///Finally \c initFinish() must be called.
+ ///The items not listed are put on the highest level.
+ ///@{
+
+ ///Start the initialization process.
+ void initStart() {
+
+ for (int i = 0; i <= _max_level; ++i) {
+ _first[i] = _last[i] = INVALID;
+ }
+ _init_level = 0;
+ for(typename ItemSetTraits<GR,Item>::ItemIt i(_graph);
+ i != INVALID; ++i) {
+ _level[i] = _max_level;
+ _active[i] = false;
+ }
+ }
+
+ ///Add an item to the current level.
+ void initAddItem(Item i) {
+ _level[i] = _init_level;
+ if (_last[_init_level] == INVALID) {
+ _first[_init_level] = i;
+ _last[_init_level] = i;
+ _prev[i] = INVALID;
+ _next[i] = INVALID;
+ } else {
+ _prev[i] = _last[_init_level];
+ _next[i] = INVALID;
+ _next[_last[_init_level]] = i;
+ _last[_init_level] = i;
+ }
+ }
+
+ ///Start a new level.
+
+ ///Start a new level.
+ ///It shouldn't be used before the items on level 0 are listed.
+ void initNewLevel() {
+ ++_init_level;
+ }
+
+ ///Finalize the initialization process.
+ void initFinish() {
+ _highest_active = -1;
+ }
+
+ ///@}
+
+ };
+
+
+} //END OF NAMESPACE LEMON
+
+#endif
+
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/error.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/error.h
new file mode 100644
index 00000000000..f937704541b
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/error.h
@@ -0,0 +1,276 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_ERROR_H
+#define LEMON_ERROR_H
+
+/// \ingroup exceptions
+/// \file
+/// \brief Basic exception classes and error handling.
+
+#include <exception>
+#include <string>
+#include <sstream>
+#include <iostream>
+#include <cstdlib>
+#include <memory>
+
+namespace lemon {
+
+ /// \addtogroup exceptions
+ /// @{
+
+ /// \brief Generic exception class.
+ ///
+ /// Base class for exceptions used in LEMON.
+ ///
+ class Exception : public std::exception {
+ public:
+ ///Constructor
+ Exception() throw() {}
+ ///Virtual destructor
+ virtual ~Exception() throw() {}
+ ///A short description of the exception
+ virtual const char* what() const throw() {
+ return "lemon::Exception";
+ }
+ };
+
+ /// \brief Input-Output error
+ ///
+ /// This exception is thrown when a file operation cannot be
+ /// succeeded.
+ class IoError : public Exception {
+ protected:
+ std::string _message;
+ std::string _file;
+
+ mutable std::string _what;
+ public:
+
+ /// Copy constructor
+ IoError(const IoError &error) throw() : Exception() {
+ message(error._message);
+ file(error._file);
+ }
+
+ /// Constructor
+ explicit IoError(const char *message) throw() {
+ IoError::message(message);
+ }
+
+ /// Constructor
+ explicit IoError(const std::string &message) throw() {
+ IoError::message(message);
+ }
+
+ /// Constructor
+ explicit IoError(const char *message,
+ const std::string &file) throw() {
+ IoError::message(message);
+ IoError::file(file);
+ }
+
+ /// Constructor
+ explicit IoError(const std::string &message,
+ const std::string &file) throw() {
+ IoError::message(message);
+ IoError::file(file);
+ }
+
+ /// Virtual destructor
+ virtual ~IoError() throw() {}
+
+ /// Set the error message
+ void message(const char *message) throw() {
+ try {
+ _message = message;
+ } catch (...) {}
+ }
+
+ /// Set the error message
+ void message(const std::string& message) throw() {
+ try {
+ _message = message;
+ } catch (...) {}
+ }
+
+ /// Set the file name
+ void file(const std::string &file) throw() {
+ try {
+ _file = file;
+ } catch (...) {}
+ }
+
+ /// Returns the error message
+ const std::string& message() const throw() {
+ return _message;
+ }
+
+ /// \brief Returns the filename
+ ///
+ /// Returns the filename or an empty string if it was not specified.
+ const std::string& file() const throw() {
+ return _file;
+ }
+
+ /// \brief Returns a short error message
+ ///
+ /// Returns a short error message which contains the message and the
+ /// file name.
+ virtual const char* what() const throw() {
+ try {
+ _what.clear();
+ std::ostringstream oss;
+ oss << "lemon:IoError" << ": ";
+ oss << _message;
+ if (!_file.empty()) {
+ oss << " ('" << _file << "')";
+ }
+ _what = oss.str();
+ }
+ catch (...) {}
+ if (!_what.empty()) return _what.c_str();
+ else return "lemon:IoError";
+ }
+
+ };
+
+ /// \brief Format error
+ ///
+ /// This exception is thrown when an input file has wrong
+ /// format or a data representation is not legal.
+ class FormatError : public Exception {
+ protected:
+ std::string _message;
+ std::string _file;
+ int _line;
+
+ mutable std::string _what;
+ public:
+
+ /// Copy constructor
+ FormatError(const FormatError &error) throw() : Exception() {
+ message(error._message);
+ file(error._file);
+ line(error._line);
+ }
+
+ /// Constructor
+ explicit FormatError(const char *message) throw() {
+ FormatError::message(message);
+ _line = 0;
+ }
+
+ /// Constructor
+ explicit FormatError(const std::string &message) throw() {
+ FormatError::message(message);
+ _line = 0;
+ }
+
+ /// Constructor
+ explicit FormatError(const char *message,
+ const std::string &file, int line = 0) throw() {
+ FormatError::message(message);
+ FormatError::file(file);
+ FormatError::line(line);
+ }
+
+ /// Constructor
+ explicit FormatError(const std::string &message,
+ const std::string &file, int line = 0) throw() {
+ FormatError::message(message);
+ FormatError::file(file);
+ FormatError::line(line);
+ }
+
+ /// Virtual destructor
+ virtual ~FormatError() throw() {}
+
+ /// Set the line number
+ void line(int line) throw() { _line = line; }
+
+ /// Set the error message
+ void message(const char *message) throw() {
+ try {
+ _message = message;
+ } catch (...) {}
+ }
+
+ /// Set the error message
+ void message(const std::string& message) throw() {
+ try {
+ _message = message;
+ } catch (...) {}
+ }
+
+ /// Set the file name
+ void file(const std::string &file) throw() {
+ try {
+ _file = file;
+ } catch (...) {}
+ }
+
+ /// \brief Returns the line number
+ ///
+ /// Returns the line number or zero if it was not specified.
+ int line() const throw() { return _line; }
+
+ /// Returns the error message
+ const std::string& message() const throw() {
+ return _message;
+ }
+
+ /// \brief Returns the filename
+ ///
+ /// Returns the filename or an empty string if it was not specified.
+ const std::string& file() const throw() {
+ return _file;
+ }
+
+ /// \brief Returns a short error message
+ ///
+ /// Returns a short error message which contains the message, the
+ /// file name and the line number.
+ virtual const char* what() const throw() {
+ try {
+ _what.clear();
+ std::ostringstream oss;
+ oss << "lemon:FormatError" << ": ";
+ oss << _message;
+ if (!_file.empty() || _line != 0) {
+ oss << " (";
+ if (!_file.empty()) oss << "in file '" << _file << "'";
+ if (!_file.empty() && _line != 0) oss << " ";
+ if (_line != 0) oss << "at line " << _line;
+ oss << ")";
+ }
+ _what = oss.str();
+ }
+ catch (...) {}
+ if (!_what.empty()) return _what.c_str();
+ else return "lemon:FormatError";
+ }
+
+ };
+
+ /// @}
+
+}
+
+#endif // LEMON_ERROR_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/euler.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/euler.h
new file mode 100644
index 00000000000..3a3cbd0653d
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/euler.h
@@ -0,0 +1,287 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_EULER_H
+#define LEMON_EULER_H
+
+#include<lemon/core.h>
+#include<lemon/adaptors.h>
+#include<lemon/connectivity.h>
+#include <list>
+
+/// \ingroup graph_properties
+/// \file
+/// \brief Euler tour iterators and a function for checking the \e Eulerian
+/// property.
+///
+///This file provides Euler tour iterators and a function to check
+///if a (di)graph is \e Eulerian.
+
+namespace lemon {
+
+ ///Euler tour iterator for digraphs.
+
+ /// \ingroup graph_properties
+ ///This iterator provides an Euler tour (Eulerian circuit) of a \e directed
+ ///graph (if there exists) and it converts to the \c Arc type of the digraph.
+ ///
+ ///For example, if the given digraph has an Euler tour (i.e it has only one
+ ///non-trivial component and the in-degree is equal to the out-degree
+ ///for all nodes), then the following code will put the arcs of \c g
+ ///to the vector \c et according to an Euler tour of \c g.
+ ///\code
+ /// std::vector<ListDigraph::Arc> et;
+ /// for(DiEulerIt<ListDigraph> e(g); e!=INVALID; ++e)
+ /// et.push_back(e);
+ ///\endcode
+ ///If \c g has no Euler tour, then the resulted walk will not be closed
+ ///or not contain all arcs.
+ ///\sa EulerIt
+ template<typename GR>
+ class DiEulerIt
+ {
+ typedef typename GR::Node Node;
+ typedef typename GR::NodeIt NodeIt;
+ typedef typename GR::Arc Arc;
+ typedef typename GR::ArcIt ArcIt;
+ typedef typename GR::OutArcIt OutArcIt;
+ typedef typename GR::InArcIt InArcIt;
+
+ const GR &g;
+ typename GR::template NodeMap<OutArcIt> narc;
+ std::list<Arc> euler;
+
+ public:
+
+ ///Constructor
+
+ ///Constructor.
+ ///\param gr A digraph.
+ ///\param start The starting point of the tour. If it is not given,
+ ///the tour will start from the first node that has an outgoing arc.
+ DiEulerIt(const GR &gr, typename GR::Node start = INVALID)
+ : g(gr), narc(g)
+ {
+ if (start==INVALID) {
+ NodeIt n(g);
+ while (n!=INVALID && OutArcIt(g,n)==INVALID) ++n;
+ start=n;
+ }
+ if (start!=INVALID) {
+ for (NodeIt n(g); n!=INVALID; ++n) narc[n]=OutArcIt(g,n);
+ while (narc[start]!=INVALID) {
+ euler.push_back(narc[start]);
+ Node next=g.target(narc[start]);
+ ++narc[start];
+ start=next;
+ }
+ }
+ }
+
+ ///Arc conversion
+ operator Arc() { return euler.empty()?INVALID:euler.front(); }
+ ///Compare with \c INVALID
+ bool operator==(Invalid) { return euler.empty(); }
+ ///Compare with \c INVALID
+ bool operator!=(Invalid) { return !euler.empty(); }
+
+ ///Next arc of the tour
+
+ ///Next arc of the tour
+ ///
+ DiEulerIt &operator++() {
+ Node s=g.target(euler.front());
+ euler.pop_front();
+ typename std::list<Arc>::iterator next=euler.begin();
+ while(narc[s]!=INVALID) {
+ euler.insert(next,narc[s]);
+ Node n=g.target(narc[s]);
+ ++narc[s];
+ s=n;
+ }
+ return *this;
+ }
+ ///Postfix incrementation
+
+ /// Postfix incrementation.
+ ///
+ ///\warning This incrementation
+ ///returns an \c Arc, not a \ref DiEulerIt, as one may
+ ///expect.
+ Arc operator++(int)
+ {
+ Arc e=*this;
+ ++(*this);
+ return e;
+ }
+ };
+
+ ///Euler tour iterator for graphs.
+
+ /// \ingroup graph_properties
+ ///This iterator provides an Euler tour (Eulerian circuit) of an
+ ///\e undirected graph (if there exists) and it converts to the \c Arc
+ ///and \c Edge types of the graph.
+ ///
+ ///For example, if the given graph has an Euler tour (i.e it has only one
+ ///non-trivial component and the degree of each node is even),
+ ///the following code will print the arc IDs according to an
+ ///Euler tour of \c g.
+ ///\code
+ /// for(EulerIt<ListGraph> e(g); e!=INVALID; ++e) {
+ /// std::cout << g.id(Edge(e)) << std::eol;
+ /// }
+ ///\endcode
+ ///Although this iterator is for undirected graphs, it still returns
+ ///arcs in order to indicate the direction of the tour.
+ ///(But arcs convert to edges, of course.)
+ ///
+ ///If \c g has no Euler tour, then the resulted walk will not be closed
+ ///or not contain all edges.
+ template<typename GR>
+ class EulerIt
+ {
+ typedef typename GR::Node Node;
+ typedef typename GR::NodeIt NodeIt;
+ typedef typename GR::Arc Arc;
+ typedef typename GR::Edge Edge;
+ typedef typename GR::ArcIt ArcIt;
+ typedef typename GR::OutArcIt OutArcIt;
+ typedef typename GR::InArcIt InArcIt;
+
+ const GR &g;
+ typename GR::template NodeMap<OutArcIt> narc;
+ typename GR::template EdgeMap<bool> visited;
+ std::list<Arc> euler;
+
+ public:
+
+ ///Constructor
+
+ ///Constructor.
+ ///\param gr A graph.
+ ///\param start The starting point of the tour. If it is not given,
+ ///the tour will start from the first node that has an incident edge.
+ EulerIt(const GR &gr, typename GR::Node start = INVALID)
+ : g(gr), narc(g), visited(g, false)
+ {
+ if (start==INVALID) {
+ NodeIt n(g);
+ while (n!=INVALID && OutArcIt(g,n)==INVALID) ++n;
+ start=n;
+ }
+ if (start!=INVALID) {
+ for (NodeIt n(g); n!=INVALID; ++n) narc[n]=OutArcIt(g,n);
+ while(narc[start]!=INVALID) {
+ euler.push_back(narc[start]);
+ visited[narc[start]]=true;
+ Node next=g.target(narc[start]);
+ ++narc[start];
+ start=next;
+ while(narc[start]!=INVALID && visited[narc[start]]) ++narc[start];
+ }
+ }
+ }
+
+ ///Arc conversion
+ operator Arc() const { return euler.empty()?INVALID:euler.front(); }
+ ///Edge conversion
+ operator Edge() const { return euler.empty()?INVALID:euler.front(); }
+ ///Compare with \c INVALID
+ bool operator==(Invalid) const { return euler.empty(); }
+ ///Compare with \c INVALID
+ bool operator!=(Invalid) const { return !euler.empty(); }
+
+ ///Next arc of the tour
+
+ ///Next arc of the tour
+ ///
+ EulerIt &operator++() {
+ Node s=g.target(euler.front());
+ euler.pop_front();
+ typename std::list<Arc>::iterator next=euler.begin();
+ while(narc[s]!=INVALID) {
+ while(narc[s]!=INVALID && visited[narc[s]]) ++narc[s];
+ if(narc[s]==INVALID) break;
+ else {
+ euler.insert(next,narc[s]);
+ visited[narc[s]]=true;
+ Node n=g.target(narc[s]);
+ ++narc[s];
+ s=n;
+ }
+ }
+ return *this;
+ }
+
+ ///Postfix incrementation
+
+ /// Postfix incrementation.
+ ///
+ ///\warning This incrementation returns an \c Arc (which converts to
+ ///an \c Edge), not an \ref EulerIt, as one may expect.
+ Arc operator++(int)
+ {
+ Arc e=*this;
+ ++(*this);
+ return e;
+ }
+ };
+
+
+ ///Check if the given graph is Eulerian
+
+ /// \ingroup graph_properties
+ ///This function checks if the given graph is Eulerian.
+ ///It works for both directed and undirected graphs.
+ ///
+ ///By definition, a digraph is called \e Eulerian if
+ ///and only if it is connected and the number of incoming and outgoing
+ ///arcs are the same for each node.
+ ///Similarly, an undirected graph is called \e Eulerian if
+ ///and only if it is connected and the number of incident edges is even
+ ///for each node.
+ ///
+ ///\note There are (di)graphs that are not Eulerian, but still have an
+ /// Euler tour, since they may contain isolated nodes.
+ ///
+ ///\sa DiEulerIt, EulerIt
+ template<typename GR>
+#ifdef DOXYGEN
+ bool
+#else
+ typename enable_if<UndirectedTagIndicator<GR>,bool>::type
+ eulerian(const GR &g)
+ {
+ for(typename GR::NodeIt n(g);n!=INVALID;++n)
+ if(countIncEdges(g,n)%2) return false;
+ return connected(g);
+ }
+ template<class GR>
+ typename disable_if<UndirectedTagIndicator<GR>,bool>::type
+#endif
+ eulerian(const GR &g)
+ {
+ for(typename GR::NodeIt n(g);n!=INVALID;++n)
+ if(countInArcs(g,n)!=countOutArcs(g,n)) return false;
+ return connected(undirector(g));
+ }
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/fib_heap.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/fib_heap.h
new file mode 100644
index 00000000000..3441722a034
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/fib_heap.h
@@ -0,0 +1,475 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_FIB_HEAP_H
+#define LEMON_FIB_HEAP_H
+
+///\file
+///\ingroup heaps
+///\brief Fibonacci heap implementation.
+
+#include <vector>
+#include <utility>
+#include <functional>
+#include <lemon/math.h>
+
+namespace lemon {
+
+ /// \ingroup heaps
+ ///
+ /// \brief Fibonacci heap data structure.
+ ///
+ /// This class implements the \e Fibonacci \e heap data structure.
+ /// It fully conforms to the \ref concepts::Heap "heap concept".
+ ///
+ /// The methods \ref increase() and \ref erase() are not efficient in a
+ /// Fibonacci heap. In case of many calls of these operations, it is
+ /// better to use other heap structure, e.g. \ref BinHeap "binary heap".
+ ///
+ /// \tparam PR Type of the priorities of the items.
+ /// \tparam IM A read-writable item map with \c int values, used
+ /// internally to handle the cross references.
+ /// \tparam CMP A functor class for comparing the priorities.
+ /// The default is \c std::less<PR>.
+#ifdef DOXYGEN
+ template <typename PR, typename IM, typename CMP>
+#else
+ template <typename PR, typename IM, typename CMP = std::less<PR> >
+#endif
+ class FibHeap {
+ public:
+
+ /// Type of the item-int map.
+ typedef IM ItemIntMap;
+ /// Type of the priorities.
+ typedef PR Prio;
+ /// Type of the items stored in the heap.
+ typedef typename ItemIntMap::Key Item;
+ /// Type of the item-priority pairs.
+ typedef std::pair<Item,Prio> Pair;
+ /// Functor type for comparing the priorities.
+ typedef CMP Compare;
+
+ private:
+ class Store;
+
+ std::vector<Store> _data;
+ int _minimum;
+ ItemIntMap &_iim;
+ Compare _comp;
+ int _num;
+
+ public:
+
+ /// \brief Type to represent the states of the items.
+ ///
+ /// Each item has a state associated to it. It can be "in heap",
+ /// "pre-heap" or "post-heap". The latter two are indifferent from the
+ /// heap's point of view, but may be useful to the user.
+ ///
+ /// The item-int map must be initialized in such way that it assigns
+ /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
+ enum State {
+ IN_HEAP = 0, ///< = 0.
+ PRE_HEAP = -1, ///< = -1.
+ POST_HEAP = -2 ///< = -2.
+ };
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// \param map A map that assigns \c int values to the items.
+ /// It is used internally to handle the cross references.
+ /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
+ explicit FibHeap(ItemIntMap &map)
+ : _minimum(0), _iim(map), _num() {}
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// \param map A map that assigns \c int values to the items.
+ /// It is used internally to handle the cross references.
+ /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
+ /// \param comp The function object used for comparing the priorities.
+ FibHeap(ItemIntMap &map, const Compare &comp)
+ : _minimum(0), _iim(map), _comp(comp), _num() {}
+
+ /// \brief The number of items stored in the heap.
+ ///
+ /// This function returns the number of items stored in the heap.
+ int size() const { return _num; }
+
+ /// \brief Check if the heap is empty.
+ ///
+ /// This function returns \c true if the heap is empty.
+ bool empty() const { return _num==0; }
+
+ /// \brief Make the heap empty.
+ ///
+ /// This functon makes the heap empty.
+ /// It does not change the cross reference map. If you want to reuse
+ /// a heap that is not surely empty, you should first clear it and
+ /// then you should set the cross reference map to \c PRE_HEAP
+ /// for each item.
+ void clear() {
+ _data.clear(); _minimum = 0; _num = 0;
+ }
+
+ /// \brief Insert an item into the heap with the given priority.
+ ///
+ /// This function inserts the given item into the heap with the
+ /// given priority.
+ /// \param item The item to insert.
+ /// \param prio The priority of the item.
+ /// \pre \e item must not be stored in the heap.
+ void push (const Item& item, const Prio& prio) {
+ int i=_iim[item];
+ if ( i < 0 ) {
+ int s=_data.size();
+ _iim.set( item, s );
+ Store st;
+ st.name=item;
+ _data.push_back(st);
+ i=s;
+ } else {
+ _data[i].parent=_data[i].child=-1;
+ _data[i].degree=0;
+ _data[i].in=true;
+ _data[i].marked=false;
+ }
+
+ if ( _num ) {
+ _data[_data[_minimum].right_neighbor].left_neighbor=i;
+ _data[i].right_neighbor=_data[_minimum].right_neighbor;
+ _data[_minimum].right_neighbor=i;
+ _data[i].left_neighbor=_minimum;
+ if ( _comp( prio, _data[_minimum].prio) ) _minimum=i;
+ } else {
+ _data[i].right_neighbor=_data[i].left_neighbor=i;
+ _minimum=i;
+ }
+ _data[i].prio=prio;
+ ++_num;
+ }
+
+ /// \brief Return the item having minimum priority.
+ ///
+ /// This function returns the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ Item top() const { return _data[_minimum].name; }
+
+ /// \brief The minimum priority.
+ ///
+ /// This function returns the minimum priority.
+ /// \pre The heap must be non-empty.
+ Prio prio() const { return _data[_minimum].prio; }
+
+ /// \brief Remove the item having minimum priority.
+ ///
+ /// This function removes the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ void pop() {
+ /*The first case is that there are only one root.*/
+ if ( _data[_minimum].left_neighbor==_minimum ) {
+ _data[_minimum].in=false;
+ if ( _data[_minimum].degree!=0 ) {
+ makeRoot(_data[_minimum].child);
+ _minimum=_data[_minimum].child;
+ balance();
+ }
+ } else {
+ int right=_data[_minimum].right_neighbor;
+ unlace(_minimum);
+ _data[_minimum].in=false;
+ if ( _data[_minimum].degree > 0 ) {
+ int left=_data[_minimum].left_neighbor;
+ int child=_data[_minimum].child;
+ int last_child=_data[child].left_neighbor;
+
+ makeRoot(child);
+
+ _data[left].right_neighbor=child;
+ _data[child].left_neighbor=left;
+ _data[right].left_neighbor=last_child;
+ _data[last_child].right_neighbor=right;
+ }
+ _minimum=right;
+ balance();
+ } // the case where there are more roots
+ --_num;
+ }
+
+ /// \brief Remove the given item from the heap.
+ ///
+ /// This function removes the given item from the heap if it is
+ /// already stored.
+ /// \param item The item to delete.
+ /// \pre \e item must be in the heap.
+ void erase (const Item& item) {
+ int i=_iim[item];
+
+ if ( i >= 0 && _data[i].in ) {
+ if ( _data[i].parent!=-1 ) {
+ int p=_data[i].parent;
+ cut(i,p);
+ cascade(p);
+ }
+ _minimum=i; //As if its prio would be -infinity
+ pop();
+ }
+ }
+
+ /// \brief The priority of the given item.
+ ///
+ /// This function returns the priority of the given item.
+ /// \param item The item.
+ /// \pre \e item must be in the heap.
+ Prio operator[](const Item& item) const {
+ return _data[_iim[item]].prio;
+ }
+
+ /// \brief Set the priority of an item or insert it, if it is
+ /// not stored in the heap.
+ ///
+ /// This method sets the priority of the given item if it is
+ /// already stored in the heap. Otherwise it inserts the given
+ /// item into the heap with the given priority.
+ /// \param item The item.
+ /// \param prio The priority.
+ void set (const Item& item, const Prio& prio) {
+ int i=_iim[item];
+ if ( i >= 0 && _data[i].in ) {
+ if ( _comp(prio, _data[i].prio) ) decrease(item, prio);
+ if ( _comp(_data[i].prio, prio) ) increase(item, prio);
+ } else push(item, prio);
+ }
+
+ /// \brief Decrease the priority of an item to the given value.
+ ///
+ /// This function decreases the priority of an item to the given value.
+ /// \param item The item.
+ /// \param prio The priority.
+ /// \pre \e item must be stored in the heap with priority at least \e prio.
+ void decrease (const Item& item, const Prio& prio) {
+ int i=_iim[item];
+ _data[i].prio=prio;
+ int p=_data[i].parent;
+
+ if ( p!=-1 && _comp(prio, _data[p].prio) ) {
+ cut(i,p);
+ cascade(p);
+ }
+ if ( _comp(prio, _data[_minimum].prio) ) _minimum=i;
+ }
+
+ /// \brief Increase the priority of an item to the given value.
+ ///
+ /// This function increases the priority of an item to the given value.
+ /// \param item The item.
+ /// \param prio The priority.
+ /// \pre \e item must be stored in the heap with priority at most \e prio.
+ void increase (const Item& item, const Prio& prio) {
+ erase(item);
+ push(item, prio);
+ }
+
+ /// \brief Return the state of an item.
+ ///
+ /// This method returns \c PRE_HEAP if the given item has never
+ /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
+ /// and \c POST_HEAP otherwise.
+ /// In the latter case it is possible that the item will get back
+ /// to the heap again.
+ /// \param item The item.
+ State state(const Item &item) const {
+ int i=_iim[item];
+ if( i>=0 ) {
+ if ( _data[i].in ) i=0;
+ else i=-2;
+ }
+ return State(i);
+ }
+
+ /// \brief Set the state of an item in the heap.
+ ///
+ /// This function sets the state of the given item in the heap.
+ /// It can be used to manually clear the heap when it is important
+ /// to achive better time complexity.
+ /// \param i The item.
+ /// \param st The state. It should not be \c IN_HEAP.
+ void state(const Item& i, State st) {
+ switch (st) {
+ case POST_HEAP:
+ case PRE_HEAP:
+ if (state(i) == IN_HEAP) {
+ erase(i);
+ }
+ _iim[i] = st;
+ break;
+ case IN_HEAP:
+ break;
+ }
+ }
+
+ private:
+
+ void balance() {
+
+ int maxdeg=int( std::floor( 2.08*log(double(_data.size()))))+1;
+
+ std::vector<int> A(maxdeg,-1);
+
+ /*
+ *Recall that now minimum does not point to the minimum prio element.
+ *We set minimum to this during balance().
+ */
+ int anchor=_data[_minimum].left_neighbor;
+ int next=_minimum;
+ bool end=false;
+
+ do {
+ int active=next;
+ if ( anchor==active ) end=true;
+ int d=_data[active].degree;
+ next=_data[active].right_neighbor;
+
+ while (A[d]!=-1) {
+ if( _comp(_data[active].prio, _data[A[d]].prio) ) {
+ fuse(active,A[d]);
+ } else {
+ fuse(A[d],active);
+ active=A[d];
+ }
+ A[d]=-1;
+ ++d;
+ }
+ A[d]=active;
+ } while ( !end );
+
+
+ while ( _data[_minimum].parent >=0 )
+ _minimum=_data[_minimum].parent;
+ int s=_minimum;
+ int m=_minimum;
+ do {
+ if ( _comp(_data[s].prio, _data[_minimum].prio) ) _minimum=s;
+ s=_data[s].right_neighbor;
+ } while ( s != m );
+ }
+
+ void makeRoot(int c) {
+ int s=c;
+ do {
+ _data[s].parent=-1;
+ s=_data[s].right_neighbor;
+ } while ( s != c );
+ }
+
+ void cut(int a, int b) {
+ /*
+ *Replacing a from the children of b.
+ */
+ --_data[b].degree;
+
+ if ( _data[b].degree !=0 ) {
+ int child=_data[b].child;
+ if ( child==a )
+ _data[b].child=_data[child].right_neighbor;
+ unlace(a);
+ }
+
+
+ /*Lacing a to the roots.*/
+ int right=_data[_minimum].right_neighbor;
+ _data[_minimum].right_neighbor=a;
+ _data[a].left_neighbor=_minimum;
+ _data[a].right_neighbor=right;
+ _data[right].left_neighbor=a;
+
+ _data[a].parent=-1;
+ _data[a].marked=false;
+ }
+
+ void cascade(int a) {
+ if ( _data[a].parent!=-1 ) {
+ int p=_data[a].parent;
+
+ if ( _data[a].marked==false ) _data[a].marked=true;
+ else {
+ cut(a,p);
+ cascade(p);
+ }
+ }
+ }
+
+ void fuse(int a, int b) {
+ unlace(b);
+
+ /*Lacing b under a.*/
+ _data[b].parent=a;
+
+ if (_data[a].degree==0) {
+ _data[b].left_neighbor=b;
+ _data[b].right_neighbor=b;
+ _data[a].child=b;
+ } else {
+ int child=_data[a].child;
+ int last_child=_data[child].left_neighbor;
+ _data[child].left_neighbor=b;
+ _data[b].right_neighbor=child;
+ _data[last_child].right_neighbor=b;
+ _data[b].left_neighbor=last_child;
+ }
+
+ ++_data[a].degree;
+
+ _data[b].marked=false;
+ }
+
+ /*
+ *It is invoked only if a has siblings.
+ */
+ void unlace(int a) {
+ int leftn=_data[a].left_neighbor;
+ int rightn=_data[a].right_neighbor;
+ _data[leftn].right_neighbor=rightn;
+ _data[rightn].left_neighbor=leftn;
+ }
+
+
+ class Store {
+ friend class FibHeap;
+
+ Item name;
+ int parent;
+ int left_neighbor;
+ int right_neighbor;
+ int child;
+ int degree;
+ bool marked;
+ bool in;
+ Prio prio;
+
+ Store() : parent(-1), child(-1), degree(), marked(false), in(true) {}
+ };
+ };
+
+} //namespace lemon
+
+#endif //LEMON_FIB_HEAP_H
+
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/fractional_matching.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/fractional_matching.h
new file mode 100644
index 00000000000..7448f411d93
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/fractional_matching.h
@@ -0,0 +1,2139 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_FRACTIONAL_MATCHING_H
+#define LEMON_FRACTIONAL_MATCHING_H
+
+#include <vector>
+#include <queue>
+#include <set>
+#include <limits>
+
+#include <lemon/core.h>
+#include <lemon/unionfind.h>
+#include <lemon/bin_heap.h>
+#include <lemon/maps.h>
+#include <lemon/assert.h>
+#include <lemon/elevator.h>
+
+///\ingroup matching
+///\file
+///\brief Fractional matching algorithms in general graphs.
+
+namespace lemon {
+
+ /// \brief Default traits class of MaxFractionalMatching class.
+ ///
+ /// Default traits class of MaxFractionalMatching class.
+ /// \tparam GR Graph type.
+ template <typename GR>
+ struct MaxFractionalMatchingDefaultTraits {
+
+ /// \brief The type of the graph the algorithm runs on.
+ typedef GR Graph;
+
+ /// \brief The type of the map that stores the matching.
+ ///
+ /// The type of the map that stores the matching arcs.
+ /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
+ typedef typename Graph::template NodeMap<typename GR::Arc> MatchingMap;
+
+ /// \brief Instantiates a MatchingMap.
+ ///
+ /// This function instantiates a \ref MatchingMap.
+ /// \param graph The graph for which we would like to define
+ /// the matching map.
+ static MatchingMap* createMatchingMap(const Graph& graph) {
+ return new MatchingMap(graph);
+ }
+
+ /// \brief The elevator type used by MaxFractionalMatching algorithm.
+ ///
+ /// The elevator type used by MaxFractionalMatching algorithm.
+ ///
+ /// \sa Elevator
+ /// \sa LinkedElevator
+ typedef LinkedElevator<Graph, typename Graph::Node> Elevator;
+
+ /// \brief Instantiates an Elevator.
+ ///
+ /// This function instantiates an \ref Elevator.
+ /// \param graph The graph for which we would like to define
+ /// the elevator.
+ /// \param max_level The maximum level of the elevator.
+ static Elevator* createElevator(const Graph& graph, int max_level) {
+ return new Elevator(graph, max_level);
+ }
+ };
+
+ /// \ingroup matching
+ ///
+ /// \brief Max cardinality fractional matching
+ ///
+ /// This class provides an implementation of fractional matching
+ /// algorithm based on push-relabel principle.
+ ///
+ /// The maximum cardinality fractional matching is a relaxation of the
+ /// maximum cardinality matching problem where the odd set constraints
+ /// are omitted.
+ /// It can be formulated with the following linear program.
+ /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
+ /// \f[x_e \ge 0\quad \forall e\in E\f]
+ /// \f[\max \sum_{e\in E}x_e\f]
+ /// where \f$\delta(X)\f$ is the set of edges incident to a node in
+ /// \f$X\f$. The result can be represented as the union of a
+ /// matching with one value edges and a set of odd length cycles
+ /// with half value edges.
+ ///
+ /// The algorithm calculates an optimal fractional matching and a
+ /// barrier. The number of adjacents of any node set minus the size
+ /// of node set is a lower bound on the uncovered nodes in the
+ /// graph. For maximum matching a barrier is computed which
+ /// maximizes this difference.
+ ///
+ /// The algorithm can be executed with the run() function. After it
+ /// the matching (the primal solution) and the barrier (the dual
+ /// solution) can be obtained using the query functions.
+ ///
+ /// The primal solution is multiplied by
+ /// \ref MaxFractionalMatching::primalScale "2".
+ ///
+ /// \tparam GR The undirected graph type the algorithm runs on.
+#ifdef DOXYGEN
+ template <typename GR, typename TR>
+#else
+ template <typename GR,
+ typename TR = MaxFractionalMatchingDefaultTraits<GR> >
+#endif
+ class MaxFractionalMatching {
+ public:
+
+ /// \brief The \ref lemon::MaxFractionalMatchingDefaultTraits
+ /// "traits class" of the algorithm.
+ typedef TR Traits;
+ /// The type of the graph the algorithm runs on.
+ typedef typename TR::Graph Graph;
+ /// The type of the matching map.
+ typedef typename TR::MatchingMap MatchingMap;
+ /// The type of the elevator.
+ typedef typename TR::Elevator Elevator;
+
+ /// \brief Scaling factor for primal solution
+ ///
+ /// Scaling factor for primal solution.
+ static const int primalScale = 2;
+
+ private:
+
+ const Graph &_graph;
+ int _node_num;
+ bool _allow_loops;
+ int _empty_level;
+
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+ bool _local_matching;
+ MatchingMap *_matching;
+
+ bool _local_level;
+ Elevator *_level;
+
+ typedef typename Graph::template NodeMap<int> InDegMap;
+ InDegMap *_indeg;
+
+ void createStructures() {
+ _node_num = countNodes(_graph);
+
+ if (!_matching) {
+ _local_matching = true;
+ _matching = Traits::createMatchingMap(_graph);
+ }
+ if (!_level) {
+ _local_level = true;
+ _level = Traits::createElevator(_graph, _node_num);
+ }
+ if (!_indeg) {
+ _indeg = new InDegMap(_graph);
+ }
+ }
+
+ void destroyStructures() {
+ if (_local_matching) {
+ delete _matching;
+ }
+ if (_local_level) {
+ delete _level;
+ }
+ if (_indeg) {
+ delete _indeg;
+ }
+ }
+
+ void postprocessing() {
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if ((*_indeg)[n] != 0) continue;
+ _indeg->set(n, -1);
+ Node u = n;
+ while ((*_matching)[u] != INVALID) {
+ Node v = _graph.target((*_matching)[u]);
+ _indeg->set(v, -1);
+ Arc a = _graph.oppositeArc((*_matching)[u]);
+ u = _graph.target((*_matching)[v]);
+ _indeg->set(u, -1);
+ _matching->set(v, a);
+ }
+ }
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if ((*_indeg)[n] != 1) continue;
+ _indeg->set(n, -1);
+
+ int num = 1;
+ Node u = _graph.target((*_matching)[n]);
+ while (u != n) {
+ _indeg->set(u, -1);
+ u = _graph.target((*_matching)[u]);
+ ++num;
+ }
+ if (num % 2 == 0 && num > 2) {
+ Arc prev = _graph.oppositeArc((*_matching)[n]);
+ Node v = _graph.target((*_matching)[n]);
+ u = _graph.target((*_matching)[v]);
+ _matching->set(v, prev);
+ while (u != n) {
+ prev = _graph.oppositeArc((*_matching)[u]);
+ v = _graph.target((*_matching)[u]);
+ u = _graph.target((*_matching)[v]);
+ _matching->set(v, prev);
+ }
+ }
+ }
+ }
+
+ public:
+
+ typedef MaxFractionalMatching Create;
+
+ ///\name Named Template Parameters
+
+ ///@{
+
+ template <typename T>
+ struct SetMatchingMapTraits : public Traits {
+ typedef T MatchingMap;
+ static MatchingMap *createMatchingMap(const Graph&) {
+ LEMON_ASSERT(false, "MatchingMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// MatchingMap type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting MatchingMap
+ /// type.
+ template <typename T>
+ struct SetMatchingMap
+ : public MaxFractionalMatching<Graph, SetMatchingMapTraits<T> > {
+ typedef MaxFractionalMatching<Graph, SetMatchingMapTraits<T> > Create;
+ };
+
+ template <typename T>
+ struct SetElevatorTraits : public Traits {
+ typedef T Elevator;
+ static Elevator *createElevator(const Graph&, int) {
+ LEMON_ASSERT(false, "Elevator is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// Elevator type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting Elevator
+ /// type. If this named parameter is used, then an external
+ /// elevator object must be passed to the algorithm using the
+ /// \ref elevator(Elevator&) "elevator()" function before calling
+ /// \ref run() or \ref init().
+ /// \sa SetStandardElevator
+ template <typename T>
+ struct SetElevator
+ : public MaxFractionalMatching<Graph, SetElevatorTraits<T> > {
+ typedef MaxFractionalMatching<Graph, SetElevatorTraits<T> > Create;
+ };
+
+ template <typename T>
+ struct SetStandardElevatorTraits : public Traits {
+ typedef T Elevator;
+ static Elevator *createElevator(const Graph& graph, int max_level) {
+ return new Elevator(graph, max_level);
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// Elevator type with automatic allocation
+ ///
+ /// \ref named-templ-param "Named parameter" for setting Elevator
+ /// type with automatic allocation.
+ /// The Elevator should have standard constructor interface to be
+ /// able to automatically created by the algorithm (i.e. the
+ /// graph and the maximum level should be passed to it).
+ /// However an external elevator object could also be passed to the
+ /// algorithm with the \ref elevator(Elevator&) "elevator()" function
+ /// before calling \ref run() or \ref init().
+ /// \sa SetElevator
+ template <typename T>
+ struct SetStandardElevator
+ : public MaxFractionalMatching<Graph, SetStandardElevatorTraits<T> > {
+ typedef MaxFractionalMatching<Graph,
+ SetStandardElevatorTraits<T> > Create;
+ };
+
+ /// @}
+
+ protected:
+
+ MaxFractionalMatching() {}
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ ///
+ MaxFractionalMatching(const Graph &graph, bool allow_loops = true)
+ : _graph(graph), _allow_loops(allow_loops),
+ _local_matching(false), _matching(0),
+ _local_level(false), _level(0), _indeg(0)
+ {}
+
+ ~MaxFractionalMatching() {
+ destroyStructures();
+ }
+
+ /// \brief Sets the matching map.
+ ///
+ /// Sets the matching map.
+ /// If you don't use this function before calling \ref run() or
+ /// \ref init(), an instance will be allocated automatically.
+ /// The destructor deallocates this automatically allocated map,
+ /// of course.
+ /// \return <tt>(*this)</tt>
+ MaxFractionalMatching& matchingMap(MatchingMap& map) {
+ if (_local_matching) {
+ delete _matching;
+ _local_matching = false;
+ }
+ _matching = &map;
+ return *this;
+ }
+
+ /// \brief Sets the elevator used by algorithm.
+ ///
+ /// Sets the elevator used by algorithm.
+ /// If you don't use this function before calling \ref run() or
+ /// \ref init(), an instance will be allocated automatically.
+ /// The destructor deallocates this automatically allocated elevator,
+ /// of course.
+ /// \return <tt>(*this)</tt>
+ MaxFractionalMatching& elevator(Elevator& elevator) {
+ if (_local_level) {
+ delete _level;
+ _local_level = false;
+ }
+ _level = &elevator;
+ return *this;
+ }
+
+ /// \brief Returns a const reference to the elevator.
+ ///
+ /// Returns a const reference to the elevator.
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ const Elevator& elevator() const {
+ return *_level;
+ }
+
+ /// \name Execution control
+ /// The simplest way to execute the algorithm is to use one of the
+ /// member functions called \c run(). \n
+ /// If you need more control on the execution, first
+ /// you must call \ref init() and then one variant of the start()
+ /// member.
+
+ /// @{
+
+ /// \brief Initializes the internal data structures.
+ ///
+ /// Initializes the internal data structures and sets the initial
+ /// matching.
+ void init() {
+ createStructures();
+
+ _level->initStart();
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ _indeg->set(n, 0);
+ _matching->set(n, INVALID);
+ _level->initAddItem(n);
+ }
+ _level->initFinish();
+
+ _empty_level = _node_num;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ for (OutArcIt a(_graph, n); a != INVALID; ++a) {
+ if (_graph.target(a) == n && !_allow_loops) continue;
+ _matching->set(n, a);
+ Node v = _graph.target((*_matching)[n]);
+ _indeg->set(v, (*_indeg)[v] + 1);
+ break;
+ }
+ }
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if ((*_indeg)[n] == 0) {
+ _level->activate(n);
+ }
+ }
+ }
+
+ /// \brief Starts the algorithm and computes a fractional matching
+ ///
+ /// The algorithm computes a maximum fractional matching.
+ ///
+ /// \param postprocess The algorithm computes first a matching
+ /// which is a union of a matching with one value edges, cycles
+ /// with half value edges and even length paths with half value
+ /// edges. If the parameter is true, then after the push-relabel
+ /// algorithm it postprocesses the matching to contain only
+ /// matching edges and half value odd cycles.
+ void start(bool postprocess = true) {
+ Node n;
+ while ((n = _level->highestActive()) != INVALID) {
+ int level = _level->highestActiveLevel();
+ int new_level = _level->maxLevel();
+ for (InArcIt a(_graph, n); a != INVALID; ++a) {
+ Node u = _graph.source(a);
+ if (n == u && !_allow_loops) continue;
+ Node v = _graph.target((*_matching)[u]);
+ if ((*_level)[v] < level) {
+ _indeg->set(v, (*_indeg)[v] - 1);
+ if ((*_indeg)[v] == 0) {
+ _level->activate(v);
+ }
+ _matching->set(u, a);
+ _indeg->set(n, (*_indeg)[n] + 1);
+ _level->deactivate(n);
+ goto no_more_push;
+ } else if (new_level > (*_level)[v]) {
+ new_level = (*_level)[v];
+ }
+ }
+
+ if (new_level + 1 < _level->maxLevel()) {
+ _level->liftHighestActive(new_level + 1);
+ } else {
+ _level->liftHighestActiveToTop();
+ }
+ if (_level->emptyLevel(level)) {
+ _level->liftToTop(level);
+ }
+ no_more_push:
+ ;
+ }
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if ((*_matching)[n] == INVALID) continue;
+ Node u = _graph.target((*_matching)[n]);
+ if ((*_indeg)[u] > 1) {
+ _indeg->set(u, (*_indeg)[u] - 1);
+ _matching->set(n, INVALID);
+ }
+ }
+ if (postprocess) {
+ postprocessing();
+ }
+ }
+
+ /// \brief Starts the algorithm and computes a perfect fractional
+ /// matching
+ ///
+ /// The algorithm computes a perfect fractional matching. If it
+ /// does not exists, then the algorithm returns false and the
+ /// matching is undefined and the barrier.
+ ///
+ /// \param postprocess The algorithm computes first a matching
+ /// which is a union of a matching with one value edges, cycles
+ /// with half value edges and even length paths with half value
+ /// edges. If the parameter is true, then after the push-relabel
+ /// algorithm it postprocesses the matching to contain only
+ /// matching edges and half value odd cycles.
+ bool startPerfect(bool postprocess = true) {
+ Node n;
+ while ((n = _level->highestActive()) != INVALID) {
+ int level = _level->highestActiveLevel();
+ int new_level = _level->maxLevel();
+ for (InArcIt a(_graph, n); a != INVALID; ++a) {
+ Node u = _graph.source(a);
+ if (n == u && !_allow_loops) continue;
+ Node v = _graph.target((*_matching)[u]);
+ if ((*_level)[v] < level) {
+ _indeg->set(v, (*_indeg)[v] - 1);
+ if ((*_indeg)[v] == 0) {
+ _level->activate(v);
+ }
+ _matching->set(u, a);
+ _indeg->set(n, (*_indeg)[n] + 1);
+ _level->deactivate(n);
+ goto no_more_push;
+ } else if (new_level > (*_level)[v]) {
+ new_level = (*_level)[v];
+ }
+ }
+
+ if (new_level + 1 < _level->maxLevel()) {
+ _level->liftHighestActive(new_level + 1);
+ } else {
+ _level->liftHighestActiveToTop();
+ _empty_level = _level->maxLevel() - 1;
+ return false;
+ }
+ if (_level->emptyLevel(level)) {
+ _level->liftToTop(level);
+ _empty_level = level;
+ return false;
+ }
+ no_more_push:
+ ;
+ }
+ if (postprocess) {
+ postprocessing();
+ }
+ return true;
+ }
+
+ /// \brief Runs the algorithm
+ ///
+ /// Just a shortcut for the next code:
+ ///\code
+ /// init();
+ /// start();
+ ///\endcode
+ void run(bool postprocess = true) {
+ init();
+ start(postprocess);
+ }
+
+ /// \brief Runs the algorithm to find a perfect fractional matching
+ ///
+ /// Just a shortcut for the next code:
+ ///\code
+ /// init();
+ /// startPerfect();
+ ///\endcode
+ bool runPerfect(bool postprocess = true) {
+ init();
+ return startPerfect(postprocess);
+ }
+
+ ///@}
+
+ /// \name Query Functions
+ /// The result of the %Matching algorithm can be obtained using these
+ /// functions.\n
+ /// Before the use of these functions,
+ /// either run() or start() must be called.
+ ///@{
+
+
+ /// \brief Return the number of covered nodes in the matching.
+ ///
+ /// This function returns the number of covered nodes in the matching.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ int matchingSize() const {
+ int num = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if ((*_matching)[n] != INVALID) {
+ ++num;
+ }
+ }
+ return num;
+ }
+
+ /// \brief Returns a const reference to the matching map.
+ ///
+ /// Returns a const reference to the node map storing the found
+ /// fractional matching. This method can be called after
+ /// running the algorithm.
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ const MatchingMap& matchingMap() const {
+ return *_matching;
+ }
+
+ /// \brief Return \c true if the given edge is in the matching.
+ ///
+ /// This function returns \c true if the given edge is in the
+ /// found matching. The result is scaled by \ref primalScale
+ /// "primal scale".
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ int matching(const Edge& edge) const {
+ return (edge == (*_matching)[_graph.u(edge)] ? 1 : 0) +
+ (edge == (*_matching)[_graph.v(edge)] ? 1 : 0);
+ }
+
+ /// \brief Return the fractional matching arc (or edge) incident
+ /// to the given node.
+ ///
+ /// This function returns one of the fractional matching arc (or
+ /// edge) incident to the given node in the found matching or \c
+ /// INVALID if the node is not covered by the matching or if the
+ /// node is on an odd length cycle then it is the successor edge
+ /// on the cycle.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Arc matching(const Node& node) const {
+ return (*_matching)[node];
+ }
+
+ /// \brief Returns true if the node is in the barrier
+ ///
+ /// The barrier is a subset of the nodes. If the nodes in the
+ /// barrier have less adjacent nodes than the size of the barrier,
+ /// then at least as much nodes cannot be covered as the
+ /// difference of the two subsets.
+ bool barrier(const Node& node) const {
+ return (*_level)[node] >= _empty_level;
+ }
+
+ /// @}
+
+ };
+
+ /// \ingroup matching
+ ///
+ /// \brief Weighted fractional matching in general graphs
+ ///
+ /// This class provides an efficient implementation of fractional
+ /// matching algorithm. The implementation uses priority queues and
+ /// provides \f$O(nm\log n)\f$ time complexity.
+ ///
+ /// The maximum weighted fractional matching is a relaxation of the
+ /// maximum weighted matching problem where the odd set constraints
+ /// are omitted.
+ /// It can be formulated with the following linear program.
+ /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
+ /// \f[x_e \ge 0\quad \forall e\in E\f]
+ /// \f[\max \sum_{e\in E}x_ew_e\f]
+ /// where \f$\delta(X)\f$ is the set of edges incident to a node in
+ /// \f$X\f$. The result must be the union of a matching with one
+ /// value edges and a set of odd length cycles with half value edges.
+ ///
+ /// The algorithm calculates an optimal fractional matching and a
+ /// proof of the optimality. The solution of the dual problem can be
+ /// used to check the result of the algorithm. The dual linear
+ /// problem is the following.
+ /// \f[ y_u + y_v \ge w_{uv} \quad \forall uv\in E\f]
+ /// \f[y_u \ge 0 \quad \forall u \in V\f]
+ /// \f[\min \sum_{u \in V}y_u \f]
+ ///
+ /// The algorithm can be executed with the run() function.
+ /// After it the matching (the primal solution) and the dual solution
+ /// can be obtained using the query functions.
+ ///
+ /// The primal solution is multiplied by
+ /// \ref MaxWeightedFractionalMatching::primalScale "2".
+ /// If the value type is integer, then the dual
+ /// solution is scaled by
+ /// \ref MaxWeightedFractionalMatching::dualScale "4".
+ ///
+ /// \tparam GR The undirected graph type the algorithm runs on.
+ /// \tparam WM The type edge weight map. The default type is
+ /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
+#ifdef DOXYGEN
+ template <typename GR, typename WM>
+#else
+ template <typename GR,
+ typename WM = typename GR::template EdgeMap<int> >
+#endif
+ class MaxWeightedFractionalMatching {
+ public:
+
+ /// The graph type of the algorithm
+ typedef GR Graph;
+ /// The type of the edge weight map
+ typedef WM WeightMap;
+ /// The value type of the edge weights
+ typedef typename WeightMap::Value Value;
+
+ /// The type of the matching map
+ typedef typename Graph::template NodeMap<typename Graph::Arc>
+ MatchingMap;
+
+ /// \brief Scaling factor for primal solution
+ ///
+ /// Scaling factor for primal solution.
+ static const int primalScale = 2;
+
+ /// \brief Scaling factor for dual solution
+ ///
+ /// Scaling factor for dual solution. It is equal to 4 or 1
+ /// according to the value type.
+ static const int dualScale =
+ std::numeric_limits<Value>::is_integer ? 4 : 1;
+
+ private:
+
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+ typedef typename Graph::template NodeMap<Value> NodePotential;
+
+ const Graph& _graph;
+ const WeightMap& _weight;
+
+ MatchingMap* _matching;
+ NodePotential* _node_potential;
+
+ int _node_num;
+ bool _allow_loops;
+
+ enum Status {
+ EVEN = -1, MATCHED = 0, ODD = 1
+ };
+
+ typedef typename Graph::template NodeMap<Status> StatusMap;
+ StatusMap* _status;
+
+ typedef typename Graph::template NodeMap<Arc> PredMap;
+ PredMap* _pred;
+
+ typedef ExtendFindEnum<IntNodeMap> TreeSet;
+
+ IntNodeMap *_tree_set_index;
+ TreeSet *_tree_set;
+
+ IntNodeMap *_delta1_index;
+ BinHeap<Value, IntNodeMap> *_delta1;
+
+ IntNodeMap *_delta2_index;
+ BinHeap<Value, IntNodeMap> *_delta2;
+
+ IntEdgeMap *_delta3_index;
+ BinHeap<Value, IntEdgeMap> *_delta3;
+
+ Value _delta_sum;
+
+ void createStructures() {
+ _node_num = countNodes(_graph);
+
+ if (!_matching) {
+ _matching = new MatchingMap(_graph);
+ }
+ if (!_node_potential) {
+ _node_potential = new NodePotential(_graph);
+ }
+ if (!_status) {
+ _status = new StatusMap(_graph);
+ }
+ if (!_pred) {
+ _pred = new PredMap(_graph);
+ }
+ if (!_tree_set) {
+ _tree_set_index = new IntNodeMap(_graph);
+ _tree_set = new TreeSet(*_tree_set_index);
+ }
+ if (!_delta1) {
+ _delta1_index = new IntNodeMap(_graph);
+ _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
+ }
+ if (!_delta2) {
+ _delta2_index = new IntNodeMap(_graph);
+ _delta2 = new BinHeap<Value, IntNodeMap>(*_delta2_index);
+ }
+ if (!_delta3) {
+ _delta3_index = new IntEdgeMap(_graph);
+ _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
+ }
+ }
+
+ void destroyStructures() {
+ if (_matching) {
+ delete _matching;
+ }
+ if (_node_potential) {
+ delete _node_potential;
+ }
+ if (_status) {
+ delete _status;
+ }
+ if (_pred) {
+ delete _pred;
+ }
+ if (_tree_set) {
+ delete _tree_set_index;
+ delete _tree_set;
+ }
+ if (_delta1) {
+ delete _delta1_index;
+ delete _delta1;
+ }
+ if (_delta2) {
+ delete _delta2_index;
+ delete _delta2;
+ }
+ if (_delta3) {
+ delete _delta3_index;
+ delete _delta3;
+ }
+ }
+
+ void matchedToEven(Node node, int tree) {
+ _tree_set->insert(node, tree);
+ _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
+ _delta1->push(node, (*_node_potential)[node]);
+
+ if (_delta2->state(node) == _delta2->IN_HEAP) {
+ _delta2->erase(node);
+ }
+
+ for (InArcIt a(_graph, node); a != INVALID; ++a) {
+ Node v = _graph.source(a);
+ Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
+ dualScale * _weight[a];
+ if (node == v) {
+ if (_allow_loops && _graph.direction(a)) {
+ _delta3->push(a, rw / 2);
+ }
+ } else if ((*_status)[v] == EVEN) {
+ _delta3->push(a, rw / 2);
+ } else if ((*_status)[v] == MATCHED) {
+ if (_delta2->state(v) != _delta2->IN_HEAP) {
+ _pred->set(v, a);
+ _delta2->push(v, rw);
+ } else if ((*_delta2)[v] > rw) {
+ _pred->set(v, a);
+ _delta2->decrease(v, rw);
+ }
+ }
+ }
+ }
+
+ void matchedToOdd(Node node, int tree) {
+ _tree_set->insert(node, tree);
+ _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
+
+ if (_delta2->state(node) == _delta2->IN_HEAP) {
+ _delta2->erase(node);
+ }
+ }
+
+ void evenToMatched(Node node, int tree) {
+ _delta1->erase(node);
+ _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
+ Arc min = INVALID;
+ Value minrw = std::numeric_limits<Value>::max();
+ for (InArcIt a(_graph, node); a != INVALID; ++a) {
+ Node v = _graph.source(a);
+ Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
+ dualScale * _weight[a];
+
+ if (node == v) {
+ if (_allow_loops && _graph.direction(a)) {
+ _delta3->erase(a);
+ }
+ } else if ((*_status)[v] == EVEN) {
+ _delta3->erase(a);
+ if (minrw > rw) {
+ min = _graph.oppositeArc(a);
+ minrw = rw;
+ }
+ } else if ((*_status)[v] == MATCHED) {
+ if ((*_pred)[v] == a) {
+ Arc mina = INVALID;
+ Value minrwa = std::numeric_limits<Value>::max();
+ for (OutArcIt aa(_graph, v); aa != INVALID; ++aa) {
+ Node va = _graph.target(aa);
+ if ((*_status)[va] != EVEN ||
+ _tree_set->find(va) == tree) continue;
+ Value rwa = (*_node_potential)[v] + (*_node_potential)[va] -
+ dualScale * _weight[aa];
+ if (minrwa > rwa) {
+ minrwa = rwa;
+ mina = aa;
+ }
+ }
+ if (mina != INVALID) {
+ _pred->set(v, mina);
+ _delta2->increase(v, minrwa);
+ } else {
+ _pred->set(v, INVALID);
+ _delta2->erase(v);
+ }
+ }
+ }
+ }
+ if (min != INVALID) {
+ _pred->set(node, min);
+ _delta2->push(node, minrw);
+ } else {
+ _pred->set(node, INVALID);
+ }
+ }
+
+ void oddToMatched(Node node) {
+ _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
+ Arc min = INVALID;
+ Value minrw = std::numeric_limits<Value>::max();
+ for (InArcIt a(_graph, node); a != INVALID; ++a) {
+ Node v = _graph.source(a);
+ if ((*_status)[v] != EVEN) continue;
+ Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
+ dualScale * _weight[a];
+
+ if (minrw > rw) {
+ min = _graph.oppositeArc(a);
+ minrw = rw;
+ }
+ }
+ if (min != INVALID) {
+ _pred->set(node, min);
+ _delta2->push(node, minrw);
+ } else {
+ _pred->set(node, INVALID);
+ }
+ }
+
+ void alternatePath(Node even, int tree) {
+ Node odd;
+
+ _status->set(even, MATCHED);
+ evenToMatched(even, tree);
+
+ Arc prev = (*_matching)[even];
+ while (prev != INVALID) {
+ odd = _graph.target(prev);
+ even = _graph.target((*_pred)[odd]);
+ _matching->set(odd, (*_pred)[odd]);
+ _status->set(odd, MATCHED);
+ oddToMatched(odd);
+
+ prev = (*_matching)[even];
+ _status->set(even, MATCHED);
+ _matching->set(even, _graph.oppositeArc((*_matching)[odd]));
+ evenToMatched(even, tree);
+ }
+ }
+
+ void destroyTree(int tree) {
+ for (typename TreeSet::ItemIt n(*_tree_set, tree); n != INVALID; ++n) {
+ if ((*_status)[n] == EVEN) {
+ _status->set(n, MATCHED);
+ evenToMatched(n, tree);
+ } else if ((*_status)[n] == ODD) {
+ _status->set(n, MATCHED);
+ oddToMatched(n);
+ }
+ }
+ _tree_set->eraseClass(tree);
+ }
+
+
+ void unmatchNode(const Node& node) {
+ int tree = _tree_set->find(node);
+
+ alternatePath(node, tree);
+ destroyTree(tree);
+
+ _matching->set(node, INVALID);
+ }
+
+
+ void augmentOnEdge(const Edge& edge) {
+ Node left = _graph.u(edge);
+ int left_tree = _tree_set->find(left);
+
+ alternatePath(left, left_tree);
+ destroyTree(left_tree);
+ _matching->set(left, _graph.direct(edge, true));
+
+ Node right = _graph.v(edge);
+ int right_tree = _tree_set->find(right);
+
+ alternatePath(right, right_tree);
+ destroyTree(right_tree);
+ _matching->set(right, _graph.direct(edge, false));
+ }
+
+ void augmentOnArc(const Arc& arc) {
+ Node left = _graph.source(arc);
+ _status->set(left, MATCHED);
+ _matching->set(left, arc);
+ _pred->set(left, arc);
+
+ Node right = _graph.target(arc);
+ int right_tree = _tree_set->find(right);
+
+ alternatePath(right, right_tree);
+ destroyTree(right_tree);
+ _matching->set(right, _graph.oppositeArc(arc));
+ }
+
+ void extendOnArc(const Arc& arc) {
+ Node base = _graph.target(arc);
+ int tree = _tree_set->find(base);
+
+ Node odd = _graph.source(arc);
+ _tree_set->insert(odd, tree);
+ _status->set(odd, ODD);
+ matchedToOdd(odd, tree);
+ _pred->set(odd, arc);
+
+ Node even = _graph.target((*_matching)[odd]);
+ _tree_set->insert(even, tree);
+ _status->set(even, EVEN);
+ matchedToEven(even, tree);
+ }
+
+ void cycleOnEdge(const Edge& edge, int tree) {
+ Node nca = INVALID;
+ std::vector<Node> left_path, right_path;
+
+ {
+ std::set<Node> left_set, right_set;
+ Node left = _graph.u(edge);
+ left_path.push_back(left);
+ left_set.insert(left);
+
+ Node right = _graph.v(edge);
+ right_path.push_back(right);
+ right_set.insert(right);
+
+ while (true) {
+
+ if (left_set.find(right) != left_set.end()) {
+ nca = right;
+ break;
+ }
+
+ if ((*_matching)[left] == INVALID) break;
+
+ left = _graph.target((*_matching)[left]);
+ left_path.push_back(left);
+ left = _graph.target((*_pred)[left]);
+ left_path.push_back(left);
+
+ left_set.insert(left);
+
+ if (right_set.find(left) != right_set.end()) {
+ nca = left;
+ break;
+ }
+
+ if ((*_matching)[right] == INVALID) break;
+
+ right = _graph.target((*_matching)[right]);
+ right_path.push_back(right);
+ right = _graph.target((*_pred)[right]);
+ right_path.push_back(right);
+
+ right_set.insert(right);
+
+ }
+
+ if (nca == INVALID) {
+ if ((*_matching)[left] == INVALID) {
+ nca = right;
+ while (left_set.find(nca) == left_set.end()) {
+ nca = _graph.target((*_matching)[nca]);
+ right_path.push_back(nca);
+ nca = _graph.target((*_pred)[nca]);
+ right_path.push_back(nca);
+ }
+ } else {
+ nca = left;
+ while (right_set.find(nca) == right_set.end()) {
+ nca = _graph.target((*_matching)[nca]);
+ left_path.push_back(nca);
+ nca = _graph.target((*_pred)[nca]);
+ left_path.push_back(nca);
+ }
+ }
+ }
+ }
+
+ alternatePath(nca, tree);
+ Arc prev;
+
+ prev = _graph.direct(edge, true);
+ for (int i = 0; left_path[i] != nca; i += 2) {
+ _matching->set(left_path[i], prev);
+ _status->set(left_path[i], MATCHED);
+ evenToMatched(left_path[i], tree);
+
+ prev = _graph.oppositeArc((*_pred)[left_path[i + 1]]);
+ _status->set(left_path[i + 1], MATCHED);
+ oddToMatched(left_path[i + 1]);
+ }
+ _matching->set(nca, prev);
+
+ for (int i = 0; right_path[i] != nca; i += 2) {
+ _status->set(right_path[i], MATCHED);
+ evenToMatched(right_path[i], tree);
+
+ _matching->set(right_path[i + 1], (*_pred)[right_path[i + 1]]);
+ _status->set(right_path[i + 1], MATCHED);
+ oddToMatched(right_path[i + 1]);
+ }
+
+ destroyTree(tree);
+ }
+
+ void extractCycle(const Arc &arc) {
+ Node left = _graph.source(arc);
+ Node odd = _graph.target((*_matching)[left]);
+ Arc prev;
+ while (odd != left) {
+ Node even = _graph.target((*_matching)[odd]);
+ prev = (*_matching)[odd];
+ odd = _graph.target((*_matching)[even]);
+ _matching->set(even, _graph.oppositeArc(prev));
+ }
+ _matching->set(left, arc);
+
+ Node right = _graph.target(arc);
+ int right_tree = _tree_set->find(right);
+ alternatePath(right, right_tree);
+ destroyTree(right_tree);
+ _matching->set(right, _graph.oppositeArc(arc));
+ }
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ MaxWeightedFractionalMatching(const Graph& graph, const WeightMap& weight,
+ bool allow_loops = true)
+ : _graph(graph), _weight(weight), _matching(0),
+ _node_potential(0), _node_num(0), _allow_loops(allow_loops),
+ _status(0), _pred(0),
+ _tree_set_index(0), _tree_set(0),
+
+ _delta1_index(0), _delta1(0),
+ _delta2_index(0), _delta2(0),
+ _delta3_index(0), _delta3(0),
+
+ _delta_sum() {}
+
+ ~MaxWeightedFractionalMatching() {
+ destroyStructures();
+ }
+
+ /// \name Execution Control
+ /// The simplest way to execute the algorithm is to use the
+ /// \ref run() member function.
+
+ ///@{
+
+ /// \brief Initialize the algorithm
+ ///
+ /// This function initializes the algorithm.
+ void init() {
+ createStructures();
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ (*_delta1_index)[n] = _delta1->PRE_HEAP;
+ (*_delta2_index)[n] = _delta2->PRE_HEAP;
+ }
+ for (EdgeIt e(_graph); e != INVALID; ++e) {
+ (*_delta3_index)[e] = _delta3->PRE_HEAP;
+ }
+
+ _delta1->clear();
+ _delta2->clear();
+ _delta3->clear();
+ _tree_set->clear();
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ Value max = 0;
+ for (OutArcIt e(_graph, n); e != INVALID; ++e) {
+ if (_graph.target(e) == n && !_allow_loops) continue;
+ if ((dualScale * _weight[e]) / 2 > max) {
+ max = (dualScale * _weight[e]) / 2;
+ }
+ }
+ _node_potential->set(n, max);
+ _delta1->push(n, max);
+
+ _tree_set->insert(n);
+
+ _matching->set(n, INVALID);
+ _status->set(n, EVEN);
+ }
+
+ for (EdgeIt e(_graph); e != INVALID; ++e) {
+ Node left = _graph.u(e);
+ Node right = _graph.v(e);
+ if (left == right && !_allow_loops) continue;
+ _delta3->push(e, ((*_node_potential)[left] +
+ (*_node_potential)[right] -
+ dualScale * _weight[e]) / 2);
+ }
+ }
+
+ /// \brief Start the algorithm
+ ///
+ /// This function starts the algorithm.
+ ///
+ /// \pre \ref init() must be called before using this function.
+ void start() {
+ enum OpType {
+ D1, D2, D3
+ };
+
+ int unmatched = _node_num;
+ while (unmatched > 0) {
+ Value d1 = !_delta1->empty() ?
+ _delta1->prio() : std::numeric_limits<Value>::max();
+
+ Value d2 = !_delta2->empty() ?
+ _delta2->prio() : std::numeric_limits<Value>::max();
+
+ Value d3 = !_delta3->empty() ?
+ _delta3->prio() : std::numeric_limits<Value>::max();
+
+ _delta_sum = d3; OpType ot = D3;
+ if (d1 < _delta_sum) { _delta_sum = d1; ot = D1; }
+ if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
+
+ switch (ot) {
+ case D1:
+ {
+ Node n = _delta1->top();
+ unmatchNode(n);
+ --unmatched;
+ }
+ break;
+ case D2:
+ {
+ Node n = _delta2->top();
+ Arc a = (*_pred)[n];
+ if ((*_matching)[n] == INVALID) {
+ augmentOnArc(a);
+ --unmatched;
+ } else {
+ Node v = _graph.target((*_matching)[n]);
+ if ((*_matching)[n] !=
+ _graph.oppositeArc((*_matching)[v])) {
+ extractCycle(a);
+ --unmatched;
+ } else {
+ extendOnArc(a);
+ }
+ }
+ } break;
+ case D3:
+ {
+ Edge e = _delta3->top();
+
+ Node left = _graph.u(e);
+ Node right = _graph.v(e);
+
+ int left_tree = _tree_set->find(left);
+ int right_tree = _tree_set->find(right);
+
+ if (left_tree == right_tree) {
+ cycleOnEdge(e, left_tree);
+ --unmatched;
+ } else {
+ augmentOnEdge(e);
+ unmatched -= 2;
+ }
+ } break;
+ }
+ }
+ }
+
+ /// \brief Run the algorithm.
+ ///
+ /// This method runs the \c %MaxWeightedFractionalMatching algorithm.
+ ///
+ /// \note mwfm.run() is just a shortcut of the following code.
+ /// \code
+ /// mwfm.init();
+ /// mwfm.start();
+ /// \endcode
+ void run() {
+ init();
+ start();
+ }
+
+ /// @}
+
+ /// \name Primal Solution
+ /// Functions to get the primal solution, i.e. the maximum weighted
+ /// matching.\n
+ /// Either \ref run() or \ref start() function should be called before
+ /// using them.
+
+ /// @{
+
+ /// \brief Return the weight of the matching.
+ ///
+ /// This function returns the weight of the found matching. This
+ /// value is scaled by \ref primalScale "primal scale".
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Value matchingWeight() const {
+ Value sum = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if ((*_matching)[n] != INVALID) {
+ sum += _weight[(*_matching)[n]];
+ }
+ }
+ return sum * primalScale / 2;
+ }
+
+ /// \brief Return the number of covered nodes in the matching.
+ ///
+ /// This function returns the number of covered nodes in the matching.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ int matchingSize() const {
+ int num = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if ((*_matching)[n] != INVALID) {
+ ++num;
+ }
+ }
+ return num;
+ }
+
+ /// \brief Return \c true if the given edge is in the matching.
+ ///
+ /// This function returns \c true if the given edge is in the
+ /// found matching. The result is scaled by \ref primalScale
+ /// "primal scale".
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ int matching(const Edge& edge) const {
+ return (edge == (*_matching)[_graph.u(edge)] ? 1 : 0)
+ + (edge == (*_matching)[_graph.v(edge)] ? 1 : 0);
+ }
+
+ /// \brief Return the fractional matching arc (or edge) incident
+ /// to the given node.
+ ///
+ /// This function returns one of the fractional matching arc (or
+ /// edge) incident to the given node in the found matching or \c
+ /// INVALID if the node is not covered by the matching or if the
+ /// node is on an odd length cycle then it is the successor edge
+ /// on the cycle.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Arc matching(const Node& node) const {
+ return (*_matching)[node];
+ }
+
+ /// \brief Return a const reference to the matching map.
+ ///
+ /// This function returns a const reference to a node map that stores
+ /// the matching arc (or edge) incident to each node.
+ const MatchingMap& matchingMap() const {
+ return *_matching;
+ }
+
+ /// @}
+
+ /// \name Dual Solution
+ /// Functions to get the dual solution.\n
+ /// Either \ref run() or \ref start() function should be called before
+ /// using them.
+
+ /// @{
+
+ /// \brief Return the value of the dual solution.
+ ///
+ /// This function returns the value of the dual solution.
+ /// It should be equal to the primal value scaled by \ref dualScale
+ /// "dual scale".
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Value dualValue() const {
+ Value sum = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ sum += nodeValue(n);
+ }
+ return sum;
+ }
+
+ /// \brief Return the dual value (potential) of the given node.
+ ///
+ /// This function returns the dual value (potential) of the given node.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Value nodeValue(const Node& n) const {
+ return (*_node_potential)[n];
+ }
+
+ /// @}
+
+ };
+
+ /// \ingroup matching
+ ///
+ /// \brief Weighted fractional perfect matching in general graphs
+ ///
+ /// This class provides an efficient implementation of fractional
+ /// matching algorithm. The implementation uses priority queues and
+ /// provides \f$O(nm\log n)\f$ time complexity.
+ ///
+ /// The maximum weighted fractional perfect matching is a relaxation
+ /// of the maximum weighted perfect matching problem where the odd
+ /// set constraints are omitted.
+ /// It can be formulated with the following linear program.
+ /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
+ /// \f[x_e \ge 0\quad \forall e\in E\f]
+ /// \f[\max \sum_{e\in E}x_ew_e\f]
+ /// where \f$\delta(X)\f$ is the set of edges incident to a node in
+ /// \f$X\f$. The result must be the union of a matching with one
+ /// value edges and a set of odd length cycles with half value edges.
+ ///
+ /// The algorithm calculates an optimal fractional matching and a
+ /// proof of the optimality. The solution of the dual problem can be
+ /// used to check the result of the algorithm. The dual linear
+ /// problem is the following.
+ /// \f[ y_u + y_v \ge w_{uv} \quad \forall uv\in E\f]
+ /// \f[\min \sum_{u \in V}y_u \f]
+ ///
+ /// The algorithm can be executed with the run() function.
+ /// After it the matching (the primal solution) and the dual solution
+ /// can be obtained using the query functions.
+ ///
+ /// The primal solution is multiplied by
+ /// \ref MaxWeightedPerfectFractionalMatching::primalScale "2".
+ /// If the value type is integer, then the dual
+ /// solution is scaled by
+ /// \ref MaxWeightedPerfectFractionalMatching::dualScale "4".
+ ///
+ /// \tparam GR The undirected graph type the algorithm runs on.
+ /// \tparam WM The type edge weight map. The default type is
+ /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
+#ifdef DOXYGEN
+ template <typename GR, typename WM>
+#else
+ template <typename GR,
+ typename WM = typename GR::template EdgeMap<int> >
+#endif
+ class MaxWeightedPerfectFractionalMatching {
+ public:
+
+ /// The graph type of the algorithm
+ typedef GR Graph;
+ /// The type of the edge weight map
+ typedef WM WeightMap;
+ /// The value type of the edge weights
+ typedef typename WeightMap::Value Value;
+
+ /// The type of the matching map
+ typedef typename Graph::template NodeMap<typename Graph::Arc>
+ MatchingMap;
+
+ /// \brief Scaling factor for primal solution
+ ///
+ /// Scaling factor for primal solution.
+ static const int primalScale = 2;
+
+ /// \brief Scaling factor for dual solution
+ ///
+ /// Scaling factor for dual solution. It is equal to 4 or 1
+ /// according to the value type.
+ static const int dualScale =
+ std::numeric_limits<Value>::is_integer ? 4 : 1;
+
+ private:
+
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+ typedef typename Graph::template NodeMap<Value> NodePotential;
+
+ const Graph& _graph;
+ const WeightMap& _weight;
+
+ MatchingMap* _matching;
+ NodePotential* _node_potential;
+
+ int _node_num;
+ bool _allow_loops;
+
+ enum Status {
+ EVEN = -1, MATCHED = 0, ODD = 1
+ };
+
+ typedef typename Graph::template NodeMap<Status> StatusMap;
+ StatusMap* _status;
+
+ typedef typename Graph::template NodeMap<Arc> PredMap;
+ PredMap* _pred;
+
+ typedef ExtendFindEnum<IntNodeMap> TreeSet;
+
+ IntNodeMap *_tree_set_index;
+ TreeSet *_tree_set;
+
+ IntNodeMap *_delta2_index;
+ BinHeap<Value, IntNodeMap> *_delta2;
+
+ IntEdgeMap *_delta3_index;
+ BinHeap<Value, IntEdgeMap> *_delta3;
+
+ Value _delta_sum;
+
+ void createStructures() {
+ _node_num = countNodes(_graph);
+
+ if (!_matching) {
+ _matching = new MatchingMap(_graph);
+ }
+ if (!_node_potential) {
+ _node_potential = new NodePotential(_graph);
+ }
+ if (!_status) {
+ _status = new StatusMap(_graph);
+ }
+ if (!_pred) {
+ _pred = new PredMap(_graph);
+ }
+ if (!_tree_set) {
+ _tree_set_index = new IntNodeMap(_graph);
+ _tree_set = new TreeSet(*_tree_set_index);
+ }
+ if (!_delta2) {
+ _delta2_index = new IntNodeMap(_graph);
+ _delta2 = new BinHeap<Value, IntNodeMap>(*_delta2_index);
+ }
+ if (!_delta3) {
+ _delta3_index = new IntEdgeMap(_graph);
+ _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
+ }
+ }
+
+ void destroyStructures() {
+ if (_matching) {
+ delete _matching;
+ }
+ if (_node_potential) {
+ delete _node_potential;
+ }
+ if (_status) {
+ delete _status;
+ }
+ if (_pred) {
+ delete _pred;
+ }
+ if (_tree_set) {
+ delete _tree_set_index;
+ delete _tree_set;
+ }
+ if (_delta2) {
+ delete _delta2_index;
+ delete _delta2;
+ }
+ if (_delta3) {
+ delete _delta3_index;
+ delete _delta3;
+ }
+ }
+
+ void matchedToEven(Node node, int tree) {
+ _tree_set->insert(node, tree);
+ _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
+
+ if (_delta2->state(node) == _delta2->IN_HEAP) {
+ _delta2->erase(node);
+ }
+
+ for (InArcIt a(_graph, node); a != INVALID; ++a) {
+ Node v = _graph.source(a);
+ Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
+ dualScale * _weight[a];
+ if (node == v) {
+ if (_allow_loops && _graph.direction(a)) {
+ _delta3->push(a, rw / 2);
+ }
+ } else if ((*_status)[v] == EVEN) {
+ _delta3->push(a, rw / 2);
+ } else if ((*_status)[v] == MATCHED) {
+ if (_delta2->state(v) != _delta2->IN_HEAP) {
+ _pred->set(v, a);
+ _delta2->push(v, rw);
+ } else if ((*_delta2)[v] > rw) {
+ _pred->set(v, a);
+ _delta2->decrease(v, rw);
+ }
+ }
+ }
+ }
+
+ void matchedToOdd(Node node, int tree) {
+ _tree_set->insert(node, tree);
+ _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
+
+ if (_delta2->state(node) == _delta2->IN_HEAP) {
+ _delta2->erase(node);
+ }
+ }
+
+ void evenToMatched(Node node, int tree) {
+ _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
+ Arc min = INVALID;
+ Value minrw = std::numeric_limits<Value>::max();
+ for (InArcIt a(_graph, node); a != INVALID; ++a) {
+ Node v = _graph.source(a);
+ Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
+ dualScale * _weight[a];
+
+ if (node == v) {
+ if (_allow_loops && _graph.direction(a)) {
+ _delta3->erase(a);
+ }
+ } else if ((*_status)[v] == EVEN) {
+ _delta3->erase(a);
+ if (minrw > rw) {
+ min = _graph.oppositeArc(a);
+ minrw = rw;
+ }
+ } else if ((*_status)[v] == MATCHED) {
+ if ((*_pred)[v] == a) {
+ Arc mina = INVALID;
+ Value minrwa = std::numeric_limits<Value>::max();
+ for (OutArcIt aa(_graph, v); aa != INVALID; ++aa) {
+ Node va = _graph.target(aa);
+ if ((*_status)[va] != EVEN ||
+ _tree_set->find(va) == tree) continue;
+ Value rwa = (*_node_potential)[v] + (*_node_potential)[va] -
+ dualScale * _weight[aa];
+ if (minrwa > rwa) {
+ minrwa = rwa;
+ mina = aa;
+ }
+ }
+ if (mina != INVALID) {
+ _pred->set(v, mina);
+ _delta2->increase(v, minrwa);
+ } else {
+ _pred->set(v, INVALID);
+ _delta2->erase(v);
+ }
+ }
+ }
+ }
+ if (min != INVALID) {
+ _pred->set(node, min);
+ _delta2->push(node, minrw);
+ } else {
+ _pred->set(node, INVALID);
+ }
+ }
+
+ void oddToMatched(Node node) {
+ _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
+ Arc min = INVALID;
+ Value minrw = std::numeric_limits<Value>::max();
+ for (InArcIt a(_graph, node); a != INVALID; ++a) {
+ Node v = _graph.source(a);
+ if ((*_status)[v] != EVEN) continue;
+ Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
+ dualScale * _weight[a];
+
+ if (minrw > rw) {
+ min = _graph.oppositeArc(a);
+ minrw = rw;
+ }
+ }
+ if (min != INVALID) {
+ _pred->set(node, min);
+ _delta2->push(node, minrw);
+ } else {
+ _pred->set(node, INVALID);
+ }
+ }
+
+ void alternatePath(Node even, int tree) {
+ Node odd;
+
+ _status->set(even, MATCHED);
+ evenToMatched(even, tree);
+
+ Arc prev = (*_matching)[even];
+ while (prev != INVALID) {
+ odd = _graph.target(prev);
+ even = _graph.target((*_pred)[odd]);
+ _matching->set(odd, (*_pred)[odd]);
+ _status->set(odd, MATCHED);
+ oddToMatched(odd);
+
+ prev = (*_matching)[even];
+ _status->set(even, MATCHED);
+ _matching->set(even, _graph.oppositeArc((*_matching)[odd]));
+ evenToMatched(even, tree);
+ }
+ }
+
+ void destroyTree(int tree) {
+ for (typename TreeSet::ItemIt n(*_tree_set, tree); n != INVALID; ++n) {
+ if ((*_status)[n] == EVEN) {
+ _status->set(n, MATCHED);
+ evenToMatched(n, tree);
+ } else if ((*_status)[n] == ODD) {
+ _status->set(n, MATCHED);
+ oddToMatched(n);
+ }
+ }
+ _tree_set->eraseClass(tree);
+ }
+
+ void augmentOnEdge(const Edge& edge) {
+ Node left = _graph.u(edge);
+ int left_tree = _tree_set->find(left);
+
+ alternatePath(left, left_tree);
+ destroyTree(left_tree);
+ _matching->set(left, _graph.direct(edge, true));
+
+ Node right = _graph.v(edge);
+ int right_tree = _tree_set->find(right);
+
+ alternatePath(right, right_tree);
+ destroyTree(right_tree);
+ _matching->set(right, _graph.direct(edge, false));
+ }
+
+ void augmentOnArc(const Arc& arc) {
+ Node left = _graph.source(arc);
+ _status->set(left, MATCHED);
+ _matching->set(left, arc);
+ _pred->set(left, arc);
+
+ Node right = _graph.target(arc);
+ int right_tree = _tree_set->find(right);
+
+ alternatePath(right, right_tree);
+ destroyTree(right_tree);
+ _matching->set(right, _graph.oppositeArc(arc));
+ }
+
+ void extendOnArc(const Arc& arc) {
+ Node base = _graph.target(arc);
+ int tree = _tree_set->find(base);
+
+ Node odd = _graph.source(arc);
+ _tree_set->insert(odd, tree);
+ _status->set(odd, ODD);
+ matchedToOdd(odd, tree);
+ _pred->set(odd, arc);
+
+ Node even = _graph.target((*_matching)[odd]);
+ _tree_set->insert(even, tree);
+ _status->set(even, EVEN);
+ matchedToEven(even, tree);
+ }
+
+ void cycleOnEdge(const Edge& edge, int tree) {
+ Node nca = INVALID;
+ std::vector<Node> left_path, right_path;
+
+ {
+ std::set<Node> left_set, right_set;
+ Node left = _graph.u(edge);
+ left_path.push_back(left);
+ left_set.insert(left);
+
+ Node right = _graph.v(edge);
+ right_path.push_back(right);
+ right_set.insert(right);
+
+ while (true) {
+
+ if (left_set.find(right) != left_set.end()) {
+ nca = right;
+ break;
+ }
+
+ if ((*_matching)[left] == INVALID) break;
+
+ left = _graph.target((*_matching)[left]);
+ left_path.push_back(left);
+ left = _graph.target((*_pred)[left]);
+ left_path.push_back(left);
+
+ left_set.insert(left);
+
+ if (right_set.find(left) != right_set.end()) {
+ nca = left;
+ break;
+ }
+
+ if ((*_matching)[right] == INVALID) break;
+
+ right = _graph.target((*_matching)[right]);
+ right_path.push_back(right);
+ right = _graph.target((*_pred)[right]);
+ right_path.push_back(right);
+
+ right_set.insert(right);
+
+ }
+
+ if (nca == INVALID) {
+ if ((*_matching)[left] == INVALID) {
+ nca = right;
+ while (left_set.find(nca) == left_set.end()) {
+ nca = _graph.target((*_matching)[nca]);
+ right_path.push_back(nca);
+ nca = _graph.target((*_pred)[nca]);
+ right_path.push_back(nca);
+ }
+ } else {
+ nca = left;
+ while (right_set.find(nca) == right_set.end()) {
+ nca = _graph.target((*_matching)[nca]);
+ left_path.push_back(nca);
+ nca = _graph.target((*_pred)[nca]);
+ left_path.push_back(nca);
+ }
+ }
+ }
+ }
+
+ alternatePath(nca, tree);
+ Arc prev;
+
+ prev = _graph.direct(edge, true);
+ for (int i = 0; left_path[i] != nca; i += 2) {
+ _matching->set(left_path[i], prev);
+ _status->set(left_path[i], MATCHED);
+ evenToMatched(left_path[i], tree);
+
+ prev = _graph.oppositeArc((*_pred)[left_path[i + 1]]);
+ _status->set(left_path[i + 1], MATCHED);
+ oddToMatched(left_path[i + 1]);
+ }
+ _matching->set(nca, prev);
+
+ for (int i = 0; right_path[i] != nca; i += 2) {
+ _status->set(right_path[i], MATCHED);
+ evenToMatched(right_path[i], tree);
+
+ _matching->set(right_path[i + 1], (*_pred)[right_path[i + 1]]);
+ _status->set(right_path[i + 1], MATCHED);
+ oddToMatched(right_path[i + 1]);
+ }
+
+ destroyTree(tree);
+ }
+
+ void extractCycle(const Arc &arc) {
+ Node left = _graph.source(arc);
+ Node odd = _graph.target((*_matching)[left]);
+ Arc prev;
+ while (odd != left) {
+ Node even = _graph.target((*_matching)[odd]);
+ prev = (*_matching)[odd];
+ odd = _graph.target((*_matching)[even]);
+ _matching->set(even, _graph.oppositeArc(prev));
+ }
+ _matching->set(left, arc);
+
+ Node right = _graph.target(arc);
+ int right_tree = _tree_set->find(right);
+ alternatePath(right, right_tree);
+ destroyTree(right_tree);
+ _matching->set(right, _graph.oppositeArc(arc));
+ }
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ MaxWeightedPerfectFractionalMatching(const Graph& graph,
+ const WeightMap& weight,
+ bool allow_loops = true)
+ : _graph(graph), _weight(weight), _matching(0),
+ _node_potential(0), _node_num(0), _allow_loops(allow_loops),
+ _status(0), _pred(0),
+ _tree_set_index(0), _tree_set(0),
+
+ _delta2_index(0), _delta2(0),
+ _delta3_index(0), _delta3(0),
+
+ _delta_sum() {}
+
+ ~MaxWeightedPerfectFractionalMatching() {
+ destroyStructures();
+ }
+
+ /// \name Execution Control
+ /// The simplest way to execute the algorithm is to use the
+ /// \ref run() member function.
+
+ ///@{
+
+ /// \brief Initialize the algorithm
+ ///
+ /// This function initializes the algorithm.
+ void init() {
+ createStructures();
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ (*_delta2_index)[n] = _delta2->PRE_HEAP;
+ }
+ for (EdgeIt e(_graph); e != INVALID; ++e) {
+ (*_delta3_index)[e] = _delta3->PRE_HEAP;
+ }
+
+ _delta2->clear();
+ _delta3->clear();
+ _tree_set->clear();
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ Value max = - std::numeric_limits<Value>::max();
+ for (OutArcIt e(_graph, n); e != INVALID; ++e) {
+ if (_graph.target(e) == n && !_allow_loops) continue;
+ if ((dualScale * _weight[e]) / 2 > max) {
+ max = (dualScale * _weight[e]) / 2;
+ }
+ }
+ _node_potential->set(n, max);
+
+ _tree_set->insert(n);
+
+ _matching->set(n, INVALID);
+ _status->set(n, EVEN);
+ }
+
+ for (EdgeIt e(_graph); e != INVALID; ++e) {
+ Node left = _graph.u(e);
+ Node right = _graph.v(e);
+ if (left == right && !_allow_loops) continue;
+ _delta3->push(e, ((*_node_potential)[left] +
+ (*_node_potential)[right] -
+ dualScale * _weight[e]) / 2);
+ }
+ }
+
+ /// \brief Start the algorithm
+ ///
+ /// This function starts the algorithm.
+ ///
+ /// \pre \ref init() must be called before using this function.
+ bool start() {
+ enum OpType {
+ D2, D3
+ };
+
+ int unmatched = _node_num;
+ while (unmatched > 0) {
+ Value d2 = !_delta2->empty() ?
+ _delta2->prio() : std::numeric_limits<Value>::max();
+
+ Value d3 = !_delta3->empty() ?
+ _delta3->prio() : std::numeric_limits<Value>::max();
+
+ _delta_sum = d3; OpType ot = D3;
+ if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
+
+ if (_delta_sum == std::numeric_limits<Value>::max()) {
+ return false;
+ }
+
+ switch (ot) {
+ case D2:
+ {
+ Node n = _delta2->top();
+ Arc a = (*_pred)[n];
+ if ((*_matching)[n] == INVALID) {
+ augmentOnArc(a);
+ --unmatched;
+ } else {
+ Node v = _graph.target((*_matching)[n]);
+ if ((*_matching)[n] !=
+ _graph.oppositeArc((*_matching)[v])) {
+ extractCycle(a);
+ --unmatched;
+ } else {
+ extendOnArc(a);
+ }
+ }
+ } break;
+ case D3:
+ {
+ Edge e = _delta3->top();
+
+ Node left = _graph.u(e);
+ Node right = _graph.v(e);
+
+ int left_tree = _tree_set->find(left);
+ int right_tree = _tree_set->find(right);
+
+ if (left_tree == right_tree) {
+ cycleOnEdge(e, left_tree);
+ --unmatched;
+ } else {
+ augmentOnEdge(e);
+ unmatched -= 2;
+ }
+ } break;
+ }
+ }
+ return true;
+ }
+
+ /// \brief Run the algorithm.
+ ///
+ /// This method runs the \c %MaxWeightedPerfectFractionalMatching
+ /// algorithm.
+ ///
+ /// \note mwfm.run() is just a shortcut of the following code.
+ /// \code
+ /// mwpfm.init();
+ /// mwpfm.start();
+ /// \endcode
+ bool run() {
+ init();
+ return start();
+ }
+
+ /// @}
+
+ /// \name Primal Solution
+ /// Functions to get the primal solution, i.e. the maximum weighted
+ /// matching.\n
+ /// Either \ref run() or \ref start() function should be called before
+ /// using them.
+
+ /// @{
+
+ /// \brief Return the weight of the matching.
+ ///
+ /// This function returns the weight of the found matching. This
+ /// value is scaled by \ref primalScale "primal scale".
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Value matchingWeight() const {
+ Value sum = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if ((*_matching)[n] != INVALID) {
+ sum += _weight[(*_matching)[n]];
+ }
+ }
+ return sum * primalScale / 2;
+ }
+
+ /// \brief Return the number of covered nodes in the matching.
+ ///
+ /// This function returns the number of covered nodes in the matching.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ int matchingSize() const {
+ int num = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if ((*_matching)[n] != INVALID) {
+ ++num;
+ }
+ }
+ return num;
+ }
+
+ /// \brief Return \c true if the given edge is in the matching.
+ ///
+ /// This function returns \c true if the given edge is in the
+ /// found matching. The result is scaled by \ref primalScale
+ /// "primal scale".
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ int matching(const Edge& edge) const {
+ return (edge == (*_matching)[_graph.u(edge)] ? 1 : 0)
+ + (edge == (*_matching)[_graph.v(edge)] ? 1 : 0);
+ }
+
+ /// \brief Return the fractional matching arc (or edge) incident
+ /// to the given node.
+ ///
+ /// This function returns one of the fractional matching arc (or
+ /// edge) incident to the given node in the found matching or \c
+ /// INVALID if the node is not covered by the matching or if the
+ /// node is on an odd length cycle then it is the successor edge
+ /// on the cycle.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Arc matching(const Node& node) const {
+ return (*_matching)[node];
+ }
+
+ /// \brief Return a const reference to the matching map.
+ ///
+ /// This function returns a const reference to a node map that stores
+ /// the matching arc (or edge) incident to each node.
+ const MatchingMap& matchingMap() const {
+ return *_matching;
+ }
+
+ /// @}
+
+ /// \name Dual Solution
+ /// Functions to get the dual solution.\n
+ /// Either \ref run() or \ref start() function should be called before
+ /// using them.
+
+ /// @{
+
+ /// \brief Return the value of the dual solution.
+ ///
+ /// This function returns the value of the dual solution.
+ /// It should be equal to the primal value scaled by \ref dualScale
+ /// "dual scale".
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Value dualValue() const {
+ Value sum = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ sum += nodeValue(n);
+ }
+ return sum;
+ }
+
+ /// \brief Return the dual value (potential) of the given node.
+ ///
+ /// This function returns the dual value (potential) of the given node.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Value nodeValue(const Node& n) const {
+ return (*_node_potential)[n];
+ }
+
+ /// @}
+
+ };
+
+} //END OF NAMESPACE LEMON
+
+#endif //LEMON_FRACTIONAL_MATCHING_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/full_graph.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/full_graph.h
new file mode 100644
index 00000000000..b63df2e0746
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/full_graph.h
@@ -0,0 +1,1082 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_FULL_GRAPH_H
+#define LEMON_FULL_GRAPH_H
+
+#include <lemon/core.h>
+#include <lemon/bits/graph_extender.h>
+
+///\ingroup graphs
+///\file
+///\brief FullDigraph and FullGraph classes.
+
+namespace lemon {
+
+ class FullDigraphBase {
+ public:
+
+ typedef FullDigraphBase Digraph;
+
+ class Node;
+ class Arc;
+
+ protected:
+
+ int _node_num;
+ int _arc_num;
+
+ FullDigraphBase() {}
+
+ void construct(int n) { _node_num = n; _arc_num = n * n; }
+
+ public:
+
+ typedef True NodeNumTag;
+ typedef True ArcNumTag;
+
+ Node operator()(int ix) const { return Node(ix); }
+ static int index(const Node& node) { return node._id; }
+
+ Arc arc(const Node& s, const Node& t) const {
+ return Arc(s._id * _node_num + t._id);
+ }
+
+ int nodeNum() const { return _node_num; }
+ int arcNum() const { return _arc_num; }
+
+ int maxNodeId() const { return _node_num - 1; }
+ int maxArcId() const { return _arc_num - 1; }
+
+ Node source(Arc arc) const { return arc._id / _node_num; }
+ Node target(Arc arc) const { return arc._id % _node_num; }
+
+ static int id(Node node) { return node._id; }
+ static int id(Arc arc) { return arc._id; }
+
+ static Node nodeFromId(int id) { return Node(id);}
+ static Arc arcFromId(int id) { return Arc(id);}
+
+ typedef True FindArcTag;
+
+ Arc findArc(Node s, Node t, Arc prev = INVALID) const {
+ return prev == INVALID ? arc(s, t) : INVALID;
+ }
+
+ class Node {
+ friend class FullDigraphBase;
+
+ protected:
+ int _id;
+ Node(int id) : _id(id) {}
+ public:
+ Node() {}
+ Node (Invalid) : _id(-1) {}
+ bool operator==(const Node node) const {return _id == node._id;}
+ bool operator!=(const Node node) const {return _id != node._id;}
+ bool operator<(const Node node) const {return _id < node._id;}
+ };
+
+ class Arc {
+ friend class FullDigraphBase;
+
+ protected:
+ int _id; // _node_num * source + target;
+
+ Arc(int id) : _id(id) {}
+
+ public:
+ Arc() { }
+ Arc (Invalid) { _id = -1; }
+ bool operator==(const Arc arc) const {return _id == arc._id;}
+ bool operator!=(const Arc arc) const {return _id != arc._id;}
+ bool operator<(const Arc arc) const {return _id < arc._id;}
+ };
+
+ void first(Node& node) const {
+ node._id = _node_num - 1;
+ }
+
+ static void next(Node& node) {
+ --node._id;
+ }
+
+ void first(Arc& arc) const {
+ arc._id = _arc_num - 1;
+ }
+
+ static void next(Arc& arc) {
+ --arc._id;
+ }
+
+ void firstOut(Arc& arc, const Node& node) const {
+ arc._id = (node._id + 1) * _node_num - 1;
+ }
+
+ void nextOut(Arc& arc) const {
+ if (arc._id % _node_num == 0) arc._id = 0;
+ --arc._id;
+ }
+
+ void firstIn(Arc& arc, const Node& node) const {
+ arc._id = _arc_num + node._id - _node_num;
+ }
+
+ void nextIn(Arc& arc) const {
+ arc._id -= _node_num;
+ if (arc._id < 0) arc._id = -1;
+ }
+
+ };
+
+ typedef DigraphExtender<FullDigraphBase> ExtendedFullDigraphBase;
+
+ /// \ingroup graphs
+ ///
+ /// \brief A directed full graph class.
+ ///
+ /// FullDigraph is a simple and fast implmenetation of directed full
+ /// (complete) graphs. It contains an arc from each node to each node
+ /// (including a loop for each node), therefore the number of arcs
+ /// is the square of the number of nodes.
+ /// This class is completely static and it needs constant memory space.
+ /// Thus you can neither add nor delete nodes or arcs, however
+ /// the structure can be resized using resize().
+ ///
+ /// This type fully conforms to the \ref concepts::Digraph "Digraph concept".
+ /// Most of its member functions and nested classes are documented
+ /// only in the concept class.
+ ///
+ /// This class provides constant time counting for nodes and arcs.
+ ///
+ /// \note FullDigraph and FullGraph classes are very similar,
+ /// but there are two differences. While this class conforms only
+ /// to the \ref concepts::Digraph "Digraph" concept, FullGraph
+ /// conforms to the \ref concepts::Graph "Graph" concept,
+ /// moreover FullGraph does not contain a loop for each
+ /// node as this class does.
+ ///
+ /// \sa FullGraph
+ class FullDigraph : public ExtendedFullDigraphBase {
+ typedef ExtendedFullDigraphBase Parent;
+
+ public:
+
+ /// \brief Default constructor.
+ ///
+ /// Default constructor. The number of nodes and arcs will be zero.
+ FullDigraph() { construct(0); }
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ /// \param n The number of the nodes.
+ FullDigraph(int n) { construct(n); }
+
+ /// \brief Resizes the digraph
+ ///
+ /// This function resizes the digraph. It fully destroys and
+ /// rebuilds the structure, therefore the maps of the digraph will be
+ /// reallocated automatically and the previous values will be lost.
+ void resize(int n) {
+ Parent::notifier(Arc()).clear();
+ Parent::notifier(Node()).clear();
+ construct(n);
+ Parent::notifier(Node()).build();
+ Parent::notifier(Arc()).build();
+ }
+
+ /// \brief Returns the node with the given index.
+ ///
+ /// Returns the node with the given index. Since this structure is
+ /// completely static, the nodes can be indexed with integers from
+ /// the range <tt>[0..nodeNum()-1]</tt>.
+ /// The index of a node is the same as its ID.
+ /// \sa index()
+ Node operator()(int ix) const { return Parent::operator()(ix); }
+
+ /// \brief Returns the index of the given node.
+ ///
+ /// Returns the index of the given node. Since this structure is
+ /// completely static, the nodes can be indexed with integers from
+ /// the range <tt>[0..nodeNum()-1]</tt>.
+ /// The index of a node is the same as its ID.
+ /// \sa operator()()
+ static int index(const Node& node) { return Parent::index(node); }
+
+ /// \brief Returns the arc connecting the given nodes.
+ ///
+ /// Returns the arc connecting the given nodes.
+ Arc arc(Node u, Node v) const {
+ return Parent::arc(u, v);
+ }
+
+ /// \brief Number of nodes.
+ int nodeNum() const { return Parent::nodeNum(); }
+ /// \brief Number of arcs.
+ int arcNum() const { return Parent::arcNum(); }
+ };
+
+
+ class FullGraphBase {
+ public:
+
+ typedef FullGraphBase Graph;
+
+ class Node;
+ class Arc;
+ class Edge;
+
+ protected:
+
+ int _node_num;
+ int _edge_num;
+
+ FullGraphBase() {}
+
+ void construct(int n) { _node_num = n; _edge_num = n * (n - 1) / 2; }
+
+ int _uid(int e) const {
+ int u = e / _node_num;
+ int v = e % _node_num;
+ return u < v ? u : _node_num - 2 - u;
+ }
+
+ int _vid(int e) const {
+ int u = e / _node_num;
+ int v = e % _node_num;
+ return u < v ? v : _node_num - 1 - v;
+ }
+
+ void _uvid(int e, int& u, int& v) const {
+ u = e / _node_num;
+ v = e % _node_num;
+ if (u >= v) {
+ u = _node_num - 2 - u;
+ v = _node_num - 1 - v;
+ }
+ }
+
+ void _stid(int a, int& s, int& t) const {
+ if ((a & 1) == 1) {
+ _uvid(a >> 1, s, t);
+ } else {
+ _uvid(a >> 1, t, s);
+ }
+ }
+
+ int _eid(int u, int v) const {
+ if (u < (_node_num - 1) / 2) {
+ return u * _node_num + v;
+ } else {
+ return (_node_num - 1 - u) * _node_num - v - 1;
+ }
+ }
+
+ public:
+
+ Node operator()(int ix) const { return Node(ix); }
+ static int index(const Node& node) { return node._id; }
+
+ Edge edge(const Node& u, const Node& v) const {
+ if (u._id < v._id) {
+ return Edge(_eid(u._id, v._id));
+ } else if (u._id != v._id) {
+ return Edge(_eid(v._id, u._id));
+ } else {
+ return INVALID;
+ }
+ }
+
+ Arc arc(const Node& s, const Node& t) const {
+ if (s._id < t._id) {
+ return Arc((_eid(s._id, t._id) << 1) | 1);
+ } else if (s._id != t._id) {
+ return Arc(_eid(t._id, s._id) << 1);
+ } else {
+ return INVALID;
+ }
+ }
+
+ typedef True NodeNumTag;
+ typedef True ArcNumTag;
+ typedef True EdgeNumTag;
+
+ int nodeNum() const { return _node_num; }
+ int arcNum() const { return 2 * _edge_num; }
+ int edgeNum() const { return _edge_num; }
+
+ static int id(Node node) { return node._id; }
+ static int id(Arc arc) { return arc._id; }
+ static int id(Edge edge) { return edge._id; }
+
+ int maxNodeId() const { return _node_num-1; }
+ int maxArcId() const { return 2 * _edge_num-1; }
+ int maxEdgeId() const { return _edge_num-1; }
+
+ static Node nodeFromId(int id) { return Node(id);}
+ static Arc arcFromId(int id) { return Arc(id);}
+ static Edge edgeFromId(int id) { return Edge(id);}
+
+ Node u(Edge edge) const {
+ return Node(_uid(edge._id));
+ }
+
+ Node v(Edge edge) const {
+ return Node(_vid(edge._id));
+ }
+
+ Node source(Arc arc) const {
+ return Node((arc._id & 1) == 1 ?
+ _uid(arc._id >> 1) : _vid(arc._id >> 1));
+ }
+
+ Node target(Arc arc) const {
+ return Node((arc._id & 1) == 1 ?
+ _vid(arc._id >> 1) : _uid(arc._id >> 1));
+ }
+
+ typedef True FindEdgeTag;
+ typedef True FindArcTag;
+
+ Edge findEdge(Node u, Node v, Edge prev = INVALID) const {
+ return prev != INVALID ? INVALID : edge(u, v);
+ }
+
+ Arc findArc(Node s, Node t, Arc prev = INVALID) const {
+ return prev != INVALID ? INVALID : arc(s, t);
+ }
+
+ class Node {
+ friend class FullGraphBase;
+
+ protected:
+ int _id;
+ Node(int id) : _id(id) {}
+ public:
+ Node() {}
+ Node (Invalid) { _id = -1; }
+ bool operator==(const Node node) const {return _id == node._id;}
+ bool operator!=(const Node node) const {return _id != node._id;}
+ bool operator<(const Node node) const {return _id < node._id;}
+ };
+
+ class Edge {
+ friend class FullGraphBase;
+ friend class Arc;
+
+ protected:
+ int _id;
+
+ Edge(int id) : _id(id) {}
+
+ public:
+ Edge() { }
+ Edge (Invalid) { _id = -1; }
+
+ bool operator==(const Edge edge) const {return _id == edge._id;}
+ bool operator!=(const Edge edge) const {return _id != edge._id;}
+ bool operator<(const Edge edge) const {return _id < edge._id;}
+ };
+
+ class Arc {
+ friend class FullGraphBase;
+
+ protected:
+ int _id;
+
+ Arc(int id) : _id(id) {}
+
+ public:
+ Arc() { }
+ Arc (Invalid) { _id = -1; }
+
+ operator Edge() const { return Edge(_id != -1 ? (_id >> 1) : -1); }
+
+ bool operator==(const Arc arc) const {return _id == arc._id;}
+ bool operator!=(const Arc arc) const {return _id != arc._id;}
+ bool operator<(const Arc arc) const {return _id < arc._id;}
+ };
+
+ static bool direction(Arc arc) {
+ return (arc._id & 1) == 1;
+ }
+
+ static Arc direct(Edge edge, bool dir) {
+ return Arc((edge._id << 1) | (dir ? 1 : 0));
+ }
+
+ void first(Node& node) const {
+ node._id = _node_num - 1;
+ }
+
+ static void next(Node& node) {
+ --node._id;
+ }
+
+ void first(Arc& arc) const {
+ arc._id = (_edge_num << 1) - 1;
+ }
+
+ static void next(Arc& arc) {
+ --arc._id;
+ }
+
+ void first(Edge& edge) const {
+ edge._id = _edge_num - 1;
+ }
+
+ static void next(Edge& edge) {
+ --edge._id;
+ }
+
+ void firstOut(Arc& arc, const Node& node) const {
+ int s = node._id, t = _node_num - 1;
+ if (s < t) {
+ arc._id = (_eid(s, t) << 1) | 1;
+ } else {
+ --t;
+ arc._id = (t != -1 ? (_eid(t, s) << 1) : -1);
+ }
+ }
+
+ void nextOut(Arc& arc) const {
+ int s, t;
+ _stid(arc._id, s, t);
+ --t;
+ if (s < t) {
+ arc._id = (_eid(s, t) << 1) | 1;
+ } else {
+ if (s == t) --t;
+ arc._id = (t != -1 ? (_eid(t, s) << 1) : -1);
+ }
+ }
+
+ void firstIn(Arc& arc, const Node& node) const {
+ int s = _node_num - 1, t = node._id;
+ if (s > t) {
+ arc._id = (_eid(t, s) << 1);
+ } else {
+ --s;
+ arc._id = (s != -1 ? (_eid(s, t) << 1) | 1 : -1);
+ }
+ }
+
+ void nextIn(Arc& arc) const {
+ int s, t;
+ _stid(arc._id, s, t);
+ --s;
+ if (s > t) {
+ arc._id = (_eid(t, s) << 1);
+ } else {
+ if (s == t) --s;
+ arc._id = (s != -1 ? (_eid(s, t) << 1) | 1 : -1);
+ }
+ }
+
+ void firstInc(Edge& edge, bool& dir, const Node& node) const {
+ int u = node._id, v = _node_num - 1;
+ if (u < v) {
+ edge._id = _eid(u, v);
+ dir = true;
+ } else {
+ --v;
+ edge._id = (v != -1 ? _eid(v, u) : -1);
+ dir = false;
+ }
+ }
+
+ void nextInc(Edge& edge, bool& dir) const {
+ int u, v;
+ if (dir) {
+ _uvid(edge._id, u, v);
+ --v;
+ if (u < v) {
+ edge._id = _eid(u, v);
+ } else {
+ --v;
+ edge._id = (v != -1 ? _eid(v, u) : -1);
+ dir = false;
+ }
+ } else {
+ _uvid(edge._id, v, u);
+ --v;
+ edge._id = (v != -1 ? _eid(v, u) : -1);
+ }
+ }
+
+ };
+
+ typedef GraphExtender<FullGraphBase> ExtendedFullGraphBase;
+
+ /// \ingroup graphs
+ ///
+ /// \brief An undirected full graph class.
+ ///
+ /// FullGraph is a simple and fast implmenetation of undirected full
+ /// (complete) graphs. It contains an edge between every distinct pair
+ /// of nodes, therefore the number of edges is <tt>n(n-1)/2</tt>.
+ /// This class is completely static and it needs constant memory space.
+ /// Thus you can neither add nor delete nodes or edges, however
+ /// the structure can be resized using resize().
+ ///
+ /// This type fully conforms to the \ref concepts::Graph "Graph concept".
+ /// Most of its member functions and nested classes are documented
+ /// only in the concept class.
+ ///
+ /// This class provides constant time counting for nodes, edges and arcs.
+ ///
+ /// \note FullDigraph and FullGraph classes are very similar,
+ /// but there are two differences. While FullDigraph
+ /// conforms only to the \ref concepts::Digraph "Digraph" concept,
+ /// this class conforms to the \ref concepts::Graph "Graph" concept,
+ /// moreover this class does not contain a loop for each
+ /// node as FullDigraph does.
+ ///
+ /// \sa FullDigraph
+ class FullGraph : public ExtendedFullGraphBase {
+ typedef ExtendedFullGraphBase Parent;
+
+ public:
+
+ /// \brief Default constructor.
+ ///
+ /// Default constructor. The number of nodes and edges will be zero.
+ FullGraph() { construct(0); }
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ /// \param n The number of the nodes.
+ FullGraph(int n) { construct(n); }
+
+ /// \brief Resizes the graph
+ ///
+ /// This function resizes the graph. It fully destroys and
+ /// rebuilds the structure, therefore the maps of the graph will be
+ /// reallocated automatically and the previous values will be lost.
+ void resize(int n) {
+ Parent::notifier(Arc()).clear();
+ Parent::notifier(Edge()).clear();
+ Parent::notifier(Node()).clear();
+ construct(n);
+ Parent::notifier(Node()).build();
+ Parent::notifier(Edge()).build();
+ Parent::notifier(Arc()).build();
+ }
+
+ /// \brief Returns the node with the given index.
+ ///
+ /// Returns the node with the given index. Since this structure is
+ /// completely static, the nodes can be indexed with integers from
+ /// the range <tt>[0..nodeNum()-1]</tt>.
+ /// The index of a node is the same as its ID.
+ /// \sa index()
+ Node operator()(int ix) const { return Parent::operator()(ix); }
+
+ /// \brief Returns the index of the given node.
+ ///
+ /// Returns the index of the given node. Since this structure is
+ /// completely static, the nodes can be indexed with integers from
+ /// the range <tt>[0..nodeNum()-1]</tt>.
+ /// The index of a node is the same as its ID.
+ /// \sa operator()()
+ static int index(const Node& node) { return Parent::index(node); }
+
+ /// \brief Returns the arc connecting the given nodes.
+ ///
+ /// Returns the arc connecting the given nodes.
+ Arc arc(Node s, Node t) const {
+ return Parent::arc(s, t);
+ }
+
+ /// \brief Returns the edge connecting the given nodes.
+ ///
+ /// Returns the edge connecting the given nodes.
+ Edge edge(Node u, Node v) const {
+ return Parent::edge(u, v);
+ }
+
+ /// \brief Number of nodes.
+ int nodeNum() const { return Parent::nodeNum(); }
+ /// \brief Number of arcs.
+ int arcNum() const { return Parent::arcNum(); }
+ /// \brief Number of edges.
+ int edgeNum() const { return Parent::edgeNum(); }
+
+ };
+
+ class FullBpGraphBase {
+
+ protected:
+
+ int _red_num, _blue_num;
+ int _node_num, _edge_num;
+
+ public:
+
+ typedef FullBpGraphBase Graph;
+
+ class Node;
+ class Arc;
+ class Edge;
+
+ class Node {
+ friend class FullBpGraphBase;
+ protected:
+
+ int _id;
+ explicit Node(int id) { _id = id;}
+
+ public:
+ Node() {}
+ Node (Invalid) { _id = -1; }
+ bool operator==(const Node& node) const {return _id == node._id;}
+ bool operator!=(const Node& node) const {return _id != node._id;}
+ bool operator<(const Node& node) const {return _id < node._id;}
+ };
+
+ class RedNode : public Node {
+ friend class FullBpGraphBase;
+ protected:
+
+ explicit RedNode(int pid) : Node(pid) {}
+
+ public:
+ RedNode() {}
+ RedNode(const RedNode& node) : Node(node) {}
+ RedNode(Invalid) : Node(INVALID){}
+ };
+
+ class BlueNode : public Node {
+ friend class FullBpGraphBase;
+ protected:
+
+ explicit BlueNode(int pid) : Node(pid) {}
+
+ public:
+ BlueNode() {}
+ BlueNode(const BlueNode& node) : Node(node) {}
+ BlueNode(Invalid) : Node(INVALID){}
+ };
+
+ class Edge {
+ friend class FullBpGraphBase;
+ protected:
+
+ int _id;
+ explicit Edge(int id) { _id = id;}
+
+ public:
+ Edge() {}
+ Edge (Invalid) { _id = -1; }
+ bool operator==(const Edge& arc) const {return _id == arc._id;}
+ bool operator!=(const Edge& arc) const {return _id != arc._id;}
+ bool operator<(const Edge& arc) const {return _id < arc._id;}
+ };
+
+ class Arc {
+ friend class FullBpGraphBase;
+ protected:
+
+ int _id;
+ explicit Arc(int id) { _id = id;}
+
+ public:
+ operator Edge() const {
+ return _id != -1 ? edgeFromId(_id / 2) : INVALID;
+ }
+
+ Arc() {}
+ Arc (Invalid) { _id = -1; }
+ bool operator==(const Arc& arc) const {return _id == arc._id;}
+ bool operator!=(const Arc& arc) const {return _id != arc._id;}
+ bool operator<(const Arc& arc) const {return _id < arc._id;}
+ };
+
+
+ protected:
+
+ FullBpGraphBase()
+ : _red_num(0), _blue_num(0), _node_num(0), _edge_num(0) {}
+
+ void construct(int redNum, int blueNum) {
+ _red_num = redNum; _blue_num = blueNum;
+ _node_num = redNum + blueNum; _edge_num = redNum * blueNum;
+ }
+
+ public:
+
+ typedef True NodeNumTag;
+ typedef True EdgeNumTag;
+ typedef True ArcNumTag;
+
+ int nodeNum() const { return _node_num; }
+ int redNum() const { return _red_num; }
+ int blueNum() const { return _blue_num; }
+ int edgeNum() const { return _edge_num; }
+ int arcNum() const { return 2 * _edge_num; }
+
+ int maxNodeId() const { return _node_num - 1; }
+ int maxRedId() const { return _red_num - 1; }
+ int maxBlueId() const { return _blue_num - 1; }
+ int maxEdgeId() const { return _edge_num - 1; }
+ int maxArcId() const { return 2 * _edge_num - 1; }
+
+ bool red(Node n) const { return n._id < _red_num; }
+ bool blue(Node n) const { return n._id >= _red_num; }
+
+ static RedNode asRedNodeUnsafe(Node n) { return RedNode(n._id); }
+ static BlueNode asBlueNodeUnsafe(Node n) { return BlueNode(n._id); }
+
+ Node source(Arc a) const {
+ if (a._id & 1) {
+ return Node((a._id >> 1) % _red_num);
+ } else {
+ return Node((a._id >> 1) / _red_num + _red_num);
+ }
+ }
+ Node target(Arc a) const {
+ if (a._id & 1) {
+ return Node((a._id >> 1) / _red_num + _red_num);
+ } else {
+ return Node((a._id >> 1) % _red_num);
+ }
+ }
+
+ RedNode redNode(Edge e) const {
+ return RedNode(e._id % _red_num);
+ }
+ BlueNode blueNode(Edge e) const {
+ return BlueNode(e._id / _red_num + _red_num);
+ }
+
+ static bool direction(Arc a) {
+ return (a._id & 1) == 1;
+ }
+
+ static Arc direct(Edge e, bool d) {
+ return Arc(e._id * 2 + (d ? 1 : 0));
+ }
+
+ void first(Node& node) const {
+ node._id = _node_num - 1;
+ }
+
+ static void next(Node& node) {
+ --node._id;
+ }
+
+ void first(RedNode& node) const {
+ node._id = _red_num - 1;
+ }
+
+ static void next(RedNode& node) {
+ --node._id;
+ }
+
+ void first(BlueNode& node) const {
+ if (_red_num == _node_num) node._id = -1;
+ else node._id = _node_num - 1;
+ }
+
+ void next(BlueNode& node) const {
+ if (node._id == _red_num) node._id = -1;
+ else --node._id;
+ }
+
+ void first(Arc& arc) const {
+ arc._id = 2 * _edge_num - 1;
+ }
+
+ static void next(Arc& arc) {
+ --arc._id;
+ }
+
+ void first(Edge& arc) const {
+ arc._id = _edge_num - 1;
+ }
+
+ static void next(Edge& arc) {
+ --arc._id;
+ }
+
+ void firstOut(Arc &a, const Node& v) const {
+ if (v._id < _red_num) {
+ a._id = 2 * (v._id + _red_num * (_blue_num - 1)) + 1;
+ } else {
+ a._id = 2 * (_red_num - 1 + _red_num * (v._id - _red_num));
+ }
+ }
+ void nextOut(Arc &a) const {
+ if (a._id & 1) {
+ a._id -= 2 * _red_num;
+ if (a._id < 0) a._id = -1;
+ } else {
+ if (a._id % (2 * _red_num) == 0) a._id = -1;
+ else a._id -= 2;
+ }
+ }
+
+ void firstIn(Arc &a, const Node& v) const {
+ if (v._id < _red_num) {
+ a._id = 2 * (v._id + _red_num * (_blue_num - 1));
+ } else {
+ a._id = 2 * (_red_num - 1 + _red_num * (v._id - _red_num)) + 1;
+ }
+ }
+ void nextIn(Arc &a) const {
+ if (a._id & 1) {
+ if (a._id % (2 * _red_num) == 1) a._id = -1;
+ else a._id -= 2;
+ } else {
+ a._id -= 2 * _red_num;
+ if (a._id < 0) a._id = -1;
+ }
+ }
+
+ void firstInc(Edge &e, bool& d, const Node& v) const {
+ if (v._id < _red_num) {
+ d = true;
+ e._id = v._id + _red_num * (_blue_num - 1);
+ } else {
+ d = false;
+ e._id = _red_num - 1 + _red_num * (v._id - _red_num);
+ }
+ }
+ void nextInc(Edge &e, bool& d) const {
+ if (d) {
+ e._id -= _red_num;
+ if (e._id < 0) e._id = -1;
+ } else {
+ if (e._id % _red_num == 0) e._id = -1;
+ else --e._id;
+ }
+ }
+
+ static int id(const Node& v) { return v._id; }
+ int id(const RedNode& v) const { return v._id; }
+ int id(const BlueNode& v) const { return v._id - _red_num; }
+ static int id(Arc e) { return e._id; }
+ static int id(Edge e) { return e._id; }
+
+ static Node nodeFromId(int id) { return Node(id);}
+ static Arc arcFromId(int id) { return Arc(id);}
+ static Edge edgeFromId(int id) { return Edge(id);}
+
+ bool valid(Node n) const {
+ return n._id >= 0 && n._id < _node_num;
+ }
+ bool valid(Arc a) const {
+ return a._id >= 0 && a._id < 2 * _edge_num;
+ }
+ bool valid(Edge e) const {
+ return e._id >= 0 && e._id < _edge_num;
+ }
+
+ RedNode redNode(int index) const {
+ return RedNode(index);
+ }
+
+ int index(RedNode n) const {
+ return n._id;
+ }
+
+ BlueNode blueNode(int index) const {
+ return BlueNode(index + _red_num);
+ }
+
+ int index(BlueNode n) const {
+ return n._id - _red_num;
+ }
+
+ void clear() {
+ _red_num = 0; _blue_num = 0;
+ _node_num = 0; _edge_num = 0;
+ }
+
+ Edge edge(const Node& u, const Node& v) const {
+ if (u._id < _red_num) {
+ if (v._id < _red_num) {
+ return Edge(-1);
+ } else {
+ return Edge(u._id + _red_num * (v._id - _red_num));
+ }
+ } else {
+ if (v._id < _red_num) {
+ return Edge(v._id + _red_num * (u._id - _red_num));
+ } else {
+ return Edge(-1);
+ }
+ }
+ }
+
+ Arc arc(const Node& u, const Node& v) const {
+ if (u._id < _red_num) {
+ if (v._id < _red_num) {
+ return Arc(-1);
+ } else {
+ return Arc(2 * (u._id + _red_num * (v._id - _red_num)) + 1);
+ }
+ } else {
+ if (v._id < _red_num) {
+ return Arc(2 * (v._id + _red_num * (u._id - _red_num)));
+ } else {
+ return Arc(-1);
+ }
+ }
+ }
+
+ typedef True FindEdgeTag;
+ typedef True FindArcTag;
+
+ Edge findEdge(Node u, Node v, Edge prev = INVALID) const {
+ return prev != INVALID ? INVALID : edge(u, v);
+ }
+
+ Arc findArc(Node s, Node t, Arc prev = INVALID) const {
+ return prev != INVALID ? INVALID : arc(s, t);
+ }
+
+ };
+
+ typedef BpGraphExtender<FullBpGraphBase> ExtendedFullBpGraphBase;
+
+ /// \ingroup graphs
+ ///
+ /// \brief An undirected full bipartite graph class.
+ ///
+ /// FullBpGraph is a simple and fast implmenetation of undirected
+ /// full bipartite graphs. It contains an edge between every
+ /// red-blue pairs of nodes, therefore the number of edges is
+ /// <tt>nr*nb</tt>. This class is completely static and it needs
+ /// constant memory space. Thus you can neither add nor delete
+ /// nodes or edges, however the structure can be resized using
+ /// resize().
+ ///
+ /// This type fully conforms to the \ref concepts::BpGraph "BpGraph concept".
+ /// Most of its member functions and nested classes are documented
+ /// only in the concept class.
+ ///
+ /// This class provides constant time counting for nodes, edges and arcs.
+ ///
+ /// \sa FullGraph
+ class FullBpGraph : public ExtendedFullBpGraphBase {
+ public:
+
+ typedef ExtendedFullBpGraphBase Parent;
+
+ /// \brief Default constructor.
+ ///
+ /// Default constructor. The number of nodes and edges will be zero.
+ FullBpGraph() { construct(0, 0); }
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ /// \param redNum The number of the red nodes.
+ /// \param blueNum The number of the blue nodes.
+ FullBpGraph(int redNum, int blueNum) { construct(redNum, blueNum); }
+
+ /// \brief Resizes the graph
+ ///
+ /// This function resizes the graph. It fully destroys and
+ /// rebuilds the structure, therefore the maps of the graph will be
+ /// reallocated automatically and the previous values will be lost.
+ void resize(int redNum, int blueNum) {
+ Parent::notifier(Arc()).clear();
+ Parent::notifier(Edge()).clear();
+ Parent::notifier(Node()).clear();
+ Parent::notifier(BlueNode()).clear();
+ Parent::notifier(RedNode()).clear();
+ construct(redNum, blueNum);
+ Parent::notifier(RedNode()).build();
+ Parent::notifier(BlueNode()).build();
+ Parent::notifier(Node()).build();
+ Parent::notifier(Edge()).build();
+ Parent::notifier(Arc()).build();
+ }
+
+ using Parent::redNode;
+ using Parent::blueNode;
+
+ /// \brief Returns the red node with the given index.
+ ///
+ /// Returns the red node with the given index. Since this
+ /// structure is completely static, the red nodes can be indexed
+ /// with integers from the range <tt>[0..redNum()-1]</tt>.
+ /// \sa redIndex()
+ RedNode redNode(int index) const { return Parent::redNode(index); }
+
+ /// \brief Returns the index of the given red node.
+ ///
+ /// Returns the index of the given red node. Since this structure
+ /// is completely static, the red nodes can be indexed with
+ /// integers from the range <tt>[0..redNum()-1]</tt>.
+ ///
+ /// \sa operator()()
+ int index(RedNode node) const { return Parent::index(node); }
+
+ /// \brief Returns the blue node with the given index.
+ ///
+ /// Returns the blue node with the given index. Since this
+ /// structure is completely static, the blue nodes can be indexed
+ /// with integers from the range <tt>[0..blueNum()-1]</tt>.
+ /// \sa blueIndex()
+ BlueNode blueNode(int index) const { return Parent::blueNode(index); }
+
+ /// \brief Returns the index of the given blue node.
+ ///
+ /// Returns the index of the given blue node. Since this structure
+ /// is completely static, the blue nodes can be indexed with
+ /// integers from the range <tt>[0..blueNum()-1]</tt>.
+ ///
+ /// \sa operator()()
+ int index(BlueNode node) const { return Parent::index(node); }
+
+ /// \brief Returns the edge which connects the given nodes.
+ ///
+ /// Returns the edge which connects the given nodes.
+ Edge edge(const Node& u, const Node& v) const {
+ return Parent::edge(u, v);
+ }
+
+ /// \brief Returns the arc which connects the given nodes.
+ ///
+ /// Returns the arc which connects the given nodes.
+ Arc arc(const Node& u, const Node& v) const {
+ return Parent::arc(u, v);
+ }
+
+ /// \brief Number of nodes.
+ int nodeNum() const { return Parent::nodeNum(); }
+ /// \brief Number of red nodes.
+ int redNum() const { return Parent::redNum(); }
+ /// \brief Number of blue nodes.
+ int blueNum() const { return Parent::blueNum(); }
+ /// \brief Number of arcs.
+ int arcNum() const { return Parent::arcNum(); }
+ /// \brief Number of edges.
+ int edgeNum() const { return Parent::edgeNum(); }
+ };
+
+
+} //namespace lemon
+
+
+#endif //LEMON_FULL_GRAPH_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/glpk.cc b/extern/quadriflow/3rd/lemon-1.3.1/lemon/glpk.cc
new file mode 100644
index 00000000000..38d81151f2f
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/glpk.cc
@@ -0,0 +1,1012 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\file
+///\brief Implementation of the LEMON GLPK LP and MIP solver interface.
+
+#include <lemon/glpk.h>
+#include <glpk.h>
+
+#include <lemon/assert.h>
+
+namespace lemon {
+
+ // GlpkBase members
+
+ GlpkBase::GlpkBase() : LpBase() {
+ lp = glp_create_prob();
+ glp_create_index(lp);
+ messageLevel(MESSAGE_NOTHING);
+ }
+
+ GlpkBase::GlpkBase(const GlpkBase &other) : LpBase() {
+ lp = glp_create_prob();
+ glp_copy_prob(lp, other.lp, GLP_ON);
+ glp_create_index(lp);
+ rows = other.rows;
+ cols = other.cols;
+ messageLevel(MESSAGE_NOTHING);
+ }
+
+ GlpkBase::~GlpkBase() {
+ glp_delete_prob(lp);
+ }
+
+ int GlpkBase::_addCol() {
+ int i = glp_add_cols(lp, 1);
+ glp_set_col_bnds(lp, i, GLP_FR, 0.0, 0.0);
+ return i;
+ }
+
+ int GlpkBase::_addRow() {
+ int i = glp_add_rows(lp, 1);
+ glp_set_row_bnds(lp, i, GLP_FR, 0.0, 0.0);
+ return i;
+ }
+
+ int GlpkBase::_addRow(Value lo, ExprIterator b,
+ ExprIterator e, Value up) {
+ int i = glp_add_rows(lp, 1);
+
+ if (lo == -INF) {
+ if (up == INF) {
+ glp_set_row_bnds(lp, i, GLP_FR, lo, up);
+ } else {
+ glp_set_row_bnds(lp, i, GLP_UP, lo, up);
+ }
+ } else {
+ if (up == INF) {
+ glp_set_row_bnds(lp, i, GLP_LO, lo, up);
+ } else if (lo != up) {
+ glp_set_row_bnds(lp, i, GLP_DB, lo, up);
+ } else {
+ glp_set_row_bnds(lp, i, GLP_FX, lo, up);
+ }
+ }
+
+ std::vector<int> indexes;
+ std::vector<Value> values;
+
+ indexes.push_back(0);
+ values.push_back(0);
+
+ for(ExprIterator it = b; it != e; ++it) {
+ indexes.push_back(it->first);
+ values.push_back(it->second);
+ }
+
+ glp_set_mat_row(lp, i, values.size() - 1,
+ &indexes.front(), &values.front());
+ return i;
+ }
+
+ void GlpkBase::_eraseCol(int i) {
+ int ca[2];
+ ca[1] = i;
+ glp_del_cols(lp, 1, ca);
+ }
+
+ void GlpkBase::_eraseRow(int i) {
+ int ra[2];
+ ra[1] = i;
+ glp_del_rows(lp, 1, ra);
+ }
+
+ void GlpkBase::_eraseColId(int i) {
+ cols.eraseIndex(i);
+ cols.shiftIndices(i);
+ }
+
+ void GlpkBase::_eraseRowId(int i) {
+ rows.eraseIndex(i);
+ rows.shiftIndices(i);
+ }
+
+ void GlpkBase::_getColName(int c, std::string& name) const {
+ const char *str = glp_get_col_name(lp, c);
+ if (str) name = str;
+ else name.clear();
+ }
+
+ void GlpkBase::_setColName(int c, const std::string & name) {
+ glp_set_col_name(lp, c, const_cast<char*>(name.c_str()));
+
+ }
+
+ int GlpkBase::_colByName(const std::string& name) const {
+ int k = glp_find_col(lp, const_cast<char*>(name.c_str()));
+ return k > 0 ? k : -1;
+ }
+
+ void GlpkBase::_getRowName(int r, std::string& name) const {
+ const char *str = glp_get_row_name(lp, r);
+ if (str) name = str;
+ else name.clear();
+ }
+
+ void GlpkBase::_setRowName(int r, const std::string & name) {
+ glp_set_row_name(lp, r, const_cast<char*>(name.c_str()));
+
+ }
+
+ int GlpkBase::_rowByName(const std::string& name) const {
+ int k = glp_find_row(lp, const_cast<char*>(name.c_str()));
+ return k > 0 ? k : -1;
+ }
+
+ void GlpkBase::_setRowCoeffs(int i, ExprIterator b, ExprIterator e) {
+ std::vector<int> indexes;
+ std::vector<Value> values;
+
+ indexes.push_back(0);
+ values.push_back(0);
+
+ for(ExprIterator it = b; it != e; ++it) {
+ indexes.push_back(it->first);
+ values.push_back(it->second);
+ }
+
+ glp_set_mat_row(lp, i, values.size() - 1,
+ &indexes.front(), &values.front());
+ }
+
+ void GlpkBase::_getRowCoeffs(int ix, InsertIterator b) const {
+ int length = glp_get_mat_row(lp, ix, 0, 0);
+
+ std::vector<int> indexes(length + 1);
+ std::vector<Value> values(length + 1);
+
+ glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
+
+ for (int i = 1; i <= length; ++i) {
+ *b = std::make_pair(indexes[i], values[i]);
+ ++b;
+ }
+ }
+
+ void GlpkBase::_setColCoeffs(int ix, ExprIterator b,
+ ExprIterator e) {
+
+ std::vector<int> indexes;
+ std::vector<Value> values;
+
+ indexes.push_back(0);
+ values.push_back(0);
+
+ for(ExprIterator it = b; it != e; ++it) {
+ indexes.push_back(it->first);
+ values.push_back(it->second);
+ }
+
+ glp_set_mat_col(lp, ix, values.size() - 1,
+ &indexes.front(), &values.front());
+ }
+
+ void GlpkBase::_getColCoeffs(int ix, InsertIterator b) const {
+ int length = glp_get_mat_col(lp, ix, 0, 0);
+
+ std::vector<int> indexes(length + 1);
+ std::vector<Value> values(length + 1);
+
+ glp_get_mat_col(lp, ix, &indexes.front(), &values.front());
+
+ for (int i = 1; i <= length; ++i) {
+ *b = std::make_pair(indexes[i], values[i]);
+ ++b;
+ }
+ }
+
+ void GlpkBase::_setCoeff(int ix, int jx, Value value) {
+
+ if (glp_get_num_cols(lp) < glp_get_num_rows(lp)) {
+
+ int length = glp_get_mat_row(lp, ix, 0, 0);
+
+ std::vector<int> indexes(length + 2);
+ std::vector<Value> values(length + 2);
+
+ glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
+
+ //The following code does not suppose that the elements of the
+ //array indexes are sorted
+ bool found = false;
+ for (int i = 1; i <= length; ++i) {
+ if (indexes[i] == jx) {
+ found = true;
+ values[i] = value;
+ break;
+ }
+ }
+ if (!found) {
+ ++length;
+ indexes[length] = jx;
+ values[length] = value;
+ }
+
+ glp_set_mat_row(lp, ix, length, &indexes.front(), &values.front());
+
+ } else {
+
+ int length = glp_get_mat_col(lp, jx, 0, 0);
+
+ std::vector<int> indexes(length + 2);
+ std::vector<Value> values(length + 2);
+
+ glp_get_mat_col(lp, jx, &indexes.front(), &values.front());
+
+ //The following code does not suppose that the elements of the
+ //array indexes are sorted
+ bool found = false;
+ for (int i = 1; i <= length; ++i) {
+ if (indexes[i] == ix) {
+ found = true;
+ values[i] = value;
+ break;
+ }
+ }
+ if (!found) {
+ ++length;
+ indexes[length] = ix;
+ values[length] = value;
+ }
+
+ glp_set_mat_col(lp, jx, length, &indexes.front(), &values.front());
+ }
+
+ }
+
+ GlpkBase::Value GlpkBase::_getCoeff(int ix, int jx) const {
+
+ int length = glp_get_mat_row(lp, ix, 0, 0);
+
+ std::vector<int> indexes(length + 1);
+ std::vector<Value> values(length + 1);
+
+ glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
+
+ for (int i = 1; i <= length; ++i) {
+ if (indexes[i] == jx) {
+ return values[i];
+ }
+ }
+
+ return 0;
+ }
+
+ void GlpkBase::_setColLowerBound(int i, Value lo) {
+ LEMON_ASSERT(lo != INF, "Invalid bound");
+
+ int b = glp_get_col_type(lp, i);
+ double up = glp_get_col_ub(lp, i);
+ if (lo == -INF) {
+ switch (b) {
+ case GLP_FR:
+ case GLP_LO:
+ glp_set_col_bnds(lp, i, GLP_FR, lo, up);
+ break;
+ case GLP_UP:
+ break;
+ case GLP_DB:
+ case GLP_FX:
+ glp_set_col_bnds(lp, i, GLP_UP, lo, up);
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (b) {
+ case GLP_FR:
+ case GLP_LO:
+ glp_set_col_bnds(lp, i, GLP_LO, lo, up);
+ break;
+ case GLP_UP:
+ case GLP_DB:
+ case GLP_FX:
+ if (lo == up)
+ glp_set_col_bnds(lp, i, GLP_FX, lo, up);
+ else
+ glp_set_col_bnds(lp, i, GLP_DB, lo, up);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ GlpkBase::Value GlpkBase::_getColLowerBound(int i) const {
+ int b = glp_get_col_type(lp, i);
+ switch (b) {
+ case GLP_LO:
+ case GLP_DB:
+ case GLP_FX:
+ return glp_get_col_lb(lp, i);
+ default:
+ return -INF;
+ }
+ }
+
+ void GlpkBase::_setColUpperBound(int i, Value up) {
+ LEMON_ASSERT(up != -INF, "Invalid bound");
+
+ int b = glp_get_col_type(lp, i);
+ double lo = glp_get_col_lb(lp, i);
+ if (up == INF) {
+ switch (b) {
+ case GLP_FR:
+ case GLP_LO:
+ break;
+ case GLP_UP:
+ glp_set_col_bnds(lp, i, GLP_FR, lo, up);
+ break;
+ case GLP_DB:
+ case GLP_FX:
+ glp_set_col_bnds(lp, i, GLP_LO, lo, up);
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (b) {
+ case GLP_FR:
+ glp_set_col_bnds(lp, i, GLP_UP, lo, up);
+ break;
+ case GLP_UP:
+ glp_set_col_bnds(lp, i, GLP_UP, lo, up);
+ break;
+ case GLP_LO:
+ case GLP_DB:
+ case GLP_FX:
+ if (lo == up)
+ glp_set_col_bnds(lp, i, GLP_FX, lo, up);
+ else
+ glp_set_col_bnds(lp, i, GLP_DB, lo, up);
+ break;
+ default:
+ break;
+ }
+ }
+
+ }
+
+ GlpkBase::Value GlpkBase::_getColUpperBound(int i) const {
+ int b = glp_get_col_type(lp, i);
+ switch (b) {
+ case GLP_UP:
+ case GLP_DB:
+ case GLP_FX:
+ return glp_get_col_ub(lp, i);
+ default:
+ return INF;
+ }
+ }
+
+ void GlpkBase::_setRowLowerBound(int i, Value lo) {
+ LEMON_ASSERT(lo != INF, "Invalid bound");
+
+ int b = glp_get_row_type(lp, i);
+ double up = glp_get_row_ub(lp, i);
+ if (lo == -INF) {
+ switch (b) {
+ case GLP_FR:
+ case GLP_LO:
+ glp_set_row_bnds(lp, i, GLP_FR, lo, up);
+ break;
+ case GLP_UP:
+ break;
+ case GLP_DB:
+ case GLP_FX:
+ glp_set_row_bnds(lp, i, GLP_UP, lo, up);
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (b) {
+ case GLP_FR:
+ case GLP_LO:
+ glp_set_row_bnds(lp, i, GLP_LO, lo, up);
+ break;
+ case GLP_UP:
+ case GLP_DB:
+ case GLP_FX:
+ if (lo == up)
+ glp_set_row_bnds(lp, i, GLP_FX, lo, up);
+ else
+ glp_set_row_bnds(lp, i, GLP_DB, lo, up);
+ break;
+ default:
+ break;
+ }
+ }
+
+ }
+
+ GlpkBase::Value GlpkBase::_getRowLowerBound(int i) const {
+ int b = glp_get_row_type(lp, i);
+ switch (b) {
+ case GLP_LO:
+ case GLP_DB:
+ case GLP_FX:
+ return glp_get_row_lb(lp, i);
+ default:
+ return -INF;
+ }
+ }
+
+ void GlpkBase::_setRowUpperBound(int i, Value up) {
+ LEMON_ASSERT(up != -INF, "Invalid bound");
+
+ int b = glp_get_row_type(lp, i);
+ double lo = glp_get_row_lb(lp, i);
+ if (up == INF) {
+ switch (b) {
+ case GLP_FR:
+ case GLP_LO:
+ break;
+ case GLP_UP:
+ glp_set_row_bnds(lp, i, GLP_FR, lo, up);
+ break;
+ case GLP_DB:
+ case GLP_FX:
+ glp_set_row_bnds(lp, i, GLP_LO, lo, up);
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (b) {
+ case GLP_FR:
+ glp_set_row_bnds(lp, i, GLP_UP, lo, up);
+ break;
+ case GLP_UP:
+ glp_set_row_bnds(lp, i, GLP_UP, lo, up);
+ break;
+ case GLP_LO:
+ case GLP_DB:
+ case GLP_FX:
+ if (lo == up)
+ glp_set_row_bnds(lp, i, GLP_FX, lo, up);
+ else
+ glp_set_row_bnds(lp, i, GLP_DB, lo, up);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ GlpkBase::Value GlpkBase::_getRowUpperBound(int i) const {
+ int b = glp_get_row_type(lp, i);
+ switch (b) {
+ case GLP_UP:
+ case GLP_DB:
+ case GLP_FX:
+ return glp_get_row_ub(lp, i);
+ default:
+ return INF;
+ }
+ }
+
+ void GlpkBase::_setObjCoeffs(ExprIterator b, ExprIterator e) {
+ for (int i = 1; i <= glp_get_num_cols(lp); ++i) {
+ glp_set_obj_coef(lp, i, 0.0);
+ }
+ for (ExprIterator it = b; it != e; ++it) {
+ glp_set_obj_coef(lp, it->first, it->second);
+ }
+ }
+
+ void GlpkBase::_getObjCoeffs(InsertIterator b) const {
+ for (int i = 1; i <= glp_get_num_cols(lp); ++i) {
+ Value val = glp_get_obj_coef(lp, i);
+ if (val != 0.0) {
+ *b = std::make_pair(i, val);
+ ++b;
+ }
+ }
+ }
+
+ void GlpkBase::_setObjCoeff(int i, Value obj_coef) {
+ //i = 0 means the constant term (shift)
+ glp_set_obj_coef(lp, i, obj_coef);
+ }
+
+ GlpkBase::Value GlpkBase::_getObjCoeff(int i) const {
+ //i = 0 means the constant term (shift)
+ return glp_get_obj_coef(lp, i);
+ }
+
+ void GlpkBase::_setSense(GlpkBase::Sense sense) {
+ switch (sense) {
+ case MIN:
+ glp_set_obj_dir(lp, GLP_MIN);
+ break;
+ case MAX:
+ glp_set_obj_dir(lp, GLP_MAX);
+ break;
+ }
+ }
+
+ GlpkBase::Sense GlpkBase::_getSense() const {
+ switch(glp_get_obj_dir(lp)) {
+ case GLP_MIN:
+ return MIN;
+ case GLP_MAX:
+ return MAX;
+ default:
+ LEMON_ASSERT(false, "Wrong sense");
+ return GlpkBase::Sense();
+ }
+ }
+
+ void GlpkBase::_clear() {
+ glp_erase_prob(lp);
+ }
+
+ void GlpkBase::freeEnv() {
+ glp_free_env();
+ }
+
+ void GlpkBase::_messageLevel(MessageLevel level) {
+ switch (level) {
+ case MESSAGE_NOTHING:
+ _message_level = GLP_MSG_OFF;
+ break;
+ case MESSAGE_ERROR:
+ _message_level = GLP_MSG_ERR;
+ break;
+ case MESSAGE_WARNING:
+ _message_level = GLP_MSG_ERR;
+ break;
+ case MESSAGE_NORMAL:
+ _message_level = GLP_MSG_ON;
+ break;
+ case MESSAGE_VERBOSE:
+ _message_level = GLP_MSG_ALL;
+ break;
+ }
+ }
+
+ void GlpkBase::_write(std::string file, std::string format) const
+ {
+ if(format == "MPS")
+ glp_write_mps(lp, GLP_MPS_FILE, 0, file.c_str());
+ else if(format == "LP")
+ glp_write_lp(lp, 0, file.c_str());
+ else throw UnsupportedFormatError(format);
+ }
+
+ GlpkBase::FreeEnvHelper GlpkBase::freeEnvHelper;
+
+ // GlpkLp members
+
+ GlpkLp::GlpkLp()
+ : LpBase(), LpSolver(), GlpkBase() {
+ presolver(false);
+ }
+
+ GlpkLp::GlpkLp(const GlpkLp& other)
+ : LpBase(other), LpSolver(other), GlpkBase(other) {
+ presolver(false);
+ }
+
+ GlpkLp* GlpkLp::newSolver() const { return new GlpkLp; }
+ GlpkLp* GlpkLp::cloneSolver() const { return new GlpkLp(*this); }
+
+ const char* GlpkLp::_solverName() const { return "GlpkLp"; }
+
+ void GlpkLp::_clear_temporals() {
+ _primal_ray.clear();
+ _dual_ray.clear();
+ }
+
+ GlpkLp::SolveExitStatus GlpkLp::_solve() {
+ return solvePrimal();
+ }
+
+ GlpkLp::SolveExitStatus GlpkLp::solvePrimal() {
+ _clear_temporals();
+
+ glp_smcp smcp;
+ glp_init_smcp(&smcp);
+
+ smcp.msg_lev = _message_level;
+ smcp.presolve = _presolve;
+
+ // If the basis is not valid we get an error return value.
+ // In this case we can try to create a new basis.
+ switch (glp_simplex(lp, &smcp)) {
+ case 0:
+ break;
+ case GLP_EBADB:
+ case GLP_ESING:
+ case GLP_ECOND:
+ glp_term_out(false);
+ glp_adv_basis(lp, 0);
+ glp_term_out(true);
+ if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
+ break;
+ default:
+ return UNSOLVED;
+ }
+
+ return SOLVED;
+ }
+
+ GlpkLp::SolveExitStatus GlpkLp::solveDual() {
+ _clear_temporals();
+
+ glp_smcp smcp;
+ glp_init_smcp(&smcp);
+
+ smcp.msg_lev = _message_level;
+ smcp.meth = GLP_DUAL;
+ smcp.presolve = _presolve;
+
+ // If the basis is not valid we get an error return value.
+ // In this case we can try to create a new basis.
+ switch (glp_simplex(lp, &smcp)) {
+ case 0:
+ break;
+ case GLP_EBADB:
+ case GLP_ESING:
+ case GLP_ECOND:
+ glp_term_out(false);
+ glp_adv_basis(lp, 0);
+ glp_term_out(true);
+ if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
+ break;
+ default:
+ return UNSOLVED;
+ }
+ return SOLVED;
+ }
+
+ GlpkLp::Value GlpkLp::_getPrimal(int i) const {
+ return glp_get_col_prim(lp, i);
+ }
+
+ GlpkLp::Value GlpkLp::_getDual(int i) const {
+ return glp_get_row_dual(lp, i);
+ }
+
+ GlpkLp::Value GlpkLp::_getPrimalValue() const {
+ return glp_get_obj_val(lp);
+ }
+
+ GlpkLp::VarStatus GlpkLp::_getColStatus(int i) const {
+ switch (glp_get_col_stat(lp, i)) {
+ case GLP_BS:
+ return BASIC;
+ case GLP_UP:
+ return UPPER;
+ case GLP_LO:
+ return LOWER;
+ case GLP_NF:
+ return FREE;
+ case GLP_NS:
+ return FIXED;
+ default:
+ LEMON_ASSERT(false, "Wrong column status");
+ return GlpkLp::VarStatus();
+ }
+ }
+
+ GlpkLp::VarStatus GlpkLp::_getRowStatus(int i) const {
+ switch (glp_get_row_stat(lp, i)) {
+ case GLP_BS:
+ return BASIC;
+ case GLP_UP:
+ return UPPER;
+ case GLP_LO:
+ return LOWER;
+ case GLP_NF:
+ return FREE;
+ case GLP_NS:
+ return FIXED;
+ default:
+ LEMON_ASSERT(false, "Wrong row status");
+ return GlpkLp::VarStatus();
+ }
+ }
+
+ GlpkLp::Value GlpkLp::_getPrimalRay(int i) const {
+ if (_primal_ray.empty()) {
+ int row_num = glp_get_num_rows(lp);
+ int col_num = glp_get_num_cols(lp);
+
+ _primal_ray.resize(col_num + 1, 0.0);
+
+ int index = glp_get_unbnd_ray(lp);
+ if (index != 0) {
+ // The primal ray is found in primal simplex second phase
+ LEMON_ASSERT((index <= row_num ? glp_get_row_stat(lp, index) :
+ glp_get_col_stat(lp, index - row_num)) != GLP_BS,
+ "Wrong primal ray");
+
+ bool negate = glp_get_obj_dir(lp) == GLP_MAX;
+
+ if (index > row_num) {
+ _primal_ray[index - row_num] = 1.0;
+ if (glp_get_col_dual(lp, index - row_num) > 0) {
+ negate = !negate;
+ }
+ } else {
+ if (glp_get_row_dual(lp, index) > 0) {
+ negate = !negate;
+ }
+ }
+
+ std::vector<int> ray_indexes(row_num + 1);
+ std::vector<Value> ray_values(row_num + 1);
+ int ray_length = glp_eval_tab_col(lp, index, &ray_indexes.front(),
+ &ray_values.front());
+
+ for (int i = 1; i <= ray_length; ++i) {
+ if (ray_indexes[i] > row_num) {
+ _primal_ray[ray_indexes[i] - row_num] = ray_values[i];
+ }
+ }
+
+ if (negate) {
+ for (int i = 1; i <= col_num; ++i) {
+ _primal_ray[i] = - _primal_ray[i];
+ }
+ }
+ } else {
+ for (int i = 1; i <= col_num; ++i) {
+ _primal_ray[i] = glp_get_col_prim(lp, i);
+ }
+ }
+ }
+ return _primal_ray[i];
+ }
+
+ GlpkLp::Value GlpkLp::_getDualRay(int i) const {
+ if (_dual_ray.empty()) {
+ int row_num = glp_get_num_rows(lp);
+
+ _dual_ray.resize(row_num + 1, 0.0);
+
+ int index = glp_get_unbnd_ray(lp);
+ if (index != 0) {
+ // The dual ray is found in dual simplex second phase
+ LEMON_ASSERT((index <= row_num ? glp_get_row_stat(lp, index) :
+ glp_get_col_stat(lp, index - row_num)) == GLP_BS,
+
+ "Wrong dual ray");
+
+ int idx;
+ bool negate = false;
+
+ if (index > row_num) {
+ idx = glp_get_col_bind(lp, index - row_num);
+ if (glp_get_col_prim(lp, index - row_num) >
+ glp_get_col_ub(lp, index - row_num)) {
+ negate = true;
+ }
+ } else {
+ idx = glp_get_row_bind(lp, index);
+ if (glp_get_row_prim(lp, index) > glp_get_row_ub(lp, index)) {
+ negate = true;
+ }
+ }
+
+ _dual_ray[idx] = negate ? - 1.0 : 1.0;
+
+ glp_btran(lp, &_dual_ray.front());
+ } else {
+ double eps = 1e-7;
+ // The dual ray is found in primal simplex first phase
+ // We assume that the glpk minimizes the slack to get feasible solution
+ for (int i = 1; i <= row_num; ++i) {
+ int index = glp_get_bhead(lp, i);
+ if (index <= row_num) {
+ double res = glp_get_row_prim(lp, index);
+ if (res > glp_get_row_ub(lp, index) + eps) {
+ _dual_ray[i] = -1;
+ } else if (res < glp_get_row_lb(lp, index) - eps) {
+ _dual_ray[i] = 1;
+ } else {
+ _dual_ray[i] = 0;
+ }
+ _dual_ray[i] *= glp_get_rii(lp, index);
+ } else {
+ double res = glp_get_col_prim(lp, index - row_num);
+ if (res > glp_get_col_ub(lp, index - row_num) + eps) {
+ _dual_ray[i] = -1;
+ } else if (res < glp_get_col_lb(lp, index - row_num) - eps) {
+ _dual_ray[i] = 1;
+ } else {
+ _dual_ray[i] = 0;
+ }
+ _dual_ray[i] /= glp_get_sjj(lp, index - row_num);
+ }
+ }
+
+ glp_btran(lp, &_dual_ray.front());
+
+ for (int i = 1; i <= row_num; ++i) {
+ _dual_ray[i] /= glp_get_rii(lp, i);
+ }
+ }
+ }
+ return _dual_ray[i];
+ }
+
+ GlpkLp::ProblemType GlpkLp::_getPrimalType() const {
+ if (glp_get_status(lp) == GLP_OPT)
+ return OPTIMAL;
+ switch (glp_get_prim_stat(lp)) {
+ case GLP_UNDEF:
+ return UNDEFINED;
+ case GLP_FEAS:
+ case GLP_INFEAS:
+ if (glp_get_dual_stat(lp) == GLP_NOFEAS) {
+ return UNBOUNDED;
+ } else {
+ return UNDEFINED;
+ }
+ case GLP_NOFEAS:
+ return INFEASIBLE;
+ default:
+ LEMON_ASSERT(false, "Wrong primal type");
+ return GlpkLp::ProblemType();
+ }
+ }
+
+ GlpkLp::ProblemType GlpkLp::_getDualType() const {
+ if (glp_get_status(lp) == GLP_OPT)
+ return OPTIMAL;
+ switch (glp_get_dual_stat(lp)) {
+ case GLP_UNDEF:
+ return UNDEFINED;
+ case GLP_FEAS:
+ case GLP_INFEAS:
+ if (glp_get_prim_stat(lp) == GLP_NOFEAS) {
+ return UNBOUNDED;
+ } else {
+ return UNDEFINED;
+ }
+ case GLP_NOFEAS:
+ return INFEASIBLE;
+ default:
+ LEMON_ASSERT(false, "Wrong primal type");
+ return GlpkLp::ProblemType();
+ }
+ }
+
+ void GlpkLp::presolver(bool presolve) {
+ _presolve = presolve;
+ }
+
+ // GlpkMip members
+
+ GlpkMip::GlpkMip()
+ : LpBase(), MipSolver(), GlpkBase() {
+ }
+
+ GlpkMip::GlpkMip(const GlpkMip& other)
+ : LpBase(), MipSolver(), GlpkBase(other) {
+ }
+
+ void GlpkMip::_setColType(int i, GlpkMip::ColTypes col_type) {
+ switch (col_type) {
+ case INTEGER:
+ glp_set_col_kind(lp, i, GLP_IV);
+ break;
+ case REAL:
+ glp_set_col_kind(lp, i, GLP_CV);
+ break;
+ }
+ }
+
+ GlpkMip::ColTypes GlpkMip::_getColType(int i) const {
+ switch (glp_get_col_kind(lp, i)) {
+ case GLP_IV:
+ case GLP_BV:
+ return INTEGER;
+ default:
+ return REAL;
+ }
+
+ }
+
+ GlpkMip::SolveExitStatus GlpkMip::_solve() {
+ glp_smcp smcp;
+ glp_init_smcp(&smcp);
+
+ smcp.msg_lev = _message_level;
+ smcp.meth = GLP_DUAL;
+
+ // If the basis is not valid we get an error return value.
+ // In this case we can try to create a new basis.
+ switch (glp_simplex(lp, &smcp)) {
+ case 0:
+ break;
+ case GLP_EBADB:
+ case GLP_ESING:
+ case GLP_ECOND:
+ glp_term_out(false);
+ glp_adv_basis(lp, 0);
+ glp_term_out(true);
+ if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
+ break;
+ default:
+ return UNSOLVED;
+ }
+
+ if (glp_get_status(lp) != GLP_OPT) return SOLVED;
+
+ glp_iocp iocp;
+ glp_init_iocp(&iocp);
+
+ iocp.msg_lev = _message_level;
+
+ if (glp_intopt(lp, &iocp) != 0) return UNSOLVED;
+ return SOLVED;
+ }
+
+
+ GlpkMip::ProblemType GlpkMip::_getType() const {
+ switch (glp_get_status(lp)) {
+ case GLP_OPT:
+ switch (glp_mip_status(lp)) {
+ case GLP_UNDEF:
+ return UNDEFINED;
+ case GLP_NOFEAS:
+ return INFEASIBLE;
+ case GLP_FEAS:
+ return FEASIBLE;
+ case GLP_OPT:
+ return OPTIMAL;
+ default:
+ LEMON_ASSERT(false, "Wrong problem type.");
+ return GlpkMip::ProblemType();
+ }
+ case GLP_NOFEAS:
+ return INFEASIBLE;
+ case GLP_INFEAS:
+ case GLP_FEAS:
+ if (glp_get_dual_stat(lp) == GLP_NOFEAS) {
+ return UNBOUNDED;
+ } else {
+ return UNDEFINED;
+ }
+ default:
+ LEMON_ASSERT(false, "Wrong problem type.");
+ return GlpkMip::ProblemType();
+ }
+ }
+
+ GlpkMip::Value GlpkMip::_getSol(int i) const {
+ return glp_mip_col_val(lp, i);
+ }
+
+ GlpkMip::Value GlpkMip::_getSolValue() const {
+ return glp_mip_obj_val(lp);
+ }
+
+ GlpkMip* GlpkMip::newSolver() const { return new GlpkMip; }
+ GlpkMip* GlpkMip::cloneSolver() const {return new GlpkMip(*this); }
+
+ const char* GlpkMip::_solverName() const { return "GlpkMip"; }
+
+
+
+} //END OF NAMESPACE LEMON
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/glpk.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/glpk.h
new file mode 100644
index 00000000000..ccdc54ac059
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/glpk.h
@@ -0,0 +1,263 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_GLPK_H
+#define LEMON_GLPK_H
+
+///\file
+///\brief Header of the LEMON-GLPK lp solver interface.
+///\ingroup lp_group
+
+#include <lemon/lp_base.h>
+
+namespace lemon {
+
+ namespace _solver_bits {
+ class VoidPtr {
+ private:
+ void *_ptr;
+ public:
+ VoidPtr() : _ptr(0) {}
+
+ template <typename T>
+ VoidPtr(T* ptr) : _ptr(reinterpret_cast<void*>(ptr)) {}
+
+ template <typename T>
+ VoidPtr& operator=(T* ptr) {
+ _ptr = reinterpret_cast<void*>(ptr);
+ return *this;
+ }
+
+ template <typename T>
+ operator T*() const { return reinterpret_cast<T*>(_ptr); }
+ };
+ }
+
+ /// \brief Base interface for the GLPK LP and MIP solver
+ ///
+ /// This class implements the common interface of the GLPK LP and MIP solver.
+ /// \ingroup lp_group
+ class GlpkBase : virtual public LpBase {
+ protected:
+
+ _solver_bits::VoidPtr lp;
+
+ GlpkBase();
+ GlpkBase(const GlpkBase&);
+ virtual ~GlpkBase();
+
+ protected:
+
+ virtual int _addCol();
+ virtual int _addRow();
+ virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
+
+ virtual void _eraseCol(int i);
+ virtual void _eraseRow(int i);
+
+ virtual void _eraseColId(int i);
+ virtual void _eraseRowId(int i);
+
+ virtual void _getColName(int col, std::string& name) const;
+ virtual void _setColName(int col, const std::string& name);
+ virtual int _colByName(const std::string& name) const;
+
+ virtual void _getRowName(int row, std::string& name) const;
+ virtual void _setRowName(int row, const std::string& name);
+ virtual int _rowByName(const std::string& name) const;
+
+ virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
+ virtual void _getRowCoeffs(int i, InsertIterator b) const;
+
+ virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
+ virtual void _getColCoeffs(int i, InsertIterator b) const;
+
+ virtual void _setCoeff(int row, int col, Value value);
+ virtual Value _getCoeff(int row, int col) const;
+
+ virtual void _setColLowerBound(int i, Value value);
+ virtual Value _getColLowerBound(int i) const;
+
+ virtual void _setColUpperBound(int i, Value value);
+ virtual Value _getColUpperBound(int i) const;
+
+ virtual void _setRowLowerBound(int i, Value value);
+ virtual Value _getRowLowerBound(int i) const;
+
+ virtual void _setRowUpperBound(int i, Value value);
+ virtual Value _getRowUpperBound(int i) const;
+
+ virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
+ virtual void _getObjCoeffs(InsertIterator b) const;
+
+ virtual void _setObjCoeff(int i, Value obj_coef);
+ virtual Value _getObjCoeff(int i) const;
+
+ virtual void _setSense(Sense);
+ virtual Sense _getSense() const;
+
+ virtual void _clear();
+
+ virtual void _messageLevel(MessageLevel level);
+
+ virtual void _write(std::string file, std::string format) const;
+
+ private:
+
+ static void freeEnv();
+
+ struct FreeEnvHelper {
+ ~FreeEnvHelper() {
+ freeEnv();
+ }
+ };
+
+ static FreeEnvHelper freeEnvHelper;
+
+ protected:
+
+ int _message_level;
+
+ public:
+
+ ///Pointer to the underlying GLPK data structure.
+ _solver_bits::VoidPtr lpx() {return lp;}
+ ///Const pointer to the underlying GLPK data structure.
+ _solver_bits::VoidPtr lpx() const {return lp;}
+
+ ///Returns the constraint identifier understood by GLPK.
+ int lpxRow(Row r) const { return rows(id(r)); }
+
+ ///Returns the variable identifier understood by GLPK.
+ int lpxCol(Col c) const { return cols(id(c)); }
+
+#ifdef DOXYGEN
+ /// Write the problem or the solution to a file in the given format
+
+ /// This function writes the problem or the solution
+ /// to a file in the given format.
+ /// Trying to write in an unsupported format will trigger
+ /// \ref LpBase::UnsupportedFormatError.
+ /// \param file The file path
+ /// \param format The output file format.
+ /// Supportted formats are "MPS" and "LP".
+ void write(std::string file, std::string format = "MPS") const {}
+#endif
+
+ };
+
+ /// \brief Interface for the GLPK LP solver
+ ///
+ /// This class implements an interface for the GLPK LP solver.
+ ///\ingroup lp_group
+ class GlpkLp : public LpSolver, public GlpkBase {
+ public:
+
+ ///\e
+ GlpkLp();
+ ///\e
+ GlpkLp(const GlpkLp&);
+
+ ///\e
+ virtual GlpkLp* cloneSolver() const;
+ ///\e
+ virtual GlpkLp* newSolver() const;
+
+ private:
+
+ mutable std::vector<double> _primal_ray;
+ mutable std::vector<double> _dual_ray;
+
+ void _clear_temporals();
+
+ protected:
+
+ virtual const char* _solverName() const;
+
+ virtual SolveExitStatus _solve();
+ virtual Value _getPrimal(int i) const;
+ virtual Value _getDual(int i) const;
+
+ virtual Value _getPrimalValue() const;
+
+ virtual VarStatus _getColStatus(int i) const;
+ virtual VarStatus _getRowStatus(int i) const;
+
+ virtual Value _getPrimalRay(int i) const;
+ virtual Value _getDualRay(int i) const;
+
+ virtual ProblemType _getPrimalType() const;
+ virtual ProblemType _getDualType() const;
+
+ public:
+
+ ///Solve with primal simplex
+ SolveExitStatus solvePrimal();
+
+ ///Solve with dual simplex
+ SolveExitStatus solveDual();
+
+ private:
+
+ bool _presolve;
+
+ public:
+
+ ///Turns on or off the presolver
+
+ ///Turns on (\c b is \c true) or off (\c b is \c false) the presolver
+ ///
+ ///The presolver is off by default.
+ void presolver(bool presolve);
+
+ };
+
+ /// \brief Interface for the GLPK MIP solver
+ ///
+ /// This class implements an interface for the GLPK MIP solver.
+ ///\ingroup lp_group
+ class GlpkMip : public MipSolver, public GlpkBase {
+ public:
+
+ ///\e
+ GlpkMip();
+ ///\e
+ GlpkMip(const GlpkMip&);
+
+ virtual GlpkMip* cloneSolver() const;
+ virtual GlpkMip* newSolver() const;
+
+ protected:
+
+ virtual const char* _solverName() const;
+
+ virtual ColTypes _getColType(int col) const;
+ virtual void _setColType(int col, ColTypes col_type);
+
+ virtual SolveExitStatus _solve();
+ virtual ProblemType _getType() const;
+ virtual Value _getSol(int i) const;
+ virtual Value _getSolValue() const;
+
+ };
+
+
+} //END OF NAMESPACE LEMON
+
+#endif //LEMON_GLPK_H
+
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/gomory_hu.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/gomory_hu.h
new file mode 100644
index 00000000000..c43305f88e1
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/gomory_hu.h
@@ -0,0 +1,568 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_GOMORY_HU_TREE_H
+#define LEMON_GOMORY_HU_TREE_H
+
+#include <limits>
+
+#include <lemon/core.h>
+#include <lemon/preflow.h>
+#include <lemon/concept_check.h>
+#include <lemon/concepts/maps.h>
+
+/// \ingroup min_cut
+/// \file
+/// \brief Gomory-Hu cut tree in graphs.
+
+namespace lemon {
+
+ /// \ingroup min_cut
+ ///
+ /// \brief Gomory-Hu cut tree algorithm
+ ///
+ /// The Gomory-Hu tree is a tree on the node set of a given graph, but it
+ /// may contain edges which are not in the original graph. It has the
+ /// property that the minimum capacity edge of the path between two nodes
+ /// in this tree has the same weight as the minimum cut in the graph
+ /// between these nodes. Moreover the components obtained by removing
+ /// this edge from the tree determine the corresponding minimum cut.
+ /// Therefore once this tree is computed, the minimum cut between any pair
+ /// of nodes can easily be obtained.
+ ///
+ /// The algorithm calculates \e n-1 distinct minimum cuts (currently with
+ /// the \ref Preflow algorithm), thus it has \f$O(n^3\sqrt{m})\f$ overall
+ /// time complexity. It calculates a rooted Gomory-Hu tree.
+ /// The structure of the tree and the edge weights can be
+ /// obtained using \c predNode(), \c predValue() and \c rootDist().
+ /// The functions \c minCutMap() and \c minCutValue() calculate
+ /// the minimum cut and the minimum cut value between any two nodes
+ /// in the graph. You can also list (iterate on) the nodes and the
+ /// edges of the cuts using \c MinCutNodeIt and \c MinCutEdgeIt.
+ ///
+ /// \tparam GR The type of the undirected graph the algorithm runs on.
+ /// \tparam CAP The type of the edge map containing the capacities.
+ /// The default map type is \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
+#ifdef DOXYGEN
+ template <typename GR,
+ typename CAP>
+#else
+ template <typename GR,
+ typename CAP = typename GR::template EdgeMap<int> >
+#endif
+ class GomoryHu {
+ public:
+
+ /// The graph type of the algorithm
+ typedef GR Graph;
+ /// The capacity map type of the algorithm
+ typedef CAP Capacity;
+ /// The value type of capacities
+ typedef typename Capacity::Value Value;
+
+ private:
+
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+ const Graph& _graph;
+ const Capacity& _capacity;
+
+ Node _root;
+ typename Graph::template NodeMap<Node>* _pred;
+ typename Graph::template NodeMap<Value>* _weight;
+ typename Graph::template NodeMap<int>* _order;
+
+ void createStructures() {
+ if (!_pred) {
+ _pred = new typename Graph::template NodeMap<Node>(_graph);
+ }
+ if (!_weight) {
+ _weight = new typename Graph::template NodeMap<Value>(_graph);
+ }
+ if (!_order) {
+ _order = new typename Graph::template NodeMap<int>(_graph);
+ }
+ }
+
+ void destroyStructures() {
+ if (_pred) {
+ delete _pred;
+ }
+ if (_weight) {
+ delete _weight;
+ }
+ if (_order) {
+ delete _order;
+ }
+ }
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ /// \param graph The undirected graph the algorithm runs on.
+ /// \param capacity The edge capacity map.
+ GomoryHu(const Graph& graph, const Capacity& capacity)
+ : _graph(graph), _capacity(capacity),
+ _pred(0), _weight(0), _order(0)
+ {
+ checkConcept<concepts::ReadMap<Edge, Value>, Capacity>();
+ }
+
+
+ /// \brief Destructor
+ ///
+ /// Destructor.
+ ~GomoryHu() {
+ destroyStructures();
+ }
+
+ private:
+
+ // Initialize the internal data structures
+ void init() {
+ createStructures();
+
+ _root = NodeIt(_graph);
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ (*_pred)[n] = _root;
+ (*_order)[n] = -1;
+ }
+ (*_pred)[_root] = INVALID;
+ (*_weight)[_root] = std::numeric_limits<Value>::max();
+ }
+
+
+ // Start the algorithm
+ void start() {
+ Preflow<Graph, Capacity> fa(_graph, _capacity, _root, INVALID);
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if (n == _root) continue;
+
+ Node pn = (*_pred)[n];
+ fa.source(n);
+ fa.target(pn);
+
+ fa.runMinCut();
+
+ (*_weight)[n] = fa.flowValue();
+
+ for (NodeIt nn(_graph); nn != INVALID; ++nn) {
+ if (nn != n && fa.minCut(nn) && (*_pred)[nn] == pn) {
+ (*_pred)[nn] = n;
+ }
+ }
+ if ((*_pred)[pn] != INVALID && fa.minCut((*_pred)[pn])) {
+ (*_pred)[n] = (*_pred)[pn];
+ (*_pred)[pn] = n;
+ (*_weight)[n] = (*_weight)[pn];
+ (*_weight)[pn] = fa.flowValue();
+ }
+ }
+
+ (*_order)[_root] = 0;
+ int index = 1;
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ std::vector<Node> st;
+ Node nn = n;
+ while ((*_order)[nn] == -1) {
+ st.push_back(nn);
+ nn = (*_pred)[nn];
+ }
+ while (!st.empty()) {
+ (*_order)[st.back()] = index++;
+ st.pop_back();
+ }
+ }
+ }
+
+ public:
+
+ ///\name Execution Control
+
+ ///@{
+
+ /// \brief Run the Gomory-Hu algorithm.
+ ///
+ /// This function runs the Gomory-Hu algorithm.
+ void run() {
+ init();
+ start();
+ }
+
+ /// @}
+
+ ///\name Query Functions
+ ///The results of the algorithm can be obtained using these
+ ///functions.\n
+ ///\ref run() should be called before using them.\n
+ ///See also \ref MinCutNodeIt and \ref MinCutEdgeIt.
+
+ ///@{
+
+ /// \brief Return the predecessor node in the Gomory-Hu tree.
+ ///
+ /// This function returns the predecessor node of the given node
+ /// in the Gomory-Hu tree.
+ /// If \c node is the root of the tree, then it returns \c INVALID.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ Node predNode(const Node& node) const {
+ return (*_pred)[node];
+ }
+
+ /// \brief Return the weight of the predecessor edge in the
+ /// Gomory-Hu tree.
+ ///
+ /// This function returns the weight of the predecessor edge of the
+ /// given node in the Gomory-Hu tree.
+ /// If \c node is the root of the tree, the result is undefined.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ Value predValue(const Node& node) const {
+ return (*_weight)[node];
+ }
+
+ /// \brief Return the distance from the root node in the Gomory-Hu tree.
+ ///
+ /// This function returns the distance of the given node from the root
+ /// node in the Gomory-Hu tree.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ int rootDist(const Node& node) const {
+ return (*_order)[node];
+ }
+
+ /// \brief Return the minimum cut value between two nodes
+ ///
+ /// This function returns the minimum cut value between the nodes
+ /// \c s and \c t.
+ /// It finds the nearest common ancestor of the given nodes in the
+ /// Gomory-Hu tree and calculates the minimum weight edge on the
+ /// paths to the ancestor.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ Value minCutValue(const Node& s, const Node& t) const {
+ Node sn = s, tn = t;
+ Value value = std::numeric_limits<Value>::max();
+
+ while (sn != tn) {
+ if ((*_order)[sn] < (*_order)[tn]) {
+ if ((*_weight)[tn] <= value) value = (*_weight)[tn];
+ tn = (*_pred)[tn];
+ } else {
+ if ((*_weight)[sn] <= value) value = (*_weight)[sn];
+ sn = (*_pred)[sn];
+ }
+ }
+ return value;
+ }
+
+ /// \brief Return the minimum cut between two nodes
+ ///
+ /// This function returns the minimum cut between the nodes \c s and \c t
+ /// in the \c cutMap parameter by setting the nodes in the component of
+ /// \c s to \c true and the other nodes to \c false.
+ ///
+ /// For higher level interfaces see MinCutNodeIt and MinCutEdgeIt.
+ ///
+ /// \param s The base node.
+ /// \param t The node you want to separate from node \c s.
+ /// \param cutMap The cut will be returned in this map.
+ /// It must be a \c bool (or convertible) \ref concepts::ReadWriteMap
+ /// "ReadWriteMap" on the graph nodes.
+ ///
+ /// \return The value of the minimum cut between \c s and \c t.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ template <typename CutMap>
+ Value minCutMap(const Node& s,
+ const Node& t,
+ CutMap& cutMap
+ ) const {
+ Node sn = s, tn = t;
+ bool s_root=false;
+ Node rn = INVALID;
+ Value value = std::numeric_limits<Value>::max();
+
+ while (sn != tn) {
+ if ((*_order)[sn] < (*_order)[tn]) {
+ if ((*_weight)[tn] <= value) {
+ rn = tn;
+ s_root = false;
+ value = (*_weight)[tn];
+ }
+ tn = (*_pred)[tn];
+ } else {
+ if ((*_weight)[sn] <= value) {
+ rn = sn;
+ s_root = true;
+ value = (*_weight)[sn];
+ }
+ sn = (*_pred)[sn];
+ }
+ }
+
+ typename Graph::template NodeMap<bool> reached(_graph, false);
+ reached[_root] = true;
+ cutMap.set(_root, !s_root);
+ reached[rn] = true;
+ cutMap.set(rn, s_root);
+
+ std::vector<Node> st;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ st.clear();
+ Node nn = n;
+ while (!reached[nn]) {
+ st.push_back(nn);
+ nn = (*_pred)[nn];
+ }
+ while (!st.empty()) {
+ cutMap.set(st.back(), cutMap[nn]);
+ st.pop_back();
+ }
+ }
+
+ return value;
+ }
+
+ ///@}
+
+ friend class MinCutNodeIt;
+
+ /// Iterate on the nodes of a minimum cut
+
+ /// This iterator class lists the nodes of a minimum cut found by
+ /// GomoryHu. Before using it, you must allocate a GomoryHu class
+ /// and call its \ref GomoryHu::run() "run()" method.
+ ///
+ /// This example counts the nodes in the minimum cut separating \c s from
+ /// \c t.
+ /// \code
+ /// GomoryHu<Graph> gom(g, capacities);
+ /// gom.run();
+ /// int cnt=0;
+ /// for(GomoryHu<Graph>::MinCutNodeIt n(gom,s,t); n!=INVALID; ++n) ++cnt;
+ /// \endcode
+ class MinCutNodeIt
+ {
+ bool _side;
+ typename Graph::NodeIt _node_it;
+ typename Graph::template NodeMap<bool> _cut;
+ public:
+ /// Constructor
+
+ /// Constructor.
+ ///
+ MinCutNodeIt(GomoryHu const &gomory,
+ ///< The GomoryHu class. You must call its
+ /// run() method
+ /// before initializing this iterator.
+ const Node& s, ///< The base node.
+ const Node& t,
+ ///< The node you want to separate from node \c s.
+ bool side=true
+ ///< If it is \c true (default) then the iterator lists
+ /// the nodes of the component containing \c s,
+ /// otherwise it lists the other component.
+ /// \note As the minimum cut is not always unique,
+ /// \code
+ /// MinCutNodeIt(gomory, s, t, true);
+ /// \endcode
+ /// and
+ /// \code
+ /// MinCutNodeIt(gomory, t, s, false);
+ /// \endcode
+ /// does not necessarily give the same set of nodes.
+ /// However, it is ensured that
+ /// \code
+ /// MinCutNodeIt(gomory, s, t, true);
+ /// \endcode
+ /// and
+ /// \code
+ /// MinCutNodeIt(gomory, s, t, false);
+ /// \endcode
+ /// together list each node exactly once.
+ )
+ : _side(side), _cut(gomory._graph)
+ {
+ gomory.minCutMap(s,t,_cut);
+ for(_node_it=typename Graph::NodeIt(gomory._graph);
+ _node_it!=INVALID && _cut[_node_it]!=_side;
+ ++_node_it) {}
+ }
+ /// Conversion to \c Node
+
+ /// Conversion to \c Node.
+ ///
+ operator typename Graph::Node() const
+ {
+ return _node_it;
+ }
+ bool operator==(Invalid) { return _node_it==INVALID; }
+ bool operator!=(Invalid) { return _node_it!=INVALID; }
+ /// Next node
+
+ /// Next node.
+ ///
+ MinCutNodeIt &operator++()
+ {
+ for(++_node_it;_node_it!=INVALID&&_cut[_node_it]!=_side;++_node_it) {}
+ return *this;
+ }
+ /// Postfix incrementation
+
+ /// Postfix incrementation.
+ ///
+ /// \warning This incrementation
+ /// returns a \c Node, not a \c MinCutNodeIt, as one may
+ /// expect.
+ typename Graph::Node operator++(int)
+ {
+ typename Graph::Node n=*this;
+ ++(*this);
+ return n;
+ }
+ };
+
+ friend class MinCutEdgeIt;
+
+ /// Iterate on the edges of a minimum cut
+
+ /// This iterator class lists the edges of a minimum cut found by
+ /// GomoryHu. Before using it, you must allocate a GomoryHu class
+ /// and call its \ref GomoryHu::run() "run()" method.
+ ///
+ /// This example computes the value of the minimum cut separating \c s from
+ /// \c t.
+ /// \code
+ /// GomoryHu<Graph> gom(g, capacities);
+ /// gom.run();
+ /// int value=0;
+ /// for(GomoryHu<Graph>::MinCutEdgeIt e(gom,s,t); e!=INVALID; ++e)
+ /// value+=capacities[e];
+ /// \endcode
+ /// The result will be the same as the value returned by
+ /// \ref GomoryHu::minCutValue() "gom.minCutValue(s,t)".
+ class MinCutEdgeIt
+ {
+ bool _side;
+ const Graph &_graph;
+ typename Graph::NodeIt _node_it;
+ typename Graph::OutArcIt _arc_it;
+ typename Graph::template NodeMap<bool> _cut;
+ void step()
+ {
+ ++_arc_it;
+ while(_node_it!=INVALID && _arc_it==INVALID)
+ {
+ for(++_node_it;_node_it!=INVALID&&!_cut[_node_it];++_node_it) {}
+ if(_node_it!=INVALID)
+ _arc_it=typename Graph::OutArcIt(_graph,_node_it);
+ }
+ }
+
+ public:
+ /// Constructor
+
+ /// Constructor.
+ ///
+ MinCutEdgeIt(GomoryHu const &gomory,
+ ///< The GomoryHu class. You must call its
+ /// run() method
+ /// before initializing this iterator.
+ const Node& s, ///< The base node.
+ const Node& t,
+ ///< The node you want to separate from node \c s.
+ bool side=true
+ ///< If it is \c true (default) then the listed arcs
+ /// will be oriented from the
+ /// nodes of the component containing \c s,
+ /// otherwise they will be oriented in the opposite
+ /// direction.
+ )
+ : _graph(gomory._graph), _cut(_graph)
+ {
+ gomory.minCutMap(s,t,_cut);
+ if(!side)
+ for(typename Graph::NodeIt n(_graph);n!=INVALID;++n)
+ _cut[n]=!_cut[n];
+
+ for(_node_it=typename Graph::NodeIt(_graph);
+ _node_it!=INVALID && !_cut[_node_it];
+ ++_node_it) {}
+ _arc_it = _node_it!=INVALID ?
+ typename Graph::OutArcIt(_graph,_node_it) : INVALID;
+ while(_node_it!=INVALID && _arc_it == INVALID)
+ {
+ for(++_node_it; _node_it!=INVALID&&!_cut[_node_it]; ++_node_it) {}
+ if(_node_it!=INVALID)
+ _arc_it= typename Graph::OutArcIt(_graph,_node_it);
+ }
+ while(_arc_it!=INVALID && _cut[_graph.target(_arc_it)]) step();
+ }
+ /// Conversion to \c Arc
+
+ /// Conversion to \c Arc.
+ ///
+ operator typename Graph::Arc() const
+ {
+ return _arc_it;
+ }
+ /// Conversion to \c Edge
+
+ /// Conversion to \c Edge.
+ ///
+ operator typename Graph::Edge() const
+ {
+ return _arc_it;
+ }
+ bool operator==(Invalid) { return _node_it==INVALID; }
+ bool operator!=(Invalid) { return _node_it!=INVALID; }
+ /// Next edge
+
+ /// Next edge.
+ ///
+ MinCutEdgeIt &operator++()
+ {
+ step();
+ while(_arc_it!=INVALID && _cut[_graph.target(_arc_it)]) step();
+ return *this;
+ }
+ /// Postfix incrementation
+
+ /// Postfix incrementation.
+ ///
+ /// \warning This incrementation
+ /// returns an \c Arc, not a \c MinCutEdgeIt, as one may expect.
+ typename Graph::Arc operator++(int)
+ {
+ typename Graph::Arc e=*this;
+ ++(*this);
+ return e;
+ }
+ };
+
+ };
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/graph_to_eps.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/graph_to_eps.h
new file mode 100644
index 00000000000..29ba836937d
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/graph_to_eps.h
@@ -0,0 +1,1186 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_GRAPH_TO_EPS_H
+#define LEMON_GRAPH_TO_EPS_H
+
+#include<iostream>
+#include<fstream>
+#include<sstream>
+#include<algorithm>
+#include<vector>
+
+#ifndef WIN32
+#include<sys/time.h>
+#include<ctime>
+#else
+#include<lemon/bits/windows.h>
+#endif
+
+#include<lemon/math.h>
+#include<lemon/core.h>
+#include<lemon/dim2.h>
+#include<lemon/maps.h>
+#include<lemon/color.h>
+#include<lemon/bits/bezier.h>
+#include<lemon/error.h>
+
+
+///\ingroup eps_io
+///\file
+///\brief A well configurable tool for visualizing graphs
+
+namespace lemon {
+
+ namespace _graph_to_eps_bits {
+ template<class MT>
+ class _NegY {
+ public:
+ typedef typename MT::Key Key;
+ typedef typename MT::Value Value;
+ const MT &map;
+ int yscale;
+ _NegY(const MT &m,bool b) : map(m), yscale(1-b*2) {}
+ Value operator[](Key n) { return Value(map[n].x,map[n].y*yscale);}
+ };
+ }
+
+///Default traits class of GraphToEps
+
+///Default traits class of \ref GraphToEps.
+///
+///\param GR is the type of the underlying graph.
+template<class GR>
+struct DefaultGraphToEpsTraits
+{
+ typedef GR Graph;
+ typedef GR Digraph;
+ typedef typename Graph::Node Node;
+ typedef typename Graph::NodeIt NodeIt;
+ typedef typename Graph::Arc Arc;
+ typedef typename Graph::ArcIt ArcIt;
+ typedef typename Graph::InArcIt InArcIt;
+ typedef typename Graph::OutArcIt OutArcIt;
+
+
+ const Graph &g;
+
+ std::ostream& os;
+
+ typedef ConstMap<typename Graph::Node,dim2::Point<double> > CoordsMapType;
+ CoordsMapType _coords;
+ ConstMap<typename Graph::Node,double > _nodeSizes;
+ ConstMap<typename Graph::Node,int > _nodeShapes;
+
+ ConstMap<typename Graph::Node,Color > _nodeColors;
+ ConstMap<typename Graph::Arc,Color > _arcColors;
+
+ ConstMap<typename Graph::Arc,double > _arcWidths;
+
+ double _arcWidthScale;
+
+ double _nodeScale;
+ double _xBorder, _yBorder;
+ double _scale;
+ double _nodeBorderQuotient;
+
+ bool _drawArrows;
+ double _arrowLength, _arrowWidth;
+
+ bool _showNodes, _showArcs;
+
+ bool _enableParallel;
+ double _parArcDist;
+
+ bool _showNodeText;
+ ConstMap<typename Graph::Node,bool > _nodeTexts;
+ double _nodeTextSize;
+
+ bool _showNodePsText;
+ ConstMap<typename Graph::Node,bool > _nodePsTexts;
+ char *_nodePsTextsPreamble;
+
+ bool _undirected;
+
+ bool _pleaseRemoveOsStream;
+
+ bool _scaleToA4;
+
+ std::string _title;
+ std::string _copyright;
+
+ enum NodeTextColorType
+ { DIST_COL=0, DIST_BW=1, CUST_COL=2, SAME_COL=3 } _nodeTextColorType;
+ ConstMap<typename Graph::Node,Color > _nodeTextColors;
+
+ bool _autoNodeScale;
+ bool _autoArcWidthScale;
+
+ bool _absoluteNodeSizes;
+ bool _absoluteArcWidths;
+
+ bool _negY;
+
+ bool _preScale;
+ ///Constructor
+
+ ///Constructor
+ ///\param gr Reference to the graph to be printed.
+ ///\param ost Reference to the output stream.
+ ///By default, it is <tt>std::cout</tt>.
+ ///\param pros If it is \c true, then the \c ostream referenced by \c os
+ ///will be explicitly deallocated by the destructor.
+ DefaultGraphToEpsTraits(const GR &gr, std::ostream& ost = std::cout,
+ bool pros = false) :
+ g(gr), os(ost),
+ _coords(dim2::Point<double>(1,1)), _nodeSizes(1), _nodeShapes(0),
+ _nodeColors(WHITE), _arcColors(BLACK),
+ _arcWidths(1.0), _arcWidthScale(0.003),
+ _nodeScale(.01), _xBorder(10), _yBorder(10), _scale(1.0),
+ _nodeBorderQuotient(.1),
+ _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
+ _showNodes(true), _showArcs(true),
+ _enableParallel(false), _parArcDist(1),
+ _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
+ _showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0),
+ _undirected(lemon::UndirectedTagIndicator<GR>::value),
+ _pleaseRemoveOsStream(pros), _scaleToA4(false),
+ _nodeTextColorType(SAME_COL), _nodeTextColors(BLACK),
+ _autoNodeScale(false),
+ _autoArcWidthScale(false),
+ _absoluteNodeSizes(false),
+ _absoluteArcWidths(false),
+ _negY(false),
+ _preScale(true)
+ {}
+};
+
+///Auxiliary class to implement the named parameters of \ref graphToEps()
+
+///Auxiliary class to implement the named parameters of \ref graphToEps().
+///
+///For detailed examples see the \ref graph_to_eps_demo.cc demo file.
+template<class T> class GraphToEps : public T
+{
+ // Can't believe it is required by the C++ standard
+ using T::g;
+ using T::os;
+
+ using T::_coords;
+ using T::_nodeSizes;
+ using T::_nodeShapes;
+ using T::_nodeColors;
+ using T::_arcColors;
+ using T::_arcWidths;
+
+ using T::_arcWidthScale;
+ using T::_nodeScale;
+ using T::_xBorder;
+ using T::_yBorder;
+ using T::_scale;
+ using T::_nodeBorderQuotient;
+
+ using T::_drawArrows;
+ using T::_arrowLength;
+ using T::_arrowWidth;
+
+ using T::_showNodes;
+ using T::_showArcs;
+
+ using T::_enableParallel;
+ using T::_parArcDist;
+
+ using T::_showNodeText;
+ using T::_nodeTexts;
+ using T::_nodeTextSize;
+
+ using T::_showNodePsText;
+ using T::_nodePsTexts;
+ using T::_nodePsTextsPreamble;
+
+ using T::_undirected;
+
+ using T::_pleaseRemoveOsStream;
+
+ using T::_scaleToA4;
+
+ using T::_title;
+ using T::_copyright;
+
+ using T::CUST_COL;
+ using T::DIST_COL;
+ using T::DIST_BW;
+ using T::_nodeTextColorType;
+ using T::_nodeTextColors;
+
+ using T::_autoNodeScale;
+ using T::_autoArcWidthScale;
+
+ using T::_absoluteNodeSizes;
+ using T::_absoluteArcWidths;
+
+
+ using T::_negY;
+ using T::_preScale;
+
+ // dradnats ++C eht yb deriuqer si ti eveileb t'naC
+
+ typedef typename T::Graph Graph;
+ typedef typename T::Digraph Digraph;
+ typedef typename Graph::Node Node;
+ typedef typename Graph::NodeIt NodeIt;
+ typedef typename Graph::Arc Arc;
+ typedef typename Graph::ArcIt ArcIt;
+ typedef typename Graph::InArcIt InArcIt;
+ typedef typename Graph::OutArcIt OutArcIt;
+
+ static const int INTERPOL_PREC;
+ static const double A4HEIGHT;
+ static const double A4WIDTH;
+ static const double A4BORDER;
+
+ bool dontPrint;
+
+public:
+ ///Node shapes
+
+ ///Node shapes.
+ ///
+ enum NodeShapes {
+ /// = 0
+ ///\image html nodeshape_0.png
+ ///\image latex nodeshape_0.eps "CIRCLE shape (0)" width=2cm
+ CIRCLE=0,
+ /// = 1
+ ///\image html nodeshape_1.png
+ ///\image latex nodeshape_1.eps "SQUARE shape (1)" width=2cm
+ SQUARE=1,
+ /// = 2
+ ///\image html nodeshape_2.png
+ ///\image latex nodeshape_2.eps "DIAMOND shape (2)" width=2cm
+ DIAMOND=2,
+ /// = 3
+ ///\image html nodeshape_3.png
+ ///\image latex nodeshape_3.eps "MALE shape (3)" width=2cm
+ MALE=3,
+ /// = 4
+ ///\image html nodeshape_4.png
+ ///\image latex nodeshape_4.eps "FEMALE shape (4)" width=2cm
+ FEMALE=4
+ };
+
+private:
+ class arcLess {
+ const Graph &g;
+ public:
+ arcLess(const Graph &_g) : g(_g) {}
+ bool operator()(Arc a,Arc b) const
+ {
+ Node ai=std::min(g.source(a),g.target(a));
+ Node aa=std::max(g.source(a),g.target(a));
+ Node bi=std::min(g.source(b),g.target(b));
+ Node ba=std::max(g.source(b),g.target(b));
+ return ai<bi ||
+ (ai==bi && (aa < ba ||
+ (aa==ba && ai==g.source(a) && bi==g.target(b))));
+ }
+ };
+ bool isParallel(Arc e,Arc f) const
+ {
+ return (g.source(e)==g.source(f)&&
+ g.target(e)==g.target(f)) ||
+ (g.source(e)==g.target(f)&&
+ g.target(e)==g.source(f));
+ }
+ template<class TT>
+ static std::string psOut(const dim2::Point<TT> &p)
+ {
+ std::ostringstream os;
+ os << p.x << ' ' << p.y;
+ return os.str();
+ }
+ static std::string psOut(const Color &c)
+ {
+ std::ostringstream os;
+ os << c.red() << ' ' << c.green() << ' ' << c.blue();
+ return os.str();
+ }
+
+public:
+ GraphToEps(const T &t) : T(t), dontPrint(false) {};
+
+ template<class X> struct CoordsTraits : public T {
+ typedef X CoordsMapType;
+ const X &_coords;
+ CoordsTraits(const T &t,const X &x) : T(t), _coords(x) {}
+ };
+ ///Sets the map of the node coordinates
+
+ ///Sets the map of the node coordinates.
+ ///\param x must be a node map with \ref dim2::Point "dim2::Point<double>" or
+ ///\ref dim2::Point "dim2::Point<int>" values.
+ template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) {
+ dontPrint=true;
+ return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x));
+ }
+ template<class X> struct NodeSizesTraits : public T {
+ const X &_nodeSizes;
+ NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {}
+ };
+ ///Sets the map of the node sizes
+
+ ///Sets the map of the node sizes.
+ ///\param x must be a node map with \c double (or convertible) values.
+ template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x)
+ {
+ dontPrint=true;
+ return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
+ }
+ template<class X> struct NodeShapesTraits : public T {
+ const X &_nodeShapes;
+ NodeShapesTraits(const T &t,const X &x) : T(t), _nodeShapes(x) {}
+ };
+ ///Sets the map of the node shapes
+
+ ///Sets the map of the node shapes.
+ ///The available shape values
+ ///can be found in \ref NodeShapes "enum NodeShapes".
+ ///\param x must be a node map with \c int (or convertible) values.
+ ///\sa NodeShapes
+ template<class X> GraphToEps<NodeShapesTraits<X> > nodeShapes(const X &x)
+ {
+ dontPrint=true;
+ return GraphToEps<NodeShapesTraits<X> >(NodeShapesTraits<X>(*this,x));
+ }
+ template<class X> struct NodeTextsTraits : public T {
+ const X &_nodeTexts;
+ NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {}
+ };
+ ///Sets the text printed on the nodes
+
+ ///Sets the text printed on the nodes.
+ ///\param x must be a node map with type that can be pushed to a standard
+ ///\c ostream.
+ template<class X> GraphToEps<NodeTextsTraits<X> > nodeTexts(const X &x)
+ {
+ dontPrint=true;
+ _showNodeText=true;
+ return GraphToEps<NodeTextsTraits<X> >(NodeTextsTraits<X>(*this,x));
+ }
+ template<class X> struct NodePsTextsTraits : public T {
+ const X &_nodePsTexts;
+ NodePsTextsTraits(const T &t,const X &x) : T(t), _nodePsTexts(x) {}
+ };
+ ///Inserts a PostScript block to the nodes
+
+ ///With this command it is possible to insert a verbatim PostScript
+ ///block to the nodes.
+ ///The PS current point will be moved to the center of the node before
+ ///the PostScript block inserted.
+ ///
+ ///Before and after the block a newline character is inserted so you
+ ///don't have to bother with the separators.
+ ///
+ ///\param x must be a node map with type that can be pushed to a standard
+ ///\c ostream.
+ ///
+ ///\sa nodePsTextsPreamble()
+ template<class X> GraphToEps<NodePsTextsTraits<X> > nodePsTexts(const X &x)
+ {
+ dontPrint=true;
+ _showNodePsText=true;
+ return GraphToEps<NodePsTextsTraits<X> >(NodePsTextsTraits<X>(*this,x));
+ }
+ template<class X> struct ArcWidthsTraits : public T {
+ const X &_arcWidths;
+ ArcWidthsTraits(const T &t,const X &x) : T(t), _arcWidths(x) {}
+ };
+ ///Sets the map of the arc widths
+
+ ///Sets the map of the arc widths.
+ ///\param x must be an arc map with \c double (or convertible) values.
+ template<class X> GraphToEps<ArcWidthsTraits<X> > arcWidths(const X &x)
+ {
+ dontPrint=true;
+ return GraphToEps<ArcWidthsTraits<X> >(ArcWidthsTraits<X>(*this,x));
+ }
+
+ template<class X> struct NodeColorsTraits : public T {
+ const X &_nodeColors;
+ NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {}
+ };
+ ///Sets the map of the node colors
+
+ ///Sets the map of the node colors.
+ ///\param x must be a node map with \ref Color values.
+ ///
+ ///\sa Palette
+ template<class X> GraphToEps<NodeColorsTraits<X> >
+ nodeColors(const X &x)
+ {
+ dontPrint=true;
+ return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
+ }
+ template<class X> struct NodeTextColorsTraits : public T {
+ const X &_nodeTextColors;
+ NodeTextColorsTraits(const T &t,const X &x) : T(t), _nodeTextColors(x) {}
+ };
+ ///Sets the map of the node text colors
+
+ ///Sets the map of the node text colors.
+ ///\param x must be a node map with \ref Color values.
+ ///
+ ///\sa Palette
+ template<class X> GraphToEps<NodeTextColorsTraits<X> >
+ nodeTextColors(const X &x)
+ {
+ dontPrint=true;
+ _nodeTextColorType=CUST_COL;
+ return GraphToEps<NodeTextColorsTraits<X> >
+ (NodeTextColorsTraits<X>(*this,x));
+ }
+ template<class X> struct ArcColorsTraits : public T {
+ const X &_arcColors;
+ ArcColorsTraits(const T &t,const X &x) : T(t), _arcColors(x) {}
+ };
+ ///Sets the map of the arc colors
+
+ ///Sets the map of the arc colors.
+ ///\param x must be an arc map with \ref Color values.
+ ///
+ ///\sa Palette
+ template<class X> GraphToEps<ArcColorsTraits<X> >
+ arcColors(const X &x)
+ {
+ dontPrint=true;
+ return GraphToEps<ArcColorsTraits<X> >(ArcColorsTraits<X>(*this,x));
+ }
+ ///Sets a global scale factor for node sizes
+
+ ///Sets a global scale factor for node sizes.
+ ///
+ /// If nodeSizes() is not given, this function simply sets the node
+ /// sizes to \c d. If nodeSizes() is given, but
+ /// autoNodeScale() is not, then the node size given by
+ /// nodeSizes() will be multiplied by the value \c d.
+ /// If both nodeSizes() and autoNodeScale() are used, then the
+ /// node sizes will be scaled in such a way that the greatest size will be
+ /// equal to \c d.
+ /// \sa nodeSizes()
+ /// \sa autoNodeScale()
+ GraphToEps<T> &nodeScale(double d=.01) {_nodeScale=d;return *this;}
+ ///Turns on/off the automatic node size scaling.
+
+ ///Turns on/off the automatic node size scaling.
+ ///
+ ///\sa nodeScale()
+ ///
+ GraphToEps<T> &autoNodeScale(bool b=true) {
+ _autoNodeScale=b;return *this;
+ }
+
+ ///Turns on/off the absolutematic node size scaling.
+
+ ///Turns on/off the absolutematic node size scaling.
+ ///
+ ///\sa nodeScale()
+ ///
+ GraphToEps<T> &absoluteNodeSizes(bool b=true) {
+ _absoluteNodeSizes=b;return *this;
+ }
+
+ ///Negates the Y coordinates.
+ GraphToEps<T> &negateY(bool b=true) {
+ _negY=b;return *this;
+ }
+
+ ///Turn on/off pre-scaling
+
+ ///By default, graphToEps() rescales the whole image in order to avoid
+ ///very big or very small bounding boxes.
+ ///
+ ///This (p)rescaling can be turned off with this function.
+ ///
+ GraphToEps<T> &preScale(bool b=true) {
+ _preScale=b;return *this;
+ }
+
+ ///Sets a global scale factor for arc widths
+
+ /// Sets a global scale factor for arc widths.
+ ///
+ /// If arcWidths() is not given, this function simply sets the arc
+ /// widths to \c d. If arcWidths() is given, but
+ /// autoArcWidthScale() is not, then the arc withs given by
+ /// arcWidths() will be multiplied by the value \c d.
+ /// If both arcWidths() and autoArcWidthScale() are used, then the
+ /// arc withs will be scaled in such a way that the greatest width will be
+ /// equal to \c d.
+ GraphToEps<T> &arcWidthScale(double d=.003) {_arcWidthScale=d;return *this;}
+ ///Turns on/off the automatic arc width scaling.
+
+ ///Turns on/off the automatic arc width scaling.
+ ///
+ ///\sa arcWidthScale()
+ ///
+ GraphToEps<T> &autoArcWidthScale(bool b=true) {
+ _autoArcWidthScale=b;return *this;
+ }
+ ///Turns on/off the absolutematic arc width scaling.
+
+ ///Turns on/off the absolutematic arc width scaling.
+ ///
+ ///\sa arcWidthScale()
+ ///
+ GraphToEps<T> &absoluteArcWidths(bool b=true) {
+ _absoluteArcWidths=b;return *this;
+ }
+ ///Sets a global scale factor for the whole picture
+ GraphToEps<T> &scale(double d) {_scale=d;return *this;}
+ ///Sets the width of the border around the picture
+ GraphToEps<T> &border(double b=10) {_xBorder=_yBorder=b;return *this;}
+ ///Sets the width of the border around the picture
+ GraphToEps<T> &border(double x, double y) {
+ _xBorder=x;_yBorder=y;return *this;
+ }
+ ///Sets whether to draw arrows
+ GraphToEps<T> &drawArrows(bool b=true) {_drawArrows=b;return *this;}
+ ///Sets the length of the arrowheads
+ GraphToEps<T> &arrowLength(double d=1.0) {_arrowLength*=d;return *this;}
+ ///Sets the width of the arrowheads
+ GraphToEps<T> &arrowWidth(double d=.3) {_arrowWidth*=d;return *this;}
+
+ ///Scales the drawing to fit to A4 page
+ GraphToEps<T> &scaleToA4() {_scaleToA4=true;return *this;}
+
+ ///Enables parallel arcs
+ GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
+
+ ///Sets the distance between parallel arcs
+ GraphToEps<T> &parArcDist(double d) {_parArcDist*=d;return *this;}
+
+ ///Hides the arcs
+ GraphToEps<T> &hideArcs(bool b=true) {_showArcs=!b;return *this;}
+ ///Hides the nodes
+ GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;}
+
+ ///Sets the size of the node texts
+ GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
+
+ ///Sets the color of the node texts to be different from the node color
+
+ ///Sets the color of the node texts to be as different from the node color
+ ///as it is possible.
+ GraphToEps<T> &distantColorNodeTexts()
+ {_nodeTextColorType=DIST_COL;return *this;}
+ ///Sets the color of the node texts to be black or white and always visible.
+
+ ///Sets the color of the node texts to be black or white according to
+ ///which is more different from the node color.
+ GraphToEps<T> &distantBWNodeTexts()
+ {_nodeTextColorType=DIST_BW;return *this;}
+
+ ///Gives a preamble block for node Postscript block.
+
+ ///Gives a preamble block for node Postscript block.
+ ///
+ ///\sa nodePsTexts()
+ GraphToEps<T> & nodePsTextsPreamble(const char *str) {
+ _nodePsTextsPreamble=str ;return *this;
+ }
+ ///Sets whether the graph is undirected
+
+ ///Sets whether the graph is undirected.
+ ///
+ ///This setting is the default for undirected graphs.
+ ///
+ ///\sa directed()
+ GraphToEps<T> &undirected(bool b=true) {_undirected=b;return *this;}
+
+ ///Sets whether the graph is directed
+
+ ///Sets whether the graph is directed.
+ ///Use it to show the edges as a pair of directed ones.
+ ///
+ ///This setting is the default for digraphs.
+ ///
+ ///\sa undirected()
+ GraphToEps<T> &directed(bool b=true) {_undirected=!b;return *this;}
+
+ ///Sets the title.
+
+ ///Sets the title of the generated image,
+ ///namely it inserts a <tt>%%Title:</tt> DSC field to the header of
+ ///the EPS file.
+ GraphToEps<T> &title(const std::string &t) {_title=t;return *this;}
+ ///Sets the copyright statement.
+
+ ///Sets the copyright statement of the generated image,
+ ///namely it inserts a <tt>%%Copyright:</tt> DSC field to the header of
+ ///the EPS file.
+ GraphToEps<T> &copyright(const std::string &t) {_copyright=t;return *this;}
+
+protected:
+ bool isInsideNode(dim2::Point<double> p, double r,int t)
+ {
+ switch(t) {
+ case CIRCLE:
+ case MALE:
+ case FEMALE:
+ return p.normSquare()<=r*r;
+ case SQUARE:
+ return p.x<=r&&p.x>=-r&&p.y<=r&&p.y>=-r;
+ case DIAMOND:
+ return p.x+p.y<=r && p.x-p.y<=r && -p.x+p.y<=r && -p.x-p.y<=r;
+ }
+ return false;
+ }
+
+public:
+ ~GraphToEps() { }
+
+ ///Draws the graph.
+
+ ///Like other functions using
+ ///\ref named-templ-func-param "named template parameters",
+ ///this function calls the algorithm itself, i.e. in this case
+ ///it draws the graph.
+ void run() {
+ const double EPSILON=1e-9;
+ if(dontPrint) return;
+
+ _graph_to_eps_bits::_NegY<typename T::CoordsMapType>
+ mycoords(_coords,_negY);
+
+ os << "%!PS-Adobe-2.0 EPSF-2.0\n";
+ if(_title.size()>0) os << "%%Title: " << _title << '\n';
+ if(_copyright.size()>0) os << "%%Copyright: " << _copyright << '\n';
+ os << "%%Creator: LEMON, graphToEps()\n";
+
+ {
+ os << "%%CreationDate: ";
+#ifndef WIN32
+ timeval tv;
+ gettimeofday(&tv, 0);
+
+ char cbuf[26];
+ ctime_r(&tv.tv_sec,cbuf);
+ os << cbuf;
+#else
+ os << bits::getWinFormattedDate();
+ os << std::endl;
+#endif
+ }
+
+ if (_autoArcWidthScale) {
+ double max_w=0;
+ for(ArcIt e(g);e!=INVALID;++e)
+ max_w=std::max(double(_arcWidths[e]),max_w);
+ if(max_w>EPSILON) {
+ _arcWidthScale/=max_w;
+ }
+ }
+
+ if (_autoNodeScale) {
+ double max_s=0;
+ for(NodeIt n(g);n!=INVALID;++n)
+ max_s=std::max(double(_nodeSizes[n]),max_s);
+ if(max_s>EPSILON) {
+ _nodeScale/=max_s;
+ }
+ }
+
+ double diag_len = 1;
+ if(!(_absoluteNodeSizes&&_absoluteArcWidths)) {
+ dim2::Box<double> bb;
+ for(NodeIt n(g);n!=INVALID;++n) bb.add(mycoords[n]);
+ if (bb.empty()) {
+ bb = dim2::Box<double>(dim2::Point<double>(0,0));
+ }
+ diag_len = std::sqrt((bb.bottomLeft()-bb.topRight()).normSquare());
+ if(diag_len<EPSILON) diag_len = 1;
+ if(!_absoluteNodeSizes) _nodeScale*=diag_len;
+ if(!_absoluteArcWidths) _arcWidthScale*=diag_len;
+ }
+
+ dim2::Box<double> bb;
+ for(NodeIt n(g);n!=INVALID;++n) {
+ double ns=_nodeSizes[n]*_nodeScale;
+ dim2::Point<double> p(ns,ns);
+ switch(_nodeShapes[n]) {
+ case CIRCLE:
+ case SQUARE:
+ case DIAMOND:
+ bb.add(p+mycoords[n]);
+ bb.add(-p+mycoords[n]);
+ break;
+ case MALE:
+ bb.add(-p+mycoords[n]);
+ bb.add(dim2::Point<double>(1.5*ns,1.5*std::sqrt(3.0)*ns)+mycoords[n]);
+ break;
+ case FEMALE:
+ bb.add(p+mycoords[n]);
+ bb.add(dim2::Point<double>(-ns,-3.01*ns)+mycoords[n]);
+ break;
+ }
+ }
+ if (bb.empty()) {
+ bb = dim2::Box<double>(dim2::Point<double>(0,0));
+ }
+
+ if(_scaleToA4)
+ os <<"%%BoundingBox: 0 0 596 842\n%%DocumentPaperSizes: a4\n";
+ else {
+ if(_preScale) {
+ //Rescale so that BoundingBox won't be neither to big nor too small.
+ while(bb.height()*_scale>1000||bb.width()*_scale>1000) _scale/=10;
+ while(bb.height()*_scale<100||bb.width()*_scale<100) _scale*=10;
+ }
+
+ os << "%%BoundingBox: "
+ << int(floor(bb.left() * _scale - _xBorder)) << ' '
+ << int(floor(bb.bottom() * _scale - _yBorder)) << ' '
+ << int(ceil(bb.right() * _scale + _xBorder)) << ' '
+ << int(ceil(bb.top() * _scale + _yBorder)) << '\n';
+ }
+
+ os << "%%EndComments\n";
+
+ //x1 y1 x2 y2 x3 y3 cr cg cb w
+ os << "/lb { setlinewidth setrgbcolor newpath moveto\n"
+ << " 4 2 roll 1 index 1 index curveto stroke } bind def\n";
+ os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke }"
+ << " bind def\n";
+ //x y r
+ os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath }"
+ << " bind def\n";
+ //x y r
+ os << "/sq { newpath 2 index 1 index add 2 index 2 index add moveto\n"
+ << " 2 index 1 index sub 2 index 2 index add lineto\n"
+ << " 2 index 1 index sub 2 index 2 index sub lineto\n"
+ << " 2 index 1 index add 2 index 2 index sub lineto\n"
+ << " closepath pop pop pop} bind def\n";
+ //x y r
+ os << "/di { newpath 2 index 1 index add 2 index moveto\n"
+ << " 2 index 2 index 2 index add lineto\n"
+ << " 2 index 1 index sub 2 index lineto\n"
+ << " 2 index 2 index 2 index sub lineto\n"
+ << " closepath pop pop pop} bind def\n";
+ // x y r cr cg cb
+ os << "/nc { 0 0 0 setrgbcolor 5 index 5 index 5 index c fill\n"
+ << " setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
+ << " } bind def\n";
+ os << "/nsq { 0 0 0 setrgbcolor 5 index 5 index 5 index sq fill\n"
+ << " setrgbcolor " << 1+_nodeBorderQuotient << " div sq fill\n"
+ << " } bind def\n";
+ os << "/ndi { 0 0 0 setrgbcolor 5 index 5 index 5 index di fill\n"
+ << " setrgbcolor " << 1+_nodeBorderQuotient << " div di fill\n"
+ << " } bind def\n";
+ os << "/nfemale { 0 0 0 setrgbcolor 3 index "
+ << _nodeBorderQuotient/(1+_nodeBorderQuotient)
+ << " 1.5 mul mul setlinewidth\n"
+ << " newpath 5 index 5 index moveto "
+ << "5 index 5 index 5 index 3.01 mul sub\n"
+ << " lineto 5 index 4 index .7 mul sub 5 index 5 index 2.2 mul sub"
+ << " moveto\n"
+ << " 5 index 4 index .7 mul add 5 index 5 index 2.2 mul sub lineto "
+ << "stroke\n"
+ << " 5 index 5 index 5 index c fill\n"
+ << " setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
+ << " } bind def\n";
+ os << "/nmale {\n"
+ << " 0 0 0 setrgbcolor 3 index "
+ << _nodeBorderQuotient/(1+_nodeBorderQuotient)
+ <<" 1.5 mul mul setlinewidth\n"
+ << " newpath 5 index 5 index moveto\n"
+ << " 5 index 4 index 1 mul 1.5 mul add\n"
+ << " 5 index 5 index 3 sqrt 1.5 mul mul add\n"
+ << " 1 index 1 index lineto\n"
+ << " 1 index 1 index 7 index sub moveto\n"
+ << " 1 index 1 index lineto\n"
+ << " exch 5 index 3 sqrt .5 mul mul sub exch 5 index .5 mul sub"
+ << " lineto\n"
+ << " stroke\n"
+ << " 5 index 5 index 5 index c fill\n"
+ << " setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
+ << " } bind def\n";
+
+
+ os << "/arrl " << _arrowLength << " def\n";
+ os << "/arrw " << _arrowWidth << " def\n";
+ // l dx_norm dy_norm
+ os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n";
+ //len w dx_norm dy_norm x1 y1 cr cg cb
+ os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx "
+ << "exch def\n"
+ << " /w exch def /len exch def\n"
+ //<< "0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
+ << " newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
+ << " len w sub arrl sub dx dy lrl\n"
+ << " arrw dy dx neg lrl\n"
+ << " dx arrl w add mul dy w 2 div arrw add mul sub\n"
+ << " dy arrl w add mul dx w 2 div arrw add mul add rlineto\n"
+ << " dx arrl w add mul neg dy w 2 div arrw add mul sub\n"
+ << " dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n"
+ << " arrw dy dx neg lrl\n"
+ << " len w sub arrl sub neg dx dy lrl\n"
+ << " closepath fill } bind def\n";
+ os << "/cshow { 2 index 2 index moveto dup stringwidth pop\n"
+ << " neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n";
+
+ os << "\ngsave\n";
+ if(_scaleToA4)
+ if(bb.height()>bb.width()) {
+ double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.height(),
+ (A4WIDTH-2*A4BORDER)/bb.width());
+ os << ((A4WIDTH -2*A4BORDER)-sc*bb.width())/2 + A4BORDER << ' '
+ << ((A4HEIGHT-2*A4BORDER)-sc*bb.height())/2 + A4BORDER
+ << " translate\n"
+ << sc << " dup scale\n"
+ << -bb.left() << ' ' << -bb.bottom() << " translate\n";
+ }
+ else {
+ double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.width(),
+ (A4WIDTH-2*A4BORDER)/bb.height());
+ os << ((A4WIDTH -2*A4BORDER)-sc*bb.height())/2 + A4BORDER << ' '
+ << ((A4HEIGHT-2*A4BORDER)-sc*bb.width())/2 + A4BORDER
+ << " translate\n"
+ << sc << " dup scale\n90 rotate\n"
+ << -bb.left() << ' ' << -bb.top() << " translate\n";
+ }
+ else if(_scale!=1.0) os << _scale << " dup scale\n";
+
+ if(_showArcs) {
+ os << "%Arcs:\ngsave\n";
+ if(_enableParallel) {
+ std::vector<Arc> el;
+ for(ArcIt e(g);e!=INVALID;++e)
+ if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
+ &&g.source(e)!=g.target(e))
+ el.push_back(e);
+ std::sort(el.begin(),el.end(),arcLess(g));
+
+ typename std::vector<Arc>::iterator j;
+ for(typename std::vector<Arc>::iterator i=el.begin();i!=el.end();i=j) {
+ for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
+
+ double sw=0;
+ for(typename std::vector<Arc>::iterator e=i;e!=j;++e)
+ sw+=_arcWidths[*e]*_arcWidthScale+_parArcDist;
+ sw-=_parArcDist;
+ sw/=-2.0;
+ dim2::Point<double>
+ dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]);
+ double l=std::sqrt(dvec.normSquare());
+ dim2::Point<double> d(dvec/std::max(l,EPSILON));
+ dim2::Point<double> m;
+// m=dim2::Point<double>(mycoords[g.target(*i)]+
+// mycoords[g.source(*i)])/2.0;
+
+// m=dim2::Point<double>(mycoords[g.source(*i)])+
+// dvec*(double(_nodeSizes[g.source(*i)])/
+// (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)]));
+
+ m=dim2::Point<double>(mycoords[g.source(*i)])+
+ d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0;
+
+ for(typename std::vector<Arc>::iterator e=i;e!=j;++e) {
+ sw+=_arcWidths[*e]*_arcWidthScale/2.0;
+ dim2::Point<double> mm=m+rot90(d)*sw/.75;
+ if(_drawArrows) {
+ int node_shape;
+ dim2::Point<double> s=mycoords[g.source(*e)];
+ dim2::Point<double> t=mycoords[g.target(*e)];
+ double rn=_nodeSizes[g.target(*e)]*_nodeScale;
+ node_shape=_nodeShapes[g.target(*e)];
+ dim2::Bezier3 bez(s,mm,mm,t);
+ double t1=0,t2=1;
+ for(int ii=0;ii<INTERPOL_PREC;++ii)
+ if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t2=(t1+t2)/2;
+ else t1=(t1+t2)/2;
+ dim2::Point<double> apoint=bez((t1+t2)/2);
+ rn = _arrowLength+_arcWidths[*e]*_arcWidthScale;
+ rn*=rn;
+ t2=(t1+t2)/2;t1=0;
+ for(int ii=0;ii<INTERPOL_PREC;++ii)
+ if((bez((t1+t2)/2)-apoint).normSquare()>rn) t1=(t1+t2)/2;
+ else t2=(t1+t2)/2;
+ dim2::Point<double> linend=bez((t1+t2)/2);
+ bez=bez.before((t1+t2)/2);
+// rn=_nodeSizes[g.source(*e)]*_nodeScale;
+// node_shape=_nodeShapes[g.source(*e)];
+// t1=0;t2=1;
+// for(int i=0;i<INTERPOL_PREC;++i)
+// if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape))
+// t1=(t1+t2)/2;
+// else t2=(t1+t2)/2;
+// bez=bez.after((t1+t2)/2);
+ os << _arcWidths[*e]*_arcWidthScale << " setlinewidth "
+ << _arcColors[*e].red() << ' '
+ << _arcColors[*e].green() << ' '
+ << _arcColors[*e].blue() << " setrgbcolor newpath\n"
+ << bez.p1.x << ' ' << bez.p1.y << " moveto\n"
+ << bez.p2.x << ' ' << bez.p2.y << ' '
+ << bez.p3.x << ' ' << bez.p3.y << ' '
+ << bez.p4.x << ' ' << bez.p4.y << " curveto stroke\n";
+ dim2::Point<double> dd(rot90(linend-apoint));
+ dd*=(.5*_arcWidths[*e]*_arcWidthScale+_arrowWidth)/
+ std::sqrt(dd.normSquare());
+ os << "newpath " << psOut(apoint) << " moveto "
+ << psOut(linend+dd) << " lineto "
+ << psOut(linend-dd) << " lineto closepath fill\n";
+ }
+ else {
+ os << mycoords[g.source(*e)].x << ' '
+ << mycoords[g.source(*e)].y << ' '
+ << mm.x << ' ' << mm.y << ' '
+ << mycoords[g.target(*e)].x << ' '
+ << mycoords[g.target(*e)].y << ' '
+ << _arcColors[*e].red() << ' '
+ << _arcColors[*e].green() << ' '
+ << _arcColors[*e].blue() << ' '
+ << _arcWidths[*e]*_arcWidthScale << " lb\n";
+ }
+ sw+=_arcWidths[*e]*_arcWidthScale/2.0+_parArcDist;
+ }
+ }
+ }
+ else for(ArcIt e(g);e!=INVALID;++e)
+ if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
+ &&g.source(e)!=g.target(e)) {
+ if(_drawArrows) {
+ dim2::Point<double> d(mycoords[g.target(e)]-mycoords[g.source(e)]);
+ double rn=_nodeSizes[g.target(e)]*_nodeScale;
+ int node_shape=_nodeShapes[g.target(e)];
+ double t1=0,t2=1;
+ for(int i=0;i<INTERPOL_PREC;++i)
+ if(isInsideNode((-(t1+t2)/2)*d,rn,node_shape)) t1=(t1+t2)/2;
+ else t2=(t1+t2)/2;
+ double l=std::sqrt(d.normSquare());
+ d/=l;
+
+ os << l*(1-(t1+t2)/2) << ' '
+ << _arcWidths[e]*_arcWidthScale << ' '
+ << d.x << ' ' << d.y << ' '
+ << mycoords[g.source(e)].x << ' '
+ << mycoords[g.source(e)].y << ' '
+ << _arcColors[e].red() << ' '
+ << _arcColors[e].green() << ' '
+ << _arcColors[e].blue() << " arr\n";
+ }
+ else os << mycoords[g.source(e)].x << ' '
+ << mycoords[g.source(e)].y << ' '
+ << mycoords[g.target(e)].x << ' '
+ << mycoords[g.target(e)].y << ' '
+ << _arcColors[e].red() << ' '
+ << _arcColors[e].green() << ' '
+ << _arcColors[e].blue() << ' '
+ << _arcWidths[e]*_arcWidthScale << " l\n";
+ }
+ os << "grestore\n";
+ }
+ if(_showNodes) {
+ os << "%Nodes:\ngsave\n";
+ for(NodeIt n(g);n!=INVALID;++n) {
+ os << mycoords[n].x << ' ' << mycoords[n].y << ' '
+ << _nodeSizes[n]*_nodeScale << ' '
+ << _nodeColors[n].red() << ' '
+ << _nodeColors[n].green() << ' '
+ << _nodeColors[n].blue() << ' ';
+ switch(_nodeShapes[n]) {
+ case CIRCLE:
+ os<< "nc";break;
+ case SQUARE:
+ os<< "nsq";break;
+ case DIAMOND:
+ os<< "ndi";break;
+ case MALE:
+ os<< "nmale";break;
+ case FEMALE:
+ os<< "nfemale";break;
+ }
+ os<<'\n';
+ }
+ os << "grestore\n";
+ }
+ if(_showNodeText) {
+ os << "%Node texts:\ngsave\n";
+ os << "/fosi " << _nodeTextSize << " def\n";
+ os << "(Helvetica) findfont fosi scalefont setfont\n";
+ for(NodeIt n(g);n!=INVALID;++n) {
+ switch(_nodeTextColorType) {
+ case DIST_COL:
+ os << psOut(distantColor(_nodeColors[n])) << " setrgbcolor\n";
+ break;
+ case DIST_BW:
+ os << psOut(distantBW(_nodeColors[n])) << " setrgbcolor\n";
+ break;
+ case CUST_COL:
+ os << psOut(distantColor(_nodeTextColors[n])) << " setrgbcolor\n";
+ break;
+ default:
+ os << "0 0 0 setrgbcolor\n";
+ }
+ os << mycoords[n].x << ' ' << mycoords[n].y
+ << " (" << _nodeTexts[n] << ") cshow\n";
+ }
+ os << "grestore\n";
+ }
+ if(_showNodePsText) {
+ os << "%Node PS blocks:\ngsave\n";
+ for(NodeIt n(g);n!=INVALID;++n)
+ os << mycoords[n].x << ' ' << mycoords[n].y
+ << " moveto\n" << _nodePsTexts[n] << "\n";
+ os << "grestore\n";
+ }
+
+ os << "grestore\nshowpage\n";
+
+ //CleanUp:
+ if(_pleaseRemoveOsStream) {delete &os;}
+ }
+
+ ///\name Aliases
+ ///These are just some aliases to other parameter setting functions.
+
+ ///@{
+
+ ///An alias for arcWidths()
+ template<class X> GraphToEps<ArcWidthsTraits<X> > edgeWidths(const X &x)
+ {
+ return arcWidths(x);
+ }
+
+ ///An alias for arcColors()
+ template<class X> GraphToEps<ArcColorsTraits<X> >
+ edgeColors(const X &x)
+ {
+ return arcColors(x);
+ }
+
+ ///An alias for arcWidthScale()
+ GraphToEps<T> &edgeWidthScale(double d) {return arcWidthScale(d);}
+
+ ///An alias for autoArcWidthScale()
+ GraphToEps<T> &autoEdgeWidthScale(bool b=true)
+ {
+ return autoArcWidthScale(b);
+ }
+
+ ///An alias for absoluteArcWidths()
+ GraphToEps<T> &absoluteEdgeWidths(bool b=true)
+ {
+ return absoluteArcWidths(b);
+ }
+
+ ///An alias for parArcDist()
+ GraphToEps<T> &parEdgeDist(double d) {return parArcDist(d);}
+
+ ///An alias for hideArcs()
+ GraphToEps<T> &hideEdges(bool b=true) {return hideArcs(b);}
+
+ ///@}
+};
+
+template<class T>
+const int GraphToEps<T>::INTERPOL_PREC = 20;
+template<class T>
+const double GraphToEps<T>::A4HEIGHT = 841.8897637795276;
+template<class T>
+const double GraphToEps<T>::A4WIDTH = 595.275590551181;
+template<class T>
+const double GraphToEps<T>::A4BORDER = 15;
+
+
+///Generates an EPS file from a graph
+
+///\ingroup eps_io
+///Generates an EPS file from a graph.
+///\param g Reference to the graph to be printed.
+///\param os Reference to the output stream.
+///By default, it is <tt>std::cout</tt>.
+///
+///This function also has a lot of
+///\ref named-templ-func-param "named parameters",
+///they are declared as the members of class \ref GraphToEps. The following
+///example shows how to use these parameters.
+///\code
+/// graphToEps(g,os).scale(10).coords(coords)
+/// .nodeScale(2).nodeSizes(sizes)
+/// .arcWidthScale(.4).run();
+///\endcode
+///
+///For more detailed examples, see the \ref graph_to_eps_demo.cc demo file.
+///
+///\warning Don't forget to put the \ref GraphToEps::run() "run()"
+///to the end of the parameter list.
+///\sa GraphToEps
+///\sa graphToEps(GR &g, const char *file_name)
+template<class GR>
+GraphToEps<DefaultGraphToEpsTraits<GR> >
+graphToEps(GR &g, std::ostream& os=std::cout)
+{
+ return
+ GraphToEps<DefaultGraphToEpsTraits<GR> >(DefaultGraphToEpsTraits<GR>(g,os));
+}
+
+///Generates an EPS file from a graph
+
+///\ingroup eps_io
+///This function does the same as
+///\ref graphToEps(GR &g,std::ostream& os)
+///but it writes its output into the file \c file_name
+///instead of a stream.
+///\sa graphToEps(GR &g, std::ostream& os)
+template<class GR>
+GraphToEps<DefaultGraphToEpsTraits<GR> >
+graphToEps(GR &g,const char *file_name)
+{
+ std::ostream* os = new std::ofstream(file_name);
+ if (!(*os)) {
+ delete os;
+ throw IoError("Cannot write file", file_name);
+ }
+ return GraphToEps<DefaultGraphToEpsTraits<GR> >
+ (DefaultGraphToEpsTraits<GR>(g,*os,true));
+}
+
+///Generates an EPS file from a graph
+
+///\ingroup eps_io
+///This function does the same as
+///\ref graphToEps(GR &g,std::ostream& os)
+///but it writes its output into the file \c file_name
+///instead of a stream.
+///\sa graphToEps(GR &g, std::ostream& os)
+template<class GR>
+GraphToEps<DefaultGraphToEpsTraits<GR> >
+graphToEps(GR &g,const std::string& file_name)
+{
+ std::ostream* os = new std::ofstream(file_name.c_str());
+ if (!(*os)) {
+ delete os;
+ throw IoError("Cannot write file", file_name);
+ }
+ return GraphToEps<DefaultGraphToEpsTraits<GR> >
+ (DefaultGraphToEpsTraits<GR>(g,*os,true));
+}
+
+} //END OF NAMESPACE LEMON
+
+#endif // LEMON_GRAPH_TO_EPS_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/greedy_tsp.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/greedy_tsp.h
new file mode 100644
index 00000000000..95461717ae0
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/greedy_tsp.h
@@ -0,0 +1,251 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_GREEDY_TSP_H
+#define LEMON_GREEDY_TSP_H
+
+/// \ingroup tsp
+/// \file
+/// \brief Greedy algorithm for symmetric TSP
+
+#include <vector>
+#include <algorithm>
+#include <lemon/full_graph.h>
+#include <lemon/unionfind.h>
+
+namespace lemon {
+
+ /// \ingroup tsp
+ ///
+ /// \brief Greedy algorithm for symmetric TSP.
+ ///
+ /// GreedyTsp implements the greedy heuristic for solving
+ /// symmetric \ref tsp "TSP".
+ ///
+ /// This algorithm is quite similar to the \ref NearestNeighborTsp
+ /// "nearest neighbor" heuristic, but it maintains a set of disjoint paths.
+ /// At each step, the shortest possible edge is added to these paths
+ /// as long as it does not create a cycle of less than n edges and it does
+ /// not increase the degree of any node above two.
+ ///
+ /// This method runs in O(n<sup>2</sup>) time.
+ /// It quickly finds a relatively short tour for most TSP instances,
+ /// but it could also yield a really bad (or even the worst) solution
+ /// in special cases.
+ ///
+ /// \tparam CM Type of the cost map.
+ template <typename CM>
+ class GreedyTsp
+ {
+ public:
+
+ /// Type of the cost map
+ typedef CM CostMap;
+ /// Type of the edge costs
+ typedef typename CM::Value Cost;
+
+ private:
+
+ GRAPH_TYPEDEFS(FullGraph);
+
+ const FullGraph &_gr;
+ const CostMap &_cost;
+ Cost _sum;
+ std::vector<Node> _path;
+
+ private:
+
+ // Functor class to compare edges by their costs
+ class EdgeComp {
+ private:
+ const CostMap &_cost;
+
+ public:
+ EdgeComp(const CostMap &cost) : _cost(cost) {}
+
+ bool operator()(const Edge &a, const Edge &b) const {
+ return _cost[a] < _cost[b];
+ }
+ };
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ /// \param gr The \ref FullGraph "full graph" the algorithm runs on.
+ /// \param cost The cost map.
+ GreedyTsp(const FullGraph &gr, const CostMap &cost)
+ : _gr(gr), _cost(cost) {}
+
+ /// \name Execution Control
+ /// @{
+
+ /// \brief Runs the algorithm.
+ ///
+ /// This function runs the algorithm.
+ ///
+ /// \return The total cost of the found tour.
+ Cost run() {
+ _path.clear();
+
+ if (_gr.nodeNum() == 0) return _sum = 0;
+ else if (_gr.nodeNum() == 1) {
+ _path.push_back(_gr(0));
+ return _sum = 0;
+ }
+
+ std::vector<int> plist;
+ plist.resize(_gr.nodeNum()*2, -1);
+
+ std::vector<Edge> sorted_edges;
+ sorted_edges.reserve(_gr.edgeNum());
+ for (EdgeIt e(_gr); e != INVALID; ++e)
+ sorted_edges.push_back(e);
+ std::sort(sorted_edges.begin(), sorted_edges.end(), EdgeComp(_cost));
+
+ FullGraph::NodeMap<int> item_int_map(_gr);
+ UnionFind<FullGraph::NodeMap<int> > union_find(item_int_map);
+ for (NodeIt n(_gr); n != INVALID; ++n)
+ union_find.insert(n);
+
+ FullGraph::NodeMap<int> degree(_gr, 0);
+
+ int nodesNum = 0, i = 0;
+ while (nodesNum != _gr.nodeNum()-1) {
+ Edge e = sorted_edges[i++];
+ Node u = _gr.u(e),
+ v = _gr.v(e);
+
+ if (degree[u] <= 1 && degree[v] <= 1) {
+ if (union_find.join(u, v)) {
+ const int uid = _gr.id(u),
+ vid = _gr.id(v);
+
+ plist[uid*2 + degree[u]] = vid;
+ plist[vid*2 + degree[v]] = uid;
+
+ ++degree[u];
+ ++degree[v];
+ ++nodesNum;
+ }
+ }
+ }
+
+ for (int i=0, n=-1; i<_gr.nodeNum()*2; ++i) {
+ if (plist[i] == -1) {
+ if (n==-1) {
+ n = i;
+ } else {
+ plist[n] = i/2;
+ plist[i] = n/2;
+ break;
+ }
+ }
+ }
+
+ for (int i=0, next=0, last=-1; i!=_gr.nodeNum(); ++i) {
+ _path.push_back(_gr.nodeFromId(next));
+ if (plist[2*next] != last) {
+ last = next;
+ next = plist[2*next];
+ } else {
+ last = next;
+ next = plist[2*next+1];
+ }
+ }
+
+ _sum = _cost[_gr.edge(_path.back(), _path.front())];
+ for (int i = 0; i < int(_path.size())-1; ++i) {
+ _sum += _cost[_gr.edge(_path[i], _path[i+1])];
+ }
+
+ return _sum;
+ }
+
+ /// @}
+
+ /// \name Query Functions
+ /// @{
+
+ /// \brief The total cost of the found tour.
+ ///
+ /// This function returns the total cost of the found tour.
+ ///
+ /// \pre run() must be called before using this function.
+ Cost tourCost() const {
+ return _sum;
+ }
+
+ /// \brief Returns a const reference to the node sequence of the
+ /// found tour.
+ ///
+ /// This function returns a const reference to a vector
+ /// that stores the node sequence of the found tour.
+ ///
+ /// \pre run() must be called before using this function.
+ const std::vector<Node>& tourNodes() const {
+ return _path;
+ }
+
+ /// \brief Gives back the node sequence of the found tour.
+ ///
+ /// This function copies the node sequence of the found tour into
+ /// an STL container through the given output iterator. The
+ /// <tt>value_type</tt> of the container must be <tt>FullGraph::Node</tt>.
+ /// For example,
+ /// \code
+ /// std::vector<FullGraph::Node> nodes(countNodes(graph));
+ /// tsp.tourNodes(nodes.begin());
+ /// \endcode
+ /// or
+ /// \code
+ /// std::list<FullGraph::Node> nodes;
+ /// tsp.tourNodes(std::back_inserter(nodes));
+ /// \endcode
+ ///
+ /// \pre run() must be called before using this function.
+ template <typename Iterator>
+ void tourNodes(Iterator out) const {
+ std::copy(_path.begin(), _path.end(), out);
+ }
+
+ /// \brief Gives back the found tour as a path.
+ ///
+ /// This function copies the found tour as a list of arcs/edges into
+ /// the given \ref lemon::concepts::Path "path structure".
+ ///
+ /// \pre run() must be called before using this function.
+ template <typename Path>
+ void tour(Path &path) const {
+ path.clear();
+ for (int i = 0; i < int(_path.size()) - 1; ++i) {
+ path.addBack(_gr.arc(_path[i], _path[i+1]));
+ }
+ if (int(_path.size()) >= 2) {
+ path.addBack(_gr.arc(_path.back(), _path.front()));
+ }
+ }
+
+ /// @}
+
+ };
+
+}; // namespace lemon
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/grid_graph.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/grid_graph.h
new file mode 100644
index 00000000000..a3dff0f612f
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/grid_graph.h
@@ -0,0 +1,699 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef GRID_GRAPH_H
+#define GRID_GRAPH_H
+
+#include <lemon/core.h>
+#include <lemon/bits/graph_extender.h>
+#include <lemon/dim2.h>
+#include <lemon/assert.h>
+
+///\ingroup graphs
+///\file
+///\brief GridGraph class.
+
+namespace lemon {
+
+ class GridGraphBase {
+
+ public:
+
+ typedef GridGraphBase Graph;
+
+ class Node;
+ class Edge;
+ class Arc;
+
+ public:
+
+ GridGraphBase() {}
+
+ protected:
+
+ void construct(int width, int height) {
+ _width = width; _height = height;
+ _node_num = width * height;
+ _edge_num = 2 * _node_num - width - height;
+ _edge_limit = _node_num - _width;
+ }
+
+ public:
+
+ Node operator()(int i, int j) const {
+ LEMON_DEBUG(0 <= i && i < _width &&
+ 0 <= j && j < _height, "Index out of range");
+ return Node(i + j * _width);
+ }
+
+ int col(Node n) const {
+ return n._id % _width;
+ }
+
+ int row(Node n) const {
+ return n._id / _width;
+ }
+
+ dim2::Point<int> pos(Node n) const {
+ return dim2::Point<int>(col(n), row(n));
+ }
+
+ int width() const {
+ return _width;
+ }
+
+ int height() const {
+ return _height;
+ }
+
+ typedef True NodeNumTag;
+ typedef True EdgeNumTag;
+ typedef True ArcNumTag;
+
+ int nodeNum() const { return _node_num; }
+ int edgeNum() const { return _edge_num; }
+ int arcNum() const { return 2 * _edge_num; }
+
+ Node u(Edge edge) const {
+ if (edge._id < _edge_limit) {
+ return edge._id;
+ } else {
+ return (edge._id - _edge_limit) % (_width - 1) +
+ (edge._id - _edge_limit) / (_width - 1) * _width;
+ }
+ }
+
+ Node v(Edge edge) const {
+ if (edge._id < _edge_limit) {
+ return edge._id + _width;
+ } else {
+ return (edge._id - _edge_limit) % (_width - 1) +
+ (edge._id - _edge_limit) / (_width - 1) * _width + 1;
+ }
+ }
+
+ Node source(Arc arc) const {
+ return (arc._id & 1) == 1 ? u(arc) : v(arc);
+ }
+
+ Node target(Arc arc) const {
+ return (arc._id & 1) == 1 ? v(arc) : u(arc);
+ }
+
+ static int id(Node node) { return node._id; }
+ static int id(Edge edge) { return edge._id; }
+ static int id(Arc arc) { return arc._id; }
+
+ int maxNodeId() const { return _node_num - 1; }
+ int maxEdgeId() const { return _edge_num - 1; }
+ int maxArcId() const { return 2 * _edge_num - 1; }
+
+ static Node nodeFromId(int id) { return Node(id);}
+ static Edge edgeFromId(int id) { return Edge(id);}
+ static Arc arcFromId(int id) { return Arc(id);}
+
+ typedef True FindEdgeTag;
+ typedef True FindArcTag;
+
+ Edge findEdge(Node u, Node v, Edge prev = INVALID) const {
+ if (prev != INVALID) return INVALID;
+ if (v._id > u._id) {
+ if (v._id - u._id == _width)
+ return Edge(u._id);
+ if (v._id - u._id == 1 && u._id % _width < _width - 1) {
+ return Edge(u._id / _width * (_width - 1) +
+ u._id % _width + _edge_limit);
+ }
+ } else {
+ if (u._id - v._id == _width)
+ return Edge(v._id);
+ if (u._id - v._id == 1 && v._id % _width < _width - 1) {
+ return Edge(v._id / _width * (_width - 1) +
+ v._id % _width + _edge_limit);
+ }
+ }
+ return INVALID;
+ }
+
+ Arc findArc(Node u, Node v, Arc prev = INVALID) const {
+ if (prev != INVALID) return INVALID;
+ if (v._id > u._id) {
+ if (v._id - u._id == _width)
+ return Arc((u._id << 1) | 1);
+ if (v._id - u._id == 1 && u._id % _width < _width - 1) {
+ return Arc(((u._id / _width * (_width - 1) +
+ u._id % _width + _edge_limit) << 1) | 1);
+ }
+ } else {
+ if (u._id - v._id == _width)
+ return Arc(v._id << 1);
+ if (u._id - v._id == 1 && v._id % _width < _width - 1) {
+ return Arc((v._id / _width * (_width - 1) +
+ v._id % _width + _edge_limit) << 1);
+ }
+ }
+ return INVALID;
+ }
+
+ class Node {
+ friend class GridGraphBase;
+
+ protected:
+ int _id;
+ Node(int id) : _id(id) {}
+ public:
+ Node() {}
+ Node (Invalid) : _id(-1) {}
+ bool operator==(const Node node) const {return _id == node._id;}
+ bool operator!=(const Node node) const {return _id != node._id;}
+ bool operator<(const Node node) const {return _id < node._id;}
+ };
+
+ class Edge {
+ friend class GridGraphBase;
+ friend class Arc;
+
+ protected:
+ int _id;
+
+ Edge(int id) : _id(id) {}
+
+ public:
+ Edge() {}
+ Edge (Invalid) : _id(-1) {}
+ bool operator==(const Edge edge) const {return _id == edge._id;}
+ bool operator!=(const Edge edge) const {return _id != edge._id;}
+ bool operator<(const Edge edge) const {return _id < edge._id;}
+ };
+
+ class Arc {
+ friend class GridGraphBase;
+
+ protected:
+ int _id;
+
+ Arc(int id) : _id(id) {}
+
+ public:
+ Arc() {}
+ Arc (Invalid) : _id(-1) {}
+ operator Edge() const { return _id != -1 ? Edge(_id >> 1) : INVALID; }
+ bool operator==(const Arc arc) const {return _id == arc._id;}
+ bool operator!=(const Arc arc) const {return _id != arc._id;}
+ bool operator<(const Arc arc) const {return _id < arc._id;}
+ };
+
+ static bool direction(Arc arc) {
+ return (arc._id & 1) == 1;
+ }
+
+ static Arc direct(Edge edge, bool dir) {
+ return Arc((edge._id << 1) | (dir ? 1 : 0));
+ }
+
+ void first(Node& node) const {
+ node._id = _node_num - 1;
+ }
+
+ static void next(Node& node) {
+ --node._id;
+ }
+
+ void first(Edge& edge) const {
+ edge._id = _edge_num - 1;
+ }
+
+ static void next(Edge& edge) {
+ --edge._id;
+ }
+
+ void first(Arc& arc) const {
+ arc._id = 2 * _edge_num - 1;
+ }
+
+ static void next(Arc& arc) {
+ --arc._id;
+ }
+
+ void firstOut(Arc& arc, const Node& node) const {
+ if (node._id % _width < _width - 1) {
+ arc._id = (_edge_limit + node._id % _width +
+ (node._id / _width) * (_width - 1)) << 1 | 1;
+ return;
+ }
+ if (node._id < _node_num - _width) {
+ arc._id = node._id << 1 | 1;
+ return;
+ }
+ if (node._id % _width > 0) {
+ arc._id = (_edge_limit + node._id % _width +
+ (node._id / _width) * (_width - 1) - 1) << 1;
+ return;
+ }
+ if (node._id >= _width) {
+ arc._id = (node._id - _width) << 1;
+ return;
+ }
+ arc._id = -1;
+ }
+
+ void nextOut(Arc& arc) const {
+ int nid = arc._id >> 1;
+ if ((arc._id & 1) == 1) {
+ if (nid >= _edge_limit) {
+ nid = (nid - _edge_limit) % (_width - 1) +
+ (nid - _edge_limit) / (_width - 1) * _width;
+ if (nid < _node_num - _width) {
+ arc._id = nid << 1 | 1;
+ return;
+ }
+ }
+ if (nid % _width > 0) {
+ arc._id = (_edge_limit + nid % _width +
+ (nid / _width) * (_width - 1) - 1) << 1;
+ return;
+ }
+ if (nid >= _width) {
+ arc._id = (nid - _width) << 1;
+ return;
+ }
+ } else {
+ if (nid >= _edge_limit) {
+ nid = (nid - _edge_limit) % (_width - 1) +
+ (nid - _edge_limit) / (_width - 1) * _width + 1;
+ if (nid >= _width) {
+ arc._id = (nid - _width) << 1;
+ return;
+ }
+ }
+ }
+ arc._id = -1;
+ }
+
+ void firstIn(Arc& arc, const Node& node) const {
+ if (node._id % _width < _width - 1) {
+ arc._id = (_edge_limit + node._id % _width +
+ (node._id / _width) * (_width - 1)) << 1;
+ return;
+ }
+ if (node._id < _node_num - _width) {
+ arc._id = node._id << 1;
+ return;
+ }
+ if (node._id % _width > 0) {
+ arc._id = (_edge_limit + node._id % _width +
+ (node._id / _width) * (_width - 1) - 1) << 1 | 1;
+ return;
+ }
+ if (node._id >= _width) {
+ arc._id = (node._id - _width) << 1 | 1;
+ return;
+ }
+ arc._id = -1;
+ }
+
+ void nextIn(Arc& arc) const {
+ int nid = arc._id >> 1;
+ if ((arc._id & 1) == 0) {
+ if (nid >= _edge_limit) {
+ nid = (nid - _edge_limit) % (_width - 1) +
+ (nid - _edge_limit) / (_width - 1) * _width;
+ if (nid < _node_num - _width) {
+ arc._id = nid << 1;
+ return;
+ }
+ }
+ if (nid % _width > 0) {
+ arc._id = (_edge_limit + nid % _width +
+ (nid / _width) * (_width - 1) - 1) << 1 | 1;
+ return;
+ }
+ if (nid >= _width) {
+ arc._id = (nid - _width) << 1 | 1;
+ return;
+ }
+ } else {
+ if (nid >= _edge_limit) {
+ nid = (nid - _edge_limit) % (_width - 1) +
+ (nid - _edge_limit) / (_width - 1) * _width + 1;
+ if (nid >= _width) {
+ arc._id = (nid - _width) << 1 | 1;
+ return;
+ }
+ }
+ }
+ arc._id = -1;
+ }
+
+ void firstInc(Edge& edge, bool& dir, const Node& node) const {
+ if (node._id % _width < _width - 1) {
+ edge._id = _edge_limit + node._id % _width +
+ (node._id / _width) * (_width - 1);
+ dir = true;
+ return;
+ }
+ if (node._id < _node_num - _width) {
+ edge._id = node._id;
+ dir = true;
+ return;
+ }
+ if (node._id % _width > 0) {
+ edge._id = _edge_limit + node._id % _width +
+ (node._id / _width) * (_width - 1) - 1;
+ dir = false;
+ return;
+ }
+ if (node._id >= _width) {
+ edge._id = node._id - _width;
+ dir = false;
+ return;
+ }
+ edge._id = -1;
+ dir = true;
+ }
+
+ void nextInc(Edge& edge, bool& dir) const {
+ int nid = edge._id;
+ if (dir) {
+ if (nid >= _edge_limit) {
+ nid = (nid - _edge_limit) % (_width - 1) +
+ (nid - _edge_limit) / (_width - 1) * _width;
+ if (nid < _node_num - _width) {
+ edge._id = nid;
+ return;
+ }
+ }
+ if (nid % _width > 0) {
+ edge._id = _edge_limit + nid % _width +
+ (nid / _width) * (_width - 1) - 1;
+ dir = false;
+ return;
+ }
+ if (nid >= _width) {
+ edge._id = nid - _width;
+ dir = false;
+ return;
+ }
+ } else {
+ if (nid >= _edge_limit) {
+ nid = (nid - _edge_limit) % (_width - 1) +
+ (nid - _edge_limit) / (_width - 1) * _width + 1;
+ if (nid >= _width) {
+ edge._id = nid - _width;
+ return;
+ }
+ }
+ }
+ edge._id = -1;
+ dir = true;
+ }
+
+ Arc right(Node n) const {
+ if (n._id % _width < _width - 1) {
+ return Arc(((_edge_limit + n._id % _width +
+ (n._id / _width) * (_width - 1)) << 1) | 1);
+ } else {
+ return INVALID;
+ }
+ }
+
+ Arc left(Node n) const {
+ if (n._id % _width > 0) {
+ return Arc((_edge_limit + n._id % _width +
+ (n._id / _width) * (_width - 1) - 1) << 1);
+ } else {
+ return INVALID;
+ }
+ }
+
+ Arc up(Node n) const {
+ if (n._id < _edge_limit) {
+ return Arc((n._id << 1) | 1);
+ } else {
+ return INVALID;
+ }
+ }
+
+ Arc down(Node n) const {
+ if (n._id >= _width) {
+ return Arc((n._id - _width) << 1);
+ } else {
+ return INVALID;
+ }
+ }
+
+ private:
+ int _width, _height;
+ int _node_num, _edge_num;
+ int _edge_limit;
+ };
+
+
+ typedef GraphExtender<GridGraphBase> ExtendedGridGraphBase;
+
+ /// \ingroup graphs
+ ///
+ /// \brief Grid graph class
+ ///
+ /// GridGraph implements a special graph type. The nodes of the
+ /// graph can be indexed by two integer values \c (i,j) where \c i is
+ /// in the range <tt>[0..width()-1]</tt> and j is in the range
+ /// <tt>[0..height()-1]</tt>. Two nodes are connected in the graph if
+ /// the indices differ exactly on one position and the difference is
+ /// also exactly one. The nodes of the graph can be obtained by position
+ /// using the \c operator()() function and the indices of the nodes can
+ /// be obtained using \c pos(), \c col() and \c row() members. The outgoing
+ /// arcs can be retrieved with the \c right(), \c up(), \c left()
+ /// and \c down() functions, where the bottom-left corner is the
+ /// origin.
+ ///
+ /// This class is completely static and it needs constant memory space.
+ /// Thus you can neither add nor delete nodes or edges, however
+ /// the structure can be resized using resize().
+ ///
+ /// \image html grid_graph.png
+ /// \image latex grid_graph.eps "Grid graph" width=\textwidth
+ ///
+ /// A short example about the basic usage:
+ ///\code
+ /// GridGraph graph(rows, cols);
+ /// GridGraph::NodeMap<int> val(graph);
+ /// for (int i = 0; i < graph.width(); ++i) {
+ /// for (int j = 0; j < graph.height(); ++j) {
+ /// val[graph(i, j)] = i + j;
+ /// }
+ /// }
+ ///\endcode
+ ///
+ /// This type fully conforms to the \ref concepts::Graph "Graph concept".
+ /// Most of its member functions and nested classes are documented
+ /// only in the concept class.
+ ///
+ /// This class provides constant time counting for nodes, edges and arcs.
+ class GridGraph : public ExtendedGridGraphBase {
+ typedef ExtendedGridGraphBase Parent;
+
+ public:
+
+ /// \brief Map to get the indices of the nodes as \ref dim2::Point
+ /// "dim2::Point<int>".
+ ///
+ /// Map to get the indices of the nodes as \ref dim2::Point
+ /// "dim2::Point<int>".
+ class IndexMap {
+ public:
+ /// \brief The key type of the map
+ typedef GridGraph::Node Key;
+ /// \brief The value type of the map
+ typedef dim2::Point<int> Value;
+
+ /// \brief Constructor
+ IndexMap(const GridGraph& graph) : _graph(graph) {}
+
+ /// \brief The subscript operator
+ Value operator[](Key key) const {
+ return _graph.pos(key);
+ }
+
+ private:
+ const GridGraph& _graph;
+ };
+
+ /// \brief Map to get the column of the nodes.
+ ///
+ /// Map to get the column of the nodes.
+ class ColMap {
+ public:
+ /// \brief The key type of the map
+ typedef GridGraph::Node Key;
+ /// \brief The value type of the map
+ typedef int Value;
+
+ /// \brief Constructor
+ ColMap(const GridGraph& graph) : _graph(graph) {}
+
+ /// \brief The subscript operator
+ Value operator[](Key key) const {
+ return _graph.col(key);
+ }
+
+ private:
+ const GridGraph& _graph;
+ };
+
+ /// \brief Map to get the row of the nodes.
+ ///
+ /// Map to get the row of the nodes.
+ class RowMap {
+ public:
+ /// \brief The key type of the map
+ typedef GridGraph::Node Key;
+ /// \brief The value type of the map
+ typedef int Value;
+
+ /// \brief Constructor
+ RowMap(const GridGraph& graph) : _graph(graph) {}
+
+ /// \brief The subscript operator
+ Value operator[](Key key) const {
+ return _graph.row(key);
+ }
+
+ private:
+ const GridGraph& _graph;
+ };
+
+ /// \brief Constructor
+ ///
+ /// Construct a grid graph with the given size.
+ GridGraph(int width, int height) { construct(width, height); }
+
+ /// \brief Resizes the graph
+ ///
+ /// This function resizes the graph. It fully destroys and
+ /// rebuilds the structure, therefore the maps of the graph will be
+ /// reallocated automatically and the previous values will be lost.
+ void resize(int width, int height) {
+ Parent::notifier(Arc()).clear();
+ Parent::notifier(Edge()).clear();
+ Parent::notifier(Node()).clear();
+ construct(width, height);
+ Parent::notifier(Node()).build();
+ Parent::notifier(Edge()).build();
+ Parent::notifier(Arc()).build();
+ }
+
+ /// \brief The node on the given position.
+ ///
+ /// Gives back the node on the given position.
+ Node operator()(int i, int j) const {
+ return Parent::operator()(i, j);
+ }
+
+ /// \brief The column index of the node.
+ ///
+ /// Gives back the column index of the node.
+ int col(Node n) const {
+ return Parent::col(n);
+ }
+
+ /// \brief The row index of the node.
+ ///
+ /// Gives back the row index of the node.
+ int row(Node n) const {
+ return Parent::row(n);
+ }
+
+ /// \brief The position of the node.
+ ///
+ /// Gives back the position of the node, ie. the <tt>(col,row)</tt> pair.
+ dim2::Point<int> pos(Node n) const {
+ return Parent::pos(n);
+ }
+
+ /// \brief The number of the columns.
+ ///
+ /// Gives back the number of the columns.
+ int width() const {
+ return Parent::width();
+ }
+
+ /// \brief The number of the rows.
+ ///
+ /// Gives back the number of the rows.
+ int height() const {
+ return Parent::height();
+ }
+
+ /// \brief The arc goes right from the node.
+ ///
+ /// Gives back the arc goes right from the node. If there is not
+ /// outgoing arc then it gives back INVALID.
+ Arc right(Node n) const {
+ return Parent::right(n);
+ }
+
+ /// \brief The arc goes left from the node.
+ ///
+ /// Gives back the arc goes left from the node. If there is not
+ /// outgoing arc then it gives back INVALID.
+ Arc left(Node n) const {
+ return Parent::left(n);
+ }
+
+ /// \brief The arc goes up from the node.
+ ///
+ /// Gives back the arc goes up from the node. If there is not
+ /// outgoing arc then it gives back INVALID.
+ Arc up(Node n) const {
+ return Parent::up(n);
+ }
+
+ /// \brief The arc goes down from the node.
+ ///
+ /// Gives back the arc goes down from the node. If there is not
+ /// outgoing arc then it gives back INVALID.
+ Arc down(Node n) const {
+ return Parent::down(n);
+ }
+
+ /// \brief Index map of the grid graph
+ ///
+ /// Just returns an IndexMap for the grid graph.
+ IndexMap indexMap() const {
+ return IndexMap(*this);
+ }
+
+ /// \brief Row map of the grid graph
+ ///
+ /// Just returns a RowMap for the grid graph.
+ RowMap rowMap() const {
+ return RowMap(*this);
+ }
+
+ /// \brief Column map of the grid graph
+ ///
+ /// Just returns a ColMap for the grid graph.
+ ColMap colMap() const {
+ return ColMap(*this);
+ }
+
+ };
+
+}
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/grosso_locatelli_pullan_mc.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/grosso_locatelli_pullan_mc.h
new file mode 100644
index 00000000000..669e1fa3298
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/grosso_locatelli_pullan_mc.h
@@ -0,0 +1,840 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_GROSSO_LOCATELLI_PULLAN_MC_H
+#define LEMON_GROSSO_LOCATELLI_PULLAN_MC_H
+
+/// \ingroup approx_algs
+///
+/// \file
+/// \brief The iterated local search algorithm of Grosso, Locatelli, and Pullan
+/// for the maximum clique problem
+
+#include <vector>
+#include <limits>
+#include <lemon/core.h>
+#include <lemon/random.h>
+
+namespace lemon {
+
+ /// \addtogroup approx_algs
+ /// @{
+
+ /// \brief Implementation of the iterated local search algorithm of Grosso,
+ /// Locatelli, and Pullan for the maximum clique problem
+ ///
+ /// \ref GrossoLocatelliPullanMc implements the iterated local search
+ /// algorithm of Grosso, Locatelli, and Pullan for solving the \e maximum
+ /// \e clique \e problem \cite grosso08maxclique.
+ /// It is to find the largest complete subgraph (\e clique) in an
+ /// undirected graph, i.e., the largest set of nodes where each
+ /// pair of nodes is connected.
+ ///
+ /// This class provides a simple but highly efficient and robust heuristic
+ /// method that quickly finds a quite large clique, but not necessarily the
+ /// largest one.
+ /// The algorithm performs a certain number of iterations to find several
+ /// cliques and selects the largest one among them. Various limits can be
+ /// specified to control the running time and the effectiveness of the
+ /// search process.
+ ///
+ /// \tparam GR The undirected graph type the algorithm runs on.
+ ///
+ /// \note %GrossoLocatelliPullanMc provides three different node selection
+ /// rules, from which the most powerful one is used by default.
+ /// For more information, see \ref SelectionRule.
+ template <typename GR>
+ class GrossoLocatelliPullanMc
+ {
+ public:
+
+ /// \brief Constants for specifying the node selection rule.
+ ///
+ /// Enum type containing constants for specifying the node selection rule
+ /// for the \ref run() function.
+ ///
+ /// During the algorithm, nodes are selected for addition to the current
+ /// clique according to the applied rule.
+ /// In general, the PENALTY_BASED rule turned out to be the most powerful
+ /// and the most robust, thus it is the default option.
+ /// However, another selection rule can be specified using the \ref run()
+ /// function with the proper parameter.
+ enum SelectionRule {
+
+ /// A node is selected randomly without any evaluation at each step.
+ RANDOM,
+
+ /// A node of maximum degree is selected randomly at each step.
+ DEGREE_BASED,
+
+ /// A node of minimum penalty is selected randomly at each step.
+ /// The node penalties are updated adaptively after each stage of the
+ /// search process.
+ PENALTY_BASED
+ };
+
+ /// \brief Constants for the causes of search termination.
+ ///
+ /// Enum type containing constants for the different causes of search
+ /// termination. The \ref run() function returns one of these values.
+ enum TerminationCause {
+
+ /// The iteration count limit is reached.
+ ITERATION_LIMIT,
+
+ /// The step count limit is reached.
+ STEP_LIMIT,
+
+ /// The clique size limit is reached.
+ SIZE_LIMIT
+ };
+
+ private:
+
+ TEMPLATE_GRAPH_TYPEDEFS(GR);
+
+ typedef std::vector<int> IntVector;
+ typedef std::vector<char> BoolVector;
+ typedef std::vector<BoolVector> BoolMatrix;
+ // Note: vector<char> is used instead of vector<bool> for efficiency reasons
+
+ // The underlying graph
+ const GR &_graph;
+ IntNodeMap _id;
+
+ // Internal matrix representation of the graph
+ BoolMatrix _gr;
+ int _n;
+
+ // Search options
+ bool _delta_based_restart;
+ int _restart_delta_limit;
+
+ // Search limits
+ int _iteration_limit;
+ int _step_limit;
+ int _size_limit;
+
+ // The current clique
+ BoolVector _clique;
+ int _size;
+
+ // The best clique found so far
+ BoolVector _best_clique;
+ int _best_size;
+
+ // The "distances" of the nodes from the current clique.
+ // _delta[u] is the number of nodes in the clique that are
+ // not connected with u.
+ IntVector _delta;
+
+ // The current tabu set
+ BoolVector _tabu;
+
+ // Random number generator
+ Random _rnd;
+
+ private:
+
+ // Implementation of the RANDOM node selection rule.
+ class RandomSelectionRule
+ {
+ private:
+
+ // References to the algorithm instance
+ const BoolVector &_clique;
+ const IntVector &_delta;
+ const BoolVector &_tabu;
+ Random &_rnd;
+
+ // Pivot rule data
+ int _n;
+
+ public:
+
+ // Constructor
+ RandomSelectionRule(GrossoLocatelliPullanMc &mc) :
+ _clique(mc._clique), _delta(mc._delta), _tabu(mc._tabu),
+ _rnd(mc._rnd), _n(mc._n)
+ {}
+
+ // Return a node index for a feasible add move or -1 if no one exists
+ int nextFeasibleAddNode() const {
+ int start_node = _rnd[_n];
+ for (int i = start_node; i != _n; i++) {
+ if (_delta[i] == 0 && !_tabu[i]) return i;
+ }
+ for (int i = 0; i != start_node; i++) {
+ if (_delta[i] == 0 && !_tabu[i]) return i;
+ }
+ return -1;
+ }
+
+ // Return a node index for a feasible swap move or -1 if no one exists
+ int nextFeasibleSwapNode() const {
+ int start_node = _rnd[_n];
+ for (int i = start_node; i != _n; i++) {
+ if (!_clique[i] && _delta[i] == 1 && !_tabu[i]) return i;
+ }
+ for (int i = 0; i != start_node; i++) {
+ if (!_clique[i] && _delta[i] == 1 && !_tabu[i]) return i;
+ }
+ return -1;
+ }
+
+ // Return a node index for an add move or -1 if no one exists
+ int nextAddNode() const {
+ int start_node = _rnd[_n];
+ for (int i = start_node; i != _n; i++) {
+ if (_delta[i] == 0) return i;
+ }
+ for (int i = 0; i != start_node; i++) {
+ if (_delta[i] == 0) return i;
+ }
+ return -1;
+ }
+
+ // Update internal data structures between stages (if necessary)
+ void update() {}
+
+ }; //class RandomSelectionRule
+
+
+ // Implementation of the DEGREE_BASED node selection rule.
+ class DegreeBasedSelectionRule
+ {
+ private:
+
+ // References to the algorithm instance
+ const BoolVector &_clique;
+ const IntVector &_delta;
+ const BoolVector &_tabu;
+ Random &_rnd;
+
+ // Pivot rule data
+ int _n;
+ IntVector _deg;
+
+ public:
+
+ // Constructor
+ DegreeBasedSelectionRule(GrossoLocatelliPullanMc &mc) :
+ _clique(mc._clique), _delta(mc._delta), _tabu(mc._tabu),
+ _rnd(mc._rnd), _n(mc._n), _deg(_n)
+ {
+ for (int i = 0; i != _n; i++) {
+ int d = 0;
+ BoolVector &row = mc._gr[i];
+ for (int j = 0; j != _n; j++) {
+ if (row[j]) d++;
+ }
+ _deg[i] = d;
+ }
+ }
+
+ // Return a node index for a feasible add move or -1 if no one exists
+ int nextFeasibleAddNode() const {
+ int start_node = _rnd[_n];
+ int node = -1, max_deg = -1;
+ for (int i = start_node; i != _n; i++) {
+ if (_delta[i] == 0 && !_tabu[i] && _deg[i] > max_deg) {
+ node = i;
+ max_deg = _deg[i];
+ }
+ }
+ for (int i = 0; i != start_node; i++) {
+ if (_delta[i] == 0 && !_tabu[i] && _deg[i] > max_deg) {
+ node = i;
+ max_deg = _deg[i];
+ }
+ }
+ return node;
+ }
+
+ // Return a node index for a feasible swap move or -1 if no one exists
+ int nextFeasibleSwapNode() const {
+ int start_node = _rnd[_n];
+ int node = -1, max_deg = -1;
+ for (int i = start_node; i != _n; i++) {
+ if (!_clique[i] && _delta[i] == 1 && !_tabu[i] &&
+ _deg[i] > max_deg) {
+ node = i;
+ max_deg = _deg[i];
+ }
+ }
+ for (int i = 0; i != start_node; i++) {
+ if (!_clique[i] && _delta[i] == 1 && !_tabu[i] &&
+ _deg[i] > max_deg) {
+ node = i;
+ max_deg = _deg[i];
+ }
+ }
+ return node;
+ }
+
+ // Return a node index for an add move or -1 if no one exists
+ int nextAddNode() const {
+ int start_node = _rnd[_n];
+ int node = -1, max_deg = -1;
+ for (int i = start_node; i != _n; i++) {
+ if (_delta[i] == 0 && _deg[i] > max_deg) {
+ node = i;
+ max_deg = _deg[i];
+ }
+ }
+ for (int i = 0; i != start_node; i++) {
+ if (_delta[i] == 0 && _deg[i] > max_deg) {
+ node = i;
+ max_deg = _deg[i];
+ }
+ }
+ return node;
+ }
+
+ // Update internal data structures between stages (if necessary)
+ void update() {}
+
+ }; //class DegreeBasedSelectionRule
+
+
+ // Implementation of the PENALTY_BASED node selection rule.
+ class PenaltyBasedSelectionRule
+ {
+ private:
+
+ // References to the algorithm instance
+ const BoolVector &_clique;
+ const IntVector &_delta;
+ const BoolVector &_tabu;
+ Random &_rnd;
+
+ // Pivot rule data
+ int _n;
+ IntVector _penalty;
+
+ public:
+
+ // Constructor
+ PenaltyBasedSelectionRule(GrossoLocatelliPullanMc &mc) :
+ _clique(mc._clique), _delta(mc._delta), _tabu(mc._tabu),
+ _rnd(mc._rnd), _n(mc._n), _penalty(_n, 0)
+ {}
+
+ // Return a node index for a feasible add move or -1 if no one exists
+ int nextFeasibleAddNode() const {
+ int start_node = _rnd[_n];
+ int node = -1, min_p = std::numeric_limits<int>::max();
+ for (int i = start_node; i != _n; i++) {
+ if (_delta[i] == 0 && !_tabu[i] && _penalty[i] < min_p) {
+ node = i;
+ min_p = _penalty[i];
+ }
+ }
+ for (int i = 0; i != start_node; i++) {
+ if (_delta[i] == 0 && !_tabu[i] && _penalty[i] < min_p) {
+ node = i;
+ min_p = _penalty[i];
+ }
+ }
+ return node;
+ }
+
+ // Return a node index for a feasible swap move or -1 if no one exists
+ int nextFeasibleSwapNode() const {
+ int start_node = _rnd[_n];
+ int node = -1, min_p = std::numeric_limits<int>::max();
+ for (int i = start_node; i != _n; i++) {
+ if (!_clique[i] && _delta[i] == 1 && !_tabu[i] &&
+ _penalty[i] < min_p) {
+ node = i;
+ min_p = _penalty[i];
+ }
+ }
+ for (int i = 0; i != start_node; i++) {
+ if (!_clique[i] && _delta[i] == 1 && !_tabu[i] &&
+ _penalty[i] < min_p) {
+ node = i;
+ min_p = _penalty[i];
+ }
+ }
+ return node;
+ }
+
+ // Return a node index for an add move or -1 if no one exists
+ int nextAddNode() const {
+ int start_node = _rnd[_n];
+ int node = -1, min_p = std::numeric_limits<int>::max();
+ for (int i = start_node; i != _n; i++) {
+ if (_delta[i] == 0 && _penalty[i] < min_p) {
+ node = i;
+ min_p = _penalty[i];
+ }
+ }
+ for (int i = 0; i != start_node; i++) {
+ if (_delta[i] == 0 && _penalty[i] < min_p) {
+ node = i;
+ min_p = _penalty[i];
+ }
+ }
+ return node;
+ }
+
+ // Update internal data structures between stages (if necessary)
+ void update() {}
+
+ }; //class PenaltyBasedSelectionRule
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// The global \ref rnd "random number generator instance" is used
+ /// during the algorithm.
+ ///
+ /// \param graph The undirected graph the algorithm runs on.
+ GrossoLocatelliPullanMc(const GR& graph) :
+ _graph(graph), _id(_graph), _rnd(rnd)
+ {
+ initOptions();
+ }
+
+ /// \brief Constructor with random seed.
+ ///
+ /// Constructor with random seed.
+ ///
+ /// \param graph The undirected graph the algorithm runs on.
+ /// \param seed Seed value for the internal random number generator
+ /// that is used during the algorithm.
+ GrossoLocatelliPullanMc(const GR& graph, int seed) :
+ _graph(graph), _id(_graph), _rnd(seed)
+ {
+ initOptions();
+ }
+
+ /// \brief Constructor with random number generator.
+ ///
+ /// Constructor with random number generator.
+ ///
+ /// \param graph The undirected graph the algorithm runs on.
+ /// \param random A random number generator that is used during the
+ /// algorithm.
+ GrossoLocatelliPullanMc(const GR& graph, const Random& random) :
+ _graph(graph), _id(_graph), _rnd(random)
+ {
+ initOptions();
+ }
+
+ /// \name Execution Control
+ /// The \ref run() function can be used to execute the algorithm.\n
+ /// The functions \ref iterationLimit(int), \ref stepLimit(int), and
+ /// \ref sizeLimit(int) can be used to specify various limits for the
+ /// search process.
+
+ /// @{
+
+ /// \brief Sets the maximum number of iterations.
+ ///
+ /// This function sets the maximum number of iterations.
+ /// Each iteration of the algorithm finds a maximal clique (but not
+ /// necessarily the largest one) by performing several search steps
+ /// (node selections).
+ ///
+ /// This limit controls the running time and the success of the
+ /// algorithm. For larger values, the algorithm runs slower, but it more
+ /// likely finds larger cliques. For smaller values, the algorithm is
+ /// faster but probably gives worse results.
+ ///
+ /// The default value is \c 1000.
+ /// \c -1 means that number of iterations is not limited.
+ ///
+ /// \warning You should specify a reasonable limit for the number of
+ /// iterations and/or the number of search steps.
+ ///
+ /// \return <tt>(*this)</tt>
+ ///
+ /// \sa stepLimit(int)
+ /// \sa sizeLimit(int)
+ GrossoLocatelliPullanMc& iterationLimit(int limit) {
+ _iteration_limit = limit;
+ return *this;
+ }
+
+ /// \brief Sets the maximum number of search steps.
+ ///
+ /// This function sets the maximum number of elementary search steps.
+ /// Each iteration of the algorithm finds a maximal clique (but not
+ /// necessarily the largest one) by performing several search steps
+ /// (node selections).
+ ///
+ /// This limit controls the running time and the success of the
+ /// algorithm. For larger values, the algorithm runs slower, but it more
+ /// likely finds larger cliques. For smaller values, the algorithm is
+ /// faster but probably gives worse results.
+ ///
+ /// The default value is \c -1, which means that number of steps
+ /// is not limited explicitly. However, the number of iterations is
+ /// limited and each iteration performs a finite number of search steps.
+ ///
+ /// \warning You should specify a reasonable limit for the number of
+ /// iterations and/or the number of search steps.
+ ///
+ /// \return <tt>(*this)</tt>
+ ///
+ /// \sa iterationLimit(int)
+ /// \sa sizeLimit(int)
+ GrossoLocatelliPullanMc& stepLimit(int limit) {
+ _step_limit = limit;
+ return *this;
+ }
+
+ /// \brief Sets the desired clique size.
+ ///
+ /// This function sets the desired clique size that serves as a search
+ /// limit. If a clique of this size (or a larger one) is found, then the
+ /// algorithm terminates.
+ ///
+ /// This function is especially useful if you know an exact upper bound
+ /// for the size of the cliques in the graph or if any clique above
+ /// a certain size limit is sufficient for your application.
+ ///
+ /// The default value is \c -1, which means that the size limit is set to
+ /// the number of nodes in the graph.
+ ///
+ /// \return <tt>(*this)</tt>
+ ///
+ /// \sa iterationLimit(int)
+ /// \sa stepLimit(int)
+ GrossoLocatelliPullanMc& sizeLimit(int limit) {
+ _size_limit = limit;
+ return *this;
+ }
+
+ /// \brief The maximum number of iterations.
+ ///
+ /// This function gives back the maximum number of iterations.
+ /// \c -1 means that no limit is specified.
+ ///
+ /// \sa iterationLimit(int)
+ int iterationLimit() const {
+ return _iteration_limit;
+ }
+
+ /// \brief The maximum number of search steps.
+ ///
+ /// This function gives back the maximum number of search steps.
+ /// \c -1 means that no limit is specified.
+ ///
+ /// \sa stepLimit(int)
+ int stepLimit() const {
+ return _step_limit;
+ }
+
+ /// \brief The desired clique size.
+ ///
+ /// This function gives back the desired clique size that serves as a
+ /// search limit. \c -1 means that this limit is set to the number of
+ /// nodes in the graph.
+ ///
+ /// \sa sizeLimit(int)
+ int sizeLimit() const {
+ return _size_limit;
+ }
+
+ /// \brief Runs the algorithm.
+ ///
+ /// This function runs the algorithm. If one of the specified limits
+ /// is reached, the search process terminates.
+ ///
+ /// \param rule The node selection rule. For more information, see
+ /// \ref SelectionRule.
+ ///
+ /// \return The termination cause of the search. For more information,
+ /// see \ref TerminationCause.
+ TerminationCause run(SelectionRule rule = PENALTY_BASED)
+ {
+ init();
+ switch (rule) {
+ case RANDOM:
+ return start<RandomSelectionRule>();
+ case DEGREE_BASED:
+ return start<DegreeBasedSelectionRule>();
+ default:
+ return start<PenaltyBasedSelectionRule>();
+ }
+ }
+
+ /// @}
+
+ /// \name Query Functions
+ /// The results of the algorithm can be obtained using these functions.\n
+ /// The run() function must be called before using them.
+
+ /// @{
+
+ /// \brief The size of the found clique
+ ///
+ /// This function returns the size of the found clique.
+ ///
+ /// \pre run() must be called before using this function.
+ int cliqueSize() const {
+ return _best_size;
+ }
+
+ /// \brief Gives back the found clique in a \c bool node map
+ ///
+ /// This function gives back the characteristic vector of the found
+ /// clique in the given node map.
+ /// It must be a \ref concepts::WriteMap "writable" node map with
+ /// \c bool (or convertible) value type.
+ ///
+ /// \pre run() must be called before using this function.
+ template <typename CliqueMap>
+ void cliqueMap(CliqueMap &map) const {
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ map[n] = static_cast<bool>(_best_clique[_id[n]]);
+ }
+ }
+
+ /// \brief Iterator to list the nodes of the found clique
+ ///
+ /// This iterator class lists the nodes of the found clique.
+ /// Before using it, you must allocate a GrossoLocatelliPullanMc instance
+ /// and call its \ref GrossoLocatelliPullanMc::run() "run()" method.
+ ///
+ /// The following example prints out the IDs of the nodes in the found
+ /// clique.
+ /// \code
+ /// GrossoLocatelliPullanMc<Graph> mc(g);
+ /// mc.run();
+ /// for (GrossoLocatelliPullanMc<Graph>::CliqueNodeIt n(mc);
+ /// n != INVALID; ++n)
+ /// {
+ /// std::cout << g.id(n) << std::endl;
+ /// }
+ /// \endcode
+ class CliqueNodeIt
+ {
+ private:
+ NodeIt _it;
+ BoolNodeMap _map;
+
+ public:
+
+ /// Constructor
+
+ /// Constructor.
+ /// \param mc The algorithm instance.
+ CliqueNodeIt(const GrossoLocatelliPullanMc &mc)
+ : _map(mc._graph)
+ {
+ mc.cliqueMap(_map);
+ for (_it = NodeIt(mc._graph); _it != INVALID && !_map[_it]; ++_it) ;
+ }
+
+ /// Conversion to \c Node
+ operator Node() const { return _it; }
+
+ bool operator==(Invalid) const { return _it == INVALID; }
+ bool operator!=(Invalid) const { return _it != INVALID; }
+
+ /// Next node
+ CliqueNodeIt &operator++() {
+ for (++_it; _it != INVALID && !_map[_it]; ++_it) ;
+ return *this;
+ }
+
+ /// Postfix incrementation
+
+ /// Postfix incrementation.
+ ///
+ /// \warning This incrementation returns a \c Node, not a
+ /// \c CliqueNodeIt as one may expect.
+ typename GR::Node operator++(int) {
+ Node n=*this;
+ ++(*this);
+ return n;
+ }
+
+ };
+
+ /// @}
+
+ private:
+
+ // Initialize search options and limits
+ void initOptions() {
+ // Search options
+ _delta_based_restart = true;
+ _restart_delta_limit = 4;
+
+ // Search limits
+ _iteration_limit = 1000;
+ _step_limit = -1; // this is disabled by default
+ _size_limit = -1; // this is disabled by default
+ }
+
+ // Adds a node to the current clique
+ void addCliqueNode(int u) {
+ if (_clique[u]) return;
+ _clique[u] = true;
+ _size++;
+ BoolVector &row = _gr[u];
+ for (int i = 0; i != _n; i++) {
+ if (!row[i]) _delta[i]++;
+ }
+ }
+
+ // Removes a node from the current clique
+ void delCliqueNode(int u) {
+ if (!_clique[u]) return;
+ _clique[u] = false;
+ _size--;
+ BoolVector &row = _gr[u];
+ for (int i = 0; i != _n; i++) {
+ if (!row[i]) _delta[i]--;
+ }
+ }
+
+ // Initialize data structures
+ void init() {
+ _n = countNodes(_graph);
+ int ui = 0;
+ for (NodeIt u(_graph); u != INVALID; ++u) {
+ _id[u] = ui++;
+ }
+ _gr.clear();
+ _gr.resize(_n, BoolVector(_n, false));
+ ui = 0;
+ for (NodeIt u(_graph); u != INVALID; ++u) {
+ for (IncEdgeIt e(_graph, u); e != INVALID; ++e) {
+ int vi = _id[_graph.runningNode(e)];
+ _gr[ui][vi] = true;
+ _gr[vi][ui] = true;
+ }
+ ++ui;
+ }
+
+ _clique.clear();
+ _clique.resize(_n, false);
+ _size = 0;
+ _best_clique.clear();
+ _best_clique.resize(_n, false);
+ _best_size = 0;
+ _delta.clear();
+ _delta.resize(_n, 0);
+ _tabu.clear();
+ _tabu.resize(_n, false);
+ }
+
+ // Executes the algorithm
+ template <typename SelectionRuleImpl>
+ TerminationCause start() {
+ if (_n == 0) return SIZE_LIMIT;
+ if (_n == 1) {
+ _best_clique[0] = true;
+ _best_size = 1;
+ return SIZE_LIMIT;
+ }
+
+ // Iterated local search algorithm
+ const int max_size = _size_limit >= 0 ? _size_limit : _n;
+ const int max_restart = _iteration_limit >= 0 ?
+ _iteration_limit : std::numeric_limits<int>::max();
+ const int max_select = _step_limit >= 0 ?
+ _step_limit : std::numeric_limits<int>::max();
+
+ SelectionRuleImpl sel_method(*this);
+ int select = 0, restart = 0;
+ IntVector restart_nodes;
+ while (select < max_select && restart < max_restart) {
+
+ // Perturbation/restart
+ restart++;
+ if (_delta_based_restart) {
+ restart_nodes.clear();
+ for (int i = 0; i != _n; i++) {
+ if (_delta[i] >= _restart_delta_limit)
+ restart_nodes.push_back(i);
+ }
+ }
+ int rs_node = -1;
+ if (restart_nodes.size() > 0) {
+ rs_node = restart_nodes[_rnd[restart_nodes.size()]];
+ } else {
+ rs_node = _rnd[_n];
+ }
+ BoolVector &row = _gr[rs_node];
+ for (int i = 0; i != _n; i++) {
+ if (_clique[i] && !row[i]) delCliqueNode(i);
+ }
+ addCliqueNode(rs_node);
+
+ // Local search
+ _tabu.clear();
+ _tabu.resize(_n, false);
+ bool tabu_empty = true;
+ int max_swap = _size;
+ while (select < max_select) {
+ select++;
+ int u;
+ if ((u = sel_method.nextFeasibleAddNode()) != -1) {
+ // Feasible add move
+ addCliqueNode(u);
+ if (tabu_empty) max_swap = _size;
+ }
+ else if ((u = sel_method.nextFeasibleSwapNode()) != -1) {
+ // Feasible swap move
+ int v = -1;
+ BoolVector &row = _gr[u];
+ for (int i = 0; i != _n; i++) {
+ if (_clique[i] && !row[i]) {
+ v = i;
+ break;
+ }
+ }
+ addCliqueNode(u);
+ delCliqueNode(v);
+ _tabu[v] = true;
+ tabu_empty = false;
+ if (--max_swap <= 0) break;
+ }
+ else if ((u = sel_method.nextAddNode()) != -1) {
+ // Non-feasible add move
+ addCliqueNode(u);
+ }
+ else break;
+ }
+ if (_size > _best_size) {
+ _best_clique = _clique;
+ _best_size = _size;
+ if (_best_size >= max_size) return SIZE_LIMIT;
+ }
+ sel_method.update();
+ }
+
+ return (restart >= max_restart ? ITERATION_LIMIT : STEP_LIMIT);
+ }
+
+ }; //class GrossoLocatelliPullanMc
+
+ ///@}
+
+} //namespace lemon
+
+#endif //LEMON_GROSSO_LOCATELLI_PULLAN_MC_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/hao_orlin.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/hao_orlin.h
new file mode 100644
index 00000000000..0eeaff95d14
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/hao_orlin.h
@@ -0,0 +1,1015 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_HAO_ORLIN_H
+#define LEMON_HAO_ORLIN_H
+
+#include <vector>
+#include <list>
+#include <limits>
+
+#include <lemon/maps.h>
+#include <lemon/core.h>
+#include <lemon/tolerance.h>
+
+/// \file
+/// \ingroup min_cut
+/// \brief Implementation of the Hao-Orlin algorithm.
+///
+/// Implementation of the Hao-Orlin algorithm for finding a minimum cut
+/// in a digraph.
+
+namespace lemon {
+
+ /// \ingroup min_cut
+ ///
+ /// \brief Hao-Orlin algorithm for finding a minimum cut in a digraph.
+ ///
+ /// This class implements the Hao-Orlin algorithm for finding a minimum
+ /// value cut in a directed graph \f$D=(V,A)\f$.
+ /// It takes a fixed node \f$ source \in V \f$ and
+ /// consists of two phases: in the first phase it determines a
+ /// minimum cut with \f$ source \f$ on the source-side (i.e. a set
+ /// \f$ X\subsetneq V \f$ with \f$ source \in X \f$ and minimal outgoing
+ /// capacity) and in the second phase it determines a minimum cut
+ /// with \f$ source \f$ on the sink-side (i.e. a set
+ /// \f$ X\subsetneq V \f$ with \f$ source \notin X \f$ and minimal outgoing
+ /// capacity). Obviously, the smaller of these two cuts will be a
+ /// minimum cut of \f$ D \f$. The algorithm is a modified
+ /// preflow push-relabel algorithm. Our implementation calculates
+ /// the minimum cut in \f$ O(n^2\sqrt{m}) \f$ time (we use the
+ /// highest-label rule), or in \f$O(nm)\f$ for unit capacities. A notable
+ /// use of this algorithm is testing network reliability.
+ ///
+ /// For an undirected graph you can run just the first phase of the
+ /// algorithm or you can use the algorithm of Nagamochi and Ibaraki,
+ /// which solves the undirected problem in \f$ O(nm + n^2 \log n) \f$
+ /// time. It is implemented in the NagamochiIbaraki algorithm class.
+ ///
+ /// \tparam GR The type of the digraph the algorithm runs on.
+ /// \tparam CAP The type of the arc map containing the capacities,
+ /// which can be any numreric type. The default map type is
+ /// \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
+ /// \tparam TOL Tolerance class for handling inexact computations. The
+ /// default tolerance type is \ref Tolerance "Tolerance<CAP::Value>".
+#ifdef DOXYGEN
+ template <typename GR, typename CAP, typename TOL>
+#else
+ template <typename GR,
+ typename CAP = typename GR::template ArcMap<int>,
+ typename TOL = Tolerance<typename CAP::Value> >
+#endif
+ class HaoOrlin {
+ public:
+
+ /// The digraph type of the algorithm
+ typedef GR Digraph;
+ /// The capacity map type of the algorithm
+ typedef CAP CapacityMap;
+ /// The tolerance type of the algorithm
+ typedef TOL Tolerance;
+
+ private:
+
+ typedef typename CapacityMap::Value Value;
+
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+
+ const Digraph& _graph;
+ const CapacityMap* _capacity;
+
+ typedef typename Digraph::template ArcMap<Value> FlowMap;
+ FlowMap* _flow;
+
+ Node _source;
+
+ int _node_num;
+
+ // Bucketing structure
+ std::vector<Node> _first, _last;
+ typename Digraph::template NodeMap<Node>* _next;
+ typename Digraph::template NodeMap<Node>* _prev;
+ typename Digraph::template NodeMap<bool>* _active;
+ typename Digraph::template NodeMap<int>* _bucket;
+
+ std::vector<bool> _dormant;
+
+ std::list<std::list<int> > _sets;
+ std::list<int>::iterator _highest;
+
+ typedef typename Digraph::template NodeMap<Value> ExcessMap;
+ ExcessMap* _excess;
+
+ typedef typename Digraph::template NodeMap<bool> SourceSetMap;
+ SourceSetMap* _source_set;
+
+ Value _min_cut;
+
+ typedef typename Digraph::template NodeMap<bool> MinCutMap;
+ MinCutMap* _min_cut_map;
+
+ Tolerance _tolerance;
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Constructor of the algorithm class.
+ HaoOrlin(const Digraph& graph, const CapacityMap& capacity,
+ const Tolerance& tolerance = Tolerance()) :
+ _graph(graph), _capacity(&capacity), _flow(0), _source(),
+ _node_num(), _first(), _last(), _next(0), _prev(0),
+ _active(0), _bucket(0), _dormant(), _sets(), _highest(),
+ _excess(0), _source_set(0), _min_cut(), _min_cut_map(0),
+ _tolerance(tolerance) {}
+
+ ~HaoOrlin() {
+ if (_min_cut_map) {
+ delete _min_cut_map;
+ }
+ if (_source_set) {
+ delete _source_set;
+ }
+ if (_excess) {
+ delete _excess;
+ }
+ if (_next) {
+ delete _next;
+ }
+ if (_prev) {
+ delete _prev;
+ }
+ if (_active) {
+ delete _active;
+ }
+ if (_bucket) {
+ delete _bucket;
+ }
+ if (_flow) {
+ delete _flow;
+ }
+ }
+
+ /// \brief Set the tolerance used by the algorithm.
+ ///
+ /// This function sets the tolerance object used by the algorithm.
+ /// \return <tt>(*this)</tt>
+ HaoOrlin& tolerance(const Tolerance& tolerance) {
+ _tolerance = tolerance;
+ return *this;
+ }
+
+ /// \brief Returns a const reference to the tolerance.
+ ///
+ /// This function returns a const reference to the tolerance object
+ /// used by the algorithm.
+ const Tolerance& tolerance() const {
+ return _tolerance;
+ }
+
+ private:
+
+ void activate(const Node& i) {
+ (*_active)[i] = true;
+
+ int bucket = (*_bucket)[i];
+
+ if ((*_prev)[i] == INVALID || (*_active)[(*_prev)[i]]) return;
+ //unlace
+ (*_next)[(*_prev)[i]] = (*_next)[i];
+ if ((*_next)[i] != INVALID) {
+ (*_prev)[(*_next)[i]] = (*_prev)[i];
+ } else {
+ _last[bucket] = (*_prev)[i];
+ }
+ //lace
+ (*_next)[i] = _first[bucket];
+ (*_prev)[_first[bucket]] = i;
+ (*_prev)[i] = INVALID;
+ _first[bucket] = i;
+ }
+
+ void deactivate(const Node& i) {
+ (*_active)[i] = false;
+ int bucket = (*_bucket)[i];
+
+ if ((*_next)[i] == INVALID || !(*_active)[(*_next)[i]]) return;
+
+ //unlace
+ (*_prev)[(*_next)[i]] = (*_prev)[i];
+ if ((*_prev)[i] != INVALID) {
+ (*_next)[(*_prev)[i]] = (*_next)[i];
+ } else {
+ _first[bucket] = (*_next)[i];
+ }
+ //lace
+ (*_prev)[i] = _last[bucket];
+ (*_next)[_last[bucket]] = i;
+ (*_next)[i] = INVALID;
+ _last[bucket] = i;
+ }
+
+ void addItem(const Node& i, int bucket) {
+ (*_bucket)[i] = bucket;
+ if (_last[bucket] != INVALID) {
+ (*_prev)[i] = _last[bucket];
+ (*_next)[_last[bucket]] = i;
+ (*_next)[i] = INVALID;
+ _last[bucket] = i;
+ } else {
+ (*_prev)[i] = INVALID;
+ _first[bucket] = i;
+ (*_next)[i] = INVALID;
+ _last[bucket] = i;
+ }
+ }
+
+ void findMinCutOut() {
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ (*_excess)[n] = 0;
+ (*_source_set)[n] = false;
+ }
+
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ (*_flow)[a] = 0;
+ }
+
+ int bucket_num = 0;
+ std::vector<Node> queue(_node_num);
+ int qfirst = 0, qlast = 0, qsep = 0;
+
+ {
+ typename Digraph::template NodeMap<bool> reached(_graph, false);
+
+ reached[_source] = true;
+ bool first_set = true;
+
+ for (NodeIt t(_graph); t != INVALID; ++t) {
+ if (reached[t]) continue;
+ _sets.push_front(std::list<int>());
+
+ queue[qlast++] = t;
+ reached[t] = true;
+
+ while (qfirst != qlast) {
+ if (qsep == qfirst) {
+ ++bucket_num;
+ _sets.front().push_front(bucket_num);
+ _dormant[bucket_num] = !first_set;
+ _first[bucket_num] = _last[bucket_num] = INVALID;
+ qsep = qlast;
+ }
+
+ Node n = queue[qfirst++];
+ addItem(n, bucket_num);
+
+ for (InArcIt a(_graph, n); a != INVALID; ++a) {
+ Node u = _graph.source(a);
+ if (!reached[u] && _tolerance.positive((*_capacity)[a])) {
+ reached[u] = true;
+ queue[qlast++] = u;
+ }
+ }
+ }
+ first_set = false;
+ }
+
+ ++bucket_num;
+ (*_bucket)[_source] = 0;
+ _dormant[0] = true;
+ }
+ (*_source_set)[_source] = true;
+
+ Node target = _last[_sets.back().back()];
+ {
+ for (OutArcIt a(_graph, _source); a != INVALID; ++a) {
+ if (_tolerance.positive((*_capacity)[a])) {
+ Node u = _graph.target(a);
+ (*_flow)[a] = (*_capacity)[a];
+ (*_excess)[u] += (*_capacity)[a];
+ if (!(*_active)[u] && u != _source) {
+ activate(u);
+ }
+ }
+ }
+
+ if ((*_active)[target]) {
+ deactivate(target);
+ }
+
+ _highest = _sets.back().begin();
+ while (_highest != _sets.back().end() &&
+ !(*_active)[_first[*_highest]]) {
+ ++_highest;
+ }
+ }
+
+ while (true) {
+ while (_highest != _sets.back().end()) {
+ Node n = _first[*_highest];
+ Value excess = (*_excess)[n];
+ int next_bucket = _node_num;
+
+ int under_bucket;
+ if (++std::list<int>::iterator(_highest) == _sets.back().end()) {
+ under_bucket = -1;
+ } else {
+ under_bucket = *(++std::list<int>::iterator(_highest));
+ }
+
+ for (OutArcIt a(_graph, n); a != INVALID; ++a) {
+ Node v = _graph.target(a);
+ if (_dormant[(*_bucket)[v]]) continue;
+ Value rem = (*_capacity)[a] - (*_flow)[a];
+ if (!_tolerance.positive(rem)) continue;
+ if ((*_bucket)[v] == under_bucket) {
+ if (!(*_active)[v] && v != target) {
+ activate(v);
+ }
+ if (!_tolerance.less(rem, excess)) {
+ (*_flow)[a] += excess;
+ (*_excess)[v] += excess;
+ excess = 0;
+ goto no_more_push;
+ } else {
+ excess -= rem;
+ (*_excess)[v] += rem;
+ (*_flow)[a] = (*_capacity)[a];
+ }
+ } else if (next_bucket > (*_bucket)[v]) {
+ next_bucket = (*_bucket)[v];
+ }
+ }
+
+ for (InArcIt a(_graph, n); a != INVALID; ++a) {
+ Node v = _graph.source(a);
+ if (_dormant[(*_bucket)[v]]) continue;
+ Value rem = (*_flow)[a];
+ if (!_tolerance.positive(rem)) continue;
+ if ((*_bucket)[v] == under_bucket) {
+ if (!(*_active)[v] && v != target) {
+ activate(v);
+ }
+ if (!_tolerance.less(rem, excess)) {
+ (*_flow)[a] -= excess;
+ (*_excess)[v] += excess;
+ excess = 0;
+ goto no_more_push;
+ } else {
+ excess -= rem;
+ (*_excess)[v] += rem;
+ (*_flow)[a] = 0;
+ }
+ } else if (next_bucket > (*_bucket)[v]) {
+ next_bucket = (*_bucket)[v];
+ }
+ }
+
+ no_more_push:
+
+ (*_excess)[n] = excess;
+
+ if (excess != 0) {
+ if ((*_next)[n] == INVALID) {
+ typename std::list<std::list<int> >::iterator new_set =
+ _sets.insert(--_sets.end(), std::list<int>());
+ new_set->splice(new_set->end(), _sets.back(),
+ _sets.back().begin(), ++_highest);
+ for (std::list<int>::iterator it = new_set->begin();
+ it != new_set->end(); ++it) {
+ _dormant[*it] = true;
+ }
+ while (_highest != _sets.back().end() &&
+ !(*_active)[_first[*_highest]]) {
+ ++_highest;
+ }
+ } else if (next_bucket == _node_num) {
+ _first[(*_bucket)[n]] = (*_next)[n];
+ (*_prev)[(*_next)[n]] = INVALID;
+
+ std::list<std::list<int> >::iterator new_set =
+ _sets.insert(--_sets.end(), std::list<int>());
+
+ new_set->push_front(bucket_num);
+ (*_bucket)[n] = bucket_num;
+ _first[bucket_num] = _last[bucket_num] = n;
+ (*_next)[n] = INVALID;
+ (*_prev)[n] = INVALID;
+ _dormant[bucket_num] = true;
+ ++bucket_num;
+
+ while (_highest != _sets.back().end() &&
+ !(*_active)[_first[*_highest]]) {
+ ++_highest;
+ }
+ } else {
+ _first[*_highest] = (*_next)[n];
+ (*_prev)[(*_next)[n]] = INVALID;
+
+ while (next_bucket != *_highest) {
+ --_highest;
+ }
+
+ if (_highest == _sets.back().begin()) {
+ _sets.back().push_front(bucket_num);
+ _dormant[bucket_num] = false;
+ _first[bucket_num] = _last[bucket_num] = INVALID;
+ ++bucket_num;
+ }
+ --_highest;
+
+ (*_bucket)[n] = *_highest;
+ (*_next)[n] = _first[*_highest];
+ if (_first[*_highest] != INVALID) {
+ (*_prev)[_first[*_highest]] = n;
+ } else {
+ _last[*_highest] = n;
+ }
+ _first[*_highest] = n;
+ }
+ } else {
+
+ deactivate(n);
+ if (!(*_active)[_first[*_highest]]) {
+ ++_highest;
+ if (_highest != _sets.back().end() &&
+ !(*_active)[_first[*_highest]]) {
+ _highest = _sets.back().end();
+ }
+ }
+ }
+ }
+
+ if ((*_excess)[target] < _min_cut) {
+ _min_cut = (*_excess)[target];
+ for (NodeIt i(_graph); i != INVALID; ++i) {
+ (*_min_cut_map)[i] = true;
+ }
+ for (std::list<int>::iterator it = _sets.back().begin();
+ it != _sets.back().end(); ++it) {
+ Node n = _first[*it];
+ while (n != INVALID) {
+ (*_min_cut_map)[n] = false;
+ n = (*_next)[n];
+ }
+ }
+ }
+
+ {
+ Node new_target;
+ if ((*_prev)[target] != INVALID || (*_next)[target] != INVALID) {
+ if ((*_next)[target] == INVALID) {
+ _last[(*_bucket)[target]] = (*_prev)[target];
+ new_target = (*_prev)[target];
+ } else {
+ (*_prev)[(*_next)[target]] = (*_prev)[target];
+ new_target = (*_next)[target];
+ }
+ if ((*_prev)[target] == INVALID) {
+ _first[(*_bucket)[target]] = (*_next)[target];
+ } else {
+ (*_next)[(*_prev)[target]] = (*_next)[target];
+ }
+ } else {
+ _sets.back().pop_back();
+ if (_sets.back().empty()) {
+ _sets.pop_back();
+ if (_sets.empty())
+ break;
+ for (std::list<int>::iterator it = _sets.back().begin();
+ it != _sets.back().end(); ++it) {
+ _dormant[*it] = false;
+ }
+ }
+ new_target = _last[_sets.back().back()];
+ }
+
+ (*_bucket)[target] = 0;
+
+ (*_source_set)[target] = true;
+ for (OutArcIt a(_graph, target); a != INVALID; ++a) {
+ Value rem = (*_capacity)[a] - (*_flow)[a];
+ if (!_tolerance.positive(rem)) continue;
+ Node v = _graph.target(a);
+ if (!(*_active)[v] && !(*_source_set)[v]) {
+ activate(v);
+ }
+ (*_excess)[v] += rem;
+ (*_flow)[a] = (*_capacity)[a];
+ }
+
+ for (InArcIt a(_graph, target); a != INVALID; ++a) {
+ Value rem = (*_flow)[a];
+ if (!_tolerance.positive(rem)) continue;
+ Node v = _graph.source(a);
+ if (!(*_active)[v] && !(*_source_set)[v]) {
+ activate(v);
+ }
+ (*_excess)[v] += rem;
+ (*_flow)[a] = 0;
+ }
+
+ target = new_target;
+ if ((*_active)[target]) {
+ deactivate(target);
+ }
+
+ _highest = _sets.back().begin();
+ while (_highest != _sets.back().end() &&
+ !(*_active)[_first[*_highest]]) {
+ ++_highest;
+ }
+ }
+ }
+ }
+
+ void findMinCutIn() {
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ (*_excess)[n] = 0;
+ (*_source_set)[n] = false;
+ }
+
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ (*_flow)[a] = 0;
+ }
+
+ int bucket_num = 0;
+ std::vector<Node> queue(_node_num);
+ int qfirst = 0, qlast = 0, qsep = 0;
+
+ {
+ typename Digraph::template NodeMap<bool> reached(_graph, false);
+
+ reached[_source] = true;
+
+ bool first_set = true;
+
+ for (NodeIt t(_graph); t != INVALID; ++t) {
+ if (reached[t]) continue;
+ _sets.push_front(std::list<int>());
+
+ queue[qlast++] = t;
+ reached[t] = true;
+
+ while (qfirst != qlast) {
+ if (qsep == qfirst) {
+ ++bucket_num;
+ _sets.front().push_front(bucket_num);
+ _dormant[bucket_num] = !first_set;
+ _first[bucket_num] = _last[bucket_num] = INVALID;
+ qsep = qlast;
+ }
+
+ Node n = queue[qfirst++];
+ addItem(n, bucket_num);
+
+ for (OutArcIt a(_graph, n); a != INVALID; ++a) {
+ Node u = _graph.target(a);
+ if (!reached[u] && _tolerance.positive((*_capacity)[a])) {
+ reached[u] = true;
+ queue[qlast++] = u;
+ }
+ }
+ }
+ first_set = false;
+ }
+
+ ++bucket_num;
+ (*_bucket)[_source] = 0;
+ _dormant[0] = true;
+ }
+ (*_source_set)[_source] = true;
+
+ Node target = _last[_sets.back().back()];
+ {
+ for (InArcIt a(_graph, _source); a != INVALID; ++a) {
+ if (_tolerance.positive((*_capacity)[a])) {
+ Node u = _graph.source(a);
+ (*_flow)[a] = (*_capacity)[a];
+ (*_excess)[u] += (*_capacity)[a];
+ if (!(*_active)[u] && u != _source) {
+ activate(u);
+ }
+ }
+ }
+ if ((*_active)[target]) {
+ deactivate(target);
+ }
+
+ _highest = _sets.back().begin();
+ while (_highest != _sets.back().end() &&
+ !(*_active)[_first[*_highest]]) {
+ ++_highest;
+ }
+ }
+
+
+ while (true) {
+ while (_highest != _sets.back().end()) {
+ Node n = _first[*_highest];
+ Value excess = (*_excess)[n];
+ int next_bucket = _node_num;
+
+ int under_bucket;
+ if (++std::list<int>::iterator(_highest) == _sets.back().end()) {
+ under_bucket = -1;
+ } else {
+ under_bucket = *(++std::list<int>::iterator(_highest));
+ }
+
+ for (InArcIt a(_graph, n); a != INVALID; ++a) {
+ Node v = _graph.source(a);
+ if (_dormant[(*_bucket)[v]]) continue;
+ Value rem = (*_capacity)[a] - (*_flow)[a];
+ if (!_tolerance.positive(rem)) continue;
+ if ((*_bucket)[v] == under_bucket) {
+ if (!(*_active)[v] && v != target) {
+ activate(v);
+ }
+ if (!_tolerance.less(rem, excess)) {
+ (*_flow)[a] += excess;
+ (*_excess)[v] += excess;
+ excess = 0;
+ goto no_more_push;
+ } else {
+ excess -= rem;
+ (*_excess)[v] += rem;
+ (*_flow)[a] = (*_capacity)[a];
+ }
+ } else if (next_bucket > (*_bucket)[v]) {
+ next_bucket = (*_bucket)[v];
+ }
+ }
+
+ for (OutArcIt a(_graph, n); a != INVALID; ++a) {
+ Node v = _graph.target(a);
+ if (_dormant[(*_bucket)[v]]) continue;
+ Value rem = (*_flow)[a];
+ if (!_tolerance.positive(rem)) continue;
+ if ((*_bucket)[v] == under_bucket) {
+ if (!(*_active)[v] && v != target) {
+ activate(v);
+ }
+ if (!_tolerance.less(rem, excess)) {
+ (*_flow)[a] -= excess;
+ (*_excess)[v] += excess;
+ excess = 0;
+ goto no_more_push;
+ } else {
+ excess -= rem;
+ (*_excess)[v] += rem;
+ (*_flow)[a] = 0;
+ }
+ } else if (next_bucket > (*_bucket)[v]) {
+ next_bucket = (*_bucket)[v];
+ }
+ }
+
+ no_more_push:
+
+ (*_excess)[n] = excess;
+
+ if (excess != 0) {
+ if ((*_next)[n] == INVALID) {
+ typename std::list<std::list<int> >::iterator new_set =
+ _sets.insert(--_sets.end(), std::list<int>());
+ new_set->splice(new_set->end(), _sets.back(),
+ _sets.back().begin(), ++_highest);
+ for (std::list<int>::iterator it = new_set->begin();
+ it != new_set->end(); ++it) {
+ _dormant[*it] = true;
+ }
+ while (_highest != _sets.back().end() &&
+ !(*_active)[_first[*_highest]]) {
+ ++_highest;
+ }
+ } else if (next_bucket == _node_num) {
+ _first[(*_bucket)[n]] = (*_next)[n];
+ (*_prev)[(*_next)[n]] = INVALID;
+
+ std::list<std::list<int> >::iterator new_set =
+ _sets.insert(--_sets.end(), std::list<int>());
+
+ new_set->push_front(bucket_num);
+ (*_bucket)[n] = bucket_num;
+ _first[bucket_num] = _last[bucket_num] = n;
+ (*_next)[n] = INVALID;
+ (*_prev)[n] = INVALID;
+ _dormant[bucket_num] = true;
+ ++bucket_num;
+
+ while (_highest != _sets.back().end() &&
+ !(*_active)[_first[*_highest]]) {
+ ++_highest;
+ }
+ } else {
+ _first[*_highest] = (*_next)[n];
+ (*_prev)[(*_next)[n]] = INVALID;
+
+ while (next_bucket != *_highest) {
+ --_highest;
+ }
+ if (_highest == _sets.back().begin()) {
+ _sets.back().push_front(bucket_num);
+ _dormant[bucket_num] = false;
+ _first[bucket_num] = _last[bucket_num] = INVALID;
+ ++bucket_num;
+ }
+ --_highest;
+
+ (*_bucket)[n] = *_highest;
+ (*_next)[n] = _first[*_highest];
+ if (_first[*_highest] != INVALID) {
+ (*_prev)[_first[*_highest]] = n;
+ } else {
+ _last[*_highest] = n;
+ }
+ _first[*_highest] = n;
+ }
+ } else {
+
+ deactivate(n);
+ if (!(*_active)[_first[*_highest]]) {
+ ++_highest;
+ if (_highest != _sets.back().end() &&
+ !(*_active)[_first[*_highest]]) {
+ _highest = _sets.back().end();
+ }
+ }
+ }
+ }
+
+ if ((*_excess)[target] < _min_cut) {
+ _min_cut = (*_excess)[target];
+ for (NodeIt i(_graph); i != INVALID; ++i) {
+ (*_min_cut_map)[i] = false;
+ }
+ for (std::list<int>::iterator it = _sets.back().begin();
+ it != _sets.back().end(); ++it) {
+ Node n = _first[*it];
+ while (n != INVALID) {
+ (*_min_cut_map)[n] = true;
+ n = (*_next)[n];
+ }
+ }
+ }
+
+ {
+ Node new_target;
+ if ((*_prev)[target] != INVALID || (*_next)[target] != INVALID) {
+ if ((*_next)[target] == INVALID) {
+ _last[(*_bucket)[target]] = (*_prev)[target];
+ new_target = (*_prev)[target];
+ } else {
+ (*_prev)[(*_next)[target]] = (*_prev)[target];
+ new_target = (*_next)[target];
+ }
+ if ((*_prev)[target] == INVALID) {
+ _first[(*_bucket)[target]] = (*_next)[target];
+ } else {
+ (*_next)[(*_prev)[target]] = (*_next)[target];
+ }
+ } else {
+ _sets.back().pop_back();
+ if (_sets.back().empty()) {
+ _sets.pop_back();
+ if (_sets.empty())
+ break;
+ for (std::list<int>::iterator it = _sets.back().begin();
+ it != _sets.back().end(); ++it) {
+ _dormant[*it] = false;
+ }
+ }
+ new_target = _last[_sets.back().back()];
+ }
+
+ (*_bucket)[target] = 0;
+
+ (*_source_set)[target] = true;
+ for (InArcIt a(_graph, target); a != INVALID; ++a) {
+ Value rem = (*_capacity)[a] - (*_flow)[a];
+ if (!_tolerance.positive(rem)) continue;
+ Node v = _graph.source(a);
+ if (!(*_active)[v] && !(*_source_set)[v]) {
+ activate(v);
+ }
+ (*_excess)[v] += rem;
+ (*_flow)[a] = (*_capacity)[a];
+ }
+
+ for (OutArcIt a(_graph, target); a != INVALID; ++a) {
+ Value rem = (*_flow)[a];
+ if (!_tolerance.positive(rem)) continue;
+ Node v = _graph.target(a);
+ if (!(*_active)[v] && !(*_source_set)[v]) {
+ activate(v);
+ }
+ (*_excess)[v] += rem;
+ (*_flow)[a] = 0;
+ }
+
+ target = new_target;
+ if ((*_active)[target]) {
+ deactivate(target);
+ }
+
+ _highest = _sets.back().begin();
+ while (_highest != _sets.back().end() &&
+ !(*_active)[_first[*_highest]]) {
+ ++_highest;
+ }
+ }
+ }
+ }
+
+ public:
+
+ /// \name Execution Control
+ /// The simplest way to execute the algorithm is to use
+ /// one of the member functions called \ref run().
+ /// \n
+ /// If you need better control on the execution,
+ /// you have to call one of the \ref init() functions first, then
+ /// \ref calculateOut() and/or \ref calculateIn().
+
+ /// @{
+
+ /// \brief Initialize the internal data structures.
+ ///
+ /// This function initializes the internal data structures. It creates
+ /// the maps and some bucket structures for the algorithm.
+ /// The first node is used as the source node for the push-relabel
+ /// algorithm.
+ void init() {
+ init(NodeIt(_graph));
+ }
+
+ /// \brief Initialize the internal data structures.
+ ///
+ /// This function initializes the internal data structures. It creates
+ /// the maps and some bucket structures for the algorithm.
+ /// The given node is used as the source node for the push-relabel
+ /// algorithm.
+ void init(const Node& source) {
+ _source = source;
+
+ _node_num = countNodes(_graph);
+
+ _first.resize(_node_num);
+ _last.resize(_node_num);
+
+ _dormant.resize(_node_num);
+
+ if (!_flow) {
+ _flow = new FlowMap(_graph);
+ }
+ if (!_next) {
+ _next = new typename Digraph::template NodeMap<Node>(_graph);
+ }
+ if (!_prev) {
+ _prev = new typename Digraph::template NodeMap<Node>(_graph);
+ }
+ if (!_active) {
+ _active = new typename Digraph::template NodeMap<bool>(_graph);
+ }
+ if (!_bucket) {
+ _bucket = new typename Digraph::template NodeMap<int>(_graph);
+ }
+ if (!_excess) {
+ _excess = new ExcessMap(_graph);
+ }
+ if (!_source_set) {
+ _source_set = new SourceSetMap(_graph);
+ }
+ if (!_min_cut_map) {
+ _min_cut_map = new MinCutMap(_graph);
+ }
+
+ _min_cut = std::numeric_limits<Value>::max();
+ }
+
+
+ /// \brief Calculate a minimum cut with \f$ source \f$ on the
+ /// source-side.
+ ///
+ /// This function calculates a minimum cut with \f$ source \f$ on the
+ /// source-side (i.e. a set \f$ X\subsetneq V \f$ with
+ /// \f$ source \in X \f$ and minimal outgoing capacity).
+ /// It updates the stored cut if (and only if) the newly found one
+ /// is better.
+ ///
+ /// \pre \ref init() must be called before using this function.
+ void calculateOut() {
+ findMinCutOut();
+ }
+
+ /// \brief Calculate a minimum cut with \f$ source \f$ on the
+ /// sink-side.
+ ///
+ /// This function calculates a minimum cut with \f$ source \f$ on the
+ /// sink-side (i.e. a set \f$ X\subsetneq V \f$ with
+ /// \f$ source \notin X \f$ and minimal outgoing capacity).
+ /// It updates the stored cut if (and only if) the newly found one
+ /// is better.
+ ///
+ /// \pre \ref init() must be called before using this function.
+ void calculateIn() {
+ findMinCutIn();
+ }
+
+
+ /// \brief Run the algorithm.
+ ///
+ /// This function runs the algorithm. It chooses source node,
+ /// then calls \ref init(), \ref calculateOut()
+ /// and \ref calculateIn().
+ void run() {
+ init();
+ calculateOut();
+ calculateIn();
+ }
+
+ /// \brief Run the algorithm.
+ ///
+ /// This function runs the algorithm. It calls \ref init(),
+ /// \ref calculateOut() and \ref calculateIn() with the given
+ /// source node.
+ void run(const Node& s) {
+ init(s);
+ calculateOut();
+ calculateIn();
+ }
+
+ /// @}
+
+ /// \name Query Functions
+ /// The result of the %HaoOrlin algorithm
+ /// can be obtained using these functions.\n
+ /// \ref run(), \ref calculateOut() or \ref calculateIn()
+ /// should be called before using them.
+
+ /// @{
+
+ /// \brief Return the value of the minimum cut.
+ ///
+ /// This function returns the value of the best cut found by the
+ /// previously called \ref run(), \ref calculateOut() or \ref
+ /// calculateIn().
+ ///
+ /// \pre \ref run(), \ref calculateOut() or \ref calculateIn()
+ /// must be called before using this function.
+ Value minCutValue() const {
+ return _min_cut;
+ }
+
+
+ /// \brief Return a minimum cut.
+ ///
+ /// This function gives the best cut found by the
+ /// previously called \ref run(), \ref calculateOut() or \ref
+ /// calculateIn().
+ ///
+ /// It sets \c cutMap to the characteristic vector of the found
+ /// minimum value cut - a non-empty set \f$ X\subsetneq V \f$
+ /// of minimum outgoing capacity (i.e. \c cutMap will be \c true exactly
+ /// for the nodes of \f$ X \f$).
+ ///
+ /// \param cutMap A \ref concepts::WriteMap "writable" node map with
+ /// \c bool (or convertible) value type.
+ ///
+ /// \return The value of the minimum cut.
+ ///
+ /// \pre \ref run(), \ref calculateOut() or \ref calculateIn()
+ /// must be called before using this function.
+ template <typename CutMap>
+ Value minCutMap(CutMap& cutMap) const {
+ for (NodeIt it(_graph); it != INVALID; ++it) {
+ cutMap.set(it, (*_min_cut_map)[it]);
+ }
+ return _min_cut;
+ }
+
+ /// @}
+
+ }; //class HaoOrlin
+
+} //namespace lemon
+
+#endif //LEMON_HAO_ORLIN_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/hartmann_orlin_mmc.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/hartmann_orlin_mmc.h
new file mode 100644
index 00000000000..6b60a85ed7a
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/hartmann_orlin_mmc.h
@@ -0,0 +1,654 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_HARTMANN_ORLIN_MMC_H
+#define LEMON_HARTMANN_ORLIN_MMC_H
+
+/// \ingroup min_mean_cycle
+///
+/// \file
+/// \brief Hartmann-Orlin's algorithm for finding a minimum mean cycle.
+
+#include <vector>
+#include <limits>
+#include <lemon/core.h>
+#include <lemon/path.h>
+#include <lemon/tolerance.h>
+#include <lemon/connectivity.h>
+
+namespace lemon {
+
+ /// \brief Default traits class of HartmannOrlinMmc class.
+ ///
+ /// Default traits class of HartmannOrlinMmc class.
+ /// \tparam GR The type of the digraph.
+ /// \tparam CM The type of the cost map.
+ /// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
+#ifdef DOXYGEN
+ template <typename GR, typename CM>
+#else
+ template <typename GR, typename CM,
+ bool integer = std::numeric_limits<typename CM::Value>::is_integer>
+#endif
+ struct HartmannOrlinMmcDefaultTraits
+ {
+ /// The type of the digraph
+ typedef GR Digraph;
+ /// The type of the cost map
+ typedef CM CostMap;
+ /// The type of the arc costs
+ typedef typename CostMap::Value Cost;
+
+ /// \brief The large cost type used for internal computations
+ ///
+ /// The large cost type used for internal computations.
+ /// It is \c long \c long if the \c Cost type is integer,
+ /// otherwise it is \c double.
+ /// \c Cost must be convertible to \c LargeCost.
+ typedef double LargeCost;
+
+ /// The tolerance type used for internal computations
+ typedef lemon::Tolerance<LargeCost> Tolerance;
+
+ /// \brief The path type of the found cycles
+ ///
+ /// The path type of the found cycles.
+ /// It must conform to the \ref lemon::concepts::Path "Path" concept
+ /// and it must have an \c addFront() function.
+ typedef lemon::Path<Digraph> Path;
+ };
+
+ // Default traits class for integer cost types
+ template <typename GR, typename CM>
+ struct HartmannOrlinMmcDefaultTraits<GR, CM, true>
+ {
+ typedef GR Digraph;
+ typedef CM CostMap;
+ typedef typename CostMap::Value Cost;
+#ifdef LEMON_HAVE_LONG_LONG
+ typedef long long LargeCost;
+#else
+ typedef long LargeCost;
+#endif
+ typedef lemon::Tolerance<LargeCost> Tolerance;
+ typedef lemon::Path<Digraph> Path;
+ };
+
+
+ /// \addtogroup min_mean_cycle
+ /// @{
+
+ /// \brief Implementation of the Hartmann-Orlin algorithm for finding
+ /// a minimum mean cycle.
+ ///
+ /// This class implements the Hartmann-Orlin algorithm for finding
+ /// a directed cycle of minimum mean cost in a digraph
+ /// \cite hartmann93finding, \cite dasdan98minmeancycle.
+ /// This method is based on \ref KarpMmc "Karp"'s original algorithm, but
+ /// applies an early termination scheme. It makes the algorithm
+ /// significantly faster for some problem instances, but slower for others.
+ /// The algorithm runs in time O(nm) and uses space O(n<sup>2</sup>+m).
+ ///
+ /// \tparam GR The type of the digraph the algorithm runs on.
+ /// \tparam CM The type of the cost map. The default
+ /// map type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
+ /// \tparam TR The traits class that defines various types used by the
+ /// algorithm. By default, it is \ref HartmannOrlinMmcDefaultTraits
+ /// "HartmannOrlinMmcDefaultTraits<GR, CM>".
+ /// In most cases, this parameter should not be set directly,
+ /// consider to use the named template parameters instead.
+#ifdef DOXYGEN
+ template <typename GR, typename CM, typename TR>
+#else
+ template < typename GR,
+ typename CM = typename GR::template ArcMap<int>,
+ typename TR = HartmannOrlinMmcDefaultTraits<GR, CM> >
+#endif
+ class HartmannOrlinMmc
+ {
+ public:
+
+ /// The type of the digraph
+ typedef typename TR::Digraph Digraph;
+ /// The type of the cost map
+ typedef typename TR::CostMap CostMap;
+ /// The type of the arc costs
+ typedef typename TR::Cost Cost;
+
+ /// \brief The large cost type
+ ///
+ /// The large cost type used for internal computations.
+ /// By default, it is \c long \c long if the \c Cost type is integer,
+ /// otherwise it is \c double.
+ typedef typename TR::LargeCost LargeCost;
+
+ /// The tolerance type
+ typedef typename TR::Tolerance Tolerance;
+
+ /// \brief The path type of the found cycles
+ ///
+ /// The path type of the found cycles.
+ /// Using the \ref lemon::HartmannOrlinMmcDefaultTraits
+ /// "default traits class",
+ /// it is \ref lemon::Path "Path<Digraph>".
+ typedef typename TR::Path Path;
+
+ /// \brief The
+ /// \ref lemon::HartmannOrlinMmcDefaultTraits "traits class"
+ /// of the algorithm
+ typedef TR Traits;
+
+ private:
+
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+
+ // Data sturcture for path data
+ struct PathData
+ {
+ LargeCost dist;
+ Arc pred;
+ PathData(LargeCost d, Arc p = INVALID) :
+ dist(d), pred(p) {}
+ };
+
+ typedef typename Digraph::template NodeMap<std::vector<PathData> >
+ PathDataNodeMap;
+
+ private:
+
+ // The digraph the algorithm runs on
+ const Digraph &_gr;
+ // The cost of the arcs
+ const CostMap &_cost;
+
+ // Data for storing the strongly connected components
+ int _comp_num;
+ typename Digraph::template NodeMap<int> _comp;
+ std::vector<std::vector<Node> > _comp_nodes;
+ std::vector<Node>* _nodes;
+ typename Digraph::template NodeMap<std::vector<Arc> > _out_arcs;
+
+ // Data for the found cycles
+ bool _curr_found, _best_found;
+ LargeCost _curr_cost, _best_cost;
+ int _curr_size, _best_size;
+ Node _curr_node, _best_node;
+ int _curr_level, _best_level;
+
+ Path *_cycle_path;
+ bool _local_path;
+
+ // Node map for storing path data
+ PathDataNodeMap _data;
+ // The processed nodes in the last round
+ std::vector<Node> _process;
+
+ Tolerance _tolerance;
+
+ // Infinite constant
+ const LargeCost INF;
+
+ public:
+
+ /// \name Named Template Parameters
+ /// @{
+
+ template <typename T>
+ struct SetLargeCostTraits : public Traits {
+ typedef T LargeCost;
+ typedef lemon::Tolerance<T> Tolerance;
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// \c LargeCost type.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting \c LargeCost
+ /// type. It is used for internal computations in the algorithm.
+ template <typename T>
+ struct SetLargeCost
+ : public HartmannOrlinMmc<GR, CM, SetLargeCostTraits<T> > {
+ typedef HartmannOrlinMmc<GR, CM, SetLargeCostTraits<T> > Create;
+ };
+
+ template <typename T>
+ struct SetPathTraits : public Traits {
+ typedef T Path;
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// \c %Path type.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting the \c %Path
+ /// type of the found cycles.
+ /// It must conform to the \ref lemon::concepts::Path "Path" concept
+ /// and it must have an \c addFront() function.
+ template <typename T>
+ struct SetPath
+ : public HartmannOrlinMmc<GR, CM, SetPathTraits<T> > {
+ typedef HartmannOrlinMmc<GR, CM, SetPathTraits<T> > Create;
+ };
+
+ /// @}
+
+ protected:
+
+ HartmannOrlinMmc() {}
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// The constructor of the class.
+ ///
+ /// \param digraph The digraph the algorithm runs on.
+ /// \param cost The costs of the arcs.
+ HartmannOrlinMmc( const Digraph &digraph,
+ const CostMap &cost ) :
+ _gr(digraph), _cost(cost), _comp(digraph), _out_arcs(digraph),
+ _best_found(false), _best_cost(0), _best_size(1),
+ _cycle_path(NULL), _local_path(false), _data(digraph),
+ INF(std::numeric_limits<LargeCost>::has_infinity ?
+ std::numeric_limits<LargeCost>::infinity() :
+ std::numeric_limits<LargeCost>::max())
+ {}
+
+ /// Destructor.
+ ~HartmannOrlinMmc() {
+ if (_local_path) delete _cycle_path;
+ }
+
+ /// \brief Set the path structure for storing the found cycle.
+ ///
+ /// This function sets an external path structure for storing the
+ /// found cycle.
+ ///
+ /// If you don't call this function before calling \ref run() or
+ /// \ref findCycleMean(), a local \ref Path "path" structure
+ /// will be allocated. The destuctor deallocates this automatically
+ /// allocated object, of course.
+ ///
+ /// \note The algorithm calls only the \ref lemon::Path::addFront()
+ /// "addFront()" function of the given path structure.
+ ///
+ /// \return <tt>(*this)</tt>
+ HartmannOrlinMmc& cycle(Path &path) {
+ if (_local_path) {
+ delete _cycle_path;
+ _local_path = false;
+ }
+ _cycle_path = &path;
+ return *this;
+ }
+
+ /// \brief Set the tolerance used by the algorithm.
+ ///
+ /// This function sets the tolerance object used by the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ HartmannOrlinMmc& tolerance(const Tolerance& tolerance) {
+ _tolerance = tolerance;
+ return *this;
+ }
+
+ /// \brief Return a const reference to the tolerance.
+ ///
+ /// This function returns a const reference to the tolerance object
+ /// used by the algorithm.
+ const Tolerance& tolerance() const {
+ return _tolerance;
+ }
+
+ /// \name Execution control
+ /// The simplest way to execute the algorithm is to call the \ref run()
+ /// function.\n
+ /// If you only need the minimum mean cost, you may call
+ /// \ref findCycleMean().
+
+ /// @{
+
+ /// \brief Run the algorithm.
+ ///
+ /// This function runs the algorithm.
+ /// It can be called more than once (e.g. if the underlying digraph
+ /// and/or the arc costs have been modified).
+ ///
+ /// \return \c true if a directed cycle exists in the digraph.
+ ///
+ /// \note <tt>mmc.run()</tt> is just a shortcut of the following code.
+ /// \code
+ /// return mmc.findCycleMean() && mmc.findCycle();
+ /// \endcode
+ bool run() {
+ return findCycleMean() && findCycle();
+ }
+
+ /// \brief Find the minimum cycle mean.
+ ///
+ /// This function finds the minimum mean cost of the directed
+ /// cycles in the digraph.
+ ///
+ /// \return \c true if a directed cycle exists in the digraph.
+ bool findCycleMean() {
+ // Initialization and find strongly connected components
+ init();
+ findComponents();
+
+ // Find the minimum cycle mean in the components
+ for (int comp = 0; comp < _comp_num; ++comp) {
+ if (!initComponent(comp)) continue;
+ processRounds();
+
+ // Update the best cycle (global minimum mean cycle)
+ if ( _curr_found && (!_best_found ||
+ _curr_cost * _best_size < _best_cost * _curr_size) ) {
+ _best_found = true;
+ _best_cost = _curr_cost;
+ _best_size = _curr_size;
+ _best_node = _curr_node;
+ _best_level = _curr_level;
+ }
+ }
+ return _best_found;
+ }
+
+ /// \brief Find a minimum mean directed cycle.
+ ///
+ /// This function finds a directed cycle of minimum mean cost
+ /// in the digraph using the data computed by findCycleMean().
+ ///
+ /// \return \c true if a directed cycle exists in the digraph.
+ ///
+ /// \pre \ref findCycleMean() must be called before using this function.
+ bool findCycle() {
+ if (!_best_found) return false;
+ IntNodeMap reached(_gr, -1);
+ int r = _best_level + 1;
+ Node u = _best_node;
+ while (reached[u] < 0) {
+ reached[u] = --r;
+ u = _gr.source(_data[u][r].pred);
+ }
+ r = reached[u];
+ Arc e = _data[u][r].pred;
+ _cycle_path->addFront(e);
+ _best_cost = _cost[e];
+ _best_size = 1;
+ Node v;
+ while ((v = _gr.source(e)) != u) {
+ e = _data[v][--r].pred;
+ _cycle_path->addFront(e);
+ _best_cost += _cost[e];
+ ++_best_size;
+ }
+ return true;
+ }
+
+ /// @}
+
+ /// \name Query Functions
+ /// The results of the algorithm can be obtained using these
+ /// functions.\n
+ /// The algorithm should be executed before using them.
+
+ /// @{
+
+ /// \brief Return the total cost of the found cycle.
+ ///
+ /// This function returns the total cost of the found cycle.
+ ///
+ /// \pre \ref run() or \ref findCycleMean() must be called before
+ /// using this function.
+ Cost cycleCost() const {
+ return static_cast<Cost>(_best_cost);
+ }
+
+ /// \brief Return the number of arcs on the found cycle.
+ ///
+ /// This function returns the number of arcs on the found cycle.
+ ///
+ /// \pre \ref run() or \ref findCycleMean() must be called before
+ /// using this function.
+ int cycleSize() const {
+ return _best_size;
+ }
+
+ /// \brief Return the mean cost of the found cycle.
+ ///
+ /// This function returns the mean cost of the found cycle.
+ ///
+ /// \note <tt>alg.cycleMean()</tt> is just a shortcut of the
+ /// following code.
+ /// \code
+ /// return static_cast<double>(alg.cycleCost()) / alg.cycleSize();
+ /// \endcode
+ ///
+ /// \pre \ref run() or \ref findCycleMean() must be called before
+ /// using this function.
+ double cycleMean() const {
+ return static_cast<double>(_best_cost) / _best_size;
+ }
+
+ /// \brief Return the found cycle.
+ ///
+ /// This function returns a const reference to the path structure
+ /// storing the found cycle.
+ ///
+ /// \pre \ref run() or \ref findCycle() must be called before using
+ /// this function.
+ const Path& cycle() const {
+ return *_cycle_path;
+ }
+
+ ///@}
+
+ private:
+
+ // Initialization
+ void init() {
+ if (!_cycle_path) {
+ _local_path = true;
+ _cycle_path = new Path;
+ }
+ _cycle_path->clear();
+ _best_found = false;
+ _best_cost = 0;
+ _best_size = 1;
+ _cycle_path->clear();
+ for (NodeIt u(_gr); u != INVALID; ++u)
+ _data[u].clear();
+ }
+
+ // Find strongly connected components and initialize _comp_nodes
+ // and _out_arcs
+ void findComponents() {
+ _comp_num = stronglyConnectedComponents(_gr, _comp);
+ _comp_nodes.resize(_comp_num);
+ if (_comp_num == 1) {
+ _comp_nodes[0].clear();
+ for (NodeIt n(_gr); n != INVALID; ++n) {
+ _comp_nodes[0].push_back(n);
+ _out_arcs[n].clear();
+ for (OutArcIt a(_gr, n); a != INVALID; ++a) {
+ _out_arcs[n].push_back(a);
+ }
+ }
+ } else {
+ for (int i = 0; i < _comp_num; ++i)
+ _comp_nodes[i].clear();
+ for (NodeIt n(_gr); n != INVALID; ++n) {
+ int k = _comp[n];
+ _comp_nodes[k].push_back(n);
+ _out_arcs[n].clear();
+ for (OutArcIt a(_gr, n); a != INVALID; ++a) {
+ if (_comp[_gr.target(a)] == k) _out_arcs[n].push_back(a);
+ }
+ }
+ }
+ }
+
+ // Initialize path data for the current component
+ bool initComponent(int comp) {
+ _nodes = &(_comp_nodes[comp]);
+ int n = _nodes->size();
+ if (n < 1 || (n == 1 && _out_arcs[(*_nodes)[0]].size() == 0)) {
+ return false;
+ }
+ for (int i = 0; i < n; ++i) {
+ _data[(*_nodes)[i]].resize(n + 1, PathData(INF));
+ }
+ return true;
+ }
+
+ // Process all rounds of computing path data for the current component.
+ // _data[v][k] is the cost of a shortest directed walk from the root
+ // node to node v containing exactly k arcs.
+ void processRounds() {
+ Node start = (*_nodes)[0];
+ _data[start][0] = PathData(0);
+ _process.clear();
+ _process.push_back(start);
+
+ int k, n = _nodes->size();
+ int next_check = 4;
+ bool terminate = false;
+ for (k = 1; k <= n && int(_process.size()) < n && !terminate; ++k) {
+ processNextBuildRound(k);
+ if (k == next_check || k == n) {
+ terminate = checkTermination(k);
+ next_check = next_check * 3 / 2;
+ }
+ }
+ for ( ; k <= n && !terminate; ++k) {
+ processNextFullRound(k);
+ if (k == next_check || k == n) {
+ terminate = checkTermination(k);
+ next_check = next_check * 3 / 2;
+ }
+ }
+ }
+
+ // Process one round and rebuild _process
+ void processNextBuildRound(int k) {
+ std::vector<Node> next;
+ Node u, v;
+ Arc e;
+ LargeCost d;
+ for (int i = 0; i < int(_process.size()); ++i) {
+ u = _process[i];
+ for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
+ e = _out_arcs[u][j];
+ v = _gr.target(e);
+ d = _data[u][k-1].dist + _cost[e];
+ if (_tolerance.less(d, _data[v][k].dist)) {
+ if (_data[v][k].dist == INF) next.push_back(v);
+ _data[v][k] = PathData(d, e);
+ }
+ }
+ }
+ _process.swap(next);
+ }
+
+ // Process one round using _nodes instead of _process
+ void processNextFullRound(int k) {
+ Node u, v;
+ Arc e;
+ LargeCost d;
+ for (int i = 0; i < int(_nodes->size()); ++i) {
+ u = (*_nodes)[i];
+ for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
+ e = _out_arcs[u][j];
+ v = _gr.target(e);
+ d = _data[u][k-1].dist + _cost[e];
+ if (_tolerance.less(d, _data[v][k].dist)) {
+ _data[v][k] = PathData(d, e);
+ }
+ }
+ }
+ }
+
+ // Check early termination
+ bool checkTermination(int k) {
+ typedef std::pair<int, int> Pair;
+ typename GR::template NodeMap<Pair> level(_gr, Pair(-1, 0));
+ typename GR::template NodeMap<LargeCost> pi(_gr);
+ int n = _nodes->size();
+ LargeCost cost;
+ int size;
+ Node u;
+
+ // Search for cycles that are already found
+ _curr_found = false;
+ for (int i = 0; i < n; ++i) {
+ u = (*_nodes)[i];
+ if (_data[u][k].dist == INF) continue;
+ for (int j = k; j >= 0; --j) {
+ if (level[u].first == i && level[u].second > 0) {
+ // A cycle is found
+ cost = _data[u][level[u].second].dist - _data[u][j].dist;
+ size = level[u].second - j;
+ if (!_curr_found || cost * _curr_size < _curr_cost * size) {
+ _curr_cost = cost;
+ _curr_size = size;
+ _curr_node = u;
+ _curr_level = level[u].second;
+ _curr_found = true;
+ }
+ }
+ level[u] = Pair(i, j);
+ if (j != 0) {
+ u = _gr.source(_data[u][j].pred);
+ }
+ }
+ }
+
+ // If at least one cycle is found, check the optimality condition
+ LargeCost d;
+ if (_curr_found && k < n) {
+ // Find node potentials
+ for (int i = 0; i < n; ++i) {
+ u = (*_nodes)[i];
+ pi[u] = INF;
+ for (int j = 0; j <= k; ++j) {
+ if (_data[u][j].dist < INF) {
+ d = _data[u][j].dist * _curr_size - j * _curr_cost;
+ if (_tolerance.less(d, pi[u])) pi[u] = d;
+ }
+ }
+ }
+
+ // Check the optimality condition for all arcs
+ bool done = true;
+ for (ArcIt a(_gr); a != INVALID; ++a) {
+ if (_tolerance.less(_cost[a] * _curr_size - _curr_cost,
+ pi[_gr.target(a)] - pi[_gr.source(a)]) ) {
+ done = false;
+ break;
+ }
+ }
+ return done;
+ }
+ return (k == n);
+ }
+
+ }; //class HartmannOrlinMmc
+
+ ///@}
+
+} //namespace lemon
+
+#endif //LEMON_HARTMANN_ORLIN_MMC_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/howard_mmc.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/howard_mmc.h
new file mode 100644
index 00000000000..690236340ff
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/howard_mmc.h
@@ -0,0 +1,651 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_HOWARD_MMC_H
+#define LEMON_HOWARD_MMC_H
+
+/// \ingroup min_mean_cycle
+///
+/// \file
+/// \brief Howard's algorithm for finding a minimum mean cycle.
+
+#include <vector>
+#include <limits>
+#include <lemon/core.h>
+#include <lemon/path.h>
+#include <lemon/tolerance.h>
+#include <lemon/connectivity.h>
+
+namespace lemon {
+
+ /// \brief Default traits class of HowardMmc class.
+ ///
+ /// Default traits class of HowardMmc class.
+ /// \tparam GR The type of the digraph.
+ /// \tparam CM The type of the cost map.
+ /// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
+#ifdef DOXYGEN
+ template <typename GR, typename CM>
+#else
+ template <typename GR, typename CM,
+ bool integer = std::numeric_limits<typename CM::Value>::is_integer>
+#endif
+ struct HowardMmcDefaultTraits
+ {
+ /// The type of the digraph
+ typedef GR Digraph;
+ /// The type of the cost map
+ typedef CM CostMap;
+ /// The type of the arc costs
+ typedef typename CostMap::Value Cost;
+
+ /// \brief The large cost type used for internal computations
+ ///
+ /// The large cost type used for internal computations.
+ /// It is \c long \c long if the \c Cost type is integer,
+ /// otherwise it is \c double.
+ /// \c Cost must be convertible to \c LargeCost.
+ typedef double LargeCost;
+
+ /// The tolerance type used for internal computations
+ typedef lemon::Tolerance<LargeCost> Tolerance;
+
+ /// \brief The path type of the found cycles
+ ///
+ /// The path type of the found cycles.
+ /// It must conform to the \ref lemon::concepts::Path "Path" concept
+ /// and it must have an \c addBack() function.
+ typedef lemon::Path<Digraph> Path;
+ };
+
+ // Default traits class for integer cost types
+ template <typename GR, typename CM>
+ struct HowardMmcDefaultTraits<GR, CM, true>
+ {
+ typedef GR Digraph;
+ typedef CM CostMap;
+ typedef typename CostMap::Value Cost;
+#ifdef LEMON_HAVE_LONG_LONG
+ typedef long long LargeCost;
+#else
+ typedef long LargeCost;
+#endif
+ typedef lemon::Tolerance<LargeCost> Tolerance;
+ typedef lemon::Path<Digraph> Path;
+ };
+
+
+ /// \addtogroup min_mean_cycle
+ /// @{
+
+ /// \brief Implementation of Howard's algorithm for finding a minimum
+ /// mean cycle.
+ ///
+ /// This class implements Howard's policy iteration algorithm for finding
+ /// a directed cycle of minimum mean cost in a digraph
+ /// \cite dasdan98minmeancycle, \cite dasdan04experimental.
+ /// This class provides the most efficient algorithm for the
+ /// minimum mean cycle problem, though the best known theoretical
+ /// bound on its running time is exponential.
+ ///
+ /// \tparam GR The type of the digraph the algorithm runs on.
+ /// \tparam CM The type of the cost map. The default
+ /// map type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
+ /// \tparam TR The traits class that defines various types used by the
+ /// algorithm. By default, it is \ref HowardMmcDefaultTraits
+ /// "HowardMmcDefaultTraits<GR, CM>".
+ /// In most cases, this parameter should not be set directly,
+ /// consider to use the named template parameters instead.
+#ifdef DOXYGEN
+ template <typename GR, typename CM, typename TR>
+#else
+ template < typename GR,
+ typename CM = typename GR::template ArcMap<int>,
+ typename TR = HowardMmcDefaultTraits<GR, CM> >
+#endif
+ class HowardMmc
+ {
+ public:
+
+ /// The type of the digraph
+ typedef typename TR::Digraph Digraph;
+ /// The type of the cost map
+ typedef typename TR::CostMap CostMap;
+ /// The type of the arc costs
+ typedef typename TR::Cost Cost;
+
+ /// \brief The large cost type
+ ///
+ /// The large cost type used for internal computations.
+ /// By default, it is \c long \c long if the \c Cost type is integer,
+ /// otherwise it is \c double.
+ typedef typename TR::LargeCost LargeCost;
+
+ /// The tolerance type
+ typedef typename TR::Tolerance Tolerance;
+
+ /// \brief The path type of the found cycles
+ ///
+ /// The path type of the found cycles.
+ /// Using the \ref lemon::HowardMmcDefaultTraits "default traits class",
+ /// it is \ref lemon::Path "Path<Digraph>".
+ typedef typename TR::Path Path;
+
+ /// The \ref lemon::HowardMmcDefaultTraits "traits class" of the algorithm
+ typedef TR Traits;
+
+ /// \brief Constants for the causes of search termination.
+ ///
+ /// Enum type containing constants for the different causes of search
+ /// termination. The \ref findCycleMean() function returns one of
+ /// these values.
+ enum TerminationCause {
+
+ /// No directed cycle can be found in the digraph.
+ NO_CYCLE = 0,
+
+ /// Optimal solution (minimum cycle mean) is found.
+ OPTIMAL = 1,
+
+ /// The iteration count limit is reached.
+ ITERATION_LIMIT
+ };
+
+ private:
+
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+
+ // The digraph the algorithm runs on
+ const Digraph &_gr;
+ // The cost of the arcs
+ const CostMap &_cost;
+
+ // Data for the found cycles
+ bool _curr_found, _best_found;
+ LargeCost _curr_cost, _best_cost;
+ int _curr_size, _best_size;
+ Node _curr_node, _best_node;
+
+ Path *_cycle_path;
+ bool _local_path;
+
+ // Internal data used by the algorithm
+ typename Digraph::template NodeMap<Arc> _policy;
+ typename Digraph::template NodeMap<bool> _reached;
+ typename Digraph::template NodeMap<int> _level;
+ typename Digraph::template NodeMap<LargeCost> _dist;
+
+ // Data for storing the strongly connected components
+ int _comp_num;
+ typename Digraph::template NodeMap<int> _comp;
+ std::vector<std::vector<Node> > _comp_nodes;
+ std::vector<Node>* _nodes;
+ typename Digraph::template NodeMap<std::vector<Arc> > _in_arcs;
+
+ // Queue used for BFS search
+ std::vector<Node> _queue;
+ int _qfront, _qback;
+
+ Tolerance _tolerance;
+
+ // Infinite constant
+ const LargeCost INF;
+
+ public:
+
+ /// \name Named Template Parameters
+ /// @{
+
+ template <typename T>
+ struct SetLargeCostTraits : public Traits {
+ typedef T LargeCost;
+ typedef lemon::Tolerance<T> Tolerance;
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// \c LargeCost type.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting \c LargeCost
+ /// type. It is used for internal computations in the algorithm.
+ template <typename T>
+ struct SetLargeCost
+ : public HowardMmc<GR, CM, SetLargeCostTraits<T> > {
+ typedef HowardMmc<GR, CM, SetLargeCostTraits<T> > Create;
+ };
+
+ template <typename T>
+ struct SetPathTraits : public Traits {
+ typedef T Path;
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// \c %Path type.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting the \c %Path
+ /// type of the found cycles.
+ /// It must conform to the \ref lemon::concepts::Path "Path" concept
+ /// and it must have an \c addBack() function.
+ template <typename T>
+ struct SetPath
+ : public HowardMmc<GR, CM, SetPathTraits<T> > {
+ typedef HowardMmc<GR, CM, SetPathTraits<T> > Create;
+ };
+
+ /// @}
+
+ protected:
+
+ HowardMmc() {}
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// The constructor of the class.
+ ///
+ /// \param digraph The digraph the algorithm runs on.
+ /// \param cost The costs of the arcs.
+ HowardMmc( const Digraph &digraph,
+ const CostMap &cost ) :
+ _gr(digraph), _cost(cost), _best_found(false),
+ _best_cost(0), _best_size(1), _cycle_path(NULL), _local_path(false),
+ _policy(digraph), _reached(digraph), _level(digraph), _dist(digraph),
+ _comp(digraph), _in_arcs(digraph),
+ INF(std::numeric_limits<LargeCost>::has_infinity ?
+ std::numeric_limits<LargeCost>::infinity() :
+ std::numeric_limits<LargeCost>::max())
+ {}
+
+ /// Destructor.
+ ~HowardMmc() {
+ if (_local_path) delete _cycle_path;
+ }
+
+ /// \brief Set the path structure for storing the found cycle.
+ ///
+ /// This function sets an external path structure for storing the
+ /// found cycle.
+ ///
+ /// If you don't call this function before calling \ref run() or
+ /// \ref findCycleMean(), a local \ref Path "path" structure
+ /// will be allocated. The destuctor deallocates this automatically
+ /// allocated object, of course.
+ ///
+ /// \note The algorithm calls only the \ref lemon::Path::addBack()
+ /// "addBack()" function of the given path structure.
+ ///
+ /// \return <tt>(*this)</tt>
+ HowardMmc& cycle(Path &path) {
+ if (_local_path) {
+ delete _cycle_path;
+ _local_path = false;
+ }
+ _cycle_path = &path;
+ return *this;
+ }
+
+ /// \brief Set the tolerance used by the algorithm.
+ ///
+ /// This function sets the tolerance object used by the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ HowardMmc& tolerance(const Tolerance& tolerance) {
+ _tolerance = tolerance;
+ return *this;
+ }
+
+ /// \brief Return a const reference to the tolerance.
+ ///
+ /// This function returns a const reference to the tolerance object
+ /// used by the algorithm.
+ const Tolerance& tolerance() const {
+ return _tolerance;
+ }
+
+ /// \name Execution control
+ /// The simplest way to execute the algorithm is to call the \ref run()
+ /// function.\n
+ /// If you only need the minimum mean cost, you may call
+ /// \ref findCycleMean().
+
+ /// @{
+
+ /// \brief Run the algorithm.
+ ///
+ /// This function runs the algorithm.
+ /// It can be called more than once (e.g. if the underlying digraph
+ /// and/or the arc costs have been modified).
+ ///
+ /// \return \c true if a directed cycle exists in the digraph.
+ ///
+ /// \note <tt>mmc.run()</tt> is just a shortcut of the following code.
+ /// \code
+ /// return mmc.findCycleMean() && mmc.findCycle();
+ /// \endcode
+ bool run() {
+ return findCycleMean() && findCycle();
+ }
+
+ /// \brief Find the minimum cycle mean (or an upper bound).
+ ///
+ /// This function finds the minimum mean cost of the directed
+ /// cycles in the digraph (or an upper bound for it).
+ ///
+ /// By default, the function finds the exact minimum cycle mean,
+ /// but an optional limit can also be specified for the number of
+ /// iterations performed during the search process.
+ /// The return value indicates if the optimal solution is found
+ /// or the iteration limit is reached. In the latter case, an
+ /// approximate solution is provided, which corresponds to a directed
+ /// cycle whose mean cost is relatively small, but not necessarily
+ /// minimal.
+ ///
+ /// \param limit The maximum allowed number of iterations during
+ /// the search process. Its default value implies that the algorithm
+ /// runs until it finds the exact optimal solution.
+ ///
+ /// \return The termination cause of the search process.
+ /// For more information, see \ref TerminationCause.
+ TerminationCause findCycleMean(int limit =
+ std::numeric_limits<int>::max()) {
+ // Initialize and find strongly connected components
+ init();
+ findComponents();
+
+ // Find the minimum cycle mean in the components
+ int iter_count = 0;
+ bool iter_limit_reached = false;
+ for (int comp = 0; comp < _comp_num; ++comp) {
+ // Find the minimum mean cycle in the current component
+ if (!buildPolicyGraph(comp)) continue;
+ while (true) {
+ if (++iter_count > limit) {
+ iter_limit_reached = true;
+ break;
+ }
+ findPolicyCycle();
+ if (!computeNodeDistances()) break;
+ }
+
+ // Update the best cycle (global minimum mean cycle)
+ if ( _curr_found && (!_best_found ||
+ _curr_cost * _best_size < _best_cost * _curr_size) ) {
+ _best_found = true;
+ _best_cost = _curr_cost;
+ _best_size = _curr_size;
+ _best_node = _curr_node;
+ }
+
+ if (iter_limit_reached) break;
+ }
+
+ if (iter_limit_reached) {
+ return ITERATION_LIMIT;
+ } else {
+ return _best_found ? OPTIMAL : NO_CYCLE;
+ }
+ }
+
+ /// \brief Find a minimum mean directed cycle.
+ ///
+ /// This function finds a directed cycle of minimum mean cost
+ /// in the digraph using the data computed by findCycleMean().
+ ///
+ /// \return \c true if a directed cycle exists in the digraph.
+ ///
+ /// \pre \ref findCycleMean() must be called before using this function.
+ bool findCycle() {
+ if (!_best_found) return false;
+ _cycle_path->addBack(_policy[_best_node]);
+ for ( Node v = _best_node;
+ (v = _gr.target(_policy[v])) != _best_node; ) {
+ _cycle_path->addBack(_policy[v]);
+ }
+ return true;
+ }
+
+ /// @}
+
+ /// \name Query Functions
+ /// The results of the algorithm can be obtained using these
+ /// functions.\n
+ /// The algorithm should be executed before using them.
+
+ /// @{
+
+ /// \brief Return the total cost of the found cycle.
+ ///
+ /// This function returns the total cost of the found cycle.
+ ///
+ /// \pre \ref run() or \ref findCycleMean() must be called before
+ /// using this function.
+ Cost cycleCost() const {
+ return static_cast<Cost>(_best_cost);
+ }
+
+ /// \brief Return the number of arcs on the found cycle.
+ ///
+ /// This function returns the number of arcs on the found cycle.
+ ///
+ /// \pre \ref run() or \ref findCycleMean() must be called before
+ /// using this function.
+ int cycleSize() const {
+ return _best_size;
+ }
+
+ /// \brief Return the mean cost of the found cycle.
+ ///
+ /// This function returns the mean cost of the found cycle.
+ ///
+ /// \note <tt>alg.cycleMean()</tt> is just a shortcut of the
+ /// following code.
+ /// \code
+ /// return static_cast<double>(alg.cycleCost()) / alg.cycleSize();
+ /// \endcode
+ ///
+ /// \pre \ref run() or \ref findCycleMean() must be called before
+ /// using this function.
+ double cycleMean() const {
+ return static_cast<double>(_best_cost) / _best_size;
+ }
+
+ /// \brief Return the found cycle.
+ ///
+ /// This function returns a const reference to the path structure
+ /// storing the found cycle.
+ ///
+ /// \pre \ref run() or \ref findCycle() must be called before using
+ /// this function.
+ const Path& cycle() const {
+ return *_cycle_path;
+ }
+
+ ///@}
+
+ private:
+
+ // Initialize
+ void init() {
+ if (!_cycle_path) {
+ _local_path = true;
+ _cycle_path = new Path;
+ }
+ _queue.resize(countNodes(_gr));
+ _best_found = false;
+ _best_cost = 0;
+ _best_size = 1;
+ _cycle_path->clear();
+ }
+
+ // Find strongly connected components and initialize _comp_nodes
+ // and _in_arcs
+ void findComponents() {
+ _comp_num = stronglyConnectedComponents(_gr, _comp);
+ _comp_nodes.resize(_comp_num);
+ if (_comp_num == 1) {
+ _comp_nodes[0].clear();
+ for (NodeIt n(_gr); n != INVALID; ++n) {
+ _comp_nodes[0].push_back(n);
+ _in_arcs[n].clear();
+ for (InArcIt a(_gr, n); a != INVALID; ++a) {
+ _in_arcs[n].push_back(a);
+ }
+ }
+ } else {
+ for (int i = 0; i < _comp_num; ++i)
+ _comp_nodes[i].clear();
+ for (NodeIt n(_gr); n != INVALID; ++n) {
+ int k = _comp[n];
+ _comp_nodes[k].push_back(n);
+ _in_arcs[n].clear();
+ for (InArcIt a(_gr, n); a != INVALID; ++a) {
+ if (_comp[_gr.source(a)] == k) _in_arcs[n].push_back(a);
+ }
+ }
+ }
+ }
+
+ // Build the policy graph in the given strongly connected component
+ // (the out-degree of every node is 1)
+ bool buildPolicyGraph(int comp) {
+ _nodes = &(_comp_nodes[comp]);
+ if (_nodes->size() < 1 ||
+ (_nodes->size() == 1 && _in_arcs[(*_nodes)[0]].size() == 0)) {
+ return false;
+ }
+ for (int i = 0; i < int(_nodes->size()); ++i) {
+ _dist[(*_nodes)[i]] = INF;
+ }
+ Node u, v;
+ Arc e;
+ for (int i = 0; i < int(_nodes->size()); ++i) {
+ v = (*_nodes)[i];
+ for (int j = 0; j < int(_in_arcs[v].size()); ++j) {
+ e = _in_arcs[v][j];
+ u = _gr.source(e);
+ if (_cost[e] < _dist[u]) {
+ _dist[u] = _cost[e];
+ _policy[u] = e;
+ }
+ }
+ }
+ return true;
+ }
+
+ // Find the minimum mean cycle in the policy graph
+ void findPolicyCycle() {
+ for (int i = 0; i < int(_nodes->size()); ++i) {
+ _level[(*_nodes)[i]] = -1;
+ }
+ LargeCost ccost;
+ int csize;
+ Node u, v;
+ _curr_found = false;
+ for (int i = 0; i < int(_nodes->size()); ++i) {
+ u = (*_nodes)[i];
+ if (_level[u] >= 0) continue;
+ for (; _level[u] < 0; u = _gr.target(_policy[u])) {
+ _level[u] = i;
+ }
+ if (_level[u] == i) {
+ // A cycle is found
+ ccost = _cost[_policy[u]];
+ csize = 1;
+ for (v = u; (v = _gr.target(_policy[v])) != u; ) {
+ ccost += _cost[_policy[v]];
+ ++csize;
+ }
+ if ( !_curr_found ||
+ (ccost * _curr_size < _curr_cost * csize) ) {
+ _curr_found = true;
+ _curr_cost = ccost;
+ _curr_size = csize;
+ _curr_node = u;
+ }
+ }
+ }
+ }
+
+ // Contract the policy graph and compute node distances
+ bool computeNodeDistances() {
+ // Find the component of the main cycle and compute node distances
+ // using reverse BFS
+ for (int i = 0; i < int(_nodes->size()); ++i) {
+ _reached[(*_nodes)[i]] = false;
+ }
+ _qfront = _qback = 0;
+ _queue[0] = _curr_node;
+ _reached[_curr_node] = true;
+ _dist[_curr_node] = 0;
+ Node u, v;
+ Arc e;
+ while (_qfront <= _qback) {
+ v = _queue[_qfront++];
+ for (int j = 0; j < int(_in_arcs[v].size()); ++j) {
+ e = _in_arcs[v][j];
+ u = _gr.source(e);
+ if (_policy[u] == e && !_reached[u]) {
+ _reached[u] = true;
+ _dist[u] = _dist[v] + _cost[e] * _curr_size - _curr_cost;
+ _queue[++_qback] = u;
+ }
+ }
+ }
+
+ // Connect all other nodes to this component and compute node
+ // distances using reverse BFS
+ _qfront = 0;
+ while (_qback < int(_nodes->size())-1) {
+ v = _queue[_qfront++];
+ for (int j = 0; j < int(_in_arcs[v].size()); ++j) {
+ e = _in_arcs[v][j];
+ u = _gr.source(e);
+ if (!_reached[u]) {
+ _reached[u] = true;
+ _policy[u] = e;
+ _dist[u] = _dist[v] + _cost[e] * _curr_size - _curr_cost;
+ _queue[++_qback] = u;
+ }
+ }
+ }
+
+ // Improve node distances
+ bool improved = false;
+ for (int i = 0; i < int(_nodes->size()); ++i) {
+ v = (*_nodes)[i];
+ for (int j = 0; j < int(_in_arcs[v].size()); ++j) {
+ e = _in_arcs[v][j];
+ u = _gr.source(e);
+ LargeCost delta = _dist[v] + _cost[e] * _curr_size - _curr_cost;
+ if (_tolerance.less(delta, _dist[u])) {
+ _dist[u] = delta;
+ _policy[u] = e;
+ improved = true;
+ }
+ }
+ }
+ return improved;
+ }
+
+ }; //class HowardMmc
+
+ ///@}
+
+} //namespace lemon
+
+#endif //LEMON_HOWARD_MMC_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/hypercube_graph.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/hypercube_graph.h
new file mode 100644
index 00000000000..2cf37ad49d2
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/hypercube_graph.h
@@ -0,0 +1,459 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef HYPERCUBE_GRAPH_H
+#define HYPERCUBE_GRAPH_H
+
+#include <vector>
+#include <lemon/core.h>
+#include <lemon/assert.h>
+#include <lemon/bits/graph_extender.h>
+
+///\ingroup graphs
+///\file
+///\brief HypercubeGraph class.
+
+namespace lemon {
+
+ class HypercubeGraphBase {
+
+ public:
+
+ typedef HypercubeGraphBase Graph;
+
+ class Node;
+ class Edge;
+ class Arc;
+
+ public:
+
+ HypercubeGraphBase() {}
+
+ protected:
+
+ void construct(int dim) {
+ LEMON_ASSERT(dim >= 1, "The number of dimensions must be at least 1.");
+ _dim = dim;
+ _node_num = 1 << dim;
+ _edge_num = dim * (1 << (dim-1));
+ }
+
+ public:
+
+ typedef True NodeNumTag;
+ typedef True EdgeNumTag;
+ typedef True ArcNumTag;
+
+ int nodeNum() const { return _node_num; }
+ int edgeNum() const { return _edge_num; }
+ int arcNum() const { return 2 * _edge_num; }
+
+ int maxNodeId() const { return _node_num - 1; }
+ int maxEdgeId() const { return _edge_num - 1; }
+ int maxArcId() const { return 2 * _edge_num - 1; }
+
+ static Node nodeFromId(int id) { return Node(id); }
+ static Edge edgeFromId(int id) { return Edge(id); }
+ static Arc arcFromId(int id) { return Arc(id); }
+
+ static int id(Node node) { return node._id; }
+ static int id(Edge edge) { return edge._id; }
+ static int id(Arc arc) { return arc._id; }
+
+ Node u(Edge edge) const {
+ int base = edge._id & ((1 << (_dim-1)) - 1);
+ int k = edge._id >> (_dim-1);
+ return ((base >> k) << (k+1)) | (base & ((1 << k) - 1));
+ }
+
+ Node v(Edge edge) const {
+ int base = edge._id & ((1 << (_dim-1)) - 1);
+ int k = edge._id >> (_dim-1);
+ return ((base >> k) << (k+1)) | (base & ((1 << k) - 1)) | (1 << k);
+ }
+
+ Node source(Arc arc) const {
+ return (arc._id & 1) == 1 ? u(arc) : v(arc);
+ }
+
+ Node target(Arc arc) const {
+ return (arc._id & 1) == 1 ? v(arc) : u(arc);
+ }
+
+ typedef True FindEdgeTag;
+ typedef True FindArcTag;
+
+ Edge findEdge(Node u, Node v, Edge prev = INVALID) const {
+ if (prev != INVALID) return INVALID;
+ int d = u._id ^ v._id;
+ int k = 0;
+ if (d == 0) return INVALID;
+ for ( ; (d & 1) == 0; d >>= 1) ++k;
+ if (d >> 1 != 0) return INVALID;
+ return (k << (_dim-1)) | ((u._id >> (k+1)) << k) |
+ (u._id & ((1 << k) - 1));
+ }
+
+ Arc findArc(Node u, Node v, Arc prev = INVALID) const {
+ Edge edge = findEdge(u, v, prev);
+ if (edge == INVALID) return INVALID;
+ int k = edge._id >> (_dim-1);
+ return ((u._id >> k) & 1) == 1 ? edge._id << 1 : (edge._id << 1) | 1;
+ }
+
+ class Node {
+ friend class HypercubeGraphBase;
+
+ protected:
+ int _id;
+ Node(int id) : _id(id) {}
+ public:
+ Node() {}
+ Node (Invalid) : _id(-1) {}
+ bool operator==(const Node node) const {return _id == node._id;}
+ bool operator!=(const Node node) const {return _id != node._id;}
+ bool operator<(const Node node) const {return _id < node._id;}
+ };
+
+ class Edge {
+ friend class HypercubeGraphBase;
+ friend class Arc;
+
+ protected:
+ int _id;
+
+ Edge(int id) : _id(id) {}
+
+ public:
+ Edge() {}
+ Edge (Invalid) : _id(-1) {}
+ bool operator==(const Edge edge) const {return _id == edge._id;}
+ bool operator!=(const Edge edge) const {return _id != edge._id;}
+ bool operator<(const Edge edge) const {return _id < edge._id;}
+ };
+
+ class Arc {
+ friend class HypercubeGraphBase;
+
+ protected:
+ int _id;
+
+ Arc(int id) : _id(id) {}
+
+ public:
+ Arc() {}
+ Arc (Invalid) : _id(-1) {}
+ operator Edge() const { return _id != -1 ? Edge(_id >> 1) : INVALID; }
+ bool operator==(const Arc arc) const {return _id == arc._id;}
+ bool operator!=(const Arc arc) const {return _id != arc._id;}
+ bool operator<(const Arc arc) const {return _id < arc._id;}
+ };
+
+ void first(Node& node) const {
+ node._id = _node_num - 1;
+ }
+
+ static void next(Node& node) {
+ --node._id;
+ }
+
+ void first(Edge& edge) const {
+ edge._id = _edge_num - 1;
+ }
+
+ static void next(Edge& edge) {
+ --edge._id;
+ }
+
+ void first(Arc& arc) const {
+ arc._id = 2 * _edge_num - 1;
+ }
+
+ static void next(Arc& arc) {
+ --arc._id;
+ }
+
+ void firstInc(Edge& edge, bool& dir, const Node& node) const {
+ edge._id = node._id >> 1;
+ dir = (node._id & 1) == 0;
+ }
+
+ void nextInc(Edge& edge, bool& dir) const {
+ Node n = dir ? u(edge) : v(edge);
+ int k = (edge._id >> (_dim-1)) + 1;
+ if (k < _dim) {
+ edge._id = (k << (_dim-1)) |
+ ((n._id >> (k+1)) << k) | (n._id & ((1 << k) - 1));
+ dir = ((n._id >> k) & 1) == 0;
+ } else {
+ edge._id = -1;
+ dir = true;
+ }
+ }
+
+ void firstOut(Arc& arc, const Node& node) const {
+ arc._id = ((node._id >> 1) << 1) | (~node._id & 1);
+ }
+
+ void nextOut(Arc& arc) const {
+ Node n = (arc._id & 1) == 1 ? u(arc) : v(arc);
+ int k = (arc._id >> _dim) + 1;
+ if (k < _dim) {
+ arc._id = (k << (_dim-1)) |
+ ((n._id >> (k+1)) << k) | (n._id & ((1 << k) - 1));
+ arc._id = (arc._id << 1) | (~(n._id >> k) & 1);
+ } else {
+ arc._id = -1;
+ }
+ }
+
+ void firstIn(Arc& arc, const Node& node) const {
+ arc._id = ((node._id >> 1) << 1) | (node._id & 1);
+ }
+
+ void nextIn(Arc& arc) const {
+ Node n = (arc._id & 1) == 1 ? v(arc) : u(arc);
+ int k = (arc._id >> _dim) + 1;
+ if (k < _dim) {
+ arc._id = (k << (_dim-1)) |
+ ((n._id >> (k+1)) << k) | (n._id & ((1 << k) - 1));
+ arc._id = (arc._id << 1) | ((n._id >> k) & 1);
+ } else {
+ arc._id = -1;
+ }
+ }
+
+ static bool direction(Arc arc) {
+ return (arc._id & 1) == 1;
+ }
+
+ static Arc direct(Edge edge, bool dir) {
+ return Arc((edge._id << 1) | (dir ? 1 : 0));
+ }
+
+ int dimension() const {
+ return _dim;
+ }
+
+ bool projection(Node node, int n) const {
+ return static_cast<bool>(node._id & (1 << n));
+ }
+
+ int dimension(Edge edge) const {
+ return edge._id >> (_dim-1);
+ }
+
+ int dimension(Arc arc) const {
+ return arc._id >> _dim;
+ }
+
+ static int index(Node node) {
+ return node._id;
+ }
+
+ Node operator()(int ix) const {
+ return Node(ix);
+ }
+
+ private:
+ int _dim;
+ int _node_num, _edge_num;
+ };
+
+
+ typedef GraphExtender<HypercubeGraphBase> ExtendedHypercubeGraphBase;
+
+ /// \ingroup graphs
+ ///
+ /// \brief Hypercube graph class
+ ///
+ /// HypercubeGraph implements a special graph type. The nodes of the
+ /// graph are indexed with integers having at most \c dim binary digits.
+ /// Two nodes are connected in the graph if and only if their indices
+ /// differ only on one position in the binary form.
+ /// This class is completely static and it needs constant memory space.
+ /// Thus you can neither add nor delete nodes or edges, however,
+ /// the structure can be resized using resize().
+ ///
+ /// This type fully conforms to the \ref concepts::Graph "Graph concept".
+ /// Most of its member functions and nested classes are documented
+ /// only in the concept class.
+ ///
+ /// This class provides constant time counting for nodes, edges and arcs.
+ ///
+ /// \note The type of the indices is chosen to \c int for efficiency
+ /// reasons. Thus the maximum dimension of this implementation is 26
+ /// (assuming that the size of \c int is 32 bit).
+ class HypercubeGraph : public ExtendedHypercubeGraphBase {
+ typedef ExtendedHypercubeGraphBase Parent;
+
+ public:
+
+ /// \brief Constructs a hypercube graph with \c dim dimensions.
+ ///
+ /// Constructs a hypercube graph with \c dim dimensions.
+ HypercubeGraph(int dim) { construct(dim); }
+
+ /// \brief Resizes the graph
+ ///
+ /// This function resizes the graph. It fully destroys and
+ /// rebuilds the structure, therefore the maps of the graph will be
+ /// reallocated automatically and the previous values will be lost.
+ void resize(int dim) {
+ Parent::notifier(Arc()).clear();
+ Parent::notifier(Edge()).clear();
+ Parent::notifier(Node()).clear();
+ construct(dim);
+ Parent::notifier(Node()).build();
+ Parent::notifier(Edge()).build();
+ Parent::notifier(Arc()).build();
+ }
+
+ /// \brief The number of dimensions.
+ ///
+ /// Gives back the number of dimensions.
+ int dimension() const {
+ return Parent::dimension();
+ }
+
+ /// \brief Returns \c true if the n'th bit of the node is one.
+ ///
+ /// Returns \c true if the n'th bit of the node is one.
+ bool projection(Node node, int n) const {
+ return Parent::projection(node, n);
+ }
+
+ /// \brief The dimension id of an edge.
+ ///
+ /// Gives back the dimension id of the given edge.
+ /// It is in the range <tt>[0..dim-1]</tt>.
+ int dimension(Edge edge) const {
+ return Parent::dimension(edge);
+ }
+
+ /// \brief The dimension id of an arc.
+ ///
+ /// Gives back the dimension id of the given arc.
+ /// It is in the range <tt>[0..dim-1]</tt>.
+ int dimension(Arc arc) const {
+ return Parent::dimension(arc);
+ }
+
+ /// \brief The index of a node.
+ ///
+ /// Gives back the index of the given node.
+ /// The lower bits of the integer describes the node.
+ static int index(Node node) {
+ return Parent::index(node);
+ }
+
+ /// \brief Gives back a node by its index.
+ ///
+ /// Gives back a node by its index.
+ Node operator()(int ix) const {
+ return Parent::operator()(ix);
+ }
+
+ /// \brief Number of nodes.
+ int nodeNum() const { return Parent::nodeNum(); }
+ /// \brief Number of edges.
+ int edgeNum() const { return Parent::edgeNum(); }
+ /// \brief Number of arcs.
+ int arcNum() const { return Parent::arcNum(); }
+
+ /// \brief Linear combination map.
+ ///
+ /// This map makes possible to give back a linear combination
+ /// for each node. It works like the \c std::accumulate function,
+ /// so it accumulates the \c bf binary function with the \c fv first
+ /// value. The map accumulates only on that positions (dimensions)
+ /// where the index of the node is one. The values that have to be
+ /// accumulated should be given by the \c begin and \c end iterators
+ /// and the length of this range should be equal to the dimension
+ /// number of the graph.
+ ///
+ ///\code
+ /// const int DIM = 3;
+ /// HypercubeGraph graph(DIM);
+ /// dim2::Point<double> base[DIM];
+ /// for (int k = 0; k < DIM; ++k) {
+ /// base[k].x = rnd();
+ /// base[k].y = rnd();
+ /// }
+ /// HypercubeGraph::HyperMap<dim2::Point<double> >
+ /// pos(graph, base, base + DIM, dim2::Point<double>(0.0, 0.0));
+ ///\endcode
+ ///
+ /// \see HypercubeGraph
+ template <typename T, typename BF = std::plus<T> >
+ class HyperMap {
+ public:
+
+ /// \brief The key type of the map
+ typedef Node Key;
+ /// \brief The value type of the map
+ typedef T Value;
+
+ /// \brief Constructor for HyperMap.
+ ///
+ /// Construct a HyperMap for the given graph. The values that have
+ /// to be accumulated should be given by the \c begin and \c end
+ /// iterators and the length of this range should be equal to the
+ /// dimension number of the graph.
+ ///
+ /// This map accumulates the \c bf binary function with the \c fv
+ /// first value on that positions (dimensions) where the index of
+ /// the node is one.
+ template <typename It>
+ HyperMap(const Graph& graph, It begin, It end,
+ T fv = 0, const BF& bf = BF())
+ : _graph(graph), _values(begin, end), _first_value(fv), _bin_func(bf)
+ {
+ LEMON_ASSERT(_values.size() == graph.dimension(),
+ "Wrong size of range");
+ }
+
+ /// \brief The partial accumulated value.
+ ///
+ /// Gives back the partial accumulated value.
+ Value operator[](const Key& k) const {
+ Value val = _first_value;
+ int id = _graph.index(k);
+ int n = 0;
+ while (id != 0) {
+ if (id & 1) {
+ val = _bin_func(val, _values[n]);
+ }
+ id >>= 1;
+ ++n;
+ }
+ return val;
+ }
+
+ private:
+ const Graph& _graph;
+ std::vector<T> _values;
+ T _first_value;
+ BF _bin_func;
+ };
+
+ };
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/insertion_tsp.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/insertion_tsp.h
new file mode 100644
index 00000000000..fa16825db52
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/insertion_tsp.h
@@ -0,0 +1,533 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_INSERTION_TSP_H
+#define LEMON_INSERTION_TSP_H
+
+/// \ingroup tsp
+/// \file
+/// \brief Insertion algorithm for symmetric TSP
+
+#include <vector>
+#include <functional>
+#include <lemon/full_graph.h>
+#include <lemon/maps.h>
+#include <lemon/random.h>
+
+namespace lemon {
+
+ /// \ingroup tsp
+ ///
+ /// \brief Insertion algorithm for symmetric TSP.
+ ///
+ /// InsertionTsp implements the insertion heuristic for solving
+ /// symmetric \ref tsp "TSP".
+ ///
+ /// This is a fast and effective tour construction method that has
+ /// many variants.
+ /// It starts with a subtour containing a few nodes of the graph and it
+ /// iteratively inserts the other nodes into this subtour according to a
+ /// certain node selection rule.
+ ///
+ /// This method is among the fastest TSP algorithms, and it typically
+ /// provides quite good solutions (usually much better than
+ /// \ref NearestNeighborTsp and \ref GreedyTsp).
+ ///
+ /// InsertionTsp implements four different node selection rules,
+ /// from which the most effective one (\e farthest \e node \e selection)
+ /// is used by default.
+ /// With this choice, the algorithm runs in O(n<sup>2</sup>) time.
+ /// For more information, see \ref SelectionRule.
+ ///
+ /// \tparam CM Type of the cost map.
+ template <typename CM>
+ class InsertionTsp
+ {
+ public:
+
+ /// Type of the cost map
+ typedef CM CostMap;
+ /// Type of the edge costs
+ typedef typename CM::Value Cost;
+
+ private:
+
+ GRAPH_TYPEDEFS(FullGraph);
+
+ const FullGraph &_gr;
+ const CostMap &_cost;
+ std::vector<Node> _notused;
+ std::vector<Node> _tour;
+ Cost _sum;
+
+ public:
+
+ /// \brief Constants for specifying the node selection rule.
+ ///
+ /// Enum type containing constants for specifying the node selection
+ /// rule for the \ref run() function.
+ ///
+ /// During the algorithm, nodes are selected for addition to the current
+ /// subtour according to the applied rule.
+ /// The FARTHEST method is one of the fastest selection rules, and
+ /// it is typically the most effective, thus it is the default
+ /// option. The RANDOM rule usually gives slightly worse results,
+ /// but it is more robust.
+ ///
+ /// The desired selection rule can be specified as a parameter of the
+ /// \ref run() function.
+ enum SelectionRule {
+
+ /// An unvisited node having minimum distance from the current
+ /// subtour is selected at each step.
+ /// The algorithm runs in O(n<sup>2</sup>) time using this
+ /// selection rule.
+ NEAREST,
+
+ /// An unvisited node having maximum distance from the current
+ /// subtour is selected at each step.
+ /// The algorithm runs in O(n<sup>2</sup>) time using this
+ /// selection rule.
+ FARTHEST,
+
+ /// An unvisited node whose insertion results in the least
+ /// increase of the subtour's total cost is selected at each step.
+ /// The algorithm runs in O(n<sup>3</sup>) time using this
+ /// selection rule, but in most cases, it is almost as fast as
+ /// with other rules.
+ CHEAPEST,
+
+ /// An unvisited node is selected randomly without any evaluation
+ /// at each step.
+ /// The global \ref rnd "random number generator instance" is used.
+ /// You can seed it before executing the algorithm, if you
+ /// would like to.
+ /// The algorithm runs in O(n<sup>2</sup>) time using this
+ /// selection rule.
+ RANDOM
+ };
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ /// \param gr The \ref FullGraph "full graph" the algorithm runs on.
+ /// \param cost The cost map.
+ InsertionTsp(const FullGraph &gr, const CostMap &cost)
+ : _gr(gr), _cost(cost) {}
+
+ /// \name Execution Control
+ /// @{
+
+ /// \brief Runs the algorithm.
+ ///
+ /// This function runs the algorithm.
+ ///
+ /// \param rule The node selection rule. For more information, see
+ /// \ref SelectionRule.
+ ///
+ /// \return The total cost of the found tour.
+ Cost run(SelectionRule rule = FARTHEST) {
+ _tour.clear();
+
+ if (_gr.nodeNum() == 0) return _sum = 0;
+ else if (_gr.nodeNum() == 1) {
+ _tour.push_back(_gr(0));
+ return _sum = 0;
+ }
+
+ switch (rule) {
+ case NEAREST:
+ init(true);
+ start<ComparingSelection<std::less<Cost> >,
+ DefaultInsertion>();
+ break;
+ case FARTHEST:
+ init(false);
+ start<ComparingSelection<std::greater<Cost> >,
+ DefaultInsertion>();
+ break;
+ case CHEAPEST:
+ init(true);
+ start<CheapestSelection, CheapestInsertion>();
+ break;
+ case RANDOM:
+ init(true);
+ start<RandomSelection, DefaultInsertion>();
+ break;
+ }
+ return _sum;
+ }
+
+ /// @}
+
+ /// \name Query Functions
+ /// @{
+
+ /// \brief The total cost of the found tour.
+ ///
+ /// This function returns the total cost of the found tour.
+ ///
+ /// \pre run() must be called before using this function.
+ Cost tourCost() const {
+ return _sum;
+ }
+
+ /// \brief Returns a const reference to the node sequence of the
+ /// found tour.
+ ///
+ /// This function returns a const reference to a vector
+ /// that stores the node sequence of the found tour.
+ ///
+ /// \pre run() must be called before using this function.
+ const std::vector<Node>& tourNodes() const {
+ return _tour;
+ }
+
+ /// \brief Gives back the node sequence of the found tour.
+ ///
+ /// This function copies the node sequence of the found tour into
+ /// an STL container through the given output iterator. The
+ /// <tt>value_type</tt> of the container must be <tt>FullGraph::Node</tt>.
+ /// For example,
+ /// \code
+ /// std::vector<FullGraph::Node> nodes(countNodes(graph));
+ /// tsp.tourNodes(nodes.begin());
+ /// \endcode
+ /// or
+ /// \code
+ /// std::list<FullGraph::Node> nodes;
+ /// tsp.tourNodes(std::back_inserter(nodes));
+ /// \endcode
+ ///
+ /// \pre run() must be called before using this function.
+ template <typename Iterator>
+ void tourNodes(Iterator out) const {
+ std::copy(_tour.begin(), _tour.end(), out);
+ }
+
+ /// \brief Gives back the found tour as a path.
+ ///
+ /// This function copies the found tour as a list of arcs/edges into
+ /// the given \ref lemon::concepts::Path "path structure".
+ ///
+ /// \pre run() must be called before using this function.
+ template <typename Path>
+ void tour(Path &path) const {
+ path.clear();
+ for (int i = 0; i < int(_tour.size()) - 1; ++i) {
+ path.addBack(_gr.arc(_tour[i], _tour[i+1]));
+ }
+ if (int(_tour.size()) >= 2) {
+ path.addBack(_gr.arc(_tour.back(), _tour.front()));
+ }
+ }
+
+ /// @}
+
+ private:
+
+ // Initializes the algorithm
+ void init(bool min) {
+ Edge min_edge = min ? mapMin(_gr, _cost) : mapMax(_gr, _cost);
+
+ _tour.clear();
+ _tour.push_back(_gr.u(min_edge));
+ _tour.push_back(_gr.v(min_edge));
+
+ _notused.clear();
+ for (NodeIt n(_gr); n!=INVALID; ++n) {
+ if (n != _gr.u(min_edge) && n != _gr.v(min_edge)) {
+ _notused.push_back(n);
+ }
+ }
+
+ _sum = _cost[min_edge] * 2;
+ }
+
+ // Executes the algorithm
+ template <class SelectionFunctor, class InsertionFunctor>
+ void start() {
+ SelectionFunctor selectNode(_gr, _cost, _tour, _notused);
+ InsertionFunctor insertNode(_gr, _cost, _tour, _sum);
+
+ for (int i=0; i<_gr.nodeNum()-2; ++i) {
+ insertNode.insert(selectNode.select());
+ }
+
+ _sum = _cost[_gr.edge(_tour.back(), _tour.front())];
+ for (int i = 0; i < int(_tour.size())-1; ++i) {
+ _sum += _cost[_gr.edge(_tour[i], _tour[i+1])];
+ }
+ }
+
+
+ // Implementation of the nearest and farthest selection rule
+ template <typename Comparator>
+ class ComparingSelection {
+ public:
+ ComparingSelection(const FullGraph &gr, const CostMap &cost,
+ std::vector<Node> &tour, std::vector<Node> &notused)
+ : _gr(gr), _cost(cost), _tour(tour), _notused(notused),
+ _dist(gr, 0), _compare()
+ {
+ // Compute initial distances for the unused nodes
+ for (unsigned int i=0; i<_notused.size(); ++i) {
+ Node u = _notused[i];
+ Cost min_dist = _cost[_gr.edge(u, _tour[0])];
+ for (unsigned int j=1; j<_tour.size(); ++j) {
+ Cost curr = _cost[_gr.edge(u, _tour[j])];
+ if (curr < min_dist) {
+ min_dist = curr;
+ }
+ }
+ _dist[u] = min_dist;
+ }
+ }
+
+ Node select() {
+
+ // Select an used node with minimum distance
+ Cost ins_dist = 0;
+ int ins_node = -1;
+ for (unsigned int i=0; i<_notused.size(); ++i) {
+ Cost curr = _dist[_notused[i]];
+ if (_compare(curr, ins_dist) || ins_node == -1) {
+ ins_dist = curr;
+ ins_node = i;
+ }
+ }
+
+ // Remove the selected node from the unused vector
+ Node sn = _notused[ins_node];
+ _notused[ins_node] = _notused.back();
+ _notused.pop_back();
+
+ // Update the distances of the remaining nodes
+ for (unsigned int i=0; i<_notused.size(); ++i) {
+ Node u = _notused[i];
+ Cost nc = _cost[_gr.edge(sn, u)];
+ if (nc < _dist[u]) {
+ _dist[u] = nc;
+ }
+ }
+
+ return sn;
+ }
+
+ private:
+ const FullGraph &_gr;
+ const CostMap &_cost;
+ std::vector<Node> &_tour;
+ std::vector<Node> &_notused;
+ FullGraph::NodeMap<Cost> _dist;
+ Comparator _compare;
+ };
+
+ // Implementation of the cheapest selection rule
+ class CheapestSelection {
+ private:
+ Cost costDiff(Node u, Node v, Node w) const {
+ return
+ _cost[_gr.edge(u, w)] +
+ _cost[_gr.edge(v, w)] -
+ _cost[_gr.edge(u, v)];
+ }
+
+ public:
+ CheapestSelection(const FullGraph &gr, const CostMap &cost,
+ std::vector<Node> &tour, std::vector<Node> &notused)
+ : _gr(gr), _cost(cost), _tour(tour), _notused(notused),
+ _ins_cost(gr, 0), _ins_pos(gr, -1)
+ {
+ // Compute insertion cost and position for the unused nodes
+ for (unsigned int i=0; i<_notused.size(); ++i) {
+ Node u = _notused[i];
+ Cost min_cost = costDiff(_tour.back(), _tour.front(), u);
+ int min_pos = 0;
+ for (unsigned int j=1; j<_tour.size(); ++j) {
+ Cost curr_cost = costDiff(_tour[j-1], _tour[j], u);
+ if (curr_cost < min_cost) {
+ min_cost = curr_cost;
+ min_pos = j;
+ }
+ }
+ _ins_cost[u] = min_cost;
+ _ins_pos[u] = min_pos;
+ }
+ }
+
+ Cost select() {
+
+ // Select an used node with minimum insertion cost
+ Cost min_cost = 0;
+ int min_node = -1;
+ for (unsigned int i=0; i<_notused.size(); ++i) {
+ Cost curr_cost = _ins_cost[_notused[i]];
+ if (curr_cost < min_cost || min_node == -1) {
+ min_cost = curr_cost;
+ min_node = i;
+ }
+ }
+
+ // Remove the selected node from the unused vector
+ Node sn = _notused[min_node];
+ _notused[min_node] = _notused.back();
+ _notused.pop_back();
+
+ // Insert the selected node into the tour
+ const int ipos = _ins_pos[sn];
+ _tour.insert(_tour.begin() + ipos, sn);
+
+ // Update the insertion cost and position of the remaining nodes
+ for (unsigned int i=0; i<_notused.size(); ++i) {
+ Node u = _notused[i];
+ Cost curr_cost = _ins_cost[u];
+ int curr_pos = _ins_pos[u];
+
+ int ipos_prev = ipos == 0 ? _tour.size()-1 : ipos-1;
+ int ipos_next = ipos == int(_tour.size())-1 ? 0 : ipos+1;
+ Cost nc1 = costDiff(_tour[ipos_prev], _tour[ipos], u);
+ Cost nc2 = costDiff(_tour[ipos], _tour[ipos_next], u);
+
+ if (nc1 <= curr_cost || nc2 <= curr_cost) {
+ // A new position is better than the old one
+ if (nc1 <= nc2) {
+ curr_cost = nc1;
+ curr_pos = ipos;
+ } else {
+ curr_cost = nc2;
+ curr_pos = ipos_next;
+ }
+ }
+ else {
+ if (curr_pos == ipos) {
+ // The minimum should be found again
+ curr_cost = costDiff(_tour.back(), _tour.front(), u);
+ curr_pos = 0;
+ for (unsigned int j=1; j<_tour.size(); ++j) {
+ Cost tmp_cost = costDiff(_tour[j-1], _tour[j], u);
+ if (tmp_cost < curr_cost) {
+ curr_cost = tmp_cost;
+ curr_pos = j;
+ }
+ }
+ }
+ else if (curr_pos > ipos) {
+ ++curr_pos;
+ }
+ }
+
+ _ins_cost[u] = curr_cost;
+ _ins_pos[u] = curr_pos;
+ }
+
+ return min_cost;
+ }
+
+ private:
+ const FullGraph &_gr;
+ const CostMap &_cost;
+ std::vector<Node> &_tour;
+ std::vector<Node> &_notused;
+ FullGraph::NodeMap<Cost> _ins_cost;
+ FullGraph::NodeMap<int> _ins_pos;
+ };
+
+ // Implementation of the random selection rule
+ class RandomSelection {
+ public:
+ RandomSelection(const FullGraph &, const CostMap &,
+ std::vector<Node> &, std::vector<Node> &notused)
+ : _notused(notused) {}
+
+ Node select() const {
+ const int index = rnd[_notused.size()];
+ Node n = _notused[index];
+ _notused[index] = _notused.back();
+ _notused.pop_back();
+ return n;
+ }
+
+ private:
+ std::vector<Node> &_notused;
+ };
+
+
+ // Implementation of the default insertion method
+ class DefaultInsertion {
+ private:
+ Cost costDiff(Node u, Node v, Node w) const {
+ return
+ _cost[_gr.edge(u, w)] +
+ _cost[_gr.edge(v, w)] -
+ _cost[_gr.edge(u, v)];
+ }
+
+ public:
+ DefaultInsertion(const FullGraph &gr, const CostMap &cost,
+ std::vector<Node> &tour, Cost &total_cost) :
+ _gr(gr), _cost(cost), _tour(tour), _total(total_cost) {}
+
+ void insert(Node n) const {
+ int min = 0;
+ Cost min_val =
+ costDiff(_tour.front(), _tour.back(), n);
+
+ for (unsigned int i=1; i<_tour.size(); ++i) {
+ Cost tmp = costDiff(_tour[i-1], _tour[i], n);
+ if (tmp < min_val) {
+ min = i;
+ min_val = tmp;
+ }
+ }
+
+ _tour.insert(_tour.begin()+min, n);
+ _total += min_val;
+ }
+
+ private:
+ const FullGraph &_gr;
+ const CostMap &_cost;
+ std::vector<Node> &_tour;
+ Cost &_total;
+ };
+
+ // Implementation of a special insertion method for the cheapest
+ // selection rule
+ class CheapestInsertion {
+ TEMPLATE_GRAPH_TYPEDEFS(FullGraph);
+ public:
+ CheapestInsertion(const FullGraph &, const CostMap &,
+ std::vector<Node> &, Cost &total_cost) :
+ _total(total_cost) {}
+
+ void insert(Cost diff) const {
+ _total += diff;
+ }
+
+ private:
+ Cost &_total;
+ };
+
+ };
+
+}; // namespace lemon
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/karp_mmc.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/karp_mmc.h
new file mode 100644
index 00000000000..1f05d4369c9
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/karp_mmc.h
@@ -0,0 +1,590 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_KARP_MMC_H
+#define LEMON_KARP_MMC_H
+
+/// \ingroup min_mean_cycle
+///
+/// \file
+/// \brief Karp's algorithm for finding a minimum mean cycle.
+
+#include <vector>
+#include <limits>
+#include <lemon/core.h>
+#include <lemon/path.h>
+#include <lemon/tolerance.h>
+#include <lemon/connectivity.h>
+
+namespace lemon {
+
+ /// \brief Default traits class of KarpMmc class.
+ ///
+ /// Default traits class of KarpMmc class.
+ /// \tparam GR The type of the digraph.
+ /// \tparam CM The type of the cost map.
+ /// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
+#ifdef DOXYGEN
+ template <typename GR, typename CM>
+#else
+ template <typename GR, typename CM,
+ bool integer = std::numeric_limits<typename CM::Value>::is_integer>
+#endif
+ struct KarpMmcDefaultTraits
+ {
+ /// The type of the digraph
+ typedef GR Digraph;
+ /// The type of the cost map
+ typedef CM CostMap;
+ /// The type of the arc costs
+ typedef typename CostMap::Value Cost;
+
+ /// \brief The large cost type used for internal computations
+ ///
+ /// The large cost type used for internal computations.
+ /// It is \c long \c long if the \c Cost type is integer,
+ /// otherwise it is \c double.
+ /// \c Cost must be convertible to \c LargeCost.
+ typedef double LargeCost;
+
+ /// The tolerance type used for internal computations
+ typedef lemon::Tolerance<LargeCost> Tolerance;
+
+ /// \brief The path type of the found cycles
+ ///
+ /// The path type of the found cycles.
+ /// It must conform to the \ref lemon::concepts::Path "Path" concept
+ /// and it must have an \c addFront() function.
+ typedef lemon::Path<Digraph> Path;
+ };
+
+ // Default traits class for integer cost types
+ template <typename GR, typename CM>
+ struct KarpMmcDefaultTraits<GR, CM, true>
+ {
+ typedef GR Digraph;
+ typedef CM CostMap;
+ typedef typename CostMap::Value Cost;
+#ifdef LEMON_HAVE_LONG_LONG
+ typedef long long LargeCost;
+#else
+ typedef long LargeCost;
+#endif
+ typedef lemon::Tolerance<LargeCost> Tolerance;
+ typedef lemon::Path<Digraph> Path;
+ };
+
+
+ /// \addtogroup min_mean_cycle
+ /// @{
+
+ /// \brief Implementation of Karp's algorithm for finding a minimum
+ /// mean cycle.
+ ///
+ /// This class implements Karp's algorithm for finding a directed
+ /// cycle of minimum mean cost in a digraph
+ /// \cite karp78characterization, \cite dasdan98minmeancycle.
+ /// It runs in time O(nm) and uses space O(n<sup>2</sup>+m).
+ ///
+ /// \tparam GR The type of the digraph the algorithm runs on.
+ /// \tparam CM The type of the cost map. The default
+ /// map type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
+ /// \tparam TR The traits class that defines various types used by the
+ /// algorithm. By default, it is \ref KarpMmcDefaultTraits
+ /// "KarpMmcDefaultTraits<GR, CM>".
+ /// In most cases, this parameter should not be set directly,
+ /// consider to use the named template parameters instead.
+#ifdef DOXYGEN
+ template <typename GR, typename CM, typename TR>
+#else
+ template < typename GR,
+ typename CM = typename GR::template ArcMap<int>,
+ typename TR = KarpMmcDefaultTraits<GR, CM> >
+#endif
+ class KarpMmc
+ {
+ public:
+
+ /// The type of the digraph
+ typedef typename TR::Digraph Digraph;
+ /// The type of the cost map
+ typedef typename TR::CostMap CostMap;
+ /// The type of the arc costs
+ typedef typename TR::Cost Cost;
+
+ /// \brief The large cost type
+ ///
+ /// The large cost type used for internal computations.
+ /// By default, it is \c long \c long if the \c Cost type is integer,
+ /// otherwise it is \c double.
+ typedef typename TR::LargeCost LargeCost;
+
+ /// The tolerance type
+ typedef typename TR::Tolerance Tolerance;
+
+ /// \brief The path type of the found cycles
+ ///
+ /// The path type of the found cycles.
+ /// Using the \ref lemon::KarpMmcDefaultTraits "default traits class",
+ /// it is \ref lemon::Path "Path<Digraph>".
+ typedef typename TR::Path Path;
+
+ /// The \ref lemon::KarpMmcDefaultTraits "traits class" of the algorithm
+ typedef TR Traits;
+
+ private:
+
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+
+ // Data sturcture for path data
+ struct PathData
+ {
+ LargeCost dist;
+ Arc pred;
+ PathData(LargeCost d, Arc p = INVALID) :
+ dist(d), pred(p) {}
+ };
+
+ typedef typename Digraph::template NodeMap<std::vector<PathData> >
+ PathDataNodeMap;
+
+ private:
+
+ // The digraph the algorithm runs on
+ const Digraph &_gr;
+ // The cost of the arcs
+ const CostMap &_cost;
+
+ // Data for storing the strongly connected components
+ int _comp_num;
+ typename Digraph::template NodeMap<int> _comp;
+ std::vector<std::vector<Node> > _comp_nodes;
+ std::vector<Node>* _nodes;
+ typename Digraph::template NodeMap<std::vector<Arc> > _out_arcs;
+
+ // Data for the found cycle
+ LargeCost _cycle_cost;
+ int _cycle_size;
+ Node _cycle_node;
+
+ Path *_cycle_path;
+ bool _local_path;
+
+ // Node map for storing path data
+ PathDataNodeMap _data;
+ // The processed nodes in the last round
+ std::vector<Node> _process;
+
+ Tolerance _tolerance;
+
+ // Infinite constant
+ const LargeCost INF;
+
+ public:
+
+ /// \name Named Template Parameters
+ /// @{
+
+ template <typename T>
+ struct SetLargeCostTraits : public Traits {
+ typedef T LargeCost;
+ typedef lemon::Tolerance<T> Tolerance;
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// \c LargeCost type.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting \c LargeCost
+ /// type. It is used for internal computations in the algorithm.
+ template <typename T>
+ struct SetLargeCost
+ : public KarpMmc<GR, CM, SetLargeCostTraits<T> > {
+ typedef KarpMmc<GR, CM, SetLargeCostTraits<T> > Create;
+ };
+
+ template <typename T>
+ struct SetPathTraits : public Traits {
+ typedef T Path;
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// \c %Path type.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting the \c %Path
+ /// type of the found cycles.
+ /// It must conform to the \ref lemon::concepts::Path "Path" concept
+ /// and it must have an \c addFront() function.
+ template <typename T>
+ struct SetPath
+ : public KarpMmc<GR, CM, SetPathTraits<T> > {
+ typedef KarpMmc<GR, CM, SetPathTraits<T> > Create;
+ };
+
+ /// @}
+
+ protected:
+
+ KarpMmc() {}
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// The constructor of the class.
+ ///
+ /// \param digraph The digraph the algorithm runs on.
+ /// \param cost The costs of the arcs.
+ KarpMmc( const Digraph &digraph,
+ const CostMap &cost ) :
+ _gr(digraph), _cost(cost), _comp(digraph), _out_arcs(digraph),
+ _cycle_cost(0), _cycle_size(1), _cycle_node(INVALID),
+ _cycle_path(NULL), _local_path(false), _data(digraph),
+ INF(std::numeric_limits<LargeCost>::has_infinity ?
+ std::numeric_limits<LargeCost>::infinity() :
+ std::numeric_limits<LargeCost>::max())
+ {}
+
+ /// Destructor.
+ ~KarpMmc() {
+ if (_local_path) delete _cycle_path;
+ }
+
+ /// \brief Set the path structure for storing the found cycle.
+ ///
+ /// This function sets an external path structure for storing the
+ /// found cycle.
+ ///
+ /// If you don't call this function before calling \ref run() or
+ /// \ref findCycleMean(), a local \ref Path "path" structure
+ /// will be allocated. The destuctor deallocates this automatically
+ /// allocated object, of course.
+ ///
+ /// \note The algorithm calls only the \ref lemon::Path::addFront()
+ /// "addFront()" function of the given path structure.
+ ///
+ /// \return <tt>(*this)</tt>
+ KarpMmc& cycle(Path &path) {
+ if (_local_path) {
+ delete _cycle_path;
+ _local_path = false;
+ }
+ _cycle_path = &path;
+ return *this;
+ }
+
+ /// \brief Set the tolerance used by the algorithm.
+ ///
+ /// This function sets the tolerance object used by the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ KarpMmc& tolerance(const Tolerance& tolerance) {
+ _tolerance = tolerance;
+ return *this;
+ }
+
+ /// \brief Return a const reference to the tolerance.
+ ///
+ /// This function returns a const reference to the tolerance object
+ /// used by the algorithm.
+ const Tolerance& tolerance() const {
+ return _tolerance;
+ }
+
+ /// \name Execution control
+ /// The simplest way to execute the algorithm is to call the \ref run()
+ /// function.\n
+ /// If you only need the minimum mean cost, you may call
+ /// \ref findCycleMean().
+
+ /// @{
+
+ /// \brief Run the algorithm.
+ ///
+ /// This function runs the algorithm.
+ /// It can be called more than once (e.g. if the underlying digraph
+ /// and/or the arc costs have been modified).
+ ///
+ /// \return \c true if a directed cycle exists in the digraph.
+ ///
+ /// \note <tt>mmc.run()</tt> is just a shortcut of the following code.
+ /// \code
+ /// return mmc.findCycleMean() && mmc.findCycle();
+ /// \endcode
+ bool run() {
+ return findCycleMean() && findCycle();
+ }
+
+ /// \brief Find the minimum cycle mean.
+ ///
+ /// This function finds the minimum mean cost of the directed
+ /// cycles in the digraph.
+ ///
+ /// \return \c true if a directed cycle exists in the digraph.
+ bool findCycleMean() {
+ // Initialization and find strongly connected components
+ init();
+ findComponents();
+
+ // Find the minimum cycle mean in the components
+ for (int comp = 0; comp < _comp_num; ++comp) {
+ if (!initComponent(comp)) continue;
+ processRounds();
+ updateMinMean();
+ }
+ return (_cycle_node != INVALID);
+ }
+
+ /// \brief Find a minimum mean directed cycle.
+ ///
+ /// This function finds a directed cycle of minimum mean cost
+ /// in the digraph using the data computed by findCycleMean().
+ ///
+ /// \return \c true if a directed cycle exists in the digraph.
+ ///
+ /// \pre \ref findCycleMean() must be called before using this function.
+ bool findCycle() {
+ if (_cycle_node == INVALID) return false;
+ IntNodeMap reached(_gr, -1);
+ int r = _data[_cycle_node].size();
+ Node u = _cycle_node;
+ while (reached[u] < 0) {
+ reached[u] = --r;
+ u = _gr.source(_data[u][r].pred);
+ }
+ r = reached[u];
+ Arc e = _data[u][r].pred;
+ _cycle_path->addFront(e);
+ _cycle_cost = _cost[e];
+ _cycle_size = 1;
+ Node v;
+ while ((v = _gr.source(e)) != u) {
+ e = _data[v][--r].pred;
+ _cycle_path->addFront(e);
+ _cycle_cost += _cost[e];
+ ++_cycle_size;
+ }
+ return true;
+ }
+
+ /// @}
+
+ /// \name Query Functions
+ /// The results of the algorithm can be obtained using these
+ /// functions.\n
+ /// The algorithm should be executed before using them.
+
+ /// @{
+
+ /// \brief Return the total cost of the found cycle.
+ ///
+ /// This function returns the total cost of the found cycle.
+ ///
+ /// \pre \ref run() or \ref findCycleMean() must be called before
+ /// using this function.
+ Cost cycleCost() const {
+ return static_cast<Cost>(_cycle_cost);
+ }
+
+ /// \brief Return the number of arcs on the found cycle.
+ ///
+ /// This function returns the number of arcs on the found cycle.
+ ///
+ /// \pre \ref run() or \ref findCycleMean() must be called before
+ /// using this function.
+ int cycleSize() const {
+ return _cycle_size;
+ }
+
+ /// \brief Return the mean cost of the found cycle.
+ ///
+ /// This function returns the mean cost of the found cycle.
+ ///
+ /// \note <tt>alg.cycleMean()</tt> is just a shortcut of the
+ /// following code.
+ /// \code
+ /// return static_cast<double>(alg.cycleCost()) / alg.cycleSize();
+ /// \endcode
+ ///
+ /// \pre \ref run() or \ref findCycleMean() must be called before
+ /// using this function.
+ double cycleMean() const {
+ return static_cast<double>(_cycle_cost) / _cycle_size;
+ }
+
+ /// \brief Return the found cycle.
+ ///
+ /// This function returns a const reference to the path structure
+ /// storing the found cycle.
+ ///
+ /// \pre \ref run() or \ref findCycle() must be called before using
+ /// this function.
+ const Path& cycle() const {
+ return *_cycle_path;
+ }
+
+ ///@}
+
+ private:
+
+ // Initialization
+ void init() {
+ if (!_cycle_path) {
+ _local_path = true;
+ _cycle_path = new Path;
+ }
+ _cycle_path->clear();
+ _cycle_cost = 0;
+ _cycle_size = 1;
+ _cycle_node = INVALID;
+ for (NodeIt u(_gr); u != INVALID; ++u)
+ _data[u].clear();
+ }
+
+ // Find strongly connected components and initialize _comp_nodes
+ // and _out_arcs
+ void findComponents() {
+ _comp_num = stronglyConnectedComponents(_gr, _comp);
+ _comp_nodes.resize(_comp_num);
+ if (_comp_num == 1) {
+ _comp_nodes[0].clear();
+ for (NodeIt n(_gr); n != INVALID; ++n) {
+ _comp_nodes[0].push_back(n);
+ _out_arcs[n].clear();
+ for (OutArcIt a(_gr, n); a != INVALID; ++a) {
+ _out_arcs[n].push_back(a);
+ }
+ }
+ } else {
+ for (int i = 0; i < _comp_num; ++i)
+ _comp_nodes[i].clear();
+ for (NodeIt n(_gr); n != INVALID; ++n) {
+ int k = _comp[n];
+ _comp_nodes[k].push_back(n);
+ _out_arcs[n].clear();
+ for (OutArcIt a(_gr, n); a != INVALID; ++a) {
+ if (_comp[_gr.target(a)] == k) _out_arcs[n].push_back(a);
+ }
+ }
+ }
+ }
+
+ // Initialize path data for the current component
+ bool initComponent(int comp) {
+ _nodes = &(_comp_nodes[comp]);
+ int n = _nodes->size();
+ if (n < 1 || (n == 1 && _out_arcs[(*_nodes)[0]].size() == 0)) {
+ return false;
+ }
+ for (int i = 0; i < n; ++i) {
+ _data[(*_nodes)[i]].resize(n + 1, PathData(INF));
+ }
+ return true;
+ }
+
+ // Process all rounds of computing path data for the current component.
+ // _data[v][k] is the cost of a shortest directed walk from the root
+ // node to node v containing exactly k arcs.
+ void processRounds() {
+ Node start = (*_nodes)[0];
+ _data[start][0] = PathData(0);
+ _process.clear();
+ _process.push_back(start);
+
+ int k, n = _nodes->size();
+ for (k = 1; k <= n && int(_process.size()) < n; ++k) {
+ processNextBuildRound(k);
+ }
+ for ( ; k <= n; ++k) {
+ processNextFullRound(k);
+ }
+ }
+
+ // Process one round and rebuild _process
+ void processNextBuildRound(int k) {
+ std::vector<Node> next;
+ Node u, v;
+ Arc e;
+ LargeCost d;
+ for (int i = 0; i < int(_process.size()); ++i) {
+ u = _process[i];
+ for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
+ e = _out_arcs[u][j];
+ v = _gr.target(e);
+ d = _data[u][k-1].dist + _cost[e];
+ if (_tolerance.less(d, _data[v][k].dist)) {
+ if (_data[v][k].dist == INF) next.push_back(v);
+ _data[v][k] = PathData(d, e);
+ }
+ }
+ }
+ _process.swap(next);
+ }
+
+ // Process one round using _nodes instead of _process
+ void processNextFullRound(int k) {
+ Node u, v;
+ Arc e;
+ LargeCost d;
+ for (int i = 0; i < int(_nodes->size()); ++i) {
+ u = (*_nodes)[i];
+ for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
+ e = _out_arcs[u][j];
+ v = _gr.target(e);
+ d = _data[u][k-1].dist + _cost[e];
+ if (_tolerance.less(d, _data[v][k].dist)) {
+ _data[v][k] = PathData(d, e);
+ }
+ }
+ }
+ }
+
+ // Update the minimum cycle mean
+ void updateMinMean() {
+ int n = _nodes->size();
+ for (int i = 0; i < n; ++i) {
+ Node u = (*_nodes)[i];
+ if (_data[u][n].dist == INF) continue;
+ LargeCost cost, max_cost = 0;
+ int size, max_size = 1;
+ bool found_curr = false;
+ for (int k = 0; k < n; ++k) {
+ if (_data[u][k].dist == INF) continue;
+ cost = _data[u][n].dist - _data[u][k].dist;
+ size = n - k;
+ if (!found_curr || cost * max_size > max_cost * size) {
+ found_curr = true;
+ max_cost = cost;
+ max_size = size;
+ }
+ }
+ if ( found_curr && (_cycle_node == INVALID ||
+ max_cost * _cycle_size < _cycle_cost * max_size) ) {
+ _cycle_cost = max_cost;
+ _cycle_size = max_size;
+ _cycle_node = u;
+ }
+ }
+ }
+
+ }; //class KarpMmc
+
+ ///@}
+
+} //namespace lemon
+
+#endif //LEMON_KARP_MMC_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/kruskal.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/kruskal.h
new file mode 100644
index 00000000000..04c2ddb9384
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/kruskal.h
@@ -0,0 +1,324 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_KRUSKAL_H
+#define LEMON_KRUSKAL_H
+
+#include <algorithm>
+#include <vector>
+#include <lemon/unionfind.h>
+#include <lemon/maps.h>
+
+#include <lemon/core.h>
+#include <lemon/bits/traits.h>
+
+///\ingroup spantree
+///\file
+///\brief Kruskal's algorithm to compute a minimum cost spanning tree
+
+namespace lemon {
+
+ namespace _kruskal_bits {
+
+ // Kruskal for directed graphs.
+
+ template <typename Digraph, typename In, typename Out>
+ typename disable_if<lemon::UndirectedTagIndicator<Digraph>,
+ typename In::value_type::second_type >::type
+ kruskal(const Digraph& digraph, const In& in, Out& out,dummy<0> = 0) {
+ typedef typename In::value_type::second_type Value;
+ typedef typename Digraph::template NodeMap<int> IndexMap;
+ typedef typename Digraph::Node Node;
+
+ IndexMap index(digraph);
+ UnionFind<IndexMap> uf(index);
+ for (typename Digraph::NodeIt it(digraph); it != INVALID; ++it) {
+ uf.insert(it);
+ }
+
+ Value tree_value = 0;
+ for (typename In::const_iterator it = in.begin(); it != in.end(); ++it) {
+ if (uf.join(digraph.target(it->first),digraph.source(it->first))) {
+ out.set(it->first, true);
+ tree_value += it->second;
+ }
+ else {
+ out.set(it->first, false);
+ }
+ }
+ return tree_value;
+ }
+
+ // Kruskal for undirected graphs.
+
+ template <typename Graph, typename In, typename Out>
+ typename enable_if<lemon::UndirectedTagIndicator<Graph>,
+ typename In::value_type::second_type >::type
+ kruskal(const Graph& graph, const In& in, Out& out,dummy<1> = 1) {
+ typedef typename In::value_type::second_type Value;
+ typedef typename Graph::template NodeMap<int> IndexMap;
+ typedef typename Graph::Node Node;
+
+ IndexMap index(graph);
+ UnionFind<IndexMap> uf(index);
+ for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
+ uf.insert(it);
+ }
+
+ Value tree_value = 0;
+ for (typename In::const_iterator it = in.begin(); it != in.end(); ++it) {
+ if (uf.join(graph.u(it->first),graph.v(it->first))) {
+ out.set(it->first, true);
+ tree_value += it->second;
+ }
+ else {
+ out.set(it->first, false);
+ }
+ }
+ return tree_value;
+ }
+
+
+ template <typename Sequence>
+ struct PairComp {
+ typedef typename Sequence::value_type Value;
+ bool operator()(const Value& left, const Value& right) {
+ return left.second < right.second;
+ }
+ };
+
+ template <typename In, typename Enable = void>
+ struct SequenceInputIndicator {
+ static const bool value = false;
+ };
+
+ template <typename In>
+ struct SequenceInputIndicator<In,
+ typename exists<typename In::value_type::first_type>::type> {
+ static const bool value = true;
+ };
+
+ template <typename In, typename Enable = void>
+ struct MapInputIndicator {
+ static const bool value = false;
+ };
+
+ template <typename In>
+ struct MapInputIndicator<In,
+ typename exists<typename In::Value>::type> {
+ static const bool value = true;
+ };
+
+ template <typename In, typename Enable = void>
+ struct SequenceOutputIndicator {
+ static const bool value = false;
+ };
+
+ template <typename Out>
+ struct SequenceOutputIndicator<Out,
+ typename exists<typename Out::value_type>::type> {
+ static const bool value = true;
+ };
+
+ template <typename Out, typename Enable = void>
+ struct MapOutputIndicator {
+ static const bool value = false;
+ };
+
+ template <typename Out>
+ struct MapOutputIndicator<Out,
+ typename exists<typename Out::Value>::type> {
+ static const bool value = true;
+ };
+
+ template <typename In, typename InEnable = void>
+ struct KruskalValueSelector {};
+
+ template <typename In>
+ struct KruskalValueSelector<In,
+ typename enable_if<SequenceInputIndicator<In>, void>::type>
+ {
+ typedef typename In::value_type::second_type Value;
+ };
+
+ template <typename In>
+ struct KruskalValueSelector<In,
+ typename enable_if<MapInputIndicator<In>, void>::type>
+ {
+ typedef typename In::Value Value;
+ };
+
+ template <typename Graph, typename In, typename Out,
+ typename InEnable = void>
+ struct KruskalInputSelector {};
+
+ template <typename Graph, typename In, typename Out,
+ typename InEnable = void>
+ struct KruskalOutputSelector {};
+
+ template <typename Graph, typename In, typename Out>
+ struct KruskalInputSelector<Graph, In, Out,
+ typename enable_if<SequenceInputIndicator<In>, void>::type >
+ {
+ typedef typename In::value_type::second_type Value;
+
+ static Value kruskal(const Graph& graph, const In& in, Out& out) {
+ return KruskalOutputSelector<Graph, In, Out>::
+ kruskal(graph, in, out);
+ }
+
+ };
+
+ template <typename Graph, typename In, typename Out>
+ struct KruskalInputSelector<Graph, In, Out,
+ typename enable_if<MapInputIndicator<In>, void>::type >
+ {
+ typedef typename In::Value Value;
+ static Value kruskal(const Graph& graph, const In& in, Out& out) {
+ typedef typename In::Key MapArc;
+ typedef typename In::Value Value;
+ typedef typename ItemSetTraits<Graph, MapArc>::ItemIt MapArcIt;
+ typedef std::vector<std::pair<MapArc, Value> > Sequence;
+ Sequence seq;
+
+ for (MapArcIt it(graph); it != INVALID; ++it) {
+ seq.push_back(std::make_pair(it, in[it]));
+ }
+
+ std::sort(seq.begin(), seq.end(), PairComp<Sequence>());
+ return KruskalOutputSelector<Graph, Sequence, Out>::
+ kruskal(graph, seq, out);
+ }
+ };
+
+ template <typename T>
+ struct RemoveConst {
+ typedef T type;
+ };
+
+ template <typename T>
+ struct RemoveConst<const T> {
+ typedef T type;
+ };
+
+ template <typename Graph, typename In, typename Out>
+ struct KruskalOutputSelector<Graph, In, Out,
+ typename enable_if<SequenceOutputIndicator<Out>, void>::type >
+ {
+ typedef typename In::value_type::second_type Value;
+
+ static Value kruskal(const Graph& graph, const In& in, Out& out) {
+ typedef LoggerBoolMap<typename RemoveConst<Out>::type> Map;
+ Map map(out);
+ return _kruskal_bits::kruskal(graph, in, map);
+ }
+
+ };
+
+ template <typename Graph, typename In, typename Out>
+ struct KruskalOutputSelector<Graph, In, Out,
+ typename enable_if<MapOutputIndicator<Out>, void>::type >
+ {
+ typedef typename In::value_type::second_type Value;
+
+ static Value kruskal(const Graph& graph, const In& in, Out& out) {
+ return _kruskal_bits::kruskal(graph, in, out);
+ }
+ };
+
+ }
+
+ /// \ingroup spantree
+ ///
+ /// \brief Kruskal's algorithm for finding a minimum cost spanning tree of
+ /// a graph.
+ ///
+ /// This function runs Kruskal's algorithm to find a minimum cost
+ /// spanning tree of a graph.
+ /// Due to some C++ hacking, it accepts various input and output types.
+ ///
+ /// \param g The graph the algorithm runs on.
+ /// It can be either \ref concepts::Digraph "directed" or
+ /// \ref concepts::Graph "undirected".
+ /// If the graph is directed, the algorithm consider it to be
+ /// undirected by disregarding the direction of the arcs.
+ ///
+ /// \param in This object is used to describe the arc/edge costs.
+ /// It can be one of the following choices.
+ /// - An STL compatible 'Forward Container' with
+ /// <tt>std::pair<GR::Arc,C></tt> or
+ /// <tt>std::pair<GR::Edge,C></tt> as its <tt>value_type</tt>, where
+ /// \c C is the type of the costs. The pairs indicates the arcs/edges
+ /// along with the assigned cost. <em>They must be in a
+ /// cost-ascending order.</em>
+ /// - Any readable arc/edge map. The values of the map indicate the
+ /// arc/edge costs.
+ ///
+ /// \retval out Here we also have a choice.
+ /// - It can be a writable arc/edge map with \c bool value type. After
+ /// running the algorithm it will contain the found minimum cost spanning
+ /// tree: the value of an arc/edge will be set to \c true if it belongs
+ /// to the tree, otherwise it will be set to \c false. The value of
+ /// each arc/edge will be set exactly once.
+ /// - It can also be an iteraror of an STL Container with
+ /// <tt>GR::Arc</tt> or <tt>GR::Edge</tt> as its
+ /// <tt>value_type</tt>. The algorithm copies the elements of the
+ /// found tree into this sequence. For example, if we know that the
+ /// spanning tree of the graph \c g has say 53 arcs, then we can
+ /// put its arcs into an STL vector \c tree with a code like this.
+ ///\code
+ /// std::vector<Arc> tree(53);
+ /// kruskal(g,cost,tree.begin());
+ ///\endcode
+ /// Or if we don't know in advance the size of the tree, we can
+ /// write this.
+ ///\code
+ /// std::vector<Arc> tree;
+ /// kruskal(g,cost,std::back_inserter(tree));
+ ///\endcode
+ ///
+ /// \return The total cost of the found spanning tree.
+ ///
+ /// \note If the input graph is not (weakly) connected, a spanning
+ /// forest is calculated instead of a spanning tree.
+
+#ifdef DOXYGEN
+ template <typename Graph, typename In, typename Out>
+ Value kruskal(const Graph& g, const In& in, Out& out)
+#else
+ template <class Graph, class In, class Out>
+ inline typename _kruskal_bits::KruskalValueSelector<In>::Value
+ kruskal(const Graph& graph, const In& in, Out& out)
+#endif
+ {
+ return _kruskal_bits::KruskalInputSelector<Graph, In, Out>::
+ kruskal(graph, in, out);
+ }
+
+
+ template <class Graph, class In, class Out>
+ inline typename _kruskal_bits::KruskalValueSelector<In>::Value
+ kruskal(const Graph& graph, const In& in, const Out& out)
+ {
+ return _kruskal_bits::KruskalInputSelector<Graph, In, const Out>::
+ kruskal(graph, in, out);
+ }
+
+} //namespace lemon
+
+#endif //LEMON_KRUSKAL_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/lemon.pc.in b/extern/quadriflow/3rd/lemon-1.3.1/lemon/lemon.pc.in
new file mode 100644
index 00000000000..e85bf7652ec
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/lemon.pc.in
@@ -0,0 +1,10 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=@CMAKE_INSTALL_PREFIX@/bin
+libdir=@CMAKE_INSTALL_PREFIX@/lib
+includedir=@CMAKE_INSTALL_PREFIX@/include
+
+Name: @PROJECT_NAME@
+Description: Library for Efficient Modeling and Optimization in Networks
+Version: @PROJECT_VERSION@
+Libs: -L${libdir} -lemon @GLPK_LIBS@ @CPLEX_LIBS@ @SOPLEX_LIBS@ @CLP_LIBS@ @CBC_LIBS@
+Cflags: -I${includedir}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/lgf_reader.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/lgf_reader.h
new file mode 100644
index 00000000000..2f49fa25f21
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/lgf_reader.h
@@ -0,0 +1,3854 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\ingroup lemon_io
+///\file
+///\brief \ref lgf-format "LEMON Graph Format" reader.
+
+
+#ifndef LEMON_LGF_READER_H
+#define LEMON_LGF_READER_H
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+#include <set>
+#include <map>
+
+#include <lemon/core.h>
+
+#include <lemon/lgf_writer.h>
+
+#include <lemon/concept_check.h>
+#include <lemon/concepts/maps.h>
+
+namespace lemon {
+
+ namespace _reader_bits {
+
+ template <typename Value>
+ struct DefaultConverter {
+ Value operator()(const std::string& str) {
+ std::istringstream is(str);
+ Value value;
+ if (!(is >> value)) {
+ throw FormatError("Cannot read token");
+ }
+
+ char c;
+ if (is >> std::ws >> c) {
+ throw FormatError("Remaining characters in token");
+ }
+ return value;
+ }
+ };
+
+ template <>
+ struct DefaultConverter<std::string> {
+ std::string operator()(const std::string& str) {
+ return str;
+ }
+ };
+
+ template <typename _Item>
+ class MapStorageBase {
+ public:
+ typedef _Item Item;
+
+ public:
+ MapStorageBase() {}
+ virtual ~MapStorageBase() {}
+
+ virtual void set(const Item& item, const std::string& value) = 0;
+
+ };
+
+ template <typename _Item, typename _Map,
+ typename _Converter = DefaultConverter<typename _Map::Value> >
+ class MapStorage : public MapStorageBase<_Item> {
+ public:
+ typedef _Map Map;
+ typedef _Converter Converter;
+ typedef _Item Item;
+
+ private:
+ Map& _map;
+ Converter _converter;
+
+ public:
+ MapStorage(Map& map, const Converter& converter = Converter())
+ : _map(map), _converter(converter) {}
+ virtual ~MapStorage() {}
+
+ virtual void set(const Item& item ,const std::string& value) {
+ _map.set(item, _converter(value));
+ }
+ };
+
+ template <typename _GR, bool _dir, typename _Map,
+ typename _Converter = DefaultConverter<typename _Map::Value> >
+ class GraphArcMapStorage : public MapStorageBase<typename _GR::Edge> {
+ public:
+ typedef _Map Map;
+ typedef _Converter Converter;
+ typedef _GR GR;
+ typedef typename GR::Edge Item;
+ static const bool dir = _dir;
+
+ private:
+ const GR& _graph;
+ Map& _map;
+ Converter _converter;
+
+ public:
+ GraphArcMapStorage(const GR& graph, Map& map,
+ const Converter& converter = Converter())
+ : _graph(graph), _map(map), _converter(converter) {}
+ virtual ~GraphArcMapStorage() {}
+
+ virtual void set(const Item& item ,const std::string& value) {
+ _map.set(_graph.direct(item, dir), _converter(value));
+ }
+ };
+
+ class ValueStorageBase {
+ public:
+ ValueStorageBase() {}
+ virtual ~ValueStorageBase() {}
+
+ virtual void set(const std::string&) = 0;
+ };
+
+ template <typename _Value, typename _Converter = DefaultConverter<_Value> >
+ class ValueStorage : public ValueStorageBase {
+ public:
+ typedef _Value Value;
+ typedef _Converter Converter;
+
+ private:
+ Value& _value;
+ Converter _converter;
+
+ public:
+ ValueStorage(Value& value, const Converter& converter = Converter())
+ : _value(value), _converter(converter) {}
+
+ virtual void set(const std::string& value) {
+ _value = _converter(value);
+ }
+ };
+
+ template <typename Value,
+ typename Map = std::map<std::string, Value> >
+ struct MapLookUpConverter {
+ const Map& _map;
+
+ MapLookUpConverter(const Map& map)
+ : _map(map) {}
+
+ Value operator()(const std::string& str) {
+ typename Map::const_iterator it = _map.find(str);
+ if (it == _map.end()) {
+ std::ostringstream msg;
+ msg << "Item not found: " << str;
+ throw FormatError(msg.str());
+ }
+ return it->second;
+ }
+ };
+
+ template <typename Value,
+ typename Map1 = std::map<std::string, Value>,
+ typename Map2 = std::map<std::string, Value> >
+ struct DoubleMapLookUpConverter {
+ const Map1& _map1;
+ const Map2& _map2;
+
+ DoubleMapLookUpConverter(const Map1& map1, const Map2& map2)
+ : _map1(map1), _map2(map2) {}
+
+ Value operator()(const std::string& str) {
+ typename Map1::const_iterator it1 = _map1.find(str);
+ typename Map2::const_iterator it2 = _map2.find(str);
+ if (it1 == _map1.end()) {
+ if (it2 == _map2.end()) {
+ std::ostringstream msg;
+ msg << "Item not found: " << str;
+ throw FormatError(msg.str());
+ } else {
+ return it2->second;
+ }
+ } else {
+ if (it2 == _map2.end()) {
+ return it1->second;
+ } else {
+ std::ostringstream msg;
+ msg << "Item is ambigous: " << str;
+ throw FormatError(msg.str());
+ }
+ }
+ }
+ };
+
+ template <typename GR>
+ struct GraphArcLookUpConverter {
+ const GR& _graph;
+ const std::map<std::string, typename GR::Edge>& _map;
+
+ GraphArcLookUpConverter(const GR& graph,
+ const std::map<std::string,
+ typename GR::Edge>& map)
+ : _graph(graph), _map(map) {}
+
+ typename GR::Arc operator()(const std::string& str) {
+ if (str.empty() || (str[0] != '+' && str[0] != '-')) {
+ throw FormatError("Item must start with '+' or '-'");
+ }
+ typename std::map<std::string, typename GR::Edge>
+ ::const_iterator it = _map.find(str.substr(1));
+ if (it == _map.end()) {
+ throw FormatError("Item not found");
+ }
+ return _graph.direct(it->second, str[0] == '+');
+ }
+ };
+
+ inline bool isWhiteSpace(char c) {
+ return c == ' ' || c == '\t' || c == '\v' ||
+ c == '\n' || c == '\r' || c == '\f';
+ }
+
+ inline bool isOct(char c) {
+ return '0' <= c && c <='7';
+ }
+
+ inline int valueOct(char c) {
+ LEMON_ASSERT(isOct(c), "The character is not octal.");
+ return c - '0';
+ }
+
+ inline bool isHex(char c) {
+ return ('0' <= c && c <= '9') ||
+ ('a' <= c && c <= 'z') ||
+ ('A' <= c && c <= 'Z');
+ }
+
+ inline int valueHex(char c) {
+ LEMON_ASSERT(isHex(c), "The character is not hexadecimal.");
+ if ('0' <= c && c <= '9') return c - '0';
+ if ('a' <= c && c <= 'z') return c - 'a' + 10;
+ return c - 'A' + 10;
+ }
+
+ inline bool isIdentifierFirstChar(char c) {
+ return ('a' <= c && c <= 'z') ||
+ ('A' <= c && c <= 'Z') || c == '_';
+ }
+
+ inline bool isIdentifierChar(char c) {
+ return isIdentifierFirstChar(c) ||
+ ('0' <= c && c <= '9');
+ }
+
+ inline char readEscape(std::istream& is) {
+ char c;
+ if (!is.get(c))
+ throw FormatError("Escape format error");
+
+ switch (c) {
+ case '\\':
+ return '\\';
+ case '\"':
+ return '\"';
+ case '\'':
+ return '\'';
+ case '\?':
+ return '\?';
+ case 'a':
+ return '\a';
+ case 'b':
+ return '\b';
+ case 'f':
+ return '\f';
+ case 'n':
+ return '\n';
+ case 'r':
+ return '\r';
+ case 't':
+ return '\t';
+ case 'v':
+ return '\v';
+ case 'x':
+ {
+ int code;
+ if (!is.get(c) || !isHex(c))
+ throw FormatError("Escape format error");
+ else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
+ else code = code * 16 + valueHex(c);
+ return code;
+ }
+ default:
+ {
+ int code;
+ if (!isOct(c))
+ throw FormatError("Escape format error");
+ else if (code = valueOct(c), !is.get(c) || !isOct(c))
+ is.putback(c);
+ else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
+ is.putback(c);
+ else code = code * 8 + valueOct(c);
+ return code;
+ }
+ }
+ }
+
+ inline std::istream& readToken(std::istream& is, std::string& str) {
+ std::ostringstream os;
+
+ char c;
+ is >> std::ws;
+
+ if (!is.get(c))
+ return is;
+
+ if (c == '\"') {
+ while (is.get(c) && c != '\"') {
+ if (c == '\\')
+ c = readEscape(is);
+ os << c;
+ }
+ if (!is)
+ throw FormatError("Quoted format error");
+ } else {
+ is.putback(c);
+ while (is.get(c) && !isWhiteSpace(c)) {
+ if (c == '\\')
+ c = readEscape(is);
+ os << c;
+ }
+ if (!is) {
+ is.clear();
+ } else {
+ is.putback(c);
+ }
+ }
+ str = os.str();
+ return is;
+ }
+
+ class Section {
+ public:
+ virtual ~Section() {}
+ virtual void process(std::istream& is, int& line_num) = 0;
+ };
+
+ template <typename Functor>
+ class LineSection : public Section {
+ private:
+
+ Functor _functor;
+
+ public:
+
+ LineSection(const Functor& functor) : _functor(functor) {}
+ virtual ~LineSection() {}
+
+ virtual void process(std::istream& is, int& line_num) {
+ char c;
+ std::string line;
+ while (is.get(c) && c != '@') {
+ if (c == '\n') {
+ ++line_num;
+ } else if (c == '#') {
+ getline(is, line);
+ ++line_num;
+ } else if (!isWhiteSpace(c)) {
+ is.putback(c);
+ getline(is, line);
+ _functor(line);
+ ++line_num;
+ }
+ }
+ if (is) is.putback(c);
+ else if (is.eof()) is.clear();
+ }
+ };
+
+ template <typename Functor>
+ class StreamSection : public Section {
+ private:
+
+ Functor _functor;
+
+ public:
+
+ StreamSection(const Functor& functor) : _functor(functor) {}
+ virtual ~StreamSection() {}
+
+ virtual void process(std::istream& is, int& line_num) {
+ _functor(is, line_num);
+ char c;
+ std::string line;
+ while (is.get(c) && c != '@') {
+ if (c == '\n') {
+ ++line_num;
+ } else if (!isWhiteSpace(c)) {
+ getline(is, line);
+ ++line_num;
+ }
+ }
+ if (is) is.putback(c);
+ else if (is.eof()) is.clear();
+ }
+ };
+
+ }
+
+ template <typename DGR>
+ class DigraphReader;
+
+ template <typename TDGR>
+ DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is = std::cin);
+ template <typename TDGR>
+ DigraphReader<TDGR> digraphReader(TDGR& digraph, const std::string& fn);
+ template <typename TDGR>
+ DigraphReader<TDGR> digraphReader(TDGR& digraph, const char *fn);
+
+ /// \ingroup lemon_io
+ ///
+ /// \brief \ref lgf-format "LGF" reader for directed graphs
+ ///
+ /// This utility reads an \ref lgf-format "LGF" file.
+ ///
+ /// The reading method does a batch processing. The user creates a
+ /// reader object, then various reading rules can be added to the
+ /// reader, and eventually the reading is executed with the \c run()
+ /// member function. A map reading rule can be added to the reader
+ /// with the \c nodeMap() or \c arcMap() members. An optional
+ /// converter parameter can also be added as a standard functor
+ /// converting from \c std::string to the value type of the map. If it
+ /// is set, it will determine how the tokens in the file should be
+ /// converted to the value type of the map. If the functor is not set,
+ /// then a default conversion will be used. One map can be read into
+ /// multiple map objects at the same time. The \c attribute(), \c
+ /// node() and \c arc() functions are used to add attribute reading
+ /// rules.
+ ///
+ ///\code
+ /// DigraphReader<DGR>(digraph, std::cin).
+ /// nodeMap("coordinates", coord_map).
+ /// arcMap("capacity", cap_map).
+ /// node("source", src).
+ /// node("target", trg).
+ /// attribute("caption", caption).
+ /// run();
+ ///\endcode
+ ///
+ /// By default, the reader uses the first section in the file of the
+ /// proper type. If a section has an optional name, then it can be
+ /// selected for reading by giving an optional name parameter to the
+ /// \c nodes(), \c arcs() or \c attributes() functions.
+ ///
+ /// The \c useNodes() and \c useArcs() functions are used to tell the reader
+ /// that the nodes or arcs should not be constructed (added to the
+ /// graph) during the reading, but instead the label map of the items
+ /// are given as a parameter of these functions. An
+ /// application of these functions is multipass reading, which is
+ /// important if two \c \@arcs sections must be read from the
+ /// file. In this case the first phase would read the node set and one
+ /// of the arc sets, while the second phase would read the second arc
+ /// set into an \e ArcSet class (\c SmartArcSet or \c ListArcSet).
+ /// The previously read label node map should be passed to the \c
+ /// useNodes() functions. Another application of multipass reading when
+ /// paths are given as a node map or an arc map.
+ /// It is impossible to read this in
+ /// a single pass, because the arcs are not constructed when the node
+ /// maps are read.
+ template <typename DGR>
+ class DigraphReader {
+ public:
+
+ typedef DGR Digraph;
+
+ private:
+
+ TEMPLATE_DIGRAPH_TYPEDEFS(DGR);
+
+ std::istream* _is;
+ bool local_is;
+ std::string _filename;
+
+ DGR& _digraph;
+
+ std::string _nodes_caption;
+ std::string _arcs_caption;
+ std::string _attributes_caption;
+
+ typedef std::map<std::string, Node> NodeIndex;
+ NodeIndex _node_index;
+ typedef std::map<std::string, Arc> ArcIndex;
+ ArcIndex _arc_index;
+
+ typedef std::vector<std::pair<std::string,
+ _reader_bits::MapStorageBase<Node>*> > NodeMaps;
+ NodeMaps _node_maps;
+
+ typedef std::vector<std::pair<std::string,
+ _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
+ ArcMaps _arc_maps;
+
+ typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
+ Attributes;
+ Attributes _attributes;
+
+ bool _use_nodes;
+ bool _use_arcs;
+
+ bool _skip_nodes;
+ bool _skip_arcs;
+
+ int line_num;
+ std::istringstream line;
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Construct a directed graph reader, which reads from the given
+ /// input stream.
+ DigraphReader(DGR& digraph, std::istream& is = std::cin)
+ : _is(&is), local_is(false), _digraph(digraph),
+ _use_nodes(false), _use_arcs(false),
+ _skip_nodes(false), _skip_arcs(false) {}
+
+ /// \brief Constructor
+ ///
+ /// Construct a directed graph reader, which reads from the given
+ /// file.
+ DigraphReader(DGR& digraph, const std::string& fn)
+ : _is(new std::ifstream(fn.c_str())), local_is(true),
+ _filename(fn), _digraph(digraph),
+ _use_nodes(false), _use_arcs(false),
+ _skip_nodes(false), _skip_arcs(false) {
+ if (!(*_is)) {
+ delete _is;
+ throw IoError("Cannot open file", fn);
+ }
+ }
+
+ /// \brief Constructor
+ ///
+ /// Construct a directed graph reader, which reads from the given
+ /// file.
+ DigraphReader(DGR& digraph, const char* fn)
+ : _is(new std::ifstream(fn)), local_is(true),
+ _filename(fn), _digraph(digraph),
+ _use_nodes(false), _use_arcs(false),
+ _skip_nodes(false), _skip_arcs(false) {
+ if (!(*_is)) {
+ delete _is;
+ throw IoError("Cannot open file", fn);
+ }
+ }
+
+ /// \brief Destructor
+ ~DigraphReader() {
+ for (typename NodeMaps::iterator it = _node_maps.begin();
+ it != _node_maps.end(); ++it) {
+ delete it->second;
+ }
+
+ for (typename ArcMaps::iterator it = _arc_maps.begin();
+ it != _arc_maps.end(); ++it) {
+ delete it->second;
+ }
+
+ for (typename Attributes::iterator it = _attributes.begin();
+ it != _attributes.end(); ++it) {
+ delete it->second;
+ }
+
+ if (local_is) {
+ delete _is;
+ }
+
+ }
+
+ private:
+
+ template <typename TDGR>
+ friend DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is);
+ template <typename TDGR>
+ friend DigraphReader<TDGR> digraphReader(TDGR& digraph,
+ const std::string& fn);
+ template <typename TDGR>
+ friend DigraphReader<TDGR> digraphReader(TDGR& digraph, const char *fn);
+
+ DigraphReader(DigraphReader& other)
+ : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
+ _use_nodes(other._use_nodes), _use_arcs(other._use_arcs),
+ _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
+
+ other._is = 0;
+ other.local_is = false;
+
+ _node_index.swap(other._node_index);
+ _arc_index.swap(other._arc_index);
+
+ _node_maps.swap(other._node_maps);
+ _arc_maps.swap(other._arc_maps);
+ _attributes.swap(other._attributes);
+
+ _nodes_caption = other._nodes_caption;
+ _arcs_caption = other._arcs_caption;
+ _attributes_caption = other._attributes_caption;
+
+ }
+
+ DigraphReader& operator=(const DigraphReader&);
+
+ public:
+
+ /// \name Reading Rules
+ /// @{
+
+ /// \brief Node map reading rule
+ ///
+ /// Add a node map reading rule to the reader.
+ template <typename Map>
+ DigraphReader& nodeMap(const std::string& caption, Map& map) {
+ checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<Node>* storage =
+ new _reader_bits::MapStorage<Node, Map>(map);
+ _node_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Node map reading rule
+ ///
+ /// Add a node map reading rule with specialized converter to the
+ /// reader.
+ template <typename Map, typename Converter>
+ DigraphReader& nodeMap(const std::string& caption, Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<Node>* storage =
+ new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
+ _node_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Arc map reading rule
+ ///
+ /// Add an arc map reading rule to the reader.
+ template <typename Map>
+ DigraphReader& arcMap(const std::string& caption, Map& map) {
+ checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<Arc>* storage =
+ new _reader_bits::MapStorage<Arc, Map>(map);
+ _arc_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Arc map reading rule
+ ///
+ /// Add an arc map reading rule with specialized converter to the
+ /// reader.
+ template <typename Map, typename Converter>
+ DigraphReader& arcMap(const std::string& caption, Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<Arc>* storage =
+ new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter);
+ _arc_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Attribute reading rule
+ ///
+ /// Add an attribute reading rule to the reader.
+ template <typename Value>
+ DigraphReader& attribute(const std::string& caption, Value& value) {
+ _reader_bits::ValueStorageBase* storage =
+ new _reader_bits::ValueStorage<Value>(value);
+ _attributes.insert(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Attribute reading rule
+ ///
+ /// Add an attribute reading rule with specialized converter to the
+ /// reader.
+ template <typename Value, typename Converter>
+ DigraphReader& attribute(const std::string& caption, Value& value,
+ const Converter& converter = Converter()) {
+ _reader_bits::ValueStorageBase* storage =
+ new _reader_bits::ValueStorage<Value, Converter>(value, converter);
+ _attributes.insert(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Node reading rule
+ ///
+ /// Add a node reading rule to reader.
+ DigraphReader& node(const std::string& caption, Node& node) {
+ typedef _reader_bits::MapLookUpConverter<Node> Converter;
+ Converter converter(_node_index);
+ _reader_bits::ValueStorageBase* storage =
+ new _reader_bits::ValueStorage<Node, Converter>(node, converter);
+ _attributes.insert(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Arc reading rule
+ ///
+ /// Add an arc reading rule to reader.
+ DigraphReader& arc(const std::string& caption, Arc& arc) {
+ typedef _reader_bits::MapLookUpConverter<Arc> Converter;
+ Converter converter(_arc_index);
+ _reader_bits::ValueStorageBase* storage =
+ new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
+ _attributes.insert(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// @}
+
+ /// \name Select Section by Name
+ /// @{
+
+ /// \brief Set \c \@nodes section to be read
+ ///
+ /// Set \c \@nodes section to be read
+ DigraphReader& nodes(const std::string& caption) {
+ _nodes_caption = caption;
+ return *this;
+ }
+
+ /// \brief Set \c \@arcs section to be read
+ ///
+ /// Set \c \@arcs section to be read
+ DigraphReader& arcs(const std::string& caption) {
+ _arcs_caption = caption;
+ return *this;
+ }
+
+ /// \brief Set \c \@attributes section to be read
+ ///
+ /// Set \c \@attributes section to be read
+ DigraphReader& attributes(const std::string& caption) {
+ _attributes_caption = caption;
+ return *this;
+ }
+
+ /// @}
+
+ /// \name Using Previously Constructed Node or Arc Set
+ /// @{
+
+ /// \brief Use previously constructed node set
+ ///
+ /// Use previously constructed node set, and specify the node
+ /// label map.
+ template <typename Map>
+ DigraphReader& useNodes(const Map& map) {
+ checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
+ LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
+ _use_nodes = true;
+ _writer_bits::DefaultConverter<typename Map::Value> converter;
+ for (NodeIt n(_digraph); n != INVALID; ++n) {
+ _node_index.insert(std::make_pair(converter(map[n]), n));
+ }
+ return *this;
+ }
+
+ /// \brief Use previously constructed node set
+ ///
+ /// Use previously constructed node set, and specify the node
+ /// label map and a functor which converts the label map values to
+ /// \c std::string.
+ template <typename Map, typename Converter>
+ DigraphReader& useNodes(const Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
+ LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
+ _use_nodes = true;
+ for (NodeIt n(_digraph); n != INVALID; ++n) {
+ _node_index.insert(std::make_pair(converter(map[n]), n));
+ }
+ return *this;
+ }
+
+ /// \brief Use previously constructed arc set
+ ///
+ /// Use previously constructed arc set, and specify the arc
+ /// label map.
+ template <typename Map>
+ DigraphReader& useArcs(const Map& map) {
+ checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
+ LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
+ _use_arcs = true;
+ _writer_bits::DefaultConverter<typename Map::Value> converter;
+ for (ArcIt a(_digraph); a != INVALID; ++a) {
+ _arc_index.insert(std::make_pair(converter(map[a]), a));
+ }
+ return *this;
+ }
+
+ /// \brief Use previously constructed arc set
+ ///
+ /// Use previously constructed arc set, and specify the arc
+ /// label map and a functor which converts the label map values to
+ /// \c std::string.
+ template <typename Map, typename Converter>
+ DigraphReader& useArcs(const Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
+ LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
+ _use_arcs = true;
+ for (ArcIt a(_digraph); a != INVALID; ++a) {
+ _arc_index.insert(std::make_pair(converter(map[a]), a));
+ }
+ return *this;
+ }
+
+ /// \brief Skips the reading of node section
+ ///
+ /// Omit the reading of the node section. This implies that each node
+ /// map reading rule will be abandoned, and the nodes of the graph
+ /// will not be constructed, which usually cause that the arc set
+ /// could not be read due to lack of node name resolving.
+ /// Therefore \c skipArcs() function should also be used, or
+ /// \c useNodes() should be used to specify the label of the nodes.
+ DigraphReader& skipNodes() {
+ LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
+ _skip_nodes = true;
+ return *this;
+ }
+
+ /// \brief Skips the reading of arc section
+ ///
+ /// Omit the reading of the arc section. This implies that each arc
+ /// map reading rule will be abandoned, and the arcs of the graph
+ /// will not be constructed.
+ DigraphReader& skipArcs() {
+ LEMON_ASSERT(!_skip_arcs, "Skip arcs already set");
+ _skip_arcs = true;
+ return *this;
+ }
+
+ /// @}
+
+ private:
+
+ bool readLine() {
+ std::string str;
+ while(++line_num, std::getline(*_is, str)) {
+ line.clear(); line.str(str);
+ char c;
+ if (line >> std::ws >> c && c != '#') {
+ line.putback(c);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool readSuccess() {
+ return static_cast<bool>(*_is);
+ }
+
+ void skipSection() {
+ char c;
+ while (readSuccess() && line >> c && c != '@') {
+ readLine();
+ }
+ if (readSuccess()) {
+ line.putback(c);
+ }
+ }
+
+ void readNodes() {
+
+ std::vector<int> map_index(_node_maps.size());
+ int map_num, label_index;
+
+ char c;
+ if (!readLine() || !(line >> c) || c == '@') {
+ if (readSuccess() && line) line.putback(c);
+ if (!_node_maps.empty())
+ throw FormatError("Cannot find map names");
+ return;
+ }
+ line.putback(c);
+
+ {
+ std::map<std::string, int> maps;
+
+ std::string map;
+ int index = 0;
+ while (_reader_bits::readToken(line, map)) {
+ if (maps.find(map) != maps.end()) {
+ std::ostringstream msg;
+ msg << "Multiple occurence of node map: " << map;
+ throw FormatError(msg.str());
+ }
+ maps.insert(std::make_pair(map, index));
+ ++index;
+ }
+
+ for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
+ std::map<std::string, int>::iterator jt =
+ maps.find(_node_maps[i].first);
+ if (jt == maps.end()) {
+ std::ostringstream msg;
+ msg << "Map not found: " << _node_maps[i].first;
+ throw FormatError(msg.str());
+ }
+ map_index[i] = jt->second;
+ }
+
+ {
+ std::map<std::string, int>::iterator jt = maps.find("label");
+ if (jt != maps.end()) {
+ label_index = jt->second;
+ } else {
+ label_index = -1;
+ }
+ }
+ map_num = maps.size();
+ }
+
+ while (readLine() && line >> c && c != '@') {
+ line.putback(c);
+
+ std::vector<std::string> tokens(map_num);
+ for (int i = 0; i < map_num; ++i) {
+ if (!_reader_bits::readToken(line, tokens[i])) {
+ std::ostringstream msg;
+ msg << "Column not found (" << i + 1 << ")";
+ throw FormatError(msg.str());
+ }
+ }
+ if (line >> std::ws >> c)
+ throw FormatError("Extra character at the end of line");
+
+ Node n;
+ if (!_use_nodes) {
+ n = _digraph.addNode();
+ if (label_index != -1)
+ _node_index.insert(std::make_pair(tokens[label_index], n));
+ } else {
+ if (label_index == -1)
+ throw FormatError("Label map not found");
+ typename std::map<std::string, Node>::iterator it =
+ _node_index.find(tokens[label_index]);
+ if (it == _node_index.end()) {
+ std::ostringstream msg;
+ msg << "Node with label not found: " << tokens[label_index];
+ throw FormatError(msg.str());
+ }
+ n = it->second;
+ }
+
+ for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
+ _node_maps[i].second->set(n, tokens[map_index[i]]);
+ }
+
+ }
+ if (readSuccess()) {
+ line.putback(c);
+ }
+ }
+
+ void readArcs() {
+
+ std::vector<int> map_index(_arc_maps.size());
+ int map_num, label_index;
+
+ char c;
+ if (!readLine() || !(line >> c) || c == '@') {
+ if (readSuccess() && line) line.putback(c);
+ if (!_arc_maps.empty())
+ throw FormatError("Cannot find map names");
+ return;
+ }
+ line.putback(c);
+
+ {
+ std::map<std::string, int> maps;
+
+ std::string map;
+ int index = 0;
+ while (_reader_bits::readToken(line, map)) {
+ if(map == "-") {
+ if(index!=0)
+ throw FormatError("'-' is not allowed as a map name");
+ else if (line >> std::ws >> c)
+ throw FormatError("Extra character at the end of line");
+ else break;
+ }
+ if (maps.find(map) != maps.end()) {
+ std::ostringstream msg;
+ msg << "Multiple occurence of arc map: " << map;
+ throw FormatError(msg.str());
+ }
+ maps.insert(std::make_pair(map, index));
+ ++index;
+ }
+
+ for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
+ std::map<std::string, int>::iterator jt =
+ maps.find(_arc_maps[i].first);
+ if (jt == maps.end()) {
+ std::ostringstream msg;
+ msg << "Map not found: " << _arc_maps[i].first;
+ throw FormatError(msg.str());
+ }
+ map_index[i] = jt->second;
+ }
+
+ {
+ std::map<std::string, int>::iterator jt = maps.find("label");
+ if (jt != maps.end()) {
+ label_index = jt->second;
+ } else {
+ label_index = -1;
+ }
+ }
+ map_num = maps.size();
+ }
+
+ while (readLine() && line >> c && c != '@') {
+ line.putback(c);
+
+ std::string source_token;
+ std::string target_token;
+
+ if (!_reader_bits::readToken(line, source_token))
+ throw FormatError("Source not found");
+
+ if (!_reader_bits::readToken(line, target_token))
+ throw FormatError("Target not found");
+
+ std::vector<std::string> tokens(map_num);
+ for (int i = 0; i < map_num; ++i) {
+ if (!_reader_bits::readToken(line, tokens[i])) {
+ std::ostringstream msg;
+ msg << "Column not found (" << i + 1 << ")";
+ throw FormatError(msg.str());
+ }
+ }
+ if (line >> std::ws >> c)
+ throw FormatError("Extra character at the end of line");
+
+ Arc a;
+ if (!_use_arcs) {
+
+ typename NodeIndex::iterator it;
+
+ it = _node_index.find(source_token);
+ if (it == _node_index.end()) {
+ std::ostringstream msg;
+ msg << "Item not found: " << source_token;
+ throw FormatError(msg.str());
+ }
+ Node source = it->second;
+
+ it = _node_index.find(target_token);
+ if (it == _node_index.end()) {
+ std::ostringstream msg;
+ msg << "Item not found: " << target_token;
+ throw FormatError(msg.str());
+ }
+ Node target = it->second;
+
+ a = _digraph.addArc(source, target);
+ if (label_index != -1)
+ _arc_index.insert(std::make_pair(tokens[label_index], a));
+ } else {
+ if (label_index == -1)
+ throw FormatError("Label map not found");
+ typename std::map<std::string, Arc>::iterator it =
+ _arc_index.find(tokens[label_index]);
+ if (it == _arc_index.end()) {
+ std::ostringstream msg;
+ msg << "Arc with label not found: " << tokens[label_index];
+ throw FormatError(msg.str());
+ }
+ a = it->second;
+ }
+
+ for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
+ _arc_maps[i].second->set(a, tokens[map_index[i]]);
+ }
+
+ }
+ if (readSuccess()) {
+ line.putback(c);
+ }
+ }
+
+ void readAttributes() {
+
+ std::set<std::string> read_attr;
+
+ char c;
+ while (readLine() && line >> c && c != '@') {
+ line.putback(c);
+
+ std::string attr, token;
+ if (!_reader_bits::readToken(line, attr))
+ throw FormatError("Attribute name not found");
+ if (!_reader_bits::readToken(line, token))
+ throw FormatError("Attribute value not found");
+ if (line >> c)
+ throw FormatError("Extra character at the end of line");
+
+ {
+ std::set<std::string>::iterator it = read_attr.find(attr);
+ if (it != read_attr.end()) {
+ std::ostringstream msg;
+ msg << "Multiple occurence of attribute: " << attr;
+ throw FormatError(msg.str());
+ }
+ read_attr.insert(attr);
+ }
+
+ {
+ typename Attributes::iterator it = _attributes.lower_bound(attr);
+ while (it != _attributes.end() && it->first == attr) {
+ it->second->set(token);
+ ++it;
+ }
+ }
+
+ }
+ if (readSuccess()) {
+ line.putback(c);
+ }
+ for (typename Attributes::iterator it = _attributes.begin();
+ it != _attributes.end(); ++it) {
+ if (read_attr.find(it->first) == read_attr.end()) {
+ std::ostringstream msg;
+ msg << "Attribute not found: " << it->first;
+ throw FormatError(msg.str());
+ }
+ }
+ }
+
+ public:
+
+ /// \name Execution of the Reader
+ /// @{
+
+ /// \brief Start the batch processing
+ ///
+ /// This function starts the batch processing
+ void run() {
+ LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
+
+ bool nodes_done = _skip_nodes;
+ bool arcs_done = _skip_arcs;
+ bool attributes_done = false;
+
+ line_num = 0;
+ readLine();
+ skipSection();
+
+ while (readSuccess()) {
+ try {
+ char c;
+ std::string section, caption;
+ line >> c;
+ _reader_bits::readToken(line, section);
+ _reader_bits::readToken(line, caption);
+
+ if (line >> c)
+ throw FormatError("Extra character at the end of line");
+
+ if (section == "nodes" && !nodes_done) {
+ if (_nodes_caption.empty() || _nodes_caption == caption) {
+ readNodes();
+ nodes_done = true;
+ }
+ } else if ((section == "arcs" || section == "edges") &&
+ !arcs_done) {
+ if (_arcs_caption.empty() || _arcs_caption == caption) {
+ readArcs();
+ arcs_done = true;
+ }
+ } else if (section == "attributes" && !attributes_done) {
+ if (_attributes_caption.empty() || _attributes_caption == caption) {
+ readAttributes();
+ attributes_done = true;
+ }
+ } else {
+ readLine();
+ skipSection();
+ }
+ } catch (FormatError& error) {
+ error.line(line_num);
+ error.file(_filename);
+ throw;
+ }
+ }
+
+ if (!nodes_done) {
+ throw FormatError("Section @nodes not found");
+ }
+
+ if (!arcs_done) {
+ throw FormatError("Section @arcs not found");
+ }
+
+ if (!attributes_done && !_attributes.empty()) {
+ throw FormatError("Section @attributes not found");
+ }
+
+ }
+
+ /// @}
+
+ };
+
+ /// \ingroup lemon_io
+ ///
+ /// \brief Return a \ref lemon::DigraphReader "DigraphReader" class
+ ///
+ /// This function just returns a \ref lemon::DigraphReader
+ /// "DigraphReader" class.
+ ///
+ /// With this function a digraph can be read from an
+ /// \ref lgf-format "LGF" file or input stream with several maps and
+ /// attributes. For example, there is network flow problem on a
+ /// digraph, i.e. a digraph with a \e capacity map on the arcs and
+ /// \e source and \e target nodes. This digraph can be read with the
+ /// following code:
+ ///
+ ///\code
+ ///ListDigraph digraph;
+ ///ListDigraph::ArcMap<int> cm(digraph);
+ ///ListDigraph::Node src, trg;
+ ///digraphReader(digraph, std::cin).
+ /// arcMap("capacity", cap).
+ /// node("source", src).
+ /// node("target", trg).
+ /// run();
+ ///\endcode
+ ///
+ /// For a complete documentation, please see the
+ /// \ref lemon::DigraphReader "DigraphReader"
+ /// class documentation.
+ /// \warning Don't forget to put the \ref lemon::DigraphReader::run() "run()"
+ /// to the end of the parameter list.
+ /// \relates DigraphReader
+ /// \sa digraphReader(TDGR& digraph, const std::string& fn)
+ /// \sa digraphReader(TDGR& digraph, const char* fn)
+ template <typename TDGR>
+ DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is) {
+ DigraphReader<TDGR> tmp(digraph, is);
+ return tmp;
+ }
+
+ /// \brief Return a \ref DigraphReader class
+ ///
+ /// This function just returns a \ref DigraphReader class.
+ /// \relates DigraphReader
+ /// \sa digraphReader(TDGR& digraph, std::istream& is)
+ template <typename TDGR>
+ DigraphReader<TDGR> digraphReader(TDGR& digraph, const std::string& fn) {
+ DigraphReader<TDGR> tmp(digraph, fn);
+ return tmp;
+ }
+
+ /// \brief Return a \ref DigraphReader class
+ ///
+ /// This function just returns a \ref DigraphReader class.
+ /// \relates DigraphReader
+ /// \sa digraphReader(TDGR& digraph, std::istream& is)
+ template <typename TDGR>
+ DigraphReader<TDGR> digraphReader(TDGR& digraph, const char* fn) {
+ DigraphReader<TDGR> tmp(digraph, fn);
+ return tmp;
+ }
+
+ template <typename GR>
+ class GraphReader;
+
+ template <typename TGR>
+ GraphReader<TGR> graphReader(TGR& graph, std::istream& is = std::cin);
+ template <typename TGR>
+ GraphReader<TGR> graphReader(TGR& graph, const std::string& fn);
+ template <typename TGR>
+ GraphReader<TGR> graphReader(TGR& graph, const char *fn);
+
+ /// \ingroup lemon_io
+ ///
+ /// \brief \ref lgf-format "LGF" reader for undirected graphs
+ ///
+ /// This utility reads an \ref lgf-format "LGF" file.
+ ///
+ /// It can be used almost the same way as \c DigraphReader.
+ /// The only difference is that this class can handle edges and
+ /// edge maps as well as arcs and arc maps.
+ ///
+ /// The columns in the \c \@edges (or \c \@arcs) section are the
+ /// edge maps. However, if there are two maps with the same name
+ /// prefixed with \c '+' and \c '-', then these can be read into an
+ /// arc map. Similarly, an attribute can be read into an arc, if
+ /// it's value is an edge label prefixed with \c '+' or \c '-'.
+ template <typename GR>
+ class GraphReader {
+ public:
+
+ typedef GR Graph;
+
+ private:
+
+ TEMPLATE_GRAPH_TYPEDEFS(GR);
+
+ std::istream* _is;
+ bool local_is;
+ std::string _filename;
+
+ GR& _graph;
+
+ std::string _nodes_caption;
+ std::string _edges_caption;
+ std::string _attributes_caption;
+
+ typedef std::map<std::string, Node> NodeIndex;
+ NodeIndex _node_index;
+ typedef std::map<std::string, Edge> EdgeIndex;
+ EdgeIndex _edge_index;
+
+ typedef std::vector<std::pair<std::string,
+ _reader_bits::MapStorageBase<Node>*> > NodeMaps;
+ NodeMaps _node_maps;
+
+ typedef std::vector<std::pair<std::string,
+ _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
+ EdgeMaps _edge_maps;
+
+ typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
+ Attributes;
+ Attributes _attributes;
+
+ bool _use_nodes;
+ bool _use_edges;
+
+ bool _skip_nodes;
+ bool _skip_edges;
+
+ int line_num;
+ std::istringstream line;
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Construct an undirected graph reader, which reads from the given
+ /// input stream.
+ GraphReader(GR& graph, std::istream& is = std::cin)
+ : _is(&is), local_is(false), _graph(graph),
+ _use_nodes(false), _use_edges(false),
+ _skip_nodes(false), _skip_edges(false) {}
+
+ /// \brief Constructor
+ ///
+ /// Construct an undirected graph reader, which reads from the given
+ /// file.
+ GraphReader(GR& graph, const std::string& fn)
+ : _is(new std::ifstream(fn.c_str())), local_is(true),
+ _filename(fn), _graph(graph),
+ _use_nodes(false), _use_edges(false),
+ _skip_nodes(false), _skip_edges(false) {
+ if (!(*_is)) {
+ delete _is;
+ throw IoError("Cannot open file", fn);
+ }
+ }
+
+ /// \brief Constructor
+ ///
+ /// Construct an undirected graph reader, which reads from the given
+ /// file.
+ GraphReader(GR& graph, const char* fn)
+ : _is(new std::ifstream(fn)), local_is(true),
+ _filename(fn), _graph(graph),
+ _use_nodes(false), _use_edges(false),
+ _skip_nodes(false), _skip_edges(false) {
+ if (!(*_is)) {
+ delete _is;
+ throw IoError("Cannot open file", fn);
+ }
+ }
+
+ /// \brief Destructor
+ ~GraphReader() {
+ for (typename NodeMaps::iterator it = _node_maps.begin();
+ it != _node_maps.end(); ++it) {
+ delete it->second;
+ }
+
+ for (typename EdgeMaps::iterator it = _edge_maps.begin();
+ it != _edge_maps.end(); ++it) {
+ delete it->second;
+ }
+
+ for (typename Attributes::iterator it = _attributes.begin();
+ it != _attributes.end(); ++it) {
+ delete it->second;
+ }
+
+ if (local_is) {
+ delete _is;
+ }
+
+ }
+
+ private:
+ template <typename TGR>
+ friend GraphReader<TGR> graphReader(TGR& graph, std::istream& is);
+ template <typename TGR>
+ friend GraphReader<TGR> graphReader(TGR& graph, const std::string& fn);
+ template <typename TGR>
+ friend GraphReader<TGR> graphReader(TGR& graph, const char *fn);
+
+ GraphReader(GraphReader& other)
+ : _is(other._is), local_is(other.local_is), _graph(other._graph),
+ _use_nodes(other._use_nodes), _use_edges(other._use_edges),
+ _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
+
+ other._is = 0;
+ other.local_is = false;
+
+ _node_index.swap(other._node_index);
+ _edge_index.swap(other._edge_index);
+
+ _node_maps.swap(other._node_maps);
+ _edge_maps.swap(other._edge_maps);
+ _attributes.swap(other._attributes);
+
+ _nodes_caption = other._nodes_caption;
+ _edges_caption = other._edges_caption;
+ _attributes_caption = other._attributes_caption;
+
+ }
+
+ GraphReader& operator=(const GraphReader&);
+
+ public:
+
+ /// \name Reading Rules
+ /// @{
+
+ /// \brief Node map reading rule
+ ///
+ /// Add a node map reading rule to the reader.
+ template <typename Map>
+ GraphReader& nodeMap(const std::string& caption, Map& map) {
+ checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<Node>* storage =
+ new _reader_bits::MapStorage<Node, Map>(map);
+ _node_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Node map reading rule
+ ///
+ /// Add a node map reading rule with specialized converter to the
+ /// reader.
+ template <typename Map, typename Converter>
+ GraphReader& nodeMap(const std::string& caption, Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<Node>* storage =
+ new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
+ _node_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Edge map reading rule
+ ///
+ /// Add an edge map reading rule to the reader.
+ template <typename Map>
+ GraphReader& edgeMap(const std::string& caption, Map& map) {
+ checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<Edge>* storage =
+ new _reader_bits::MapStorage<Edge, Map>(map);
+ _edge_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Edge map reading rule
+ ///
+ /// Add an edge map reading rule with specialized converter to the
+ /// reader.
+ template <typename Map, typename Converter>
+ GraphReader& edgeMap(const std::string& caption, Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<Edge>* storage =
+ new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
+ _edge_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Arc map reading rule
+ ///
+ /// Add an arc map reading rule to the reader.
+ template <typename Map>
+ GraphReader& arcMap(const std::string& caption, Map& map) {
+ checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<Edge>* forward_storage =
+ new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
+ _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
+ _reader_bits::MapStorageBase<Edge>* backward_storage =
+ new _reader_bits::GraphArcMapStorage<GR, false, Map>(_graph, map);
+ _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
+ return *this;
+ }
+
+ /// \brief Arc map reading rule
+ ///
+ /// Add an arc map reading rule with specialized converter to the
+ /// reader.
+ template <typename Map, typename Converter>
+ GraphReader& arcMap(const std::string& caption, Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<Edge>* forward_storage =
+ new _reader_bits::GraphArcMapStorage<GR, true, Map, Converter>
+ (_graph, map, converter);
+ _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
+ _reader_bits::MapStorageBase<Edge>* backward_storage =
+ new _reader_bits::GraphArcMapStorage<GR, false, Map, Converter>
+ (_graph, map, converter);
+ _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
+ return *this;
+ }
+
+ /// \brief Attribute reading rule
+ ///
+ /// Add an attribute reading rule to the reader.
+ template <typename Value>
+ GraphReader& attribute(const std::string& caption, Value& value) {
+ _reader_bits::ValueStorageBase* storage =
+ new _reader_bits::ValueStorage<Value>(value);
+ _attributes.insert(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Attribute reading rule
+ ///
+ /// Add an attribute reading rule with specialized converter to the
+ /// reader.
+ template <typename Value, typename Converter>
+ GraphReader& attribute(const std::string& caption, Value& value,
+ const Converter& converter = Converter()) {
+ _reader_bits::ValueStorageBase* storage =
+ new _reader_bits::ValueStorage<Value, Converter>(value, converter);
+ _attributes.insert(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Node reading rule
+ ///
+ /// Add a node reading rule to reader.
+ GraphReader& node(const std::string& caption, Node& node) {
+ typedef _reader_bits::MapLookUpConverter<Node> Converter;
+ Converter converter(_node_index);
+ _reader_bits::ValueStorageBase* storage =
+ new _reader_bits::ValueStorage<Node, Converter>(node, converter);
+ _attributes.insert(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Edge reading rule
+ ///
+ /// Add an edge reading rule to reader.
+ GraphReader& edge(const std::string& caption, Edge& edge) {
+ typedef _reader_bits::MapLookUpConverter<Edge> Converter;
+ Converter converter(_edge_index);
+ _reader_bits::ValueStorageBase* storage =
+ new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
+ _attributes.insert(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Arc reading rule
+ ///
+ /// Add an arc reading rule to reader.
+ GraphReader& arc(const std::string& caption, Arc& arc) {
+ typedef _reader_bits::GraphArcLookUpConverter<GR> Converter;
+ Converter converter(_graph, _edge_index);
+ _reader_bits::ValueStorageBase* storage =
+ new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
+ _attributes.insert(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// @}
+
+ /// \name Select Section by Name
+ /// @{
+
+ /// \brief Set \c \@nodes section to be read
+ ///
+ /// Set \c \@nodes section to be read.
+ GraphReader& nodes(const std::string& caption) {
+ _nodes_caption = caption;
+ return *this;
+ }
+
+ /// \brief Set \c \@edges section to be read
+ ///
+ /// Set \c \@edges section to be read.
+ GraphReader& edges(const std::string& caption) {
+ _edges_caption = caption;
+ return *this;
+ }
+
+ /// \brief Set \c \@attributes section to be read
+ ///
+ /// Set \c \@attributes section to be read.
+ GraphReader& attributes(const std::string& caption) {
+ _attributes_caption = caption;
+ return *this;
+ }
+
+ /// @}
+
+ /// \name Using Previously Constructed Node or Edge Set
+ /// @{
+
+ /// \brief Use previously constructed node set
+ ///
+ /// Use previously constructed node set, and specify the node
+ /// label map.
+ template <typename Map>
+ GraphReader& useNodes(const Map& map) {
+ checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
+ LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
+ _use_nodes = true;
+ _writer_bits::DefaultConverter<typename Map::Value> converter;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ _node_index.insert(std::make_pair(converter(map[n]), n));
+ }
+ return *this;
+ }
+
+ /// \brief Use previously constructed node set
+ ///
+ /// Use previously constructed node set, and specify the node
+ /// label map and a functor which converts the label map values to
+ /// \c std::string.
+ template <typename Map, typename Converter>
+ GraphReader& useNodes(const Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
+ LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
+ _use_nodes = true;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ _node_index.insert(std::make_pair(converter(map[n]), n));
+ }
+ return *this;
+ }
+
+ /// \brief Use previously constructed edge set
+ ///
+ /// Use previously constructed edge set, and specify the edge
+ /// label map.
+ template <typename Map>
+ GraphReader& useEdges(const Map& map) {
+ checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
+ LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
+ _use_edges = true;
+ _writer_bits::DefaultConverter<typename Map::Value> converter;
+ for (EdgeIt a(_graph); a != INVALID; ++a) {
+ _edge_index.insert(std::make_pair(converter(map[a]), a));
+ }
+ return *this;
+ }
+
+ /// \brief Use previously constructed edge set
+ ///
+ /// Use previously constructed edge set, and specify the edge
+ /// label map and a functor which converts the label map values to
+ /// \c std::string.
+ template <typename Map, typename Converter>
+ GraphReader& useEdges(const Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
+ LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
+ _use_edges = true;
+ for (EdgeIt a(_graph); a != INVALID; ++a) {
+ _edge_index.insert(std::make_pair(converter(map[a]), a));
+ }
+ return *this;
+ }
+
+ /// \brief Skip the reading of node section
+ ///
+ /// Omit the reading of the node section. This implies that each node
+ /// map reading rule will be abandoned, and the nodes of the graph
+ /// will not be constructed, which usually cause that the edge set
+ /// could not be read due to lack of node name
+ /// could not be read due to lack of node name resolving.
+ /// Therefore \c skipEdges() function should also be used, or
+ /// \c useNodes() should be used to specify the label of the nodes.
+ GraphReader& skipNodes() {
+ LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
+ _skip_nodes = true;
+ return *this;
+ }
+
+ /// \brief Skip the reading of edge section
+ ///
+ /// Omit the reading of the edge section. This implies that each edge
+ /// map reading rule will be abandoned, and the edges of the graph
+ /// will not be constructed.
+ GraphReader& skipEdges() {
+ LEMON_ASSERT(!_skip_edges, "Skip edges already set");
+ _skip_edges = true;
+ return *this;
+ }
+
+ /// @}
+
+ private:
+
+ bool readLine() {
+ std::string str;
+ while(++line_num, std::getline(*_is, str)) {
+ line.clear(); line.str(str);
+ char c;
+ if (line >> std::ws >> c && c != '#') {
+ line.putback(c);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool readSuccess() {
+ return static_cast<bool>(*_is);
+ }
+
+ void skipSection() {
+ char c;
+ while (readSuccess() && line >> c && c != '@') {
+ readLine();
+ }
+ if (readSuccess()) {
+ line.putback(c);
+ }
+ }
+
+ void readNodes() {
+
+ std::vector<int> map_index(_node_maps.size());
+ int map_num, label_index;
+
+ char c;
+ if (!readLine() || !(line >> c) || c == '@') {
+ if (readSuccess() && line) line.putback(c);
+ if (!_node_maps.empty())
+ throw FormatError("Cannot find map names");
+ return;
+ }
+ line.putback(c);
+
+ {
+ std::map<std::string, int> maps;
+
+ std::string map;
+ int index = 0;
+ while (_reader_bits::readToken(line, map)) {
+ if (maps.find(map) != maps.end()) {
+ std::ostringstream msg;
+ msg << "Multiple occurence of node map: " << map;
+ throw FormatError(msg.str());
+ }
+ maps.insert(std::make_pair(map, index));
+ ++index;
+ }
+
+ for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
+ std::map<std::string, int>::iterator jt =
+ maps.find(_node_maps[i].first);
+ if (jt == maps.end()) {
+ std::ostringstream msg;
+ msg << "Map not found: " << _node_maps[i].first;
+ throw FormatError(msg.str());
+ }
+ map_index[i] = jt->second;
+ }
+
+ {
+ std::map<std::string, int>::iterator jt = maps.find("label");
+ if (jt != maps.end()) {
+ label_index = jt->second;
+ } else {
+ label_index = -1;
+ }
+ }
+ map_num = maps.size();
+ }
+
+ while (readLine() && line >> c && c != '@') {
+ line.putback(c);
+
+ std::vector<std::string> tokens(map_num);
+ for (int i = 0; i < map_num; ++i) {
+ if (!_reader_bits::readToken(line, tokens[i])) {
+ std::ostringstream msg;
+ msg << "Column not found (" << i + 1 << ")";
+ throw FormatError(msg.str());
+ }
+ }
+ if (line >> std::ws >> c)
+ throw FormatError("Extra character at the end of line");
+
+ Node n;
+ if (!_use_nodes) {
+ n = _graph.addNode();
+ if (label_index != -1)
+ _node_index.insert(std::make_pair(tokens[label_index], n));
+ } else {
+ if (label_index == -1)
+ throw FormatError("Label map not found");
+ typename std::map<std::string, Node>::iterator it =
+ _node_index.find(tokens[label_index]);
+ if (it == _node_index.end()) {
+ std::ostringstream msg;
+ msg << "Node with label not found: " << tokens[label_index];
+ throw FormatError(msg.str());
+ }
+ n = it->second;
+ }
+
+ for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
+ _node_maps[i].second->set(n, tokens[map_index[i]]);
+ }
+
+ }
+ if (readSuccess()) {
+ line.putback(c);
+ }
+ }
+
+ void readEdges() {
+
+ std::vector<int> map_index(_edge_maps.size());
+ int map_num, label_index;
+
+ char c;
+ if (!readLine() || !(line >> c) || c == '@') {
+ if (readSuccess() && line) line.putback(c);
+ if (!_edge_maps.empty())
+ throw FormatError("Cannot find map names");
+ return;
+ }
+ line.putback(c);
+
+ {
+ std::map<std::string, int> maps;
+
+ std::string map;
+ int index = 0;
+ while (_reader_bits::readToken(line, map)) {
+ if(map == "-") {
+ if(index!=0)
+ throw FormatError("'-' is not allowed as a map name");
+ else if (line >> std::ws >> c)
+ throw FormatError("Extra character at the end of line");
+ else break;
+ }
+ if (maps.find(map) != maps.end()) {
+ std::ostringstream msg;
+ msg << "Multiple occurence of edge map: " << map;
+ throw FormatError(msg.str());
+ }
+ maps.insert(std::make_pair(map, index));
+ ++index;
+ }
+
+ for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
+ std::map<std::string, int>::iterator jt =
+ maps.find(_edge_maps[i].first);
+ if (jt == maps.end()) {
+ std::ostringstream msg;
+ msg << "Map not found: " << _edge_maps[i].first;
+ throw FormatError(msg.str());
+ }
+ map_index[i] = jt->second;
+ }
+
+ {
+ std::map<std::string, int>::iterator jt = maps.find("label");
+ if (jt != maps.end()) {
+ label_index = jt->second;
+ } else {
+ label_index = -1;
+ }
+ }
+ map_num = maps.size();
+ }
+
+ while (readLine() && line >> c && c != '@') {
+ line.putback(c);
+
+ std::string source_token;
+ std::string target_token;
+
+ if (!_reader_bits::readToken(line, source_token))
+ throw FormatError("Node u not found");
+
+ if (!_reader_bits::readToken(line, target_token))
+ throw FormatError("Node v not found");
+
+ std::vector<std::string> tokens(map_num);
+ for (int i = 0; i < map_num; ++i) {
+ if (!_reader_bits::readToken(line, tokens[i])) {
+ std::ostringstream msg;
+ msg << "Column not found (" << i + 1 << ")";
+ throw FormatError(msg.str());
+ }
+ }
+ if (line >> std::ws >> c)
+ throw FormatError("Extra character at the end of line");
+
+ Edge e;
+ if (!_use_edges) {
+
+ typename NodeIndex::iterator it;
+
+ it = _node_index.find(source_token);
+ if (it == _node_index.end()) {
+ std::ostringstream msg;
+ msg << "Item not found: " << source_token;
+ throw FormatError(msg.str());
+ }
+ Node source = it->second;
+
+ it = _node_index.find(target_token);
+ if (it == _node_index.end()) {
+ std::ostringstream msg;
+ msg << "Item not found: " << target_token;
+ throw FormatError(msg.str());
+ }
+ Node target = it->second;
+
+ e = _graph.addEdge(source, target);
+ if (label_index != -1)
+ _edge_index.insert(std::make_pair(tokens[label_index], e));
+ } else {
+ if (label_index == -1)
+ throw FormatError("Label map not found");
+ typename std::map<std::string, Edge>::iterator it =
+ _edge_index.find(tokens[label_index]);
+ if (it == _edge_index.end()) {
+ std::ostringstream msg;
+ msg << "Edge with label not found: " << tokens[label_index];
+ throw FormatError(msg.str());
+ }
+ e = it->second;
+ }
+
+ for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
+ _edge_maps[i].second->set(e, tokens[map_index[i]]);
+ }
+
+ }
+ if (readSuccess()) {
+ line.putback(c);
+ }
+ }
+
+ void readAttributes() {
+
+ std::set<std::string> read_attr;
+
+ char c;
+ while (readLine() && line >> c && c != '@') {
+ line.putback(c);
+
+ std::string attr, token;
+ if (!_reader_bits::readToken(line, attr))
+ throw FormatError("Attribute name not found");
+ if (!_reader_bits::readToken(line, token))
+ throw FormatError("Attribute value not found");
+ if (line >> c)
+ throw FormatError("Extra character at the end of line");
+
+ {
+ std::set<std::string>::iterator it = read_attr.find(attr);
+ if (it != read_attr.end()) {
+ std::ostringstream msg;
+ msg << "Multiple occurence of attribute: " << attr;
+ throw FormatError(msg.str());
+ }
+ read_attr.insert(attr);
+ }
+
+ {
+ typename Attributes::iterator it = _attributes.lower_bound(attr);
+ while (it != _attributes.end() && it->first == attr) {
+ it->second->set(token);
+ ++it;
+ }
+ }
+
+ }
+ if (readSuccess()) {
+ line.putback(c);
+ }
+ for (typename Attributes::iterator it = _attributes.begin();
+ it != _attributes.end(); ++it) {
+ if (read_attr.find(it->first) == read_attr.end()) {
+ std::ostringstream msg;
+ msg << "Attribute not found: " << it->first;
+ throw FormatError(msg.str());
+ }
+ }
+ }
+
+ public:
+
+ /// \name Execution of the Reader
+ /// @{
+
+ /// \brief Start the batch processing
+ ///
+ /// This function starts the batch processing
+ void run() {
+
+ LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
+
+ bool nodes_done = _skip_nodes;
+ bool edges_done = _skip_edges;
+ bool attributes_done = false;
+
+ line_num = 0;
+ readLine();
+ skipSection();
+
+ while (readSuccess()) {
+ try {
+ char c;
+ std::string section, caption;
+ line >> c;
+ _reader_bits::readToken(line, section);
+ _reader_bits::readToken(line, caption);
+
+ if (line >> c)
+ throw FormatError("Extra character at the end of line");
+
+ if (section == "nodes" && !nodes_done) {
+ if (_nodes_caption.empty() || _nodes_caption == caption) {
+ readNodes();
+ nodes_done = true;
+ }
+ } else if ((section == "edges" || section == "arcs") &&
+ !edges_done) {
+ if (_edges_caption.empty() || _edges_caption == caption) {
+ readEdges();
+ edges_done = true;
+ }
+ } else if (section == "attributes" && !attributes_done) {
+ if (_attributes_caption.empty() || _attributes_caption == caption) {
+ readAttributes();
+ attributes_done = true;
+ }
+ } else {
+ readLine();
+ skipSection();
+ }
+ } catch (FormatError& error) {
+ error.line(line_num);
+ error.file(_filename);
+ throw;
+ }
+ }
+
+ if (!nodes_done) {
+ throw FormatError("Section @nodes not found");
+ }
+
+ if (!edges_done) {
+ throw FormatError("Section @edges not found");
+ }
+
+ if (!attributes_done && !_attributes.empty()) {
+ throw FormatError("Section @attributes not found");
+ }
+
+ }
+
+ /// @}
+
+ };
+
+ /// \ingroup lemon_io
+ ///
+ /// \brief Return a \ref lemon::GraphReader "GraphReader" class
+ ///
+ /// This function just returns a \ref lemon::GraphReader "GraphReader" class.
+ ///
+ /// With this function a graph can be read from an
+ /// \ref lgf-format "LGF" file or input stream with several maps and
+ /// attributes. For example, there is weighted matching problem on a
+ /// graph, i.e. a graph with a \e weight map on the edges. This
+ /// graph can be read with the following code:
+ ///
+ ///\code
+ ///ListGraph graph;
+ ///ListGraph::EdgeMap<int> weight(graph);
+ ///graphReader(graph, std::cin).
+ /// edgeMap("weight", weight).
+ /// run();
+ ///\endcode
+ ///
+ /// For a complete documentation, please see the
+ /// \ref lemon::GraphReader "GraphReader"
+ /// class documentation.
+ /// \warning Don't forget to put the \ref lemon::GraphReader::run() "run()"
+ /// to the end of the parameter list.
+ /// \relates GraphReader
+ /// \sa graphReader(TGR& graph, const std::string& fn)
+ /// \sa graphReader(TGR& graph, const char* fn)
+ template <typename TGR>
+ GraphReader<TGR> graphReader(TGR& graph, std::istream& is) {
+ GraphReader<TGR> tmp(graph, is);
+ return tmp;
+ }
+
+ /// \brief Return a \ref GraphReader class
+ ///
+ /// This function just returns a \ref GraphReader class.
+ /// \relates GraphReader
+ /// \sa graphReader(TGR& graph, std::istream& is)
+ template <typename TGR>
+ GraphReader<TGR> graphReader(TGR& graph, const std::string& fn) {
+ GraphReader<TGR> tmp(graph, fn);
+ return tmp;
+ }
+
+ /// \brief Return a \ref GraphReader class
+ ///
+ /// This function just returns a \ref GraphReader class.
+ /// \relates GraphReader
+ /// \sa graphReader(TGR& graph, std::istream& is)
+ template <typename TGR>
+ GraphReader<TGR> graphReader(TGR& graph, const char* fn) {
+ GraphReader<TGR> tmp(graph, fn);
+ return tmp;
+ }
+
+ template <typename BGR>
+ class BpGraphReader;
+
+ template <typename TBGR>
+ BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is = std::cin);
+ template <typename TBGR>
+ BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const std::string& fn);
+ template <typename TBGR>
+ BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char *fn);
+
+ /// \ingroup lemon_io
+ ///
+ /// \brief \ref lgf-format "LGF" reader for bipartite graphs
+ ///
+ /// This utility reads an \ref lgf-format "LGF" file.
+ ///
+ /// It can be used almost the same way as \c GraphReader, but it
+ /// reads the red and blue nodes from separate sections, and these
+ /// sections can contain different set of maps.
+ ///
+ /// The red and blue node maps are read from the corresponding
+ /// sections. If a map is defined with the same name in both of
+ /// these sections, then it can be read as a node map.
+ template <typename BGR>
+ class BpGraphReader {
+ public:
+
+ typedef BGR Graph;
+
+ private:
+
+ TEMPLATE_BPGRAPH_TYPEDEFS(BGR);
+
+ std::istream* _is;
+ bool local_is;
+ std::string _filename;
+
+ BGR& _graph;
+
+ std::string _nodes_caption;
+ std::string _edges_caption;
+ std::string _attributes_caption;
+
+ typedef std::map<std::string, RedNode> RedNodeIndex;
+ RedNodeIndex _red_node_index;
+ typedef std::map<std::string, BlueNode> BlueNodeIndex;
+ BlueNodeIndex _blue_node_index;
+ typedef std::map<std::string, Edge> EdgeIndex;
+ EdgeIndex _edge_index;
+
+ typedef std::vector<std::pair<std::string,
+ _reader_bits::MapStorageBase<RedNode>*> > RedNodeMaps;
+ RedNodeMaps _red_node_maps;
+ typedef std::vector<std::pair<std::string,
+ _reader_bits::MapStorageBase<BlueNode>*> > BlueNodeMaps;
+ BlueNodeMaps _blue_node_maps;
+
+ typedef std::vector<std::pair<std::string,
+ _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
+ EdgeMaps _edge_maps;
+
+ typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
+ Attributes;
+ Attributes _attributes;
+
+ bool _use_nodes;
+ bool _use_edges;
+
+ bool _skip_nodes;
+ bool _skip_edges;
+
+ int line_num;
+ std::istringstream line;
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Construct an undirected graph reader, which reads from the given
+ /// input stream.
+ BpGraphReader(BGR& graph, std::istream& is = std::cin)
+ : _is(&is), local_is(false), _graph(graph),
+ _use_nodes(false), _use_edges(false),
+ _skip_nodes(false), _skip_edges(false) {}
+
+ /// \brief Constructor
+ ///
+ /// Construct an undirected graph reader, which reads from the given
+ /// file.
+ BpGraphReader(BGR& graph, const std::string& fn)
+ : _is(new std::ifstream(fn.c_str())), local_is(true),
+ _filename(fn), _graph(graph),
+ _use_nodes(false), _use_edges(false),
+ _skip_nodes(false), _skip_edges(false) {
+ if (!(*_is)) {
+ delete _is;
+ throw IoError("Cannot open file", fn);
+ }
+ }
+
+ /// \brief Constructor
+ ///
+ /// Construct an undirected graph reader, which reads from the given
+ /// file.
+ BpGraphReader(BGR& graph, const char* fn)
+ : _is(new std::ifstream(fn)), local_is(true),
+ _filename(fn), _graph(graph),
+ _use_nodes(false), _use_edges(false),
+ _skip_nodes(false), _skip_edges(false) {
+ if (!(*_is)) {
+ delete _is;
+ throw IoError("Cannot open file", fn);
+ }
+ }
+
+ /// \brief Destructor
+ ~BpGraphReader() {
+ for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
+ it != _red_node_maps.end(); ++it) {
+ delete it->second;
+ }
+
+ for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
+ it != _blue_node_maps.end(); ++it) {
+ delete it->second;
+ }
+
+ for (typename EdgeMaps::iterator it = _edge_maps.begin();
+ it != _edge_maps.end(); ++it) {
+ delete it->second;
+ }
+
+ for (typename Attributes::iterator it = _attributes.begin();
+ it != _attributes.end(); ++it) {
+ delete it->second;
+ }
+
+ if (local_is) {
+ delete _is;
+ }
+
+ }
+
+ private:
+ template <typename TBGR>
+ friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is);
+ template <typename TBGR>
+ friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph,
+ const std::string& fn);
+ template <typename TBGR>
+ friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char *fn);
+
+ BpGraphReader(BpGraphReader& other)
+ : _is(other._is), local_is(other.local_is), _graph(other._graph),
+ _use_nodes(other._use_nodes), _use_edges(other._use_edges),
+ _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
+
+ other._is = 0;
+ other.local_is = false;
+
+ _red_node_index.swap(other._red_node_index);
+ _blue_node_index.swap(other._blue_node_index);
+ _edge_index.swap(other._edge_index);
+
+ _red_node_maps.swap(other._red_node_maps);
+ _blue_node_maps.swap(other._blue_node_maps);
+ _edge_maps.swap(other._edge_maps);
+ _attributes.swap(other._attributes);
+
+ _nodes_caption = other._nodes_caption;
+ _edges_caption = other._edges_caption;
+ _attributes_caption = other._attributes_caption;
+
+ }
+
+ BpGraphReader& operator=(const BpGraphReader&);
+
+ public:
+
+ /// \name Reading Rules
+ /// @{
+
+ /// \brief Node map reading rule
+ ///
+ /// Add a node map reading rule to the reader.
+ template <typename Map>
+ BpGraphReader& nodeMap(const std::string& caption, Map& map) {
+ checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<RedNode>* red_storage =
+ new _reader_bits::MapStorage<RedNode, Map>(map);
+ _red_node_maps.push_back(std::make_pair(caption, red_storage));
+ _reader_bits::MapStorageBase<BlueNode>* blue_storage =
+ new _reader_bits::MapStorage<BlueNode, Map>(map);
+ _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
+ return *this;
+ }
+
+ /// \brief Node map reading rule
+ ///
+ /// Add a node map reading rule with specialized converter to the
+ /// reader.
+ template <typename Map, typename Converter>
+ BpGraphReader& nodeMap(const std::string& caption, Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<RedNode>* red_storage =
+ new _reader_bits::MapStorage<RedNode, Map, Converter>(map, converter);
+ _red_node_maps.push_back(std::make_pair(caption, red_storage));
+ _reader_bits::MapStorageBase<BlueNode>* blue_storage =
+ new _reader_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
+ _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
+ return *this;
+ }
+
+ /// Add a red node map reading rule to the reader.
+ template <typename Map>
+ BpGraphReader& redNodeMap(const std::string& caption, Map& map) {
+ checkConcept<concepts::WriteMap<RedNode, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<RedNode>* storage =
+ new _reader_bits::MapStorage<RedNode, Map>(map);
+ _red_node_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Red node map reading rule
+ ///
+ /// Add a red node map node reading rule with specialized converter to
+ /// the reader.
+ template <typename Map, typename Converter>
+ BpGraphReader& redNodeMap(const std::string& caption, Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::WriteMap<RedNode, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<RedNode>* storage =
+ new _reader_bits::MapStorage<RedNode, Map, Converter>(map, converter);
+ _red_node_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// Add a blue node map reading rule to the reader.
+ template <typename Map>
+ BpGraphReader& blueNodeMap(const std::string& caption, Map& map) {
+ checkConcept<concepts::WriteMap<BlueNode, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<BlueNode>* storage =
+ new _reader_bits::MapStorage<BlueNode, Map>(map);
+ _blue_node_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Blue node map reading rule
+ ///
+ /// Add a blue node map reading rule with specialized converter to
+ /// the reader.
+ template <typename Map, typename Converter>
+ BpGraphReader& blueNodeMap(const std::string& caption, Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::WriteMap<BlueNode, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<BlueNode>* storage =
+ new _reader_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
+ _blue_node_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Edge map reading rule
+ ///
+ /// Add an edge map reading rule to the reader.
+ template <typename Map>
+ BpGraphReader& edgeMap(const std::string& caption, Map& map) {
+ checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<Edge>* storage =
+ new _reader_bits::MapStorage<Edge, Map>(map);
+ _edge_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Edge map reading rule
+ ///
+ /// Add an edge map reading rule with specialized converter to the
+ /// reader.
+ template <typename Map, typename Converter>
+ BpGraphReader& edgeMap(const std::string& caption, Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<Edge>* storage =
+ new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
+ _edge_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Arc map reading rule
+ ///
+ /// Add an arc map reading rule to the reader.
+ template <typename Map>
+ BpGraphReader& arcMap(const std::string& caption, Map& map) {
+ checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<Edge>* forward_storage =
+ new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
+ _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
+ _reader_bits::MapStorageBase<Edge>* backward_storage =
+ new _reader_bits::GraphArcMapStorage<BGR, false, Map>(_graph, map);
+ _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
+ return *this;
+ }
+
+ /// \brief Arc map reading rule
+ ///
+ /// Add an arc map reading rule with specialized converter to the
+ /// reader.
+ template <typename Map, typename Converter>
+ BpGraphReader& arcMap(const std::string& caption, Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
+ _reader_bits::MapStorageBase<Edge>* forward_storage =
+ new _reader_bits::GraphArcMapStorage<BGR, true, Map, Converter>
+ (_graph, map, converter);
+ _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
+ _reader_bits::MapStorageBase<Edge>* backward_storage =
+ new _reader_bits::GraphArcMapStorage<BGR, false, Map, Converter>
+ (_graph, map, converter);
+ _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
+ return *this;
+ }
+
+ /// \brief Attribute reading rule
+ ///
+ /// Add an attribute reading rule to the reader.
+ template <typename Value>
+ BpGraphReader& attribute(const std::string& caption, Value& value) {
+ _reader_bits::ValueStorageBase* storage =
+ new _reader_bits::ValueStorage<Value>(value);
+ _attributes.insert(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Attribute reading rule
+ ///
+ /// Add an attribute reading rule with specialized converter to the
+ /// reader.
+ template <typename Value, typename Converter>
+ BpGraphReader& attribute(const std::string& caption, Value& value,
+ const Converter& converter = Converter()) {
+ _reader_bits::ValueStorageBase* storage =
+ new _reader_bits::ValueStorage<Value, Converter>(value, converter);
+ _attributes.insert(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Node reading rule
+ ///
+ /// Add a node reading rule to reader.
+ BpGraphReader& node(const std::string& caption, Node& node) {
+ typedef _reader_bits::DoubleMapLookUpConverter<
+ Node, RedNodeIndex, BlueNodeIndex> Converter;
+ Converter converter(_red_node_index, _blue_node_index);
+ _reader_bits::ValueStorageBase* storage =
+ new _reader_bits::ValueStorage<Node, Converter>(node, converter);
+ _attributes.insert(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Red node reading rule
+ ///
+ /// Add a red node reading rule to reader.
+ BpGraphReader& redNode(const std::string& caption, RedNode& node) {
+ typedef _reader_bits::MapLookUpConverter<RedNode> Converter;
+ Converter converter(_red_node_index);
+ _reader_bits::ValueStorageBase* storage =
+ new _reader_bits::ValueStorage<RedNode, Converter>(node, converter);
+ _attributes.insert(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Blue node reading rule
+ ///
+ /// Add a blue node reading rule to reader.
+ BpGraphReader& blueNode(const std::string& caption, BlueNode& node) {
+ typedef _reader_bits::MapLookUpConverter<BlueNode> Converter;
+ Converter converter(_blue_node_index);
+ _reader_bits::ValueStorageBase* storage =
+ new _reader_bits::ValueStorage<BlueNode, Converter>(node, converter);
+ _attributes.insert(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Edge reading rule
+ ///
+ /// Add an edge reading rule to reader.
+ BpGraphReader& edge(const std::string& caption, Edge& edge) {
+ typedef _reader_bits::MapLookUpConverter<Edge> Converter;
+ Converter converter(_edge_index);
+ _reader_bits::ValueStorageBase* storage =
+ new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
+ _attributes.insert(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Arc reading rule
+ ///
+ /// Add an arc reading rule to reader.
+ BpGraphReader& arc(const std::string& caption, Arc& arc) {
+ typedef _reader_bits::GraphArcLookUpConverter<BGR> Converter;
+ Converter converter(_graph, _edge_index);
+ _reader_bits::ValueStorageBase* storage =
+ new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
+ _attributes.insert(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// @}
+
+ /// \name Select Section by Name
+ /// @{
+
+ /// \brief Set \c \@nodes section to be read
+ ///
+ /// Set \c \@nodes section to be read.
+ BpGraphReader& nodes(const std::string& caption) {
+ _nodes_caption = caption;
+ return *this;
+ }
+
+ /// \brief Set \c \@edges section to be read
+ ///
+ /// Set \c \@edges section to be read.
+ BpGraphReader& edges(const std::string& caption) {
+ _edges_caption = caption;
+ return *this;
+ }
+
+ /// \brief Set \c \@attributes section to be read
+ ///
+ /// Set \c \@attributes section to be read.
+ BpGraphReader& attributes(const std::string& caption) {
+ _attributes_caption = caption;
+ return *this;
+ }
+
+ /// @}
+
+ /// \name Using Previously Constructed Node or Edge Set
+ /// @{
+
+ /// \brief Use previously constructed node set
+ ///
+ /// Use previously constructed node set, and specify the node
+ /// label map.
+ template <typename Map>
+ BpGraphReader& useNodes(const Map& map) {
+ checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
+ LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
+ _use_nodes = true;
+ _writer_bits::DefaultConverter<typename Map::Value> converter;
+ for (RedNodeIt n(_graph); n != INVALID; ++n) {
+ _red_node_index.insert(std::make_pair(converter(map[n]), n));
+ }
+ for (BlueNodeIt n(_graph); n != INVALID; ++n) {
+ _blue_node_index.insert(std::make_pair(converter(map[n]), n));
+ }
+ return *this;
+ }
+
+ /// \brief Use previously constructed node set
+ ///
+ /// Use previously constructed node set, and specify the node
+ /// label map and a functor which converts the label map values to
+ /// \c std::string.
+ template <typename Map, typename Converter>
+ BpGraphReader& useNodes(const Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
+ LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
+ _use_nodes = true;
+ for (RedNodeIt n(_graph); n != INVALID; ++n) {
+ _red_node_index.insert(std::make_pair(converter(map[n]), n));
+ }
+ for (BlueNodeIt n(_graph); n != INVALID; ++n) {
+ _blue_node_index.insert(std::make_pair(converter(map[n]), n));
+ }
+ return *this;
+ }
+
+ /// \brief Use previously constructed edge set
+ ///
+ /// Use previously constructed edge set, and specify the edge
+ /// label map.
+ template <typename Map>
+ BpGraphReader& useEdges(const Map& map) {
+ checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
+ LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
+ _use_edges = true;
+ _writer_bits::DefaultConverter<typename Map::Value> converter;
+ for (EdgeIt a(_graph); a != INVALID; ++a) {
+ _edge_index.insert(std::make_pair(converter(map[a]), a));
+ }
+ return *this;
+ }
+
+ /// \brief Use previously constructed edge set
+ ///
+ /// Use previously constructed edge set, and specify the edge
+ /// label map and a functor which converts the label map values to
+ /// \c std::string.
+ template <typename Map, typename Converter>
+ BpGraphReader& useEdges(const Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
+ LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
+ _use_edges = true;
+ for (EdgeIt a(_graph); a != INVALID; ++a) {
+ _edge_index.insert(std::make_pair(converter(map[a]), a));
+ }
+ return *this;
+ }
+
+ /// \brief Skip the reading of node section
+ ///
+ /// Omit the reading of the node section. This implies that each node
+ /// map reading rule will be abandoned, and the nodes of the graph
+ /// will not be constructed, which usually cause that the edge set
+ /// could not be read due to lack of node name
+ /// could not be read due to lack of node name resolving.
+ /// Therefore \c skipEdges() function should also be used, or
+ /// \c useNodes() should be used to specify the label of the nodes.
+ BpGraphReader& skipNodes() {
+ LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
+ _skip_nodes = true;
+ return *this;
+ }
+
+ /// \brief Skip the reading of edge section
+ ///
+ /// Omit the reading of the edge section. This implies that each edge
+ /// map reading rule will be abandoned, and the edges of the graph
+ /// will not be constructed.
+ BpGraphReader& skipEdges() {
+ LEMON_ASSERT(!_skip_edges, "Skip edges already set");
+ _skip_edges = true;
+ return *this;
+ }
+
+ /// @}
+
+ private:
+
+ bool readLine() {
+ std::string str;
+ while(++line_num, std::getline(*_is, str)) {
+ line.clear(); line.str(str);
+ char c;
+ if (line >> std::ws >> c && c != '#') {
+ line.putback(c);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool readSuccess() {
+ return static_cast<bool>(*_is);
+ }
+
+ void skipSection() {
+ char c;
+ while (readSuccess() && line >> c && c != '@') {
+ readLine();
+ }
+ if (readSuccess()) {
+ line.putback(c);
+ }
+ }
+
+ void readRedNodes() {
+
+ std::vector<int> map_index(_red_node_maps.size());
+ int map_num, label_index;
+
+ char c;
+ if (!readLine() || !(line >> c) || c == '@') {
+ if (readSuccess() && line) line.putback(c);
+ if (!_red_node_maps.empty())
+ throw FormatError("Cannot find map names");
+ return;
+ }
+ line.putback(c);
+
+ {
+ std::map<std::string, int> maps;
+
+ std::string map;
+ int index = 0;
+ while (_reader_bits::readToken(line, map)) {
+ if (maps.find(map) != maps.end()) {
+ std::ostringstream msg;
+ msg << "Multiple occurence of red node map: " << map;
+ throw FormatError(msg.str());
+ }
+ maps.insert(std::make_pair(map, index));
+ ++index;
+ }
+
+ for (int i = 0; i < static_cast<int>(_red_node_maps.size()); ++i) {
+ std::map<std::string, int>::iterator jt =
+ maps.find(_red_node_maps[i].first);
+ if (jt == maps.end()) {
+ std::ostringstream msg;
+ msg << "Map not found: " << _red_node_maps[i].first;
+ throw FormatError(msg.str());
+ }
+ map_index[i] = jt->second;
+ }
+
+ {
+ std::map<std::string, int>::iterator jt = maps.find("label");
+ if (jt != maps.end()) {
+ label_index = jt->second;
+ } else {
+ label_index = -1;
+ }
+ }
+ map_num = maps.size();
+ }
+
+ while (readLine() && line >> c && c != '@') {
+ line.putback(c);
+
+ std::vector<std::string> tokens(map_num);
+ for (int i = 0; i < map_num; ++i) {
+ if (!_reader_bits::readToken(line, tokens[i])) {
+ std::ostringstream msg;
+ msg << "Column not found (" << i + 1 << ")";
+ throw FormatError(msg.str());
+ }
+ }
+ if (line >> std::ws >> c)
+ throw FormatError("Extra character at the end of line");
+
+ RedNode n;
+ if (!_use_nodes) {
+ n = _graph.addRedNode();
+ if (label_index != -1)
+ _red_node_index.insert(std::make_pair(tokens[label_index], n));
+ } else {
+ if (label_index == -1)
+ throw FormatError("Label map not found");
+ typename std::map<std::string, RedNode>::iterator it =
+ _red_node_index.find(tokens[label_index]);
+ if (it == _red_node_index.end()) {
+ std::ostringstream msg;
+ msg << "Node with label not found: " << tokens[label_index];
+ throw FormatError(msg.str());
+ }
+ n = it->second;
+ }
+
+ for (int i = 0; i < static_cast<int>(_red_node_maps.size()); ++i) {
+ _red_node_maps[i].second->set(n, tokens[map_index[i]]);
+ }
+
+ }
+ if (readSuccess()) {
+ line.putback(c);
+ }
+ }
+
+ void readBlueNodes() {
+
+ std::vector<int> map_index(_blue_node_maps.size());
+ int map_num, label_index;
+
+ char c;
+ if (!readLine() || !(line >> c) || c == '@') {
+ if (readSuccess() && line) line.putback(c);
+ if (!_blue_node_maps.empty())
+ throw FormatError("Cannot find map names");
+ return;
+ }
+ line.putback(c);
+
+ {
+ std::map<std::string, int> maps;
+
+ std::string map;
+ int index = 0;
+ while (_reader_bits::readToken(line, map)) {
+ if (maps.find(map) != maps.end()) {
+ std::ostringstream msg;
+ msg << "Multiple occurence of blue node map: " << map;
+ throw FormatError(msg.str());
+ }
+ maps.insert(std::make_pair(map, index));
+ ++index;
+ }
+
+ for (int i = 0; i < static_cast<int>(_blue_node_maps.size()); ++i) {
+ std::map<std::string, int>::iterator jt =
+ maps.find(_blue_node_maps[i].first);
+ if (jt == maps.end()) {
+ std::ostringstream msg;
+ msg << "Map not found: " << _blue_node_maps[i].first;
+ throw FormatError(msg.str());
+ }
+ map_index[i] = jt->second;
+ }
+
+ {
+ std::map<std::string, int>::iterator jt = maps.find("label");
+ if (jt != maps.end()) {
+ label_index = jt->second;
+ } else {
+ label_index = -1;
+ }
+ }
+ map_num = maps.size();
+ }
+
+ while (readLine() && line >> c && c != '@') {
+ line.putback(c);
+
+ std::vector<std::string> tokens(map_num);
+ for (int i = 0; i < map_num; ++i) {
+ if (!_reader_bits::readToken(line, tokens[i])) {
+ std::ostringstream msg;
+ msg << "Column not found (" << i + 1 << ")";
+ throw FormatError(msg.str());
+ }
+ }
+ if (line >> std::ws >> c)
+ throw FormatError("Extra character at the end of line");
+
+ BlueNode n;
+ if (!_use_nodes) {
+ n = _graph.addBlueNode();
+ if (label_index != -1)
+ _blue_node_index.insert(std::make_pair(tokens[label_index], n));
+ } else {
+ if (label_index == -1)
+ throw FormatError("Label map not found");
+ typename std::map<std::string, BlueNode>::iterator it =
+ _blue_node_index.find(tokens[label_index]);
+ if (it == _blue_node_index.end()) {
+ std::ostringstream msg;
+ msg << "Node with label not found: " << tokens[label_index];
+ throw FormatError(msg.str());
+ }
+ n = it->second;
+ }
+
+ for (int i = 0; i < static_cast<int>(_blue_node_maps.size()); ++i) {
+ _blue_node_maps[i].second->set(n, tokens[map_index[i]]);
+ }
+
+ }
+ if (readSuccess()) {
+ line.putback(c);
+ }
+ }
+
+ void readEdges() {
+
+ std::vector<int> map_index(_edge_maps.size());
+ int map_num, label_index;
+
+ char c;
+ if (!readLine() || !(line >> c) || c == '@') {
+ if (readSuccess() && line) line.putback(c);
+ if (!_edge_maps.empty())
+ throw FormatError("Cannot find map names");
+ return;
+ }
+ line.putback(c);
+
+ {
+ std::map<std::string, int> maps;
+
+ std::string map;
+ int index = 0;
+ while (_reader_bits::readToken(line, map)) {
+ if (maps.find(map) != maps.end()) {
+ std::ostringstream msg;
+ msg << "Multiple occurence of edge map: " << map;
+ throw FormatError(msg.str());
+ }
+ maps.insert(std::make_pair(map, index));
+ ++index;
+ }
+
+ for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
+ std::map<std::string, int>::iterator jt =
+ maps.find(_edge_maps[i].first);
+ if (jt == maps.end()) {
+ std::ostringstream msg;
+ msg << "Map not found: " << _edge_maps[i].first;
+ throw FormatError(msg.str());
+ }
+ map_index[i] = jt->second;
+ }
+
+ {
+ std::map<std::string, int>::iterator jt = maps.find("label");
+ if (jt != maps.end()) {
+ label_index = jt->second;
+ } else {
+ label_index = -1;
+ }
+ }
+ map_num = maps.size();
+ }
+
+ while (readLine() && line >> c && c != '@') {
+ line.putback(c);
+
+ std::string source_token;
+ std::string target_token;
+
+ if (!_reader_bits::readToken(line, source_token))
+ throw FormatError("Red node not found");
+
+ if (!_reader_bits::readToken(line, target_token))
+ throw FormatError("Blue node not found");
+
+ std::vector<std::string> tokens(map_num);
+ for (int i = 0; i < map_num; ++i) {
+ if (!_reader_bits::readToken(line, tokens[i])) {
+ std::ostringstream msg;
+ msg << "Column not found (" << i + 1 << ")";
+ throw FormatError(msg.str());
+ }
+ }
+ if (line >> std::ws >> c)
+ throw FormatError("Extra character at the end of line");
+
+ Edge e;
+ if (!_use_edges) {
+ typename RedNodeIndex::iterator rit =
+ _red_node_index.find(source_token);
+ if (rit == _red_node_index.end()) {
+ std::ostringstream msg;
+ msg << "Item not found: " << source_token;
+ throw FormatError(msg.str());
+ }
+ RedNode source = rit->second;
+ typename BlueNodeIndex::iterator it =
+ _blue_node_index.find(target_token);
+ if (it == _blue_node_index.end()) {
+ std::ostringstream msg;
+ msg << "Item not found: " << target_token;
+ throw FormatError(msg.str());
+ }
+ BlueNode target = it->second;
+
+ // It is checked that source is red and
+ // target is blue, so this should be safe:
+ e = _graph.addEdge(source, target);
+ if (label_index != -1)
+ _edge_index.insert(std::make_pair(tokens[label_index], e));
+ } else {
+ if (label_index == -1)
+ throw FormatError("Label map not found");
+ typename std::map<std::string, Edge>::iterator it =
+ _edge_index.find(tokens[label_index]);
+ if (it == _edge_index.end()) {
+ std::ostringstream msg;
+ msg << "Edge with label not found: " << tokens[label_index];
+ throw FormatError(msg.str());
+ }
+ e = it->second;
+ }
+
+ for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
+ _edge_maps[i].second->set(e, tokens[map_index[i]]);
+ }
+
+ }
+ if (readSuccess()) {
+ line.putback(c);
+ }
+ }
+
+ void readAttributes() {
+
+ std::set<std::string> read_attr;
+
+ char c;
+ while (readLine() && line >> c && c != '@') {
+ line.putback(c);
+
+ std::string attr, token;
+ if (!_reader_bits::readToken(line, attr))
+ throw FormatError("Attribute name not found");
+ if (!_reader_bits::readToken(line, token))
+ throw FormatError("Attribute value not found");
+ if (line >> c)
+ throw FormatError("Extra character at the end of line");
+
+ {
+ std::set<std::string>::iterator it = read_attr.find(attr);
+ if (it != read_attr.end()) {
+ std::ostringstream msg;
+ msg << "Multiple occurence of attribute: " << attr;
+ throw FormatError(msg.str());
+ }
+ read_attr.insert(attr);
+ }
+
+ {
+ typename Attributes::iterator it = _attributes.lower_bound(attr);
+ while (it != _attributes.end() && it->first == attr) {
+ it->second->set(token);
+ ++it;
+ }
+ }
+
+ }
+ if (readSuccess()) {
+ line.putback(c);
+ }
+ for (typename Attributes::iterator it = _attributes.begin();
+ it != _attributes.end(); ++it) {
+ if (read_attr.find(it->first) == read_attr.end()) {
+ std::ostringstream msg;
+ msg << "Attribute not found: " << it->first;
+ throw FormatError(msg.str());
+ }
+ }
+ }
+
+ public:
+
+ /// \name Execution of the Reader
+ /// @{
+
+ /// \brief Start the batch processing
+ ///
+ /// This function starts the batch processing
+ void run() {
+
+ LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
+
+ bool red_nodes_done = _skip_nodes;
+ bool blue_nodes_done = _skip_nodes;
+ bool edges_done = _skip_edges;
+ bool attributes_done = false;
+
+ line_num = 0;
+ readLine();
+ skipSection();
+
+ while (readSuccess()) {
+ try {
+ char c;
+ std::string section, caption;
+ line >> c;
+ _reader_bits::readToken(line, section);
+ _reader_bits::readToken(line, caption);
+
+ if (line >> c)
+ throw FormatError("Extra character at the end of line");
+
+ if (section == "red_nodes" && !red_nodes_done) {
+ if (_nodes_caption.empty() || _nodes_caption == caption) {
+ readRedNodes();
+ red_nodes_done = true;
+ }
+ } else if (section == "blue_nodes" && !blue_nodes_done) {
+ if (_nodes_caption.empty() || _nodes_caption == caption) {
+ readBlueNodes();
+ blue_nodes_done = true;
+ }
+ } else if ((section == "edges" || section == "arcs") &&
+ !edges_done) {
+ if (_edges_caption.empty() || _edges_caption == caption) {
+ readEdges();
+ edges_done = true;
+ }
+ } else if (section == "attributes" && !attributes_done) {
+ if (_attributes_caption.empty() || _attributes_caption == caption) {
+ readAttributes();
+ attributes_done = true;
+ }
+ } else {
+ readLine();
+ skipSection();
+ }
+ } catch (FormatError& error) {
+ error.line(line_num);
+ error.file(_filename);
+ throw;
+ }
+ }
+
+ if (!red_nodes_done) {
+ throw FormatError("Section @red_nodes not found");
+ }
+
+ if (!blue_nodes_done) {
+ throw FormatError("Section @blue_nodes not found");
+ }
+
+ if (!edges_done) {
+ throw FormatError("Section @edges not found");
+ }
+
+ if (!attributes_done && !_attributes.empty()) {
+ throw FormatError("Section @attributes not found");
+ }
+
+ }
+
+ /// @}
+
+ };
+
+ /// \ingroup lemon_io
+ ///
+ /// \brief Return a \ref lemon::BpGraphReader "BpGraphReader" class
+ ///
+ /// This function just returns a \ref lemon::BpGraphReader
+ /// "BpGraphReader" class.
+ ///
+ /// With this function a graph can be read from an
+ /// \ref lgf-format "LGF" file or input stream with several maps and
+ /// attributes. For example, there is bipartite weighted matching problem
+ /// on a graph, i.e. a graph with a \e weight map on the edges. This
+ /// graph can be read with the following code:
+ ///
+ ///\code
+ ///ListBpGraph graph;
+ ///ListBpGraph::EdgeMap<int> weight(graph);
+ ///bpGraphReader(graph, std::cin).
+ /// edgeMap("weight", weight).
+ /// run();
+ ///\endcode
+ ///
+ /// For a complete documentation, please see the
+ /// \ref lemon::BpGraphReader "BpGraphReader"
+ /// class documentation.
+ /// \warning Don't forget to put the \ref lemon::BpGraphReader::run() "run()"
+ /// to the end of the parameter list.
+ /// \relates BpGraphReader
+ /// \sa bpGraphReader(TBGR& graph, const std::string& fn)
+ /// \sa bpGraphReader(TBGR& graph, const char* fn)
+ template <typename TBGR>
+ BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is) {
+ BpGraphReader<TBGR> tmp(graph, is);
+ return tmp;
+ }
+
+ /// \brief Return a \ref BpGraphReader class
+ ///
+ /// This function just returns a \ref BpGraphReader class.
+ /// \relates BpGraphReader
+ /// \sa bpGraphReader(TBGR& graph, std::istream& is)
+ template <typename TBGR>
+ BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const std::string& fn) {
+ BpGraphReader<TBGR> tmp(graph, fn);
+ return tmp;
+ }
+
+ /// \brief Return a \ref BpGraphReader class
+ ///
+ /// This function just returns a \ref BpGraphReader class.
+ /// \relates BpGraphReader
+ /// \sa bpGraphReader(TBGR& graph, std::istream& is)
+ template <typename TBGR>
+ BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char* fn) {
+ BpGraphReader<TBGR> tmp(graph, fn);
+ return tmp;
+ }
+
+ class SectionReader;
+
+ SectionReader sectionReader(std::istream& is);
+ SectionReader sectionReader(const std::string& fn);
+ SectionReader sectionReader(const char* fn);
+
+ /// \ingroup lemon_io
+ ///
+ /// \brief Section reader class
+ ///
+ /// In the \ref lgf-format "LGF" file extra sections can be placed,
+ /// which contain any data in arbitrary format. Such sections can be
+ /// read with this class. A reading rule can be added to the class
+ /// with two different functions. With the \c sectionLines() function a
+ /// functor can process the section line-by-line, while with the \c
+ /// sectionStream() member the section can be read from an input
+ /// stream.
+ class SectionReader {
+ private:
+
+ std::istream* _is;
+ bool local_is;
+ std::string _filename;
+
+ typedef std::map<std::string, _reader_bits::Section*> Sections;
+ Sections _sections;
+
+ int line_num;
+ std::istringstream line;
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Construct a section reader, which reads from the given input
+ /// stream.
+ SectionReader(std::istream& is)
+ : _is(&is), local_is(false) {}
+
+ /// \brief Constructor
+ ///
+ /// Construct a section reader, which reads from the given file.
+ SectionReader(const std::string& fn)
+ : _is(new std::ifstream(fn.c_str())), local_is(true),
+ _filename(fn) {
+ if (!(*_is)) {
+ delete _is;
+ throw IoError("Cannot open file", fn);
+ }
+ }
+
+ /// \brief Constructor
+ ///
+ /// Construct a section reader, which reads from the given file.
+ SectionReader(const char* fn)
+ : _is(new std::ifstream(fn)), local_is(true),
+ _filename(fn) {
+ if (!(*_is)) {
+ delete _is;
+ throw IoError("Cannot open file", fn);
+ }
+ }
+
+ /// \brief Destructor
+ ~SectionReader() {
+ for (Sections::iterator it = _sections.begin();
+ it != _sections.end(); ++it) {
+ delete it->second;
+ }
+
+ if (local_is) {
+ delete _is;
+ }
+
+ }
+
+ private:
+
+ friend SectionReader sectionReader(std::istream& is);
+ friend SectionReader sectionReader(const std::string& fn);
+ friend SectionReader sectionReader(const char* fn);
+
+ SectionReader(SectionReader& other)
+ : _is(other._is), local_is(other.local_is) {
+
+ other._is = 0;
+ other.local_is = false;
+
+ _sections.swap(other._sections);
+ }
+
+ SectionReader& operator=(const SectionReader&);
+
+ public:
+
+ /// \name Section Readers
+ /// @{
+
+ /// \brief Add a section processor with line oriented reading
+ ///
+ /// The first parameter is the type descriptor of the section, the
+ /// second is a functor, which takes just one \c std::string
+ /// parameter. At the reading process, each line of the section
+ /// will be given to the functor object. However, the empty lines
+ /// and the comment lines are filtered out, and the leading
+ /// whitespaces are trimmed from each processed string.
+ ///
+ /// For example, let's see a section, which contain several
+ /// integers, which should be inserted into a vector.
+ ///\code
+ /// @numbers
+ /// 12 45 23
+ /// 4
+ /// 23 6
+ ///\endcode
+ ///
+ /// The functor is implemented as a struct:
+ ///\code
+ /// struct NumberSection {
+ /// std::vector<int>& _data;
+ /// NumberSection(std::vector<int>& data) : _data(data) {}
+ /// void operator()(const std::string& line) {
+ /// std::istringstream ls(line);
+ /// int value;
+ /// while (ls >> value) _data.push_back(value);
+ /// }
+ /// };
+ ///
+ /// // ...
+ ///
+ /// reader.sectionLines("numbers", NumberSection(vec));
+ ///\endcode
+ template <typename Functor>
+ SectionReader& sectionLines(const std::string& type, Functor functor) {
+ LEMON_ASSERT(!type.empty(), "Type is empty.");
+ LEMON_ASSERT(_sections.find(type) == _sections.end(),
+ "Multiple reading of section.");
+ _sections.insert(std::make_pair(type,
+ new _reader_bits::LineSection<Functor>(functor)));
+ return *this;
+ }
+
+
+ /// \brief Add a section processor with stream oriented reading
+ ///
+ /// The first parameter is the type of the section, the second is
+ /// a functor, which takes an \c std::istream& and an \c int&
+ /// parameter, the latter regard to the line number of stream. The
+ /// functor can read the input while the section go on, and the
+ /// line number should be modified accordingly.
+ template <typename Functor>
+ SectionReader& sectionStream(const std::string& type, Functor functor) {
+ LEMON_ASSERT(!type.empty(), "Type is empty.");
+ LEMON_ASSERT(_sections.find(type) == _sections.end(),
+ "Multiple reading of section.");
+ _sections.insert(std::make_pair(type,
+ new _reader_bits::StreamSection<Functor>(functor)));
+ return *this;
+ }
+
+ /// @}
+
+ private:
+
+ bool readLine() {
+ std::string str;
+ while(++line_num, std::getline(*_is, str)) {
+ line.clear(); line.str(str);
+ char c;
+ if (line >> std::ws >> c && c != '#') {
+ line.putback(c);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool readSuccess() {
+ return static_cast<bool>(*_is);
+ }
+
+ void skipSection() {
+ char c;
+ while (readSuccess() && line >> c && c != '@') {
+ readLine();
+ }
+ if (readSuccess()) {
+ line.putback(c);
+ }
+ }
+
+ public:
+
+
+ /// \name Execution of the Reader
+ /// @{
+
+ /// \brief Start the batch processing
+ ///
+ /// This function starts the batch processing.
+ void run() {
+
+ LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
+
+ std::set<std::string> extra_sections;
+
+ line_num = 0;
+ readLine();
+ skipSection();
+
+ while (readSuccess()) {
+ try {
+ char c;
+ std::string section, caption;
+ line >> c;
+ _reader_bits::readToken(line, section);
+ _reader_bits::readToken(line, caption);
+
+ if (line >> c)
+ throw FormatError("Extra character at the end of line");
+
+ if (extra_sections.find(section) != extra_sections.end()) {
+ std::ostringstream msg;
+ msg << "Multiple occurence of section: " << section;
+ throw FormatError(msg.str());
+ }
+ Sections::iterator it = _sections.find(section);
+ if (it != _sections.end()) {
+ extra_sections.insert(section);
+ it->second->process(*_is, line_num);
+ }
+ readLine();
+ skipSection();
+ } catch (FormatError& error) {
+ error.line(line_num);
+ error.file(_filename);
+ throw;
+ }
+ }
+ for (Sections::iterator it = _sections.begin();
+ it != _sections.end(); ++it) {
+ if (extra_sections.find(it->first) == extra_sections.end()) {
+ std::ostringstream os;
+ os << "Cannot find section: " << it->first;
+ throw FormatError(os.str());
+ }
+ }
+ }
+
+ /// @}
+
+ };
+
+ /// \ingroup lemon_io
+ ///
+ /// \brief Return a \ref SectionReader class
+ ///
+ /// This function just returns a \ref SectionReader class.
+ ///
+ /// Please see SectionReader documentation about the custom section
+ /// input.
+ ///
+ /// \relates SectionReader
+ /// \sa sectionReader(const std::string& fn)
+ /// \sa sectionReader(const char *fn)
+ inline SectionReader sectionReader(std::istream& is) {
+ SectionReader tmp(is);
+ return tmp;
+ }
+
+ /// \brief Return a \ref SectionReader class
+ ///
+ /// This function just returns a \ref SectionReader class.
+ /// \relates SectionReader
+ /// \sa sectionReader(std::istream& is)
+ inline SectionReader sectionReader(const std::string& fn) {
+ SectionReader tmp(fn);
+ return tmp;
+ }
+
+ /// \brief Return a \ref SectionReader class
+ ///
+ /// This function just returns a \ref SectionReader class.
+ /// \relates SectionReader
+ /// \sa sectionReader(std::istream& is)
+ inline SectionReader sectionReader(const char* fn) {
+ SectionReader tmp(fn);
+ return tmp;
+ }
+
+ /// \ingroup lemon_io
+ ///
+ /// \brief Reader for the contents of the \ref lgf-format "LGF" file
+ ///
+ /// This class can be used to read the sections, the map names and
+ /// the attributes from a file. Usually, the LEMON programs know
+ /// that, which type of graph, which maps and which attributes
+ /// should be read from a file, but in general tools (like glemon)
+ /// the contents of an LGF file should be guessed somehow. This class
+ /// reads the graph and stores the appropriate information for
+ /// reading the graph.
+ ///
+ ///\code
+ /// LgfContents contents("graph.lgf");
+ /// contents.run();
+ ///
+ /// // Does it contain any node section and arc section?
+ /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
+ /// std::cerr << "Failure, cannot find graph." << std::endl;
+ /// return -1;
+ /// }
+ /// std::cout << "The name of the default node section: "
+ /// << contents.nodeSection(0) << std::endl;
+ /// std::cout << "The number of the arc maps: "
+ /// << contents.arcMaps(0).size() << std::endl;
+ /// std::cout << "The name of second arc map: "
+ /// << contents.arcMaps(0)[1] << std::endl;
+ ///\endcode
+ class LgfContents {
+ private:
+
+ std::istream* _is;
+ bool local_is;
+
+ std::vector<std::string> _node_sections;
+ std::vector<std::string> _edge_sections;
+ std::vector<std::string> _attribute_sections;
+ std::vector<std::string> _extra_sections;
+
+ std::vector<bool> _arc_sections;
+
+ std::vector<std::vector<std::string> > _node_maps;
+ std::vector<std::vector<std::string> > _edge_maps;
+
+ std::vector<std::vector<std::string> > _attributes;
+
+
+ int line_num;
+ std::istringstream line;
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Construct an \e LGF contents reader, which reads from the given
+ /// input stream.
+ LgfContents(std::istream& is)
+ : _is(&is), local_is(false) {}
+
+ /// \brief Constructor
+ ///
+ /// Construct an \e LGF contents reader, which reads from the given
+ /// file.
+ LgfContents(const std::string& fn)
+ : _is(new std::ifstream(fn.c_str())), local_is(true) {
+ if (!(*_is)) {
+ delete _is;
+ throw IoError("Cannot open file", fn);
+ }
+ }
+
+ /// \brief Constructor
+ ///
+ /// Construct an \e LGF contents reader, which reads from the given
+ /// file.
+ LgfContents(const char* fn)
+ : _is(new std::ifstream(fn)), local_is(true) {
+ if (!(*_is)) {
+ delete _is;
+ throw IoError("Cannot open file", fn);
+ }
+ }
+
+ /// \brief Destructor
+ ~LgfContents() {
+ if (local_is) delete _is;
+ }
+
+ private:
+
+ LgfContents(const LgfContents&);
+ LgfContents& operator=(const LgfContents&);
+
+ public:
+
+
+ /// \name Node Sections
+ /// @{
+
+ /// \brief Gives back the number of node sections in the file.
+ ///
+ /// Gives back the number of node sections in the file.
+ int nodeSectionNum() const {
+ return _node_sections.size();
+ }
+
+ /// \brief Returns the node section name at the given position.
+ ///
+ /// Returns the node section name at the given position.
+ const std::string& nodeSection(int i) const {
+ return _node_sections[i];
+ }
+
+ /// \brief Gives back the node maps for the given section.
+ ///
+ /// Gives back the node maps for the given section.
+ const std::vector<std::string>& nodeMapNames(int i) const {
+ return _node_maps[i];
+ }
+
+ /// @}
+
+ /// \name Arc/Edge Sections
+ /// @{
+
+ /// \brief Gives back the number of arc/edge sections in the file.
+ ///
+ /// Gives back the number of arc/edge sections in the file.
+ /// \note It is synonym of \c edgeSectionNum().
+ int arcSectionNum() const {
+ return _edge_sections.size();
+ }
+
+ /// \brief Returns the arc/edge section name at the given position.
+ ///
+ /// Returns the arc/edge section name at the given position.
+ /// \note It is synonym of \c edgeSection().
+ const std::string& arcSection(int i) const {
+ return _edge_sections[i];
+ }
+
+ /// \brief Gives back the arc/edge maps for the given section.
+ ///
+ /// Gives back the arc/edge maps for the given section.
+ /// \note It is synonym of \c edgeMapNames().
+ const std::vector<std::string>& arcMapNames(int i) const {
+ return _edge_maps[i];
+ }
+
+ /// @}
+
+ /// \name Synonyms
+ /// @{
+
+ /// \brief Gives back the number of arc/edge sections in the file.
+ ///
+ /// Gives back the number of arc/edge sections in the file.
+ /// \note It is synonym of \c arcSectionNum().
+ int edgeSectionNum() const {
+ return _edge_sections.size();
+ }
+
+ /// \brief Returns the section name at the given position.
+ ///
+ /// Returns the section name at the given position.
+ /// \note It is synonym of \c arcSection().
+ const std::string& edgeSection(int i) const {
+ return _edge_sections[i];
+ }
+
+ /// \brief Gives back the edge maps for the given section.
+ ///
+ /// Gives back the edge maps for the given section.
+ /// \note It is synonym of \c arcMapNames().
+ const std::vector<std::string>& edgeMapNames(int i) const {
+ return _edge_maps[i];
+ }
+
+ /// @}
+
+ /// \name Attribute Sections
+ /// @{
+
+ /// \brief Gives back the number of attribute sections in the file.
+ ///
+ /// Gives back the number of attribute sections in the file.
+ int attributeSectionNum() const {
+ return _attribute_sections.size();
+ }
+
+ /// \brief Returns the attribute section name at the given position.
+ ///
+ /// Returns the attribute section name at the given position.
+ const std::string& attributeSectionNames(int i) const {
+ return _attribute_sections[i];
+ }
+
+ /// \brief Gives back the attributes for the given section.
+ ///
+ /// Gives back the attributes for the given section.
+ const std::vector<std::string>& attributes(int i) const {
+ return _attributes[i];
+ }
+
+ /// @}
+
+ /// \name Extra Sections
+ /// @{
+
+ /// \brief Gives back the number of extra sections in the file.
+ ///
+ /// Gives back the number of extra sections in the file.
+ int extraSectionNum() const {
+ return _extra_sections.size();
+ }
+
+ /// \brief Returns the extra section type at the given position.
+ ///
+ /// Returns the section type at the given position.
+ const std::string& extraSection(int i) const {
+ return _extra_sections[i];
+ }
+
+ /// @}
+
+ private:
+
+ bool readLine() {
+ std::string str;
+ while(++line_num, std::getline(*_is, str)) {
+ line.clear(); line.str(str);
+ char c;
+ if (line >> std::ws >> c && c != '#') {
+ line.putback(c);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool readSuccess() {
+ return static_cast<bool>(*_is);
+ }
+
+ void skipSection() {
+ char c;
+ while (readSuccess() && line >> c && c != '@') {
+ readLine();
+ }
+ if (readSuccess()) {
+ line.putback(c);
+ }
+ }
+
+ void readMaps(std::vector<std::string>& maps) {
+ char c;
+ if (!readLine() || !(line >> c) || c == '@') {
+ if (readSuccess() && line) line.putback(c);
+ return;
+ }
+ line.putback(c);
+ std::string map;
+ while (_reader_bits::readToken(line, map)) {
+ maps.push_back(map);
+ }
+ }
+
+ void readAttributes(std::vector<std::string>& attrs) {
+ readLine();
+ char c;
+ while (readSuccess() && line >> c && c != '@') {
+ line.putback(c);
+ std::string attr;
+ _reader_bits::readToken(line, attr);
+ attrs.push_back(attr);
+ readLine();
+ }
+ line.putback(c);
+ }
+
+ public:
+
+ /// \name Execution of the Contents Reader
+ /// @{
+
+ /// \brief Starts the reading
+ ///
+ /// This function starts the reading.
+ void run() {
+
+ readLine();
+ skipSection();
+
+ while (readSuccess()) {
+
+ char c;
+ line >> c;
+
+ std::string section, caption;
+ _reader_bits::readToken(line, section);
+ _reader_bits::readToken(line, caption);
+
+ if (section == "nodes") {
+ _node_sections.push_back(caption);
+ _node_maps.push_back(std::vector<std::string>());
+ readMaps(_node_maps.back());
+ readLine(); skipSection();
+ } else if (section == "arcs" || section == "edges") {
+ _edge_sections.push_back(caption);
+ _arc_sections.push_back(section == "arcs");
+ _edge_maps.push_back(std::vector<std::string>());
+ readMaps(_edge_maps.back());
+ readLine(); skipSection();
+ } else if (section == "attributes") {
+ _attribute_sections.push_back(caption);
+ _attributes.push_back(std::vector<std::string>());
+ readAttributes(_attributes.back());
+ } else {
+ _extra_sections.push_back(section);
+ readLine(); skipSection();
+ }
+ }
+ }
+
+ /// @}
+
+ };
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/lgf_writer.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/lgf_writer.h
new file mode 100644
index 00000000000..0695287d518
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/lgf_writer.h
@@ -0,0 +1,2687 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\ingroup lemon_io
+///\file
+///\brief \ref lgf-format "LEMON Graph Format" writer.
+
+
+#ifndef LEMON_LGF_WRITER_H
+#define LEMON_LGF_WRITER_H
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+#include <algorithm>
+
+#include <vector>
+#include <functional>
+
+#include <lemon/core.h>
+#include <lemon/maps.h>
+
+#include <lemon/concept_check.h>
+#include <lemon/concepts/maps.h>
+
+namespace lemon {
+
+ namespace _writer_bits {
+
+ template <typename Value>
+ struct DefaultConverter {
+ std::string operator()(const Value& value) {
+ std::ostringstream os;
+ os << value;
+ return os.str();
+ }
+ };
+
+ template <typename T>
+ bool operator<(const T&, const T&) {
+ throw FormatError("Label map is not comparable");
+ }
+
+ template <typename _Map>
+ class MapLess {
+ public:
+ typedef _Map Map;
+ typedef typename Map::Key Item;
+
+ private:
+ const Map& _map;
+
+ public:
+ MapLess(const Map& map) : _map(map) {}
+
+ bool operator()(const Item& left, const Item& right) {
+ return _map[left] < _map[right];
+ }
+ };
+
+ template <typename _Graph, bool _dir, typename _Map>
+ class GraphArcMapLess {
+ public:
+ typedef _Map Map;
+ typedef _Graph Graph;
+ typedef typename Graph::Edge Item;
+
+ private:
+ const Graph& _graph;
+ const Map& _map;
+
+ public:
+ GraphArcMapLess(const Graph& graph, const Map& map)
+ : _graph(graph), _map(map) {}
+
+ bool operator()(const Item& left, const Item& right) {
+ return _map[_graph.direct(left, _dir)] <
+ _map[_graph.direct(right, _dir)];
+ }
+ };
+
+ template <typename _Item>
+ class MapStorageBase {
+ public:
+ typedef _Item Item;
+
+ public:
+ MapStorageBase() {}
+ virtual ~MapStorageBase() {}
+
+ virtual std::string get(const Item& item) = 0;
+ virtual void sort(std::vector<Item>&) = 0;
+ };
+
+ template <typename _Item, typename _Map,
+ typename _Converter = DefaultConverter<typename _Map::Value> >
+ class MapStorage : public MapStorageBase<_Item> {
+ public:
+ typedef _Map Map;
+ typedef _Converter Converter;
+ typedef _Item Item;
+
+ private:
+ const Map& _map;
+ Converter _converter;
+
+ public:
+ MapStorage(const Map& map, const Converter& converter = Converter())
+ : _map(map), _converter(converter) {}
+ virtual ~MapStorage() {}
+
+ virtual std::string get(const Item& item) {
+ return _converter(_map[item]);
+ }
+ virtual void sort(std::vector<Item>& items) {
+ MapLess<Map> less(_map);
+ std::sort(items.begin(), items.end(), less);
+ }
+ };
+
+ template <typename _Graph, bool _dir, typename _Map,
+ typename _Converter = DefaultConverter<typename _Map::Value> >
+ class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
+ public:
+ typedef _Map Map;
+ typedef _Converter Converter;
+ typedef _Graph Graph;
+ typedef typename Graph::Edge Item;
+ static const bool dir = _dir;
+
+ private:
+ const Graph& _graph;
+ const Map& _map;
+ Converter _converter;
+
+ public:
+ GraphArcMapStorage(const Graph& graph, const Map& map,
+ const Converter& converter = Converter())
+ : _graph(graph), _map(map), _converter(converter) {}
+ virtual ~GraphArcMapStorage() {}
+
+ virtual std::string get(const Item& item) {
+ return _converter(_map[_graph.direct(item, dir)]);
+ }
+ virtual void sort(std::vector<Item>& items) {
+ GraphArcMapLess<Graph, dir, Map> less(_graph, _map);
+ std::sort(items.begin(), items.end(), less);
+ }
+ };
+
+ class ValueStorageBase {
+ public:
+ ValueStorageBase() {}
+ virtual ~ValueStorageBase() {}
+
+ virtual std::string get() = 0;
+ };
+
+ template <typename _Value, typename _Converter = DefaultConverter<_Value> >
+ class ValueStorage : public ValueStorageBase {
+ public:
+ typedef _Value Value;
+ typedef _Converter Converter;
+
+ private:
+ const Value& _value;
+ Converter _converter;
+
+ public:
+ ValueStorage(const Value& value, const Converter& converter = Converter())
+ : _value(value), _converter(converter) {}
+
+ virtual std::string get() {
+ return _converter(_value);
+ }
+ };
+
+ template <typename Value,
+ typename Map = std::map<Value, std::string> >
+ struct MapLookUpConverter {
+ const Map& _map;
+
+ MapLookUpConverter(const Map& map)
+ : _map(map) {}
+
+ std::string operator()(const Value& value) {
+ typename Map::const_iterator it = _map.find(value);
+ if (it == _map.end()) {
+ throw FormatError("Item not found");
+ }
+ return it->second;
+ }
+ };
+
+ template <typename Value,
+ typename Map1 = std::map<Value, std::string>,
+ typename Map2 = std::map<Value, std::string> >
+ struct DoubleMapLookUpConverter {
+ const Map1& _map1;
+ const Map2& _map2;
+
+ DoubleMapLookUpConverter(const Map1& map1, const Map2& map2)
+ : _map1(map1), _map2(map2) {}
+
+ std::string operator()(const Value& value) {
+ typename Map1::const_iterator it1 = _map1.find(value);
+ typename Map1::const_iterator it2 = _map2.find(value);
+ if (it1 == _map1.end()) {
+ if (it2 == _map2.end()) {
+ throw FormatError("Item not found");
+ } else {
+ return it2->second;
+ }
+ } else {
+ if (it2 == _map2.end()) {
+ return it1->second;
+ } else {
+ throw FormatError("Item is ambigous");
+ }
+ }
+ }
+ };
+
+ template <typename Graph>
+ struct GraphArcLookUpConverter {
+ const Graph& _graph;
+ const std::map<typename Graph::Edge, std::string>& _map;
+
+ GraphArcLookUpConverter(const Graph& graph,
+ const std::map<typename Graph::Edge,
+ std::string>& map)
+ : _graph(graph), _map(map) {}
+
+ std::string operator()(const typename Graph::Arc& val) {
+ typename std::map<typename Graph::Edge, std::string>
+ ::const_iterator it = _map.find(val);
+ if (it == _map.end()) {
+ throw FormatError("Item not found");
+ }
+ return (_graph.direction(val) ? '+' : '-') + it->second;
+ }
+ };
+
+ inline bool isWhiteSpace(char c) {
+ return c == ' ' || c == '\t' || c == '\v' ||
+ c == '\n' || c == '\r' || c == '\f';
+ }
+
+ inline bool isEscaped(char c) {
+ return c == '\\' || c == '\"' || c == '\'' ||
+ c == '\a' || c == '\b';
+ }
+
+ inline static void writeEscape(std::ostream& os, char c) {
+ switch (c) {
+ case '\\':
+ os << "\\\\";
+ return;
+ case '\"':
+ os << "\\\"";
+ return;
+ case '\a':
+ os << "\\a";
+ return;
+ case '\b':
+ os << "\\b";
+ return;
+ case '\f':
+ os << "\\f";
+ return;
+ case '\r':
+ os << "\\r";
+ return;
+ case '\n':
+ os << "\\n";
+ return;
+ case '\t':
+ os << "\\t";
+ return;
+ case '\v':
+ os << "\\v";
+ return;
+ default:
+ if (c < 0x20) {
+ std::ios::fmtflags flags = os.flags();
+ os << '\\' << std::oct << static_cast<int>(c);
+ os.flags(flags);
+ } else {
+ os << c;
+ }
+ return;
+ }
+ }
+
+ inline bool requireEscape(const std::string& str) {
+ if (str.empty() || str[0] == '@') return true;
+ std::istringstream is(str);
+ char c;
+ while (is.get(c)) {
+ if (isWhiteSpace(c) || isEscaped(c)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ inline std::ostream& writeToken(std::ostream& os, const std::string& str) {
+
+ if (requireEscape(str)) {
+ os << '\"';
+ for (std::string::const_iterator it = str.begin();
+ it != str.end(); ++it) {
+ writeEscape(os, *it);
+ }
+ os << '\"';
+ } else {
+ os << str;
+ }
+ return os;
+ }
+
+ class Section {
+ public:
+ virtual ~Section() {}
+ virtual void process(std::ostream& os) = 0;
+ };
+
+ template <typename Functor>
+ class LineSection : public Section {
+ private:
+
+ Functor _functor;
+
+ public:
+
+ LineSection(const Functor& functor) : _functor(functor) {}
+ virtual ~LineSection() {}
+
+ virtual void process(std::ostream& os) {
+ std::string line;
+ while (!(line = _functor()).empty()) os << line << std::endl;
+ }
+ };
+
+ template <typename Functor>
+ class StreamSection : public Section {
+ private:
+
+ Functor _functor;
+
+ public:
+
+ StreamSection(const Functor& functor) : _functor(functor) {}
+ virtual ~StreamSection() {}
+
+ virtual void process(std::ostream& os) {
+ _functor(os);
+ }
+ };
+
+ }
+
+ template <typename DGR>
+ class DigraphWriter;
+
+ template <typename TDGR>
+ DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
+ std::ostream& os = std::cout);
+ template <typename TDGR>
+ DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const std::string& fn);
+
+ template <typename TDGR>
+ DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const char* fn);
+
+
+ /// \ingroup lemon_io
+ ///
+ /// \brief \ref lgf-format "LGF" writer for directed graphs
+ ///
+ /// This utility writes an \ref lgf-format "LGF" file.
+ ///
+ /// The writing method does a batch processing. The user creates a
+ /// writer object, then various writing rules can be added to the
+ /// writer, and eventually the writing is executed with the \c run()
+ /// member function. A map writing rule can be added to the writer
+ /// with the \c nodeMap() or \c arcMap() members. An optional
+ /// converter parameter can also be added as a standard functor
+ /// converting from the value type of the map to \c std::string. If it
+ /// is set, it will determine how the value type of the map is written to
+ /// the output stream. If the functor is not set, then a default
+ /// conversion will be used. The \c attribute(), \c node() and \c
+ /// arc() functions are used to add attribute writing rules.
+ ///
+ ///\code
+ /// DigraphWriter<DGR>(digraph, std::cout).
+ /// nodeMap("coordinates", coord_map).
+ /// nodeMap("size", size).
+ /// nodeMap("title", title).
+ /// arcMap("capacity", cap_map).
+ /// node("source", src).
+ /// node("target", trg).
+ /// attribute("caption", caption).
+ /// run();
+ ///\endcode
+ ///
+ ///
+ /// By default, the writer does not write additional captions to the
+ /// sections, but they can be give as an optional parameter of
+ /// the \c nodes(), \c arcs() or \c
+ /// attributes() functions.
+ ///
+ /// The \c skipNodes() and \c skipArcs() functions forbid the
+ /// writing of the sections. If two arc sections should be written
+ /// to the output, it can be done in two passes, the first pass
+ /// writes the node section and the first arc section, then the
+ /// second pass skips the node section and writes just the arc
+ /// section to the stream. The output stream can be retrieved with
+ /// the \c ostream() function, hence the second pass can append its
+ /// output to the output of the first pass.
+ template <typename DGR>
+ class DigraphWriter {
+ public:
+
+ typedef DGR Digraph;
+ TEMPLATE_DIGRAPH_TYPEDEFS(DGR);
+
+ private:
+
+
+ std::ostream* _os;
+ bool local_os;
+
+ const DGR& _digraph;
+
+ std::string _nodes_caption;
+ std::string _arcs_caption;
+ std::string _attributes_caption;
+
+ typedef std::map<Node, std::string> NodeIndex;
+ NodeIndex _node_index;
+ typedef std::map<Arc, std::string> ArcIndex;
+ ArcIndex _arc_index;
+
+ typedef std::vector<std::pair<std::string,
+ _writer_bits::MapStorageBase<Node>* > > NodeMaps;
+ NodeMaps _node_maps;
+
+ typedef std::vector<std::pair<std::string,
+ _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
+ ArcMaps _arc_maps;
+
+ typedef std::vector<std::pair<std::string,
+ _writer_bits::ValueStorageBase*> > Attributes;
+ Attributes _attributes;
+
+ bool _skip_nodes;
+ bool _skip_arcs;
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Construct a directed graph writer, which writes to the given
+ /// output stream.
+ DigraphWriter(const DGR& digraph, std::ostream& os = std::cout)
+ : _os(&os), local_os(false), _digraph(digraph),
+ _skip_nodes(false), _skip_arcs(false) {}
+
+ /// \brief Constructor
+ ///
+ /// Construct a directed graph writer, which writes to the given
+ /// output file.
+ DigraphWriter(const DGR& digraph, const std::string& fn)
+ : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
+ _skip_nodes(false), _skip_arcs(false) {
+ if (!(*_os)) {
+ delete _os;
+ throw IoError("Cannot write file", fn);
+ }
+ }
+
+ /// \brief Constructor
+ ///
+ /// Construct a directed graph writer, which writes to the given
+ /// output file.
+ DigraphWriter(const DGR& digraph, const char* fn)
+ : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
+ _skip_nodes(false), _skip_arcs(false) {
+ if (!(*_os)) {
+ delete _os;
+ throw IoError("Cannot write file", fn);
+ }
+ }
+
+ /// \brief Destructor
+ ~DigraphWriter() {
+ for (typename NodeMaps::iterator it = _node_maps.begin();
+ it != _node_maps.end(); ++it) {
+ delete it->second;
+ }
+
+ for (typename ArcMaps::iterator it = _arc_maps.begin();
+ it != _arc_maps.end(); ++it) {
+ delete it->second;
+ }
+
+ for (typename Attributes::iterator it = _attributes.begin();
+ it != _attributes.end(); ++it) {
+ delete it->second;
+ }
+
+ if (local_os) {
+ delete _os;
+ }
+ }
+
+ private:
+
+ template <typename TDGR>
+ friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
+ std::ostream& os);
+ template <typename TDGR>
+ friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
+ const std::string& fn);
+ template <typename TDGR>
+ friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
+ const char *fn);
+
+ DigraphWriter(DigraphWriter& other)
+ : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
+ _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
+
+ other._os = 0;
+ other.local_os = false;
+
+ _node_index.swap(other._node_index);
+ _arc_index.swap(other._arc_index);
+
+ _node_maps.swap(other._node_maps);
+ _arc_maps.swap(other._arc_maps);
+ _attributes.swap(other._attributes);
+
+ _nodes_caption = other._nodes_caption;
+ _arcs_caption = other._arcs_caption;
+ _attributes_caption = other._attributes_caption;
+ }
+
+ DigraphWriter& operator=(const DigraphWriter&);
+
+ public:
+
+ /// \name Writing Rules
+ /// @{
+
+ /// \brief Node map writing rule
+ ///
+ /// Add a node map writing rule to the writer.
+ template <typename Map>
+ DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
+ checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<Node>* storage =
+ new _writer_bits::MapStorage<Node, Map>(map);
+ _node_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Node map writing rule
+ ///
+ /// Add a node map writing rule with specialized converter to the
+ /// writer.
+ template <typename Map, typename Converter>
+ DigraphWriter& nodeMap(const std::string& caption, const Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<Node>* storage =
+ new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
+ _node_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Arc map writing rule
+ ///
+ /// Add an arc map writing rule to the writer.
+ template <typename Map>
+ DigraphWriter& arcMap(const std::string& caption, const Map& map) {
+ checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<Arc>* storage =
+ new _writer_bits::MapStorage<Arc, Map>(map);
+ _arc_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Arc map writing rule
+ ///
+ /// Add an arc map writing rule with specialized converter to the
+ /// writer.
+ template <typename Map, typename Converter>
+ DigraphWriter& arcMap(const std::string& caption, const Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<Arc>* storage =
+ new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
+ _arc_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Attribute writing rule
+ ///
+ /// Add an attribute writing rule to the writer.
+ template <typename Value>
+ DigraphWriter& attribute(const std::string& caption, const Value& value) {
+ _writer_bits::ValueStorageBase* storage =
+ new _writer_bits::ValueStorage<Value>(value);
+ _attributes.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Attribute writing rule
+ ///
+ /// Add an attribute writing rule with specialized converter to the
+ /// writer.
+ template <typename Value, typename Converter>
+ DigraphWriter& attribute(const std::string& caption, const Value& value,
+ const Converter& converter = Converter()) {
+ _writer_bits::ValueStorageBase* storage =
+ new _writer_bits::ValueStorage<Value, Converter>(value, converter);
+ _attributes.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Node writing rule
+ ///
+ /// Add a node writing rule to the writer.
+ DigraphWriter& node(const std::string& caption, const Node& node) {
+ typedef _writer_bits::MapLookUpConverter<Node> Converter;
+ Converter converter(_node_index);
+ _writer_bits::ValueStorageBase* storage =
+ new _writer_bits::ValueStorage<Node, Converter>(node, converter);
+ _attributes.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Arc writing rule
+ ///
+ /// Add an arc writing rule to writer.
+ DigraphWriter& arc(const std::string& caption, const Arc& arc) {
+ typedef _writer_bits::MapLookUpConverter<Arc> Converter;
+ Converter converter(_arc_index);
+ _writer_bits::ValueStorageBase* storage =
+ new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
+ _attributes.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \name Section Captions
+ /// @{
+
+ /// \brief Add an additional caption to the \c \@nodes section
+ ///
+ /// Add an additional caption to the \c \@nodes section.
+ DigraphWriter& nodes(const std::string& caption) {
+ _nodes_caption = caption;
+ return *this;
+ }
+
+ /// \brief Add an additional caption to the \c \@arcs section
+ ///
+ /// Add an additional caption to the \c \@arcs section.
+ DigraphWriter& arcs(const std::string& caption) {
+ _arcs_caption = caption;
+ return *this;
+ }
+
+ /// \brief Add an additional caption to the \c \@attributes section
+ ///
+ /// Add an additional caption to the \c \@attributes section.
+ DigraphWriter& attributes(const std::string& caption) {
+ _attributes_caption = caption;
+ return *this;
+ }
+
+ /// \name Skipping Section
+ /// @{
+
+ /// \brief Skip writing the node set
+ ///
+ /// The \c \@nodes section will not be written to the stream.
+ DigraphWriter& skipNodes() {
+ LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
+ _skip_nodes = true;
+ return *this;
+ }
+
+ /// \brief Skip writing arc set
+ ///
+ /// The \c \@arcs section will not be written to the stream.
+ DigraphWriter& skipArcs() {
+ LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
+ _skip_arcs = true;
+ return *this;
+ }
+
+ /// @}
+
+ private:
+
+ void writeNodes() {
+ _writer_bits::MapStorageBase<Node>* label = 0;
+ for (typename NodeMaps::iterator it = _node_maps.begin();
+ it != _node_maps.end(); ++it) {
+ if (it->first == "label") {
+ label = it->second;
+ break;
+ }
+ }
+
+ *_os << "@nodes";
+ if (!_nodes_caption.empty()) {
+ _writer_bits::writeToken(*_os << ' ', _nodes_caption);
+ }
+ *_os << std::endl;
+
+ if (label == 0) {
+ *_os << "label" << '\t';
+ }
+ for (typename NodeMaps::iterator it = _node_maps.begin();
+ it != _node_maps.end(); ++it) {
+ _writer_bits::writeToken(*_os, it->first) << '\t';
+ }
+ *_os << std::endl;
+
+ std::vector<Node> nodes;
+ for (NodeIt n(_digraph); n != INVALID; ++n) {
+ nodes.push_back(n);
+ }
+
+ if (label == 0) {
+ IdMap<DGR, Node> id_map(_digraph);
+ _writer_bits::MapLess<IdMap<DGR, Node> > id_less(id_map);
+ std::sort(nodes.begin(), nodes.end(), id_less);
+ } else {
+ label->sort(nodes);
+ }
+
+ for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
+ Node n = nodes[i];
+ if (label == 0) {
+ std::ostringstream os;
+ os << _digraph.id(n);
+ _writer_bits::writeToken(*_os, os.str());
+ *_os << '\t';
+ _node_index.insert(std::make_pair(n, os.str()));
+ }
+ for (typename NodeMaps::iterator it = _node_maps.begin();
+ it != _node_maps.end(); ++it) {
+ std::string value = it->second->get(n);
+ _writer_bits::writeToken(*_os, value);
+ if (it->first == "label") {
+ _node_index.insert(std::make_pair(n, value));
+ }
+ *_os << '\t';
+ }
+ *_os << std::endl;
+ }
+ }
+
+ void createNodeIndex() {
+ _writer_bits::MapStorageBase<Node>* label = 0;
+ for (typename NodeMaps::iterator it = _node_maps.begin();
+ it != _node_maps.end(); ++it) {
+ if (it->first == "label") {
+ label = it->second;
+ break;
+ }
+ }
+
+ if (label == 0) {
+ for (NodeIt n(_digraph); n != INVALID; ++n) {
+ std::ostringstream os;
+ os << _digraph.id(n);
+ _node_index.insert(std::make_pair(n, os.str()));
+ }
+ } else {
+ for (NodeIt n(_digraph); n != INVALID; ++n) {
+ std::string value = label->get(n);
+ _node_index.insert(std::make_pair(n, value));
+ }
+ }
+ }
+
+ void writeArcs() {
+ _writer_bits::MapStorageBase<Arc>* label = 0;
+ for (typename ArcMaps::iterator it = _arc_maps.begin();
+ it != _arc_maps.end(); ++it) {
+ if (it->first == "label") {
+ label = it->second;
+ break;
+ }
+ }
+
+ *_os << "@arcs";
+ if (!_arcs_caption.empty()) {
+ _writer_bits::writeToken(*_os << ' ', _arcs_caption);
+ }
+ *_os << std::endl;
+
+ *_os << '\t' << '\t';
+ if (label == 0) {
+ *_os << "label" << '\t';
+ }
+ for (typename ArcMaps::iterator it = _arc_maps.begin();
+ it != _arc_maps.end(); ++it) {
+ _writer_bits::writeToken(*_os, it->first) << '\t';
+ }
+ *_os << std::endl;
+
+ std::vector<Arc> arcs;
+ for (ArcIt n(_digraph); n != INVALID; ++n) {
+ arcs.push_back(n);
+ }
+
+ if (label == 0) {
+ IdMap<DGR, Arc> id_map(_digraph);
+ _writer_bits::MapLess<IdMap<DGR, Arc> > id_less(id_map);
+ std::sort(arcs.begin(), arcs.end(), id_less);
+ } else {
+ label->sort(arcs);
+ }
+
+ for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
+ Arc a = arcs[i];
+ _writer_bits::writeToken(*_os, _node_index.
+ find(_digraph.source(a))->second);
+ *_os << '\t';
+ _writer_bits::writeToken(*_os, _node_index.
+ find(_digraph.target(a))->second);
+ *_os << '\t';
+ if (label == 0) {
+ std::ostringstream os;
+ os << _digraph.id(a);
+ _writer_bits::writeToken(*_os, os.str());
+ *_os << '\t';
+ _arc_index.insert(std::make_pair(a, os.str()));
+ }
+ for (typename ArcMaps::iterator it = _arc_maps.begin();
+ it != _arc_maps.end(); ++it) {
+ std::string value = it->second->get(a);
+ _writer_bits::writeToken(*_os, value);
+ if (it->first == "label") {
+ _arc_index.insert(std::make_pair(a, value));
+ }
+ *_os << '\t';
+ }
+ *_os << std::endl;
+ }
+ }
+
+ void createArcIndex() {
+ _writer_bits::MapStorageBase<Arc>* label = 0;
+ for (typename ArcMaps::iterator it = _arc_maps.begin();
+ it != _arc_maps.end(); ++it) {
+ if (it->first == "label") {
+ label = it->second;
+ break;
+ }
+ }
+
+ if (label == 0) {
+ for (ArcIt a(_digraph); a != INVALID; ++a) {
+ std::ostringstream os;
+ os << _digraph.id(a);
+ _arc_index.insert(std::make_pair(a, os.str()));
+ }
+ } else {
+ for (ArcIt a(_digraph); a != INVALID; ++a) {
+ std::string value = label->get(a);
+ _arc_index.insert(std::make_pair(a, value));
+ }
+ }
+ }
+
+ void writeAttributes() {
+ if (_attributes.empty()) return;
+ *_os << "@attributes";
+ if (!_attributes_caption.empty()) {
+ _writer_bits::writeToken(*_os << ' ', _attributes_caption);
+ }
+ *_os << std::endl;
+ for (typename Attributes::iterator it = _attributes.begin();
+ it != _attributes.end(); ++it) {
+ _writer_bits::writeToken(*_os, it->first) << ' ';
+ _writer_bits::writeToken(*_os, it->second->get());
+ *_os << std::endl;
+ }
+ }
+
+ public:
+
+ /// \name Execution of the Writer
+ /// @{
+
+ /// \brief Start the batch processing
+ ///
+ /// This function starts the batch processing.
+ void run() {
+ if (!_skip_nodes) {
+ writeNodes();
+ } else {
+ createNodeIndex();
+ }
+ if (!_skip_arcs) {
+ writeArcs();
+ } else {
+ createArcIndex();
+ }
+ writeAttributes();
+ }
+
+ /// \brief Give back the stream of the writer
+ ///
+ /// Give back the stream of the writer.
+ std::ostream& ostream() {
+ return *_os;
+ }
+
+ /// @}
+ };
+
+ /// \ingroup lemon_io
+ ///
+ /// \brief Return a \ref lemon::DigraphWriter "DigraphWriter" class
+ ///
+ /// This function just returns a \ref lemon::DigraphWriter
+ /// "DigraphWriter" class.
+ ///
+ /// With this function a digraph can be write to a file or output
+ /// stream in \ref lgf-format "LGF" format with several maps and
+ /// attributes. For example, with the following code a network flow
+ /// problem can be written to the standard output, i.e. a digraph
+ /// with a \e capacity map on the arcs and \e source and \e target
+ /// nodes:
+ ///
+ ///\code
+ ///ListDigraph digraph;
+ ///ListDigraph::ArcMap<int> cap(digraph);
+ ///ListDigraph::Node src, trg;
+ /// // Setting the capacity map and source and target nodes
+ ///digraphWriter(digraph, std::cout).
+ /// arcMap("capacity", cap).
+ /// node("source", src).
+ /// node("target", trg).
+ /// run();
+ ///\endcode
+ ///
+ /// For a complete documentation, please see the
+ /// \ref lemon::DigraphWriter "DigraphWriter"
+ /// class documentation.
+ /// \warning Don't forget to put the \ref lemon::DigraphWriter::run() "run()"
+ /// to the end of the parameter list.
+ /// \relates DigraphWriter
+ /// \sa digraphWriter(const TDGR& digraph, const std::string& fn)
+ /// \sa digraphWriter(const TDGR& digraph, const char* fn)
+ template <typename TDGR>
+ DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, std::ostream& os) {
+ DigraphWriter<TDGR> tmp(digraph, os);
+ return tmp;
+ }
+
+ /// \brief Return a \ref DigraphWriter class
+ ///
+ /// This function just returns a \ref DigraphWriter class.
+ /// \relates DigraphWriter
+ /// \sa digraphWriter(const TDGR& digraph, std::ostream& os)
+ template <typename TDGR>
+ DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
+ const std::string& fn) {
+ DigraphWriter<TDGR> tmp(digraph, fn);
+ return tmp;
+ }
+
+ /// \brief Return a \ref DigraphWriter class
+ ///
+ /// This function just returns a \ref DigraphWriter class.
+ /// \relates DigraphWriter
+ /// \sa digraphWriter(const TDGR& digraph, std::ostream& os)
+ template <typename TDGR>
+ DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const char* fn) {
+ DigraphWriter<TDGR> tmp(digraph, fn);
+ return tmp;
+ }
+
+ template <typename GR>
+ class GraphWriter;
+
+ template <typename TGR>
+ GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os = std::cout);
+ template <typename TGR>
+ GraphWriter<TGR> graphWriter(const TGR& graph, const std::string& fn);
+ template <typename TGR>
+ GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn);
+
+ /// \ingroup lemon_io
+ ///
+ /// \brief \ref lgf-format "LGF" writer for undirected graphs
+ ///
+ /// This utility writes an \ref lgf-format "LGF" file.
+ ///
+ /// It can be used almost the same way as \c DigraphWriter.
+ /// The only difference is that this class can handle edges and
+ /// edge maps as well as arcs and arc maps.
+ ///
+ /// The arc maps are written into the file as two columns, the
+ /// caption of the columns are the name of the map prefixed with \c
+ /// '+' and \c '-'. The arcs are written into the \c \@attributes
+ /// section as a \c '+' or a \c '-' prefix (depends on the direction
+ /// of the arc) and the label of corresponding edge.
+ template <typename GR>
+ class GraphWriter {
+ public:
+
+ typedef GR Graph;
+ TEMPLATE_GRAPH_TYPEDEFS(GR);
+
+ private:
+
+
+ std::ostream* _os;
+ bool local_os;
+
+ const GR& _graph;
+
+ std::string _nodes_caption;
+ std::string _edges_caption;
+ std::string _attributes_caption;
+
+ typedef std::map<Node, std::string> NodeIndex;
+ NodeIndex _node_index;
+ typedef std::map<Edge, std::string> EdgeIndex;
+ EdgeIndex _edge_index;
+
+ typedef std::vector<std::pair<std::string,
+ _writer_bits::MapStorageBase<Node>* > > NodeMaps;
+ NodeMaps _node_maps;
+
+ typedef std::vector<std::pair<std::string,
+ _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
+ EdgeMaps _edge_maps;
+
+ typedef std::vector<std::pair<std::string,
+ _writer_bits::ValueStorageBase*> > Attributes;
+ Attributes _attributes;
+
+ bool _skip_nodes;
+ bool _skip_edges;
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Construct an undirected graph writer, which writes to the
+ /// given output stream.
+ GraphWriter(const GR& graph, std::ostream& os = std::cout)
+ : _os(&os), local_os(false), _graph(graph),
+ _skip_nodes(false), _skip_edges(false) {}
+
+ /// \brief Constructor
+ ///
+ /// Construct a undirected graph writer, which writes to the given
+ /// output file.
+ GraphWriter(const GR& graph, const std::string& fn)
+ : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
+ _skip_nodes(false), _skip_edges(false) {
+ if (!(*_os)) {
+ delete _os;
+ throw IoError("Cannot write file", fn);
+ }
+ }
+
+ /// \brief Constructor
+ ///
+ /// Construct a undirected graph writer, which writes to the given
+ /// output file.
+ GraphWriter(const GR& graph, const char* fn)
+ : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
+ _skip_nodes(false), _skip_edges(false) {
+ if (!(*_os)) {
+ delete _os;
+ throw IoError("Cannot write file", fn);
+ }
+ }
+
+ /// \brief Destructor
+ ~GraphWriter() {
+ for (typename NodeMaps::iterator it = _node_maps.begin();
+ it != _node_maps.end(); ++it) {
+ delete it->second;
+ }
+
+ for (typename EdgeMaps::iterator it = _edge_maps.begin();
+ it != _edge_maps.end(); ++it) {
+ delete it->second;
+ }
+
+ for (typename Attributes::iterator it = _attributes.begin();
+ it != _attributes.end(); ++it) {
+ delete it->second;
+ }
+
+ if (local_os) {
+ delete _os;
+ }
+ }
+
+ private:
+
+ template <typename TGR>
+ friend GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os);
+ template <typename TGR>
+ friend GraphWriter<TGR> graphWriter(const TGR& graph,
+ const std::string& fn);
+ template <typename TGR>
+ friend GraphWriter<TGR> graphWriter(const TGR& graph, const char *fn);
+
+ GraphWriter(GraphWriter& other)
+ : _os(other._os), local_os(other.local_os), _graph(other._graph),
+ _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
+
+ other._os = 0;
+ other.local_os = false;
+
+ _node_index.swap(other._node_index);
+ _edge_index.swap(other._edge_index);
+
+ _node_maps.swap(other._node_maps);
+ _edge_maps.swap(other._edge_maps);
+ _attributes.swap(other._attributes);
+
+ _nodes_caption = other._nodes_caption;
+ _edges_caption = other._edges_caption;
+ _attributes_caption = other._attributes_caption;
+ }
+
+ GraphWriter& operator=(const GraphWriter&);
+
+ public:
+
+ /// \name Writing Rules
+ /// @{
+
+ /// \brief Node map writing rule
+ ///
+ /// Add a node map writing rule to the writer.
+ template <typename Map>
+ GraphWriter& nodeMap(const std::string& caption, const Map& map) {
+ checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<Node>* storage =
+ new _writer_bits::MapStorage<Node, Map>(map);
+ _node_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Node map writing rule
+ ///
+ /// Add a node map writing rule with specialized converter to the
+ /// writer.
+ template <typename Map, typename Converter>
+ GraphWriter& nodeMap(const std::string& caption, const Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<Node>* storage =
+ new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
+ _node_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Edge map writing rule
+ ///
+ /// Add an edge map writing rule to the writer.
+ template <typename Map>
+ GraphWriter& edgeMap(const std::string& caption, const Map& map) {
+ checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<Edge>* storage =
+ new _writer_bits::MapStorage<Edge, Map>(map);
+ _edge_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Edge map writing rule
+ ///
+ /// Add an edge map writing rule with specialized converter to the
+ /// writer.
+ template <typename Map, typename Converter>
+ GraphWriter& edgeMap(const std::string& caption, const Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<Edge>* storage =
+ new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
+ _edge_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Arc map writing rule
+ ///
+ /// Add an arc map writing rule to the writer.
+ template <typename Map>
+ GraphWriter& arcMap(const std::string& caption, const Map& map) {
+ checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<Edge>* forward_storage =
+ new _writer_bits::GraphArcMapStorage<GR, true, Map>(_graph, map);
+ _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
+ _writer_bits::MapStorageBase<Edge>* backward_storage =
+ new _writer_bits::GraphArcMapStorage<GR, false, Map>(_graph, map);
+ _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
+ return *this;
+ }
+
+ /// \brief Arc map writing rule
+ ///
+ /// Add an arc map writing rule with specialized converter to the
+ /// writer.
+ template <typename Map, typename Converter>
+ GraphWriter& arcMap(const std::string& caption, const Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<Edge>* forward_storage =
+ new _writer_bits::GraphArcMapStorage<GR, true, Map, Converter>
+ (_graph, map, converter);
+ _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
+ _writer_bits::MapStorageBase<Edge>* backward_storage =
+ new _writer_bits::GraphArcMapStorage<GR, false, Map, Converter>
+ (_graph, map, converter);
+ _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
+ return *this;
+ }
+
+ /// \brief Attribute writing rule
+ ///
+ /// Add an attribute writing rule to the writer.
+ template <typename Value>
+ GraphWriter& attribute(const std::string& caption, const Value& value) {
+ _writer_bits::ValueStorageBase* storage =
+ new _writer_bits::ValueStorage<Value>(value);
+ _attributes.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Attribute writing rule
+ ///
+ /// Add an attribute writing rule with specialized converter to the
+ /// writer.
+ template <typename Value, typename Converter>
+ GraphWriter& attribute(const std::string& caption, const Value& value,
+ const Converter& converter = Converter()) {
+ _writer_bits::ValueStorageBase* storage =
+ new _writer_bits::ValueStorage<Value, Converter>(value, converter);
+ _attributes.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Node writing rule
+ ///
+ /// Add a node writing rule to the writer.
+ GraphWriter& node(const std::string& caption, const Node& node) {
+ typedef _writer_bits::MapLookUpConverter<Node> Converter;
+ Converter converter(_node_index);
+ _writer_bits::ValueStorageBase* storage =
+ new _writer_bits::ValueStorage<Node, Converter>(node, converter);
+ _attributes.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Edge writing rule
+ ///
+ /// Add an edge writing rule to writer.
+ GraphWriter& edge(const std::string& caption, const Edge& edge) {
+ typedef _writer_bits::MapLookUpConverter<Edge> Converter;
+ Converter converter(_edge_index);
+ _writer_bits::ValueStorageBase* storage =
+ new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
+ _attributes.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Arc writing rule
+ ///
+ /// Add an arc writing rule to writer.
+ GraphWriter& arc(const std::string& caption, const Arc& arc) {
+ typedef _writer_bits::GraphArcLookUpConverter<GR> Converter;
+ Converter converter(_graph, _edge_index);
+ _writer_bits::ValueStorageBase* storage =
+ new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
+ _attributes.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \name Section Captions
+ /// @{
+
+ /// \brief Add an additional caption to the \c \@nodes section
+ ///
+ /// Add an additional caption to the \c \@nodes section.
+ GraphWriter& nodes(const std::string& caption) {
+ _nodes_caption = caption;
+ return *this;
+ }
+
+ /// \brief Add an additional caption to the \c \@edges section
+ ///
+ /// Add an additional caption to the \c \@edges section.
+ GraphWriter& edges(const std::string& caption) {
+ _edges_caption = caption;
+ return *this;
+ }
+
+ /// \brief Add an additional caption to the \c \@attributes section
+ ///
+ /// Add an additional caption to the \c \@attributes section.
+ GraphWriter& attributes(const std::string& caption) {
+ _attributes_caption = caption;
+ return *this;
+ }
+
+ /// \name Skipping Section
+ /// @{
+
+ /// \brief Skip writing the node set
+ ///
+ /// The \c \@nodes section will not be written to the stream.
+ GraphWriter& skipNodes() {
+ LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
+ _skip_nodes = true;
+ return *this;
+ }
+
+ /// \brief Skip writing edge set
+ ///
+ /// The \c \@edges section will not be written to the stream.
+ GraphWriter& skipEdges() {
+ LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
+ _skip_edges = true;
+ return *this;
+ }
+
+ /// @}
+
+ private:
+
+ void writeNodes() {
+ _writer_bits::MapStorageBase<Node>* label = 0;
+ for (typename NodeMaps::iterator it = _node_maps.begin();
+ it != _node_maps.end(); ++it) {
+ if (it->first == "label") {
+ label = it->second;
+ break;
+ }
+ }
+
+ *_os << "@nodes";
+ if (!_nodes_caption.empty()) {
+ _writer_bits::writeToken(*_os << ' ', _nodes_caption);
+ }
+ *_os << std::endl;
+
+ if (label == 0) {
+ *_os << "label" << '\t';
+ }
+ for (typename NodeMaps::iterator it = _node_maps.begin();
+ it != _node_maps.end(); ++it) {
+ _writer_bits::writeToken(*_os, it->first) << '\t';
+ }
+ *_os << std::endl;
+
+ std::vector<Node> nodes;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ nodes.push_back(n);
+ }
+
+ if (label == 0) {
+ IdMap<GR, Node> id_map(_graph);
+ _writer_bits::MapLess<IdMap<GR, Node> > id_less(id_map);
+ std::sort(nodes.begin(), nodes.end(), id_less);
+ } else {
+ label->sort(nodes);
+ }
+
+ for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
+ Node n = nodes[i];
+ if (label == 0) {
+ std::ostringstream os;
+ os << _graph.id(n);
+ _writer_bits::writeToken(*_os, os.str());
+ *_os << '\t';
+ _node_index.insert(std::make_pair(n, os.str()));
+ }
+ for (typename NodeMaps::iterator it = _node_maps.begin();
+ it != _node_maps.end(); ++it) {
+ std::string value = it->second->get(n);
+ _writer_bits::writeToken(*_os, value);
+ if (it->first == "label") {
+ _node_index.insert(std::make_pair(n, value));
+ }
+ *_os << '\t';
+ }
+ *_os << std::endl;
+ }
+ }
+
+ void createNodeIndex() {
+ _writer_bits::MapStorageBase<Node>* label = 0;
+ for (typename NodeMaps::iterator it = _node_maps.begin();
+ it != _node_maps.end(); ++it) {
+ if (it->first == "label") {
+ label = it->second;
+ break;
+ }
+ }
+
+ if (label == 0) {
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ std::ostringstream os;
+ os << _graph.id(n);
+ _node_index.insert(std::make_pair(n, os.str()));
+ }
+ } else {
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ std::string value = label->get(n);
+ _node_index.insert(std::make_pair(n, value));
+ }
+ }
+ }
+
+ void writeEdges() {
+ _writer_bits::MapStorageBase<Edge>* label = 0;
+ for (typename EdgeMaps::iterator it = _edge_maps.begin();
+ it != _edge_maps.end(); ++it) {
+ if (it->first == "label") {
+ label = it->second;
+ break;
+ }
+ }
+
+ *_os << "@edges";
+ if (!_edges_caption.empty()) {
+ _writer_bits::writeToken(*_os << ' ', _edges_caption);
+ }
+ *_os << std::endl;
+
+ *_os << '\t' << '\t';
+ if (label == 0) {
+ *_os << "label" << '\t';
+ }
+ for (typename EdgeMaps::iterator it = _edge_maps.begin();
+ it != _edge_maps.end(); ++it) {
+ _writer_bits::writeToken(*_os, it->first) << '\t';
+ }
+ *_os << std::endl;
+
+ std::vector<Edge> edges;
+ for (EdgeIt n(_graph); n != INVALID; ++n) {
+ edges.push_back(n);
+ }
+
+ if (label == 0) {
+ IdMap<GR, Edge> id_map(_graph);
+ _writer_bits::MapLess<IdMap<GR, Edge> > id_less(id_map);
+ std::sort(edges.begin(), edges.end(), id_less);
+ } else {
+ label->sort(edges);
+ }
+
+ for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
+ Edge e = edges[i];
+ _writer_bits::writeToken(*_os, _node_index.
+ find(_graph.u(e))->second);
+ *_os << '\t';
+ _writer_bits::writeToken(*_os, _node_index.
+ find(_graph.v(e))->second);
+ *_os << '\t';
+ if (label == 0) {
+ std::ostringstream os;
+ os << _graph.id(e);
+ _writer_bits::writeToken(*_os, os.str());
+ *_os << '\t';
+ _edge_index.insert(std::make_pair(e, os.str()));
+ }
+ for (typename EdgeMaps::iterator it = _edge_maps.begin();
+ it != _edge_maps.end(); ++it) {
+ std::string value = it->second->get(e);
+ _writer_bits::writeToken(*_os, value);
+ if (it->first == "label") {
+ _edge_index.insert(std::make_pair(e, value));
+ }
+ *_os << '\t';
+ }
+ *_os << std::endl;
+ }
+ }
+
+ void createEdgeIndex() {
+ _writer_bits::MapStorageBase<Edge>* label = 0;
+ for (typename EdgeMaps::iterator it = _edge_maps.begin();
+ it != _edge_maps.end(); ++it) {
+ if (it->first == "label") {
+ label = it->second;
+ break;
+ }
+ }
+
+ if (label == 0) {
+ for (EdgeIt e(_graph); e != INVALID; ++e) {
+ std::ostringstream os;
+ os << _graph.id(e);
+ _edge_index.insert(std::make_pair(e, os.str()));
+ }
+ } else {
+ for (EdgeIt e(_graph); e != INVALID; ++e) {
+ std::string value = label->get(e);
+ _edge_index.insert(std::make_pair(e, value));
+ }
+ }
+ }
+
+ void writeAttributes() {
+ if (_attributes.empty()) return;
+ *_os << "@attributes";
+ if (!_attributes_caption.empty()) {
+ _writer_bits::writeToken(*_os << ' ', _attributes_caption);
+ }
+ *_os << std::endl;
+ for (typename Attributes::iterator it = _attributes.begin();
+ it != _attributes.end(); ++it) {
+ _writer_bits::writeToken(*_os, it->first) << ' ';
+ _writer_bits::writeToken(*_os, it->second->get());
+ *_os << std::endl;
+ }
+ }
+
+ public:
+
+ /// \name Execution of the Writer
+ /// @{
+
+ /// \brief Start the batch processing
+ ///
+ /// This function starts the batch processing.
+ void run() {
+ if (!_skip_nodes) {
+ writeNodes();
+ } else {
+ createNodeIndex();
+ }
+ if (!_skip_edges) {
+ writeEdges();
+ } else {
+ createEdgeIndex();
+ }
+ writeAttributes();
+ }
+
+ /// \brief Give back the stream of the writer
+ ///
+ /// Give back the stream of the writer
+ std::ostream& ostream() {
+ return *_os;
+ }
+
+ /// @}
+ };
+
+ /// \ingroup lemon_io
+ ///
+ /// \brief Return a \ref lemon::GraphWriter "GraphWriter" class
+ ///
+ /// This function just returns a \ref lemon::GraphWriter "GraphWriter" class.
+ ///
+ /// With this function a graph can be write to a file or output
+ /// stream in \ref lgf-format "LGF" format with several maps and
+ /// attributes. For example, with the following code a weighted
+ /// matching problem can be written to the standard output, i.e. a
+ /// graph with a \e weight map on the edges:
+ ///
+ ///\code
+ ///ListGraph graph;
+ ///ListGraph::EdgeMap<int> weight(graph);
+ /// // Setting the weight map
+ ///graphWriter(graph, std::cout).
+ /// edgeMap("weight", weight).
+ /// run();
+ ///\endcode
+ ///
+ /// For a complete documentation, please see the
+ /// \ref lemon::GraphWriter "GraphWriter"
+ /// class documentation.
+ /// \warning Don't forget to put the \ref lemon::GraphWriter::run() "run()"
+ /// to the end of the parameter list.
+ /// \relates GraphWriter
+ /// \sa graphWriter(const TGR& graph, const std::string& fn)
+ /// \sa graphWriter(const TGR& graph, const char* fn)
+ template <typename TGR>
+ GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os) {
+ GraphWriter<TGR> tmp(graph, os);
+ return tmp;
+ }
+
+ /// \brief Return a \ref GraphWriter class
+ ///
+ /// This function just returns a \ref GraphWriter class.
+ /// \relates GraphWriter
+ /// \sa graphWriter(const TGR& graph, std::ostream& os)
+ template <typename TGR>
+ GraphWriter<TGR> graphWriter(const TGR& graph, const std::string& fn) {
+ GraphWriter<TGR> tmp(graph, fn);
+ return tmp;
+ }
+
+ /// \brief Return a \ref GraphWriter class
+ ///
+ /// This function just returns a \ref GraphWriter class.
+ /// \relates GraphWriter
+ /// \sa graphWriter(const TGR& graph, std::ostream& os)
+ template <typename TGR>
+ GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn) {
+ GraphWriter<TGR> tmp(graph, fn);
+ return tmp;
+ }
+
+ template <typename BGR>
+ class BpGraphWriter;
+
+ template <typename TBGR>
+ BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
+ std::ostream& os = std::cout);
+ template <typename TBGR>
+ BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const std::string& fn);
+ template <typename TBGR>
+ BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char* fn);
+
+ /// \ingroup lemon_io
+ ///
+ /// \brief \ref lgf-format "LGF" writer for undirected bipartite graphs
+ ///
+ /// This utility writes an \ref lgf-format "LGF" file.
+ ///
+ /// It can be used almost the same way as \c GraphWriter, but it
+ /// reads the red and blue nodes from separate sections, and these
+ /// sections can contain different set of maps.
+ ///
+ /// The red and blue node maps are written to the corresponding
+ /// sections. The node maps are written to both of these sections
+ /// with the same map name.
+ template <typename BGR>
+ class BpGraphWriter {
+ public:
+
+ typedef BGR BpGraph;
+ TEMPLATE_BPGRAPH_TYPEDEFS(BGR);
+
+ private:
+
+
+ std::ostream* _os;
+ bool local_os;
+
+ const BGR& _graph;
+
+ std::string _nodes_caption;
+ std::string _edges_caption;
+ std::string _attributes_caption;
+
+ typedef std::map<Node, std::string> RedNodeIndex;
+ RedNodeIndex _red_node_index;
+ typedef std::map<Node, std::string> BlueNodeIndex;
+ BlueNodeIndex _blue_node_index;
+ typedef std::map<Edge, std::string> EdgeIndex;
+ EdgeIndex _edge_index;
+
+ typedef std::vector<std::pair<std::string,
+ _writer_bits::MapStorageBase<RedNode>* > > RedNodeMaps;
+ RedNodeMaps _red_node_maps;
+ typedef std::vector<std::pair<std::string,
+ _writer_bits::MapStorageBase<BlueNode>* > > BlueNodeMaps;
+ BlueNodeMaps _blue_node_maps;
+
+ typedef std::vector<std::pair<std::string,
+ _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
+ EdgeMaps _edge_maps;
+
+ typedef std::vector<std::pair<std::string,
+ _writer_bits::ValueStorageBase*> > Attributes;
+ Attributes _attributes;
+
+ bool _skip_nodes;
+ bool _skip_edges;
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Construct a bipartite graph writer, which writes to the given
+ /// output stream.
+ BpGraphWriter(const BGR& graph, std::ostream& os = std::cout)
+ : _os(&os), local_os(false), _graph(graph),
+ _skip_nodes(false), _skip_edges(false) {}
+
+ /// \brief Constructor
+ ///
+ /// Construct a bipartite graph writer, which writes to the given
+ /// output file.
+ BpGraphWriter(const BGR& graph, const std::string& fn)
+ : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
+ _skip_nodes(false), _skip_edges(false) {
+ if (!(*_os)) {
+ delete _os;
+ throw IoError("Cannot write file", fn);
+ }
+ }
+
+ /// \brief Constructor
+ ///
+ /// Construct a bipartite graph writer, which writes to the given
+ /// output file.
+ BpGraphWriter(const BGR& graph, const char* fn)
+ : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
+ _skip_nodes(false), _skip_edges(false) {
+ if (!(*_os)) {
+ delete _os;
+ throw IoError("Cannot write file", fn);
+ }
+ }
+
+ /// \brief Destructor
+ ~BpGraphWriter() {
+ for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
+ it != _red_node_maps.end(); ++it) {
+ delete it->second;
+ }
+
+ for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
+ it != _blue_node_maps.end(); ++it) {
+ delete it->second;
+ }
+
+ for (typename EdgeMaps::iterator it = _edge_maps.begin();
+ it != _edge_maps.end(); ++it) {
+ delete it->second;
+ }
+
+ for (typename Attributes::iterator it = _attributes.begin();
+ it != _attributes.end(); ++it) {
+ delete it->second;
+ }
+
+ if (local_os) {
+ delete _os;
+ }
+ }
+
+ private:
+
+ template <typename TBGR>
+ friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
+ std::ostream& os);
+ template <typename TBGR>
+ friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
+ const std::string& fn);
+ template <typename TBGR>
+ friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char *fn);
+
+ BpGraphWriter(BpGraphWriter& other)
+ : _os(other._os), local_os(other.local_os), _graph(other._graph),
+ _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
+
+ other._os = 0;
+ other.local_os = false;
+
+ _red_node_index.swap(other._red_node_index);
+ _blue_node_index.swap(other._blue_node_index);
+ _edge_index.swap(other._edge_index);
+
+ _red_node_maps.swap(other._red_node_maps);
+ _blue_node_maps.swap(other._blue_node_maps);
+ _edge_maps.swap(other._edge_maps);
+ _attributes.swap(other._attributes);
+
+ _nodes_caption = other._nodes_caption;
+ _edges_caption = other._edges_caption;
+ _attributes_caption = other._attributes_caption;
+ }
+
+ BpGraphWriter& operator=(const BpGraphWriter&);
+
+ public:
+
+ /// \name Writing Rules
+ /// @{
+
+ /// \brief Node map writing rule
+ ///
+ /// Add a node map writing rule to the writer.
+ template <typename Map>
+ BpGraphWriter& nodeMap(const std::string& caption, const Map& map) {
+ checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<RedNode>* red_storage =
+ new _writer_bits::MapStorage<RedNode, Map>(map);
+ _red_node_maps.push_back(std::make_pair(caption, red_storage));
+ _writer_bits::MapStorageBase<BlueNode>* blue_storage =
+ new _writer_bits::MapStorage<BlueNode, Map>(map);
+ _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
+ return *this;
+ }
+
+ /// \brief Node map writing rule
+ ///
+ /// Add a node map writing rule with specialized converter to the
+ /// writer.
+ template <typename Map, typename Converter>
+ BpGraphWriter& nodeMap(const std::string& caption, const Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<RedNode>* red_storage =
+ new _writer_bits::MapStorage<RedNode, Map, Converter>(map, converter);
+ _red_node_maps.push_back(std::make_pair(caption, red_storage));
+ _writer_bits::MapStorageBase<BlueNode>* blue_storage =
+ new _writer_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
+ _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
+ return *this;
+ }
+
+ /// \brief Red node map writing rule
+ ///
+ /// Add a red node map writing rule to the writer.
+ template <typename Map>
+ BpGraphWriter& redNodeMap(const std::string& caption, const Map& map) {
+ checkConcept<concepts::ReadMap<RedNode, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<RedNode>* storage =
+ new _writer_bits::MapStorage<RedNode, Map>(map);
+ _red_node_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Red node map writing rule
+ ///
+ /// Add a red node map writing rule with specialized converter to the
+ /// writer.
+ template <typename Map, typename Converter>
+ BpGraphWriter& redNodeMap(const std::string& caption, const Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::ReadMap<RedNode, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<RedNode>* storage =
+ new _writer_bits::MapStorage<RedNode, Map, Converter>(map, converter);
+ _red_node_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Blue node map writing rule
+ ///
+ /// Add a blue node map writing rule to the writer.
+ template <typename Map>
+ BpGraphWriter& blueNodeMap(const std::string& caption, const Map& map) {
+ checkConcept<concepts::ReadMap<BlueNode, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<BlueNode>* storage =
+ new _writer_bits::MapStorage<BlueNode, Map>(map);
+ _blue_node_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Blue node map writing rule
+ ///
+ /// Add a blue node map writing rule with specialized converter to the
+ /// writer.
+ template <typename Map, typename Converter>
+ BpGraphWriter& blueNodeMap(const std::string& caption, const Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::ReadMap<BlueNode, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<BlueNode>* storage =
+ new _writer_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
+ _blue_node_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Edge map writing rule
+ ///
+ /// Add an edge map writing rule to the writer.
+ template <typename Map>
+ BpGraphWriter& edgeMap(const std::string& caption, const Map& map) {
+ checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<Edge>* storage =
+ new _writer_bits::MapStorage<Edge, Map>(map);
+ _edge_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Edge map writing rule
+ ///
+ /// Add an edge map writing rule with specialized converter to the
+ /// writer.
+ template <typename Map, typename Converter>
+ BpGraphWriter& edgeMap(const std::string& caption, const Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<Edge>* storage =
+ new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
+ _edge_maps.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Arc map writing rule
+ ///
+ /// Add an arc map writing rule to the writer.
+ template <typename Map>
+ BpGraphWriter& arcMap(const std::string& caption, const Map& map) {
+ checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<Edge>* forward_storage =
+ new _writer_bits::GraphArcMapStorage<BGR, true, Map>(_graph, map);
+ _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
+ _writer_bits::MapStorageBase<Edge>* backward_storage =
+ new _writer_bits::GraphArcMapStorage<BGR, false, Map>(_graph, map);
+ _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
+ return *this;
+ }
+
+ /// \brief Arc map writing rule
+ ///
+ /// Add an arc map writing rule with specialized converter to the
+ /// writer.
+ template <typename Map, typename Converter>
+ BpGraphWriter& arcMap(const std::string& caption, const Map& map,
+ const Converter& converter = Converter()) {
+ checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
+ _writer_bits::MapStorageBase<Edge>* forward_storage =
+ new _writer_bits::GraphArcMapStorage<BGR, true, Map, Converter>
+ (_graph, map, converter);
+ _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
+ _writer_bits::MapStorageBase<Edge>* backward_storage =
+ new _writer_bits::GraphArcMapStorage<BGR, false, Map, Converter>
+ (_graph, map, converter);
+ _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
+ return *this;
+ }
+
+ /// \brief Attribute writing rule
+ ///
+ /// Add an attribute writing rule to the writer.
+ template <typename Value>
+ BpGraphWriter& attribute(const std::string& caption, const Value& value) {
+ _writer_bits::ValueStorageBase* storage =
+ new _writer_bits::ValueStorage<Value>(value);
+ _attributes.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Attribute writing rule
+ ///
+ /// Add an attribute writing rule with specialized converter to the
+ /// writer.
+ template <typename Value, typename Converter>
+ BpGraphWriter& attribute(const std::string& caption, const Value& value,
+ const Converter& converter = Converter()) {
+ _writer_bits::ValueStorageBase* storage =
+ new _writer_bits::ValueStorage<Value, Converter>(value, converter);
+ _attributes.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Node writing rule
+ ///
+ /// Add a node writing rule to the writer.
+ BpGraphWriter& node(const std::string& caption, const Node& node) {
+ typedef _writer_bits::DoubleMapLookUpConverter<
+ Node, RedNodeIndex, BlueNodeIndex> Converter;
+ Converter converter(_red_node_index, _blue_node_index);
+ _writer_bits::ValueStorageBase* storage =
+ new _writer_bits::ValueStorage<Node, Converter>(node, converter);
+ _attributes.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Red node writing rule
+ ///
+ /// Add a red node writing rule to the writer.
+ BpGraphWriter& redNode(const std::string& caption, const RedNode& node) {
+ typedef _writer_bits::MapLookUpConverter<Node> Converter;
+ Converter converter(_red_node_index);
+ _writer_bits::ValueStorageBase* storage =
+ new _writer_bits::ValueStorage<Node, Converter>(node, converter);
+ _attributes.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Blue node writing rule
+ ///
+ /// Add a blue node writing rule to the writer.
+ BpGraphWriter& blueNode(const std::string& caption, const BlueNode& node) {
+ typedef _writer_bits::MapLookUpConverter<Node> Converter;
+ Converter converter(_blue_node_index);
+ _writer_bits::ValueStorageBase* storage =
+ new _writer_bits::ValueStorage<Node, Converter>(node, converter);
+ _attributes.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Edge writing rule
+ ///
+ /// Add an edge writing rule to writer.
+ BpGraphWriter& edge(const std::string& caption, const Edge& edge) {
+ typedef _writer_bits::MapLookUpConverter<Edge> Converter;
+ Converter converter(_edge_index);
+ _writer_bits::ValueStorageBase* storage =
+ new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
+ _attributes.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \brief Arc writing rule
+ ///
+ /// Add an arc writing rule to writer.
+ BpGraphWriter& arc(const std::string& caption, const Arc& arc) {
+ typedef _writer_bits::GraphArcLookUpConverter<BGR> Converter;
+ Converter converter(_graph, _edge_index);
+ _writer_bits::ValueStorageBase* storage =
+ new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
+ _attributes.push_back(std::make_pair(caption, storage));
+ return *this;
+ }
+
+ /// \name Section Captions
+ /// @{
+
+ /// \brief Add an additional caption to the \c \@red_nodes and
+ /// \c \@blue_nodes section
+ ///
+ /// Add an additional caption to the \c \@red_nodes and \c
+ /// \@blue_nodes section.
+ BpGraphWriter& nodes(const std::string& caption) {
+ _nodes_caption = caption;
+ return *this;
+ }
+
+ /// \brief Add an additional caption to the \c \@edges section
+ ///
+ /// Add an additional caption to the \c \@edges section.
+ BpGraphWriter& edges(const std::string& caption) {
+ _edges_caption = caption;
+ return *this;
+ }
+
+ /// \brief Add an additional caption to the \c \@attributes section
+ ///
+ /// Add an additional caption to the \c \@attributes section.
+ BpGraphWriter& attributes(const std::string& caption) {
+ _attributes_caption = caption;
+ return *this;
+ }
+
+ /// \name Skipping Section
+ /// @{
+
+ /// \brief Skip writing the node set
+ ///
+ /// The \c \@red_nodes and \c \@blue_nodes section will not be
+ /// written to the stream.
+ BpGraphWriter& skipNodes() {
+ LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
+ _skip_nodes = true;
+ return *this;
+ }
+
+ /// \brief Skip writing edge set
+ ///
+ /// The \c \@edges section will not be written to the stream.
+ BpGraphWriter& skipEdges() {
+ LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
+ _skip_edges = true;
+ return *this;
+ }
+
+ /// @}
+
+ private:
+
+ void writeRedNodes() {
+ _writer_bits::MapStorageBase<RedNode>* label = 0;
+ for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
+ it != _red_node_maps.end(); ++it) {
+ if (it->first == "label") {
+ label = it->second;
+ break;
+ }
+ }
+
+ *_os << "@red_nodes";
+ if (!_nodes_caption.empty()) {
+ _writer_bits::writeToken(*_os << ' ', _nodes_caption);
+ }
+ *_os << std::endl;
+
+ if (label == 0) {
+ *_os << "label" << '\t';
+ }
+ for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
+ it != _red_node_maps.end(); ++it) {
+ _writer_bits::writeToken(*_os, it->first) << '\t';
+ }
+ *_os << std::endl;
+
+ std::vector<RedNode> nodes;
+ for (RedNodeIt n(_graph); n != INVALID; ++n) {
+ nodes.push_back(n);
+ }
+
+ if (label == 0) {
+ IdMap<BGR, Node> id_map(_graph);
+ _writer_bits::MapLess<IdMap<BGR, Node> > id_less(id_map);
+ std::sort(nodes.begin(), nodes.end(), id_less);
+ } else {
+ label->sort(nodes);
+ }
+
+ for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
+ RedNode n = nodes[i];
+ if (label == 0) {
+ std::ostringstream os;
+ os << _graph.id(static_cast<Node>(n));
+ _writer_bits::writeToken(*_os, os.str());
+ *_os << '\t';
+ _red_node_index.insert(std::make_pair(n, os.str()));
+ }
+ for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
+ it != _red_node_maps.end(); ++it) {
+ std::string value = it->second->get(n);
+ _writer_bits::writeToken(*_os, value);
+ if (it->first == "label") {
+ _red_node_index.insert(std::make_pair(n, value));
+ }
+ *_os << '\t';
+ }
+ *_os << std::endl;
+ }
+ }
+
+ void writeBlueNodes() {
+ _writer_bits::MapStorageBase<BlueNode>* label = 0;
+ for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
+ it != _blue_node_maps.end(); ++it) {
+ if (it->first == "label") {
+ label = it->second;
+ break;
+ }
+ }
+
+ *_os << "@blue_nodes";
+ if (!_nodes_caption.empty()) {
+ _writer_bits::writeToken(*_os << ' ', _nodes_caption);
+ }
+ *_os << std::endl;
+
+ if (label == 0) {
+ *_os << "label" << '\t';
+ }
+ for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
+ it != _blue_node_maps.end(); ++it) {
+ _writer_bits::writeToken(*_os, it->first) << '\t';
+ }
+ *_os << std::endl;
+
+ std::vector<BlueNode> nodes;
+ for (BlueNodeIt n(_graph); n != INVALID; ++n) {
+ nodes.push_back(n);
+ }
+
+ if (label == 0) {
+ IdMap<BGR, Node> id_map(_graph);
+ _writer_bits::MapLess<IdMap<BGR, Node> > id_less(id_map);
+ std::sort(nodes.begin(), nodes.end(), id_less);
+ } else {
+ label->sort(nodes);
+ }
+
+ for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
+ BlueNode n = nodes[i];
+ if (label == 0) {
+ std::ostringstream os;
+ os << _graph.id(static_cast<Node>(n));
+ _writer_bits::writeToken(*_os, os.str());
+ *_os << '\t';
+ _blue_node_index.insert(std::make_pair(n, os.str()));
+ }
+ for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
+ it != _blue_node_maps.end(); ++it) {
+ std::string value = it->second->get(n);
+ _writer_bits::writeToken(*_os, value);
+ if (it->first == "label") {
+ _blue_node_index.insert(std::make_pair(n, value));
+ }
+ *_os << '\t';
+ }
+ *_os << std::endl;
+ }
+ }
+
+ void createRedNodeIndex() {
+ _writer_bits::MapStorageBase<RedNode>* label = 0;
+ for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
+ it != _red_node_maps.end(); ++it) {
+ if (it->first == "label") {
+ label = it->second;
+ break;
+ }
+ }
+
+ if (label == 0) {
+ for (RedNodeIt n(_graph); n != INVALID; ++n) {
+ std::ostringstream os;
+ os << _graph.id(n);
+ _red_node_index.insert(std::make_pair(n, os.str()));
+ }
+ } else {
+ for (RedNodeIt n(_graph); n != INVALID; ++n) {
+ std::string value = label->get(n);
+ _red_node_index.insert(std::make_pair(n, value));
+ }
+ }
+ }
+
+ void createBlueNodeIndex() {
+ _writer_bits::MapStorageBase<BlueNode>* label = 0;
+ for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
+ it != _blue_node_maps.end(); ++it) {
+ if (it->first == "label") {
+ label = it->second;
+ break;
+ }
+ }
+
+ if (label == 0) {
+ for (BlueNodeIt n(_graph); n != INVALID; ++n) {
+ std::ostringstream os;
+ os << _graph.id(n);
+ _blue_node_index.insert(std::make_pair(n, os.str()));
+ }
+ } else {
+ for (BlueNodeIt n(_graph); n != INVALID; ++n) {
+ std::string value = label->get(n);
+ _blue_node_index.insert(std::make_pair(n, value));
+ }
+ }
+ }
+
+ void writeEdges() {
+ _writer_bits::MapStorageBase<Edge>* label = 0;
+ for (typename EdgeMaps::iterator it = _edge_maps.begin();
+ it != _edge_maps.end(); ++it) {
+ if (it->first == "label") {
+ label = it->second;
+ break;
+ }
+ }
+
+ *_os << "@edges";
+ if (!_edges_caption.empty()) {
+ _writer_bits::writeToken(*_os << ' ', _edges_caption);
+ }
+ *_os << std::endl;
+
+ *_os << '\t' << '\t';
+ if (label == 0) {
+ *_os << "label" << '\t';
+ }
+ for (typename EdgeMaps::iterator it = _edge_maps.begin();
+ it != _edge_maps.end(); ++it) {
+ _writer_bits::writeToken(*_os, it->first) << '\t';
+ }
+ *_os << std::endl;
+
+ std::vector<Edge> edges;
+ for (EdgeIt n(_graph); n != INVALID; ++n) {
+ edges.push_back(n);
+ }
+
+ if (label == 0) {
+ IdMap<BGR, Edge> id_map(_graph);
+ _writer_bits::MapLess<IdMap<BGR, Edge> > id_less(id_map);
+ std::sort(edges.begin(), edges.end(), id_less);
+ } else {
+ label->sort(edges);
+ }
+
+ for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
+ Edge e = edges[i];
+ _writer_bits::writeToken(*_os, _red_node_index.
+ find(_graph.redNode(e))->second);
+ *_os << '\t';
+ _writer_bits::writeToken(*_os, _blue_node_index.
+ find(_graph.blueNode(e))->second);
+ *_os << '\t';
+ if (label == 0) {
+ std::ostringstream os;
+ os << _graph.id(e);
+ _writer_bits::writeToken(*_os, os.str());
+ *_os << '\t';
+ _edge_index.insert(std::make_pair(e, os.str()));
+ }
+ for (typename EdgeMaps::iterator it = _edge_maps.begin();
+ it != _edge_maps.end(); ++it) {
+ std::string value = it->second->get(e);
+ _writer_bits::writeToken(*_os, value);
+ if (it->first == "label") {
+ _edge_index.insert(std::make_pair(e, value));
+ }
+ *_os << '\t';
+ }
+ *_os << std::endl;
+ }
+ }
+
+ void createEdgeIndex() {
+ _writer_bits::MapStorageBase<Edge>* label = 0;
+ for (typename EdgeMaps::iterator it = _edge_maps.begin();
+ it != _edge_maps.end(); ++it) {
+ if (it->first == "label") {
+ label = it->second;
+ break;
+ }
+ }
+
+ if (label == 0) {
+ for (EdgeIt e(_graph); e != INVALID; ++e) {
+ std::ostringstream os;
+ os << _graph.id(e);
+ _edge_index.insert(std::make_pair(e, os.str()));
+ }
+ } else {
+ for (EdgeIt e(_graph); e != INVALID; ++e) {
+ std::string value = label->get(e);
+ _edge_index.insert(std::make_pair(e, value));
+ }
+ }
+ }
+
+ void writeAttributes() {
+ if (_attributes.empty()) return;
+ *_os << "@attributes";
+ if (!_attributes_caption.empty()) {
+ _writer_bits::writeToken(*_os << ' ', _attributes_caption);
+ }
+ *_os << std::endl;
+ for (typename Attributes::iterator it = _attributes.begin();
+ it != _attributes.end(); ++it) {
+ _writer_bits::writeToken(*_os, it->first) << ' ';
+ _writer_bits::writeToken(*_os, it->second->get());
+ *_os << std::endl;
+ }
+ }
+
+ public:
+
+ /// \name Execution of the Writer
+ /// @{
+
+ /// \brief Start the batch processing
+ ///
+ /// This function starts the batch processing.
+ void run() {
+ if (!_skip_nodes) {
+ writeRedNodes();
+ writeBlueNodes();
+ } else {
+ createRedNodeIndex();
+ createBlueNodeIndex();
+ }
+ if (!_skip_edges) {
+ writeEdges();
+ } else {
+ createEdgeIndex();
+ }
+ writeAttributes();
+ }
+
+ /// \brief Give back the stream of the writer
+ ///
+ /// Give back the stream of the writer
+ std::ostream& ostream() {
+ return *_os;
+ }
+
+ /// @}
+ };
+
+ /// \ingroup lemon_io
+ ///
+ /// \brief Return a \ref lemon::BpGraphWriter "BpGraphWriter" class
+ ///
+ /// This function just returns a \ref lemon::BpGraphWriter
+ /// "BpGraphWriter" class.
+ ///
+ /// With this function a bipartite graph can be write to a file or output
+ /// stream in \ref lgf-format "LGF" format with several maps and
+ /// attributes. For example, with the following code a bipartite
+ /// weighted matching problem can be written to the standard output,
+ /// i.e. a graph with a \e weight map on the edges:
+ ///
+ ///\code
+ ///ListBpGraph graph;
+ ///ListBpGraph::EdgeMap<int> weight(graph);
+ /// // Setting the weight map
+ ///bpGraphWriter(graph, std::cout).
+ /// edgeMap("weight", weight).
+ /// run();
+ ///\endcode
+ ///
+ /// For a complete documentation, please see the
+ /// \ref lemon::BpGraphWriter "BpGraphWriter"
+ /// class documentation.
+ /// \warning Don't forget to put the \ref lemon::BpGraphWriter::run() "run()"
+ /// to the end of the parameter list.
+ /// \relates BpGraphWriter
+ /// \sa bpGraphWriter(const TBGR& graph, const std::string& fn)
+ /// \sa bpGraphWriter(const TBGR& graph, const char* fn)
+ template <typename TBGR>
+ BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, std::ostream& os) {
+ BpGraphWriter<TBGR> tmp(graph, os);
+ return tmp;
+ }
+
+ /// \brief Return a \ref BpGraphWriter class
+ ///
+ /// This function just returns a \ref BpGraphWriter class.
+ /// \relates BpGraphWriter
+ /// \sa graphWriter(const TBGR& graph, std::ostream& os)
+ template <typename TBGR>
+ BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const std::string& fn) {
+ BpGraphWriter<TBGR> tmp(graph, fn);
+ return tmp;
+ }
+
+ /// \brief Return a \ref BpGraphWriter class
+ ///
+ /// This function just returns a \ref BpGraphWriter class.
+ /// \relates BpGraphWriter
+ /// \sa graphWriter(const TBGR& graph, std::ostream& os)
+ template <typename TBGR>
+ BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char* fn) {
+ BpGraphWriter<TBGR> tmp(graph, fn);
+ return tmp;
+ }
+
+ class SectionWriter;
+
+ SectionWriter sectionWriter(std::istream& is);
+ SectionWriter sectionWriter(const std::string& fn);
+ SectionWriter sectionWriter(const char* fn);
+
+ /// \ingroup lemon_io
+ ///
+ /// \brief Section writer class
+ ///
+ /// In the \ref lgf-format "LGF" file extra sections can be placed,
+ /// which contain any data in arbitrary format. Such sections can be
+ /// written with this class. A writing rule can be added to the
+ /// class with two different functions. With the \c sectionLines()
+ /// function a generator can write the section line-by-line, while
+ /// with the \c sectionStream() member the section can be written to
+ /// an output stream.
+ class SectionWriter {
+ private:
+
+ std::ostream* _os;
+ bool local_os;
+
+ typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
+ Sections;
+
+ Sections _sections;
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Construct a section writer, which writes to the given output
+ /// stream.
+ SectionWriter(std::ostream& os)
+ : _os(&os), local_os(false) {}
+
+ /// \brief Constructor
+ ///
+ /// Construct a section writer, which writes into the given file.
+ SectionWriter(const std::string& fn)
+ : _os(new std::ofstream(fn.c_str())), local_os(true) {
+ if (!(*_os)) {
+ delete _os;
+ throw IoError("Cannot write file", fn);
+ }
+ }
+
+ /// \brief Constructor
+ ///
+ /// Construct a section writer, which writes into the given file.
+ SectionWriter(const char* fn)
+ : _os(new std::ofstream(fn)), local_os(true) {
+ if (!(*_os)) {
+ delete _os;
+ throw IoError("Cannot write file", fn);
+ }
+ }
+
+ /// \brief Destructor
+ ~SectionWriter() {
+ for (Sections::iterator it = _sections.begin();
+ it != _sections.end(); ++it) {
+ delete it->second;
+ }
+
+ if (local_os) {
+ delete _os;
+ }
+
+ }
+
+ private:
+
+ friend SectionWriter sectionWriter(std::ostream& os);
+ friend SectionWriter sectionWriter(const std::string& fn);
+ friend SectionWriter sectionWriter(const char* fn);
+
+ SectionWriter(SectionWriter& other)
+ : _os(other._os), local_os(other.local_os) {
+
+ other._os = 0;
+ other.local_os = false;
+
+ _sections.swap(other._sections);
+ }
+
+ SectionWriter& operator=(const SectionWriter&);
+
+ public:
+
+ /// \name Section Writers
+ /// @{
+
+ /// \brief Add a section writer with line oriented writing
+ ///
+ /// The first parameter is the type descriptor of the section, the
+ /// second is a generator with std::string values. At the writing
+ /// process, the returned \c std::string will be written into the
+ /// output file until it is an empty string.
+ ///
+ /// For example, an integer vector is written into a section.
+ ///\code
+ /// @numbers
+ /// 12 45 23 78
+ /// 4 28 38 28
+ /// 23 6 16
+ ///\endcode
+ ///
+ /// The generator is implemented as a struct.
+ ///\code
+ /// struct NumberSection {
+ /// std::vector<int>::const_iterator _it, _end;
+ /// NumberSection(const std::vector<int>& data)
+ /// : _it(data.begin()), _end(data.end()) {}
+ /// std::string operator()() {
+ /// int rem_in_line = 4;
+ /// std::ostringstream ls;
+ /// while (rem_in_line > 0 && _it != _end) {
+ /// ls << *(_it++) << ' ';
+ /// --rem_in_line;
+ /// }
+ /// return ls.str();
+ /// }
+ /// };
+ ///
+ /// // ...
+ ///
+ /// writer.sectionLines("numbers", NumberSection(vec));
+ ///\endcode
+ template <typename Functor>
+ SectionWriter& sectionLines(const std::string& type, Functor functor) {
+ LEMON_ASSERT(!type.empty(), "Type is empty.");
+ _sections.push_back(std::make_pair(type,
+ new _writer_bits::LineSection<Functor>(functor)));
+ return *this;
+ }
+
+
+ /// \brief Add a section writer with stream oriented writing
+ ///
+ /// The first parameter is the type of the section, the second is
+ /// a functor, which takes a \c std::ostream& parameter. The
+ /// functor writes the section to the output stream.
+ /// \warning The last line must be closed with end-line character.
+ template <typename Functor>
+ SectionWriter& sectionStream(const std::string& type, Functor functor) {
+ LEMON_ASSERT(!type.empty(), "Type is empty.");
+ _sections.push_back(std::make_pair(type,
+ new _writer_bits::StreamSection<Functor>(functor)));
+ return *this;
+ }
+
+ /// @}
+
+ public:
+
+
+ /// \name Execution of the Writer
+ /// @{
+
+ /// \brief Start the batch processing
+ ///
+ /// This function starts the batch processing.
+ void run() {
+
+ LEMON_ASSERT(_os != 0, "This writer is assigned to an other writer");
+
+ for (Sections::iterator it = _sections.begin();
+ it != _sections.end(); ++it) {
+ (*_os) << '@' << it->first << std::endl;
+ it->second->process(*_os);
+ }
+ }
+
+ /// \brief Give back the stream of the writer
+ ///
+ /// Returns the stream of the writer
+ std::ostream& ostream() {
+ return *_os;
+ }
+
+ /// @}
+
+ };
+
+ /// \ingroup lemon_io
+ ///
+ /// \brief Return a \ref SectionWriter class
+ ///
+ /// This function just returns a \ref SectionWriter class.
+ ///
+ /// Please see SectionWriter documentation about the custom section
+ /// output.
+ ///
+ /// \relates SectionWriter
+ /// \sa sectionWriter(const std::string& fn)
+ /// \sa sectionWriter(const char *fn)
+ inline SectionWriter sectionWriter(std::ostream& os) {
+ SectionWriter tmp(os);
+ return tmp;
+ }
+
+ /// \brief Return a \ref SectionWriter class
+ ///
+ /// This function just returns a \ref SectionWriter class.
+ /// \relates SectionWriter
+ /// \sa sectionWriter(std::ostream& os)
+ inline SectionWriter sectionWriter(const std::string& fn) {
+ SectionWriter tmp(fn);
+ return tmp;
+ }
+
+ /// \brief Return a \ref SectionWriter class
+ ///
+ /// This function just returns a \ref SectionWriter class.
+ /// \relates SectionWriter
+ /// \sa sectionWriter(std::ostream& os)
+ inline SectionWriter sectionWriter(const char* fn) {
+ SectionWriter tmp(fn);
+ return tmp;
+ }
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/list_graph.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/list_graph.h
new file mode 100644
index 00000000000..2a236cf91de
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/list_graph.h
@@ -0,0 +1,2510 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_LIST_GRAPH_H
+#define LEMON_LIST_GRAPH_H
+
+///\ingroup graphs
+///\file
+///\brief ListDigraph and ListGraph classes.
+
+#include <lemon/core.h>
+#include <lemon/error.h>
+#include <lemon/bits/graph_extender.h>
+
+#include <vector>
+#include <list>
+
+namespace lemon {
+
+ class ListDigraph;
+
+ class ListDigraphBase {
+
+ protected:
+ struct NodeT {
+ int first_in, first_out;
+ int prev, next;
+ };
+
+ struct ArcT {
+ int target, source;
+ int prev_in, prev_out;
+ int next_in, next_out;
+ };
+
+ std::vector<NodeT> nodes;
+
+ int first_node;
+
+ int first_free_node;
+
+ std::vector<ArcT> arcs;
+
+ int first_free_arc;
+
+ public:
+
+ typedef ListDigraphBase Digraph;
+
+ class Node {
+ friend class ListDigraphBase;
+ friend class ListDigraph;
+ protected:
+
+ int id;
+ explicit Node(int pid) { id = pid;}
+
+ public:
+ Node() {}
+ Node (Invalid) { id = -1; }
+ bool operator==(const Node& node) const {return id == node.id;}
+ bool operator!=(const Node& node) const {return id != node.id;}
+ bool operator<(const Node& node) const {return id < node.id;}
+ };
+
+ class Arc {
+ friend class ListDigraphBase;
+ friend class ListDigraph;
+ protected:
+
+ int id;
+ explicit Arc(int pid) { id = pid;}
+
+ public:
+ Arc() {}
+ Arc (Invalid) { id = -1; }
+ bool operator==(const Arc& arc) const {return id == arc.id;}
+ bool operator!=(const Arc& arc) const {return id != arc.id;}
+ bool operator<(const Arc& arc) const {return id < arc.id;}
+ };
+
+
+
+ ListDigraphBase()
+ : nodes(), first_node(-1),
+ first_free_node(-1), arcs(), first_free_arc(-1) {}
+
+
+ int maxNodeId() const { return nodes.size()-1; }
+ int maxArcId() const { return arcs.size()-1; }
+
+ Node source(Arc e) const { return Node(arcs[e.id].source); }
+ Node target(Arc e) const { return Node(arcs[e.id].target); }
+
+
+ void first(Node& node) const {
+ node.id = first_node;
+ }
+
+ void next(Node& node) const {
+ node.id = nodes[node.id].next;
+ }
+
+
+ void first(Arc& arc) const {
+ int n;
+ for(n = first_node;
+ n != -1 && nodes[n].first_out == -1;
+ n = nodes[n].next) {}
+ arc.id = (n == -1) ? -1 : nodes[n].first_out;
+ }
+
+ void next(Arc& arc) const {
+ if (arcs[arc.id].next_out != -1) {
+ arc.id = arcs[arc.id].next_out;
+ } else {
+ int n;
+ for(n = nodes[arcs[arc.id].source].next;
+ n != -1 && nodes[n].first_out == -1;
+ n = nodes[n].next) {}
+ arc.id = (n == -1) ? -1 : nodes[n].first_out;
+ }
+ }
+
+ void firstOut(Arc &e, const Node& v) const {
+ e.id = nodes[v.id].first_out;
+ }
+ void nextOut(Arc &e) const {
+ e.id=arcs[e.id].next_out;
+ }
+
+ void firstIn(Arc &e, const Node& v) const {
+ e.id = nodes[v.id].first_in;
+ }
+ void nextIn(Arc &e) const {
+ e.id=arcs[e.id].next_in;
+ }
+
+
+ static int id(Node v) { return v.id; }
+ static int id(Arc e) { return e.id; }
+
+ static Node nodeFromId(int id) { return Node(id);}
+ static Arc arcFromId(int id) { return Arc(id);}
+
+ bool valid(Node n) const {
+ return n.id >= 0 && n.id < static_cast<int>(nodes.size()) &&
+ nodes[n.id].prev != -2;
+ }
+
+ bool valid(Arc a) const {
+ return a.id >= 0 && a.id < static_cast<int>(arcs.size()) &&
+ arcs[a.id].prev_in != -2;
+ }
+
+ Node addNode() {
+ int n;
+
+ if(first_free_node==-1) {
+ n = nodes.size();
+ nodes.push_back(NodeT());
+ } else {
+ n = first_free_node;
+ first_free_node = nodes[n].next;
+ }
+
+ nodes[n].next = first_node;
+ if(first_node != -1) nodes[first_node].prev = n;
+ first_node = n;
+ nodes[n].prev = -1;
+
+ nodes[n].first_in = nodes[n].first_out = -1;
+
+ return Node(n);
+ }
+
+ Arc addArc(Node u, Node v) {
+ int n;
+
+ if (first_free_arc == -1) {
+ n = arcs.size();
+ arcs.push_back(ArcT());
+ } else {
+ n = first_free_arc;
+ first_free_arc = arcs[n].next_in;
+ }
+
+ arcs[n].source = u.id;
+ arcs[n].target = v.id;
+
+ arcs[n].next_out = nodes[u.id].first_out;
+ if(nodes[u.id].first_out != -1) {
+ arcs[nodes[u.id].first_out].prev_out = n;
+ }
+
+ arcs[n].next_in = nodes[v.id].first_in;
+ if(nodes[v.id].first_in != -1) {
+ arcs[nodes[v.id].first_in].prev_in = n;
+ }
+
+ arcs[n].prev_in = arcs[n].prev_out = -1;
+
+ nodes[u.id].first_out = nodes[v.id].first_in = n;
+
+ return Arc(n);
+ }
+
+ void erase(const Node& node) {
+ int n = node.id;
+
+ if(nodes[n].next != -1) {
+ nodes[nodes[n].next].prev = nodes[n].prev;
+ }
+
+ if(nodes[n].prev != -1) {
+ nodes[nodes[n].prev].next = nodes[n].next;
+ } else {
+ first_node = nodes[n].next;
+ }
+
+ nodes[n].next = first_free_node;
+ first_free_node = n;
+ nodes[n].prev = -2;
+
+ }
+
+ void erase(const Arc& arc) {
+ int n = arc.id;
+
+ if(arcs[n].next_in!=-1) {
+ arcs[arcs[n].next_in].prev_in = arcs[n].prev_in;
+ }
+
+ if(arcs[n].prev_in!=-1) {
+ arcs[arcs[n].prev_in].next_in = arcs[n].next_in;
+ } else {
+ nodes[arcs[n].target].first_in = arcs[n].next_in;
+ }
+
+
+ if(arcs[n].next_out!=-1) {
+ arcs[arcs[n].next_out].prev_out = arcs[n].prev_out;
+ }
+
+ if(arcs[n].prev_out!=-1) {
+ arcs[arcs[n].prev_out].next_out = arcs[n].next_out;
+ } else {
+ nodes[arcs[n].source].first_out = arcs[n].next_out;
+ }
+
+ arcs[n].next_in = first_free_arc;
+ first_free_arc = n;
+ arcs[n].prev_in = -2;
+ }
+
+ void clear() {
+ arcs.clear();
+ nodes.clear();
+ first_node = first_free_node = first_free_arc = -1;
+ }
+
+ protected:
+ void changeTarget(Arc e, Node n)
+ {
+ if(arcs[e.id].next_in != -1)
+ arcs[arcs[e.id].next_in].prev_in = arcs[e.id].prev_in;
+ if(arcs[e.id].prev_in != -1)
+ arcs[arcs[e.id].prev_in].next_in = arcs[e.id].next_in;
+ else nodes[arcs[e.id].target].first_in = arcs[e.id].next_in;
+ if (nodes[n.id].first_in != -1) {
+ arcs[nodes[n.id].first_in].prev_in = e.id;
+ }
+ arcs[e.id].target = n.id;
+ arcs[e.id].prev_in = -1;
+ arcs[e.id].next_in = nodes[n.id].first_in;
+ nodes[n.id].first_in = e.id;
+ }
+ void changeSource(Arc e, Node n)
+ {
+ if(arcs[e.id].next_out != -1)
+ arcs[arcs[e.id].next_out].prev_out = arcs[e.id].prev_out;
+ if(arcs[e.id].prev_out != -1)
+ arcs[arcs[e.id].prev_out].next_out = arcs[e.id].next_out;
+ else nodes[arcs[e.id].source].first_out = arcs[e.id].next_out;
+ if (nodes[n.id].first_out != -1) {
+ arcs[nodes[n.id].first_out].prev_out = e.id;
+ }
+ arcs[e.id].source = n.id;
+ arcs[e.id].prev_out = -1;
+ arcs[e.id].next_out = nodes[n.id].first_out;
+ nodes[n.id].first_out = e.id;
+ }
+
+ };
+
+ typedef DigraphExtender<ListDigraphBase> ExtendedListDigraphBase;
+
+ /// \addtogroup graphs
+ /// @{
+
+ ///A general directed graph structure.
+
+ ///\ref ListDigraph is a versatile and fast directed graph
+ ///implementation based on linked lists that are stored in
+ ///\c std::vector structures.
+ ///
+ ///This type fully conforms to the \ref concepts::Digraph "Digraph concept"
+ ///and it also provides several useful additional functionalities.
+ ///Most of its member functions and nested classes are documented
+ ///only in the concept class.
+ ///
+ ///This class provides only linear time counting for nodes and arcs.
+ ///
+ ///\sa concepts::Digraph
+ ///\sa ListGraph
+ class ListDigraph : public ExtendedListDigraphBase {
+ typedef ExtendedListDigraphBase Parent;
+
+ private:
+ /// Digraphs are \e not copy constructible. Use DigraphCopy instead.
+ ListDigraph(const ListDigraph &) :ExtendedListDigraphBase() {};
+ /// \brief Assignment of a digraph to another one is \e not allowed.
+ /// Use DigraphCopy instead.
+ void operator=(const ListDigraph &) {}
+ public:
+
+ /// Constructor
+
+ /// Constructor.
+ ///
+ ListDigraph() {}
+
+ ///Add a new node to the digraph.
+
+ ///This function adds a new node to the digraph.
+ ///\return The new node.
+ Node addNode() { return Parent::addNode(); }
+
+ ///Add a new arc to the digraph.
+
+ ///This function adds a new arc to the digraph with source node \c s
+ ///and target node \c t.
+ ///\return The new arc.
+ Arc addArc(Node s, Node t) {
+ return Parent::addArc(s, t);
+ }
+
+ ///\brief Erase a node from the digraph.
+ ///
+ ///This function erases the given node along with its outgoing and
+ ///incoming arcs from the digraph.
+ ///
+ ///\note All iterators referencing the removed node or the connected
+ ///arcs are invalidated, of course.
+ void erase(Node n) { Parent::erase(n); }
+
+ ///\brief Erase an arc from the digraph.
+ ///
+ ///This function erases the given arc from the digraph.
+ ///
+ ///\note All iterators referencing the removed arc are invalidated,
+ ///of course.
+ void erase(Arc a) { Parent::erase(a); }
+
+ /// Node validity check
+
+ /// This function gives back \c true if the given node is valid,
+ /// i.e. it is a real node of the digraph.
+ ///
+ /// \warning A removed node could become valid again if new nodes are
+ /// added to the digraph.
+ bool valid(Node n) const { return Parent::valid(n); }
+
+ /// Arc validity check
+
+ /// This function gives back \c true if the given arc is valid,
+ /// i.e. it is a real arc of the digraph.
+ ///
+ /// \warning A removed arc could become valid again if new arcs are
+ /// added to the digraph.
+ bool valid(Arc a) const { return Parent::valid(a); }
+
+ /// Change the target node of an arc
+
+ /// This function changes the target node of the given arc \c a to \c n.
+ ///
+ ///\note \c ArcIt and \c OutArcIt iterators referencing the changed
+ ///arc remain valid, but \c InArcIt iterators are invalidated.
+ ///
+ ///\warning This functionality cannot be used together with the Snapshot
+ ///feature.
+ void changeTarget(Arc a, Node n) {
+ Parent::changeTarget(a,n);
+ }
+ /// Change the source node of an arc
+
+ /// This function changes the source node of the given arc \c a to \c n.
+ ///
+ ///\note \c InArcIt iterators referencing the changed arc remain
+ ///valid, but \c ArcIt and \c OutArcIt iterators are invalidated.
+ ///
+ ///\warning This functionality cannot be used together with the Snapshot
+ ///feature.
+ void changeSource(Arc a, Node n) {
+ Parent::changeSource(a,n);
+ }
+
+ /// Reverse the direction of an arc.
+
+ /// This function reverses the direction of the given arc.
+ ///\note \c ArcIt, \c OutArcIt and \c InArcIt iterators referencing
+ ///the changed arc are invalidated.
+ ///
+ ///\warning This functionality cannot be used together with the Snapshot
+ ///feature.
+ void reverseArc(Arc a) {
+ Node t=target(a);
+ changeTarget(a,source(a));
+ changeSource(a,t);
+ }
+
+ ///Contract two nodes.
+
+ ///This function contracts the given two nodes.
+ ///Node \c v is removed, but instead of deleting its
+ ///incident arcs, they are joined to node \c u.
+ ///If the last parameter \c r is \c true (this is the default value),
+ ///then the newly created loops are removed.
+ ///
+ ///\note The moved arcs are joined to node \c u using changeSource()
+ ///or changeTarget(), thus \c ArcIt and \c OutArcIt iterators are
+ ///invalidated for the outgoing arcs of node \c v and \c InArcIt
+ ///iterators are invalidated for the incoming arcs of \c v.
+ ///Moreover all iterators referencing node \c v or the removed
+ ///loops are also invalidated. Other iterators remain valid.
+ ///
+ ///\warning This functionality cannot be used together with the Snapshot
+ ///feature.
+ void contract(Node u, Node v, bool r = true)
+ {
+ for(OutArcIt e(*this,v);e!=INVALID;) {
+ OutArcIt f=e;
+ ++f;
+ if(r && target(e)==u) erase(e);
+ else changeSource(e,u);
+ e=f;
+ }
+ for(InArcIt e(*this,v);e!=INVALID;) {
+ InArcIt f=e;
+ ++f;
+ if(r && source(e)==u) erase(e);
+ else changeTarget(e,u);
+ e=f;
+ }
+ erase(v);
+ }
+
+ ///Split a node.
+
+ ///This function splits the given node. First, a new node is added
+ ///to the digraph, then the source of each outgoing arc of node \c n
+ ///is moved to this new node.
+ ///If the second parameter \c connect is \c true (this is the default
+ ///value), then a new arc from node \c n to the newly created node
+ ///is also added.
+ ///\return The newly created node.
+ ///
+ ///\note All iterators remain valid.
+ ///
+ ///\warning This functionality cannot be used together with the
+ ///Snapshot feature.
+ Node split(Node n, bool connect = true) {
+ Node b = addNode();
+ nodes[b.id].first_out=nodes[n.id].first_out;
+ nodes[n.id].first_out=-1;
+ for(int i=nodes[b.id].first_out; i!=-1; i=arcs[i].next_out) {
+ arcs[i].source=b.id;
+ }
+ if (connect) addArc(n,b);
+ return b;
+ }
+
+ ///Split an arc.
+
+ ///This function splits the given arc. First, a new node \c v is
+ ///added to the digraph, then the target node of the original arc
+ ///is set to \c v. Finally, an arc from \c v to the original target
+ ///is added.
+ ///\return The newly created node.
+ ///
+ ///\note \c InArcIt iterators referencing the original arc are
+ ///invalidated. Other iterators remain valid.
+ ///
+ ///\warning This functionality cannot be used together with the
+ ///Snapshot feature.
+ Node split(Arc a) {
+ Node v = addNode();
+ addArc(v,target(a));
+ changeTarget(a,v);
+ return v;
+ }
+
+ ///Clear the digraph.
+
+ ///This function erases all nodes and arcs from the digraph.
+ ///
+ ///\note All iterators of the digraph are invalidated, of course.
+ void clear() {
+ Parent::clear();
+ }
+
+ /// Reserve memory for nodes.
+
+ /// Using this function, it is possible to avoid superfluous memory
+ /// allocation: if you know that the digraph you want to build will
+ /// be large (e.g. it will contain millions of nodes and/or arcs),
+ /// then it is worth reserving space for this amount before starting
+ /// to build the digraph.
+ /// \sa reserveArc()
+ void reserveNode(int n) { nodes.reserve(n); };
+
+ /// Reserve memory for arcs.
+
+ /// Using this function, it is possible to avoid superfluous memory
+ /// allocation: if you know that the digraph you want to build will
+ /// be large (e.g. it will contain millions of nodes and/or arcs),
+ /// then it is worth reserving space for this amount before starting
+ /// to build the digraph.
+ /// \sa reserveNode()
+ void reserveArc(int m) { arcs.reserve(m); };
+
+ /// \brief Class to make a snapshot of the digraph and restore
+ /// it later.
+ ///
+ /// Class to make a snapshot of the digraph and restore it later.
+ ///
+ /// The newly added nodes and arcs can be removed using the
+ /// restore() function.
+ ///
+ /// \note After a state is restored, you cannot restore a later state,
+ /// i.e. you cannot add the removed nodes and arcs again using
+ /// another Snapshot instance.
+ ///
+ /// \warning Node and arc deletions and other modifications (e.g.
+ /// reversing, contracting, splitting arcs or nodes) cannot be
+ /// restored. These events invalidate the snapshot.
+ /// However, the arcs and nodes that were added to the digraph after
+ /// making the current snapshot can be removed without invalidating it.
+ class Snapshot {
+ protected:
+
+ typedef Parent::NodeNotifier NodeNotifier;
+
+ class NodeObserverProxy : public NodeNotifier::ObserverBase {
+ public:
+
+ NodeObserverProxy(Snapshot& _snapshot)
+ : snapshot(_snapshot) {}
+
+ using NodeNotifier::ObserverBase::attach;
+ using NodeNotifier::ObserverBase::detach;
+ using NodeNotifier::ObserverBase::attached;
+
+ protected:
+
+ virtual void add(const Node& node) {
+ snapshot.addNode(node);
+ }
+ virtual void add(const std::vector<Node>& nodes) {
+ for (int i = nodes.size() - 1; i >= 0; ++i) {
+ snapshot.addNode(nodes[i]);
+ }
+ }
+ virtual void erase(const Node& node) {
+ snapshot.eraseNode(node);
+ }
+ virtual void erase(const std::vector<Node>& nodes) {
+ for (int i = 0; i < int(nodes.size()); ++i) {
+ snapshot.eraseNode(nodes[i]);
+ }
+ }
+ virtual void build() {
+ Node node;
+ std::vector<Node> nodes;
+ for (notifier()->first(node); node != INVALID;
+ notifier()->next(node)) {
+ nodes.push_back(node);
+ }
+ for (int i = nodes.size() - 1; i >= 0; --i) {
+ snapshot.addNode(nodes[i]);
+ }
+ }
+ virtual void clear() {
+ Node node;
+ for (notifier()->first(node); node != INVALID;
+ notifier()->next(node)) {
+ snapshot.eraseNode(node);
+ }
+ }
+
+ Snapshot& snapshot;
+ };
+
+ class ArcObserverProxy : public ArcNotifier::ObserverBase {
+ public:
+
+ ArcObserverProxy(Snapshot& _snapshot)
+ : snapshot(_snapshot) {}
+
+ using ArcNotifier::ObserverBase::attach;
+ using ArcNotifier::ObserverBase::detach;
+ using ArcNotifier::ObserverBase::attached;
+
+ protected:
+
+ virtual void add(const Arc& arc) {
+ snapshot.addArc(arc);
+ }
+ virtual void add(const std::vector<Arc>& arcs) {
+ for (int i = arcs.size() - 1; i >= 0; ++i) {
+ snapshot.addArc(arcs[i]);
+ }
+ }
+ virtual void erase(const Arc& arc) {
+ snapshot.eraseArc(arc);
+ }
+ virtual void erase(const std::vector<Arc>& arcs) {
+ for (int i = 0; i < int(arcs.size()); ++i) {
+ snapshot.eraseArc(arcs[i]);
+ }
+ }
+ virtual void build() {
+ Arc arc;
+ std::vector<Arc> arcs;
+ for (notifier()->first(arc); arc != INVALID;
+ notifier()->next(arc)) {
+ arcs.push_back(arc);
+ }
+ for (int i = arcs.size() - 1; i >= 0; --i) {
+ snapshot.addArc(arcs[i]);
+ }
+ }
+ virtual void clear() {
+ Arc arc;
+ for (notifier()->first(arc); arc != INVALID;
+ notifier()->next(arc)) {
+ snapshot.eraseArc(arc);
+ }
+ }
+
+ Snapshot& snapshot;
+ };
+
+ ListDigraph *digraph;
+
+ NodeObserverProxy node_observer_proxy;
+ ArcObserverProxy arc_observer_proxy;
+
+ std::list<Node> added_nodes;
+ std::list<Arc> added_arcs;
+
+
+ void addNode(const Node& node) {
+ added_nodes.push_front(node);
+ }
+ void eraseNode(const Node& node) {
+ std::list<Node>::iterator it =
+ std::find(added_nodes.begin(), added_nodes.end(), node);
+ if (it == added_nodes.end()) {
+ clear();
+ arc_observer_proxy.detach();
+ throw NodeNotifier::ImmediateDetach();
+ } else {
+ added_nodes.erase(it);
+ }
+ }
+
+ void addArc(const Arc& arc) {
+ added_arcs.push_front(arc);
+ }
+ void eraseArc(const Arc& arc) {
+ std::list<Arc>::iterator it =
+ std::find(added_arcs.begin(), added_arcs.end(), arc);
+ if (it == added_arcs.end()) {
+ clear();
+ node_observer_proxy.detach();
+ throw ArcNotifier::ImmediateDetach();
+ } else {
+ added_arcs.erase(it);
+ }
+ }
+
+ void attach(ListDigraph &_digraph) {
+ digraph = &_digraph;
+ node_observer_proxy.attach(digraph->notifier(Node()));
+ arc_observer_proxy.attach(digraph->notifier(Arc()));
+ }
+
+ void detach() {
+ node_observer_proxy.detach();
+ arc_observer_proxy.detach();
+ }
+
+ bool attached() const {
+ return node_observer_proxy.attached();
+ }
+
+ void clear() {
+ added_nodes.clear();
+ added_arcs.clear();
+ }
+
+ public:
+
+ /// \brief Default constructor.
+ ///
+ /// Default constructor.
+ /// You have to call save() to actually make a snapshot.
+ Snapshot()
+ : digraph(0), node_observer_proxy(*this),
+ arc_observer_proxy(*this) {}
+
+ /// \brief Constructor that immediately makes a snapshot.
+ ///
+ /// This constructor immediately makes a snapshot of the given digraph.
+ Snapshot(ListDigraph &gr)
+ : node_observer_proxy(*this),
+ arc_observer_proxy(*this) {
+ attach(gr);
+ }
+
+ /// \brief Make a snapshot.
+ ///
+ /// This function makes a snapshot of the given digraph.
+ /// It can be called more than once. In case of a repeated
+ /// call, the previous snapshot gets lost.
+ void save(ListDigraph &gr) {
+ if (attached()) {
+ detach();
+ clear();
+ }
+ attach(gr);
+ }
+
+ /// \brief Undo the changes until the last snapshot.
+ ///
+ /// This function undos the changes until the last snapshot
+ /// created by save() or Snapshot(ListDigraph&).
+ ///
+ /// \warning This method invalidates the snapshot, i.e. repeated
+ /// restoring is not supported unless you call save() again.
+ void restore() {
+ detach();
+ for(std::list<Arc>::iterator it = added_arcs.begin();
+ it != added_arcs.end(); ++it) {
+ digraph->erase(*it);
+ }
+ for(std::list<Node>::iterator it = added_nodes.begin();
+ it != added_nodes.end(); ++it) {
+ digraph->erase(*it);
+ }
+ clear();
+ }
+
+ /// \brief Returns \c true if the snapshot is valid.
+ ///
+ /// This function returns \c true if the snapshot is valid.
+ bool valid() const {
+ return attached();
+ }
+ };
+
+ };
+
+ ///@}
+
+ class ListGraphBase {
+
+ protected:
+
+ struct NodeT {
+ int first_out;
+ int prev, next;
+ };
+
+ struct ArcT {
+ int target;
+ int prev_out, next_out;
+ };
+
+ std::vector<NodeT> nodes;
+
+ int first_node;
+
+ int first_free_node;
+
+ std::vector<ArcT> arcs;
+
+ int first_free_arc;
+
+ public:
+
+ typedef ListGraphBase Graph;
+
+ class Node {
+ friend class ListGraphBase;
+ protected:
+
+ int id;
+ explicit Node(int pid) { id = pid;}
+
+ public:
+ Node() {}
+ Node (Invalid) { id = -1; }
+ bool operator==(const Node& node) const {return id == node.id;}
+ bool operator!=(const Node& node) const {return id != node.id;}
+ bool operator<(const Node& node) const {return id < node.id;}
+ };
+
+ class Edge {
+ friend class ListGraphBase;
+ protected:
+
+ int id;
+ explicit Edge(int pid) { id = pid;}
+
+ public:
+ Edge() {}
+ Edge (Invalid) { id = -1; }
+ bool operator==(const Edge& edge) const {return id == edge.id;}
+ bool operator!=(const Edge& edge) const {return id != edge.id;}
+ bool operator<(const Edge& edge) const {return id < edge.id;}
+ };
+
+ class Arc {
+ friend class ListGraphBase;
+ protected:
+
+ int id;
+ explicit Arc(int pid) { id = pid;}
+
+ public:
+ operator Edge() const {
+ return id != -1 ? edgeFromId(id / 2) : INVALID;
+ }
+
+ Arc() {}
+ Arc (Invalid) { id = -1; }
+ bool operator==(const Arc& arc) const {return id == arc.id;}
+ bool operator!=(const Arc& arc) const {return id != arc.id;}
+ bool operator<(const Arc& arc) const {return id < arc.id;}
+ };
+
+ ListGraphBase()
+ : nodes(), first_node(-1),
+ first_free_node(-1), arcs(), first_free_arc(-1) {}
+
+
+ int maxNodeId() const { return nodes.size()-1; }
+ int maxEdgeId() const { return arcs.size() / 2 - 1; }
+ int maxArcId() const { return arcs.size()-1; }
+
+ Node source(Arc e) const { return Node(arcs[e.id ^ 1].target); }
+ Node target(Arc e) const { return Node(arcs[e.id].target); }
+
+ Node u(Edge e) const { return Node(arcs[2 * e.id].target); }
+ Node v(Edge e) const { return Node(arcs[2 * e.id + 1].target); }
+
+ static bool direction(Arc e) {
+ return (e.id & 1) == 1;
+ }
+
+ static Arc direct(Edge e, bool d) {
+ return Arc(e.id * 2 + (d ? 1 : 0));
+ }
+
+ void first(Node& node) const {
+ node.id = first_node;
+ }
+
+ void next(Node& node) const {
+ node.id = nodes[node.id].next;
+ }
+
+ void first(Arc& e) const {
+ int n = first_node;
+ while (n != -1 && nodes[n].first_out == -1) {
+ n = nodes[n].next;
+ }
+ e.id = (n == -1) ? -1 : nodes[n].first_out;
+ }
+
+ void next(Arc& e) const {
+ if (arcs[e.id].next_out != -1) {
+ e.id = arcs[e.id].next_out;
+ } else {
+ int n = nodes[arcs[e.id ^ 1].target].next;
+ while(n != -1 && nodes[n].first_out == -1) {
+ n = nodes[n].next;
+ }
+ e.id = (n == -1) ? -1 : nodes[n].first_out;
+ }
+ }
+
+ void first(Edge& e) const {
+ int n = first_node;
+ while (n != -1) {
+ e.id = nodes[n].first_out;
+ while ((e.id & 1) != 1) {
+ e.id = arcs[e.id].next_out;
+ }
+ if (e.id != -1) {
+ e.id /= 2;
+ return;
+ }
+ n = nodes[n].next;
+ }
+ e.id = -1;
+ }
+
+ void next(Edge& e) const {
+ int n = arcs[e.id * 2].target;
+ e.id = arcs[(e.id * 2) | 1].next_out;
+ while ((e.id & 1) != 1) {
+ e.id = arcs[e.id].next_out;
+ }
+ if (e.id != -1) {
+ e.id /= 2;
+ return;
+ }
+ n = nodes[n].next;
+ while (n != -1) {
+ e.id = nodes[n].first_out;
+ while ((e.id & 1) != 1) {
+ e.id = arcs[e.id].next_out;
+ }
+ if (e.id != -1) {
+ e.id /= 2;
+ return;
+ }
+ n = nodes[n].next;
+ }
+ e.id = -1;
+ }
+
+ void firstOut(Arc &e, const Node& v) const {
+ e.id = nodes[v.id].first_out;
+ }
+ void nextOut(Arc &e) const {
+ e.id = arcs[e.id].next_out;
+ }
+
+ void firstIn(Arc &e, const Node& v) const {
+ e.id = ((nodes[v.id].first_out) ^ 1);
+ if (e.id == -2) e.id = -1;
+ }
+ void nextIn(Arc &e) const {
+ e.id = ((arcs[e.id ^ 1].next_out) ^ 1);
+ if (e.id == -2) e.id = -1;
+ }
+
+ void firstInc(Edge &e, bool& d, const Node& v) const {
+ int a = nodes[v.id].first_out;
+ if (a != -1 ) {
+ e.id = a / 2;
+ d = ((a & 1) == 1);
+ } else {
+ e.id = -1;
+ d = true;
+ }
+ }
+ void nextInc(Edge &e, bool& d) const {
+ int a = (arcs[(e.id * 2) | (d ? 1 : 0)].next_out);
+ if (a != -1 ) {
+ e.id = a / 2;
+ d = ((a & 1) == 1);
+ } else {
+ e.id = -1;
+ d = true;
+ }
+ }
+
+ static int id(Node v) { return v.id; }
+ static int id(Arc e) { return e.id; }
+ static int id(Edge e) { return e.id; }
+
+ static Node nodeFromId(int id) { return Node(id);}
+ static Arc arcFromId(int id) { return Arc(id);}
+ static Edge edgeFromId(int id) { return Edge(id);}
+
+ bool valid(Node n) const {
+ return n.id >= 0 && n.id < static_cast<int>(nodes.size()) &&
+ nodes[n.id].prev != -2;
+ }
+
+ bool valid(Arc a) const {
+ return a.id >= 0 && a.id < static_cast<int>(arcs.size()) &&
+ arcs[a.id].prev_out != -2;
+ }
+
+ bool valid(Edge e) const {
+ return e.id >= 0 && 2 * e.id < static_cast<int>(arcs.size()) &&
+ arcs[2 * e.id].prev_out != -2;
+ }
+
+ Node addNode() {
+ int n;
+
+ if(first_free_node==-1) {
+ n = nodes.size();
+ nodes.push_back(NodeT());
+ } else {
+ n = first_free_node;
+ first_free_node = nodes[n].next;
+ }
+
+ nodes[n].next = first_node;
+ if (first_node != -1) nodes[first_node].prev = n;
+ first_node = n;
+ nodes[n].prev = -1;
+
+ nodes[n].first_out = -1;
+
+ return Node(n);
+ }
+
+ Edge addEdge(Node u, Node v) {
+ int n;
+
+ if (first_free_arc == -1) {
+ n = arcs.size();
+ arcs.push_back(ArcT());
+ arcs.push_back(ArcT());
+ } else {
+ n = first_free_arc;
+ first_free_arc = arcs[n].next_out;
+ }
+
+ arcs[n].target = u.id;
+ arcs[n | 1].target = v.id;
+
+ arcs[n].next_out = nodes[v.id].first_out;
+ if (nodes[v.id].first_out != -1) {
+ arcs[nodes[v.id].first_out].prev_out = n;
+ }
+ arcs[n].prev_out = -1;
+ nodes[v.id].first_out = n;
+
+ arcs[n | 1].next_out = nodes[u.id].first_out;
+ if (nodes[u.id].first_out != -1) {
+ arcs[nodes[u.id].first_out].prev_out = (n | 1);
+ }
+ arcs[n | 1].prev_out = -1;
+ nodes[u.id].first_out = (n | 1);
+
+ return Edge(n / 2);
+ }
+
+ void erase(const Node& node) {
+ int n = node.id;
+
+ if(nodes[n].next != -1) {
+ nodes[nodes[n].next].prev = nodes[n].prev;
+ }
+
+ if(nodes[n].prev != -1) {
+ nodes[nodes[n].prev].next = nodes[n].next;
+ } else {
+ first_node = nodes[n].next;
+ }
+
+ nodes[n].next = first_free_node;
+ first_free_node = n;
+ nodes[n].prev = -2;
+ }
+
+ void erase(const Edge& edge) {
+ int n = edge.id * 2;
+
+ if (arcs[n].next_out != -1) {
+ arcs[arcs[n].next_out].prev_out = arcs[n].prev_out;
+ }
+
+ if (arcs[n].prev_out != -1) {
+ arcs[arcs[n].prev_out].next_out = arcs[n].next_out;
+ } else {
+ nodes[arcs[n | 1].target].first_out = arcs[n].next_out;
+ }
+
+ if (arcs[n | 1].next_out != -1) {
+ arcs[arcs[n | 1].next_out].prev_out = arcs[n | 1].prev_out;
+ }
+
+ if (arcs[n | 1].prev_out != -1) {
+ arcs[arcs[n | 1].prev_out].next_out = arcs[n | 1].next_out;
+ } else {
+ nodes[arcs[n].target].first_out = arcs[n | 1].next_out;
+ }
+
+ arcs[n].next_out = first_free_arc;
+ first_free_arc = n;
+ arcs[n].prev_out = -2;
+ arcs[n | 1].prev_out = -2;
+
+ }
+
+ void clear() {
+ arcs.clear();
+ nodes.clear();
+ first_node = first_free_node = first_free_arc = -1;
+ }
+
+ protected:
+
+ void changeV(Edge e, Node n) {
+ if(arcs[2 * e.id].next_out != -1) {
+ arcs[arcs[2 * e.id].next_out].prev_out = arcs[2 * e.id].prev_out;
+ }
+ if(arcs[2 * e.id].prev_out != -1) {
+ arcs[arcs[2 * e.id].prev_out].next_out =
+ arcs[2 * e.id].next_out;
+ } else {
+ nodes[arcs[(2 * e.id) | 1].target].first_out =
+ arcs[2 * e.id].next_out;
+ }
+
+ if (nodes[n.id].first_out != -1) {
+ arcs[nodes[n.id].first_out].prev_out = 2 * e.id;
+ }
+ arcs[(2 * e.id) | 1].target = n.id;
+ arcs[2 * e.id].prev_out = -1;
+ arcs[2 * e.id].next_out = nodes[n.id].first_out;
+ nodes[n.id].first_out = 2 * e.id;
+ }
+
+ void changeU(Edge e, Node n) {
+ if(arcs[(2 * e.id) | 1].next_out != -1) {
+ arcs[arcs[(2 * e.id) | 1].next_out].prev_out =
+ arcs[(2 * e.id) | 1].prev_out;
+ }
+ if(arcs[(2 * e.id) | 1].prev_out != -1) {
+ arcs[arcs[(2 * e.id) | 1].prev_out].next_out =
+ arcs[(2 * e.id) | 1].next_out;
+ } else {
+ nodes[arcs[2 * e.id].target].first_out =
+ arcs[(2 * e.id) | 1].next_out;
+ }
+
+ if (nodes[n.id].first_out != -1) {
+ arcs[nodes[n.id].first_out].prev_out = ((2 * e.id) | 1);
+ }
+ arcs[2 * e.id].target = n.id;
+ arcs[(2 * e.id) | 1].prev_out = -1;
+ arcs[(2 * e.id) | 1].next_out = nodes[n.id].first_out;
+ nodes[n.id].first_out = ((2 * e.id) | 1);
+ }
+
+ };
+
+ typedef GraphExtender<ListGraphBase> ExtendedListGraphBase;
+
+
+ /// \addtogroup graphs
+ /// @{
+
+ ///A general undirected graph structure.
+
+ ///\ref ListGraph is a versatile and fast undirected graph
+ ///implementation based on linked lists that are stored in
+ ///\c std::vector structures.
+ ///
+ ///This type fully conforms to the \ref concepts::Graph "Graph concept"
+ ///and it also provides several useful additional functionalities.
+ ///Most of its member functions and nested classes are documented
+ ///only in the concept class.
+ ///
+ ///This class provides only linear time counting for nodes, edges and arcs.
+ ///
+ ///\sa concepts::Graph
+ ///\sa ListDigraph
+ class ListGraph : public ExtendedListGraphBase {
+ typedef ExtendedListGraphBase Parent;
+
+ private:
+ /// Graphs are \e not copy constructible. Use GraphCopy instead.
+ ListGraph(const ListGraph &) :ExtendedListGraphBase() {};
+ /// \brief Assignment of a graph to another one is \e not allowed.
+ /// Use GraphCopy instead.
+ void operator=(const ListGraph &) {}
+ public:
+ /// Constructor
+
+ /// Constructor.
+ ///
+ ListGraph() {}
+
+ typedef Parent::OutArcIt IncEdgeIt;
+
+ /// \brief Add a new node to the graph.
+ ///
+ /// This function adds a new node to the graph.
+ /// \return The new node.
+ Node addNode() { return Parent::addNode(); }
+
+ /// \brief Add a new edge to the graph.
+ ///
+ /// This function adds a new edge to the graph between nodes
+ /// \c u and \c v with inherent orientation from node \c u to
+ /// node \c v.
+ /// \return The new edge.
+ Edge addEdge(Node u, Node v) {
+ return Parent::addEdge(u, v);
+ }
+
+ ///\brief Erase a node from the graph.
+ ///
+ /// This function erases the given node along with its incident arcs
+ /// from the graph.
+ ///
+ /// \note All iterators referencing the removed node or the incident
+ /// edges are invalidated, of course.
+ void erase(Node n) { Parent::erase(n); }
+
+ ///\brief Erase an edge from the graph.
+ ///
+ /// This function erases the given edge from the graph.
+ ///
+ /// \note All iterators referencing the removed edge are invalidated,
+ /// of course.
+ void erase(Edge e) { Parent::erase(e); }
+ /// Node validity check
+
+ /// This function gives back \c true if the given node is valid,
+ /// i.e. it is a real node of the graph.
+ ///
+ /// \warning A removed node could become valid again if new nodes are
+ /// added to the graph.
+ bool valid(Node n) const { return Parent::valid(n); }
+ /// Edge validity check
+
+ /// This function gives back \c true if the given edge is valid,
+ /// i.e. it is a real edge of the graph.
+ ///
+ /// \warning A removed edge could become valid again if new edges are
+ /// added to the graph.
+ bool valid(Edge e) const { return Parent::valid(e); }
+ /// Arc validity check
+
+ /// This function gives back \c true if the given arc is valid,
+ /// i.e. it is a real arc of the graph.
+ ///
+ /// \warning A removed arc could become valid again if new edges are
+ /// added to the graph.
+ bool valid(Arc a) const { return Parent::valid(a); }
+
+ /// \brief Change the first node of an edge.
+ ///
+ /// This function changes the first node of the given edge \c e to \c n.
+ ///
+ ///\note \c EdgeIt and \c ArcIt iterators referencing the
+ ///changed edge are invalidated and all other iterators whose
+ ///base node is the changed node are also invalidated.
+ ///
+ ///\warning This functionality cannot be used together with the
+ ///Snapshot feature.
+ void changeU(Edge e, Node n) {
+ Parent::changeU(e,n);
+ }
+ /// \brief Change the second node of an edge.
+ ///
+ /// This function changes the second node of the given edge \c e to \c n.
+ ///
+ ///\note \c EdgeIt iterators referencing the changed edge remain
+ ///valid, but \c ArcIt iterators referencing the changed edge and
+ ///all other iterators whose base node is the changed node are also
+ ///invalidated.
+ ///
+ ///\warning This functionality cannot be used together with the
+ ///Snapshot feature.
+ void changeV(Edge e, Node n) {
+ Parent::changeV(e,n);
+ }
+
+ /// \brief Contract two nodes.
+ ///
+ /// This function contracts the given two nodes.
+ /// Node \c b is removed, but instead of deleting
+ /// its incident edges, they are joined to node \c a.
+ /// If the last parameter \c r is \c true (this is the default value),
+ /// then the newly created loops are removed.
+ ///
+ /// \note The moved edges are joined to node \c a using changeU()
+ /// or changeV(), thus all edge and arc iterators whose base node is
+ /// \c b are invalidated.
+ /// Moreover all iterators referencing node \c b or the removed
+ /// loops are also invalidated. Other iterators remain valid.
+ ///
+ ///\warning This functionality cannot be used together with the
+ ///Snapshot feature.
+ void contract(Node a, Node b, bool r = true) {
+ for(IncEdgeIt e(*this, b); e!=INVALID;) {
+ IncEdgeIt f = e; ++f;
+ if (r && runningNode(e) == a) {
+ erase(e);
+ } else if (u(e) == b) {
+ changeU(e, a);
+ } else {
+ changeV(e, a);
+ }
+ e = f;
+ }
+ erase(b);
+ }
+
+ ///Clear the graph.
+
+ ///This function erases all nodes and arcs from the graph.
+ ///
+ ///\note All iterators of the graph are invalidated, of course.
+ void clear() {
+ Parent::clear();
+ }
+
+ /// Reserve memory for nodes.
+
+ /// Using this function, it is possible to avoid superfluous memory
+ /// allocation: if you know that the graph you want to build will
+ /// be large (e.g. it will contain millions of nodes and/or edges),
+ /// then it is worth reserving space for this amount before starting
+ /// to build the graph.
+ /// \sa reserveEdge()
+ void reserveNode(int n) { nodes.reserve(n); };
+
+ /// Reserve memory for edges.
+
+ /// Using this function, it is possible to avoid superfluous memory
+ /// allocation: if you know that the graph you want to build will
+ /// be large (e.g. it will contain millions of nodes and/or edges),
+ /// then it is worth reserving space for this amount before starting
+ /// to build the graph.
+ /// \sa reserveNode()
+ void reserveEdge(int m) { arcs.reserve(2 * m); };
+
+ /// \brief Class to make a snapshot of the graph and restore
+ /// it later.
+ ///
+ /// Class to make a snapshot of the graph and restore it later.
+ ///
+ /// The newly added nodes and edges can be removed
+ /// using the restore() function.
+ ///
+ /// \note After a state is restored, you cannot restore a later state,
+ /// i.e. you cannot add the removed nodes and edges again using
+ /// another Snapshot instance.
+ ///
+ /// \warning Node and edge deletions and other modifications
+ /// (e.g. changing the end-nodes of edges or contracting nodes)
+ /// cannot be restored. These events invalidate the snapshot.
+ /// However, the edges and nodes that were added to the graph after
+ /// making the current snapshot can be removed without invalidating it.
+ class Snapshot {
+ protected:
+
+ typedef Parent::NodeNotifier NodeNotifier;
+
+ class NodeObserverProxy : public NodeNotifier::ObserverBase {
+ public:
+
+ NodeObserverProxy(Snapshot& _snapshot)
+ : snapshot(_snapshot) {}
+
+ using NodeNotifier::ObserverBase::attach;
+ using NodeNotifier::ObserverBase::detach;
+ using NodeNotifier::ObserverBase::attached;
+
+ protected:
+
+ virtual void add(const Node& node) {
+ snapshot.addNode(node);
+ }
+ virtual void add(const std::vector<Node>& nodes) {
+ for (int i = nodes.size() - 1; i >= 0; ++i) {
+ snapshot.addNode(nodes[i]);
+ }
+ }
+ virtual void erase(const Node& node) {
+ snapshot.eraseNode(node);
+ }
+ virtual void erase(const std::vector<Node>& nodes) {
+ for (int i = 0; i < int(nodes.size()); ++i) {
+ snapshot.eraseNode(nodes[i]);
+ }
+ }
+ virtual void build() {
+ Node node;
+ std::vector<Node> nodes;
+ for (notifier()->first(node); node != INVALID;
+ notifier()->next(node)) {
+ nodes.push_back(node);
+ }
+ for (int i = nodes.size() - 1; i >= 0; --i) {
+ snapshot.addNode(nodes[i]);
+ }
+ }
+ virtual void clear() {
+ Node node;
+ for (notifier()->first(node); node != INVALID;
+ notifier()->next(node)) {
+ snapshot.eraseNode(node);
+ }
+ }
+
+ Snapshot& snapshot;
+ };
+
+ class EdgeObserverProxy : public EdgeNotifier::ObserverBase {
+ public:
+
+ EdgeObserverProxy(Snapshot& _snapshot)
+ : snapshot(_snapshot) {}
+
+ using EdgeNotifier::ObserverBase::attach;
+ using EdgeNotifier::ObserverBase::detach;
+ using EdgeNotifier::ObserverBase::attached;
+
+ protected:
+
+ virtual void add(const Edge& edge) {
+ snapshot.addEdge(edge);
+ }
+ virtual void add(const std::vector<Edge>& edges) {
+ for (int i = edges.size() - 1; i >= 0; ++i) {
+ snapshot.addEdge(edges[i]);
+ }
+ }
+ virtual void erase(const Edge& edge) {
+ snapshot.eraseEdge(edge);
+ }
+ virtual void erase(const std::vector<Edge>& edges) {
+ for (int i = 0; i < int(edges.size()); ++i) {
+ snapshot.eraseEdge(edges[i]);
+ }
+ }
+ virtual void build() {
+ Edge edge;
+ std::vector<Edge> edges;
+ for (notifier()->first(edge); edge != INVALID;
+ notifier()->next(edge)) {
+ edges.push_back(edge);
+ }
+ for (int i = edges.size() - 1; i >= 0; --i) {
+ snapshot.addEdge(edges[i]);
+ }
+ }
+ virtual void clear() {
+ Edge edge;
+ for (notifier()->first(edge); edge != INVALID;
+ notifier()->next(edge)) {
+ snapshot.eraseEdge(edge);
+ }
+ }
+
+ Snapshot& snapshot;
+ };
+
+ ListGraph *graph;
+
+ NodeObserverProxy node_observer_proxy;
+ EdgeObserverProxy edge_observer_proxy;
+
+ std::list<Node> added_nodes;
+ std::list<Edge> added_edges;
+
+
+ void addNode(const Node& node) {
+ added_nodes.push_front(node);
+ }
+ void eraseNode(const Node& node) {
+ std::list<Node>::iterator it =
+ std::find(added_nodes.begin(), added_nodes.end(), node);
+ if (it == added_nodes.end()) {
+ clear();
+ edge_observer_proxy.detach();
+ throw NodeNotifier::ImmediateDetach();
+ } else {
+ added_nodes.erase(it);
+ }
+ }
+
+ void addEdge(const Edge& edge) {
+ added_edges.push_front(edge);
+ }
+ void eraseEdge(const Edge& edge) {
+ std::list<Edge>::iterator it =
+ std::find(added_edges.begin(), added_edges.end(), edge);
+ if (it == added_edges.end()) {
+ clear();
+ node_observer_proxy.detach();
+ throw EdgeNotifier::ImmediateDetach();
+ } else {
+ added_edges.erase(it);
+ }
+ }
+
+ void attach(ListGraph &_graph) {
+ graph = &_graph;
+ node_observer_proxy.attach(graph->notifier(Node()));
+ edge_observer_proxy.attach(graph->notifier(Edge()));
+ }
+
+ void detach() {
+ node_observer_proxy.detach();
+ edge_observer_proxy.detach();
+ }
+
+ bool attached() const {
+ return node_observer_proxy.attached();
+ }
+
+ void clear() {
+ added_nodes.clear();
+ added_edges.clear();
+ }
+
+ public:
+
+ /// \brief Default constructor.
+ ///
+ /// Default constructor.
+ /// You have to call save() to actually make a snapshot.
+ Snapshot()
+ : graph(0), node_observer_proxy(*this),
+ edge_observer_proxy(*this) {}
+
+ /// \brief Constructor that immediately makes a snapshot.
+ ///
+ /// This constructor immediately makes a snapshot of the given graph.
+ Snapshot(ListGraph &gr)
+ : node_observer_proxy(*this),
+ edge_observer_proxy(*this) {
+ attach(gr);
+ }
+
+ /// \brief Make a snapshot.
+ ///
+ /// This function makes a snapshot of the given graph.
+ /// It can be called more than once. In case of a repeated
+ /// call, the previous snapshot gets lost.
+ void save(ListGraph &gr) {
+ if (attached()) {
+ detach();
+ clear();
+ }
+ attach(gr);
+ }
+
+ /// \brief Undo the changes until the last snapshot.
+ ///
+ /// This function undos the changes until the last snapshot
+ /// created by save() or Snapshot(ListGraph&).
+ ///
+ /// \warning This method invalidates the snapshot, i.e. repeated
+ /// restoring is not supported unless you call save() again.
+ void restore() {
+ detach();
+ for(std::list<Edge>::iterator it = added_edges.begin();
+ it != added_edges.end(); ++it) {
+ graph->erase(*it);
+ }
+ for(std::list<Node>::iterator it = added_nodes.begin();
+ it != added_nodes.end(); ++it) {
+ graph->erase(*it);
+ }
+ clear();
+ }
+
+ /// \brief Returns \c true if the snapshot is valid.
+ ///
+ /// This function returns \c true if the snapshot is valid.
+ bool valid() const {
+ return attached();
+ }
+ };
+ };
+
+ /// @}
+
+ class ListBpGraphBase {
+
+ protected:
+
+ struct NodeT {
+ int first_out;
+ int prev, next;
+ int partition_prev, partition_next;
+ int partition_index;
+ bool red;
+ };
+
+ struct ArcT {
+ int target;
+ int prev_out, next_out;
+ };
+
+ std::vector<NodeT> nodes;
+
+ int first_node, first_red, first_blue;
+ int max_red, max_blue;
+
+ int first_free_red, first_free_blue;
+
+ std::vector<ArcT> arcs;
+
+ int first_free_arc;
+
+ public:
+
+ typedef ListBpGraphBase BpGraph;
+
+ class Node {
+ friend class ListBpGraphBase;
+ protected:
+
+ int id;
+ explicit Node(int pid) { id = pid;}
+
+ public:
+ Node() {}
+ Node (Invalid) { id = -1; }
+ bool operator==(const Node& node) const {return id == node.id;}
+ bool operator!=(const Node& node) const {return id != node.id;}
+ bool operator<(const Node& node) const {return id < node.id;}
+ };
+
+ class RedNode : public Node {
+ friend class ListBpGraphBase;
+ protected:
+
+ explicit RedNode(int pid) : Node(pid) {}
+
+ public:
+ RedNode() {}
+ RedNode(const RedNode& node) : Node(node) {}
+ RedNode(Invalid) : Node(INVALID){}
+ };
+
+ class BlueNode : public Node {
+ friend class ListBpGraphBase;
+ protected:
+
+ explicit BlueNode(int pid) : Node(pid) {}
+
+ public:
+ BlueNode() {}
+ BlueNode(const BlueNode& node) : Node(node) {}
+ BlueNode(Invalid) : Node(INVALID){}
+ };
+
+ class Edge {
+ friend class ListBpGraphBase;
+ protected:
+
+ int id;
+ explicit Edge(int pid) { id = pid;}
+
+ public:
+ Edge() {}
+ Edge (Invalid) { id = -1; }
+ bool operator==(const Edge& edge) const {return id == edge.id;}
+ bool operator!=(const Edge& edge) const {return id != edge.id;}
+ bool operator<(const Edge& edge) const {return id < edge.id;}
+ };
+
+ class Arc {
+ friend class ListBpGraphBase;
+ protected:
+
+ int id;
+ explicit Arc(int pid) { id = pid;}
+
+ public:
+ operator Edge() const {
+ return id != -1 ? edgeFromId(id / 2) : INVALID;
+ }
+
+ Arc() {}
+ Arc (Invalid) { id = -1; }
+ bool operator==(const Arc& arc) const {return id == arc.id;}
+ bool operator!=(const Arc& arc) const {return id != arc.id;}
+ bool operator<(const Arc& arc) const {return id < arc.id;}
+ };
+
+ ListBpGraphBase()
+ : nodes(), first_node(-1),
+ first_red(-1), first_blue(-1),
+ max_red(-1), max_blue(-1),
+ first_free_red(-1), first_free_blue(-1),
+ arcs(), first_free_arc(-1) {}
+
+
+ bool red(Node n) const { return nodes[n.id].red; }
+ bool blue(Node n) const { return !nodes[n.id].red; }
+
+ static RedNode asRedNodeUnsafe(Node n) { return RedNode(n.id); }
+ static BlueNode asBlueNodeUnsafe(Node n) { return BlueNode(n.id); }
+
+ int maxNodeId() const { return nodes.size()-1; }
+ int maxRedId() const { return max_red; }
+ int maxBlueId() const { return max_blue; }
+ int maxEdgeId() const { return arcs.size() / 2 - 1; }
+ int maxArcId() const { return arcs.size()-1; }
+
+ Node source(Arc e) const { return Node(arcs[e.id ^ 1].target); }
+ Node target(Arc e) const { return Node(arcs[e.id].target); }
+
+ RedNode redNode(Edge e) const {
+ return RedNode(arcs[2 * e.id].target);
+ }
+ BlueNode blueNode(Edge e) const {
+ return BlueNode(arcs[2 * e.id + 1].target);
+ }
+
+ static bool direction(Arc e) {
+ return (e.id & 1) == 1;
+ }
+
+ static Arc direct(Edge e, bool d) {
+ return Arc(e.id * 2 + (d ? 1 : 0));
+ }
+
+ void first(Node& node) const {
+ node.id = first_node;
+ }
+
+ void next(Node& node) const {
+ node.id = nodes[node.id].next;
+ }
+
+ void first(RedNode& node) const {
+ node.id = first_red;
+ }
+
+ void next(RedNode& node) const {
+ node.id = nodes[node.id].partition_next;
+ }
+
+ void first(BlueNode& node) const {
+ node.id = first_blue;
+ }
+
+ void next(BlueNode& node) const {
+ node.id = nodes[node.id].partition_next;
+ }
+
+ void first(Arc& e) const {
+ int n = first_node;
+ while (n != -1 && nodes[n].first_out == -1) {
+ n = nodes[n].next;
+ }
+ e.id = (n == -1) ? -1 : nodes[n].first_out;
+ }
+
+ void next(Arc& e) const {
+ if (arcs[e.id].next_out != -1) {
+ e.id = arcs[e.id].next_out;
+ } else {
+ int n = nodes[arcs[e.id ^ 1].target].next;
+ while(n != -1 && nodes[n].first_out == -1) {
+ n = nodes[n].next;
+ }
+ e.id = (n == -1) ? -1 : nodes[n].first_out;
+ }
+ }
+
+ void first(Edge& e) const {
+ int n = first_node;
+ while (n != -1) {
+ e.id = nodes[n].first_out;
+ while ((e.id & 1) != 1) {
+ e.id = arcs[e.id].next_out;
+ }
+ if (e.id != -1) {
+ e.id /= 2;
+ return;
+ }
+ n = nodes[n].next;
+ }
+ e.id = -1;
+ }
+
+ void next(Edge& e) const {
+ int n = arcs[e.id * 2].target;
+ e.id = arcs[(e.id * 2) | 1].next_out;
+ while ((e.id & 1) != 1) {
+ e.id = arcs[e.id].next_out;
+ }
+ if (e.id != -1) {
+ e.id /= 2;
+ return;
+ }
+ n = nodes[n].next;
+ while (n != -1) {
+ e.id = nodes[n].first_out;
+ while ((e.id & 1) != 1) {
+ e.id = arcs[e.id].next_out;
+ }
+ if (e.id != -1) {
+ e.id /= 2;
+ return;
+ }
+ n = nodes[n].next;
+ }
+ e.id = -1;
+ }
+
+ void firstOut(Arc &e, const Node& v) const {
+ e.id = nodes[v.id].first_out;
+ }
+ void nextOut(Arc &e) const {
+ e.id = arcs[e.id].next_out;
+ }
+
+ void firstIn(Arc &e, const Node& v) const {
+ e.id = ((nodes[v.id].first_out) ^ 1);
+ if (e.id == -2) e.id = -1;
+ }
+ void nextIn(Arc &e) const {
+ e.id = ((arcs[e.id ^ 1].next_out) ^ 1);
+ if (e.id == -2) e.id = -1;
+ }
+
+ void firstInc(Edge &e, bool& d, const Node& v) const {
+ int a = nodes[v.id].first_out;
+ if (a != -1 ) {
+ e.id = a / 2;
+ d = ((a & 1) == 1);
+ } else {
+ e.id = -1;
+ d = true;
+ }
+ }
+ void nextInc(Edge &e, bool& d) const {
+ int a = (arcs[(e.id * 2) | (d ? 1 : 0)].next_out);
+ if (a != -1 ) {
+ e.id = a / 2;
+ d = ((a & 1) == 1);
+ } else {
+ e.id = -1;
+ d = true;
+ }
+ }
+
+ static int id(Node v) { return v.id; }
+ int id(RedNode v) const { return nodes[v.id].partition_index; }
+ int id(BlueNode v) const { return nodes[v.id].partition_index; }
+ static int id(Arc e) { return e.id; }
+ static int id(Edge e) { return e.id; }
+
+ static Node nodeFromId(int id) { return Node(id);}
+ static Arc arcFromId(int id) { return Arc(id);}
+ static Edge edgeFromId(int id) { return Edge(id);}
+
+ bool valid(Node n) const {
+ return n.id >= 0 && n.id < static_cast<int>(nodes.size()) &&
+ nodes[n.id].prev != -2;
+ }
+
+ bool valid(Arc a) const {
+ return a.id >= 0 && a.id < static_cast<int>(arcs.size()) &&
+ arcs[a.id].prev_out != -2;
+ }
+
+ bool valid(Edge e) const {
+ return e.id >= 0 && 2 * e.id < static_cast<int>(arcs.size()) &&
+ arcs[2 * e.id].prev_out != -2;
+ }
+
+ RedNode addRedNode() {
+ int n;
+
+ if(first_free_red==-1) {
+ n = nodes.size();
+ nodes.push_back(NodeT());
+ nodes[n].partition_index = ++max_red;
+ nodes[n].red = true;
+ } else {
+ n = first_free_red;
+ first_free_red = nodes[n].next;
+ }
+
+ nodes[n].next = first_node;
+ if (first_node != -1) nodes[first_node].prev = n;
+ first_node = n;
+ nodes[n].prev = -1;
+
+ nodes[n].partition_next = first_red;
+ if (first_red != -1) nodes[first_red].partition_prev = n;
+ first_red = n;
+ nodes[n].partition_prev = -1;
+
+ nodes[n].first_out = -1;
+
+ return RedNode(n);
+ }
+
+ BlueNode addBlueNode() {
+ int n;
+
+ if(first_free_blue==-1) {
+ n = nodes.size();
+ nodes.push_back(NodeT());
+ nodes[n].partition_index = ++max_blue;
+ nodes[n].red = false;
+ } else {
+ n = first_free_blue;
+ first_free_blue = nodes[n].next;
+ }
+
+ nodes[n].next = first_node;
+ if (first_node != -1) nodes[first_node].prev = n;
+ first_node = n;
+ nodes[n].prev = -1;
+
+ nodes[n].partition_next = first_blue;
+ if (first_blue != -1) nodes[first_blue].partition_prev = n;
+ first_blue = n;
+ nodes[n].partition_prev = -1;
+
+ nodes[n].first_out = -1;
+
+ return BlueNode(n);
+ }
+
+ Edge addEdge(Node u, Node v) {
+ int n;
+
+ if (first_free_arc == -1) {
+ n = arcs.size();
+ arcs.push_back(ArcT());
+ arcs.push_back(ArcT());
+ } else {
+ n = first_free_arc;
+ first_free_arc = arcs[n].next_out;
+ }
+
+ arcs[n].target = u.id;
+ arcs[n | 1].target = v.id;
+
+ arcs[n].next_out = nodes[v.id].first_out;
+ if (nodes[v.id].first_out != -1) {
+ arcs[nodes[v.id].first_out].prev_out = n;
+ }
+ arcs[n].prev_out = -1;
+ nodes[v.id].first_out = n;
+
+ arcs[n | 1].next_out = nodes[u.id].first_out;
+ if (nodes[u.id].first_out != -1) {
+ arcs[nodes[u.id].first_out].prev_out = (n | 1);
+ }
+ arcs[n | 1].prev_out = -1;
+ nodes[u.id].first_out = (n | 1);
+
+ return Edge(n / 2);
+ }
+
+ void erase(const Node& node) {
+ int n = node.id;
+
+ if(nodes[n].next != -1) {
+ nodes[nodes[n].next].prev = nodes[n].prev;
+ }
+
+ if(nodes[n].prev != -1) {
+ nodes[nodes[n].prev].next = nodes[n].next;
+ } else {
+ first_node = nodes[n].next;
+ }
+
+ if (nodes[n].partition_next != -1) {
+ nodes[nodes[n].partition_next].partition_prev = nodes[n].partition_prev;
+ }
+
+ if (nodes[n].partition_prev != -1) {
+ nodes[nodes[n].partition_prev].partition_next = nodes[n].partition_next;
+ } else {
+ if (nodes[n].red) {
+ first_red = nodes[n].partition_next;
+ } else {
+ first_blue = nodes[n].partition_next;
+ }
+ }
+
+ if (nodes[n].red) {
+ nodes[n].next = first_free_red;
+ first_free_red = n;
+ } else {
+ nodes[n].next = first_free_blue;
+ first_free_blue = n;
+ }
+ nodes[n].prev = -2;
+ }
+
+ void erase(const Edge& edge) {
+ int n = edge.id * 2;
+
+ if (arcs[n].next_out != -1) {
+ arcs[arcs[n].next_out].prev_out = arcs[n].prev_out;
+ }
+
+ if (arcs[n].prev_out != -1) {
+ arcs[arcs[n].prev_out].next_out = arcs[n].next_out;
+ } else {
+ nodes[arcs[n | 1].target].first_out = arcs[n].next_out;
+ }
+
+ if (arcs[n | 1].next_out != -1) {
+ arcs[arcs[n | 1].next_out].prev_out = arcs[n | 1].prev_out;
+ }
+
+ if (arcs[n | 1].prev_out != -1) {
+ arcs[arcs[n | 1].prev_out].next_out = arcs[n | 1].next_out;
+ } else {
+ nodes[arcs[n].target].first_out = arcs[n | 1].next_out;
+ }
+
+ arcs[n].next_out = first_free_arc;
+ first_free_arc = n;
+ arcs[n].prev_out = -2;
+ arcs[n | 1].prev_out = -2;
+
+ }
+
+ void clear() {
+ arcs.clear();
+ nodes.clear();
+ first_node = first_free_arc = first_red = first_blue =
+ max_red = max_blue = first_free_red = first_free_blue = -1;
+ }
+
+ protected:
+
+ void changeRed(Edge e, RedNode n) {
+ if(arcs[(2 * e.id) | 1].next_out != -1) {
+ arcs[arcs[(2 * e.id) | 1].next_out].prev_out =
+ arcs[(2 * e.id) | 1].prev_out;
+ }
+ if(arcs[(2 * e.id) | 1].prev_out != -1) {
+ arcs[arcs[(2 * e.id) | 1].prev_out].next_out =
+ arcs[(2 * e.id) | 1].next_out;
+ } else {
+ nodes[arcs[2 * e.id].target].first_out =
+ arcs[(2 * e.id) | 1].next_out;
+ }
+
+ if (nodes[n.id].first_out != -1) {
+ arcs[nodes[n.id].first_out].prev_out = ((2 * e.id) | 1);
+ }
+ arcs[2 * e.id].target = n.id;
+ arcs[(2 * e.id) | 1].prev_out = -1;
+ arcs[(2 * e.id) | 1].next_out = nodes[n.id].first_out;
+ nodes[n.id].first_out = ((2 * e.id) | 1);
+ }
+
+ void changeBlue(Edge e, BlueNode n) {
+ if(arcs[2 * e.id].next_out != -1) {
+ arcs[arcs[2 * e.id].next_out].prev_out = arcs[2 * e.id].prev_out;
+ }
+ if(arcs[2 * e.id].prev_out != -1) {
+ arcs[arcs[2 * e.id].prev_out].next_out =
+ arcs[2 * e.id].next_out;
+ } else {
+ nodes[arcs[(2 * e.id) | 1].target].first_out =
+ arcs[2 * e.id].next_out;
+ }
+
+ if (nodes[n.id].first_out != -1) {
+ arcs[nodes[n.id].first_out].prev_out = 2 * e.id;
+ }
+ arcs[(2 * e.id) | 1].target = n.id;
+ arcs[2 * e.id].prev_out = -1;
+ arcs[2 * e.id].next_out = nodes[n.id].first_out;
+ nodes[n.id].first_out = 2 * e.id;
+ }
+
+ };
+
+ typedef BpGraphExtender<ListBpGraphBase> ExtendedListBpGraphBase;
+
+
+ /// \addtogroup graphs
+ /// @{
+
+ ///A general undirected graph structure.
+
+ ///\ref ListBpGraph is a versatile and fast undirected graph
+ ///implementation based on linked lists that are stored in
+ ///\c std::vector structures.
+ ///
+ ///This type fully conforms to the \ref concepts::BpGraph "BpGraph concept"
+ ///and it also provides several useful additional functionalities.
+ ///Most of its member functions and nested classes are documented
+ ///only in the concept class.
+ ///
+ ///This class provides only linear time counting for nodes, edges and arcs.
+ ///
+ ///\sa concepts::BpGraph
+ ///\sa ListDigraph
+ class ListBpGraph : public ExtendedListBpGraphBase {
+ typedef ExtendedListBpGraphBase Parent;
+
+ private:
+ /// BpGraphs are \e not copy constructible. Use BpGraphCopy instead.
+ ListBpGraph(const ListBpGraph &) :ExtendedListBpGraphBase() {};
+ /// \brief Assignment of a graph to another one is \e not allowed.
+ /// Use BpGraphCopy instead.
+ void operator=(const ListBpGraph &) {}
+ public:
+ /// Constructor
+
+ /// Constructor.
+ ///
+ ListBpGraph() {}
+
+ typedef Parent::OutArcIt IncEdgeIt;
+
+ /// \brief Add a new red node to the graph.
+ ///
+ /// This function adds a red new node to the graph.
+ /// \return The new node.
+ RedNode addRedNode() { return Parent::addRedNode(); }
+
+ /// \brief Add a new blue node to the graph.
+ ///
+ /// This function adds a blue new node to the graph.
+ /// \return The new node.
+ BlueNode addBlueNode() { return Parent::addBlueNode(); }
+
+ /// \brief Add a new edge to the graph.
+ ///
+ /// This function adds a new edge to the graph between nodes
+ /// \c u and \c v with inherent orientation from node \c u to
+ /// node \c v.
+ /// \return The new edge.
+ Edge addEdge(RedNode u, BlueNode v) {
+ return Parent::addEdge(u, v);
+ }
+ Edge addEdge(BlueNode v, RedNode u) {
+ return Parent::addEdge(u, v);
+ }
+
+ ///\brief Erase a node from the graph.
+ ///
+ /// This function erases the given node along with its incident arcs
+ /// from the graph.
+ ///
+ /// \note All iterators referencing the removed node or the incident
+ /// edges are invalidated, of course.
+ void erase(Node n) { Parent::erase(n); }
+
+ ///\brief Erase an edge from the graph.
+ ///
+ /// This function erases the given edge from the graph.
+ ///
+ /// \note All iterators referencing the removed edge are invalidated,
+ /// of course.
+ void erase(Edge e) { Parent::erase(e); }
+ /// Node validity check
+
+ /// This function gives back \c true if the given node is valid,
+ /// i.e. it is a real node of the graph.
+ ///
+ /// \warning A removed node could become valid again if new nodes are
+ /// added to the graph.
+ bool valid(Node n) const { return Parent::valid(n); }
+ /// Edge validity check
+
+ /// This function gives back \c true if the given edge is valid,
+ /// i.e. it is a real edge of the graph.
+ ///
+ /// \warning A removed edge could become valid again if new edges are
+ /// added to the graph.
+ bool valid(Edge e) const { return Parent::valid(e); }
+ /// Arc validity check
+
+ /// This function gives back \c true if the given arc is valid,
+ /// i.e. it is a real arc of the graph.
+ ///
+ /// \warning A removed arc could become valid again if new edges are
+ /// added to the graph.
+ bool valid(Arc a) const { return Parent::valid(a); }
+
+ /// \brief Change the red node of an edge.
+ ///
+ /// This function changes the red node of the given edge \c e to \c n.
+ ///
+ ///\note \c EdgeIt and \c ArcIt iterators referencing the
+ ///changed edge are invalidated and all other iterators whose
+ ///base node is the changed node are also invalidated.
+ ///
+ ///\warning This functionality cannot be used together with the
+ ///Snapshot feature.
+ void changeRed(Edge e, RedNode n) {
+ Parent::changeRed(e, n);
+ }
+ /// \brief Change the blue node of an edge.
+ ///
+ /// This function changes the blue node of the given edge \c e to \c n.
+ ///
+ ///\note \c EdgeIt iterators referencing the changed edge remain
+ ///valid, but \c ArcIt iterators referencing the changed edge and
+ ///all other iterators whose base node is the changed node are also
+ ///invalidated.
+ ///
+ ///\warning This functionality cannot be used together with the
+ ///Snapshot feature.
+ void changeBlue(Edge e, BlueNode n) {
+ Parent::changeBlue(e, n);
+ }
+
+ ///Clear the graph.
+
+ ///This function erases all nodes and arcs from the graph.
+ ///
+ ///\note All iterators of the graph are invalidated, of course.
+ void clear() {
+ Parent::clear();
+ }
+
+ /// Reserve memory for nodes.
+
+ /// Using this function, it is possible to avoid superfluous memory
+ /// allocation: if you know that the graph you want to build will
+ /// be large (e.g. it will contain millions of nodes and/or edges),
+ /// then it is worth reserving space for this amount before starting
+ /// to build the graph.
+ /// \sa reserveEdge()
+ void reserveNode(int n) { nodes.reserve(n); };
+
+ /// Reserve memory for edges.
+
+ /// Using this function, it is possible to avoid superfluous memory
+ /// allocation: if you know that the graph you want to build will
+ /// be large (e.g. it will contain millions of nodes and/or edges),
+ /// then it is worth reserving space for this amount before starting
+ /// to build the graph.
+ /// \sa reserveNode()
+ void reserveEdge(int m) { arcs.reserve(2 * m); };
+
+ /// \brief Class to make a snapshot of the graph and restore
+ /// it later.
+ ///
+ /// Class to make a snapshot of the graph and restore it later.
+ ///
+ /// The newly added nodes and edges can be removed
+ /// using the restore() function.
+ ///
+ /// \note After a state is restored, you cannot restore a later state,
+ /// i.e. you cannot add the removed nodes and edges again using
+ /// another Snapshot instance.
+ ///
+ /// \warning Node and edge deletions and other modifications
+ /// (e.g. changing the end-nodes of edges or contracting nodes)
+ /// cannot be restored. These events invalidate the snapshot.
+ /// However, the edges and nodes that were added to the graph after
+ /// making the current snapshot can be removed without invalidating it.
+ class Snapshot {
+ protected:
+
+ typedef Parent::NodeNotifier NodeNotifier;
+
+ class NodeObserverProxy : public NodeNotifier::ObserverBase {
+ public:
+
+ NodeObserverProxy(Snapshot& _snapshot)
+ : snapshot(_snapshot) {}
+
+ using NodeNotifier::ObserverBase::attach;
+ using NodeNotifier::ObserverBase::detach;
+ using NodeNotifier::ObserverBase::attached;
+
+ protected:
+
+ virtual void add(const Node& node) {
+ snapshot.addNode(node);
+ }
+ virtual void add(const std::vector<Node>& nodes) {
+ for (int i = nodes.size() - 1; i >= 0; ++i) {
+ snapshot.addNode(nodes[i]);
+ }
+ }
+ virtual void erase(const Node& node) {
+ snapshot.eraseNode(node);
+ }
+ virtual void erase(const std::vector<Node>& nodes) {
+ for (int i = 0; i < int(nodes.size()); ++i) {
+ snapshot.eraseNode(nodes[i]);
+ }
+ }
+ virtual void build() {
+ Node node;
+ std::vector<Node> nodes;
+ for (notifier()->first(node); node != INVALID;
+ notifier()->next(node)) {
+ nodes.push_back(node);
+ }
+ for (int i = nodes.size() - 1; i >= 0; --i) {
+ snapshot.addNode(nodes[i]);
+ }
+ }
+ virtual void clear() {
+ Node node;
+ for (notifier()->first(node); node != INVALID;
+ notifier()->next(node)) {
+ snapshot.eraseNode(node);
+ }
+ }
+
+ Snapshot& snapshot;
+ };
+
+ class EdgeObserverProxy : public EdgeNotifier::ObserverBase {
+ public:
+
+ EdgeObserverProxy(Snapshot& _snapshot)
+ : snapshot(_snapshot) {}
+
+ using EdgeNotifier::ObserverBase::attach;
+ using EdgeNotifier::ObserverBase::detach;
+ using EdgeNotifier::ObserverBase::attached;
+
+ protected:
+
+ virtual void add(const Edge& edge) {
+ snapshot.addEdge(edge);
+ }
+ virtual void add(const std::vector<Edge>& edges) {
+ for (int i = edges.size() - 1; i >= 0; ++i) {
+ snapshot.addEdge(edges[i]);
+ }
+ }
+ virtual void erase(const Edge& edge) {
+ snapshot.eraseEdge(edge);
+ }
+ virtual void erase(const std::vector<Edge>& edges) {
+ for (int i = 0; i < int(edges.size()); ++i) {
+ snapshot.eraseEdge(edges[i]);
+ }
+ }
+ virtual void build() {
+ Edge edge;
+ std::vector<Edge> edges;
+ for (notifier()->first(edge); edge != INVALID;
+ notifier()->next(edge)) {
+ edges.push_back(edge);
+ }
+ for (int i = edges.size() - 1; i >= 0; --i) {
+ snapshot.addEdge(edges[i]);
+ }
+ }
+ virtual void clear() {
+ Edge edge;
+ for (notifier()->first(edge); edge != INVALID;
+ notifier()->next(edge)) {
+ snapshot.eraseEdge(edge);
+ }
+ }
+
+ Snapshot& snapshot;
+ };
+
+ ListBpGraph *graph;
+
+ NodeObserverProxy node_observer_proxy;
+ EdgeObserverProxy edge_observer_proxy;
+
+ std::list<Node> added_nodes;
+ std::list<Edge> added_edges;
+
+
+ void addNode(const Node& node) {
+ added_nodes.push_front(node);
+ }
+ void eraseNode(const Node& node) {
+ std::list<Node>::iterator it =
+ std::find(added_nodes.begin(), added_nodes.end(), node);
+ if (it == added_nodes.end()) {
+ clear();
+ edge_observer_proxy.detach();
+ throw NodeNotifier::ImmediateDetach();
+ } else {
+ added_nodes.erase(it);
+ }
+ }
+
+ void addEdge(const Edge& edge) {
+ added_edges.push_front(edge);
+ }
+ void eraseEdge(const Edge& edge) {
+ std::list<Edge>::iterator it =
+ std::find(added_edges.begin(), added_edges.end(), edge);
+ if (it == added_edges.end()) {
+ clear();
+ node_observer_proxy.detach();
+ throw EdgeNotifier::ImmediateDetach();
+ } else {
+ added_edges.erase(it);
+ }
+ }
+
+ void attach(ListBpGraph &_graph) {
+ graph = &_graph;
+ node_observer_proxy.attach(graph->notifier(Node()));
+ edge_observer_proxy.attach(graph->notifier(Edge()));
+ }
+
+ void detach() {
+ node_observer_proxy.detach();
+ edge_observer_proxy.detach();
+ }
+
+ bool attached() const {
+ return node_observer_proxy.attached();
+ }
+
+ void clear() {
+ added_nodes.clear();
+ added_edges.clear();
+ }
+
+ public:
+
+ /// \brief Default constructor.
+ ///
+ /// Default constructor.
+ /// You have to call save() to actually make a snapshot.
+ Snapshot()
+ : graph(0), node_observer_proxy(*this),
+ edge_observer_proxy(*this) {}
+
+ /// \brief Constructor that immediately makes a snapshot.
+ ///
+ /// This constructor immediately makes a snapshot of the given graph.
+ Snapshot(ListBpGraph &gr)
+ : node_observer_proxy(*this),
+ edge_observer_proxy(*this) {
+ attach(gr);
+ }
+
+ /// \brief Make a snapshot.
+ ///
+ /// This function makes a snapshot of the given graph.
+ /// It can be called more than once. In case of a repeated
+ /// call, the previous snapshot gets lost.
+ void save(ListBpGraph &gr) {
+ if (attached()) {
+ detach();
+ clear();
+ }
+ attach(gr);
+ }
+
+ /// \brief Undo the changes until the last snapshot.
+ ///
+ /// This function undos the changes until the last snapshot
+ /// created by save() or Snapshot(ListBpGraph&).
+ ///
+ /// \warning This method invalidates the snapshot, i.e. repeated
+ /// restoring is not supported unless you call save() again.
+ void restore() {
+ detach();
+ for(std::list<Edge>::iterator it = added_edges.begin();
+ it != added_edges.end(); ++it) {
+ graph->erase(*it);
+ }
+ for(std::list<Node>::iterator it = added_nodes.begin();
+ it != added_nodes.end(); ++it) {
+ graph->erase(*it);
+ }
+ clear();
+ }
+
+ /// \brief Returns \c true if the snapshot is valid.
+ ///
+ /// This function returns \c true if the snapshot is valid.
+ bool valid() const {
+ return attached();
+ }
+ };
+ };
+
+ /// @}
+} //namespace lemon
+
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/lp.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/lp.h
new file mode 100644
index 00000000000..567763f0222
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/lp.h
@@ -0,0 +1,95 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_LP_H
+#define LEMON_LP_H
+
+#include<lemon/config.h>
+
+
+#ifdef LEMON_HAVE_GLPK
+#include <lemon/glpk.h>
+#elif LEMON_HAVE_CPLEX
+#include <lemon/cplex.h>
+#elif LEMON_HAVE_SOPLEX
+#include <lemon/soplex.h>
+#elif LEMON_HAVE_CLP
+#include <lemon/clp.h>
+#elif LEMON_HAVE_CBC
+#include <lemon/cbc.h>
+#endif
+
+///\file
+///\brief Defines a default LP solver
+///\ingroup lp_group
+namespace lemon {
+
+#ifdef DOXYGEN
+ ///The default LP solver identifier
+
+ ///The default LP solver identifier.
+ ///\ingroup lp_group
+ ///
+ ///Currently, the possible values are \c _LEMON_GLPK, \c LEMON__CPLEX,
+ ///\c _LEMON_SOPLEX or \c LEMON__CLP
+#define LEMON_DEFAULT_LP SOLVER
+ ///The default LP solver
+
+ ///The default LP solver.
+ ///\ingroup lp_group
+ ///
+ ///Currently, it is either \c GlpkLp, \c CplexLp, \c SoplexLp or \c ClpLp
+ typedef GlpkLp Lp;
+
+ ///The default MIP solver identifier
+
+ ///The default MIP solver identifier.
+ ///\ingroup lp_group
+ ///
+ ///Currently, the possible values are \c _LEMON_GLPK, \c LEMON__CPLEX
+ ///or \c _LEMON_CBC
+#define LEMON_DEFAULT_MIP SOLVER
+ ///The default MIP solver.
+
+ ///The default MIP solver.
+ ///\ingroup lp_group
+ ///
+ ///Currently, it is either \c GlpkMip, \c CplexMip , \c CbcMip
+ typedef GlpkMip Mip;
+#else
+#if LEMON_DEFAULT_LP == _LEMON_GLPK
+ typedef GlpkLp Lp;
+#elif LEMON_DEFAULT_LP == _LEMON_CPLEX
+ typedef CplexLp Lp;
+#elif LEMON_DEFAULT_LP == _LEMON_SOPLEX
+ typedef SoplexLp Lp;
+#elif LEMON_DEFAULT_LP == _LEMON_CLP
+ typedef ClpLp Lp;
+#endif
+#if LEMON_DEFAULT_MIP == _LEMON_GLPK
+ typedef GlpkMip Mip;
+#elif LEMON_DEFAULT_MIP == _LEMON_CPLEX
+ typedef CplexMip Mip;
+#elif LEMON_DEFAULT_MIP == _LEMON_CBC
+ typedef CbcMip Mip;
+#endif
+#endif
+
+} //namespace lemon
+
+#endif //LEMON_LP_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/lp_base.cc b/extern/quadriflow/3rd/lemon-1.3.1/lemon/lp_base.cc
new file mode 100644
index 00000000000..312fd631f9a
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/lp_base.cc
@@ -0,0 +1,30 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\file
+///\brief The implementation of the LP solver interface.
+
+#include <lemon/lp_base.h>
+namespace lemon {
+
+ const LpBase::Value LpBase::INF =
+ std::numeric_limits<LpBase::Value>::infinity();
+ const LpBase::Value LpBase::NaN =
+ std::numeric_limits<LpBase::Value>::quiet_NaN();
+
+} //namespace lemon
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/lp_base.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/lp_base.h
new file mode 100644
index 00000000000..22d3e4899fe
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/lp_base.h
@@ -0,0 +1,2147 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_LP_BASE_H
+#define LEMON_LP_BASE_H
+
+#include<iostream>
+#include<vector>
+#include<map>
+#include<limits>
+#include<lemon/math.h>
+
+#include<lemon/error.h>
+#include<lemon/assert.h>
+
+#include<lemon/core.h>
+#include<lemon/bits/solver_bits.h>
+
+///\file
+///\brief The interface of the LP solver interface.
+///\ingroup lp_group
+namespace lemon {
+
+ ///Common base class for LP and MIP solvers
+
+ ///Usually this class is not used directly, please use one of the concrete
+ ///implementations of the solver interface.
+ ///\ingroup lp_group
+ class LpBase {
+
+ protected:
+
+ _solver_bits::VarIndex rows;
+ _solver_bits::VarIndex cols;
+
+ public:
+
+ ///Possible outcomes of an LP solving procedure
+ enum SolveExitStatus {
+ /// = 0. It means that the problem has been successfully solved: either
+ ///an optimal solution has been found or infeasibility/unboundedness
+ ///has been proved.
+ SOLVED = 0,
+ /// = 1. Any other case (including the case when some user specified
+ ///limit has been exceeded).
+ UNSOLVED = 1
+ };
+
+ ///Direction of the optimization
+ enum Sense {
+ /// Minimization
+ MIN,
+ /// Maximization
+ MAX
+ };
+
+ ///Enum for \c messageLevel() parameter
+ enum MessageLevel {
+ /// No output (default value).
+ MESSAGE_NOTHING,
+ /// Error messages only.
+ MESSAGE_ERROR,
+ /// Warnings.
+ MESSAGE_WARNING,
+ /// Normal output.
+ MESSAGE_NORMAL,
+ /// Verbose output.
+ MESSAGE_VERBOSE
+ };
+
+
+ ///The floating point type used by the solver
+ typedef double Value;
+ ///The infinity constant
+ static const Value INF;
+ ///The not a number constant
+ static const Value NaN;
+
+ friend class Col;
+ friend class ColIt;
+ friend class Row;
+ friend class RowIt;
+
+ ///Refer to a column of the LP.
+
+ ///This type is used to refer to a column of the LP.
+ ///
+ ///Its value remains valid and correct even after the addition or erase of
+ ///other columns.
+ ///
+ ///\note This class is similar to other Item types in LEMON, like
+ ///Node and Arc types in digraph.
+ class Col {
+ friend class LpBase;
+ protected:
+ int _id;
+ explicit Col(int id) : _id(id) {}
+ public:
+ typedef Value ExprValue;
+ typedef True LpCol;
+ /// Default constructor
+
+ /// \warning The default constructor sets the Col to an
+ /// undefined value.
+ Col() {}
+ /// Invalid constructor \& conversion.
+
+ /// This constructor initializes the Col to be invalid.
+ /// \sa Invalid for more details.
+ Col(const Invalid&) : _id(-1) {}
+ /// Equality operator
+
+ /// Two \ref Col "Col"s are equal if and only if they point to
+ /// the same LP column or both are invalid.
+ bool operator==(Col c) const {return _id == c._id;}
+ /// Inequality operator
+
+ /// \sa operator==(Col c)
+ ///
+ bool operator!=(Col c) const {return _id != c._id;}
+ /// Artificial ordering operator.
+
+ /// To allow the use of this object in std::map or similar
+ /// associative container we require this.
+ ///
+ /// \note This operator only have to define some strict ordering of
+ /// the items; this order has nothing to do with the iteration
+ /// ordering of the items.
+ bool operator<(Col c) const {return _id < c._id;}
+ };
+
+ ///Iterator for iterate over the columns of an LP problem
+
+ /// Its usage is quite simple, for example, you can count the number
+ /// of columns in an LP \c lp:
+ ///\code
+ /// int count=0;
+ /// for (LpBase::ColIt c(lp); c!=INVALID; ++c) ++count;
+ ///\endcode
+ class ColIt : public Col {
+ const LpBase *_solver;
+ public:
+ /// Default constructor
+
+ /// \warning The default constructor sets the iterator
+ /// to an undefined value.
+ ColIt() {}
+ /// Sets the iterator to the first Col
+
+ /// Sets the iterator to the first Col.
+ ///
+ ColIt(const LpBase &solver) : _solver(&solver)
+ {
+ _solver->cols.firstItem(_id);
+ }
+ /// Invalid constructor \& conversion
+
+ /// Initialize the iterator to be invalid.
+ /// \sa Invalid for more details.
+ ColIt(const Invalid&) : Col(INVALID) {}
+ /// Next column
+
+ /// Assign the iterator to the next column.
+ ///
+ ColIt &operator++()
+ {
+ _solver->cols.nextItem(_id);
+ return *this;
+ }
+ };
+
+ /// \brief Returns the ID of the column.
+ static int id(const Col& col) { return col._id; }
+ /// \brief Returns the column with the given ID.
+ ///
+ /// \pre The argument should be a valid column ID in the LP problem.
+ static Col colFromId(int id) { return Col(id); }
+
+ ///Refer to a row of the LP.
+
+ ///This type is used to refer to a row of the LP.
+ ///
+ ///Its value remains valid and correct even after the addition or erase of
+ ///other rows.
+ ///
+ ///\note This class is similar to other Item types in LEMON, like
+ ///Node and Arc types in digraph.
+ class Row {
+ friend class LpBase;
+ protected:
+ int _id;
+ explicit Row(int id) : _id(id) {}
+ public:
+ typedef Value ExprValue;
+ typedef True LpRow;
+ /// Default constructor
+
+ /// \warning The default constructor sets the Row to an
+ /// undefined value.
+ Row() {}
+ /// Invalid constructor \& conversion.
+
+ /// This constructor initializes the Row to be invalid.
+ /// \sa Invalid for more details.
+ Row(const Invalid&) : _id(-1) {}
+ /// Equality operator
+
+ /// Two \ref Row "Row"s are equal if and only if they point to
+ /// the same LP row or both are invalid.
+ bool operator==(Row r) const {return _id == r._id;}
+ /// Inequality operator
+
+ /// \sa operator==(Row r)
+ ///
+ bool operator!=(Row r) const {return _id != r._id;}
+ /// Artificial ordering operator.
+
+ /// To allow the use of this object in std::map or similar
+ /// associative container we require this.
+ ///
+ /// \note This operator only have to define some strict ordering of
+ /// the items; this order has nothing to do with the iteration
+ /// ordering of the items.
+ bool operator<(Row r) const {return _id < r._id;}
+ };
+
+ ///Iterator for iterate over the rows of an LP problem
+
+ /// Its usage is quite simple, for example, you can count the number
+ /// of rows in an LP \c lp:
+ ///\code
+ /// int count=0;
+ /// for (LpBase::RowIt c(lp); c!=INVALID; ++c) ++count;
+ ///\endcode
+ class RowIt : public Row {
+ const LpBase *_solver;
+ public:
+ /// Default constructor
+
+ /// \warning The default constructor sets the iterator
+ /// to an undefined value.
+ RowIt() {}
+ /// Sets the iterator to the first Row
+
+ /// Sets the iterator to the first Row.
+ ///
+ RowIt(const LpBase &solver) : _solver(&solver)
+ {
+ _solver->rows.firstItem(_id);
+ }
+ /// Invalid constructor \& conversion
+
+ /// Initialize the iterator to be invalid.
+ /// \sa Invalid for more details.
+ RowIt(const Invalid&) : Row(INVALID) {}
+ /// Next row
+
+ /// Assign the iterator to the next row.
+ ///
+ RowIt &operator++()
+ {
+ _solver->rows.nextItem(_id);
+ return *this;
+ }
+ };
+
+ /// \brief Returns the ID of the row.
+ static int id(const Row& row) { return row._id; }
+ /// \brief Returns the row with the given ID.
+ ///
+ /// \pre The argument should be a valid row ID in the LP problem.
+ static Row rowFromId(int id) { return Row(id); }
+
+ public:
+
+ ///Linear expression of variables and a constant component
+
+ ///This data structure stores a linear expression of the variables
+ ///(\ref Col "Col"s) and also has a constant component.
+ ///
+ ///There are several ways to access and modify the contents of this
+ ///container.
+ ///\code
+ ///e[v]=5;
+ ///e[v]+=12;
+ ///e.erase(v);
+ ///\endcode
+ ///or you can also iterate through its elements.
+ ///\code
+ ///double s=0;
+ ///for(LpBase::Expr::ConstCoeffIt i(e);i!=INVALID;++i)
+ /// s+=*i * primal(i);
+ ///\endcode
+ ///(This code computes the primal value of the expression).
+ ///- Numbers (<tt>double</tt>'s)
+ ///and variables (\ref Col "Col"s) directly convert to an
+ ///\ref Expr and the usual linear operations are defined, so
+ ///\code
+ ///v+w
+ ///2*v-3.12*(v-w/2)+2
+ ///v*2.1+(3*v+(v*12+w+6)*3)/2
+ ///\endcode
+ ///are valid expressions.
+ ///The usual assignment operations are also defined.
+ ///\code
+ ///e=v+w;
+ ///e+=2*v-3.12*(v-w/2)+2;
+ ///e*=3.4;
+ ///e/=5;
+ ///\endcode
+ ///- The constant member can be set and read by dereference
+ /// operator (unary *)
+ ///
+ ///\code
+ ///*e=12;
+ ///double c=*e;
+ ///\endcode
+ ///
+ ///\sa Constr
+ class Expr {
+ friend class LpBase;
+ public:
+ /// The key type of the expression
+ typedef LpBase::Col Key;
+ /// The value type of the expression
+ typedef LpBase::Value Value;
+
+ protected:
+ Value const_comp;
+ std::map<int, Value> comps;
+
+ public:
+ typedef True SolverExpr;
+ /// Default constructor
+
+ /// Construct an empty expression, the coefficients and
+ /// the constant component are initialized to zero.
+ Expr() : const_comp(0) {}
+ /// Construct an expression from a column
+
+ /// Construct an expression, which has a term with \c c variable
+ /// and 1.0 coefficient.
+ Expr(const Col &c) : const_comp(0) {
+ typedef std::map<int, Value>::value_type pair_type;
+ comps.insert(pair_type(id(c), 1));
+ }
+ /// Construct an expression from a constant
+
+ /// Construct an expression, which's constant component is \c v.
+ ///
+ Expr(const Value &v) : const_comp(v) {}
+ /// Returns the coefficient of the column
+ Value operator[](const Col& c) const {
+ std::map<int, Value>::const_iterator it=comps.find(id(c));
+ if (it != comps.end()) {
+ return it->second;
+ } else {
+ return 0;
+ }
+ }
+ /// Returns the coefficient of the column
+ Value& operator[](const Col& c) {
+ return comps[id(c)];
+ }
+ /// Sets the coefficient of the column
+ void set(const Col &c, const Value &v) {
+ if (v != 0.0) {
+ typedef std::map<int, Value>::value_type pair_type;
+ comps.insert(pair_type(id(c), v));
+ } else {
+ comps.erase(id(c));
+ }
+ }
+ /// Returns the constant component of the expression
+ Value& operator*() { return const_comp; }
+ /// Returns the constant component of the expression
+ const Value& operator*() const { return const_comp; }
+ /// \brief Removes the coefficients which's absolute value does
+ /// not exceed \c epsilon. It also sets to zero the constant
+ /// component, if it does not exceed epsilon in absolute value.
+ void simplify(Value epsilon = 0.0) {
+ std::map<int, Value>::iterator it=comps.begin();
+ while (it != comps.end()) {
+ std::map<int, Value>::iterator jt=it;
+ ++jt;
+ if (std::fabs((*it).second) <= epsilon) comps.erase(it);
+ it=jt;
+ }
+ if (std::fabs(const_comp) <= epsilon) const_comp = 0;
+ }
+
+ void simplify(Value epsilon = 0.0) const {
+ const_cast<Expr*>(this)->simplify(epsilon);
+ }
+
+ ///Sets all coefficients and the constant component to 0.
+ void clear() {
+ comps.clear();
+ const_comp=0;
+ }
+
+ ///Compound assignment
+ Expr &operator+=(const Expr &e) {
+ for (std::map<int, Value>::const_iterator it=e.comps.begin();
+ it!=e.comps.end(); ++it)
+ comps[it->first]+=it->second;
+ const_comp+=e.const_comp;
+ return *this;
+ }
+ ///Compound assignment
+ Expr &operator-=(const Expr &e) {
+ for (std::map<int, Value>::const_iterator it=e.comps.begin();
+ it!=e.comps.end(); ++it)
+ comps[it->first]-=it->second;
+ const_comp-=e.const_comp;
+ return *this;
+ }
+ ///Multiply with a constant
+ Expr &operator*=(const Value &v) {
+ for (std::map<int, Value>::iterator it=comps.begin();
+ it!=comps.end(); ++it)
+ it->second*=v;
+ const_comp*=v;
+ return *this;
+ }
+ ///Division with a constant
+ Expr &operator/=(const Value &c) {
+ for (std::map<int, Value>::iterator it=comps.begin();
+ it!=comps.end(); ++it)
+ it->second/=c;
+ const_comp/=c;
+ return *this;
+ }
+
+ ///Iterator over the expression
+
+ ///The iterator iterates over the terms of the expression.
+ ///
+ ///\code
+ ///double s=0;
+ ///for(LpBase::Expr::CoeffIt i(e);i!=INVALID;++i)
+ /// s+= *i * primal(i);
+ ///\endcode
+ class CoeffIt {
+ private:
+
+ std::map<int, Value>::iterator _it, _end;
+
+ public:
+
+ /// Sets the iterator to the first term
+
+ /// Sets the iterator to the first term of the expression.
+ ///
+ CoeffIt(Expr& e)
+ : _it(e.comps.begin()), _end(e.comps.end()){}
+
+ /// Convert the iterator to the column of the term
+ operator Col() const {
+ return colFromId(_it->first);
+ }
+
+ /// Returns the coefficient of the term
+ Value& operator*() { return _it->second; }
+
+ /// Returns the coefficient of the term
+ const Value& operator*() const { return _it->second; }
+ /// Next term
+
+ /// Assign the iterator to the next term.
+ ///
+ CoeffIt& operator++() { ++_it; return *this; }
+
+ /// Equality operator
+ bool operator==(Invalid) const { return _it == _end; }
+ /// Inequality operator
+ bool operator!=(Invalid) const { return _it != _end; }
+ };
+
+ /// Const iterator over the expression
+
+ ///The iterator iterates over the terms of the expression.
+ ///
+ ///\code
+ ///double s=0;
+ ///for(LpBase::Expr::ConstCoeffIt i(e);i!=INVALID;++i)
+ /// s+=*i * primal(i);
+ ///\endcode
+ class ConstCoeffIt {
+ private:
+
+ std::map<int, Value>::const_iterator _it, _end;
+
+ public:
+
+ /// Sets the iterator to the first term
+
+ /// Sets the iterator to the first term of the expression.
+ ///
+ ConstCoeffIt(const Expr& e)
+ : _it(e.comps.begin()), _end(e.comps.end()){}
+
+ /// Convert the iterator to the column of the term
+ operator Col() const {
+ return colFromId(_it->first);
+ }
+
+ /// Returns the coefficient of the term
+ const Value& operator*() const { return _it->second; }
+
+ /// Next term
+
+ /// Assign the iterator to the next term.
+ ///
+ ConstCoeffIt& operator++() { ++_it; return *this; }
+
+ /// Equality operator
+ bool operator==(Invalid) const { return _it == _end; }
+ /// Inequality operator
+ bool operator!=(Invalid) const { return _it != _end; }
+ };
+
+ };
+
+ ///Linear constraint
+
+ ///This data stucture represents a linear constraint in the LP.
+ ///Basically it is a linear expression with a lower or an upper bound
+ ///(or both). These parts of the constraint can be obtained by the member
+ ///functions \ref expr(), \ref lowerBound() and \ref upperBound(),
+ ///respectively.
+ ///There are two ways to construct a constraint.
+ ///- You can set the linear expression and the bounds directly
+ /// by the functions above.
+ ///- The operators <tt>\<=</tt>, <tt>==</tt> and <tt>\>=</tt>
+ /// are defined between expressions, or even between constraints whenever
+ /// it makes sense. Therefore if \c e and \c f are linear expressions and
+ /// \c s and \c t are numbers, then the followings are valid expressions
+ /// and thus they can be used directly e.g. in \ref addRow() whenever
+ /// it makes sense.
+ ///\code
+ /// e<=s
+ /// e<=f
+ /// e==f
+ /// s<=e<=t
+ /// e>=t
+ ///\endcode
+ ///\warning The validity of a constraint is checked only at run
+ ///time, so e.g. \ref addRow(<tt>x[1]\<=x[2]<=5</tt>) will
+ ///compile, but will fail an assertion.
+ class Constr
+ {
+ public:
+ typedef LpBase::Expr Expr;
+ typedef Expr::Key Key;
+ typedef Expr::Value Value;
+
+ protected:
+ Expr _expr;
+ Value _lb,_ub;
+ public:
+ ///\e
+ Constr() : _expr(), _lb(NaN), _ub(NaN) {}
+ ///\e
+ Constr(Value lb, const Expr &e, Value ub) :
+ _expr(e), _lb(lb), _ub(ub) {}
+ Constr(const Expr &e) :
+ _expr(e), _lb(NaN), _ub(NaN) {}
+ ///\e
+ void clear()
+ {
+ _expr.clear();
+ _lb=_ub=NaN;
+ }
+
+ ///Reference to the linear expression
+ Expr &expr() { return _expr; }
+ ///Cont reference to the linear expression
+ const Expr &expr() const { return _expr; }
+ ///Reference to the lower bound.
+
+ ///\return
+ ///- \ref INF "INF": the constraint is lower unbounded.
+ ///- \ref NaN "NaN": lower bound has not been set.
+ ///- finite number: the lower bound
+ Value &lowerBound() { return _lb; }
+ ///The const version of \ref lowerBound()
+ const Value &lowerBound() const { return _lb; }
+ ///Reference to the upper bound.
+
+ ///\return
+ ///- \ref INF "INF": the constraint is upper unbounded.
+ ///- \ref NaN "NaN": upper bound has not been set.
+ ///- finite number: the upper bound
+ Value &upperBound() { return _ub; }
+ ///The const version of \ref upperBound()
+ const Value &upperBound() const { return _ub; }
+ ///Is the constraint lower bounded?
+ bool lowerBounded() const {
+ return _lb != -INF && !isNaN(_lb);
+ }
+ ///Is the constraint upper bounded?
+ bool upperBounded() const {
+ return _ub != INF && !isNaN(_ub);
+ }
+
+ };
+
+ ///Linear expression of rows
+
+ ///This data structure represents a column of the matrix,
+ ///thas is it strores a linear expression of the dual variables
+ ///(\ref Row "Row"s).
+ ///
+ ///There are several ways to access and modify the contents of this
+ ///container.
+ ///\code
+ ///e[v]=5;
+ ///e[v]+=12;
+ ///e.erase(v);
+ ///\endcode
+ ///or you can also iterate through its elements.
+ ///\code
+ ///double s=0;
+ ///for(LpBase::DualExpr::ConstCoeffIt i(e);i!=INVALID;++i)
+ /// s+=*i;
+ ///\endcode
+ ///(This code computes the sum of all coefficients).
+ ///- Numbers (<tt>double</tt>'s)
+ ///and variables (\ref Row "Row"s) directly convert to an
+ ///\ref DualExpr and the usual linear operations are defined, so
+ ///\code
+ ///v+w
+ ///2*v-3.12*(v-w/2)
+ ///v*2.1+(3*v+(v*12+w)*3)/2
+ ///\endcode
+ ///are valid \ref DualExpr dual expressions.
+ ///The usual assignment operations are also defined.
+ ///\code
+ ///e=v+w;
+ ///e+=2*v-3.12*(v-w/2);
+ ///e*=3.4;
+ ///e/=5;
+ ///\endcode
+ ///
+ ///\sa Expr
+ class DualExpr {
+ friend class LpBase;
+ public:
+ /// The key type of the expression
+ typedef LpBase::Row Key;
+ /// The value type of the expression
+ typedef LpBase::Value Value;
+
+ protected:
+ std::map<int, Value> comps;
+
+ public:
+ typedef True SolverExpr;
+ /// Default constructor
+
+ /// Construct an empty expression, the coefficients are
+ /// initialized to zero.
+ DualExpr() {}
+ /// Construct an expression from a row
+
+ /// Construct an expression, which has a term with \c r dual
+ /// variable and 1.0 coefficient.
+ DualExpr(const Row &r) {
+ typedef std::map<int, Value>::value_type pair_type;
+ comps.insert(pair_type(id(r), 1));
+ }
+ /// Returns the coefficient of the row
+ Value operator[](const Row& r) const {
+ std::map<int, Value>::const_iterator it = comps.find(id(r));
+ if (it != comps.end()) {
+ return it->second;
+ } else {
+ return 0;
+ }
+ }
+ /// Returns the coefficient of the row
+ Value& operator[](const Row& r) {
+ return comps[id(r)];
+ }
+ /// Sets the coefficient of the row
+ void set(const Row &r, const Value &v) {
+ if (v != 0.0) {
+ typedef std::map<int, Value>::value_type pair_type;
+ comps.insert(pair_type(id(r), v));
+ } else {
+ comps.erase(id(r));
+ }
+ }
+ /// \brief Removes the coefficients which's absolute value does
+ /// not exceed \c epsilon.
+ void simplify(Value epsilon = 0.0) {
+ std::map<int, Value>::iterator it=comps.begin();
+ while (it != comps.end()) {
+ std::map<int, Value>::iterator jt=it;
+ ++jt;
+ if (std::fabs((*it).second) <= epsilon) comps.erase(it);
+ it=jt;
+ }
+ }
+
+ void simplify(Value epsilon = 0.0) const {
+ const_cast<DualExpr*>(this)->simplify(epsilon);
+ }
+
+ ///Sets all coefficients to 0.
+ void clear() {
+ comps.clear();
+ }
+ ///Compound assignment
+ DualExpr &operator+=(const DualExpr &e) {
+ for (std::map<int, Value>::const_iterator it=e.comps.begin();
+ it!=e.comps.end(); ++it)
+ comps[it->first]+=it->second;
+ return *this;
+ }
+ ///Compound assignment
+ DualExpr &operator-=(const DualExpr &e) {
+ for (std::map<int, Value>::const_iterator it=e.comps.begin();
+ it!=e.comps.end(); ++it)
+ comps[it->first]-=it->second;
+ return *this;
+ }
+ ///Multiply with a constant
+ DualExpr &operator*=(const Value &v) {
+ for (std::map<int, Value>::iterator it=comps.begin();
+ it!=comps.end(); ++it)
+ it->second*=v;
+ return *this;
+ }
+ ///Division with a constant
+ DualExpr &operator/=(const Value &v) {
+ for (std::map<int, Value>::iterator it=comps.begin();
+ it!=comps.end(); ++it)
+ it->second/=v;
+ return *this;
+ }
+
+ ///Iterator over the expression
+
+ ///The iterator iterates over the terms of the expression.
+ ///
+ ///\code
+ ///double s=0;
+ ///for(LpBase::DualExpr::CoeffIt i(e);i!=INVALID;++i)
+ /// s+= *i * dual(i);
+ ///\endcode
+ class CoeffIt {
+ private:
+
+ std::map<int, Value>::iterator _it, _end;
+
+ public:
+
+ /// Sets the iterator to the first term
+
+ /// Sets the iterator to the first term of the expression.
+ ///
+ CoeffIt(DualExpr& e)
+ : _it(e.comps.begin()), _end(e.comps.end()){}
+
+ /// Convert the iterator to the row of the term
+ operator Row() const {
+ return rowFromId(_it->first);
+ }
+
+ /// Returns the coefficient of the term
+ Value& operator*() { return _it->second; }
+
+ /// Returns the coefficient of the term
+ const Value& operator*() const { return _it->second; }
+
+ /// Next term
+
+ /// Assign the iterator to the next term.
+ ///
+ CoeffIt& operator++() { ++_it; return *this; }
+
+ /// Equality operator
+ bool operator==(Invalid) const { return _it == _end; }
+ /// Inequality operator
+ bool operator!=(Invalid) const { return _it != _end; }
+ };
+
+ ///Iterator over the expression
+
+ ///The iterator iterates over the terms of the expression.
+ ///
+ ///\code
+ ///double s=0;
+ ///for(LpBase::DualExpr::ConstCoeffIt i(e);i!=INVALID;++i)
+ /// s+= *i * dual(i);
+ ///\endcode
+ class ConstCoeffIt {
+ private:
+
+ std::map<int, Value>::const_iterator _it, _end;
+
+ public:
+
+ /// Sets the iterator to the first term
+
+ /// Sets the iterator to the first term of the expression.
+ ///
+ ConstCoeffIt(const DualExpr& e)
+ : _it(e.comps.begin()), _end(e.comps.end()){}
+
+ /// Convert the iterator to the row of the term
+ operator Row() const {
+ return rowFromId(_it->first);
+ }
+
+ /// Returns the coefficient of the term
+ const Value& operator*() const { return _it->second; }
+
+ /// Next term
+
+ /// Assign the iterator to the next term.
+ ///
+ ConstCoeffIt& operator++() { ++_it; return *this; }
+
+ /// Equality operator
+ bool operator==(Invalid) const { return _it == _end; }
+ /// Inequality operator
+ bool operator!=(Invalid) const { return _it != _end; }
+ };
+ };
+
+
+ protected:
+
+ class InsertIterator {
+ private:
+
+ std::map<int, Value>& _host;
+ const _solver_bits::VarIndex& _index;
+
+ public:
+
+ typedef std::output_iterator_tag iterator_category;
+ typedef void difference_type;
+ typedef void value_type;
+ typedef void reference;
+ typedef void pointer;
+
+ InsertIterator(std::map<int, Value>& host,
+ const _solver_bits::VarIndex& index)
+ : _host(host), _index(index) {}
+
+ InsertIterator& operator=(const std::pair<int, Value>& value) {
+ typedef std::map<int, Value>::value_type pair_type;
+ _host.insert(pair_type(_index[value.first], value.second));
+ return *this;
+ }
+
+ InsertIterator& operator*() { return *this; }
+ InsertIterator& operator++() { return *this; }
+ InsertIterator operator++(int) { return *this; }
+
+ };
+
+ class ExprIterator {
+ private:
+ std::map<int, Value>::const_iterator _host_it;
+ const _solver_bits::VarIndex& _index;
+ public:
+
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+ typedef const std::pair<int, Value> value_type;
+ typedef value_type reference;
+
+ class pointer {
+ public:
+ pointer(value_type& _value) : value(_value) {}
+ value_type* operator->() { return &value; }
+ private:
+ value_type value;
+ };
+
+ ExprIterator(const std::map<int, Value>::const_iterator& host_it,
+ const _solver_bits::VarIndex& index)
+ : _host_it(host_it), _index(index) {}
+
+ reference operator*() {
+ return std::make_pair(_index(_host_it->first), _host_it->second);
+ }
+
+ pointer operator->() {
+ return pointer(operator*());
+ }
+
+ ExprIterator& operator++() { ++_host_it; return *this; }
+ ExprIterator operator++(int) {
+ ExprIterator tmp(*this); ++_host_it; return tmp;
+ }
+
+ ExprIterator& operator--() { --_host_it; return *this; }
+ ExprIterator operator--(int) {
+ ExprIterator tmp(*this); --_host_it; return tmp;
+ }
+
+ bool operator==(const ExprIterator& it) const {
+ return _host_it == it._host_it;
+ }
+
+ bool operator!=(const ExprIterator& it) const {
+ return _host_it != it._host_it;
+ }
+
+ };
+
+ protected:
+
+ //Abstract virtual functions
+
+ virtual int _addColId(int col) { return cols.addIndex(col); }
+ virtual int _addRowId(int row) { return rows.addIndex(row); }
+
+ virtual void _eraseColId(int col) { cols.eraseIndex(col); }
+ virtual void _eraseRowId(int row) { rows.eraseIndex(row); }
+
+ virtual int _addCol() = 0;
+ virtual int _addRow() = 0;
+
+ virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u) {
+ int row = _addRow();
+ _setRowCoeffs(row, b, e);
+ _setRowLowerBound(row, l);
+ _setRowUpperBound(row, u);
+ return row;
+ }
+
+ virtual void _eraseCol(int col) = 0;
+ virtual void _eraseRow(int row) = 0;
+
+ virtual void _getColName(int col, std::string& name) const = 0;
+ virtual void _setColName(int col, const std::string& name) = 0;
+ virtual int _colByName(const std::string& name) const = 0;
+
+ virtual void _getRowName(int row, std::string& name) const = 0;
+ virtual void _setRowName(int row, const std::string& name) = 0;
+ virtual int _rowByName(const std::string& name) const = 0;
+
+ virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e) = 0;
+ virtual void _getRowCoeffs(int i, InsertIterator b) const = 0;
+
+ virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e) = 0;
+ virtual void _getColCoeffs(int i, InsertIterator b) const = 0;
+
+ virtual void _setCoeff(int row, int col, Value value) = 0;
+ virtual Value _getCoeff(int row, int col) const = 0;
+
+ virtual void _setColLowerBound(int i, Value value) = 0;
+ virtual Value _getColLowerBound(int i) const = 0;
+
+ virtual void _setColUpperBound(int i, Value value) = 0;
+ virtual Value _getColUpperBound(int i) const = 0;
+
+ virtual void _setRowLowerBound(int i, Value value) = 0;
+ virtual Value _getRowLowerBound(int i) const = 0;
+
+ virtual void _setRowUpperBound(int i, Value value) = 0;
+ virtual Value _getRowUpperBound(int i) const = 0;
+
+ virtual void _setObjCoeffs(ExprIterator b, ExprIterator e) = 0;
+ virtual void _getObjCoeffs(InsertIterator b) const = 0;
+
+ virtual void _setObjCoeff(int i, Value obj_coef) = 0;
+ virtual Value _getObjCoeff(int i) const = 0;
+
+ virtual void _setSense(Sense) = 0;
+ virtual Sense _getSense() const = 0;
+
+ virtual void _clear() = 0;
+
+ virtual const char* _solverName() const = 0;
+
+ virtual void _messageLevel(MessageLevel level) = 0;
+
+ //Own protected stuff
+
+ //Constant component of the objective function
+ Value obj_const_comp;
+
+ LpBase() : rows(), cols(), obj_const_comp(0) {}
+
+ public:
+
+ ///Unsupported file format exception
+ class UnsupportedFormatError : public Exception
+ {
+ std::string _format;
+ mutable std::string _what;
+ public:
+ explicit UnsupportedFormatError(std::string format) throw()
+ : _format(format) { }
+ virtual ~UnsupportedFormatError() throw() {}
+ virtual const char* what() const throw() {
+ try {
+ _what.clear();
+ std::ostringstream oss;
+ oss << "lemon::UnsupportedFormatError: " << _format;
+ _what = oss.str();
+ }
+ catch (...) {}
+ if (!_what.empty()) return _what.c_str();
+ else return "lemon::UnsupportedFormatError";
+ }
+ };
+
+ protected:
+ virtual void _write(std::string, std::string format) const
+ {
+ throw UnsupportedFormatError(format);
+ }
+
+ public:
+
+ /// Virtual destructor
+ virtual ~LpBase() {}
+
+ ///Gives back the name of the solver.
+ const char* solverName() const {return _solverName();}
+
+ ///\name Build Up and Modify the LP
+
+ ///@{
+
+ ///Add a new empty column (i.e a new variable) to the LP
+ Col addCol() { Col c; c._id = _addColId(_addCol()); return c;}
+
+ ///\brief Adds several new columns (i.e variables) at once
+ ///
+ ///This magic function takes a container as its argument and fills
+ ///its elements with new columns (i.e. variables)
+ ///\param t can be
+ ///- a standard STL compatible iterable container with
+ ///\ref Col as its \c values_type like
+ ///\code
+ ///std::vector<LpBase::Col>
+ ///std::list<LpBase::Col>
+ ///\endcode
+ ///- a standard STL compatible iterable container with
+ ///\ref Col as its \c mapped_type like
+ ///\code
+ ///std::map<AnyType,LpBase::Col>
+ ///\endcode
+ ///- an iterable lemon \ref concepts::WriteMap "write map" like
+ ///\code
+ ///ListGraph::NodeMap<LpBase::Col>
+ ///ListGraph::ArcMap<LpBase::Col>
+ ///\endcode
+ ///\return The number of the created column.
+#ifdef DOXYGEN
+ template<class T>
+ int addColSet(T &t) { return 0;}
+#else
+ template<class T>
+ typename enable_if<typename T::value_type::LpCol,int>::type
+ addColSet(T &t,dummy<0> = 0) {
+ int s=0;
+ for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addCol();s++;}
+ return s;
+ }
+ template<class T>
+ typename enable_if<typename T::value_type::second_type::LpCol,
+ int>::type
+ addColSet(T &t,dummy<1> = 1) {
+ int s=0;
+ for(typename T::iterator i=t.begin();i!=t.end();++i) {
+ i->second=addCol();
+ s++;
+ }
+ return s;
+ }
+ template<class T>
+ typename enable_if<typename T::MapIt::Value::LpCol,
+ int>::type
+ addColSet(T &t,dummy<2> = 2) {
+ int s=0;
+ for(typename T::MapIt i(t); i!=INVALID; ++i)
+ {
+ i.set(addCol());
+ s++;
+ }
+ return s;
+ }
+#endif
+
+ ///Set a column (i.e a dual constraint) of the LP
+
+ ///\param c is the column to be modified
+ ///\param e is a dual linear expression (see \ref DualExpr)
+ ///a better one.
+ void col(Col c, const DualExpr &e) {
+ e.simplify();
+ _setColCoeffs(cols(id(c)), ExprIterator(e.comps.begin(), rows),
+ ExprIterator(e.comps.end(), rows));
+ }
+
+ ///Get a column (i.e a dual constraint) of the LP
+
+ ///\param c is the column to get
+ ///\return the dual expression associated to the column
+ DualExpr col(Col c) const {
+ DualExpr e;
+ _getColCoeffs(cols(id(c)), InsertIterator(e.comps, rows));
+ return e;
+ }
+
+ ///Add a new column to the LP
+
+ ///\param e is a dual linear expression (see \ref DualExpr)
+ ///\param o is the corresponding component of the objective
+ ///function. It is 0 by default.
+ ///\return The created column.
+ Col addCol(const DualExpr &e, Value o = 0) {
+ Col c=addCol();
+ col(c,e);
+ objCoeff(c,o);
+ return c;
+ }
+
+ ///Add a new empty row (i.e a new constraint) to the LP
+
+ ///This function adds a new empty row (i.e a new constraint) to the LP.
+ ///\return The created row
+ Row addRow() { Row r; r._id = _addRowId(_addRow()); return r;}
+
+ ///\brief Add several new rows (i.e constraints) at once
+ ///
+ ///This magic function takes a container as its argument and fills
+ ///its elements with new row (i.e. variables)
+ ///\param t can be
+ ///- a standard STL compatible iterable container with
+ ///\ref Row as its \c values_type like
+ ///\code
+ ///std::vector<LpBase::Row>
+ ///std::list<LpBase::Row>
+ ///\endcode
+ ///- a standard STL compatible iterable container with
+ ///\ref Row as its \c mapped_type like
+ ///\code
+ ///std::map<AnyType,LpBase::Row>
+ ///\endcode
+ ///- an iterable lemon \ref concepts::WriteMap "write map" like
+ ///\code
+ ///ListGraph::NodeMap<LpBase::Row>
+ ///ListGraph::ArcMap<LpBase::Row>
+ ///\endcode
+ ///\return The number of rows created.
+#ifdef DOXYGEN
+ template<class T>
+ int addRowSet(T &t) { return 0;}
+#else
+ template<class T>
+ typename enable_if<typename T::value_type::LpRow,int>::type
+ addRowSet(T &t, dummy<0> = 0) {
+ int s=0;
+ for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addRow();s++;}
+ return s;
+ }
+ template<class T>
+ typename enable_if<typename T::value_type::second_type::LpRow, int>::type
+ addRowSet(T &t, dummy<1> = 1) {
+ int s=0;
+ for(typename T::iterator i=t.begin();i!=t.end();++i) {
+ i->second=addRow();
+ s++;
+ }
+ return s;
+ }
+ template<class T>
+ typename enable_if<typename T::MapIt::Value::LpRow, int>::type
+ addRowSet(T &t, dummy<2> = 2) {
+ int s=0;
+ for(typename T::MapIt i(t); i!=INVALID; ++i)
+ {
+ i.set(addRow());
+ s++;
+ }
+ return s;
+ }
+#endif
+
+ ///Set a row (i.e a constraint) of the LP
+
+ ///\param r is the row to be modified
+ ///\param l is lower bound (-\ref INF means no bound)
+ ///\param e is a linear expression (see \ref Expr)
+ ///\param u is the upper bound (\ref INF means no bound)
+ void row(Row r, Value l, const Expr &e, Value u) {
+ e.simplify();
+ _setRowCoeffs(rows(id(r)), ExprIterator(e.comps.begin(), cols),
+ ExprIterator(e.comps.end(), cols));
+ _setRowLowerBound(rows(id(r)),l - *e);
+ _setRowUpperBound(rows(id(r)),u - *e);
+ }
+
+ ///Set a row (i.e a constraint) of the LP
+
+ ///\param r is the row to be modified
+ ///\param c is a linear expression (see \ref Constr)
+ void row(Row r, const Constr &c) {
+ row(r, c.lowerBounded()?c.lowerBound():-INF,
+ c.expr(), c.upperBounded()?c.upperBound():INF);
+ }
+
+
+ ///Get a row (i.e a constraint) of the LP
+
+ ///\param r is the row to get
+ ///\return the expression associated to the row
+ Expr row(Row r) const {
+ Expr e;
+ _getRowCoeffs(rows(id(r)), InsertIterator(e.comps, cols));
+ return e;
+ }
+
+ ///Add a new row (i.e a new constraint) to the LP
+
+ ///\param l is the lower bound (-\ref INF means no bound)
+ ///\param e is a linear expression (see \ref Expr)
+ ///\param u is the upper bound (\ref INF means no bound)
+ ///\return The created row.
+ Row addRow(Value l,const Expr &e, Value u) {
+ Row r;
+ e.simplify();
+ r._id = _addRowId(_addRow(l - *e, ExprIterator(e.comps.begin(), cols),
+ ExprIterator(e.comps.end(), cols), u - *e));
+ return r;
+ }
+
+ ///Add a new row (i.e a new constraint) to the LP
+
+ ///\param c is a linear expression (see \ref Constr)
+ ///\return The created row.
+ Row addRow(const Constr &c) {
+ Row r;
+ c.expr().simplify();
+ r._id = _addRowId(_addRow(c.lowerBounded()?c.lowerBound()-*c.expr():-INF,
+ ExprIterator(c.expr().comps.begin(), cols),
+ ExprIterator(c.expr().comps.end(), cols),
+ c.upperBounded()?c.upperBound()-*c.expr():INF));
+ return r;
+ }
+ ///Erase a column (i.e a variable) from the LP
+
+ ///\param c is the column to be deleted
+ void erase(Col c) {
+ _eraseCol(cols(id(c)));
+ _eraseColId(cols(id(c)));
+ }
+ ///Erase a row (i.e a constraint) from the LP
+
+ ///\param r is the row to be deleted
+ void erase(Row r) {
+ _eraseRow(rows(id(r)));
+ _eraseRowId(rows(id(r)));
+ }
+
+ /// Get the name of a column
+
+ ///\param c is the coresponding column
+ ///\return The name of the colunm
+ std::string colName(Col c) const {
+ std::string name;
+ _getColName(cols(id(c)), name);
+ return name;
+ }
+
+ /// Set the name of a column
+
+ ///\param c is the coresponding column
+ ///\param name The name to be given
+ void colName(Col c, const std::string& name) {
+ _setColName(cols(id(c)), name);
+ }
+
+ /// Get the column by its name
+
+ ///\param name The name of the column
+ ///\return the proper column or \c INVALID
+ Col colByName(const std::string& name) const {
+ int k = _colByName(name);
+ return k != -1 ? Col(cols[k]) : Col(INVALID);
+ }
+
+ /// Get the name of a row
+
+ ///\param r is the coresponding row
+ ///\return The name of the row
+ std::string rowName(Row r) const {
+ std::string name;
+ _getRowName(rows(id(r)), name);
+ return name;
+ }
+
+ /// Set the name of a row
+
+ ///\param r is the coresponding row
+ ///\param name The name to be given
+ void rowName(Row r, const std::string& name) {
+ _setRowName(rows(id(r)), name);
+ }
+
+ /// Get the row by its name
+
+ ///\param name The name of the row
+ ///\return the proper row or \c INVALID
+ Row rowByName(const std::string& name) const {
+ int k = _rowByName(name);
+ return k != -1 ? Row(rows[k]) : Row(INVALID);
+ }
+
+ /// Set an element of the coefficient matrix of the LP
+
+ ///\param r is the row of the element to be modified
+ ///\param c is the column of the element to be modified
+ ///\param val is the new value of the coefficient
+ void coeff(Row r, Col c, Value val) {
+ _setCoeff(rows(id(r)),cols(id(c)), val);
+ }
+
+ /// Get an element of the coefficient matrix of the LP
+
+ ///\param r is the row of the element
+ ///\param c is the column of the element
+ ///\return the corresponding coefficient
+ Value coeff(Row r, Col c) const {
+ return _getCoeff(rows(id(r)),cols(id(c)));
+ }
+
+ /// Set the lower bound of a column (i.e a variable)
+
+ /// The lower bound of a variable (column) has to be given by an
+ /// extended number of type Value, i.e. a finite number of type
+ /// Value or -\ref INF.
+ void colLowerBound(Col c, Value value) {
+ _setColLowerBound(cols(id(c)),value);
+ }
+
+ /// Get the lower bound of a column (i.e a variable)
+
+ /// This function returns the lower bound for column (variable) \c c
+ /// (this might be -\ref INF as well).
+ ///\return The lower bound for column \c c
+ Value colLowerBound(Col c) const {
+ return _getColLowerBound(cols(id(c)));
+ }
+
+ ///\brief Set the lower bound of several columns
+ ///(i.e variables) at once
+ ///
+ ///This magic function takes a container as its argument
+ ///and applies the function on all of its elements.
+ ///The lower bound of a variable (column) has to be given by an
+ ///extended number of type Value, i.e. a finite number of type
+ ///Value or -\ref INF.
+#ifdef DOXYGEN
+ template<class T>
+ void colLowerBound(T &t, Value value) { return 0;}
+#else
+ template<class T>
+ typename enable_if<typename T::value_type::LpCol,void>::type
+ colLowerBound(T &t, Value value,dummy<0> = 0) {
+ for(typename T::iterator i=t.begin();i!=t.end();++i) {
+ colLowerBound(*i, value);
+ }
+ }
+ template<class T>
+ typename enable_if<typename T::value_type::second_type::LpCol,
+ void>::type
+ colLowerBound(T &t, Value value,dummy<1> = 1) {
+ for(typename T::iterator i=t.begin();i!=t.end();++i) {
+ colLowerBound(i->second, value);
+ }
+ }
+ template<class T>
+ typename enable_if<typename T::MapIt::Value::LpCol,
+ void>::type
+ colLowerBound(T &t, Value value,dummy<2> = 2) {
+ for(typename T::MapIt i(t); i!=INVALID; ++i){
+ colLowerBound(*i, value);
+ }
+ }
+#endif
+
+ /// Set the upper bound of a column (i.e a variable)
+
+ /// The upper bound of a variable (column) has to be given by an
+ /// extended number of type Value, i.e. a finite number of type
+ /// Value or \ref INF.
+ void colUpperBound(Col c, Value value) {
+ _setColUpperBound(cols(id(c)),value);
+ };
+
+ /// Get the upper bound of a column (i.e a variable)
+
+ /// This function returns the upper bound for column (variable) \c c
+ /// (this might be \ref INF as well).
+ /// \return The upper bound for column \c c
+ Value colUpperBound(Col c) const {
+ return _getColUpperBound(cols(id(c)));
+ }
+
+ ///\brief Set the upper bound of several columns
+ ///(i.e variables) at once
+ ///
+ ///This magic function takes a container as its argument
+ ///and applies the function on all of its elements.
+ ///The upper bound of a variable (column) has to be given by an
+ ///extended number of type Value, i.e. a finite number of type
+ ///Value or \ref INF.
+#ifdef DOXYGEN
+ template<class T>
+ void colUpperBound(T &t, Value value) { return 0;}
+#else
+ template<class T1>
+ typename enable_if<typename T1::value_type::LpCol,void>::type
+ colUpperBound(T1 &t, Value value,dummy<0> = 0) {
+ for(typename T1::iterator i=t.begin();i!=t.end();++i) {
+ colUpperBound(*i, value);
+ }
+ }
+ template<class T1>
+ typename enable_if<typename T1::value_type::second_type::LpCol,
+ void>::type
+ colUpperBound(T1 &t, Value value,dummy<1> = 1) {
+ for(typename T1::iterator i=t.begin();i!=t.end();++i) {
+ colUpperBound(i->second, value);
+ }
+ }
+ template<class T1>
+ typename enable_if<typename T1::MapIt::Value::LpCol,
+ void>::type
+ colUpperBound(T1 &t, Value value,dummy<2> = 2) {
+ for(typename T1::MapIt i(t); i!=INVALID; ++i){
+ colUpperBound(*i, value);
+ }
+ }
+#endif
+
+ /// Set the lower and the upper bounds of a column (i.e a variable)
+
+ /// The lower and the upper bounds of
+ /// a variable (column) have to be given by an
+ /// extended number of type Value, i.e. a finite number of type
+ /// Value, -\ref INF or \ref INF.
+ void colBounds(Col c, Value lower, Value upper) {
+ _setColLowerBound(cols(id(c)),lower);
+ _setColUpperBound(cols(id(c)),upper);
+ }
+
+ ///\brief Set the lower and the upper bound of several columns
+ ///(i.e variables) at once
+ ///
+ ///This magic function takes a container as its argument
+ ///and applies the function on all of its elements.
+ /// The lower and the upper bounds of
+ /// a variable (column) have to be given by an
+ /// extended number of type Value, i.e. a finite number of type
+ /// Value, -\ref INF or \ref INF.
+#ifdef DOXYGEN
+ template<class T>
+ void colBounds(T &t, Value lower, Value upper) { return 0;}
+#else
+ template<class T2>
+ typename enable_if<typename T2::value_type::LpCol,void>::type
+ colBounds(T2 &t, Value lower, Value upper,dummy<0> = 0) {
+ for(typename T2::iterator i=t.begin();i!=t.end();++i) {
+ colBounds(*i, lower, upper);
+ }
+ }
+ template<class T2>
+ typename enable_if<typename T2::value_type::second_type::LpCol, void>::type
+ colBounds(T2 &t, Value lower, Value upper,dummy<1> = 1) {
+ for(typename T2::iterator i=t.begin();i!=t.end();++i) {
+ colBounds(i->second, lower, upper);
+ }
+ }
+ template<class T2>
+ typename enable_if<typename T2::MapIt::Value::LpCol, void>::type
+ colBounds(T2 &t, Value lower, Value upper,dummy<2> = 2) {
+ for(typename T2::MapIt i(t); i!=INVALID; ++i){
+ colBounds(*i, lower, upper);
+ }
+ }
+#endif
+
+ /// Set the lower bound of a row (i.e a constraint)
+
+ /// The lower bound of a constraint (row) has to be given by an
+ /// extended number of type Value, i.e. a finite number of type
+ /// Value or -\ref INF.
+ void rowLowerBound(Row r, Value value) {
+ _setRowLowerBound(rows(id(r)),value);
+ }
+
+ /// Get the lower bound of a row (i.e a constraint)
+
+ /// This function returns the lower bound for row (constraint) \c c
+ /// (this might be -\ref INF as well).
+ ///\return The lower bound for row \c r
+ Value rowLowerBound(Row r) const {
+ return _getRowLowerBound(rows(id(r)));
+ }
+
+ /// Set the upper bound of a row (i.e a constraint)
+
+ /// The upper bound of a constraint (row) has to be given by an
+ /// extended number of type Value, i.e. a finite number of type
+ /// Value or -\ref INF.
+ void rowUpperBound(Row r, Value value) {
+ _setRowUpperBound(rows(id(r)),value);
+ }
+
+ /// Get the upper bound of a row (i.e a constraint)
+
+ /// This function returns the upper bound for row (constraint) \c c
+ /// (this might be -\ref INF as well).
+ ///\return The upper bound for row \c r
+ Value rowUpperBound(Row r) const {
+ return _getRowUpperBound(rows(id(r)));
+ }
+
+ ///Set an element of the objective function
+ void objCoeff(Col c, Value v) {_setObjCoeff(cols(id(c)),v); };
+
+ ///Get an element of the objective function
+ Value objCoeff(Col c) const { return _getObjCoeff(cols(id(c))); };
+
+ ///Set the objective function
+
+ ///\param e is a linear expression of type \ref Expr.
+ ///
+ void obj(const Expr& e) {
+ _setObjCoeffs(ExprIterator(e.comps.begin(), cols),
+ ExprIterator(e.comps.end(), cols));
+ obj_const_comp = *e;
+ }
+
+ ///Get the objective function
+
+ ///\return the objective function as a linear expression of type
+ ///Expr.
+ Expr obj() const {
+ Expr e;
+ _getObjCoeffs(InsertIterator(e.comps, cols));
+ *e = obj_const_comp;
+ return e;
+ }
+
+
+ ///Set the direction of optimization
+ void sense(Sense sense) { _setSense(sense); }
+
+ ///Query the direction of the optimization
+ Sense sense() const {return _getSense(); }
+
+ ///Set the sense to maximization
+ void max() { _setSense(MAX); }
+
+ ///Set the sense to maximization
+ void min() { _setSense(MIN); }
+
+ ///Clear the problem
+ void clear() { _clear(); rows.clear(); cols.clear(); }
+
+ /// Set the message level of the solver
+ void messageLevel(MessageLevel level) { _messageLevel(level); }
+
+ /// Write the problem to a file in the given format
+
+ /// This function writes the problem to a file in the given format.
+ /// Different solver backends may support different formats.
+ /// Trying to write in an unsupported format will trigger
+ /// \ref UnsupportedFormatError. For the supported formats,
+ /// visit the documentation of the base class of the related backends
+ /// (\ref CplexBase, \ref GlpkBase etc.)
+ /// \param file The file path
+ /// \param format The output file format.
+ void write(std::string file, std::string format = "MPS") const
+ {
+ _write(file.c_str(),format.c_str());
+ }
+
+ ///@}
+
+ };
+
+ /// Addition
+
+ ///\relates LpBase::Expr
+ ///
+ inline LpBase::Expr operator+(const LpBase::Expr &a, const LpBase::Expr &b) {
+ LpBase::Expr tmp(a);
+ tmp+=b;
+ return tmp;
+ }
+ ///Substraction
+
+ ///\relates LpBase::Expr
+ ///
+ inline LpBase::Expr operator-(const LpBase::Expr &a, const LpBase::Expr &b) {
+ LpBase::Expr tmp(a);
+ tmp-=b;
+ return tmp;
+ }
+ ///Multiply with constant
+
+ ///\relates LpBase::Expr
+ ///
+ inline LpBase::Expr operator*(const LpBase::Expr &a, const LpBase::Value &b) {
+ LpBase::Expr tmp(a);
+ tmp*=b;
+ return tmp;
+ }
+
+ ///Multiply with constant
+
+ ///\relates LpBase::Expr
+ ///
+ inline LpBase::Expr operator*(const LpBase::Value &a, const LpBase::Expr &b) {
+ LpBase::Expr tmp(b);
+ tmp*=a;
+ return tmp;
+ }
+ ///Divide with constant
+
+ ///\relates LpBase::Expr
+ ///
+ inline LpBase::Expr operator/(const LpBase::Expr &a, const LpBase::Value &b) {
+ LpBase::Expr tmp(a);
+ tmp/=b;
+ return tmp;
+ }
+
+ ///Create constraint
+
+ ///\relates LpBase::Constr
+ ///
+ inline LpBase::Constr operator<=(const LpBase::Expr &e,
+ const LpBase::Expr &f) {
+ return LpBase::Constr(0, f - e, LpBase::NaN);
+ }
+
+ ///Create constraint
+
+ ///\relates LpBase::Constr
+ ///
+ inline LpBase::Constr operator<=(const LpBase::Value &e,
+ const LpBase::Expr &f) {
+ return LpBase::Constr(e, f, LpBase::NaN);
+ }
+
+ ///Create constraint
+
+ ///\relates LpBase::Constr
+ ///
+ inline LpBase::Constr operator<=(const LpBase::Expr &e,
+ const LpBase::Value &f) {
+ return LpBase::Constr(LpBase::NaN, e, f);
+ }
+
+ ///Create constraint
+
+ ///\relates LpBase::Constr
+ ///
+ inline LpBase::Constr operator>=(const LpBase::Expr &e,
+ const LpBase::Expr &f) {
+ return LpBase::Constr(0, e - f, LpBase::NaN);
+ }
+
+
+ ///Create constraint
+
+ ///\relates LpBase::Constr
+ ///
+ inline LpBase::Constr operator>=(const LpBase::Value &e,
+ const LpBase::Expr &f) {
+ return LpBase::Constr(LpBase::NaN, f, e);
+ }
+
+
+ ///Create constraint
+
+ ///\relates LpBase::Constr
+ ///
+ inline LpBase::Constr operator>=(const LpBase::Expr &e,
+ const LpBase::Value &f) {
+ return LpBase::Constr(f, e, LpBase::NaN);
+ }
+
+ ///Create constraint
+
+ ///\relates LpBase::Constr
+ ///
+ inline LpBase::Constr operator==(const LpBase::Expr &e,
+ const LpBase::Value &f) {
+ return LpBase::Constr(f, e, f);
+ }
+
+ ///Create constraint
+
+ ///\relates LpBase::Constr
+ ///
+ inline LpBase::Constr operator==(const LpBase::Expr &e,
+ const LpBase::Expr &f) {
+ return LpBase::Constr(0, f - e, 0);
+ }
+
+ ///Create constraint
+
+ ///\relates LpBase::Constr
+ ///
+ inline LpBase::Constr operator<=(const LpBase::Value &n,
+ const LpBase::Constr &c) {
+ LpBase::Constr tmp(c);
+ LEMON_ASSERT(isNaN(tmp.lowerBound()), "Wrong LP constraint");
+ tmp.lowerBound()=n;
+ return tmp;
+ }
+ ///Create constraint
+
+ ///\relates LpBase::Constr
+ ///
+ inline LpBase::Constr operator<=(const LpBase::Constr &c,
+ const LpBase::Value &n)
+ {
+ LpBase::Constr tmp(c);
+ LEMON_ASSERT(isNaN(tmp.upperBound()), "Wrong LP constraint");
+ tmp.upperBound()=n;
+ return tmp;
+ }
+
+ ///Create constraint
+
+ ///\relates LpBase::Constr
+ ///
+ inline LpBase::Constr operator>=(const LpBase::Value &n,
+ const LpBase::Constr &c) {
+ LpBase::Constr tmp(c);
+ LEMON_ASSERT(isNaN(tmp.upperBound()), "Wrong LP constraint");
+ tmp.upperBound()=n;
+ return tmp;
+ }
+ ///Create constraint
+
+ ///\relates LpBase::Constr
+ ///
+ inline LpBase::Constr operator>=(const LpBase::Constr &c,
+ const LpBase::Value &n)
+ {
+ LpBase::Constr tmp(c);
+ LEMON_ASSERT(isNaN(tmp.lowerBound()), "Wrong LP constraint");
+ tmp.lowerBound()=n;
+ return tmp;
+ }
+
+ ///Addition
+
+ ///\relates LpBase::DualExpr
+ ///
+ inline LpBase::DualExpr operator+(const LpBase::DualExpr &a,
+ const LpBase::DualExpr &b) {
+ LpBase::DualExpr tmp(a);
+ tmp+=b;
+ return tmp;
+ }
+ ///Substraction
+
+ ///\relates LpBase::DualExpr
+ ///
+ inline LpBase::DualExpr operator-(const LpBase::DualExpr &a,
+ const LpBase::DualExpr &b) {
+ LpBase::DualExpr tmp(a);
+ tmp-=b;
+ return tmp;
+ }
+ ///Multiply with constant
+
+ ///\relates LpBase::DualExpr
+ ///
+ inline LpBase::DualExpr operator*(const LpBase::DualExpr &a,
+ const LpBase::Value &b) {
+ LpBase::DualExpr tmp(a);
+ tmp*=b;
+ return tmp;
+ }
+
+ ///Multiply with constant
+
+ ///\relates LpBase::DualExpr
+ ///
+ inline LpBase::DualExpr operator*(const LpBase::Value &a,
+ const LpBase::DualExpr &b) {
+ LpBase::DualExpr tmp(b);
+ tmp*=a;
+ return tmp;
+ }
+ ///Divide with constant
+
+ ///\relates LpBase::DualExpr
+ ///
+ inline LpBase::DualExpr operator/(const LpBase::DualExpr &a,
+ const LpBase::Value &b) {
+ LpBase::DualExpr tmp(a);
+ tmp/=b;
+ return tmp;
+ }
+
+ /// \ingroup lp_group
+ ///
+ /// \brief Common base class for LP solvers
+ ///
+ /// This class is an abstract base class for LP solvers. This class
+ /// provides a full interface for set and modify an LP problem,
+ /// solve it and retrieve the solution. You can use one of the
+ /// descendants as a concrete implementation, or the \c Lp
+ /// default LP solver. However, if you would like to handle LP
+ /// solvers as reference or pointer in a generic way, you can use
+ /// this class directly.
+ class LpSolver : virtual public LpBase {
+ public:
+
+ /// The problem types for primal and dual problems
+ enum ProblemType {
+ /// = 0. Feasible solution hasn't been found (but may exist).
+ UNDEFINED = 0,
+ /// = 1. The problem has no feasible solution.
+ INFEASIBLE = 1,
+ /// = 2. Feasible solution found.
+ FEASIBLE = 2,
+ /// = 3. Optimal solution exists and found.
+ OPTIMAL = 3,
+ /// = 4. The cost function is unbounded.
+ UNBOUNDED = 4
+ };
+
+ ///The basis status of variables
+ enum VarStatus {
+ /// The variable is in the basis
+ BASIC,
+ /// The variable is free, but not basic
+ FREE,
+ /// The variable has active lower bound
+ LOWER,
+ /// The variable has active upper bound
+ UPPER,
+ /// The variable is non-basic and fixed
+ FIXED
+ };
+
+ protected:
+
+ virtual SolveExitStatus _solve() = 0;
+
+ virtual Value _getPrimal(int i) const = 0;
+ virtual Value _getDual(int i) const = 0;
+
+ virtual Value _getPrimalRay(int i) const = 0;
+ virtual Value _getDualRay(int i) const = 0;
+
+ virtual Value _getPrimalValue() const = 0;
+
+ virtual VarStatus _getColStatus(int i) const = 0;
+ virtual VarStatus _getRowStatus(int i) const = 0;
+
+ virtual ProblemType _getPrimalType() const = 0;
+ virtual ProblemType _getDualType() const = 0;
+
+ public:
+
+ ///Allocate a new LP problem instance
+ virtual LpSolver* newSolver() const = 0;
+ ///Make a copy of the LP problem
+ virtual LpSolver* cloneSolver() const = 0;
+
+ ///\name Solve the LP
+
+ ///@{
+
+ ///\e Solve the LP problem at hand
+ ///
+ ///\return The result of the optimization procedure. Possible
+ ///values and their meanings can be found in the documentation of
+ ///\ref SolveExitStatus.
+ SolveExitStatus solve() { return _solve(); }
+
+ ///@}
+
+ ///\name Obtain the Solution
+
+ ///@{
+
+ /// The type of the primal problem
+ ProblemType primalType() const {
+ return _getPrimalType();
+ }
+
+ /// The type of the dual problem
+ ProblemType dualType() const {
+ return _getDualType();
+ }
+
+ /// Return the primal value of the column
+
+ /// Return the primal value of the column.
+ /// \pre The problem is solved.
+ Value primal(Col c) const { return _getPrimal(cols(id(c))); }
+
+ /// Return the primal value of the expression
+
+ /// Return the primal value of the expression, i.e. the dot
+ /// product of the primal solution and the expression.
+ /// \pre The problem is solved.
+ Value primal(const Expr& e) const {
+ double res = *e;
+ for (Expr::ConstCoeffIt c(e); c != INVALID; ++c) {
+ res += *c * primal(c);
+ }
+ return res;
+ }
+ /// Returns a component of the primal ray
+
+ /// The primal ray is solution of the modified primal problem,
+ /// where we change each finite bound to 0, and we looking for a
+ /// negative objective value in case of minimization, and positive
+ /// objective value for maximization. If there is such solution,
+ /// that proofs the unsolvability of the dual problem, and if a
+ /// feasible primal solution exists, then the unboundness of
+ /// primal problem.
+ ///
+ /// \pre The problem is solved and the dual problem is infeasible.
+ /// \note Some solvers does not provide primal ray calculation
+ /// functions.
+ Value primalRay(Col c) const { return _getPrimalRay(cols(id(c))); }
+
+ /// Return the dual value of the row
+
+ /// Return the dual value of the row.
+ /// \pre The problem is solved.
+ Value dual(Row r) const { return _getDual(rows(id(r))); }
+
+ /// Return the dual value of the dual expression
+
+ /// Return the dual value of the dual expression, i.e. the dot
+ /// product of the dual solution and the dual expression.
+ /// \pre The problem is solved.
+ Value dual(const DualExpr& e) const {
+ double res = 0.0;
+ for (DualExpr::ConstCoeffIt r(e); r != INVALID; ++r) {
+ res += *r * dual(r);
+ }
+ return res;
+ }
+
+ /// Returns a component of the dual ray
+
+ /// The dual ray is solution of the modified primal problem, where
+ /// we change each finite bound to 0 (i.e. the objective function
+ /// coefficients in the primal problem), and we looking for a
+ /// ositive objective value. If there is such solution, that
+ /// proofs the unsolvability of the primal problem, and if a
+ /// feasible dual solution exists, then the unboundness of
+ /// dual problem.
+ ///
+ /// \pre The problem is solved and the primal problem is infeasible.
+ /// \note Some solvers does not provide dual ray calculation
+ /// functions.
+ Value dualRay(Row r) const { return _getDualRay(rows(id(r))); }
+
+ /// Return the basis status of the column
+
+ /// \see VarStatus
+ VarStatus colStatus(Col c) const { return _getColStatus(cols(id(c))); }
+
+ /// Return the basis status of the row
+
+ /// \see VarStatus
+ VarStatus rowStatus(Row r) const { return _getRowStatus(rows(id(r))); }
+
+ ///The value of the objective function
+
+ ///\return
+ ///- \ref INF or -\ref INF means either infeasibility or unboundedness
+ /// of the primal problem, depending on whether we minimize or maximize.
+ ///- \ref NaN if no primal solution is found.
+ ///- The (finite) objective value if an optimal solution is found.
+ Value primal() const { return _getPrimalValue()+obj_const_comp;}
+ ///@}
+
+ protected:
+
+ };
+
+
+ /// \ingroup lp_group
+ ///
+ /// \brief Common base class for MIP solvers
+ ///
+ /// This class is an abstract base class for MIP solvers. This class
+ /// provides a full interface for set and modify an MIP problem,
+ /// solve it and retrieve the solution. You can use one of the
+ /// descendants as a concrete implementation, or the \c Lp
+ /// default MIP solver. However, if you would like to handle MIP
+ /// solvers as reference or pointer in a generic way, you can use
+ /// this class directly.
+ class MipSolver : virtual public LpBase {
+ public:
+
+ /// The problem types for MIP problems
+ enum ProblemType {
+ /// = 0. Feasible solution hasn't been found (but may exist).
+ UNDEFINED = 0,
+ /// = 1. The problem has no feasible solution.
+ INFEASIBLE = 1,
+ /// = 2. Feasible solution found.
+ FEASIBLE = 2,
+ /// = 3. Optimal solution exists and found.
+ OPTIMAL = 3,
+ /// = 4. The cost function is unbounded.
+ ///The Mip or at least the relaxed problem is unbounded.
+ UNBOUNDED = 4
+ };
+
+ ///Allocate a new MIP problem instance
+ virtual MipSolver* newSolver() const = 0;
+ ///Make a copy of the MIP problem
+ virtual MipSolver* cloneSolver() const = 0;
+
+ ///\name Solve the MIP
+
+ ///@{
+
+ /// Solve the MIP problem at hand
+ ///
+ ///\return The result of the optimization procedure. Possible
+ ///values and their meanings can be found in the documentation of
+ ///\ref SolveExitStatus.
+ SolveExitStatus solve() { return _solve(); }
+
+ ///@}
+
+ ///\name Set Column Type
+ ///@{
+
+ ///Possible variable (column) types (e.g. real, integer, binary etc.)
+ enum ColTypes {
+ /// = 0. Continuous variable (default).
+ REAL = 0,
+ /// = 1. Integer variable.
+ INTEGER = 1
+ };
+
+ ///Sets the type of the given column to the given type
+
+ ///Sets the type of the given column to the given type.
+ ///
+ void colType(Col c, ColTypes col_type) {
+ _setColType(cols(id(c)),col_type);
+ }
+
+ ///Gives back the type of the column.
+
+ ///Gives back the type of the column.
+ ///
+ ColTypes colType(Col c) const {
+ return _getColType(cols(id(c)));
+ }
+ ///@}
+
+ ///\name Obtain the Solution
+
+ ///@{
+
+ /// The type of the MIP problem
+ ProblemType type() const {
+ return _getType();
+ }
+
+ /// Return the value of the row in the solution
+
+ /// Return the value of the row in the solution.
+ /// \pre The problem is solved.
+ Value sol(Col c) const { return _getSol(cols(id(c))); }
+
+ /// Return the value of the expression in the solution
+
+ /// Return the value of the expression in the solution, i.e. the
+ /// dot product of the solution and the expression.
+ /// \pre The problem is solved.
+ Value sol(const Expr& e) const {
+ double res = *e;
+ for (Expr::ConstCoeffIt c(e); c != INVALID; ++c) {
+ res += *c * sol(c);
+ }
+ return res;
+ }
+ ///The value of the objective function
+
+ ///\return
+ ///- \ref INF or -\ref INF means either infeasibility or unboundedness
+ /// of the problem, depending on whether we minimize or maximize.
+ ///- \ref NaN if no primal solution is found.
+ ///- The (finite) objective value if an optimal solution is found.
+ Value solValue() const { return _getSolValue()+obj_const_comp;}
+ ///@}
+
+ protected:
+
+ virtual SolveExitStatus _solve() = 0;
+ virtual ColTypes _getColType(int col) const = 0;
+ virtual void _setColType(int col, ColTypes col_type) = 0;
+ virtual ProblemType _getType() const = 0;
+ virtual Value _getSol(int i) const = 0;
+ virtual Value _getSolValue() const = 0;
+
+ };
+
+
+
+} //namespace lemon
+
+#endif //LEMON_LP_BASE_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/lp_skeleton.cc b/extern/quadriflow/3rd/lemon-1.3.1/lemon/lp_skeleton.cc
new file mode 100644
index 00000000000..fc1c143f3ca
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/lp_skeleton.cc
@@ -0,0 +1,143 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/lp_skeleton.h>
+
+///\file
+///\brief A skeleton file to implement LP solver interfaces
+namespace lemon {
+
+ int SkeletonSolverBase::_addCol()
+ {
+ return ++col_num;
+ }
+
+ int SkeletonSolverBase::_addRow()
+ {
+ return ++row_num;
+ }
+
+ int SkeletonSolverBase::_addRow(Value, ExprIterator, ExprIterator, Value)
+ {
+ return ++row_num;
+ }
+
+ void SkeletonSolverBase::_eraseCol(int) {}
+ void SkeletonSolverBase::_eraseRow(int) {}
+
+ void SkeletonSolverBase::_getColName(int, std::string &) const {}
+ void SkeletonSolverBase::_setColName(int, const std::string &) {}
+ int SkeletonSolverBase::_colByName(const std::string&) const { return -1; }
+
+ void SkeletonSolverBase::_getRowName(int, std::string &) const {}
+ void SkeletonSolverBase::_setRowName(int, const std::string &) {}
+ int SkeletonSolverBase::_rowByName(const std::string&) const { return -1; }
+
+ void SkeletonSolverBase::_setRowCoeffs(int, ExprIterator, ExprIterator) {}
+ void SkeletonSolverBase::_getRowCoeffs(int, InsertIterator) const {}
+
+ void SkeletonSolverBase::_setColCoeffs(int, ExprIterator, ExprIterator) {}
+ void SkeletonSolverBase::_getColCoeffs(int, InsertIterator) const {}
+
+ void SkeletonSolverBase::_setCoeff(int, int, Value) {}
+ SkeletonSolverBase::Value SkeletonSolverBase::_getCoeff(int, int) const
+ { return 0; }
+
+ void SkeletonSolverBase::_setColLowerBound(int, Value) {}
+ SkeletonSolverBase::Value SkeletonSolverBase::_getColLowerBound(int) const
+ { return 0; }
+
+ void SkeletonSolverBase::_setColUpperBound(int, Value) {}
+ SkeletonSolverBase::Value SkeletonSolverBase::_getColUpperBound(int) const
+ { return 0; }
+
+ void SkeletonSolverBase::_setRowLowerBound(int, Value) {}
+ SkeletonSolverBase::Value SkeletonSolverBase::_getRowLowerBound(int) const
+ { return 0; }
+
+ void SkeletonSolverBase::_setRowUpperBound(int, Value) {}
+ SkeletonSolverBase::Value SkeletonSolverBase::_getRowUpperBound(int) const
+ { return 0; }
+
+ void SkeletonSolverBase::_setObjCoeffs(ExprIterator, ExprIterator) {}
+ void SkeletonSolverBase::_getObjCoeffs(InsertIterator) const {};
+
+ void SkeletonSolverBase::_setObjCoeff(int, Value) {}
+ SkeletonSolverBase::Value SkeletonSolverBase::_getObjCoeff(int) const
+ { return 0; }
+
+ void SkeletonSolverBase::_setSense(Sense) {}
+ SkeletonSolverBase::Sense SkeletonSolverBase::_getSense() const
+ { return MIN; }
+
+ void SkeletonSolverBase::_clear() {
+ row_num = col_num = 0;
+ }
+
+ void SkeletonSolverBase::_messageLevel(MessageLevel) {}
+
+ void SkeletonSolverBase::_write(std::string, std::string) const {}
+
+ LpSkeleton::SolveExitStatus LpSkeleton::_solve() { return SOLVED; }
+
+ LpSkeleton::Value LpSkeleton::_getPrimal(int) const { return 0; }
+ LpSkeleton::Value LpSkeleton::_getDual(int) const { return 0; }
+ LpSkeleton::Value LpSkeleton::_getPrimalValue() const { return 0; }
+
+ LpSkeleton::Value LpSkeleton::_getPrimalRay(int) const { return 0; }
+ LpSkeleton::Value LpSkeleton::_getDualRay(int) const { return 0; }
+
+ LpSkeleton::ProblemType LpSkeleton::_getPrimalType() const
+ { return UNDEFINED; }
+
+ LpSkeleton::ProblemType LpSkeleton::_getDualType() const
+ { return UNDEFINED; }
+
+ LpSkeleton::VarStatus LpSkeleton::_getColStatus(int) const
+ { return BASIC; }
+
+ LpSkeleton::VarStatus LpSkeleton::_getRowStatus(int) const
+ { return BASIC; }
+
+ LpSkeleton* LpSkeleton::newSolver() const
+ { return static_cast<LpSkeleton*>(0); }
+
+ LpSkeleton* LpSkeleton::cloneSolver() const
+ { return static_cast<LpSkeleton*>(0); }
+
+ const char* LpSkeleton::_solverName() const { return "LpSkeleton"; }
+
+ MipSkeleton::SolveExitStatus MipSkeleton::_solve()
+ { return SOLVED; }
+
+ MipSkeleton::Value MipSkeleton::_getSol(int) const { return 0; }
+ MipSkeleton::Value MipSkeleton::_getSolValue() const { return 0; }
+
+ MipSkeleton::ProblemType MipSkeleton::_getType() const
+ { return UNDEFINED; }
+
+ MipSkeleton* MipSkeleton::newSolver() const
+ { return static_cast<MipSkeleton*>(0); }
+
+ MipSkeleton* MipSkeleton::cloneSolver() const
+ { return static_cast<MipSkeleton*>(0); }
+
+ const char* MipSkeleton::_solverName() const { return "MipSkeleton"; }
+
+} //namespace lemon
+
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/lp_skeleton.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/lp_skeleton.h
new file mode 100644
index 00000000000..27285a4982a
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/lp_skeleton.h
@@ -0,0 +1,234 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_LP_SKELETON_H
+#define LEMON_LP_SKELETON_H
+
+#include <lemon/lp_base.h>
+
+///\file
+///\brief Skeleton file to implement LP/MIP solver interfaces
+///
+///The classes in this file do nothing, but they can serve as skeletons when
+///implementing an interface to new solvers.
+namespace lemon {
+
+ ///A skeleton class to implement LP/MIP solver base interface
+
+ ///This class does nothing, but it can serve as a skeleton when
+ ///implementing an interface to new solvers.
+ class SkeletonSolverBase : public virtual LpBase {
+ int col_num,row_num;
+
+ protected:
+
+ SkeletonSolverBase()
+ : col_num(-1), row_num(-1) {}
+
+ /// \e
+ virtual int _addCol();
+ /// \e
+ virtual int _addRow();
+ /// \e
+ virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
+ /// \e
+ virtual void _eraseCol(int i);
+ /// \e
+ virtual void _eraseRow(int i);
+
+ /// \e
+ virtual void _getColName(int col, std::string& name) const;
+ /// \e
+ virtual void _setColName(int col, const std::string& name);
+ /// \e
+ virtual int _colByName(const std::string& name) const;
+
+ /// \e
+ virtual void _getRowName(int row, std::string& name) const;
+ /// \e
+ virtual void _setRowName(int row, const std::string& name);
+ /// \e
+ virtual int _rowByName(const std::string& name) const;
+
+ /// \e
+ virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
+ /// \e
+ virtual void _getRowCoeffs(int i, InsertIterator b) const;
+ /// \e
+ virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
+ /// \e
+ virtual void _getColCoeffs(int i, InsertIterator b) const;
+
+ /// Set one element of the coefficient matrix
+ virtual void _setCoeff(int row, int col, Value value);
+
+ /// Get one element of the coefficient matrix
+ virtual Value _getCoeff(int row, int col) const;
+
+ /// The lower bound of a variable (column) have to be given by an
+ /// extended number of type Value, i.e. a finite number of type
+ /// Value or -\ref INF.
+ virtual void _setColLowerBound(int i, Value value);
+ /// \e
+
+ /// The lower bound of a variable (column) is an
+ /// extended number of type Value, i.e. a finite number of type
+ /// Value or -\ref INF.
+ virtual Value _getColLowerBound(int i) const;
+
+ /// The upper bound of a variable (column) have to be given by an
+ /// extended number of type Value, i.e. a finite number of type
+ /// Value or \ref INF.
+ virtual void _setColUpperBound(int i, Value value);
+ /// \e
+
+ /// The upper bound of a variable (column) is an
+ /// extended number of type Value, i.e. a finite number of type
+ /// Value or \ref INF.
+ virtual Value _getColUpperBound(int i) const;
+
+ /// The lower bound of a constraint (row) have to be given by an
+ /// extended number of type Value, i.e. a finite number of type
+ /// Value or -\ref INF.
+ virtual void _setRowLowerBound(int i, Value value);
+ /// \e
+
+ /// The lower bound of a constraint (row) is an
+ /// extended number of type Value, i.e. a finite number of type
+ /// Value or -\ref INF.
+ virtual Value _getRowLowerBound(int i) const;
+
+ /// The upper bound of a constraint (row) have to be given by an
+ /// extended number of type Value, i.e. a finite number of type
+ /// Value or \ref INF.
+ virtual void _setRowUpperBound(int i, Value value);
+ /// \e
+
+ /// The upper bound of a constraint (row) is an
+ /// extended number of type Value, i.e. a finite number of type
+ /// Value or \ref INF.
+ virtual Value _getRowUpperBound(int i) const;
+
+ /// \e
+ virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
+ /// \e
+ virtual void _getObjCoeffs(InsertIterator b) const;
+
+ /// \e
+ virtual void _setObjCoeff(int i, Value obj_coef);
+ /// \e
+ virtual Value _getObjCoeff(int i) const;
+
+ ///\e
+ virtual void _setSense(Sense);
+ ///\e
+ virtual Sense _getSense() const;
+
+ ///\e
+ virtual void _clear();
+
+ ///\e
+ virtual void _messageLevel(MessageLevel);
+
+ ///\e
+ virtual void _write(std::string file, std::string format) const;
+
+ };
+
+ /// \brief Skeleton class for an LP solver interface
+ ///
+ ///This class does nothing, but it can serve as a skeleton when
+ ///implementing an interface to new solvers.
+
+ ///\ingroup lp_group
+ class LpSkeleton : public LpSolver, public SkeletonSolverBase {
+ public:
+ ///\e
+ LpSkeleton() : LpSolver(), SkeletonSolverBase() {}
+ ///\e
+ virtual LpSkeleton* newSolver() const;
+ ///\e
+ virtual LpSkeleton* cloneSolver() const;
+ protected:
+
+ ///\e
+ virtual SolveExitStatus _solve();
+
+ ///\e
+ virtual Value _getPrimal(int i) const;
+ ///\e
+ virtual Value _getDual(int i) const;
+
+ ///\e
+ virtual Value _getPrimalValue() const;
+
+ ///\e
+ virtual Value _getPrimalRay(int i) const;
+ ///\e
+ virtual Value _getDualRay(int i) const;
+
+ ///\e
+ virtual ProblemType _getPrimalType() const;
+ ///\e
+ virtual ProblemType _getDualType() const;
+
+ ///\e
+ virtual VarStatus _getColStatus(int i) const;
+ ///\e
+ virtual VarStatus _getRowStatus(int i) const;
+
+ ///\e
+ virtual const char* _solverName() const;
+
+ };
+
+ /// \brief Skeleton class for a MIP solver interface
+ ///
+ ///This class does nothing, but it can serve as a skeleton when
+ ///implementing an interface to new solvers.
+ ///\ingroup lp_group
+ class MipSkeleton : public MipSolver, public SkeletonSolverBase {
+ public:
+ ///\e
+ MipSkeleton() : MipSolver(), SkeletonSolverBase() {}
+ ///\e
+ virtual MipSkeleton* newSolver() const;
+ ///\e
+ virtual MipSkeleton* cloneSolver() const;
+
+ protected:
+ ///\e
+ virtual SolveExitStatus _solve();
+
+ ///\e
+ virtual Value _getSol(int i) const;
+
+ ///\e
+ virtual Value _getSolValue() const;
+
+ ///\e
+ virtual ProblemType _getType() const;
+
+ ///\e
+ virtual const char* _solverName() const;
+
+ };
+
+} //namespace lemon
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/maps.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/maps.h
new file mode 100644
index 00000000000..1bc49e911ca
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/maps.h
@@ -0,0 +1,4057 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_MAPS_H
+#define LEMON_MAPS_H
+
+#include <iterator>
+#include <functional>
+#include <vector>
+#include <map>
+
+#include <lemon/core.h>
+
+///\file
+///\ingroup maps
+///\brief Miscellaneous property maps
+
+namespace lemon {
+
+ /// \addtogroup maps
+ /// @{
+
+ /// Base class of maps.
+
+ /// Base class of maps. It provides the necessary type definitions
+ /// required by the map %concepts.
+ template<typename K, typename V>
+ class MapBase {
+ public:
+ /// \brief The key type of the map.
+ typedef K Key;
+ /// \brief The value type of the map.
+ /// (The type of objects associated with the keys).
+ typedef V Value;
+ };
+
+
+ /// Null map. (a.k.a. DoNothingMap)
+
+ /// This map can be used if you have to provide a map only for
+ /// its type definitions, or if you have to provide a writable map,
+ /// but data written to it is not required (i.e. it will be sent to
+ /// <tt>/dev/null</tt>).
+ /// It conforms to the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
+ ///
+ /// \sa ConstMap
+ template<typename K, typename V>
+ class NullMap : public MapBase<K, V> {
+ public:
+ ///\e
+ typedef K Key;
+ ///\e
+ typedef V Value;
+
+ /// Gives back a default constructed element.
+ Value operator[](const Key&) const { return Value(); }
+ /// Absorbs the value.
+ void set(const Key&, const Value&) {}
+ };
+
+ /// Returns a \c NullMap class
+
+ /// This function just returns a \c NullMap class.
+ /// \relates NullMap
+ template <typename K, typename V>
+ NullMap<K, V> nullMap() {
+ return NullMap<K, V>();
+ }
+
+
+ /// Constant map.
+
+ /// This \ref concepts::ReadMap "readable map" assigns a specified
+ /// value to each key.
+ ///
+ /// In other aspects it is equivalent to \c NullMap.
+ /// So it conforms to the \ref concepts::ReadWriteMap "ReadWriteMap"
+ /// concept, but it absorbs the data written to it.
+ ///
+ /// The simplest way of using this map is through the constMap()
+ /// function.
+ ///
+ /// \sa NullMap
+ /// \sa IdentityMap
+ template<typename K, typename V>
+ class ConstMap : public MapBase<K, V> {
+ private:
+ V _value;
+ public:
+ ///\e
+ typedef K Key;
+ ///\e
+ typedef V Value;
+
+ /// Default constructor
+
+ /// Default constructor.
+ /// The value of the map will be default constructed.
+ ConstMap() {}
+
+ /// Constructor with specified initial value
+
+ /// Constructor with specified initial value.
+ /// \param v The initial value of the map.
+ ConstMap(const Value &v) : _value(v) {}
+
+ /// Gives back the specified value.
+ Value operator[](const Key&) const { return _value; }
+
+ /// Absorbs the value.
+ void set(const Key&, const Value&) {}
+
+ /// Sets the value that is assigned to each key.
+ void setAll(const Value &v) {
+ _value = v;
+ }
+
+ template<typename V1>
+ ConstMap(const ConstMap<K, V1> &, const Value &v) : _value(v) {}
+ };
+
+ /// Returns a \c ConstMap class
+
+ /// This function just returns a \c ConstMap class.
+ /// \relates ConstMap
+ template<typename K, typename V>
+ inline ConstMap<K, V> constMap(const V &v) {
+ return ConstMap<K, V>(v);
+ }
+
+ template<typename K, typename V>
+ inline ConstMap<K, V> constMap() {
+ return ConstMap<K, V>();
+ }
+
+
+ template<typename T, T v>
+ struct Const {};
+
+ /// Constant map with inlined constant value.
+
+ /// This \ref concepts::ReadMap "readable map" assigns a specified
+ /// value to each key.
+ ///
+ /// In other aspects it is equivalent to \c NullMap.
+ /// So it conforms to the \ref concepts::ReadWriteMap "ReadWriteMap"
+ /// concept, but it absorbs the data written to it.
+ ///
+ /// The simplest way of using this map is through the constMap()
+ /// function.
+ ///
+ /// \sa NullMap
+ /// \sa IdentityMap
+ template<typename K, typename V, V v>
+ class ConstMap<K, Const<V, v> > : public MapBase<K, V> {
+ public:
+ ///\e
+ typedef K Key;
+ ///\e
+ typedef V Value;
+
+ /// Constructor.
+ ConstMap() {}
+
+ /// Gives back the specified value.
+ Value operator[](const Key&) const { return v; }
+
+ /// Absorbs the value.
+ void set(const Key&, const Value&) {}
+ };
+
+ /// Returns a \c ConstMap class with inlined constant value
+
+ /// This function just returns a \c ConstMap class with inlined
+ /// constant value.
+ /// \relates ConstMap
+ template<typename K, typename V, V v>
+ inline ConstMap<K, Const<V, v> > constMap() {
+ return ConstMap<K, Const<V, v> >();
+ }
+
+
+ /// Identity map.
+
+ /// This \ref concepts::ReadMap "read-only map" gives back the given
+ /// key as value without any modification.
+ ///
+ /// \sa ConstMap
+ template <typename T>
+ class IdentityMap : public MapBase<T, T> {
+ public:
+ ///\e
+ typedef T Key;
+ ///\e
+ typedef T Value;
+
+ /// Gives back the given value without any modification.
+ Value operator[](const Key &k) const {
+ return k;
+ }
+ };
+
+ /// Returns an \c IdentityMap class
+
+ /// This function just returns an \c IdentityMap class.
+ /// \relates IdentityMap
+ template<typename T>
+ inline IdentityMap<T> identityMap() {
+ return IdentityMap<T>();
+ }
+
+
+ /// \brief Map for storing values for integer keys from the range
+ /// <tt>[0..size-1]</tt>.
+ ///
+ /// This map is essentially a wrapper for \c std::vector. It assigns
+ /// values to integer keys from the range <tt>[0..size-1]</tt>.
+ /// It can be used together with some data structures, e.g.
+ /// heap types and \c UnionFind, when the used items are small
+ /// integers. This map conforms to the \ref concepts::ReferenceMap
+ /// "ReferenceMap" concept.
+ ///
+ /// The simplest way of using this map is through the rangeMap()
+ /// function.
+ template <typename V>
+ class RangeMap : public MapBase<int, V> {
+ template <typename V1>
+ friend class RangeMap;
+ private:
+
+ typedef std::vector<V> Vector;
+ Vector _vector;
+
+ public:
+
+ /// Key type
+ typedef int Key;
+ /// Value type
+ typedef V Value;
+ /// Reference type
+ typedef typename Vector::reference Reference;
+ /// Const reference type
+ typedef typename Vector::const_reference ConstReference;
+
+ typedef True ReferenceMapTag;
+
+ public:
+
+ /// Constructor with specified default value.
+ RangeMap(int size = 0, const Value &value = Value())
+ : _vector(size, value) {}
+
+ /// Constructs the map from an appropriate \c std::vector.
+ template <typename V1>
+ RangeMap(const std::vector<V1>& vector)
+ : _vector(vector.begin(), vector.end()) {}
+
+ /// Constructs the map from another \c RangeMap.
+ template <typename V1>
+ RangeMap(const RangeMap<V1> &c)
+ : _vector(c._vector.begin(), c._vector.end()) {}
+
+ /// Returns the size of the map.
+ int size() {
+ return _vector.size();
+ }
+
+ /// Resizes the map.
+
+ /// Resizes the underlying \c std::vector container, so changes the
+ /// keyset of the map.
+ /// \param size The new size of the map. The new keyset will be the
+ /// range <tt>[0..size-1]</tt>.
+ /// \param value The default value to assign to the new keys.
+ void resize(int size, const Value &value = Value()) {
+ _vector.resize(size, value);
+ }
+
+ private:
+
+ RangeMap& operator=(const RangeMap&);
+
+ public:
+
+ ///\e
+ Reference operator[](const Key &k) {
+ return _vector[k];
+ }
+
+ ///\e
+ ConstReference operator[](const Key &k) const {
+ return _vector[k];
+ }
+
+ ///\e
+ void set(const Key &k, const Value &v) {
+ _vector[k] = v;
+ }
+ };
+
+ /// Returns a \c RangeMap class
+
+ /// This function just returns a \c RangeMap class.
+ /// \relates RangeMap
+ template<typename V>
+ inline RangeMap<V> rangeMap(int size = 0, const V &value = V()) {
+ return RangeMap<V>(size, value);
+ }
+
+ /// \brief Returns a \c RangeMap class created from an appropriate
+ /// \c std::vector
+
+ /// This function just returns a \c RangeMap class created from an
+ /// appropriate \c std::vector.
+ /// \relates RangeMap
+ template<typename V>
+ inline RangeMap<V> rangeMap(const std::vector<V> &vector) {
+ return RangeMap<V>(vector);
+ }
+
+
+ /// Map type based on \c std::map
+
+ /// This map is essentially a wrapper for \c std::map with addition
+ /// that you can specify a default value for the keys that are not
+ /// stored actually. This value can be different from the default
+ /// contructed value (i.e. \c %Value()).
+ /// This type conforms to the \ref concepts::ReferenceMap "ReferenceMap"
+ /// concept.
+ ///
+ /// This map is useful if a default value should be assigned to most of
+ /// the keys and different values should be assigned only to a few
+ /// keys (i.e. the map is "sparse").
+ /// The name of this type also refers to this important usage.
+ ///
+ /// Apart form that, this map can be used in many other cases since it
+ /// is based on \c std::map, which is a general associative container.
+ /// However, keep in mind that it is usually not as efficient as other
+ /// maps.
+ ///
+ /// The simplest way of using this map is through the sparseMap()
+ /// function.
+ template <typename K, typename V, typename Comp = std::less<K> >
+ class SparseMap : public MapBase<K, V> {
+ template <typename K1, typename V1, typename C1>
+ friend class SparseMap;
+ public:
+
+ /// Key type
+ typedef K Key;
+ /// Value type
+ typedef V Value;
+ /// Reference type
+ typedef Value& Reference;
+ /// Const reference type
+ typedef const Value& ConstReference;
+
+ typedef True ReferenceMapTag;
+
+ private:
+
+ typedef std::map<K, V, Comp> Map;
+ Map _map;
+ Value _value;
+
+ public:
+
+ /// \brief Constructor with specified default value.
+ SparseMap(const Value &value = Value()) : _value(value) {}
+ /// \brief Constructs the map from an appropriate \c std::map, and
+ /// explicitly specifies a default value.
+ template <typename V1, typename Comp1>
+ SparseMap(const std::map<Key, V1, Comp1> &map,
+ const Value &value = Value())
+ : _map(map.begin(), map.end()), _value(value) {}
+
+ /// \brief Constructs the map from another \c SparseMap.
+ template<typename V1, typename Comp1>
+ SparseMap(const SparseMap<Key, V1, Comp1> &c)
+ : _map(c._map.begin(), c._map.end()), _value(c._value) {}
+
+ private:
+
+ SparseMap& operator=(const SparseMap&);
+
+ public:
+
+ ///\e
+ Reference operator[](const Key &k) {
+ typename Map::iterator it = _map.lower_bound(k);
+ if (it != _map.end() && !_map.key_comp()(k, it->first))
+ return it->second;
+ else
+ return _map.insert(it, std::make_pair(k, _value))->second;
+ }
+
+ ///\e
+ ConstReference operator[](const Key &k) const {
+ typename Map::const_iterator it = _map.find(k);
+ if (it != _map.end())
+ return it->second;
+ else
+ return _value;
+ }
+
+ ///\e
+ void set(const Key &k, const Value &v) {
+ typename Map::iterator it = _map.lower_bound(k);
+ if (it != _map.end() && !_map.key_comp()(k, it->first))
+ it->second = v;
+ else
+ _map.insert(it, std::make_pair(k, v));
+ }
+
+ ///\e
+ void setAll(const Value &v) {
+ _value = v;
+ _map.clear();
+ }
+ };
+
+ /// Returns a \c SparseMap class
+
+ /// This function just returns a \c SparseMap class with specified
+ /// default value.
+ /// \relates SparseMap
+ template<typename K, typename V, typename Compare>
+ inline SparseMap<K, V, Compare> sparseMap(const V& value = V()) {
+ return SparseMap<K, V, Compare>(value);
+ }
+
+ template<typename K, typename V>
+ inline SparseMap<K, V, std::less<K> > sparseMap(const V& value = V()) {
+ return SparseMap<K, V, std::less<K> >(value);
+ }
+
+ /// \brief Returns a \c SparseMap class created from an appropriate
+ /// \c std::map
+
+ /// This function just returns a \c SparseMap class created from an
+ /// appropriate \c std::map.
+ /// \relates SparseMap
+ template<typename K, typename V, typename Compare>
+ inline SparseMap<K, V, Compare>
+ sparseMap(const std::map<K, V, Compare> &map, const V& value = V())
+ {
+ return SparseMap<K, V, Compare>(map, value);
+ }
+
+ /// @}
+
+ /// \addtogroup map_adaptors
+ /// @{
+
+ /// Composition of two maps
+
+ /// This \ref concepts::ReadMap "read-only map" returns the
+ /// composition of two given maps. That is to say, if \c m1 is of
+ /// type \c M1 and \c m2 is of \c M2, then for
+ /// \code
+ /// ComposeMap<M1, M2> cm(m1,m2);
+ /// \endcode
+ /// <tt>cm[x]</tt> will be equal to <tt>m1[m2[x]]</tt>.
+ ///
+ /// The \c Key type of the map is inherited from \c M2 and the
+ /// \c Value type is from \c M1.
+ /// \c M2::Value must be convertible to \c M1::Key.
+ ///
+ /// The simplest way of using this map is through the composeMap()
+ /// function.
+ ///
+ /// \sa CombineMap
+ template <typename M1, typename M2>
+ class ComposeMap : public MapBase<typename M2::Key, typename M1::Value> {
+ const M1 &_m1;
+ const M2 &_m2;
+ public:
+ ///\e
+ typedef typename M2::Key Key;
+ ///\e
+ typedef typename M1::Value Value;
+
+ /// Constructor
+ ComposeMap(const M1 &m1, const M2 &m2) : _m1(m1), _m2(m2) {}
+
+ ///\e
+ typename MapTraits<M1>::ConstReturnValue
+ operator[](const Key &k) const { return _m1[_m2[k]]; }
+ };
+
+ /// Returns a \c ComposeMap class
+
+ /// This function just returns a \c ComposeMap class.
+ ///
+ /// If \c m1 and \c m2 are maps and the \c Value type of \c m2 is
+ /// convertible to the \c Key of \c m1, then <tt>composeMap(m1,m2)[x]</tt>
+ /// will be equal to <tt>m1[m2[x]]</tt>.
+ ///
+ /// \relates ComposeMap
+ template <typename M1, typename M2>
+ inline ComposeMap<M1, M2> composeMap(const M1 &m1, const M2 &m2) {
+ return ComposeMap<M1, M2>(m1, m2);
+ }
+
+
+ /// Combination of two maps using an STL (binary) functor.
+
+ /// This \ref concepts::ReadMap "read-only map" takes two maps and a
+ /// binary functor and returns the combination of the two given maps
+ /// using the functor.
+ /// That is to say, if \c m1 is of type \c M1 and \c m2 is of \c M2
+ /// and \c f is of \c F, then for
+ /// \code
+ /// CombineMap<M1,M2,F,V> cm(m1,m2,f);
+ /// \endcode
+ /// <tt>cm[x]</tt> will be equal to <tt>f(m1[x],m2[x])</tt>.
+ ///
+ /// The \c Key type of the map is inherited from \c M1 (\c M1::Key
+ /// must be convertible to \c M2::Key) and the \c Value type is \c V.
+ /// \c M2::Value and \c M1::Value must be convertible to the
+ /// corresponding input parameter of \c F and the return type of \c F
+ /// must be convertible to \c V.
+ ///
+ /// The simplest way of using this map is through the combineMap()
+ /// function.
+ ///
+ /// \sa ComposeMap
+ template<typename M1, typename M2, typename F,
+ typename V = typename F::result_type>
+ class CombineMap : public MapBase<typename M1::Key, V> {
+ const M1 &_m1;
+ const M2 &_m2;
+ F _f;
+ public:
+ ///\e
+ typedef typename M1::Key Key;
+ ///\e
+ typedef V Value;
+
+ /// Constructor
+ CombineMap(const M1 &m1, const M2 &m2, const F &f = F())
+ : _m1(m1), _m2(m2), _f(f) {}
+ ///\e
+ Value operator[](const Key &k) const { return _f(_m1[k],_m2[k]); }
+ };
+
+ /// Returns a \c CombineMap class
+
+ /// This function just returns a \c CombineMap class.
+ ///
+ /// For example, if \c m1 and \c m2 are both maps with \c double
+ /// values, then
+ /// \code
+ /// combineMap(m1,m2,std::plus<double>())
+ /// \endcode
+ /// is equivalent to
+ /// \code
+ /// addMap(m1,m2)
+ /// \endcode
+ ///
+ /// This function is specialized for adaptable binary function
+ /// classes and C++ functions.
+ ///
+ /// \relates CombineMap
+ template<typename M1, typename M2, typename F, typename V>
+ inline CombineMap<M1, M2, F, V>
+ combineMap(const M1 &m1, const M2 &m2, const F &f) {
+ return CombineMap<M1, M2, F, V>(m1,m2,f);
+ }
+
+ template<typename M1, typename M2, typename F>
+ inline CombineMap<M1, M2, F, typename F::result_type>
+ combineMap(const M1 &m1, const M2 &m2, const F &f) {
+ return combineMap<M1, M2, F, typename F::result_type>(m1,m2,f);
+ }
+
+ template<typename M1, typename M2, typename K1, typename K2, typename V>
+ inline CombineMap<M1, M2, V (*)(K1, K2), V>
+ combineMap(const M1 &m1, const M2 &m2, V (*f)(K1, K2)) {
+ return combineMap<M1, M2, V (*)(K1, K2), V>(m1,m2,f);
+ }
+
+
+ /// Converts an STL style (unary) functor to a map
+
+ /// This \ref concepts::ReadMap "read-only map" returns the value
+ /// of a given functor. Actually, it just wraps the functor and
+ /// provides the \c Key and \c Value typedefs.
+ ///
+ /// Template parameters \c K and \c V will become its \c Key and
+ /// \c Value. In most cases they have to be given explicitly because
+ /// a functor typically does not provide \c argument_type and
+ /// \c result_type typedefs.
+ /// Parameter \c F is the type of the used functor.
+ ///
+ /// The simplest way of using this map is through the functorToMap()
+ /// function.
+ ///
+ /// \sa MapToFunctor
+ template<typename F,
+ typename K = typename F::argument_type,
+ typename V = typename F::result_type>
+ class FunctorToMap : public MapBase<K, V> {
+ F _f;
+ public:
+ ///\e
+ typedef K Key;
+ ///\e
+ typedef V Value;
+
+ /// Constructor
+ FunctorToMap(const F &f = F()) : _f(f) {}
+ ///\e
+ Value operator[](const Key &k) const { return _f(k); }
+ };
+
+ /// Returns a \c FunctorToMap class
+
+ /// This function just returns a \c FunctorToMap class.
+ ///
+ /// This function is specialized for adaptable binary function
+ /// classes and C++ functions.
+ ///
+ /// \relates FunctorToMap
+ template<typename K, typename V, typename F>
+ inline FunctorToMap<F, K, V> functorToMap(const F &f) {
+ return FunctorToMap<F, K, V>(f);
+ }
+
+ template <typename F>
+ inline FunctorToMap<F, typename F::argument_type, typename F::result_type>
+ functorToMap(const F &f)
+ {
+ return FunctorToMap<F, typename F::argument_type,
+ typename F::result_type>(f);
+ }
+
+ template <typename K, typename V>
+ inline FunctorToMap<V (*)(K), K, V> functorToMap(V (*f)(K)) {
+ return FunctorToMap<V (*)(K), K, V>(f);
+ }
+
+
+ /// Converts a map to an STL style (unary) functor
+
+ /// This class converts a map to an STL style (unary) functor.
+ /// That is it provides an <tt>operator()</tt> to read its values.
+ ///
+ /// For the sake of convenience it also works as a usual
+ /// \ref concepts::ReadMap "readable map", i.e. <tt>operator[]</tt>
+ /// and the \c Key and \c Value typedefs also exist.
+ ///
+ /// The simplest way of using this map is through the mapToFunctor()
+ /// function.
+ ///
+ ///\sa FunctorToMap
+ template <typename M>
+ class MapToFunctor : public MapBase<typename M::Key, typename M::Value> {
+ const M &_m;
+ public:
+ ///\e
+ typedef typename M::Key Key;
+ ///\e
+ typedef typename M::Value Value;
+
+ typedef typename M::Key argument_type;
+ typedef typename M::Value result_type;
+
+ /// Constructor
+ MapToFunctor(const M &m) : _m(m) {}
+ ///\e
+ Value operator()(const Key &k) const { return _m[k]; }
+ ///\e
+ Value operator[](const Key &k) const { return _m[k]; }
+ };
+
+ /// Returns a \c MapToFunctor class
+
+ /// This function just returns a \c MapToFunctor class.
+ /// \relates MapToFunctor
+ template<typename M>
+ inline MapToFunctor<M> mapToFunctor(const M &m) {
+ return MapToFunctor<M>(m);
+ }
+
+
+ /// \brief Map adaptor to convert the \c Value type of a map to
+ /// another type using the default conversion.
+
+ /// Map adaptor to convert the \c Value type of a \ref concepts::ReadMap
+ /// "readable map" to another type using the default conversion.
+ /// The \c Key type of it is inherited from \c M and the \c Value
+ /// type is \c V.
+ /// This type conforms to the \ref concepts::ReadMap "ReadMap" concept.
+ ///
+ /// The simplest way of using this map is through the convertMap()
+ /// function.
+ template <typename M, typename V>
+ class ConvertMap : public MapBase<typename M::Key, V> {
+ const M &_m;
+ public:
+ ///\e
+ typedef typename M::Key Key;
+ ///\e
+ typedef V Value;
+
+ /// Constructor
+
+ /// Constructor.
+ /// \param m The underlying map.
+ ConvertMap(const M &m) : _m(m) {}
+
+ ///\e
+ Value operator[](const Key &k) const { return _m[k]; }
+ };
+
+ /// Returns a \c ConvertMap class
+
+ /// This function just returns a \c ConvertMap class.
+ /// \relates ConvertMap
+ template<typename V, typename M>
+ inline ConvertMap<M, V> convertMap(const M &map) {
+ return ConvertMap<M, V>(map);
+ }
+
+
+ /// Applies all map setting operations to two maps
+
+ /// This map has two \ref concepts::WriteMap "writable map" parameters
+ /// and each write request will be passed to both of them.
+ /// If \c M1 is also \ref concepts::ReadMap "readable", then the read
+ /// operations will return the corresponding values of \c M1.
+ ///
+ /// The \c Key and \c Value types are inherited from \c M1.
+ /// The \c Key and \c Value of \c M2 must be convertible from those
+ /// of \c M1.
+ ///
+ /// The simplest way of using this map is through the forkMap()
+ /// function.
+ template<typename M1, typename M2>
+ class ForkMap : public MapBase<typename M1::Key, typename M1::Value> {
+ M1 &_m1;
+ M2 &_m2;
+ public:
+ ///\e
+ typedef typename M1::Key Key;
+ ///\e
+ typedef typename M1::Value Value;
+
+ /// Constructor
+ ForkMap(M1 &m1, M2 &m2) : _m1(m1), _m2(m2) {}
+ /// Returns the value associated with the given key in the first map.
+ Value operator[](const Key &k) const { return _m1[k]; }
+ /// Sets the value associated with the given key in both maps.
+ void set(const Key &k, const Value &v) { _m1.set(k,v); _m2.set(k,v); }
+ };
+
+ /// Returns a \c ForkMap class
+
+ /// This function just returns a \c ForkMap class.
+ /// \relates ForkMap
+ template <typename M1, typename M2>
+ inline ForkMap<M1,M2> forkMap(M1 &m1, M2 &m2) {
+ return ForkMap<M1,M2>(m1,m2);
+ }
+
+
+ /// Sum of two maps
+
+ /// This \ref concepts::ReadMap "read-only map" returns the sum
+ /// of the values of the two given maps.
+ /// Its \c Key and \c Value types are inherited from \c M1.
+ /// The \c Key and \c Value of \c M2 must be convertible to those of
+ /// \c M1.
+ ///
+ /// If \c m1 is of type \c M1 and \c m2 is of \c M2, then for
+ /// \code
+ /// AddMap<M1,M2> am(m1,m2);
+ /// \endcode
+ /// <tt>am[x]</tt> will be equal to <tt>m1[x]+m2[x]</tt>.
+ ///
+ /// The simplest way of using this map is through the addMap()
+ /// function.
+ ///
+ /// \sa SubMap, MulMap, DivMap
+ /// \sa ShiftMap, ShiftWriteMap
+ template<typename M1, typename M2>
+ class AddMap : public MapBase<typename M1::Key, typename M1::Value> {
+ const M1 &_m1;
+ const M2 &_m2;
+ public:
+ ///\e
+ typedef typename M1::Key Key;
+ ///\e
+ typedef typename M1::Value Value;
+
+ /// Constructor
+ AddMap(const M1 &m1, const M2 &m2) : _m1(m1), _m2(m2) {}
+ ///\e
+ Value operator[](const Key &k) const { return _m1[k]+_m2[k]; }
+ };
+
+ /// Returns an \c AddMap class
+
+ /// This function just returns an \c AddMap class.
+ ///
+ /// For example, if \c m1 and \c m2 are both maps with \c double
+ /// values, then <tt>addMap(m1,m2)[x]</tt> will be equal to
+ /// <tt>m1[x]+m2[x]</tt>.
+ ///
+ /// \relates AddMap
+ template<typename M1, typename M2>
+ inline AddMap<M1, M2> addMap(const M1 &m1, const M2 &m2) {
+ return AddMap<M1, M2>(m1,m2);
+ }
+
+
+ /// Difference of two maps
+
+ /// This \ref concepts::ReadMap "read-only map" returns the difference
+ /// of the values of the two given maps.
+ /// Its \c Key and \c Value types are inherited from \c M1.
+ /// The \c Key and \c Value of \c M2 must be convertible to those of
+ /// \c M1.
+ ///
+ /// If \c m1 is of type \c M1 and \c m2 is of \c M2, then for
+ /// \code
+ /// SubMap<M1,M2> sm(m1,m2);
+ /// \endcode
+ /// <tt>sm[x]</tt> will be equal to <tt>m1[x]-m2[x]</tt>.
+ ///
+ /// The simplest way of using this map is through the subMap()
+ /// function.
+ ///
+ /// \sa AddMap, MulMap, DivMap
+ template<typename M1, typename M2>
+ class SubMap : public MapBase<typename M1::Key, typename M1::Value> {
+ const M1 &_m1;
+ const M2 &_m2;
+ public:
+ ///\e
+ typedef typename M1::Key Key;
+ ///\e
+ typedef typename M1::Value Value;
+
+ /// Constructor
+ SubMap(const M1 &m1, const M2 &m2) : _m1(m1), _m2(m2) {}
+ ///\e
+ Value operator[](const Key &k) const { return _m1[k]-_m2[k]; }
+ };
+
+ /// Returns a \c SubMap class
+
+ /// This function just returns a \c SubMap class.
+ ///
+ /// For example, if \c m1 and \c m2 are both maps with \c double
+ /// values, then <tt>subMap(m1,m2)[x]</tt> will be equal to
+ /// <tt>m1[x]-m2[x]</tt>.
+ ///
+ /// \relates SubMap
+ template<typename M1, typename M2>
+ inline SubMap<M1, M2> subMap(const M1 &m1, const M2 &m2) {
+ return SubMap<M1, M2>(m1,m2);
+ }
+
+
+ /// Product of two maps
+
+ /// This \ref concepts::ReadMap "read-only map" returns the product
+ /// of the values of the two given maps.
+ /// Its \c Key and \c Value types are inherited from \c M1.
+ /// The \c Key and \c Value of \c M2 must be convertible to those of
+ /// \c M1.
+ ///
+ /// If \c m1 is of type \c M1 and \c m2 is of \c M2, then for
+ /// \code
+ /// MulMap<M1,M2> mm(m1,m2);
+ /// \endcode
+ /// <tt>mm[x]</tt> will be equal to <tt>m1[x]*m2[x]</tt>.
+ ///
+ /// The simplest way of using this map is through the mulMap()
+ /// function.
+ ///
+ /// \sa AddMap, SubMap, DivMap
+ /// \sa ScaleMap, ScaleWriteMap
+ template<typename M1, typename M2>
+ class MulMap : public MapBase<typename M1::Key, typename M1::Value> {
+ const M1 &_m1;
+ const M2 &_m2;
+ public:
+ ///\e
+ typedef typename M1::Key Key;
+ ///\e
+ typedef typename M1::Value Value;
+
+ /// Constructor
+ MulMap(const M1 &m1,const M2 &m2) : _m1(m1), _m2(m2) {}
+ ///\e
+ Value operator[](const Key &k) const { return _m1[k]*_m2[k]; }
+ };
+
+ /// Returns a \c MulMap class
+
+ /// This function just returns a \c MulMap class.
+ ///
+ /// For example, if \c m1 and \c m2 are both maps with \c double
+ /// values, then <tt>mulMap(m1,m2)[x]</tt> will be equal to
+ /// <tt>m1[x]*m2[x]</tt>.
+ ///
+ /// \relates MulMap
+ template<typename M1, typename M2>
+ inline MulMap<M1, M2> mulMap(const M1 &m1,const M2 &m2) {
+ return MulMap<M1, M2>(m1,m2);
+ }
+
+
+ /// Quotient of two maps
+
+ /// This \ref concepts::ReadMap "read-only map" returns the quotient
+ /// of the values of the two given maps.
+ /// Its \c Key and \c Value types are inherited from \c M1.
+ /// The \c Key and \c Value of \c M2 must be convertible to those of
+ /// \c M1.
+ ///
+ /// If \c m1 is of type \c M1 and \c m2 is of \c M2, then for
+ /// \code
+ /// DivMap<M1,M2> dm(m1,m2);
+ /// \endcode
+ /// <tt>dm[x]</tt> will be equal to <tt>m1[x]/m2[x]</tt>.
+ ///
+ /// The simplest way of using this map is through the divMap()
+ /// function.
+ ///
+ /// \sa AddMap, SubMap, MulMap
+ template<typename M1, typename M2>
+ class DivMap : public MapBase<typename M1::Key, typename M1::Value> {
+ const M1 &_m1;
+ const M2 &_m2;
+ public:
+ ///\e
+ typedef typename M1::Key Key;
+ ///\e
+ typedef typename M1::Value Value;
+
+ /// Constructor
+ DivMap(const M1 &m1,const M2 &m2) : _m1(m1), _m2(m2) {}
+ ///\e
+ Value operator[](const Key &k) const { return _m1[k]/_m2[k]; }
+ };
+
+ /// Returns a \c DivMap class
+
+ /// This function just returns a \c DivMap class.
+ ///
+ /// For example, if \c m1 and \c m2 are both maps with \c double
+ /// values, then <tt>divMap(m1,m2)[x]</tt> will be equal to
+ /// <tt>m1[x]/m2[x]</tt>.
+ ///
+ /// \relates DivMap
+ template<typename M1, typename M2>
+ inline DivMap<M1, M2> divMap(const M1 &m1,const M2 &m2) {
+ return DivMap<M1, M2>(m1,m2);
+ }
+
+
+ /// Shifts a map with a constant.
+
+ /// This \ref concepts::ReadMap "read-only map" returns the sum of
+ /// the given map and a constant value (i.e. it shifts the map with
+ /// the constant). Its \c Key and \c Value are inherited from \c M.
+ ///
+ /// Actually,
+ /// \code
+ /// ShiftMap<M> sh(m,v);
+ /// \endcode
+ /// is equivalent to
+ /// \code
+ /// ConstMap<M::Key, M::Value> cm(v);
+ /// AddMap<M, ConstMap<M::Key, M::Value> > sh(m,cm);
+ /// \endcode
+ ///
+ /// The simplest way of using this map is through the shiftMap()
+ /// function.
+ ///
+ /// \sa ShiftWriteMap
+ template<typename M, typename C = typename M::Value>
+ class ShiftMap : public MapBase<typename M::Key, typename M::Value> {
+ const M &_m;
+ C _v;
+ public:
+ ///\e
+ typedef typename M::Key Key;
+ ///\e
+ typedef typename M::Value Value;
+
+ /// Constructor
+
+ /// Constructor.
+ /// \param m The undelying map.
+ /// \param v The constant value.
+ ShiftMap(const M &m, const C &v) : _m(m), _v(v) {}
+ ///\e
+ Value operator[](const Key &k) const { return _m[k]+_v; }
+ };
+
+ /// Shifts a map with a constant (read-write version).
+
+ /// This \ref concepts::ReadWriteMap "read-write map" returns the sum
+ /// of the given map and a constant value (i.e. it shifts the map with
+ /// the constant). Its \c Key and \c Value are inherited from \c M.
+ /// It makes also possible to write the map.
+ ///
+ /// The simplest way of using this map is through the shiftWriteMap()
+ /// function.
+ ///
+ /// \sa ShiftMap
+ template<typename M, typename C = typename M::Value>
+ class ShiftWriteMap : public MapBase<typename M::Key, typename M::Value> {
+ M &_m;
+ C _v;
+ public:
+ ///\e
+ typedef typename M::Key Key;
+ ///\e
+ typedef typename M::Value Value;
+
+ /// Constructor
+
+ /// Constructor.
+ /// \param m The undelying map.
+ /// \param v The constant value.
+ ShiftWriteMap(M &m, const C &v) : _m(m), _v(v) {}
+ ///\e
+ Value operator[](const Key &k) const { return _m[k]+_v; }
+ ///\e
+ void set(const Key &k, const Value &v) { _m.set(k, v-_v); }
+ };
+
+ /// Returns a \c ShiftMap class
+
+ /// This function just returns a \c ShiftMap class.
+ ///
+ /// For example, if \c m is a map with \c double values and \c v is
+ /// \c double, then <tt>shiftMap(m,v)[x]</tt> will be equal to
+ /// <tt>m[x]+v</tt>.
+ ///
+ /// \relates ShiftMap
+ template<typename M, typename C>
+ inline ShiftMap<M, C> shiftMap(const M &m, const C &v) {
+ return ShiftMap<M, C>(m,v);
+ }
+
+ /// Returns a \c ShiftWriteMap class
+
+ /// This function just returns a \c ShiftWriteMap class.
+ ///
+ /// For example, if \c m is a map with \c double values and \c v is
+ /// \c double, then <tt>shiftWriteMap(m,v)[x]</tt> will be equal to
+ /// <tt>m[x]+v</tt>.
+ /// Moreover it makes also possible to write the map.
+ ///
+ /// \relates ShiftWriteMap
+ template<typename M, typename C>
+ inline ShiftWriteMap<M, C> shiftWriteMap(M &m, const C &v) {
+ return ShiftWriteMap<M, C>(m,v);
+ }
+
+
+ /// Scales a map with a constant.
+
+ /// This \ref concepts::ReadMap "read-only map" returns the value of
+ /// the given map multiplied from the left side with a constant value.
+ /// Its \c Key and \c Value are inherited from \c M.
+ ///
+ /// Actually,
+ /// \code
+ /// ScaleMap<M> sc(m,v);
+ /// \endcode
+ /// is equivalent to
+ /// \code
+ /// ConstMap<M::Key, M::Value> cm(v);
+ /// MulMap<ConstMap<M::Key, M::Value>, M> sc(cm,m);
+ /// \endcode
+ ///
+ /// The simplest way of using this map is through the scaleMap()
+ /// function.
+ ///
+ /// \sa ScaleWriteMap
+ template<typename M, typename C = typename M::Value>
+ class ScaleMap : public MapBase<typename M::Key, typename M::Value> {
+ const M &_m;
+ C _v;
+ public:
+ ///\e
+ typedef typename M::Key Key;
+ ///\e
+ typedef typename M::Value Value;
+
+ /// Constructor
+
+ /// Constructor.
+ /// \param m The undelying map.
+ /// \param v The constant value.
+ ScaleMap(const M &m, const C &v) : _m(m), _v(v) {}
+ ///\e
+ Value operator[](const Key &k) const { return _v*_m[k]; }
+ };
+
+ /// Scales a map with a constant (read-write version).
+
+ /// This \ref concepts::ReadWriteMap "read-write map" returns the value of
+ /// the given map multiplied from the left side with a constant value.
+ /// Its \c Key and \c Value are inherited from \c M.
+ /// It can also be used as write map if the \c / operator is defined
+ /// between \c Value and \c C and the given multiplier is not zero.
+ ///
+ /// The simplest way of using this map is through the scaleWriteMap()
+ /// function.
+ ///
+ /// \sa ScaleMap
+ template<typename M, typename C = typename M::Value>
+ class ScaleWriteMap : public MapBase<typename M::Key, typename M::Value> {
+ M &_m;
+ C _v;
+ public:
+ ///\e
+ typedef typename M::Key Key;
+ ///\e
+ typedef typename M::Value Value;
+
+ /// Constructor
+
+ /// Constructor.
+ /// \param m The undelying map.
+ /// \param v The constant value.
+ ScaleWriteMap(M &m, const C &v) : _m(m), _v(v) {}
+ ///\e
+ Value operator[](const Key &k) const { return _v*_m[k]; }
+ ///\e
+ void set(const Key &k, const Value &v) { _m.set(k, v/_v); }
+ };
+
+ /// Returns a \c ScaleMap class
+
+ /// This function just returns a \c ScaleMap class.
+ ///
+ /// For example, if \c m is a map with \c double values and \c v is
+ /// \c double, then <tt>scaleMap(m,v)[x]</tt> will be equal to
+ /// <tt>v*m[x]</tt>.
+ ///
+ /// \relates ScaleMap
+ template<typename M, typename C>
+ inline ScaleMap<M, C> scaleMap(const M &m, const C &v) {
+ return ScaleMap<M, C>(m,v);
+ }
+
+ /// Returns a \c ScaleWriteMap class
+
+ /// This function just returns a \c ScaleWriteMap class.
+ ///
+ /// For example, if \c m is a map with \c double values and \c v is
+ /// \c double, then <tt>scaleWriteMap(m,v)[x]</tt> will be equal to
+ /// <tt>v*m[x]</tt>.
+ /// Moreover it makes also possible to write the map.
+ ///
+ /// \relates ScaleWriteMap
+ template<typename M, typename C>
+ inline ScaleWriteMap<M, C> scaleWriteMap(M &m, const C &v) {
+ return ScaleWriteMap<M, C>(m,v);
+ }
+
+
+ /// Negative of a map
+
+ /// This \ref concepts::ReadMap "read-only map" returns the negative
+ /// of the values of the given map (using the unary \c - operator).
+ /// Its \c Key and \c Value are inherited from \c M.
+ ///
+ /// If M::Value is \c int, \c double etc., then
+ /// \code
+ /// NegMap<M> neg(m);
+ /// \endcode
+ /// is equivalent to
+ /// \code
+ /// ScaleMap<M> neg(m,-1);
+ /// \endcode
+ ///
+ /// The simplest way of using this map is through the negMap()
+ /// function.
+ ///
+ /// \sa NegWriteMap
+ template<typename M>
+ class NegMap : public MapBase<typename M::Key, typename M::Value> {
+ const M& _m;
+ public:
+ ///\e
+ typedef typename M::Key Key;
+ ///\e
+ typedef typename M::Value Value;
+
+ /// Constructor
+ NegMap(const M &m) : _m(m) {}
+ ///\e
+ Value operator[](const Key &k) const { return -_m[k]; }
+ };
+
+ /// Negative of a map (read-write version)
+
+ /// This \ref concepts::ReadWriteMap "read-write map" returns the
+ /// negative of the values of the given map (using the unary \c -
+ /// operator).
+ /// Its \c Key and \c Value are inherited from \c M.
+ /// It makes also possible to write the map.
+ ///
+ /// If M::Value is \c int, \c double etc., then
+ /// \code
+ /// NegWriteMap<M> neg(m);
+ /// \endcode
+ /// is equivalent to
+ /// \code
+ /// ScaleWriteMap<M> neg(m,-1);
+ /// \endcode
+ ///
+ /// The simplest way of using this map is through the negWriteMap()
+ /// function.
+ ///
+ /// \sa NegMap
+ template<typename M>
+ class NegWriteMap : public MapBase<typename M::Key, typename M::Value> {
+ M &_m;
+ public:
+ ///\e
+ typedef typename M::Key Key;
+ ///\e
+ typedef typename M::Value Value;
+
+ /// Constructor
+ NegWriteMap(M &m) : _m(m) {}
+ ///\e
+ Value operator[](const Key &k) const { return -_m[k]; }
+ ///\e
+ void set(const Key &k, const Value &v) { _m.set(k, -v); }
+ };
+
+ /// Returns a \c NegMap class
+
+ /// This function just returns a \c NegMap class.
+ ///
+ /// For example, if \c m is a map with \c double values, then
+ /// <tt>negMap(m)[x]</tt> will be equal to <tt>-m[x]</tt>.
+ ///
+ /// \relates NegMap
+ template <typename M>
+ inline NegMap<M> negMap(const M &m) {
+ return NegMap<M>(m);
+ }
+
+ /// Returns a \c NegWriteMap class
+
+ /// This function just returns a \c NegWriteMap class.
+ ///
+ /// For example, if \c m is a map with \c double values, then
+ /// <tt>negWriteMap(m)[x]</tt> will be equal to <tt>-m[x]</tt>.
+ /// Moreover it makes also possible to write the map.
+ ///
+ /// \relates NegWriteMap
+ template <typename M>
+ inline NegWriteMap<M> negWriteMap(M &m) {
+ return NegWriteMap<M>(m);
+ }
+
+
+ /// Absolute value of a map
+
+ /// This \ref concepts::ReadMap "read-only map" returns the absolute
+ /// value of the values of the given map.
+ /// Its \c Key and \c Value are inherited from \c M.
+ /// \c Value must be comparable to \c 0 and the unary \c -
+ /// operator must be defined for it, of course.
+ ///
+ /// The simplest way of using this map is through the absMap()
+ /// function.
+ template<typename M>
+ class AbsMap : public MapBase<typename M::Key, typename M::Value> {
+ const M &_m;
+ public:
+ ///\e
+ typedef typename M::Key Key;
+ ///\e
+ typedef typename M::Value Value;
+
+ /// Constructor
+ AbsMap(const M &m) : _m(m) {}
+ ///\e
+ Value operator[](const Key &k) const {
+ Value tmp = _m[k];
+ return tmp >= 0 ? tmp : -tmp;
+ }
+
+ };
+
+ /// Returns an \c AbsMap class
+
+ /// This function just returns an \c AbsMap class.
+ ///
+ /// For example, if \c m is a map with \c double values, then
+ /// <tt>absMap(m)[x]</tt> will be equal to <tt>m[x]</tt> if
+ /// it is positive or zero and <tt>-m[x]</tt> if <tt>m[x]</tt> is
+ /// negative.
+ ///
+ /// \relates AbsMap
+ template<typename M>
+ inline AbsMap<M> absMap(const M &m) {
+ return AbsMap<M>(m);
+ }
+
+ /// @}
+
+ // Logical maps and map adaptors:
+
+ /// \addtogroup maps
+ /// @{
+
+ /// Constant \c true map.
+
+ /// This \ref concepts::ReadMap "read-only map" assigns \c true to
+ /// each key.
+ ///
+ /// Note that
+ /// \code
+ /// TrueMap<K> tm;
+ /// \endcode
+ /// is equivalent to
+ /// \code
+ /// ConstMap<K,bool> tm(true);
+ /// \endcode
+ ///
+ /// \sa FalseMap
+ /// \sa ConstMap
+ template <typename K>
+ class TrueMap : public MapBase<K, bool> {
+ public:
+ ///\e
+ typedef K Key;
+ ///\e
+ typedef bool Value;
+
+ /// Gives back \c true.
+ Value operator[](const Key&) const { return true; }
+ };
+
+ /// Returns a \c TrueMap class
+
+ /// This function just returns a \c TrueMap class.
+ /// \relates TrueMap
+ template<typename K>
+ inline TrueMap<K> trueMap() {
+ return TrueMap<K>();
+ }
+
+
+ /// Constant \c false map.
+
+ /// This \ref concepts::ReadMap "read-only map" assigns \c false to
+ /// each key.
+ ///
+ /// Note that
+ /// \code
+ /// FalseMap<K> fm;
+ /// \endcode
+ /// is equivalent to
+ /// \code
+ /// ConstMap<K,bool> fm(false);
+ /// \endcode
+ ///
+ /// \sa TrueMap
+ /// \sa ConstMap
+ template <typename K>
+ class FalseMap : public MapBase<K, bool> {
+ public:
+ ///\e
+ typedef K Key;
+ ///\e
+ typedef bool Value;
+
+ /// Gives back \c false.
+ Value operator[](const Key&) const { return false; }
+ };
+
+ /// Returns a \c FalseMap class
+
+ /// This function just returns a \c FalseMap class.
+ /// \relates FalseMap
+ template<typename K>
+ inline FalseMap<K> falseMap() {
+ return FalseMap<K>();
+ }
+
+ /// @}
+
+ /// \addtogroup map_adaptors
+ /// @{
+
+ /// Logical 'and' of two maps
+
+ /// This \ref concepts::ReadMap "read-only map" returns the logical
+ /// 'and' of the values of the two given maps.
+ /// Its \c Key type is inherited from \c M1 and its \c Value type is
+ /// \c bool. \c M2::Key must be convertible to \c M1::Key.
+ ///
+ /// If \c m1 is of type \c M1 and \c m2 is of \c M2, then for
+ /// \code
+ /// AndMap<M1,M2> am(m1,m2);
+ /// \endcode
+ /// <tt>am[x]</tt> will be equal to <tt>m1[x]&&m2[x]</tt>.
+ ///
+ /// The simplest way of using this map is through the andMap()
+ /// function.
+ ///
+ /// \sa OrMap
+ /// \sa NotMap, NotWriteMap
+ template<typename M1, typename M2>
+ class AndMap : public MapBase<typename M1::Key, bool> {
+ const M1 &_m1;
+ const M2 &_m2;
+ public:
+ ///\e
+ typedef typename M1::Key Key;
+ ///\e
+ typedef bool Value;
+
+ /// Constructor
+ AndMap(const M1 &m1, const M2 &m2) : _m1(m1), _m2(m2) {}
+ ///\e
+ Value operator[](const Key &k) const { return _m1[k]&&_m2[k]; }
+ };
+
+ /// Returns an \c AndMap class
+
+ /// This function just returns an \c AndMap class.
+ ///
+ /// For example, if \c m1 and \c m2 are both maps with \c bool values,
+ /// then <tt>andMap(m1,m2)[x]</tt> will be equal to
+ /// <tt>m1[x]&&m2[x]</tt>.
+ ///
+ /// \relates AndMap
+ template<typename M1, typename M2>
+ inline AndMap<M1, M2> andMap(const M1 &m1, const M2 &m2) {
+ return AndMap<M1, M2>(m1,m2);
+ }
+
+
+ /// Logical 'or' of two maps
+
+ /// This \ref concepts::ReadMap "read-only map" returns the logical
+ /// 'or' of the values of the two given maps.
+ /// Its \c Key type is inherited from \c M1 and its \c Value type is
+ /// \c bool. \c M2::Key must be convertible to \c M1::Key.
+ ///
+ /// If \c m1 is of type \c M1 and \c m2 is of \c M2, then for
+ /// \code
+ /// OrMap<M1,M2> om(m1,m2);
+ /// \endcode
+ /// <tt>om[x]</tt> will be equal to <tt>m1[x]||m2[x]</tt>.
+ ///
+ /// The simplest way of using this map is through the orMap()
+ /// function.
+ ///
+ /// \sa AndMap
+ /// \sa NotMap, NotWriteMap
+ template<typename M1, typename M2>
+ class OrMap : public MapBase<typename M1::Key, bool> {
+ const M1 &_m1;
+ const M2 &_m2;
+ public:
+ ///\e
+ typedef typename M1::Key Key;
+ ///\e
+ typedef bool Value;
+
+ /// Constructor
+ OrMap(const M1 &m1, const M2 &m2) : _m1(m1), _m2(m2) {}
+ ///\e
+ Value operator[](const Key &k) const { return _m1[k]||_m2[k]; }
+ };
+
+ /// Returns an \c OrMap class
+
+ /// This function just returns an \c OrMap class.
+ ///
+ /// For example, if \c m1 and \c m2 are both maps with \c bool values,
+ /// then <tt>orMap(m1,m2)[x]</tt> will be equal to
+ /// <tt>m1[x]||m2[x]</tt>.
+ ///
+ /// \relates OrMap
+ template<typename M1, typename M2>
+ inline OrMap<M1, M2> orMap(const M1 &m1, const M2 &m2) {
+ return OrMap<M1, M2>(m1,m2);
+ }
+
+
+ /// Logical 'not' of a map
+
+ /// This \ref concepts::ReadMap "read-only map" returns the logical
+ /// negation of the values of the given map.
+ /// Its \c Key is inherited from \c M and its \c Value is \c bool.
+ ///
+ /// The simplest way of using this map is through the notMap()
+ /// function.
+ ///
+ /// \sa NotWriteMap
+ template <typename M>
+ class NotMap : public MapBase<typename M::Key, bool> {
+ const M &_m;
+ public:
+ ///\e
+ typedef typename M::Key Key;
+ ///\e
+ typedef bool Value;
+
+ /// Constructor
+ NotMap(const M &m) : _m(m) {}
+ ///\e
+ Value operator[](const Key &k) const { return !_m[k]; }
+ };
+
+ /// Logical 'not' of a map (read-write version)
+
+ /// This \ref concepts::ReadWriteMap "read-write map" returns the
+ /// logical negation of the values of the given map.
+ /// Its \c Key is inherited from \c M and its \c Value is \c bool.
+ /// It makes also possible to write the map. When a value is set,
+ /// the opposite value is set to the original map.
+ ///
+ /// The simplest way of using this map is through the notWriteMap()
+ /// function.
+ ///
+ /// \sa NotMap
+ template <typename M>
+ class NotWriteMap : public MapBase<typename M::Key, bool> {
+ M &_m;
+ public:
+ ///\e
+ typedef typename M::Key Key;
+ ///\e
+ typedef bool Value;
+
+ /// Constructor
+ NotWriteMap(M &m) : _m(m) {}
+ ///\e
+ Value operator[](const Key &k) const { return !_m[k]; }
+ ///\e
+ void set(const Key &k, bool v) { _m.set(k, !v); }
+ };
+
+ /// Returns a \c NotMap class
+
+ /// This function just returns a \c NotMap class.
+ ///
+ /// For example, if \c m is a map with \c bool values, then
+ /// <tt>notMap(m)[x]</tt> will be equal to <tt>!m[x]</tt>.
+ ///
+ /// \relates NotMap
+ template <typename M>
+ inline NotMap<M> notMap(const M &m) {
+ return NotMap<M>(m);
+ }
+
+ /// Returns a \c NotWriteMap class
+
+ /// This function just returns a \c NotWriteMap class.
+ ///
+ /// For example, if \c m is a map with \c bool values, then
+ /// <tt>notWriteMap(m)[x]</tt> will be equal to <tt>!m[x]</tt>.
+ /// Moreover it makes also possible to write the map.
+ ///
+ /// \relates NotWriteMap
+ template <typename M>
+ inline NotWriteMap<M> notWriteMap(M &m) {
+ return NotWriteMap<M>(m);
+ }
+
+
+ /// Combination of two maps using the \c == operator
+
+ /// This \ref concepts::ReadMap "read-only map" assigns \c true to
+ /// the keys for which the corresponding values of the two maps are
+ /// equal.
+ /// Its \c Key type is inherited from \c M1 and its \c Value type is
+ /// \c bool. \c M2::Key must be convertible to \c M1::Key.
+ ///
+ /// If \c m1 is of type \c M1 and \c m2 is of \c M2, then for
+ /// \code
+ /// EqualMap<M1,M2> em(m1,m2);
+ /// \endcode
+ /// <tt>em[x]</tt> will be equal to <tt>m1[x]==m2[x]</tt>.
+ ///
+ /// The simplest way of using this map is through the equalMap()
+ /// function.
+ ///
+ /// \sa LessMap
+ template<typename M1, typename M2>
+ class EqualMap : public MapBase<typename M1::Key, bool> {
+ const M1 &_m1;
+ const M2 &_m2;
+ public:
+ ///\e
+ typedef typename M1::Key Key;
+ ///\e
+ typedef bool Value;
+
+ /// Constructor
+ EqualMap(const M1 &m1, const M2 &m2) : _m1(m1), _m2(m2) {}
+ ///\e
+ Value operator[](const Key &k) const { return _m1[k]==_m2[k]; }
+ };
+
+ /// Returns an \c EqualMap class
+
+ /// This function just returns an \c EqualMap class.
+ ///
+ /// For example, if \c m1 and \c m2 are maps with keys and values of
+ /// the same type, then <tt>equalMap(m1,m2)[x]</tt> will be equal to
+ /// <tt>m1[x]==m2[x]</tt>.
+ ///
+ /// \relates EqualMap
+ template<typename M1, typename M2>
+ inline EqualMap<M1, M2> equalMap(const M1 &m1, const M2 &m2) {
+ return EqualMap<M1, M2>(m1,m2);
+ }
+
+
+ /// Combination of two maps using the \c < operator
+
+ /// This \ref concepts::ReadMap "read-only map" assigns \c true to
+ /// the keys for which the corresponding value of the first map is
+ /// less then the value of the second map.
+ /// Its \c Key type is inherited from \c M1 and its \c Value type is
+ /// \c bool. \c M2::Key must be convertible to \c M1::Key.
+ ///
+ /// If \c m1 is of type \c M1 and \c m2 is of \c M2, then for
+ /// \code
+ /// LessMap<M1,M2> lm(m1,m2);
+ /// \endcode
+ /// <tt>lm[x]</tt> will be equal to <tt>m1[x]<m2[x]</tt>.
+ ///
+ /// The simplest way of using this map is through the lessMap()
+ /// function.
+ ///
+ /// \sa EqualMap
+ template<typename M1, typename M2>
+ class LessMap : public MapBase<typename M1::Key, bool> {
+ const M1 &_m1;
+ const M2 &_m2;
+ public:
+ ///\e
+ typedef typename M1::Key Key;
+ ///\e
+ typedef bool Value;
+
+ /// Constructor
+ LessMap(const M1 &m1, const M2 &m2) : _m1(m1), _m2(m2) {}
+ ///\e
+ Value operator[](const Key &k) const { return _m1[k]<_m2[k]; }
+ };
+
+ /// Returns an \c LessMap class
+
+ /// This function just returns an \c LessMap class.
+ ///
+ /// For example, if \c m1 and \c m2 are maps with keys and values of
+ /// the same type, then <tt>lessMap(m1,m2)[x]</tt> will be equal to
+ /// <tt>m1[x]<m2[x]</tt>.
+ ///
+ /// \relates LessMap
+ template<typename M1, typename M2>
+ inline LessMap<M1, M2> lessMap(const M1 &m1, const M2 &m2) {
+ return LessMap<M1, M2>(m1,m2);
+ }
+
+ namespace _maps_bits {
+
+ template <typename _Iterator, typename Enable = void>
+ struct IteratorTraits {
+ typedef typename std::iterator_traits<_Iterator>::value_type Value;
+ };
+
+ template <typename _Iterator>
+ struct IteratorTraits<_Iterator,
+ typename exists<typename _Iterator::container_type>::type>
+ {
+ typedef typename _Iterator::container_type::value_type Value;
+ };
+
+ }
+
+ /// @}
+
+ /// \addtogroup maps
+ /// @{
+
+ /// \brief Writable bool map for logging each \c true assigned element
+ ///
+ /// A \ref concepts::WriteMap "writable" bool map for logging
+ /// each \c true assigned element, i.e it copies subsequently each
+ /// keys set to \c true to the given iterator.
+ /// The most important usage of it is storing certain nodes or arcs
+ /// that were marked \c true by an algorithm.
+ ///
+ /// There are several algorithms that provide solutions through bool
+ /// maps and most of them assign \c true at most once for each key.
+ /// In these cases it is a natural request to store each \c true
+ /// assigned elements (in order of the assignment), which can be
+ /// easily done with LoggerBoolMap.
+ ///
+ /// The simplest way of using this map is through the loggerBoolMap()
+ /// function.
+ ///
+ /// \tparam IT The type of the iterator.
+ /// \tparam KEY The key type of the map. The default value set
+ /// according to the iterator type should work in most cases.
+ ///
+ /// \note The container of the iterator must contain enough space
+ /// for the elements or the iterator should be an inserter iterator.
+#ifdef DOXYGEN
+ template <typename IT, typename KEY>
+#else
+ template <typename IT,
+ typename KEY = typename _maps_bits::IteratorTraits<IT>::Value>
+#endif
+ class LoggerBoolMap : public MapBase<KEY, bool> {
+ public:
+
+ ///\e
+ typedef KEY Key;
+ ///\e
+ typedef bool Value;
+ ///\e
+ typedef IT Iterator;
+
+ /// Constructor
+ LoggerBoolMap(Iterator it)
+ : _begin(it), _end(it) {}
+
+ /// Gives back the given iterator set for the first key
+ Iterator begin() const {
+ return _begin;
+ }
+
+ /// Gives back the the 'after the last' iterator
+ Iterator end() const {
+ return _end;
+ }
+
+ /// The set function of the map
+ void set(const Key& key, Value value) {
+ if (value) {
+ *_end++ = key;
+ }
+ }
+
+ private:
+ Iterator _begin;
+ Iterator _end;
+ };
+
+ /// Returns a \c LoggerBoolMap class
+
+ /// This function just returns a \c LoggerBoolMap class.
+ ///
+ /// The most important usage of it is storing certain nodes or arcs
+ /// that were marked \c true by an algorithm.
+ /// For example, it makes easier to store the nodes in the processing
+ /// order of Dfs algorithm, as the following examples show.
+ /// \code
+ /// std::vector<Node> v;
+ /// dfs(g).processedMap(loggerBoolMap(std::back_inserter(v))).run(s);
+ /// \endcode
+ /// \code
+ /// std::vector<Node> v(countNodes(g));
+ /// dfs(g).processedMap(loggerBoolMap(v.begin())).run(s);
+ /// \endcode
+ ///
+ /// \note The container of the iterator must contain enough space
+ /// for the elements or the iterator should be an inserter iterator.
+ ///
+ /// \note LoggerBoolMap is just \ref concepts::WriteMap "writable", so
+ /// it cannot be used when a readable map is needed, for example, as
+ /// \c ReachedMap for \c Bfs, \c Dfs and \c Dijkstra algorithms.
+ ///
+ /// \relates LoggerBoolMap
+ template<typename Iterator>
+ inline LoggerBoolMap<Iterator> loggerBoolMap(Iterator it) {
+ return LoggerBoolMap<Iterator>(it);
+ }
+
+ /// @}
+
+ /// \addtogroup graph_maps
+ /// @{
+
+ /// \brief Provides an immutable and unique id for each item in a graph.
+ ///
+ /// IdMap provides a unique and immutable id for each item of the
+ /// same type (\c Node, \c Arc or \c Edge) in a graph. This id is
+ /// - \b unique: different items get different ids,
+ /// - \b immutable: the id of an item does not change (even if you
+ /// delete other nodes).
+ ///
+ /// Using this map you get access (i.e. can read) the inner id values of
+ /// the items stored in the graph, which is returned by the \c id()
+ /// function of the graph. This map can be inverted with its member
+ /// class \c InverseMap or with the \c operator()() member.
+ ///
+ /// \tparam GR The graph type.
+ /// \tparam K The key type of the map (\c GR::Node, \c GR::Arc or
+ /// \c GR::Edge).
+ ///
+ /// \see RangeIdMap
+ template <typename GR, typename K>
+ class IdMap : public MapBase<K, int> {
+ public:
+ /// The graph type of IdMap.
+ typedef GR Graph;
+ typedef GR Digraph;
+ /// The key type of IdMap (\c Node, \c Arc or \c Edge).
+ typedef K Item;
+ /// The key type of IdMap (\c Node, \c Arc or \c Edge).
+ typedef K Key;
+ /// The value type of IdMap.
+ typedef int Value;
+
+ /// \brief Constructor.
+ ///
+ /// Constructor of the map.
+ explicit IdMap(const Graph& graph) : _graph(&graph) {}
+
+ /// \brief Gives back the \e id of the item.
+ ///
+ /// Gives back the immutable and unique \e id of the item.
+ int operator[](const Item& item) const { return _graph->id(item);}
+
+ /// \brief Gives back the \e item by its id.
+ ///
+ /// Gives back the \e item by its id.
+ Item operator()(int id) { return _graph->fromId(id, Item()); }
+
+ private:
+ const Graph* _graph;
+
+ public:
+
+ /// \brief The inverse map type of IdMap.
+ ///
+ /// The inverse map type of IdMap. The subscript operator gives back
+ /// an item by its id.
+ /// This type conforms to the \ref concepts::ReadMap "ReadMap" concept.
+ /// \see inverse()
+ class InverseMap {
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor for creating an id-to-item map.
+ explicit InverseMap(const Graph& graph) : _graph(&graph) {}
+
+ /// \brief Constructor.
+ ///
+ /// Constructor for creating an id-to-item map.
+ explicit InverseMap(const IdMap& map) : _graph(map._graph) {}
+
+ /// \brief Gives back an item by its id.
+ ///
+ /// Gives back an item by its id.
+ Item operator[](int id) const { return _graph->fromId(id, Item());}
+
+ private:
+ const Graph* _graph;
+ };
+
+ /// \brief Gives back the inverse of the map.
+ ///
+ /// Gives back the inverse of the IdMap.
+ InverseMap inverse() const { return InverseMap(*_graph);}
+ };
+
+ /// \brief Returns an \c IdMap class.
+ ///
+ /// This function just returns an \c IdMap class.
+ /// \relates IdMap
+ template <typename K, typename GR>
+ inline IdMap<GR, K> idMap(const GR& graph) {
+ return IdMap<GR, K>(graph);
+ }
+
+ /// \brief General cross reference graph map type.
+
+ /// This class provides simple invertable graph maps.
+ /// It wraps a standard graph map (\c NodeMap, \c ArcMap or \c EdgeMap)
+ /// and if a key is set to a new value, then stores it in the inverse map.
+ /// The graph items can be accessed by their values either using
+ /// \c InverseMap or \c operator()(), and the values of the map can be
+ /// accessed with an STL compatible forward iterator (\c ValueIt).
+ ///
+ /// This map is intended to be used when all associated values are
+ /// different (the map is actually invertable) or there are only a few
+ /// items with the same value.
+ /// Otherwise consider to use \c IterableValueMap, which is more
+ /// suitable and more efficient for such cases. It provides iterators
+ /// to traverse the items with the same associated value, but
+ /// it does not have \c InverseMap.
+ ///
+ /// This type is not reference map, so it cannot be modified with
+ /// the subscript operator.
+ ///
+ /// \tparam GR The graph type.
+ /// \tparam K The key type of the map (\c GR::Node, \c GR::Arc or
+ /// \c GR::Edge).
+ /// \tparam V The value type of the map.
+ ///
+ /// \see IterableValueMap
+ template <typename GR, typename K, typename V>
+ class CrossRefMap
+ : protected ItemSetTraits<GR, K>::template Map<V>::Type {
+ private:
+
+ typedef typename ItemSetTraits<GR, K>::
+ template Map<V>::Type Map;
+
+ typedef std::multimap<V, K> Container;
+ Container _inv_map;
+
+ public:
+
+ /// The graph type of CrossRefMap.
+ typedef GR Graph;
+ typedef GR Digraph;
+ /// The key type of CrossRefMap (\c Node, \c Arc or \c Edge).
+ typedef K Item;
+ /// The key type of CrossRefMap (\c Node, \c Arc or \c Edge).
+ typedef K Key;
+ /// The value type of CrossRefMap.
+ typedef V Value;
+
+ /// \brief Constructor.
+ ///
+ /// Construct a new CrossRefMap for the given graph.
+ explicit CrossRefMap(const Graph& graph) : Map(graph) {}
+
+ /// \brief Forward iterator for values.
+ ///
+ /// This iterator is an STL compatible forward
+ /// iterator on the values of the map. The values can
+ /// be accessed in the <tt>[beginValue, endValue)</tt> range.
+ /// They are considered with multiplicity, so each value is
+ /// traversed for each item it is assigned to.
+ class ValueIt
+ : public std::iterator<std::forward_iterator_tag, Value> {
+ friend class CrossRefMap;
+ private:
+ ValueIt(typename Container::const_iterator _it)
+ : it(_it) {}
+ public:
+
+ /// Constructor
+ ValueIt() {}
+
+ /// \e
+ ValueIt& operator++() { ++it; return *this; }
+ /// \e
+ ValueIt operator++(int) {
+ ValueIt tmp(*this);
+ operator++();
+ return tmp;
+ }
+
+ /// \e
+ const Value& operator*() const { return it->first; }
+ /// \e
+ const Value* operator->() const { return &(it->first); }
+
+ /// \e
+ bool operator==(ValueIt jt) const { return it == jt.it; }
+ /// \e
+ bool operator!=(ValueIt jt) const { return it != jt.it; }
+
+ private:
+ typename Container::const_iterator it;
+ };
+
+ /// Alias for \c ValueIt
+ typedef ValueIt ValueIterator;
+
+ /// \brief Returns an iterator to the first value.
+ ///
+ /// Returns an STL compatible iterator to the
+ /// first value of the map. The values of the
+ /// map can be accessed in the <tt>[beginValue, endValue)</tt>
+ /// range.
+ ValueIt beginValue() const {
+ return ValueIt(_inv_map.begin());
+ }
+
+ /// \brief Returns an iterator after the last value.
+ ///
+ /// Returns an STL compatible iterator after the
+ /// last value of the map. The values of the
+ /// map can be accessed in the <tt>[beginValue, endValue)</tt>
+ /// range.
+ ValueIt endValue() const {
+ return ValueIt(_inv_map.end());
+ }
+
+ /// \brief Sets the value associated with the given key.
+ ///
+ /// Sets the value associated with the given key.
+ void set(const Key& key, const Value& val) {
+ Value oldval = Map::operator[](key);
+ typename Container::iterator it;
+ for (it = _inv_map.equal_range(oldval).first;
+ it != _inv_map.equal_range(oldval).second; ++it) {
+ if (it->second == key) {
+ _inv_map.erase(it);
+ break;
+ }
+ }
+ _inv_map.insert(std::make_pair(val, key));
+ Map::set(key, val);
+ }
+
+ /// \brief Returns the value associated with the given key.
+ ///
+ /// Returns the value associated with the given key.
+ typename MapTraits<Map>::ConstReturnValue
+ operator[](const Key& key) const {
+ return Map::operator[](key);
+ }
+
+ /// \brief Gives back an item by its value.
+ ///
+ /// This function gives back an item that is assigned to
+ /// the given value or \c INVALID if no such item exists.
+ /// If there are more items with the same associated value,
+ /// only one of them is returned.
+ Key operator()(const Value& val) const {
+ typename Container::const_iterator it = _inv_map.find(val);
+ return it != _inv_map.end() ? it->second : INVALID;
+ }
+
+ /// \brief Returns the number of items with the given value.
+ ///
+ /// This function returns the number of items with the given value
+ /// associated with it.
+ int count(const Value &val) const {
+ return _inv_map.count(val);
+ }
+
+ protected:
+
+ /// \brief Erase the key from the map and the inverse map.
+ ///
+ /// Erase the key from the map and the inverse map. It is called by the
+ /// \c AlterationNotifier.
+ virtual void erase(const Key& key) {
+ Value val = Map::operator[](key);
+ typename Container::iterator it;
+ for (it = _inv_map.equal_range(val).first;
+ it != _inv_map.equal_range(val).second; ++it) {
+ if (it->second == key) {
+ _inv_map.erase(it);
+ break;
+ }
+ }
+ Map::erase(key);
+ }
+
+ /// \brief Erase more keys from the map and the inverse map.
+ ///
+ /// Erase more keys from the map and the inverse map. It is called by the
+ /// \c AlterationNotifier.
+ virtual void erase(const std::vector<Key>& keys) {
+ for (int i = 0; i < int(keys.size()); ++i) {
+ Value val = Map::operator[](keys[i]);
+ typename Container::iterator it;
+ for (it = _inv_map.equal_range(val).first;
+ it != _inv_map.equal_range(val).second; ++it) {
+ if (it->second == keys[i]) {
+ _inv_map.erase(it);
+ break;
+ }
+ }
+ }
+ Map::erase(keys);
+ }
+
+ /// \brief Clear the keys from the map and the inverse map.
+ ///
+ /// Clear the keys from the map and the inverse map. It is called by the
+ /// \c AlterationNotifier.
+ virtual void clear() {
+ _inv_map.clear();
+ Map::clear();
+ }
+
+ public:
+
+ /// \brief The inverse map type of CrossRefMap.
+ ///
+ /// The inverse map type of CrossRefMap. The subscript operator gives
+ /// back an item by its value.
+ /// This type conforms to the \ref concepts::ReadMap "ReadMap" concept.
+ /// \see inverse()
+ class InverseMap {
+ public:
+ /// \brief Constructor
+ ///
+ /// Constructor of the InverseMap.
+ explicit InverseMap(const CrossRefMap& inverted)
+ : _inverted(inverted) {}
+
+ /// The value type of the InverseMap.
+ typedef typename CrossRefMap::Key Value;
+ /// The key type of the InverseMap.
+ typedef typename CrossRefMap::Value Key;
+
+ /// \brief Subscript operator.
+ ///
+ /// Subscript operator. It gives back an item
+ /// that is assigned to the given value or \c INVALID
+ /// if no such item exists.
+ Value operator[](const Key& key) const {
+ return _inverted(key);
+ }
+
+ private:
+ const CrossRefMap& _inverted;
+ };
+
+ /// \brief Gives back the inverse of the map.
+ ///
+ /// Gives back the inverse of the CrossRefMap.
+ InverseMap inverse() const {
+ return InverseMap(*this);
+ }
+
+ };
+
+ /// \brief Provides continuous and unique id for the
+ /// items of a graph.
+ ///
+ /// RangeIdMap provides a unique and continuous
+ /// id for each item of a given type (\c Node, \c Arc or
+ /// \c Edge) in a graph. This id is
+ /// - \b unique: different items get different ids,
+ /// - \b continuous: the range of the ids is the set of integers
+ /// between 0 and \c n-1, where \c n is the number of the items of
+ /// this type (\c Node, \c Arc or \c Edge).
+ /// - So, the ids can change when deleting an item of the same type.
+ ///
+ /// Thus this id is not (necessarily) the same as what can get using
+ /// the \c id() function of the graph or \ref IdMap.
+ /// This map can be inverted with its member class \c InverseMap,
+ /// or with the \c operator()() member.
+ ///
+ /// \tparam GR The graph type.
+ /// \tparam K The key type of the map (\c GR::Node, \c GR::Arc or
+ /// \c GR::Edge).
+ ///
+ /// \see IdMap
+ template <typename GR, typename K>
+ class RangeIdMap
+ : protected ItemSetTraits<GR, K>::template Map<int>::Type {
+
+ typedef typename ItemSetTraits<GR, K>::template Map<int>::Type Map;
+
+ public:
+ /// The graph type of RangeIdMap.
+ typedef GR Graph;
+ typedef GR Digraph;
+ /// The key type of RangeIdMap (\c Node, \c Arc or \c Edge).
+ typedef K Item;
+ /// The key type of RangeIdMap (\c Node, \c Arc or \c Edge).
+ typedef K Key;
+ /// The value type of RangeIdMap.
+ typedef int Value;
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ explicit RangeIdMap(const Graph& gr) : Map(gr) {
+ Item it;
+ const typename Map::Notifier* nf = Map::notifier();
+ for (nf->first(it); it != INVALID; nf->next(it)) {
+ Map::set(it, _inv_map.size());
+ _inv_map.push_back(it);
+ }
+ }
+
+ protected:
+
+ /// \brief Adds a new key to the map.
+ ///
+ /// Add a new key to the map. It is called by the
+ /// \c AlterationNotifier.
+ virtual void add(const Item& item) {
+ Map::add(item);
+ Map::set(item, _inv_map.size());
+ _inv_map.push_back(item);
+ }
+
+ /// \brief Add more new keys to the map.
+ ///
+ /// Add more new keys to the map. It is called by the
+ /// \c AlterationNotifier.
+ virtual void add(const std::vector<Item>& items) {
+ Map::add(items);
+ for (int i = 0; i < int(items.size()); ++i) {
+ Map::set(items[i], _inv_map.size());
+ _inv_map.push_back(items[i]);
+ }
+ }
+
+ /// \brief Erase the key from the map.
+ ///
+ /// Erase the key from the map. It is called by the
+ /// \c AlterationNotifier.
+ virtual void erase(const Item& item) {
+ Map::set(_inv_map.back(), Map::operator[](item));
+ _inv_map[Map::operator[](item)] = _inv_map.back();
+ _inv_map.pop_back();
+ Map::erase(item);
+ }
+
+ /// \brief Erase more keys from the map.
+ ///
+ /// Erase more keys from the map. It is called by the
+ /// \c AlterationNotifier.
+ virtual void erase(const std::vector<Item>& items) {
+ for (int i = 0; i < int(items.size()); ++i) {
+ Map::set(_inv_map.back(), Map::operator[](items[i]));
+ _inv_map[Map::operator[](items[i])] = _inv_map.back();
+ _inv_map.pop_back();
+ }
+ Map::erase(items);
+ }
+
+ /// \brief Build the unique map.
+ ///
+ /// Build the unique map. It is called by the
+ /// \c AlterationNotifier.
+ virtual void build() {
+ Map::build();
+ Item it;
+ const typename Map::Notifier* nf = Map::notifier();
+ for (nf->first(it); it != INVALID; nf->next(it)) {
+ Map::set(it, _inv_map.size());
+ _inv_map.push_back(it);
+ }
+ }
+
+ /// \brief Clear the keys from the map.
+ ///
+ /// Clear the keys from the map. It is called by the
+ /// \c AlterationNotifier.
+ virtual void clear() {
+ _inv_map.clear();
+ Map::clear();
+ }
+
+ public:
+
+ /// \brief Returns the maximal value plus one.
+ ///
+ /// Returns the maximal value plus one in the map.
+ unsigned int size() const {
+ return _inv_map.size();
+ }
+
+ /// \brief Swaps the position of the two items in the map.
+ ///
+ /// Swaps the position of the two items in the map.
+ void swap(const Item& p, const Item& q) {
+ int pi = Map::operator[](p);
+ int qi = Map::operator[](q);
+ Map::set(p, qi);
+ _inv_map[qi] = p;
+ Map::set(q, pi);
+ _inv_map[pi] = q;
+ }
+
+ /// \brief Gives back the \e range \e id of the item
+ ///
+ /// Gives back the \e range \e id of the item.
+ int operator[](const Item& item) const {
+ return Map::operator[](item);
+ }
+
+ /// \brief Gives back the item belonging to a \e range \e id
+ ///
+ /// Gives back the item belonging to the given \e range \e id.
+ Item operator()(int id) const {
+ return _inv_map[id];
+ }
+
+ private:
+
+ typedef std::vector<Item> Container;
+ Container _inv_map;
+
+ public:
+
+ /// \brief The inverse map type of RangeIdMap.
+ ///
+ /// The inverse map type of RangeIdMap. The subscript operator gives
+ /// back an item by its \e range \e id.
+ /// This type conforms to the \ref concepts::ReadMap "ReadMap" concept.
+ class InverseMap {
+ public:
+ /// \brief Constructor
+ ///
+ /// Constructor of the InverseMap.
+ explicit InverseMap(const RangeIdMap& inverted)
+ : _inverted(inverted) {}
+
+
+ /// The value type of the InverseMap.
+ typedef typename RangeIdMap::Key Value;
+ /// The key type of the InverseMap.
+ typedef typename RangeIdMap::Value Key;
+
+ /// \brief Subscript operator.
+ ///
+ /// Subscript operator. It gives back the item
+ /// that the given \e range \e id currently belongs to.
+ Value operator[](const Key& key) const {
+ return _inverted(key);
+ }
+
+ /// \brief Size of the map.
+ ///
+ /// Returns the size of the map.
+ unsigned int size() const {
+ return _inverted.size();
+ }
+
+ private:
+ const RangeIdMap& _inverted;
+ };
+
+ /// \brief Gives back the inverse of the map.
+ ///
+ /// Gives back the inverse of the RangeIdMap.
+ const InverseMap inverse() const {
+ return InverseMap(*this);
+ }
+ };
+
+ /// \brief Returns a \c RangeIdMap class.
+ ///
+ /// This function just returns an \c RangeIdMap class.
+ /// \relates RangeIdMap
+ template <typename K, typename GR>
+ inline RangeIdMap<GR, K> rangeIdMap(const GR& graph) {
+ return RangeIdMap<GR, K>(graph);
+ }
+
+ /// \brief Dynamic iterable \c bool map.
+ ///
+ /// This class provides a special graph map type which can store a
+ /// \c bool value for graph items (\c Node, \c Arc or \c Edge).
+ /// For both \c true and \c false values it is possible to iterate on
+ /// the keys mapped to the value.
+ ///
+ /// This type is a reference map, so it can be modified with the
+ /// subscript operator.
+ ///
+ /// \tparam GR The graph type.
+ /// \tparam K The key type of the map (\c GR::Node, \c GR::Arc or
+ /// \c GR::Edge).
+ ///
+ /// \see IterableIntMap, IterableValueMap
+ /// \see CrossRefMap
+ template <typename GR, typename K>
+ class IterableBoolMap
+ : protected ItemSetTraits<GR, K>::template Map<int>::Type {
+ private:
+ typedef GR Graph;
+
+ typedef typename ItemSetTraits<GR, K>::ItemIt KeyIt;
+ typedef typename ItemSetTraits<GR, K>::template Map<int>::Type Parent;
+
+ std::vector<K> _array;
+ int _sep;
+
+ public:
+
+ /// Indicates that the map is reference map.
+ typedef True ReferenceMapTag;
+
+ /// The key type
+ typedef K Key;
+ /// The value type
+ typedef bool Value;
+ /// The const reference type.
+ typedef const Value& ConstReference;
+
+ private:
+
+ int position(const Key& key) const {
+ return Parent::operator[](key);
+ }
+
+ public:
+
+ /// \brief Reference to the value of the map.
+ ///
+ /// This class is similar to the \c bool type. It can be converted to
+ /// \c bool and it provides the same operators.
+ class Reference {
+ friend class IterableBoolMap;
+ private:
+ Reference(IterableBoolMap& map, const Key& key)
+ : _key(key), _map(map) {}
+ public:
+
+ Reference& operator=(const Reference& value) {
+ _map.set(_key, static_cast<bool>(value));
+ return *this;
+ }
+
+ operator bool() const {
+ return static_cast<const IterableBoolMap&>(_map)[_key];
+ }
+
+ Reference& operator=(bool value) {
+ _map.set(_key, value);
+ return *this;
+ }
+ Reference& operator&=(bool value) {
+ _map.set(_key, _map[_key] & value);
+ return *this;
+ }
+ Reference& operator|=(bool value) {
+ _map.set(_key, _map[_key] | value);
+ return *this;
+ }
+ Reference& operator^=(bool value) {
+ _map.set(_key, _map[_key] ^ value);
+ return *this;
+ }
+ private:
+ Key _key;
+ IterableBoolMap& _map;
+ };
+
+ /// \brief Constructor of the map with a default value.
+ ///
+ /// Constructor of the map with a default value.
+ explicit IterableBoolMap(const Graph& graph, bool def = false)
+ : Parent(graph) {
+ typename Parent::Notifier* nf = Parent::notifier();
+ Key it;
+ for (nf->first(it); it != INVALID; nf->next(it)) {
+ Parent::set(it, _array.size());
+ _array.push_back(it);
+ }
+ _sep = (def ? _array.size() : 0);
+ }
+
+ /// \brief Const subscript operator of the map.
+ ///
+ /// Const subscript operator of the map.
+ bool operator[](const Key& key) const {
+ return position(key) < _sep;
+ }
+
+ /// \brief Subscript operator of the map.
+ ///
+ /// Subscript operator of the map.
+ Reference operator[](const Key& key) {
+ return Reference(*this, key);
+ }
+
+ /// \brief Set operation of the map.
+ ///
+ /// Set operation of the map.
+ void set(const Key& key, bool value) {
+ int pos = position(key);
+ if (value) {
+ if (pos < _sep) return;
+ Key tmp = _array[_sep];
+ _array[_sep] = key;
+ Parent::set(key, _sep);
+ _array[pos] = tmp;
+ Parent::set(tmp, pos);
+ ++_sep;
+ } else {
+ if (pos >= _sep) return;
+ --_sep;
+ Key tmp = _array[_sep];
+ _array[_sep] = key;
+ Parent::set(key, _sep);
+ _array[pos] = tmp;
+ Parent::set(tmp, pos);
+ }
+ }
+
+ /// \brief Set all items.
+ ///
+ /// Set all items in the map.
+ /// \note Constant time operation.
+ void setAll(bool value) {
+ _sep = (value ? _array.size() : 0);
+ }
+
+ /// \brief Returns the number of the keys mapped to \c true.
+ ///
+ /// Returns the number of the keys mapped to \c true.
+ int trueNum() const {
+ return _sep;
+ }
+
+ /// \brief Returns the number of the keys mapped to \c false.
+ ///
+ /// Returns the number of the keys mapped to \c false.
+ int falseNum() const {
+ return _array.size() - _sep;
+ }
+
+ /// \brief Iterator for the keys mapped to \c true.
+ ///
+ /// Iterator for the keys mapped to \c true. It works
+ /// like a graph item iterator, it can be converted to
+ /// the key type of the map, incremented with \c ++ operator, and
+ /// if the iterator leaves the last valid key, it will be equal to
+ /// \c INVALID.
+ class TrueIt : public Key {
+ public:
+ typedef Key Parent;
+
+ /// \brief Creates an iterator.
+ ///
+ /// Creates an iterator. It iterates on the
+ /// keys mapped to \c true.
+ /// \param map The IterableBoolMap.
+ explicit TrueIt(const IterableBoolMap& map)
+ : Parent(map._sep > 0 ? map._array[map._sep - 1] : INVALID),
+ _map(&map) {}
+
+ /// \brief Invalid constructor \& conversion.
+ ///
+ /// This constructor initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ TrueIt(Invalid) : Parent(INVALID), _map(0) {}
+
+ /// \brief Increment operator.
+ ///
+ /// Increment operator.
+ TrueIt& operator++() {
+ int pos = _map->position(*this);
+ Parent::operator=(pos > 0 ? _map->_array[pos - 1] : INVALID);
+ return *this;
+ }
+
+ private:
+ const IterableBoolMap* _map;
+ };
+
+ /// \brief Iterator for the keys mapped to \c false.
+ ///
+ /// Iterator for the keys mapped to \c false. It works
+ /// like a graph item iterator, it can be converted to
+ /// the key type of the map, incremented with \c ++ operator, and
+ /// if the iterator leaves the last valid key, it will be equal to
+ /// \c INVALID.
+ class FalseIt : public Key {
+ public:
+ typedef Key Parent;
+
+ /// \brief Creates an iterator.
+ ///
+ /// Creates an iterator. It iterates on the
+ /// keys mapped to \c false.
+ /// \param map The IterableBoolMap.
+ explicit FalseIt(const IterableBoolMap& map)
+ : Parent(map._sep < int(map._array.size()) ?
+ map._array.back() : INVALID), _map(&map) {}
+
+ /// \brief Invalid constructor \& conversion.
+ ///
+ /// This constructor initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ FalseIt(Invalid) : Parent(INVALID), _map(0) {}
+
+ /// \brief Increment operator.
+ ///
+ /// Increment operator.
+ FalseIt& operator++() {
+ int pos = _map->position(*this);
+ Parent::operator=(pos > _map->_sep ? _map->_array[pos - 1] : INVALID);
+ return *this;
+ }
+
+ private:
+ const IterableBoolMap* _map;
+ };
+
+ /// \brief Iterator for the keys mapped to a given value.
+ ///
+ /// Iterator for the keys mapped to a given value. It works
+ /// like a graph item iterator, it can be converted to
+ /// the key type of the map, incremented with \c ++ operator, and
+ /// if the iterator leaves the last valid key, it will be equal to
+ /// \c INVALID.
+ class ItemIt : public Key {
+ public:
+ typedef Key Parent;
+
+ /// \brief Creates an iterator with a value.
+ ///
+ /// Creates an iterator with a value. It iterates on the
+ /// keys mapped to the given value.
+ /// \param map The IterableBoolMap.
+ /// \param value The value.
+ ItemIt(const IterableBoolMap& map, bool value)
+ : Parent(value ?
+ (map._sep > 0 ?
+ map._array[map._sep - 1] : INVALID) :
+ (map._sep < int(map._array.size()) ?
+ map._array.back() : INVALID)), _map(&map) {}
+
+ /// \brief Invalid constructor \& conversion.
+ ///
+ /// This constructor initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ ItemIt(Invalid) : Parent(INVALID), _map(0) {}
+
+ /// \brief Increment operator.
+ ///
+ /// Increment operator.
+ ItemIt& operator++() {
+ int pos = _map->position(*this);
+ int _sep = pos >= _map->_sep ? _map->_sep : 0;
+ Parent::operator=(pos > _sep ? _map->_array[pos - 1] : INVALID);
+ return *this;
+ }
+
+ private:
+ const IterableBoolMap* _map;
+ };
+
+ protected:
+
+ virtual void add(const Key& key) {
+ Parent::add(key);
+ Parent::set(key, _array.size());
+ _array.push_back(key);
+ }
+
+ virtual void add(const std::vector<Key>& keys) {
+ Parent::add(keys);
+ for (int i = 0; i < int(keys.size()); ++i) {
+ Parent::set(keys[i], _array.size());
+ _array.push_back(keys[i]);
+ }
+ }
+
+ virtual void erase(const Key& key) {
+ int pos = position(key);
+ if (pos < _sep) {
+ --_sep;
+ Parent::set(_array[_sep], pos);
+ _array[pos] = _array[_sep];
+ Parent::set(_array.back(), _sep);
+ _array[_sep] = _array.back();
+ _array.pop_back();
+ } else {
+ Parent::set(_array.back(), pos);
+ _array[pos] = _array.back();
+ _array.pop_back();
+ }
+ Parent::erase(key);
+ }
+
+ virtual void erase(const std::vector<Key>& keys) {
+ for (int i = 0; i < int(keys.size()); ++i) {
+ int pos = position(keys[i]);
+ if (pos < _sep) {
+ --_sep;
+ Parent::set(_array[_sep], pos);
+ _array[pos] = _array[_sep];
+ Parent::set(_array.back(), _sep);
+ _array[_sep] = _array.back();
+ _array.pop_back();
+ } else {
+ Parent::set(_array.back(), pos);
+ _array[pos] = _array.back();
+ _array.pop_back();
+ }
+ }
+ Parent::erase(keys);
+ }
+
+ virtual void build() {
+ Parent::build();
+ typename Parent::Notifier* nf = Parent::notifier();
+ Key it;
+ for (nf->first(it); it != INVALID; nf->next(it)) {
+ Parent::set(it, _array.size());
+ _array.push_back(it);
+ }
+ _sep = 0;
+ }
+
+ virtual void clear() {
+ _array.clear();
+ _sep = 0;
+ Parent::clear();
+ }
+
+ };
+
+
+ namespace _maps_bits {
+ template <typename Item>
+ struct IterableIntMapNode {
+ IterableIntMapNode() : value(-1) {}
+ IterableIntMapNode(int _value) : value(_value) {}
+ Item prev, next;
+ int value;
+ };
+ }
+
+ /// \brief Dynamic iterable integer map.
+ ///
+ /// This class provides a special graph map type which can store an
+ /// integer value for graph items (\c Node, \c Arc or \c Edge).
+ /// For each non-negative value it is possible to iterate on the keys
+ /// mapped to the value.
+ ///
+ /// This map is intended to be used with small integer values, for which
+ /// it is efficient, and supports iteration only for non-negative values.
+ /// If you need large values and/or iteration for negative integers,
+ /// consider to use \ref IterableValueMap instead.
+ ///
+ /// This type is a reference map, so it can be modified with the
+ /// subscript operator.
+ ///
+ /// \note The size of the data structure depends on the largest
+ /// value in the map.
+ ///
+ /// \tparam GR The graph type.
+ /// \tparam K The key type of the map (\c GR::Node, \c GR::Arc or
+ /// \c GR::Edge).
+ ///
+ /// \see IterableBoolMap, IterableValueMap
+ /// \see CrossRefMap
+ template <typename GR, typename K>
+ class IterableIntMap
+ : protected ItemSetTraits<GR, K>::
+ template Map<_maps_bits::IterableIntMapNode<K> >::Type {
+ public:
+ typedef typename ItemSetTraits<GR, K>::
+ template Map<_maps_bits::IterableIntMapNode<K> >::Type Parent;
+
+ /// The key type
+ typedef K Key;
+ /// The value type
+ typedef int Value;
+ /// The graph type
+ typedef GR Graph;
+
+ /// \brief Constructor of the map.
+ ///
+ /// Constructor of the map. It sets all values to -1.
+ explicit IterableIntMap(const Graph& graph)
+ : Parent(graph) {}
+
+ /// \brief Constructor of the map with a given value.
+ ///
+ /// Constructor of the map with a given value.
+ explicit IterableIntMap(const Graph& graph, int value)
+ : Parent(graph, _maps_bits::IterableIntMapNode<K>(value)) {
+ if (value >= 0) {
+ for (typename Parent::ItemIt it(*this); it != INVALID; ++it) {
+ lace(it);
+ }
+ }
+ }
+
+ private:
+
+ void unlace(const Key& key) {
+ typename Parent::Value& node = Parent::operator[](key);
+ if (node.value < 0) return;
+ if (node.prev != INVALID) {
+ Parent::operator[](node.prev).next = node.next;
+ } else {
+ _first[node.value] = node.next;
+ }
+ if (node.next != INVALID) {
+ Parent::operator[](node.next).prev = node.prev;
+ }
+ while (!_first.empty() && _first.back() == INVALID) {
+ _first.pop_back();
+ }
+ }
+
+ void lace(const Key& key) {
+ typename Parent::Value& node = Parent::operator[](key);
+ if (node.value < 0) return;
+ if (node.value >= int(_first.size())) {
+ _first.resize(node.value + 1, INVALID);
+ }
+ node.prev = INVALID;
+ node.next = _first[node.value];
+ if (node.next != INVALID) {
+ Parent::operator[](node.next).prev = key;
+ }
+ _first[node.value] = key;
+ }
+
+ public:
+
+ /// Indicates that the map is reference map.
+ typedef True ReferenceMapTag;
+
+ /// \brief Reference to the value of the map.
+ ///
+ /// This class is similar to the \c int type. It can
+ /// be converted to \c int and it has the same operators.
+ class Reference {
+ friend class IterableIntMap;
+ private:
+ Reference(IterableIntMap& map, const Key& key)
+ : _key(key), _map(map) {}
+ public:
+
+ Reference& operator=(const Reference& value) {
+ _map.set(_key, static_cast<const int&>(value));
+ return *this;
+ }
+
+ operator const int&() const {
+ return static_cast<const IterableIntMap&>(_map)[_key];
+ }
+
+ Reference& operator=(int value) {
+ _map.set(_key, value);
+ return *this;
+ }
+ Reference& operator++() {
+ _map.set(_key, _map[_key] + 1);
+ return *this;
+ }
+ int operator++(int) {
+ int value = _map[_key];
+ _map.set(_key, value + 1);
+ return value;
+ }
+ Reference& operator--() {
+ _map.set(_key, _map[_key] - 1);
+ return *this;
+ }
+ int operator--(int) {
+ int value = _map[_key];
+ _map.set(_key, value - 1);
+ return value;
+ }
+ Reference& operator+=(int value) {
+ _map.set(_key, _map[_key] + value);
+ return *this;
+ }
+ Reference& operator-=(int value) {
+ _map.set(_key, _map[_key] - value);
+ return *this;
+ }
+ Reference& operator*=(int value) {
+ _map.set(_key, _map[_key] * value);
+ return *this;
+ }
+ Reference& operator/=(int value) {
+ _map.set(_key, _map[_key] / value);
+ return *this;
+ }
+ Reference& operator%=(int value) {
+ _map.set(_key, _map[_key] % value);
+ return *this;
+ }
+ Reference& operator&=(int value) {
+ _map.set(_key, _map[_key] & value);
+ return *this;
+ }
+ Reference& operator|=(int value) {
+ _map.set(_key, _map[_key] | value);
+ return *this;
+ }
+ Reference& operator^=(int value) {
+ _map.set(_key, _map[_key] ^ value);
+ return *this;
+ }
+ Reference& operator<<=(int value) {
+ _map.set(_key, _map[_key] << value);
+ return *this;
+ }
+ Reference& operator>>=(int value) {
+ _map.set(_key, _map[_key] >> value);
+ return *this;
+ }
+
+ private:
+ Key _key;
+ IterableIntMap& _map;
+ };
+
+ /// The const reference type.
+ typedef const Value& ConstReference;
+
+ /// \brief Gives back the maximal value plus one.
+ ///
+ /// Gives back the maximal value plus one.
+ int size() const {
+ return _first.size();
+ }
+
+ /// \brief Set operation of the map.
+ ///
+ /// Set operation of the map.
+ void set(const Key& key, const Value& value) {
+ unlace(key);
+ Parent::operator[](key).value = value;
+ lace(key);
+ }
+
+ /// \brief Const subscript operator of the map.
+ ///
+ /// Const subscript operator of the map.
+ const Value& operator[](const Key& key) const {
+ return Parent::operator[](key).value;
+ }
+
+ /// \brief Subscript operator of the map.
+ ///
+ /// Subscript operator of the map.
+ Reference operator[](const Key& key) {
+ return Reference(*this, key);
+ }
+
+ /// \brief Iterator for the keys with the same value.
+ ///
+ /// Iterator for the keys with the same value. It works
+ /// like a graph item iterator, it can be converted to
+ /// the item type of the map, incremented with \c ++ operator, and
+ /// if the iterator leaves the last valid item, it will be equal to
+ /// \c INVALID.
+ class ItemIt : public Key {
+ public:
+ typedef Key Parent;
+
+ /// \brief Invalid constructor \& conversion.
+ ///
+ /// This constructor initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ ItemIt(Invalid) : Parent(INVALID), _map(0) {}
+
+ /// \brief Creates an iterator with a value.
+ ///
+ /// Creates an iterator with a value. It iterates on the
+ /// keys mapped to the given value.
+ /// \param map The IterableIntMap.
+ /// \param value The value.
+ ItemIt(const IterableIntMap& map, int value) : _map(&map) {
+ if (value < 0 || value >= int(_map->_first.size())) {
+ Parent::operator=(INVALID);
+ } else {
+ Parent::operator=(_map->_first[value]);
+ }
+ }
+
+ /// \brief Increment operator.
+ ///
+ /// Increment operator.
+ ItemIt& operator++() {
+ Parent::operator=(_map->IterableIntMap::Parent::
+ operator[](static_cast<Parent&>(*this)).next);
+ return *this;
+ }
+
+ private:
+ const IterableIntMap* _map;
+ };
+
+ protected:
+
+ virtual void erase(const Key& key) {
+ unlace(key);
+ Parent::erase(key);
+ }
+
+ virtual void erase(const std::vector<Key>& keys) {
+ for (int i = 0; i < int(keys.size()); ++i) {
+ unlace(keys[i]);
+ }
+ Parent::erase(keys);
+ }
+
+ virtual void clear() {
+ _first.clear();
+ Parent::clear();
+ }
+
+ private:
+ std::vector<Key> _first;
+ };
+
+ namespace _maps_bits {
+ template <typename Item, typename Value>
+ struct IterableValueMapNode {
+ IterableValueMapNode(Value _value = Value()) : value(_value) {}
+ Item prev, next;
+ Value value;
+ };
+ }
+
+ /// \brief Dynamic iterable map for comparable values.
+ ///
+ /// This class provides a special graph map type which can store a
+ /// comparable value for graph items (\c Node, \c Arc or \c Edge).
+ /// For each value it is possible to iterate on the keys mapped to
+ /// the value (\c ItemIt), and the values of the map can be accessed
+ /// with an STL compatible forward iterator (\c ValueIt).
+ /// The map stores a linked list for each value, which contains
+ /// the items mapped to the value, and the used values are stored
+ /// in balanced binary tree (\c std::map).
+ ///
+ /// \ref IterableBoolMap and \ref IterableIntMap are similar classes
+ /// specialized for \c bool and \c int values, respectively.
+ ///
+ /// This type is not reference map, so it cannot be modified with
+ /// the subscript operator.
+ ///
+ /// \tparam GR The graph type.
+ /// \tparam K The key type of the map (\c GR::Node, \c GR::Arc or
+ /// \c GR::Edge).
+ /// \tparam V The value type of the map. It can be any comparable
+ /// value type.
+ ///
+ /// \see IterableBoolMap, IterableIntMap
+ /// \see CrossRefMap
+ template <typename GR, typename K, typename V>
+ class IterableValueMap
+ : protected ItemSetTraits<GR, K>::
+ template Map<_maps_bits::IterableValueMapNode<K, V> >::Type {
+ public:
+ typedef typename ItemSetTraits<GR, K>::
+ template Map<_maps_bits::IterableValueMapNode<K, V> >::Type Parent;
+
+ /// The key type
+ typedef K Key;
+ /// The value type
+ typedef V Value;
+ /// The graph type
+ typedef GR Graph;
+
+ public:
+
+ /// \brief Constructor of the map with a given value.
+ ///
+ /// Constructor of the map with a given value.
+ explicit IterableValueMap(const Graph& graph,
+ const Value& value = Value())
+ : Parent(graph, _maps_bits::IterableValueMapNode<K, V>(value)) {
+ for (typename Parent::ItemIt it(*this); it != INVALID; ++it) {
+ lace(it);
+ }
+ }
+
+ protected:
+
+ void unlace(const Key& key) {
+ typename Parent::Value& node = Parent::operator[](key);
+ if (node.prev != INVALID) {
+ Parent::operator[](node.prev).next = node.next;
+ } else {
+ if (node.next != INVALID) {
+ _first[node.value] = node.next;
+ } else {
+ _first.erase(node.value);
+ }
+ }
+ if (node.next != INVALID) {
+ Parent::operator[](node.next).prev = node.prev;
+ }
+ }
+
+ void lace(const Key& key) {
+ typename Parent::Value& node = Parent::operator[](key);
+ typename std::map<Value, Key>::iterator it = _first.find(node.value);
+ if (it == _first.end()) {
+ node.prev = node.next = INVALID;
+ _first.insert(std::make_pair(node.value, key));
+ } else {
+ node.prev = INVALID;
+ node.next = it->second;
+ if (node.next != INVALID) {
+ Parent::operator[](node.next).prev = key;
+ }
+ it->second = key;
+ }
+ }
+
+ public:
+
+ /// \brief Forward iterator for values.
+ ///
+ /// This iterator is an STL compatible forward
+ /// iterator on the values of the map. The values can
+ /// be accessed in the <tt>[beginValue, endValue)</tt> range.
+ class ValueIt
+ : public std::iterator<std::forward_iterator_tag, Value> {
+ friend class IterableValueMap;
+ private:
+ ValueIt(typename std::map<Value, Key>::const_iterator _it)
+ : it(_it) {}
+ public:
+
+ /// Constructor
+ ValueIt() {}
+
+ /// \e
+ ValueIt& operator++() { ++it; return *this; }
+ /// \e
+ ValueIt operator++(int) {
+ ValueIt tmp(*this);
+ operator++();
+ return tmp;
+ }
+
+ /// \e
+ const Value& operator*() const { return it->first; }
+ /// \e
+ const Value* operator->() const { return &(it->first); }
+
+ /// \e
+ bool operator==(ValueIt jt) const { return it == jt.it; }
+ /// \e
+ bool operator!=(ValueIt jt) const { return it != jt.it; }
+
+ private:
+ typename std::map<Value, Key>::const_iterator it;
+ };
+
+ /// \brief Returns an iterator to the first value.
+ ///
+ /// Returns an STL compatible iterator to the
+ /// first value of the map. The values of the
+ /// map can be accessed in the <tt>[beginValue, endValue)</tt>
+ /// range.
+ ValueIt beginValue() const {
+ return ValueIt(_first.begin());
+ }
+
+ /// \brief Returns an iterator after the last value.
+ ///
+ /// Returns an STL compatible iterator after the
+ /// last value of the map. The values of the
+ /// map can be accessed in the <tt>[beginValue, endValue)</tt>
+ /// range.
+ ValueIt endValue() const {
+ return ValueIt(_first.end());
+ }
+
+ /// \brief Set operation of the map.
+ ///
+ /// Set operation of the map.
+ void set(const Key& key, const Value& value) {
+ unlace(key);
+ Parent::operator[](key).value = value;
+ lace(key);
+ }
+
+ /// \brief Const subscript operator of the map.
+ ///
+ /// Const subscript operator of the map.
+ const Value& operator[](const Key& key) const {
+ return Parent::operator[](key).value;
+ }
+
+ /// \brief Iterator for the keys with the same value.
+ ///
+ /// Iterator for the keys with the same value. It works
+ /// like a graph item iterator, it can be converted to
+ /// the item type of the map, incremented with \c ++ operator, and
+ /// if the iterator leaves the last valid item, it will be equal to
+ /// \c INVALID.
+ class ItemIt : public Key {
+ public:
+ typedef Key Parent;
+
+ /// \brief Invalid constructor \& conversion.
+ ///
+ /// This constructor initializes the iterator to be invalid.
+ /// \sa Invalid for more details.
+ ItemIt(Invalid) : Parent(INVALID), _map(0) {}
+
+ /// \brief Creates an iterator with a value.
+ ///
+ /// Creates an iterator with a value. It iterates on the
+ /// keys which have the given value.
+ /// \param map The IterableValueMap
+ /// \param value The value
+ ItemIt(const IterableValueMap& map, const Value& value) : _map(&map) {
+ typename std::map<Value, Key>::const_iterator it =
+ map._first.find(value);
+ if (it == map._first.end()) {
+ Parent::operator=(INVALID);
+ } else {
+ Parent::operator=(it->second);
+ }
+ }
+
+ /// \brief Increment operator.
+ ///
+ /// Increment Operator.
+ ItemIt& operator++() {
+ Parent::operator=(_map->IterableValueMap::Parent::
+ operator[](static_cast<Parent&>(*this)).next);
+ return *this;
+ }
+
+
+ private:
+ const IterableValueMap* _map;
+ };
+
+ protected:
+
+ virtual void add(const Key& key) {
+ Parent::add(key);
+ lace(key);
+ }
+
+ virtual void add(const std::vector<Key>& keys) {
+ Parent::add(keys);
+ for (int i = 0; i < int(keys.size()); ++i) {
+ lace(keys[i]);
+ }
+ }
+
+ virtual void erase(const Key& key) {
+ unlace(key);
+ Parent::erase(key);
+ }
+
+ virtual void erase(const std::vector<Key>& keys) {
+ for (int i = 0; i < int(keys.size()); ++i) {
+ unlace(keys[i]);
+ }
+ Parent::erase(keys);
+ }
+
+ virtual void build() {
+ Parent::build();
+ for (typename Parent::ItemIt it(*this); it != INVALID; ++it) {
+ lace(it);
+ }
+ }
+
+ virtual void clear() {
+ _first.clear();
+ Parent::clear();
+ }
+
+ private:
+ std::map<Value, Key> _first;
+ };
+
+ /// \brief Map of the source nodes of arcs in a digraph.
+ ///
+ /// SourceMap provides access for the source node of each arc in a digraph,
+ /// which is returned by the \c source() function of the digraph.
+ /// \tparam GR The digraph type.
+ /// \see TargetMap
+ template <typename GR>
+ class SourceMap {
+ public:
+
+ /// The key type (the \c Arc type of the digraph).
+ typedef typename GR::Arc Key;
+ /// The value type (the \c Node type of the digraph).
+ typedef typename GR::Node Value;
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ /// \param digraph The digraph that the map belongs to.
+ explicit SourceMap(const GR& digraph) : _graph(digraph) {}
+
+ /// \brief Returns the source node of the given arc.
+ ///
+ /// Returns the source node of the given arc.
+ Value operator[](const Key& arc) const {
+ return _graph.source(arc);
+ }
+
+ private:
+ const GR& _graph;
+ };
+
+ /// \brief Returns a \c SourceMap class.
+ ///
+ /// This function just returns an \c SourceMap class.
+ /// \relates SourceMap
+ template <typename GR>
+ inline SourceMap<GR> sourceMap(const GR& graph) {
+ return SourceMap<GR>(graph);
+ }
+
+ /// \brief Map of the target nodes of arcs in a digraph.
+ ///
+ /// TargetMap provides access for the target node of each arc in a digraph,
+ /// which is returned by the \c target() function of the digraph.
+ /// \tparam GR The digraph type.
+ /// \see SourceMap
+ template <typename GR>
+ class TargetMap {
+ public:
+
+ /// The key type (the \c Arc type of the digraph).
+ typedef typename GR::Arc Key;
+ /// The value type (the \c Node type of the digraph).
+ typedef typename GR::Node Value;
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ /// \param digraph The digraph that the map belongs to.
+ explicit TargetMap(const GR& digraph) : _graph(digraph) {}
+
+ /// \brief Returns the target node of the given arc.
+ ///
+ /// Returns the target node of the given arc.
+ Value operator[](const Key& e) const {
+ return _graph.target(e);
+ }
+
+ private:
+ const GR& _graph;
+ };
+
+ /// \brief Returns a \c TargetMap class.
+ ///
+ /// This function just returns a \c TargetMap class.
+ /// \relates TargetMap
+ template <typename GR>
+ inline TargetMap<GR> targetMap(const GR& graph) {
+ return TargetMap<GR>(graph);
+ }
+
+ /// \brief Map of the "forward" directed arc view of edges in a graph.
+ ///
+ /// ForwardMap provides access for the "forward" directed arc view of
+ /// each edge in a graph, which is returned by the \c direct() function
+ /// of the graph with \c true parameter.
+ /// \tparam GR The graph type.
+ /// \see BackwardMap
+ template <typename GR>
+ class ForwardMap {
+ public:
+
+ /// The key type (the \c Edge type of the digraph).
+ typedef typename GR::Edge Key;
+ /// The value type (the \c Arc type of the digraph).
+ typedef typename GR::Arc Value;
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ /// \param graph The graph that the map belongs to.
+ explicit ForwardMap(const GR& graph) : _graph(graph) {}
+
+ /// \brief Returns the "forward" directed arc view of the given edge.
+ ///
+ /// Returns the "forward" directed arc view of the given edge.
+ Value operator[](const Key& key) const {
+ return _graph.direct(key, true);
+ }
+
+ private:
+ const GR& _graph;
+ };
+
+ /// \brief Returns a \c ForwardMap class.
+ ///
+ /// This function just returns an \c ForwardMap class.
+ /// \relates ForwardMap
+ template <typename GR>
+ inline ForwardMap<GR> forwardMap(const GR& graph) {
+ return ForwardMap<GR>(graph);
+ }
+
+ /// \brief Map of the "backward" directed arc view of edges in a graph.
+ ///
+ /// BackwardMap provides access for the "backward" directed arc view of
+ /// each edge in a graph, which is returned by the \c direct() function
+ /// of the graph with \c false parameter.
+ /// \tparam GR The graph type.
+ /// \see ForwardMap
+ template <typename GR>
+ class BackwardMap {
+ public:
+
+ /// The key type (the \c Edge type of the digraph).
+ typedef typename GR::Edge Key;
+ /// The value type (the \c Arc type of the digraph).
+ typedef typename GR::Arc Value;
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ /// \param graph The graph that the map belongs to.
+ explicit BackwardMap(const GR& graph) : _graph(graph) {}
+
+ /// \brief Returns the "backward" directed arc view of the given edge.
+ ///
+ /// Returns the "backward" directed arc view of the given edge.
+ Value operator[](const Key& key) const {
+ return _graph.direct(key, false);
+ }
+
+ private:
+ const GR& _graph;
+ };
+
+ /// \brief Returns a \c BackwardMap class
+
+ /// This function just returns a \c BackwardMap class.
+ /// \relates BackwardMap
+ template <typename GR>
+ inline BackwardMap<GR> backwardMap(const GR& graph) {
+ return BackwardMap<GR>(graph);
+ }
+
+ /// \brief Map of the in-degrees of nodes in a digraph.
+ ///
+ /// This map returns the in-degree of a node. Once it is constructed,
+ /// the degrees are stored in a standard \c NodeMap, so each query is done
+ /// in constant time. On the other hand, the values are updated automatically
+ /// whenever the digraph changes.
+ ///
+ /// \warning Besides \c addNode() and \c addArc(), a digraph structure
+ /// may provide alternative ways to modify the digraph.
+ /// The correct behavior of InDegMap is not guarantied if these additional
+ /// features are used. For example, the functions
+ /// \ref ListDigraph::changeSource() "changeSource()",
+ /// \ref ListDigraph::changeTarget() "changeTarget()" and
+ /// \ref ListDigraph::reverseArc() "reverseArc()"
+ /// of \ref ListDigraph will \e not update the degree values correctly.
+ ///
+ /// \sa OutDegMap
+ template <typename GR>
+ class InDegMap
+ : protected ItemSetTraits<GR, typename GR::Arc>
+ ::ItemNotifier::ObserverBase {
+
+ public:
+
+ /// The graph type of InDegMap
+ typedef GR Graph;
+ typedef GR Digraph;
+ /// The key type
+ typedef typename Digraph::Node Key;
+ /// The value type
+ typedef int Value;
+
+ typedef typename ItemSetTraits<Digraph, typename Digraph::Arc>
+ ::ItemNotifier::ObserverBase Parent;
+
+ private:
+
+ class AutoNodeMap
+ : public ItemSetTraits<Digraph, Key>::template Map<int>::Type {
+ public:
+
+ typedef typename ItemSetTraits<Digraph, Key>::
+ template Map<int>::Type Parent;
+
+ AutoNodeMap(const Digraph& digraph) : Parent(digraph, 0) {}
+
+ virtual void add(const Key& key) {
+ Parent::add(key);
+ Parent::set(key, 0);
+ }
+
+ virtual void add(const std::vector<Key>& keys) {
+ Parent::add(keys);
+ for (int i = 0; i < int(keys.size()); ++i) {
+ Parent::set(keys[i], 0);
+ }
+ }
+
+ virtual void build() {
+ Parent::build();
+ Key it;
+ typename Parent::Notifier* nf = Parent::notifier();
+ for (nf->first(it); it != INVALID; nf->next(it)) {
+ Parent::set(it, 0);
+ }
+ }
+ };
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor for creating an in-degree map.
+ explicit InDegMap(const Digraph& graph)
+ : _digraph(graph), _deg(graph) {
+ Parent::attach(_digraph.notifier(typename Digraph::Arc()));
+
+ for(typename Digraph::NodeIt it(_digraph); it != INVALID; ++it) {
+ _deg[it] = countInArcs(_digraph, it);
+ }
+ }
+
+ /// \brief Gives back the in-degree of a Node.
+ ///
+ /// Gives back the in-degree of a Node.
+ int operator[](const Key& key) const {
+ return _deg[key];
+ }
+
+ protected:
+
+ typedef typename Digraph::Arc Arc;
+
+ virtual void add(const Arc& arc) {
+ ++_deg[_digraph.target(arc)];
+ }
+
+ virtual void add(const std::vector<Arc>& arcs) {
+ for (int i = 0; i < int(arcs.size()); ++i) {
+ ++_deg[_digraph.target(arcs[i])];
+ }
+ }
+
+ virtual void erase(const Arc& arc) {
+ --_deg[_digraph.target(arc)];
+ }
+
+ virtual void erase(const std::vector<Arc>& arcs) {
+ for (int i = 0; i < int(arcs.size()); ++i) {
+ --_deg[_digraph.target(arcs[i])];
+ }
+ }
+
+ virtual void build() {
+ for(typename Digraph::NodeIt it(_digraph); it != INVALID; ++it) {
+ _deg[it] = countInArcs(_digraph, it);
+ }
+ }
+
+ virtual void clear() {
+ for(typename Digraph::NodeIt it(_digraph); it != INVALID; ++it) {
+ _deg[it] = 0;
+ }
+ }
+ private:
+
+ const Digraph& _digraph;
+ AutoNodeMap _deg;
+ };
+
+ /// \brief Map of the out-degrees of nodes in a digraph.
+ ///
+ /// This map returns the out-degree of a node. Once it is constructed,
+ /// the degrees are stored in a standard \c NodeMap, so each query is done
+ /// in constant time. On the other hand, the values are updated automatically
+ /// whenever the digraph changes.
+ ///
+ /// \warning Besides \c addNode() and \c addArc(), a digraph structure
+ /// may provide alternative ways to modify the digraph.
+ /// The correct behavior of OutDegMap is not guarantied if these additional
+ /// features are used. For example, the functions
+ /// \ref ListDigraph::changeSource() "changeSource()",
+ /// \ref ListDigraph::changeTarget() "changeTarget()" and
+ /// \ref ListDigraph::reverseArc() "reverseArc()"
+ /// of \ref ListDigraph will \e not update the degree values correctly.
+ ///
+ /// \sa InDegMap
+ template <typename GR>
+ class OutDegMap
+ : protected ItemSetTraits<GR, typename GR::Arc>
+ ::ItemNotifier::ObserverBase {
+
+ public:
+
+ /// The graph type of OutDegMap
+ typedef GR Graph;
+ typedef GR Digraph;
+ /// The key type
+ typedef typename Digraph::Node Key;
+ /// The value type
+ typedef int Value;
+
+ typedef typename ItemSetTraits<Digraph, typename Digraph::Arc>
+ ::ItemNotifier::ObserverBase Parent;
+
+ private:
+
+ class AutoNodeMap
+ : public ItemSetTraits<Digraph, Key>::template Map<int>::Type {
+ public:
+
+ typedef typename ItemSetTraits<Digraph, Key>::
+ template Map<int>::Type Parent;
+
+ AutoNodeMap(const Digraph& digraph) : Parent(digraph, 0) {}
+
+ virtual void add(const Key& key) {
+ Parent::add(key);
+ Parent::set(key, 0);
+ }
+ virtual void add(const std::vector<Key>& keys) {
+ Parent::add(keys);
+ for (int i = 0; i < int(keys.size()); ++i) {
+ Parent::set(keys[i], 0);
+ }
+ }
+ virtual void build() {
+ Parent::build();
+ Key it;
+ typename Parent::Notifier* nf = Parent::notifier();
+ for (nf->first(it); it != INVALID; nf->next(it)) {
+ Parent::set(it, 0);
+ }
+ }
+ };
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor for creating an out-degree map.
+ explicit OutDegMap(const Digraph& graph)
+ : _digraph(graph), _deg(graph) {
+ Parent::attach(_digraph.notifier(typename Digraph::Arc()));
+
+ for(typename Digraph::NodeIt it(_digraph); it != INVALID; ++it) {
+ _deg[it] = countOutArcs(_digraph, it);
+ }
+ }
+
+ /// \brief Gives back the out-degree of a Node.
+ ///
+ /// Gives back the out-degree of a Node.
+ int operator[](const Key& key) const {
+ return _deg[key];
+ }
+
+ protected:
+
+ typedef typename Digraph::Arc Arc;
+
+ virtual void add(const Arc& arc) {
+ ++_deg[_digraph.source(arc)];
+ }
+
+ virtual void add(const std::vector<Arc>& arcs) {
+ for (int i = 0; i < int(arcs.size()); ++i) {
+ ++_deg[_digraph.source(arcs[i])];
+ }
+ }
+
+ virtual void erase(const Arc& arc) {
+ --_deg[_digraph.source(arc)];
+ }
+
+ virtual void erase(const std::vector<Arc>& arcs) {
+ for (int i = 0; i < int(arcs.size()); ++i) {
+ --_deg[_digraph.source(arcs[i])];
+ }
+ }
+
+ virtual void build() {
+ for(typename Digraph::NodeIt it(_digraph); it != INVALID; ++it) {
+ _deg[it] = countOutArcs(_digraph, it);
+ }
+ }
+
+ virtual void clear() {
+ for(typename Digraph::NodeIt it(_digraph); it != INVALID; ++it) {
+ _deg[it] = 0;
+ }
+ }
+ private:
+
+ const Digraph& _digraph;
+ AutoNodeMap _deg;
+ };
+
+ /// \brief Potential difference map
+ ///
+ /// PotentialDifferenceMap returns the difference between the potentials of
+ /// the source and target nodes of each arc in a digraph, i.e. it returns
+ /// \code
+ /// potential[gr.target(arc)] - potential[gr.source(arc)].
+ /// \endcode
+ /// \tparam GR The digraph type.
+ /// \tparam POT A node map storing the potentials.
+ template <typename GR, typename POT>
+ class PotentialDifferenceMap {
+ public:
+ /// Key type
+ typedef typename GR::Arc Key;
+ /// Value type
+ typedef typename POT::Value Value;
+
+ /// \brief Constructor
+ ///
+ /// Contructor of the map.
+ explicit PotentialDifferenceMap(const GR& gr,
+ const POT& potential)
+ : _digraph(gr), _potential(potential) {}
+
+ /// \brief Returns the potential difference for the given arc.
+ ///
+ /// Returns the potential difference for the given arc, i.e.
+ /// \code
+ /// potential[gr.target(arc)] - potential[gr.source(arc)].
+ /// \endcode
+ Value operator[](const Key& arc) const {
+ return _potential[_digraph.target(arc)] -
+ _potential[_digraph.source(arc)];
+ }
+
+ private:
+ const GR& _digraph;
+ const POT& _potential;
+ };
+
+ /// \brief Returns a PotentialDifferenceMap.
+ ///
+ /// This function just returns a PotentialDifferenceMap.
+ /// \relates PotentialDifferenceMap
+ template <typename GR, typename POT>
+ PotentialDifferenceMap<GR, POT>
+ potentialDifferenceMap(const GR& gr, const POT& potential) {
+ return PotentialDifferenceMap<GR, POT>(gr, potential);
+ }
+
+
+ /// \brief Copy the values of a graph map to another map.
+ ///
+ /// This function copies the values of a graph map to another graph map.
+ /// \c To::Key must be equal or convertible to \c From::Key and
+ /// \c From::Value must be equal or convertible to \c To::Value.
+ ///
+ /// For example, an edge map of \c int value type can be copied to
+ /// an arc map of \c double value type in an undirected graph, but
+ /// an arc map cannot be copied to an edge map.
+ /// Note that even a \ref ConstMap can be copied to a standard graph map,
+ /// but \ref mapFill() can also be used for this purpose.
+ ///
+ /// \param gr The graph for which the maps are defined.
+ /// \param from The map from which the values have to be copied.
+ /// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
+ /// \param to The map to which the values have to be copied.
+ /// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ template <typename GR, typename From, typename To>
+ void mapCopy(const GR& gr, const From& from, To& to) {
+ typedef typename To::Key Item;
+ typedef typename ItemSetTraits<GR, Item>::ItemIt ItemIt;
+
+ for (ItemIt it(gr); it != INVALID; ++it) {
+ to.set(it, from[it]);
+ }
+ }
+
+ /// \brief Compare two graph maps.
+ ///
+ /// This function compares the values of two graph maps. It returns
+ /// \c true if the maps assign the same value for all items in the graph.
+ /// The \c Key type of the maps (\c Node, \c Arc or \c Edge) must be equal
+ /// and their \c Value types must be comparable using \c %operator==().
+ ///
+ /// \param gr The graph for which the maps are defined.
+ /// \param map1 The first map.
+ /// \param map2 The second map.
+ template <typename GR, typename Map1, typename Map2>
+ bool mapCompare(const GR& gr, const Map1& map1, const Map2& map2) {
+ typedef typename Map2::Key Item;
+ typedef typename ItemSetTraits<GR, Item>::ItemIt ItemIt;
+
+ for (ItemIt it(gr); it != INVALID; ++it) {
+ if (!(map1[it] == map2[it])) return false;
+ }
+ return true;
+ }
+
+ /// \brief Return an item having minimum value of a graph map.
+ ///
+ /// This function returns an item (\c Node, \c Arc or \c Edge) having
+ /// minimum value of the given graph map.
+ /// If the item set is empty, it returns \c INVALID.
+ ///
+ /// \param gr The graph for which the map is defined.
+ /// \param map The graph map.
+ template <typename GR, typename Map>
+ typename Map::Key mapMin(const GR& gr, const Map& map) {
+ return mapMin(gr, map, std::less<typename Map::Value>());
+ }
+
+ /// \brief Return an item having minimum value of a graph map.
+ ///
+ /// This function returns an item (\c Node, \c Arc or \c Edge) having
+ /// minimum value of the given graph map.
+ /// If the item set is empty, it returns \c INVALID.
+ ///
+ /// \param gr The graph for which the map is defined.
+ /// \param map The graph map.
+ /// \param comp Comparison function object.
+ template <typename GR, typename Map, typename Comp>
+ typename Map::Key mapMin(const GR& gr, const Map& map, const Comp& comp) {
+ typedef typename Map::Key Item;
+ typedef typename Map::Value Value;
+ typedef typename ItemSetTraits<GR, Item>::ItemIt ItemIt;
+
+ ItemIt min_item(gr);
+ if (min_item == INVALID) return INVALID;
+ Value min = map[min_item];
+ for (ItemIt it(gr); it != INVALID; ++it) {
+ if (comp(map[it], min)) {
+ min = map[it];
+ min_item = it;
+ }
+ }
+ return min_item;
+ }
+
+ /// \brief Return an item having maximum value of a graph map.
+ ///
+ /// This function returns an item (\c Node, \c Arc or \c Edge) having
+ /// maximum value of the given graph map.
+ /// If the item set is empty, it returns \c INVALID.
+ ///
+ /// \param gr The graph for which the map is defined.
+ /// \param map The graph map.
+ template <typename GR, typename Map>
+ typename Map::Key mapMax(const GR& gr, const Map& map) {
+ return mapMax(gr, map, std::less<typename Map::Value>());
+ }
+
+ /// \brief Return an item having maximum value of a graph map.
+ ///
+ /// This function returns an item (\c Node, \c Arc or \c Edge) having
+ /// maximum value of the given graph map.
+ /// If the item set is empty, it returns \c INVALID.
+ ///
+ /// \param gr The graph for which the map is defined.
+ /// \param map The graph map.
+ /// \param comp Comparison function object.
+ template <typename GR, typename Map, typename Comp>
+ typename Map::Key mapMax(const GR& gr, const Map& map, const Comp& comp) {
+ typedef typename Map::Key Item;
+ typedef typename Map::Value Value;
+ typedef typename ItemSetTraits<GR, Item>::ItemIt ItemIt;
+
+ ItemIt max_item(gr);
+ if (max_item == INVALID) return INVALID;
+ Value max = map[max_item];
+ for (ItemIt it(gr); it != INVALID; ++it) {
+ if (comp(max, map[it])) {
+ max = map[it];
+ max_item = it;
+ }
+ }
+ return max_item;
+ }
+
+ /// \brief Return the minimum value of a graph map.
+ ///
+ /// This function returns the minimum value of the given graph map.
+ /// The corresponding item set of the graph must not be empty.
+ ///
+ /// \param gr The graph for which the map is defined.
+ /// \param map The graph map.
+ template <typename GR, typename Map>
+ typename Map::Value mapMinValue(const GR& gr, const Map& map) {
+ return map[mapMin(gr, map, std::less<typename Map::Value>())];
+ }
+
+ /// \brief Return the minimum value of a graph map.
+ ///
+ /// This function returns the minimum value of the given graph map.
+ /// The corresponding item set of the graph must not be empty.
+ ///
+ /// \param gr The graph for which the map is defined.
+ /// \param map The graph map.
+ /// \param comp Comparison function object.
+ template <typename GR, typename Map, typename Comp>
+ typename Map::Value
+ mapMinValue(const GR& gr, const Map& map, const Comp& comp) {
+ return map[mapMin(gr, map, comp)];
+ }
+
+ /// \brief Return the maximum value of a graph map.
+ ///
+ /// This function returns the maximum value of the given graph map.
+ /// The corresponding item set of the graph must not be empty.
+ ///
+ /// \param gr The graph for which the map is defined.
+ /// \param map The graph map.
+ template <typename GR, typename Map>
+ typename Map::Value mapMaxValue(const GR& gr, const Map& map) {
+ return map[mapMax(gr, map, std::less<typename Map::Value>())];
+ }
+
+ /// \brief Return the maximum value of a graph map.
+ ///
+ /// This function returns the maximum value of the given graph map.
+ /// The corresponding item set of the graph must not be empty.
+ ///
+ /// \param gr The graph for which the map is defined.
+ /// \param map The graph map.
+ /// \param comp Comparison function object.
+ template <typename GR, typename Map, typename Comp>
+ typename Map::Value
+ mapMaxValue(const GR& gr, const Map& map, const Comp& comp) {
+ return map[mapMax(gr, map, comp)];
+ }
+
+ /// \brief Return an item having a specified value in a graph map.
+ ///
+ /// This function returns an item (\c Node, \c Arc or \c Edge) having
+ /// the specified assigned value in the given graph map.
+ /// If no such item exists, it returns \c INVALID.
+ ///
+ /// \param gr The graph for which the map is defined.
+ /// \param map The graph map.
+ /// \param val The value that have to be found.
+ template <typename GR, typename Map>
+ typename Map::Key
+ mapFind(const GR& gr, const Map& map, const typename Map::Value& val) {
+ typedef typename Map::Key Item;
+ typedef typename ItemSetTraits<GR, Item>::ItemIt ItemIt;
+
+ for (ItemIt it(gr); it != INVALID; ++it) {
+ if (map[it] == val) return it;
+ }
+ return INVALID;
+ }
+
+ /// \brief Return an item having value for which a certain predicate is
+ /// true in a graph map.
+ ///
+ /// This function returns an item (\c Node, \c Arc or \c Edge) having
+ /// such assigned value for which the specified predicate is true
+ /// in the given graph map.
+ /// If no such item exists, it returns \c INVALID.
+ ///
+ /// \param gr The graph for which the map is defined.
+ /// \param map The graph map.
+ /// \param pred The predicate function object.
+ template <typename GR, typename Map, typename Pred>
+ typename Map::Key
+ mapFindIf(const GR& gr, const Map& map, const Pred& pred) {
+ typedef typename Map::Key Item;
+ typedef typename ItemSetTraits<GR, Item>::ItemIt ItemIt;
+
+ for (ItemIt it(gr); it != INVALID; ++it) {
+ if (pred(map[it])) return it;
+ }
+ return INVALID;
+ }
+
+ /// \brief Return the number of items having a specified value in a
+ /// graph map.
+ ///
+ /// This function returns the number of items (\c Node, \c Arc or \c Edge)
+ /// having the specified assigned value in the given graph map.
+ ///
+ /// \param gr The graph for which the map is defined.
+ /// \param map The graph map.
+ /// \param val The value that have to be counted.
+ template <typename GR, typename Map>
+ int mapCount(const GR& gr, const Map& map, const typename Map::Value& val) {
+ typedef typename Map::Key Item;
+ typedef typename ItemSetTraits<GR, Item>::ItemIt ItemIt;
+
+ int cnt = 0;
+ for (ItemIt it(gr); it != INVALID; ++it) {
+ if (map[it] == val) ++cnt;
+ }
+ return cnt;
+ }
+
+ /// \brief Return the number of items having values for which a certain
+ /// predicate is true in a graph map.
+ ///
+ /// This function returns the number of items (\c Node, \c Arc or \c Edge)
+ /// having such assigned values for which the specified predicate is true
+ /// in the given graph map.
+ ///
+ /// \param gr The graph for which the map is defined.
+ /// \param map The graph map.
+ /// \param pred The predicate function object.
+ template <typename GR, typename Map, typename Pred>
+ int mapCountIf(const GR& gr, const Map& map, const Pred& pred) {
+ typedef typename Map::Key Item;
+ typedef typename ItemSetTraits<GR, Item>::ItemIt ItemIt;
+
+ int cnt = 0;
+ for (ItemIt it(gr); it != INVALID; ++it) {
+ if (pred(map[it])) ++cnt;
+ }
+ return cnt;
+ }
+
+ /// \brief Fill a graph map with a certain value.
+ ///
+ /// This function sets the specified value for all items (\c Node,
+ /// \c Arc or \c Edge) in the given graph map.
+ ///
+ /// \param gr The graph for which the map is defined.
+ /// \param map The graph map. It must conform to the
+ /// \ref concepts::WriteMap "WriteMap" concept.
+ /// \param val The value.
+ template <typename GR, typename Map>
+ void mapFill(const GR& gr, Map& map, const typename Map::Value& val) {
+ typedef typename Map::Key Item;
+ typedef typename ItemSetTraits<GR, Item>::ItemIt ItemIt;
+
+ for (ItemIt it(gr); it != INVALID; ++it) {
+ map.set(it, val);
+ }
+ }
+
+ /// @}
+}
+
+#endif // LEMON_MAPS_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/matching.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/matching.h
new file mode 100644
index 00000000000..5ee23412835
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/matching.h
@@ -0,0 +1,3505 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_MATCHING_H
+#define LEMON_MATCHING_H
+
+#include <vector>
+#include <queue>
+#include <set>
+#include <limits>
+
+#include <lemon/core.h>
+#include <lemon/unionfind.h>
+#include <lemon/bin_heap.h>
+#include <lemon/maps.h>
+#include <lemon/fractional_matching.h>
+
+///\ingroup matching
+///\file
+///\brief Maximum matching algorithms in general graphs.
+
+namespace lemon {
+
+ /// \ingroup matching
+ ///
+ /// \brief Maximum cardinality matching in general graphs
+ ///
+ /// This class implements Edmonds' alternating forest matching algorithm
+ /// for finding a maximum cardinality matching in a general undirected graph.
+ /// It can be started from an arbitrary initial matching
+ /// (the default is the empty one).
+ ///
+ /// The dual solution of the problem is a map of the nodes to
+ /// \ref MaxMatching::Status "Status", having values \c EVEN (or \c D),
+ /// \c ODD (or \c A) and \c MATCHED (or \c C) defining the Gallai-Edmonds
+ /// decomposition of the graph. The nodes in \c EVEN/D induce a subgraph
+ /// with factor-critical components, the nodes in \c ODD/A form the
+ /// canonical barrier, and the nodes in \c MATCHED/C induce a graph having
+ /// a perfect matching. The number of the factor-critical components
+ /// minus the number of barrier nodes is a lower bound on the
+ /// unmatched nodes, and the matching is optimal if and only if this bound is
+ /// tight. This decomposition can be obtained using \ref status() or
+ /// \ref statusMap() after running the algorithm.
+ ///
+ /// \tparam GR The undirected graph type the algorithm runs on.
+ template <typename GR>
+ class MaxMatching {
+ public:
+
+ /// The graph type of the algorithm
+ typedef GR Graph;
+ /// The type of the matching map
+ typedef typename Graph::template NodeMap<typename Graph::Arc>
+ MatchingMap;
+
+ ///\brief Status constants for Gallai-Edmonds decomposition.
+ ///
+ ///These constants are used for indicating the Gallai-Edmonds
+ ///decomposition of a graph. The nodes with status \c EVEN (or \c D)
+ ///induce a subgraph with factor-critical components, the nodes with
+ ///status \c ODD (or \c A) form the canonical barrier, and the nodes
+ ///with status \c MATCHED (or \c C) induce a subgraph having a
+ ///perfect matching.
+ enum Status {
+ EVEN = 1, ///< = 1. (\c D is an alias for \c EVEN.)
+ D = 1,
+ MATCHED = 0, ///< = 0. (\c C is an alias for \c MATCHED.)
+ C = 0,
+ ODD = -1, ///< = -1. (\c A is an alias for \c ODD.)
+ A = -1,
+ UNMATCHED = -2 ///< = -2.
+ };
+
+ /// The type of the status map
+ typedef typename Graph::template NodeMap<Status> StatusMap;
+
+ private:
+
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+ typedef UnionFindEnum<IntNodeMap> BlossomSet;
+ typedef ExtendFindEnum<IntNodeMap> TreeSet;
+ typedef RangeMap<Node> NodeIntMap;
+ typedef MatchingMap EarMap;
+ typedef std::vector<Node> NodeQueue;
+
+ const Graph& _graph;
+ MatchingMap* _matching;
+ StatusMap* _status;
+
+ EarMap* _ear;
+
+ IntNodeMap* _blossom_set_index;
+ BlossomSet* _blossom_set;
+ NodeIntMap* _blossom_rep;
+
+ IntNodeMap* _tree_set_index;
+ TreeSet* _tree_set;
+
+ NodeQueue _node_queue;
+ int _process, _postpone, _last;
+
+ int _node_num;
+
+ private:
+
+ void createStructures() {
+ _node_num = countNodes(_graph);
+ if (!_matching) {
+ _matching = new MatchingMap(_graph);
+ }
+ if (!_status) {
+ _status = new StatusMap(_graph);
+ }
+ if (!_ear) {
+ _ear = new EarMap(_graph);
+ }
+ if (!_blossom_set) {
+ _blossom_set_index = new IntNodeMap(_graph);
+ _blossom_set = new BlossomSet(*_blossom_set_index);
+ }
+ if (!_blossom_rep) {
+ _blossom_rep = new NodeIntMap(_node_num);
+ }
+ if (!_tree_set) {
+ _tree_set_index = new IntNodeMap(_graph);
+ _tree_set = new TreeSet(*_tree_set_index);
+ }
+ _node_queue.resize(_node_num);
+ }
+
+ void destroyStructures() {
+ if (_matching) {
+ delete _matching;
+ }
+ if (_status) {
+ delete _status;
+ }
+ if (_ear) {
+ delete _ear;
+ }
+ if (_blossom_set) {
+ delete _blossom_set;
+ delete _blossom_set_index;
+ }
+ if (_blossom_rep) {
+ delete _blossom_rep;
+ }
+ if (_tree_set) {
+ delete _tree_set_index;
+ delete _tree_set;
+ }
+ }
+
+ void processDense(const Node& n) {
+ _process = _postpone = _last = 0;
+ _node_queue[_last++] = n;
+
+ while (_process != _last) {
+ Node u = _node_queue[_process++];
+ for (OutArcIt a(_graph, u); a != INVALID; ++a) {
+ Node v = _graph.target(a);
+ if ((*_status)[v] == MATCHED) {
+ extendOnArc(a);
+ } else if ((*_status)[v] == UNMATCHED) {
+ augmentOnArc(a);
+ return;
+ }
+ }
+ }
+
+ while (_postpone != _last) {
+ Node u = _node_queue[_postpone++];
+
+ for (OutArcIt a(_graph, u); a != INVALID ; ++a) {
+ Node v = _graph.target(a);
+
+ if ((*_status)[v] == EVEN) {
+ if (_blossom_set->find(u) != _blossom_set->find(v)) {
+ shrinkOnEdge(a);
+ }
+ }
+
+ while (_process != _last) {
+ Node w = _node_queue[_process++];
+ for (OutArcIt b(_graph, w); b != INVALID; ++b) {
+ Node x = _graph.target(b);
+ if ((*_status)[x] == MATCHED) {
+ extendOnArc(b);
+ } else if ((*_status)[x] == UNMATCHED) {
+ augmentOnArc(b);
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void processSparse(const Node& n) {
+ _process = _last = 0;
+ _node_queue[_last++] = n;
+ while (_process != _last) {
+ Node u = _node_queue[_process++];
+ for (OutArcIt a(_graph, u); a != INVALID; ++a) {
+ Node v = _graph.target(a);
+
+ if ((*_status)[v] == EVEN) {
+ if (_blossom_set->find(u) != _blossom_set->find(v)) {
+ shrinkOnEdge(a);
+ }
+ } else if ((*_status)[v] == MATCHED) {
+ extendOnArc(a);
+ } else if ((*_status)[v] == UNMATCHED) {
+ augmentOnArc(a);
+ return;
+ }
+ }
+ }
+ }
+
+ void shrinkOnEdge(const Edge& e) {
+ Node nca = INVALID;
+
+ {
+ std::set<Node> left_set, right_set;
+
+ Node left = (*_blossom_rep)[_blossom_set->find(_graph.u(e))];
+ left_set.insert(left);
+
+ Node right = (*_blossom_rep)[_blossom_set->find(_graph.v(e))];
+ right_set.insert(right);
+
+ while (true) {
+ if ((*_matching)[left] == INVALID) break;
+ left = _graph.target((*_matching)[left]);
+ left = (*_blossom_rep)[_blossom_set->
+ find(_graph.target((*_ear)[left]))];
+ if (right_set.find(left) != right_set.end()) {
+ nca = left;
+ break;
+ }
+ left_set.insert(left);
+
+ if ((*_matching)[right] == INVALID) break;
+ right = _graph.target((*_matching)[right]);
+ right = (*_blossom_rep)[_blossom_set->
+ find(_graph.target((*_ear)[right]))];
+ if (left_set.find(right) != left_set.end()) {
+ nca = right;
+ break;
+ }
+ right_set.insert(right);
+ }
+
+ if (nca == INVALID) {
+ if ((*_matching)[left] == INVALID) {
+ nca = right;
+ while (left_set.find(nca) == left_set.end()) {
+ nca = _graph.target((*_matching)[nca]);
+ nca =(*_blossom_rep)[_blossom_set->
+ find(_graph.target((*_ear)[nca]))];
+ }
+ } else {
+ nca = left;
+ while (right_set.find(nca) == right_set.end()) {
+ nca = _graph.target((*_matching)[nca]);
+ nca = (*_blossom_rep)[_blossom_set->
+ find(_graph.target((*_ear)[nca]))];
+ }
+ }
+ }
+ }
+
+ {
+
+ Node node = _graph.u(e);
+ Arc arc = _graph.direct(e, true);
+ Node base = (*_blossom_rep)[_blossom_set->find(node)];
+
+ while (base != nca) {
+ (*_ear)[node] = arc;
+
+ Node n = node;
+ while (n != base) {
+ n = _graph.target((*_matching)[n]);
+ Arc a = (*_ear)[n];
+ n = _graph.target(a);
+ (*_ear)[n] = _graph.oppositeArc(a);
+ }
+ node = _graph.target((*_matching)[base]);
+ _tree_set->erase(base);
+ _tree_set->erase(node);
+ _blossom_set->insert(node, _blossom_set->find(base));
+ (*_status)[node] = EVEN;
+ _node_queue[_last++] = node;
+ arc = _graph.oppositeArc((*_ear)[node]);
+ node = _graph.target((*_ear)[node]);
+ base = (*_blossom_rep)[_blossom_set->find(node)];
+ _blossom_set->join(_graph.target(arc), base);
+ }
+ }
+
+ (*_blossom_rep)[_blossom_set->find(nca)] = nca;
+
+ {
+
+ Node node = _graph.v(e);
+ Arc arc = _graph.direct(e, false);
+ Node base = (*_blossom_rep)[_blossom_set->find(node)];
+
+ while (base != nca) {
+ (*_ear)[node] = arc;
+
+ Node n = node;
+ while (n != base) {
+ n = _graph.target((*_matching)[n]);
+ Arc a = (*_ear)[n];
+ n = _graph.target(a);
+ (*_ear)[n] = _graph.oppositeArc(a);
+ }
+ node = _graph.target((*_matching)[base]);
+ _tree_set->erase(base);
+ _tree_set->erase(node);
+ _blossom_set->insert(node, _blossom_set->find(base));
+ (*_status)[node] = EVEN;
+ _node_queue[_last++] = node;
+ arc = _graph.oppositeArc((*_ear)[node]);
+ node = _graph.target((*_ear)[node]);
+ base = (*_blossom_rep)[_blossom_set->find(node)];
+ _blossom_set->join(_graph.target(arc), base);
+ }
+ }
+
+ (*_blossom_rep)[_blossom_set->find(nca)] = nca;
+ }
+
+ void extendOnArc(const Arc& a) {
+ Node base = _graph.source(a);
+ Node odd = _graph.target(a);
+
+ (*_ear)[odd] = _graph.oppositeArc(a);
+ Node even = _graph.target((*_matching)[odd]);
+ (*_blossom_rep)[_blossom_set->insert(even)] = even;
+ (*_status)[odd] = ODD;
+ (*_status)[even] = EVEN;
+ int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(base)]);
+ _tree_set->insert(odd, tree);
+ _tree_set->insert(even, tree);
+ _node_queue[_last++] = even;
+
+ }
+
+ void augmentOnArc(const Arc& a) {
+ Node even = _graph.source(a);
+ Node odd = _graph.target(a);
+
+ int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(even)]);
+
+ (*_matching)[odd] = _graph.oppositeArc(a);
+ (*_status)[odd] = MATCHED;
+
+ Arc arc = (*_matching)[even];
+ (*_matching)[even] = a;
+
+ while (arc != INVALID) {
+ odd = _graph.target(arc);
+ arc = (*_ear)[odd];
+ even = _graph.target(arc);
+ (*_matching)[odd] = arc;
+ arc = (*_matching)[even];
+ (*_matching)[even] = _graph.oppositeArc((*_matching)[odd]);
+ }
+
+ for (typename TreeSet::ItemIt it(*_tree_set, tree);
+ it != INVALID; ++it) {
+ if ((*_status)[it] == ODD) {
+ (*_status)[it] = MATCHED;
+ } else {
+ int blossom = _blossom_set->find(it);
+ for (typename BlossomSet::ItemIt jt(*_blossom_set, blossom);
+ jt != INVALID; ++jt) {
+ (*_status)[jt] = MATCHED;
+ }
+ _blossom_set->eraseClass(blossom);
+ }
+ }
+ _tree_set->eraseClass(tree);
+
+ }
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ MaxMatching(const Graph& graph)
+ : _graph(graph), _matching(0), _status(0), _ear(0),
+ _blossom_set_index(0), _blossom_set(0), _blossom_rep(0),
+ _tree_set_index(0), _tree_set(0) {}
+
+ ~MaxMatching() {
+ destroyStructures();
+ }
+
+ /// \name Execution Control
+ /// The simplest way to execute the algorithm is to use the
+ /// \c run() member function.\n
+ /// If you need better control on the execution, you have to call
+ /// one of the functions \ref init(), \ref greedyInit() or
+ /// \ref matchingInit() first, then you can start the algorithm with
+ /// \ref startSparse() or \ref startDense().
+
+ ///@{
+
+ /// \brief Set the initial matching to the empty matching.
+ ///
+ /// This function sets the initial matching to the empty matching.
+ void init() {
+ createStructures();
+ for(NodeIt n(_graph); n != INVALID; ++n) {
+ (*_matching)[n] = INVALID;
+ (*_status)[n] = UNMATCHED;
+ }
+ }
+
+ /// \brief Find an initial matching in a greedy way.
+ ///
+ /// This function finds an initial matching in a greedy way.
+ void greedyInit() {
+ createStructures();
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ (*_matching)[n] = INVALID;
+ (*_status)[n] = UNMATCHED;
+ }
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if ((*_matching)[n] == INVALID) {
+ for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
+ Node v = _graph.target(a);
+ if ((*_matching)[v] == INVALID && v != n) {
+ (*_matching)[n] = a;
+ (*_status)[n] = MATCHED;
+ (*_matching)[v] = _graph.oppositeArc(a);
+ (*_status)[v] = MATCHED;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+
+ /// \brief Initialize the matching from a map.
+ ///
+ /// This function initializes the matching from a \c bool valued edge
+ /// map. This map should have the property that there are no two incident
+ /// edges with \c true value, i.e. it really contains a matching.
+ /// \return \c true if the map contains a matching.
+ template <typename MatchingMap>
+ bool matchingInit(const MatchingMap& matching) {
+ createStructures();
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ (*_matching)[n] = INVALID;
+ (*_status)[n] = UNMATCHED;
+ }
+ for(EdgeIt e(_graph); e!=INVALID; ++e) {
+ if (matching[e]) {
+
+ Node u = _graph.u(e);
+ if ((*_matching)[u] != INVALID) return false;
+ (*_matching)[u] = _graph.direct(e, true);
+ (*_status)[u] = MATCHED;
+
+ Node v = _graph.v(e);
+ if ((*_matching)[v] != INVALID) return false;
+ (*_matching)[v] = _graph.direct(e, false);
+ (*_status)[v] = MATCHED;
+ }
+ }
+ return true;
+ }
+
+ /// \brief Start Edmonds' algorithm
+ ///
+ /// This function runs the original Edmonds' algorithm.
+ ///
+ /// \pre \ref init(), \ref greedyInit() or \ref matchingInit() must be
+ /// called before using this function.
+ void startSparse() {
+ for(NodeIt n(_graph); n != INVALID; ++n) {
+ if ((*_status)[n] == UNMATCHED) {
+ (*_blossom_rep)[_blossom_set->insert(n)] = n;
+ _tree_set->insert(n);
+ (*_status)[n] = EVEN;
+ processSparse(n);
+ }
+ }
+ }
+
+ /// \brief Start Edmonds' algorithm with a heuristic improvement
+ /// for dense graphs
+ ///
+ /// This function runs Edmonds' algorithm with a heuristic of postponing
+ /// shrinks, therefore resulting in a faster algorithm for dense graphs.
+ ///
+ /// \pre \ref init(), \ref greedyInit() or \ref matchingInit() must be
+ /// called before using this function.
+ void startDense() {
+ for(NodeIt n(_graph); n != INVALID; ++n) {
+ if ((*_status)[n] == UNMATCHED) {
+ (*_blossom_rep)[_blossom_set->insert(n)] = n;
+ _tree_set->insert(n);
+ (*_status)[n] = EVEN;
+ processDense(n);
+ }
+ }
+ }
+
+
+ /// \brief Run Edmonds' algorithm
+ ///
+ /// This function runs Edmonds' algorithm. An additional heuristic of
+ /// postponing shrinks is used for relatively dense graphs
+ /// (for which <tt>m>=2*n</tt> holds).
+ void run() {
+ if (countEdges(_graph) < 2 * countNodes(_graph)) {
+ greedyInit();
+ startSparse();
+ } else {
+ init();
+ startDense();
+ }
+ }
+
+ /// @}
+
+ /// \name Primal Solution
+ /// Functions to get the primal solution, i.e. the maximum matching.
+
+ /// @{
+
+ /// \brief Return the size (cardinality) of the matching.
+ ///
+ /// This function returns the size (cardinality) of the current matching.
+ /// After run() it returns the size of the maximum matching in the graph.
+ int matchingSize() const {
+ int size = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if ((*_matching)[n] != INVALID) {
+ ++size;
+ }
+ }
+ return size / 2;
+ }
+
+ /// \brief Return \c true if the given edge is in the matching.
+ ///
+ /// This function returns \c true if the given edge is in the current
+ /// matching.
+ bool matching(const Edge& edge) const {
+ return edge == (*_matching)[_graph.u(edge)];
+ }
+
+ /// \brief Return the matching arc (or edge) incident to the given node.
+ ///
+ /// This function returns the matching arc (or edge) incident to the
+ /// given node in the current matching or \c INVALID if the node is
+ /// not covered by the matching.
+ Arc matching(const Node& n) const {
+ return (*_matching)[n];
+ }
+
+ /// \brief Return a const reference to the matching map.
+ ///
+ /// This function returns a const reference to a node map that stores
+ /// the matching arc (or edge) incident to each node.
+ const MatchingMap& matchingMap() const {
+ return *_matching;
+ }
+
+ /// \brief Return the mate of the given node.
+ ///
+ /// This function returns the mate of the given node in the current
+ /// matching or \c INVALID if the node is not covered by the matching.
+ Node mate(const Node& n) const {
+ return (*_matching)[n] != INVALID ?
+ _graph.target((*_matching)[n]) : INVALID;
+ }
+
+ /// @}
+
+ /// \name Dual Solution
+ /// Functions to get the dual solution, i.e. the Gallai-Edmonds
+ /// decomposition.
+
+ /// @{
+
+ /// \brief Return the status of the given node in the Edmonds-Gallai
+ /// decomposition.
+ ///
+ /// This function returns the \ref Status "status" of the given node
+ /// in the Edmonds-Gallai decomposition.
+ Status status(const Node& n) const {
+ return (*_status)[n];
+ }
+
+ /// \brief Return a const reference to the status map, which stores
+ /// the Edmonds-Gallai decomposition.
+ ///
+ /// This function returns a const reference to a node map that stores the
+ /// \ref Status "status" of each node in the Edmonds-Gallai decomposition.
+ const StatusMap& statusMap() const {
+ return *_status;
+ }
+
+ /// \brief Return \c true if the given node is in the barrier.
+ ///
+ /// This function returns \c true if the given node is in the barrier.
+ bool barrier(const Node& n) const {
+ return (*_status)[n] == ODD;
+ }
+
+ /// @}
+
+ };
+
+ /// \ingroup matching
+ ///
+ /// \brief Weighted matching in general graphs
+ ///
+ /// This class provides an efficient implementation of Edmond's
+ /// maximum weighted matching algorithm. The implementation is based
+ /// on extensive use of priority queues and provides
+ /// \f$O(nm\log n)\f$ time complexity.
+ ///
+ /// The maximum weighted matching problem is to find a subset of the
+ /// edges in an undirected graph with maximum overall weight for which
+ /// each node has at most one incident edge.
+ /// It can be formulated with the following linear program.
+ /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
+ /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
+ \quad \forall B\in\mathcal{O}\f] */
+ /// \f[x_e \ge 0\quad \forall e\in E\f]
+ /// \f[\max \sum_{e\in E}x_ew_e\f]
+ /// where \f$\delta(X)\f$ is the set of edges incident to a node in
+ /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
+ /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
+ /// subsets of the nodes.
+ ///
+ /// The algorithm calculates an optimal matching and a proof of the
+ /// optimality. The solution of the dual problem can be used to check
+ /// the result of the algorithm. The dual linear problem is the
+ /// following.
+ /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}
+ z_B \ge w_{uv} \quad \forall uv\in E\f] */
+ /// \f[y_u \ge 0 \quad \forall u \in V\f]
+ /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
+ /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
+ \frac{\vert B \vert - 1}{2}z_B\f] */
+ ///
+ /// The algorithm can be executed with the run() function.
+ /// After it the matching (the primal solution) and the dual solution
+ /// can be obtained using the query functions and the
+ /// \ref MaxWeightedMatching::BlossomIt "BlossomIt" nested class,
+ /// which is able to iterate on the nodes of a blossom.
+ /// If the value type is integer, then the dual solution is multiplied
+ /// by \ref MaxWeightedMatching::dualScale "4".
+ ///
+ /// \tparam GR The undirected graph type the algorithm runs on.
+ /// \tparam WM The type edge weight map. The default type is
+ /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
+#ifdef DOXYGEN
+ template <typename GR, typename WM>
+#else
+ template <typename GR,
+ typename WM = typename GR::template EdgeMap<int> >
+#endif
+ class MaxWeightedMatching {
+ public:
+
+ /// The graph type of the algorithm
+ typedef GR Graph;
+ /// The type of the edge weight map
+ typedef WM WeightMap;
+ /// The value type of the edge weights
+ typedef typename WeightMap::Value Value;
+
+ /// The type of the matching map
+ typedef typename Graph::template NodeMap<typename Graph::Arc>
+ MatchingMap;
+
+ /// \brief Scaling factor for dual solution
+ ///
+ /// Scaling factor for dual solution. It is equal to 4 or 1
+ /// according to the value type.
+ static const int dualScale =
+ std::numeric_limits<Value>::is_integer ? 4 : 1;
+
+ private:
+
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+ typedef typename Graph::template NodeMap<Value> NodePotential;
+ typedef std::vector<Node> BlossomNodeList;
+
+ struct BlossomVariable {
+ int begin, end;
+ Value value;
+
+ BlossomVariable(int _begin, int _end, Value _value)
+ : begin(_begin), end(_end), value(_value) {}
+
+ };
+
+ typedef std::vector<BlossomVariable> BlossomPotential;
+
+ const Graph& _graph;
+ const WeightMap& _weight;
+
+ MatchingMap* _matching;
+
+ NodePotential* _node_potential;
+
+ BlossomPotential _blossom_potential;
+ BlossomNodeList _blossom_node_list;
+
+ int _node_num;
+ int _blossom_num;
+
+ typedef RangeMap<int> IntIntMap;
+
+ enum Status {
+ EVEN = -1, MATCHED = 0, ODD = 1
+ };
+
+ typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
+ struct BlossomData {
+ int tree;
+ Status status;
+ Arc pred, next;
+ Value pot, offset;
+ Node base;
+ };
+
+ IntNodeMap *_blossom_index;
+ BlossomSet *_blossom_set;
+ RangeMap<BlossomData>* _blossom_data;
+
+ IntNodeMap *_node_index;
+ IntArcMap *_node_heap_index;
+
+ struct NodeData {
+
+ NodeData(IntArcMap& node_heap_index)
+ : heap(node_heap_index) {}
+
+ int blossom;
+ Value pot;
+ BinHeap<Value, IntArcMap> heap;
+ std::map<int, Arc> heap_index;
+
+ int tree;
+ };
+
+ RangeMap<NodeData>* _node_data;
+
+ typedef ExtendFindEnum<IntIntMap> TreeSet;
+
+ IntIntMap *_tree_set_index;
+ TreeSet *_tree_set;
+
+ IntNodeMap *_delta1_index;
+ BinHeap<Value, IntNodeMap> *_delta1;
+
+ IntIntMap *_delta2_index;
+ BinHeap<Value, IntIntMap> *_delta2;
+
+ IntEdgeMap *_delta3_index;
+ BinHeap<Value, IntEdgeMap> *_delta3;
+
+ IntIntMap *_delta4_index;
+ BinHeap<Value, IntIntMap> *_delta4;
+
+ Value _delta_sum;
+ int _unmatched;
+
+ typedef MaxWeightedFractionalMatching<Graph, WeightMap> FractionalMatching;
+ FractionalMatching *_fractional;
+
+ void createStructures() {
+ _node_num = countNodes(_graph);
+ _blossom_num = _node_num * 3 / 2;
+
+ if (!_matching) {
+ _matching = new MatchingMap(_graph);
+ }
+
+ if (!_node_potential) {
+ _node_potential = new NodePotential(_graph);
+ }
+
+ if (!_blossom_set) {
+ _blossom_index = new IntNodeMap(_graph);
+ _blossom_set = new BlossomSet(*_blossom_index);
+ _blossom_data = new RangeMap<BlossomData>(_blossom_num);
+ } else if (_blossom_data->size() != _blossom_num) {
+ delete _blossom_data;
+ _blossom_data = new RangeMap<BlossomData>(_blossom_num);
+ }
+
+ if (!_node_index) {
+ _node_index = new IntNodeMap(_graph);
+ _node_heap_index = new IntArcMap(_graph);
+ _node_data = new RangeMap<NodeData>(_node_num,
+ NodeData(*_node_heap_index));
+ } else {
+ delete _node_data;
+ _node_data = new RangeMap<NodeData>(_node_num,
+ NodeData(*_node_heap_index));
+ }
+
+ if (!_tree_set) {
+ _tree_set_index = new IntIntMap(_blossom_num);
+ _tree_set = new TreeSet(*_tree_set_index);
+ } else {
+ _tree_set_index->resize(_blossom_num);
+ }
+
+ if (!_delta1) {
+ _delta1_index = new IntNodeMap(_graph);
+ _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
+ }
+
+ if (!_delta2) {
+ _delta2_index = new IntIntMap(_blossom_num);
+ _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
+ } else {
+ _delta2_index->resize(_blossom_num);
+ }
+
+ if (!_delta3) {
+ _delta3_index = new IntEdgeMap(_graph);
+ _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
+ }
+
+ if (!_delta4) {
+ _delta4_index = new IntIntMap(_blossom_num);
+ _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
+ } else {
+ _delta4_index->resize(_blossom_num);
+ }
+ }
+
+ void destroyStructures() {
+ if (_matching) {
+ delete _matching;
+ }
+ if (_node_potential) {
+ delete _node_potential;
+ }
+ if (_blossom_set) {
+ delete _blossom_index;
+ delete _blossom_set;
+ delete _blossom_data;
+ }
+
+ if (_node_index) {
+ delete _node_index;
+ delete _node_heap_index;
+ delete _node_data;
+ }
+
+ if (_tree_set) {
+ delete _tree_set_index;
+ delete _tree_set;
+ }
+ if (_delta1) {
+ delete _delta1_index;
+ delete _delta1;
+ }
+ if (_delta2) {
+ delete _delta2_index;
+ delete _delta2;
+ }
+ if (_delta3) {
+ delete _delta3_index;
+ delete _delta3;
+ }
+ if (_delta4) {
+ delete _delta4_index;
+ delete _delta4;
+ }
+ }
+
+ void matchedToEven(int blossom, int tree) {
+ if (_delta2->state(blossom) == _delta2->IN_HEAP) {
+ _delta2->erase(blossom);
+ }
+
+ if (!_blossom_set->trivial(blossom)) {
+ (*_blossom_data)[blossom].pot -=
+ 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
+ }
+
+ for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
+ n != INVALID; ++n) {
+
+ _blossom_set->increase(n, std::numeric_limits<Value>::max());
+ int ni = (*_node_index)[n];
+
+ (*_node_data)[ni].heap.clear();
+ (*_node_data)[ni].heap_index.clear();
+
+ (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
+
+ _delta1->push(n, (*_node_data)[ni].pot);
+
+ for (InArcIt e(_graph, n); e != INVALID; ++e) {
+ Node v = _graph.source(e);
+ int vb = _blossom_set->find(v);
+ int vi = (*_node_index)[v];
+
+ Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
+ dualScale * _weight[e];
+
+ if ((*_blossom_data)[vb].status == EVEN) {
+ if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
+ _delta3->push(e, rw / 2);
+ }
+ } else {
+ typename std::map<int, Arc>::iterator it =
+ (*_node_data)[vi].heap_index.find(tree);
+
+ if (it != (*_node_data)[vi].heap_index.end()) {
+ if ((*_node_data)[vi].heap[it->second] > rw) {
+ (*_node_data)[vi].heap.replace(it->second, e);
+ (*_node_data)[vi].heap.decrease(e, rw);
+ it->second = e;
+ }
+ } else {
+ (*_node_data)[vi].heap.push(e, rw);
+ (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
+ }
+
+ if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
+ _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
+
+ if ((*_blossom_data)[vb].status == MATCHED) {
+ if (_delta2->state(vb) != _delta2->IN_HEAP) {
+ _delta2->push(vb, _blossom_set->classPrio(vb) -
+ (*_blossom_data)[vb].offset);
+ } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
+ (*_blossom_data)[vb].offset) {
+ _delta2->decrease(vb, _blossom_set->classPrio(vb) -
+ (*_blossom_data)[vb].offset);
+ }
+ }
+ }
+ }
+ }
+ }
+ (*_blossom_data)[blossom].offset = 0;
+ }
+
+ void matchedToOdd(int blossom) {
+ if (_delta2->state(blossom) == _delta2->IN_HEAP) {
+ _delta2->erase(blossom);
+ }
+ (*_blossom_data)[blossom].offset += _delta_sum;
+ if (!_blossom_set->trivial(blossom)) {
+ _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
+ (*_blossom_data)[blossom].offset);
+ }
+ }
+
+ void evenToMatched(int blossom, int tree) {
+ if (!_blossom_set->trivial(blossom)) {
+ (*_blossom_data)[blossom].pot += 2 * _delta_sum;
+ }
+
+ for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
+ n != INVALID; ++n) {
+ int ni = (*_node_index)[n];
+ (*_node_data)[ni].pot -= _delta_sum;
+
+ _delta1->erase(n);
+
+ for (InArcIt e(_graph, n); e != INVALID; ++e) {
+ Node v = _graph.source(e);
+ int vb = _blossom_set->find(v);
+ int vi = (*_node_index)[v];
+
+ Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
+ dualScale * _weight[e];
+
+ if (vb == blossom) {
+ if (_delta3->state(e) == _delta3->IN_HEAP) {
+ _delta3->erase(e);
+ }
+ } else if ((*_blossom_data)[vb].status == EVEN) {
+
+ if (_delta3->state(e) == _delta3->IN_HEAP) {
+ _delta3->erase(e);
+ }
+
+ int vt = _tree_set->find(vb);
+
+ if (vt != tree) {
+
+ Arc r = _graph.oppositeArc(e);
+
+ typename std::map<int, Arc>::iterator it =
+ (*_node_data)[ni].heap_index.find(vt);
+
+ if (it != (*_node_data)[ni].heap_index.end()) {
+ if ((*_node_data)[ni].heap[it->second] > rw) {
+ (*_node_data)[ni].heap.replace(it->second, r);
+ (*_node_data)[ni].heap.decrease(r, rw);
+ it->second = r;
+ }
+ } else {
+ (*_node_data)[ni].heap.push(r, rw);
+ (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
+ }
+
+ if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
+ _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
+
+ if (_delta2->state(blossom) != _delta2->IN_HEAP) {
+ _delta2->push(blossom, _blossom_set->classPrio(blossom) -
+ (*_blossom_data)[blossom].offset);
+ } else if ((*_delta2)[blossom] >
+ _blossom_set->classPrio(blossom) -
+ (*_blossom_data)[blossom].offset){
+ _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
+ (*_blossom_data)[blossom].offset);
+ }
+ }
+ }
+ } else {
+
+ typename std::map<int, Arc>::iterator it =
+ (*_node_data)[vi].heap_index.find(tree);
+
+ if (it != (*_node_data)[vi].heap_index.end()) {
+ (*_node_data)[vi].heap.erase(it->second);
+ (*_node_data)[vi].heap_index.erase(it);
+ if ((*_node_data)[vi].heap.empty()) {
+ _blossom_set->increase(v, std::numeric_limits<Value>::max());
+ } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
+ _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
+ }
+
+ if ((*_blossom_data)[vb].status == MATCHED) {
+ if (_blossom_set->classPrio(vb) ==
+ std::numeric_limits<Value>::max()) {
+ _delta2->erase(vb);
+ } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
+ (*_blossom_data)[vb].offset) {
+ _delta2->increase(vb, _blossom_set->classPrio(vb) -
+ (*_blossom_data)[vb].offset);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void oddToMatched(int blossom) {
+ (*_blossom_data)[blossom].offset -= _delta_sum;
+
+ if (_blossom_set->classPrio(blossom) !=
+ std::numeric_limits<Value>::max()) {
+ _delta2->push(blossom, _blossom_set->classPrio(blossom) -
+ (*_blossom_data)[blossom].offset);
+ }
+
+ if (!_blossom_set->trivial(blossom)) {
+ _delta4->erase(blossom);
+ }
+ }
+
+ void oddToEven(int blossom, int tree) {
+ if (!_blossom_set->trivial(blossom)) {
+ _delta4->erase(blossom);
+ (*_blossom_data)[blossom].pot -=
+ 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
+ }
+
+ for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
+ n != INVALID; ++n) {
+ int ni = (*_node_index)[n];
+
+ _blossom_set->increase(n, std::numeric_limits<Value>::max());
+
+ (*_node_data)[ni].heap.clear();
+ (*_node_data)[ni].heap_index.clear();
+ (*_node_data)[ni].pot +=
+ 2 * _delta_sum - (*_blossom_data)[blossom].offset;
+
+ _delta1->push(n, (*_node_data)[ni].pot);
+
+ for (InArcIt e(_graph, n); e != INVALID; ++e) {
+ Node v = _graph.source(e);
+ int vb = _blossom_set->find(v);
+ int vi = (*_node_index)[v];
+
+ Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
+ dualScale * _weight[e];
+
+ if ((*_blossom_data)[vb].status == EVEN) {
+ if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
+ _delta3->push(e, rw / 2);
+ }
+ } else {
+
+ typename std::map<int, Arc>::iterator it =
+ (*_node_data)[vi].heap_index.find(tree);
+
+ if (it != (*_node_data)[vi].heap_index.end()) {
+ if ((*_node_data)[vi].heap[it->second] > rw) {
+ (*_node_data)[vi].heap.replace(it->second, e);
+ (*_node_data)[vi].heap.decrease(e, rw);
+ it->second = e;
+ }
+ } else {
+ (*_node_data)[vi].heap.push(e, rw);
+ (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
+ }
+
+ if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
+ _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
+
+ if ((*_blossom_data)[vb].status == MATCHED) {
+ if (_delta2->state(vb) != _delta2->IN_HEAP) {
+ _delta2->push(vb, _blossom_set->classPrio(vb) -
+ (*_blossom_data)[vb].offset);
+ } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
+ (*_blossom_data)[vb].offset) {
+ _delta2->decrease(vb, _blossom_set->classPrio(vb) -
+ (*_blossom_data)[vb].offset);
+ }
+ }
+ }
+ }
+ }
+ }
+ (*_blossom_data)[blossom].offset = 0;
+ }
+
+ void alternatePath(int even, int tree) {
+ int odd;
+
+ evenToMatched(even, tree);
+ (*_blossom_data)[even].status = MATCHED;
+
+ while ((*_blossom_data)[even].pred != INVALID) {
+ odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
+ (*_blossom_data)[odd].status = MATCHED;
+ oddToMatched(odd);
+ (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
+
+ even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
+ (*_blossom_data)[even].status = MATCHED;
+ evenToMatched(even, tree);
+ (*_blossom_data)[even].next =
+ _graph.oppositeArc((*_blossom_data)[odd].pred);
+ }
+
+ }
+
+ void destroyTree(int tree) {
+ for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
+ if ((*_blossom_data)[b].status == EVEN) {
+ (*_blossom_data)[b].status = MATCHED;
+ evenToMatched(b, tree);
+ } else if ((*_blossom_data)[b].status == ODD) {
+ (*_blossom_data)[b].status = MATCHED;
+ oddToMatched(b);
+ }
+ }
+ _tree_set->eraseClass(tree);
+ }
+
+
+ void unmatchNode(const Node& node) {
+ int blossom = _blossom_set->find(node);
+ int tree = _tree_set->find(blossom);
+
+ alternatePath(blossom, tree);
+ destroyTree(tree);
+
+ (*_blossom_data)[blossom].base = node;
+ (*_blossom_data)[blossom].next = INVALID;
+ }
+
+ void augmentOnEdge(const Edge& edge) {
+
+ int left = _blossom_set->find(_graph.u(edge));
+ int right = _blossom_set->find(_graph.v(edge));
+
+ int left_tree = _tree_set->find(left);
+ alternatePath(left, left_tree);
+ destroyTree(left_tree);
+
+ int right_tree = _tree_set->find(right);
+ alternatePath(right, right_tree);
+ destroyTree(right_tree);
+
+ (*_blossom_data)[left].next = _graph.direct(edge, true);
+ (*_blossom_data)[right].next = _graph.direct(edge, false);
+ }
+
+ void augmentOnArc(const Arc& arc) {
+
+ int left = _blossom_set->find(_graph.source(arc));
+ int right = _blossom_set->find(_graph.target(arc));
+
+ (*_blossom_data)[left].status = MATCHED;
+
+ int right_tree = _tree_set->find(right);
+ alternatePath(right, right_tree);
+ destroyTree(right_tree);
+
+ (*_blossom_data)[left].next = arc;
+ (*_blossom_data)[right].next = _graph.oppositeArc(arc);
+ }
+
+ void extendOnArc(const Arc& arc) {
+ int base = _blossom_set->find(_graph.target(arc));
+ int tree = _tree_set->find(base);
+
+ int odd = _blossom_set->find(_graph.source(arc));
+ _tree_set->insert(odd, tree);
+ (*_blossom_data)[odd].status = ODD;
+ matchedToOdd(odd);
+ (*_blossom_data)[odd].pred = arc;
+
+ int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
+ (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
+ _tree_set->insert(even, tree);
+ (*_blossom_data)[even].status = EVEN;
+ matchedToEven(even, tree);
+ }
+
+ void shrinkOnEdge(const Edge& edge, int tree) {
+ int nca = -1;
+ std::vector<int> left_path, right_path;
+
+ {
+ std::set<int> left_set, right_set;
+ int left = _blossom_set->find(_graph.u(edge));
+ left_path.push_back(left);
+ left_set.insert(left);
+
+ int right = _blossom_set->find(_graph.v(edge));
+ right_path.push_back(right);
+ right_set.insert(right);
+
+ while (true) {
+
+ if ((*_blossom_data)[left].pred == INVALID) break;
+
+ left =
+ _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
+ left_path.push_back(left);
+ left =
+ _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
+ left_path.push_back(left);
+
+ left_set.insert(left);
+
+ if (right_set.find(left) != right_set.end()) {
+ nca = left;
+ break;
+ }
+
+ if ((*_blossom_data)[right].pred == INVALID) break;
+
+ right =
+ _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
+ right_path.push_back(right);
+ right =
+ _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
+ right_path.push_back(right);
+
+ right_set.insert(right);
+
+ if (left_set.find(right) != left_set.end()) {
+ nca = right;
+ break;
+ }
+
+ }
+
+ if (nca == -1) {
+ if ((*_blossom_data)[left].pred == INVALID) {
+ nca = right;
+ while (left_set.find(nca) == left_set.end()) {
+ nca =
+ _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
+ right_path.push_back(nca);
+ nca =
+ _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
+ right_path.push_back(nca);
+ }
+ } else {
+ nca = left;
+ while (right_set.find(nca) == right_set.end()) {
+ nca =
+ _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
+ left_path.push_back(nca);
+ nca =
+ _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
+ left_path.push_back(nca);
+ }
+ }
+ }
+ }
+
+ std::vector<int> subblossoms;
+ Arc prev;
+
+ prev = _graph.direct(edge, true);
+ for (int i = 0; left_path[i] != nca; i += 2) {
+ subblossoms.push_back(left_path[i]);
+ (*_blossom_data)[left_path[i]].next = prev;
+ _tree_set->erase(left_path[i]);
+
+ subblossoms.push_back(left_path[i + 1]);
+ (*_blossom_data)[left_path[i + 1]].status = EVEN;
+ oddToEven(left_path[i + 1], tree);
+ _tree_set->erase(left_path[i + 1]);
+ prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
+ }
+
+ int k = 0;
+ while (right_path[k] != nca) ++k;
+
+ subblossoms.push_back(nca);
+ (*_blossom_data)[nca].next = prev;
+
+ for (int i = k - 2; i >= 0; i -= 2) {
+ subblossoms.push_back(right_path[i + 1]);
+ (*_blossom_data)[right_path[i + 1]].status = EVEN;
+ oddToEven(right_path[i + 1], tree);
+ _tree_set->erase(right_path[i + 1]);
+
+ (*_blossom_data)[right_path[i + 1]].next =
+ (*_blossom_data)[right_path[i + 1]].pred;
+
+ subblossoms.push_back(right_path[i]);
+ _tree_set->erase(right_path[i]);
+ }
+
+ int surface =
+ _blossom_set->join(subblossoms.begin(), subblossoms.end());
+
+ for (int i = 0; i < int(subblossoms.size()); ++i) {
+ if (!_blossom_set->trivial(subblossoms[i])) {
+ (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
+ }
+ (*_blossom_data)[subblossoms[i]].status = MATCHED;
+ }
+
+ (*_blossom_data)[surface].pot = -2 * _delta_sum;
+ (*_blossom_data)[surface].offset = 0;
+ (*_blossom_data)[surface].status = EVEN;
+ (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
+ (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
+
+ _tree_set->insert(surface, tree);
+ _tree_set->erase(nca);
+ }
+
+ void splitBlossom(int blossom) {
+ Arc next = (*_blossom_data)[blossom].next;
+ Arc pred = (*_blossom_data)[blossom].pred;
+
+ int tree = _tree_set->find(blossom);
+
+ (*_blossom_data)[blossom].status = MATCHED;
+ oddToMatched(blossom);
+ if (_delta2->state(blossom) == _delta2->IN_HEAP) {
+ _delta2->erase(blossom);
+ }
+
+ std::vector<int> subblossoms;
+ _blossom_set->split(blossom, std::back_inserter(subblossoms));
+
+ Value offset = (*_blossom_data)[blossom].offset;
+ int b = _blossom_set->find(_graph.source(pred));
+ int d = _blossom_set->find(_graph.source(next));
+
+ int ib = -1, id = -1;
+ for (int i = 0; i < int(subblossoms.size()); ++i) {
+ if (subblossoms[i] == b) ib = i;
+ if (subblossoms[i] == d) id = i;
+
+ (*_blossom_data)[subblossoms[i]].offset = offset;
+ if (!_blossom_set->trivial(subblossoms[i])) {
+ (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
+ }
+ if (_blossom_set->classPrio(subblossoms[i]) !=
+ std::numeric_limits<Value>::max()) {
+ _delta2->push(subblossoms[i],
+ _blossom_set->classPrio(subblossoms[i]) -
+ (*_blossom_data)[subblossoms[i]].offset);
+ }
+ }
+
+ if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
+ for (int i = (id + 1) % subblossoms.size();
+ i != ib; i = (i + 2) % subblossoms.size()) {
+ int sb = subblossoms[i];
+ int tb = subblossoms[(i + 1) % subblossoms.size()];
+ (*_blossom_data)[sb].next =
+ _graph.oppositeArc((*_blossom_data)[tb].next);
+ }
+
+ for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
+ int sb = subblossoms[i];
+ int tb = subblossoms[(i + 1) % subblossoms.size()];
+ int ub = subblossoms[(i + 2) % subblossoms.size()];
+
+ (*_blossom_data)[sb].status = ODD;
+ matchedToOdd(sb);
+ _tree_set->insert(sb, tree);
+ (*_blossom_data)[sb].pred = pred;
+ (*_blossom_data)[sb].next =
+ _graph.oppositeArc((*_blossom_data)[tb].next);
+
+ pred = (*_blossom_data)[ub].next;
+
+ (*_blossom_data)[tb].status = EVEN;
+ matchedToEven(tb, tree);
+ _tree_set->insert(tb, tree);
+ (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
+ }
+
+ (*_blossom_data)[subblossoms[id]].status = ODD;
+ matchedToOdd(subblossoms[id]);
+ _tree_set->insert(subblossoms[id], tree);
+ (*_blossom_data)[subblossoms[id]].next = next;
+ (*_blossom_data)[subblossoms[id]].pred = pred;
+
+ } else {
+
+ for (int i = (ib + 1) % subblossoms.size();
+ i != id; i = (i + 2) % subblossoms.size()) {
+ int sb = subblossoms[i];
+ int tb = subblossoms[(i + 1) % subblossoms.size()];
+ (*_blossom_data)[sb].next =
+ _graph.oppositeArc((*_blossom_data)[tb].next);
+ }
+
+ for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
+ int sb = subblossoms[i];
+ int tb = subblossoms[(i + 1) % subblossoms.size()];
+ int ub = subblossoms[(i + 2) % subblossoms.size()];
+
+ (*_blossom_data)[sb].status = ODD;
+ matchedToOdd(sb);
+ _tree_set->insert(sb, tree);
+ (*_blossom_data)[sb].next = next;
+ (*_blossom_data)[sb].pred =
+ _graph.oppositeArc((*_blossom_data)[tb].next);
+
+ (*_blossom_data)[tb].status = EVEN;
+ matchedToEven(tb, tree);
+ _tree_set->insert(tb, tree);
+ (*_blossom_data)[tb].pred =
+ (*_blossom_data)[tb].next =
+ _graph.oppositeArc((*_blossom_data)[ub].next);
+ next = (*_blossom_data)[ub].next;
+ }
+
+ (*_blossom_data)[subblossoms[ib]].status = ODD;
+ matchedToOdd(subblossoms[ib]);
+ _tree_set->insert(subblossoms[ib], tree);
+ (*_blossom_data)[subblossoms[ib]].next = next;
+ (*_blossom_data)[subblossoms[ib]].pred = pred;
+ }
+ _tree_set->erase(blossom);
+ }
+
+ void extractBlossom(int blossom, const Node& base, const Arc& matching) {
+ if (_blossom_set->trivial(blossom)) {
+ int bi = (*_node_index)[base];
+ Value pot = (*_node_data)[bi].pot;
+
+ (*_matching)[base] = matching;
+ _blossom_node_list.push_back(base);
+ (*_node_potential)[base] = pot;
+ } else {
+
+ Value pot = (*_blossom_data)[blossom].pot;
+ int bn = _blossom_node_list.size();
+
+ std::vector<int> subblossoms;
+ _blossom_set->split(blossom, std::back_inserter(subblossoms));
+ int b = _blossom_set->find(base);
+ int ib = -1;
+ for (int i = 0; i < int(subblossoms.size()); ++i) {
+ if (subblossoms[i] == b) { ib = i; break; }
+ }
+
+ for (int i = 1; i < int(subblossoms.size()); i += 2) {
+ int sb = subblossoms[(ib + i) % subblossoms.size()];
+ int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
+
+ Arc m = (*_blossom_data)[tb].next;
+ extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
+ extractBlossom(tb, _graph.source(m), m);
+ }
+ extractBlossom(subblossoms[ib], base, matching);
+
+ int en = _blossom_node_list.size();
+
+ _blossom_potential.push_back(BlossomVariable(bn, en, pot));
+ }
+ }
+
+ void extractMatching() {
+ std::vector<int> blossoms;
+ for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
+ blossoms.push_back(c);
+ }
+
+ for (int i = 0; i < int(blossoms.size()); ++i) {
+ if ((*_blossom_data)[blossoms[i]].next != INVALID) {
+
+ Value offset = (*_blossom_data)[blossoms[i]].offset;
+ (*_blossom_data)[blossoms[i]].pot += 2 * offset;
+ for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
+ n != INVALID; ++n) {
+ (*_node_data)[(*_node_index)[n]].pot -= offset;
+ }
+
+ Arc matching = (*_blossom_data)[blossoms[i]].next;
+ Node base = _graph.source(matching);
+ extractBlossom(blossoms[i], base, matching);
+ } else {
+ Node base = (*_blossom_data)[blossoms[i]].base;
+ extractBlossom(blossoms[i], base, INVALID);
+ }
+ }
+ }
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
+ : _graph(graph), _weight(weight), _matching(0),
+ _node_potential(0), _blossom_potential(), _blossom_node_list(),
+ _node_num(0), _blossom_num(0),
+
+ _blossom_index(0), _blossom_set(0), _blossom_data(0),
+ _node_index(0), _node_heap_index(0), _node_data(0),
+ _tree_set_index(0), _tree_set(0),
+
+ _delta1_index(0), _delta1(0),
+ _delta2_index(0), _delta2(0),
+ _delta3_index(0), _delta3(0),
+ _delta4_index(0), _delta4(0),
+
+ _delta_sum(), _unmatched(0),
+
+ _fractional(0)
+ {}
+
+ ~MaxWeightedMatching() {
+ destroyStructures();
+ if (_fractional) {
+ delete _fractional;
+ }
+ }
+
+ /// \name Execution Control
+ /// The simplest way to execute the algorithm is to use the
+ /// \ref run() member function.
+
+ ///@{
+
+ /// \brief Initialize the algorithm
+ ///
+ /// This function initializes the algorithm.
+ void init() {
+ createStructures();
+
+ _blossom_node_list.clear();
+ _blossom_potential.clear();
+
+ for (ArcIt e(_graph); e != INVALID; ++e) {
+ (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
+ }
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ (*_delta1_index)[n] = _delta1->PRE_HEAP;
+ }
+ for (EdgeIt e(_graph); e != INVALID; ++e) {
+ (*_delta3_index)[e] = _delta3->PRE_HEAP;
+ }
+ for (int i = 0; i < _blossom_num; ++i) {
+ (*_delta2_index)[i] = _delta2->PRE_HEAP;
+ (*_delta4_index)[i] = _delta4->PRE_HEAP;
+ }
+
+ _unmatched = _node_num;
+
+ _delta1->clear();
+ _delta2->clear();
+ _delta3->clear();
+ _delta4->clear();
+ _blossom_set->clear();
+ _tree_set->clear();
+
+ int index = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ Value max = 0;
+ for (OutArcIt e(_graph, n); e != INVALID; ++e) {
+ if (_graph.target(e) == n) continue;
+ if ((dualScale * _weight[e]) / 2 > max) {
+ max = (dualScale * _weight[e]) / 2;
+ }
+ }
+ (*_node_index)[n] = index;
+ (*_node_data)[index].heap_index.clear();
+ (*_node_data)[index].heap.clear();
+ (*_node_data)[index].pot = max;
+ _delta1->push(n, max);
+ int blossom =
+ _blossom_set->insert(n, std::numeric_limits<Value>::max());
+
+ _tree_set->insert(blossom);
+
+ (*_blossom_data)[blossom].status = EVEN;
+ (*_blossom_data)[blossom].pred = INVALID;
+ (*_blossom_data)[blossom].next = INVALID;
+ (*_blossom_data)[blossom].pot = 0;
+ (*_blossom_data)[blossom].offset = 0;
+ ++index;
+ }
+ for (EdgeIt e(_graph); e != INVALID; ++e) {
+ int si = (*_node_index)[_graph.u(e)];
+ int ti = (*_node_index)[_graph.v(e)];
+ if (_graph.u(e) != _graph.v(e)) {
+ _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
+ dualScale * _weight[e]) / 2);
+ }
+ }
+ }
+
+ /// \brief Initialize the algorithm with fractional matching
+ ///
+ /// This function initializes the algorithm with a fractional
+ /// matching. This initialization is also called jumpstart heuristic.
+ void fractionalInit() {
+ createStructures();
+
+ _blossom_node_list.clear();
+ _blossom_potential.clear();
+
+ if (_fractional == 0) {
+ _fractional = new FractionalMatching(_graph, _weight, false);
+ }
+ _fractional->run();
+
+ for (ArcIt e(_graph); e != INVALID; ++e) {
+ (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
+ }
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ (*_delta1_index)[n] = _delta1->PRE_HEAP;
+ }
+ for (EdgeIt e(_graph); e != INVALID; ++e) {
+ (*_delta3_index)[e] = _delta3->PRE_HEAP;
+ }
+ for (int i = 0; i < _blossom_num; ++i) {
+ (*_delta2_index)[i] = _delta2->PRE_HEAP;
+ (*_delta4_index)[i] = _delta4->PRE_HEAP;
+ }
+
+ _unmatched = 0;
+
+ _delta1->clear();
+ _delta2->clear();
+ _delta3->clear();
+ _delta4->clear();
+ _blossom_set->clear();
+ _tree_set->clear();
+
+ int index = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ Value pot = _fractional->nodeValue(n);
+ (*_node_index)[n] = index;
+ (*_node_data)[index].pot = pot;
+ (*_node_data)[index].heap_index.clear();
+ (*_node_data)[index].heap.clear();
+ int blossom =
+ _blossom_set->insert(n, std::numeric_limits<Value>::max());
+
+ (*_blossom_data)[blossom].status = MATCHED;
+ (*_blossom_data)[blossom].pred = INVALID;
+ (*_blossom_data)[blossom].next = _fractional->matching(n);
+ if (_fractional->matching(n) == INVALID) {
+ (*_blossom_data)[blossom].base = n;
+ }
+ (*_blossom_data)[blossom].pot = 0;
+ (*_blossom_data)[blossom].offset = 0;
+ ++index;
+ }
+
+ typename Graph::template NodeMap<bool> processed(_graph, false);
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if (processed[n]) continue;
+ processed[n] = true;
+ if (_fractional->matching(n) == INVALID) continue;
+ int num = 1;
+ Node v = _graph.target(_fractional->matching(n));
+ while (n != v) {
+ processed[v] = true;
+ v = _graph.target(_fractional->matching(v));
+ ++num;
+ }
+
+ if (num % 2 == 1) {
+ std::vector<int> subblossoms(num);
+
+ subblossoms[--num] = _blossom_set->find(n);
+ _delta1->push(n, _fractional->nodeValue(n));
+ v = _graph.target(_fractional->matching(n));
+ while (n != v) {
+ subblossoms[--num] = _blossom_set->find(v);
+ _delta1->push(v, _fractional->nodeValue(v));
+ v = _graph.target(_fractional->matching(v));
+ }
+
+ int surface =
+ _blossom_set->join(subblossoms.begin(), subblossoms.end());
+ (*_blossom_data)[surface].status = EVEN;
+ (*_blossom_data)[surface].pred = INVALID;
+ (*_blossom_data)[surface].next = INVALID;
+ (*_blossom_data)[surface].pot = 0;
+ (*_blossom_data)[surface].offset = 0;
+
+ _tree_set->insert(surface);
+ ++_unmatched;
+ }
+ }
+
+ for (EdgeIt e(_graph); e != INVALID; ++e) {
+ int si = (*_node_index)[_graph.u(e)];
+ int sb = _blossom_set->find(_graph.u(e));
+ int ti = (*_node_index)[_graph.v(e)];
+ int tb = _blossom_set->find(_graph.v(e));
+ if ((*_blossom_data)[sb].status == EVEN &&
+ (*_blossom_data)[tb].status == EVEN && sb != tb) {
+ _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
+ dualScale * _weight[e]) / 2);
+ }
+ }
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ int nb = _blossom_set->find(n);
+ if ((*_blossom_data)[nb].status != MATCHED) continue;
+ int ni = (*_node_index)[n];
+
+ for (OutArcIt e(_graph, n); e != INVALID; ++e) {
+ Node v = _graph.target(e);
+ int vb = _blossom_set->find(v);
+ int vi = (*_node_index)[v];
+
+ Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
+ dualScale * _weight[e];
+
+ if ((*_blossom_data)[vb].status == EVEN) {
+
+ int vt = _tree_set->find(vb);
+
+ typename std::map<int, Arc>::iterator it =
+ (*_node_data)[ni].heap_index.find(vt);
+
+ if (it != (*_node_data)[ni].heap_index.end()) {
+ if ((*_node_data)[ni].heap[it->second] > rw) {
+ (*_node_data)[ni].heap.replace(it->second, e);
+ (*_node_data)[ni].heap.decrease(e, rw);
+ it->second = e;
+ }
+ } else {
+ (*_node_data)[ni].heap.push(e, rw);
+ (*_node_data)[ni].heap_index.insert(std::make_pair(vt, e));
+ }
+ }
+ }
+
+ if (!(*_node_data)[ni].heap.empty()) {
+ _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
+ _delta2->push(nb, _blossom_set->classPrio(nb));
+ }
+ }
+ }
+
+ /// \brief Start the algorithm
+ ///
+ /// This function starts the algorithm.
+ ///
+ /// \pre \ref init() or \ref fractionalInit() must be called
+ /// before using this function.
+ void start() {
+ enum OpType {
+ D1, D2, D3, D4
+ };
+
+ while (_unmatched > 0) {
+ Value d1 = !_delta1->empty() ?
+ _delta1->prio() : std::numeric_limits<Value>::max();
+
+ Value d2 = !_delta2->empty() ?
+ _delta2->prio() : std::numeric_limits<Value>::max();
+
+ Value d3 = !_delta3->empty() ?
+ _delta3->prio() : std::numeric_limits<Value>::max();
+
+ Value d4 = !_delta4->empty() ?
+ _delta4->prio() : std::numeric_limits<Value>::max();
+
+ _delta_sum = d3; OpType ot = D3;
+ if (d1 < _delta_sum) { _delta_sum = d1; ot = D1; }
+ if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
+ if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
+
+ switch (ot) {
+ case D1:
+ {
+ Node n = _delta1->top();
+ unmatchNode(n);
+ --_unmatched;
+ }
+ break;
+ case D2:
+ {
+ int blossom = _delta2->top();
+ Node n = _blossom_set->classTop(blossom);
+ Arc a = (*_node_data)[(*_node_index)[n]].heap.top();
+ if ((*_blossom_data)[blossom].next == INVALID) {
+ augmentOnArc(a);
+ --_unmatched;
+ } else {
+ extendOnArc(a);
+ }
+ }
+ break;
+ case D3:
+ {
+ Edge e = _delta3->top();
+
+ int left_blossom = _blossom_set->find(_graph.u(e));
+ int right_blossom = _blossom_set->find(_graph.v(e));
+
+ if (left_blossom == right_blossom) {
+ _delta3->pop();
+ } else {
+ int left_tree = _tree_set->find(left_blossom);
+ int right_tree = _tree_set->find(right_blossom);
+
+ if (left_tree == right_tree) {
+ shrinkOnEdge(e, left_tree);
+ } else {
+ augmentOnEdge(e);
+ _unmatched -= 2;
+ }
+ }
+ } break;
+ case D4:
+ splitBlossom(_delta4->top());
+ break;
+ }
+ }
+ extractMatching();
+ }
+
+ /// \brief Run the algorithm.
+ ///
+ /// This method runs the \c %MaxWeightedMatching algorithm.
+ ///
+ /// \note mwm.run() is just a shortcut of the following code.
+ /// \code
+ /// mwm.fractionalInit();
+ /// mwm.start();
+ /// \endcode
+ void run() {
+ fractionalInit();
+ start();
+ }
+
+ /// @}
+
+ /// \name Primal Solution
+ /// Functions to get the primal solution, i.e. the maximum weighted
+ /// matching.\n
+ /// Either \ref run() or \ref start() function should be called before
+ /// using them.
+
+ /// @{
+
+ /// \brief Return the weight of the matching.
+ ///
+ /// This function returns the weight of the found matching.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Value matchingWeight() const {
+ Value sum = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if ((*_matching)[n] != INVALID) {
+ sum += _weight[(*_matching)[n]];
+ }
+ }
+ return sum / 2;
+ }
+
+ /// \brief Return the size (cardinality) of the matching.
+ ///
+ /// This function returns the size (cardinality) of the found matching.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ int matchingSize() const {
+ int num = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if ((*_matching)[n] != INVALID) {
+ ++num;
+ }
+ }
+ return num /= 2;
+ }
+
+ /// \brief Return \c true if the given edge is in the matching.
+ ///
+ /// This function returns \c true if the given edge is in the found
+ /// matching.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ bool matching(const Edge& edge) const {
+ return edge == (*_matching)[_graph.u(edge)];
+ }
+
+ /// \brief Return the matching arc (or edge) incident to the given node.
+ ///
+ /// This function returns the matching arc (or edge) incident to the
+ /// given node in the found matching or \c INVALID if the node is
+ /// not covered by the matching.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Arc matching(const Node& node) const {
+ return (*_matching)[node];
+ }
+
+ /// \brief Return a const reference to the matching map.
+ ///
+ /// This function returns a const reference to a node map that stores
+ /// the matching arc (or edge) incident to each node.
+ const MatchingMap& matchingMap() const {
+ return *_matching;
+ }
+
+ /// \brief Return the mate of the given node.
+ ///
+ /// This function returns the mate of the given node in the found
+ /// matching or \c INVALID if the node is not covered by the matching.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Node mate(const Node& node) const {
+ return (*_matching)[node] != INVALID ?
+ _graph.target((*_matching)[node]) : INVALID;
+ }
+
+ /// @}
+
+ /// \name Dual Solution
+ /// Functions to get the dual solution.\n
+ /// Either \ref run() or \ref start() function should be called before
+ /// using them.
+
+ /// @{
+
+ /// \brief Return the value of the dual solution.
+ ///
+ /// This function returns the value of the dual solution.
+ /// It should be equal to the primal value scaled by \ref dualScale
+ /// "dual scale".
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Value dualValue() const {
+ Value sum = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ sum += nodeValue(n);
+ }
+ for (int i = 0; i < blossomNum(); ++i) {
+ sum += blossomValue(i) * (blossomSize(i) / 2);
+ }
+ return sum;
+ }
+
+ /// \brief Return the dual value (potential) of the given node.
+ ///
+ /// This function returns the dual value (potential) of the given node.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Value nodeValue(const Node& n) const {
+ return (*_node_potential)[n];
+ }
+
+ /// \brief Return the number of the blossoms in the basis.
+ ///
+ /// This function returns the number of the blossoms in the basis.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ /// \see BlossomIt
+ int blossomNum() const {
+ return _blossom_potential.size();
+ }
+
+ /// \brief Return the number of the nodes in the given blossom.
+ ///
+ /// This function returns the number of the nodes in the given blossom.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ /// \see BlossomIt
+ int blossomSize(int k) const {
+ return _blossom_potential[k].end - _blossom_potential[k].begin;
+ }
+
+ /// \brief Return the dual value (ptential) of the given blossom.
+ ///
+ /// This function returns the dual value (ptential) of the given blossom.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Value blossomValue(int k) const {
+ return _blossom_potential[k].value;
+ }
+
+ /// \brief Iterator for obtaining the nodes of a blossom.
+ ///
+ /// This class provides an iterator for obtaining the nodes of the
+ /// given blossom. It lists a subset of the nodes.
+ /// Before using this iterator, you must allocate a
+ /// MaxWeightedMatching class and execute it.
+ class BlossomIt {
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor to get the nodes of the given variable.
+ ///
+ /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or
+ /// \ref MaxWeightedMatching::start() "algorithm.start()" must be
+ /// called before initializing this iterator.
+ BlossomIt(const MaxWeightedMatching& algorithm, int variable)
+ : _algorithm(&algorithm)
+ {
+ _index = _algorithm->_blossom_potential[variable].begin;
+ _last = _algorithm->_blossom_potential[variable].end;
+ }
+
+ /// \brief Conversion to \c Node.
+ ///
+ /// Conversion to \c Node.
+ operator Node() const {
+ return _algorithm->_blossom_node_list[_index];
+ }
+
+ /// \brief Increment operator.
+ ///
+ /// Increment operator.
+ BlossomIt& operator++() {
+ ++_index;
+ return *this;
+ }
+
+ /// \brief Validity checking
+ ///
+ /// Checks whether the iterator is invalid.
+ bool operator==(Invalid) const { return _index == _last; }
+
+ /// \brief Validity checking
+ ///
+ /// Checks whether the iterator is valid.
+ bool operator!=(Invalid) const { return _index != _last; }
+
+ private:
+ const MaxWeightedMatching* _algorithm;
+ int _last;
+ int _index;
+ };
+
+ /// @}
+
+ };
+
+ /// \ingroup matching
+ ///
+ /// \brief Weighted perfect matching in general graphs
+ ///
+ /// This class provides an efficient implementation of Edmond's
+ /// maximum weighted perfect matching algorithm. The implementation
+ /// is based on extensive use of priority queues and provides
+ /// \f$O(nm\log n)\f$ time complexity.
+ ///
+ /// The maximum weighted perfect matching problem is to find a subset of
+ /// the edges in an undirected graph with maximum overall weight for which
+ /// each node has exactly one incident edge.
+ /// It can be formulated with the following linear program.
+ /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
+ /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
+ \quad \forall B\in\mathcal{O}\f] */
+ /// \f[x_e \ge 0\quad \forall e\in E\f]
+ /// \f[\max \sum_{e\in E}x_ew_e\f]
+ /// where \f$\delta(X)\f$ is the set of edges incident to a node in
+ /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
+ /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
+ /// subsets of the nodes.
+ ///
+ /// The algorithm calculates an optimal matching and a proof of the
+ /// optimality. The solution of the dual problem can be used to check
+ /// the result of the algorithm. The dual linear problem is the
+ /// following.
+ /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
+ w_{uv} \quad \forall uv\in E\f] */
+ /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
+ /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
+ \frac{\vert B \vert - 1}{2}z_B\f] */
+ ///
+ /// The algorithm can be executed with the run() function.
+ /// After it the matching (the primal solution) and the dual solution
+ /// can be obtained using the query functions and the
+ /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class,
+ /// which is able to iterate on the nodes of a blossom.
+ /// If the value type is integer, then the dual solution is multiplied
+ /// by \ref MaxWeightedMatching::dualScale "4".
+ ///
+ /// \tparam GR The undirected graph type the algorithm runs on.
+ /// \tparam WM The type edge weight map. The default type is
+ /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
+#ifdef DOXYGEN
+ template <typename GR, typename WM>
+#else
+ template <typename GR,
+ typename WM = typename GR::template EdgeMap<int> >
+#endif
+ class MaxWeightedPerfectMatching {
+ public:
+
+ /// The graph type of the algorithm
+ typedef GR Graph;
+ /// The type of the edge weight map
+ typedef WM WeightMap;
+ /// The value type of the edge weights
+ typedef typename WeightMap::Value Value;
+
+ /// \brief Scaling factor for dual solution
+ ///
+ /// Scaling factor for dual solution, it is equal to 4 or 1
+ /// according to the value type.
+ static const int dualScale =
+ std::numeric_limits<Value>::is_integer ? 4 : 1;
+
+ /// The type of the matching map
+ typedef typename Graph::template NodeMap<typename Graph::Arc>
+ MatchingMap;
+
+ private:
+
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+ typedef typename Graph::template NodeMap<Value> NodePotential;
+ typedef std::vector<Node> BlossomNodeList;
+
+ struct BlossomVariable {
+ int begin, end;
+ Value value;
+
+ BlossomVariable(int _begin, int _end, Value _value)
+ : begin(_begin), end(_end), value(_value) {}
+
+ };
+
+ typedef std::vector<BlossomVariable> BlossomPotential;
+
+ const Graph& _graph;
+ const WeightMap& _weight;
+
+ MatchingMap* _matching;
+
+ NodePotential* _node_potential;
+
+ BlossomPotential _blossom_potential;
+ BlossomNodeList _blossom_node_list;
+
+ int _node_num;
+ int _blossom_num;
+
+ typedef RangeMap<int> IntIntMap;
+
+ enum Status {
+ EVEN = -1, MATCHED = 0, ODD = 1
+ };
+
+ typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
+ struct BlossomData {
+ int tree;
+ Status status;
+ Arc pred, next;
+ Value pot, offset;
+ };
+
+ IntNodeMap *_blossom_index;
+ BlossomSet *_blossom_set;
+ RangeMap<BlossomData>* _blossom_data;
+
+ IntNodeMap *_node_index;
+ IntArcMap *_node_heap_index;
+
+ struct NodeData {
+
+ NodeData(IntArcMap& node_heap_index)
+ : heap(node_heap_index) {}
+
+ int blossom;
+ Value pot;
+ BinHeap<Value, IntArcMap> heap;
+ std::map<int, Arc> heap_index;
+
+ int tree;
+ };
+
+ RangeMap<NodeData>* _node_data;
+
+ typedef ExtendFindEnum<IntIntMap> TreeSet;
+
+ IntIntMap *_tree_set_index;
+ TreeSet *_tree_set;
+
+ IntIntMap *_delta2_index;
+ BinHeap<Value, IntIntMap> *_delta2;
+
+ IntEdgeMap *_delta3_index;
+ BinHeap<Value, IntEdgeMap> *_delta3;
+
+ IntIntMap *_delta4_index;
+ BinHeap<Value, IntIntMap> *_delta4;
+
+ Value _delta_sum;
+ int _unmatched;
+
+ typedef MaxWeightedPerfectFractionalMatching<Graph, WeightMap>
+ FractionalMatching;
+ FractionalMatching *_fractional;
+
+ void createStructures() {
+ _node_num = countNodes(_graph);
+ _blossom_num = _node_num * 3 / 2;
+
+ if (!_matching) {
+ _matching = new MatchingMap(_graph);
+ }
+
+ if (!_node_potential) {
+ _node_potential = new NodePotential(_graph);
+ }
+
+ if (!_blossom_set) {
+ _blossom_index = new IntNodeMap(_graph);
+ _blossom_set = new BlossomSet(*_blossom_index);
+ _blossom_data = new RangeMap<BlossomData>(_blossom_num);
+ } else if (_blossom_data->size() != _blossom_num) {
+ delete _blossom_data;
+ _blossom_data = new RangeMap<BlossomData>(_blossom_num);
+ }
+
+ if (!_node_index) {
+ _node_index = new IntNodeMap(_graph);
+ _node_heap_index = new IntArcMap(_graph);
+ _node_data = new RangeMap<NodeData>(_node_num,
+ NodeData(*_node_heap_index));
+ } else if (_node_data->size() != _node_num) {
+ delete _node_data;
+ _node_data = new RangeMap<NodeData>(_node_num,
+ NodeData(*_node_heap_index));
+ }
+
+ if (!_tree_set) {
+ _tree_set_index = new IntIntMap(_blossom_num);
+ _tree_set = new TreeSet(*_tree_set_index);
+ } else {
+ _tree_set_index->resize(_blossom_num);
+ }
+
+ if (!_delta2) {
+ _delta2_index = new IntIntMap(_blossom_num);
+ _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
+ } else {
+ _delta2_index->resize(_blossom_num);
+ }
+
+ if (!_delta3) {
+ _delta3_index = new IntEdgeMap(_graph);
+ _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
+ }
+
+ if (!_delta4) {
+ _delta4_index = new IntIntMap(_blossom_num);
+ _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
+ } else {
+ _delta4_index->resize(_blossom_num);
+ }
+ }
+
+ void destroyStructures() {
+ if (_matching) {
+ delete _matching;
+ }
+ if (_node_potential) {
+ delete _node_potential;
+ }
+ if (_blossom_set) {
+ delete _blossom_index;
+ delete _blossom_set;
+ delete _blossom_data;
+ }
+
+ if (_node_index) {
+ delete _node_index;
+ delete _node_heap_index;
+ delete _node_data;
+ }
+
+ if (_tree_set) {
+ delete _tree_set_index;
+ delete _tree_set;
+ }
+ if (_delta2) {
+ delete _delta2_index;
+ delete _delta2;
+ }
+ if (_delta3) {
+ delete _delta3_index;
+ delete _delta3;
+ }
+ if (_delta4) {
+ delete _delta4_index;
+ delete _delta4;
+ }
+ }
+
+ void matchedToEven(int blossom, int tree) {
+ if (_delta2->state(blossom) == _delta2->IN_HEAP) {
+ _delta2->erase(blossom);
+ }
+
+ if (!_blossom_set->trivial(blossom)) {
+ (*_blossom_data)[blossom].pot -=
+ 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
+ }
+
+ for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
+ n != INVALID; ++n) {
+
+ _blossom_set->increase(n, std::numeric_limits<Value>::max());
+ int ni = (*_node_index)[n];
+
+ (*_node_data)[ni].heap.clear();
+ (*_node_data)[ni].heap_index.clear();
+
+ (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
+
+ for (InArcIt e(_graph, n); e != INVALID; ++e) {
+ Node v = _graph.source(e);
+ int vb = _blossom_set->find(v);
+ int vi = (*_node_index)[v];
+
+ Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
+ dualScale * _weight[e];
+
+ if ((*_blossom_data)[vb].status == EVEN) {
+ if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
+ _delta3->push(e, rw / 2);
+ }
+ } else {
+ typename std::map<int, Arc>::iterator it =
+ (*_node_data)[vi].heap_index.find(tree);
+
+ if (it != (*_node_data)[vi].heap_index.end()) {
+ if ((*_node_data)[vi].heap[it->second] > rw) {
+ (*_node_data)[vi].heap.replace(it->second, e);
+ (*_node_data)[vi].heap.decrease(e, rw);
+ it->second = e;
+ }
+ } else {
+ (*_node_data)[vi].heap.push(e, rw);
+ (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
+ }
+
+ if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
+ _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
+
+ if ((*_blossom_data)[vb].status == MATCHED) {
+ if (_delta2->state(vb) != _delta2->IN_HEAP) {
+ _delta2->push(vb, _blossom_set->classPrio(vb) -
+ (*_blossom_data)[vb].offset);
+ } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
+ (*_blossom_data)[vb].offset){
+ _delta2->decrease(vb, _blossom_set->classPrio(vb) -
+ (*_blossom_data)[vb].offset);
+ }
+ }
+ }
+ }
+ }
+ }
+ (*_blossom_data)[blossom].offset = 0;
+ }
+
+ void matchedToOdd(int blossom) {
+ if (_delta2->state(blossom) == _delta2->IN_HEAP) {
+ _delta2->erase(blossom);
+ }
+ (*_blossom_data)[blossom].offset += _delta_sum;
+ if (!_blossom_set->trivial(blossom)) {
+ _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
+ (*_blossom_data)[blossom].offset);
+ }
+ }
+
+ void evenToMatched(int blossom, int tree) {
+ if (!_blossom_set->trivial(blossom)) {
+ (*_blossom_data)[blossom].pot += 2 * _delta_sum;
+ }
+
+ for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
+ n != INVALID; ++n) {
+ int ni = (*_node_index)[n];
+ (*_node_data)[ni].pot -= _delta_sum;
+
+ for (InArcIt e(_graph, n); e != INVALID; ++e) {
+ Node v = _graph.source(e);
+ int vb = _blossom_set->find(v);
+ int vi = (*_node_index)[v];
+
+ Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
+ dualScale * _weight[e];
+
+ if (vb == blossom) {
+ if (_delta3->state(e) == _delta3->IN_HEAP) {
+ _delta3->erase(e);
+ }
+ } else if ((*_blossom_data)[vb].status == EVEN) {
+
+ if (_delta3->state(e) == _delta3->IN_HEAP) {
+ _delta3->erase(e);
+ }
+
+ int vt = _tree_set->find(vb);
+
+ if (vt != tree) {
+
+ Arc r = _graph.oppositeArc(e);
+
+ typename std::map<int, Arc>::iterator it =
+ (*_node_data)[ni].heap_index.find(vt);
+
+ if (it != (*_node_data)[ni].heap_index.end()) {
+ if ((*_node_data)[ni].heap[it->second] > rw) {
+ (*_node_data)[ni].heap.replace(it->second, r);
+ (*_node_data)[ni].heap.decrease(r, rw);
+ it->second = r;
+ }
+ } else {
+ (*_node_data)[ni].heap.push(r, rw);
+ (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
+ }
+
+ if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
+ _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
+
+ if (_delta2->state(blossom) != _delta2->IN_HEAP) {
+ _delta2->push(blossom, _blossom_set->classPrio(blossom) -
+ (*_blossom_data)[blossom].offset);
+ } else if ((*_delta2)[blossom] >
+ _blossom_set->classPrio(blossom) -
+ (*_blossom_data)[blossom].offset){
+ _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
+ (*_blossom_data)[blossom].offset);
+ }
+ }
+ }
+ } else {
+
+ typename std::map<int, Arc>::iterator it =
+ (*_node_data)[vi].heap_index.find(tree);
+
+ if (it != (*_node_data)[vi].heap_index.end()) {
+ (*_node_data)[vi].heap.erase(it->second);
+ (*_node_data)[vi].heap_index.erase(it);
+ if ((*_node_data)[vi].heap.empty()) {
+ _blossom_set->increase(v, std::numeric_limits<Value>::max());
+ } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
+ _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
+ }
+
+ if ((*_blossom_data)[vb].status == MATCHED) {
+ if (_blossom_set->classPrio(vb) ==
+ std::numeric_limits<Value>::max()) {
+ _delta2->erase(vb);
+ } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
+ (*_blossom_data)[vb].offset) {
+ _delta2->increase(vb, _blossom_set->classPrio(vb) -
+ (*_blossom_data)[vb].offset);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void oddToMatched(int blossom) {
+ (*_blossom_data)[blossom].offset -= _delta_sum;
+
+ if (_blossom_set->classPrio(blossom) !=
+ std::numeric_limits<Value>::max()) {
+ _delta2->push(blossom, _blossom_set->classPrio(blossom) -
+ (*_blossom_data)[blossom].offset);
+ }
+
+ if (!_blossom_set->trivial(blossom)) {
+ _delta4->erase(blossom);
+ }
+ }
+
+ void oddToEven(int blossom, int tree) {
+ if (!_blossom_set->trivial(blossom)) {
+ _delta4->erase(blossom);
+ (*_blossom_data)[blossom].pot -=
+ 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
+ }
+
+ for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
+ n != INVALID; ++n) {
+ int ni = (*_node_index)[n];
+
+ _blossom_set->increase(n, std::numeric_limits<Value>::max());
+
+ (*_node_data)[ni].heap.clear();
+ (*_node_data)[ni].heap_index.clear();
+ (*_node_data)[ni].pot +=
+ 2 * _delta_sum - (*_blossom_data)[blossom].offset;
+
+ for (InArcIt e(_graph, n); e != INVALID; ++e) {
+ Node v = _graph.source(e);
+ int vb = _blossom_set->find(v);
+ int vi = (*_node_index)[v];
+
+ Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
+ dualScale * _weight[e];
+
+ if ((*_blossom_data)[vb].status == EVEN) {
+ if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
+ _delta3->push(e, rw / 2);
+ }
+ } else {
+
+ typename std::map<int, Arc>::iterator it =
+ (*_node_data)[vi].heap_index.find(tree);
+
+ if (it != (*_node_data)[vi].heap_index.end()) {
+ if ((*_node_data)[vi].heap[it->second] > rw) {
+ (*_node_data)[vi].heap.replace(it->second, e);
+ (*_node_data)[vi].heap.decrease(e, rw);
+ it->second = e;
+ }
+ } else {
+ (*_node_data)[vi].heap.push(e, rw);
+ (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
+ }
+
+ if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
+ _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
+
+ if ((*_blossom_data)[vb].status == MATCHED) {
+ if (_delta2->state(vb) != _delta2->IN_HEAP) {
+ _delta2->push(vb, _blossom_set->classPrio(vb) -
+ (*_blossom_data)[vb].offset);
+ } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
+ (*_blossom_data)[vb].offset) {
+ _delta2->decrease(vb, _blossom_set->classPrio(vb) -
+ (*_blossom_data)[vb].offset);
+ }
+ }
+ }
+ }
+ }
+ }
+ (*_blossom_data)[blossom].offset = 0;
+ }
+
+ void alternatePath(int even, int tree) {
+ int odd;
+
+ evenToMatched(even, tree);
+ (*_blossom_data)[even].status = MATCHED;
+
+ while ((*_blossom_data)[even].pred != INVALID) {
+ odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
+ (*_blossom_data)[odd].status = MATCHED;
+ oddToMatched(odd);
+ (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
+
+ even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
+ (*_blossom_data)[even].status = MATCHED;
+ evenToMatched(even, tree);
+ (*_blossom_data)[even].next =
+ _graph.oppositeArc((*_blossom_data)[odd].pred);
+ }
+
+ }
+
+ void destroyTree(int tree) {
+ for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
+ if ((*_blossom_data)[b].status == EVEN) {
+ (*_blossom_data)[b].status = MATCHED;
+ evenToMatched(b, tree);
+ } else if ((*_blossom_data)[b].status == ODD) {
+ (*_blossom_data)[b].status = MATCHED;
+ oddToMatched(b);
+ }
+ }
+ _tree_set->eraseClass(tree);
+ }
+
+ void augmentOnEdge(const Edge& edge) {
+
+ int left = _blossom_set->find(_graph.u(edge));
+ int right = _blossom_set->find(_graph.v(edge));
+
+ int left_tree = _tree_set->find(left);
+ alternatePath(left, left_tree);
+ destroyTree(left_tree);
+
+ int right_tree = _tree_set->find(right);
+ alternatePath(right, right_tree);
+ destroyTree(right_tree);
+
+ (*_blossom_data)[left].next = _graph.direct(edge, true);
+ (*_blossom_data)[right].next = _graph.direct(edge, false);
+ }
+
+ void extendOnArc(const Arc& arc) {
+ int base = _blossom_set->find(_graph.target(arc));
+ int tree = _tree_set->find(base);
+
+ int odd = _blossom_set->find(_graph.source(arc));
+ _tree_set->insert(odd, tree);
+ (*_blossom_data)[odd].status = ODD;
+ matchedToOdd(odd);
+ (*_blossom_data)[odd].pred = arc;
+
+ int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
+ (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
+ _tree_set->insert(even, tree);
+ (*_blossom_data)[even].status = EVEN;
+ matchedToEven(even, tree);
+ }
+
+ void shrinkOnEdge(const Edge& edge, int tree) {
+ int nca = -1;
+ std::vector<int> left_path, right_path;
+
+ {
+ std::set<int> left_set, right_set;
+ int left = _blossom_set->find(_graph.u(edge));
+ left_path.push_back(left);
+ left_set.insert(left);
+
+ int right = _blossom_set->find(_graph.v(edge));
+ right_path.push_back(right);
+ right_set.insert(right);
+
+ while (true) {
+
+ if ((*_blossom_data)[left].pred == INVALID) break;
+
+ left =
+ _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
+ left_path.push_back(left);
+ left =
+ _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
+ left_path.push_back(left);
+
+ left_set.insert(left);
+
+ if (right_set.find(left) != right_set.end()) {
+ nca = left;
+ break;
+ }
+
+ if ((*_blossom_data)[right].pred == INVALID) break;
+
+ right =
+ _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
+ right_path.push_back(right);
+ right =
+ _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
+ right_path.push_back(right);
+
+ right_set.insert(right);
+
+ if (left_set.find(right) != left_set.end()) {
+ nca = right;
+ break;
+ }
+
+ }
+
+ if (nca == -1) {
+ if ((*_blossom_data)[left].pred == INVALID) {
+ nca = right;
+ while (left_set.find(nca) == left_set.end()) {
+ nca =
+ _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
+ right_path.push_back(nca);
+ nca =
+ _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
+ right_path.push_back(nca);
+ }
+ } else {
+ nca = left;
+ while (right_set.find(nca) == right_set.end()) {
+ nca =
+ _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
+ left_path.push_back(nca);
+ nca =
+ _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
+ left_path.push_back(nca);
+ }
+ }
+ }
+ }
+
+ std::vector<int> subblossoms;
+ Arc prev;
+
+ prev = _graph.direct(edge, true);
+ for (int i = 0; left_path[i] != nca; i += 2) {
+ subblossoms.push_back(left_path[i]);
+ (*_blossom_data)[left_path[i]].next = prev;
+ _tree_set->erase(left_path[i]);
+
+ subblossoms.push_back(left_path[i + 1]);
+ (*_blossom_data)[left_path[i + 1]].status = EVEN;
+ oddToEven(left_path[i + 1], tree);
+ _tree_set->erase(left_path[i + 1]);
+ prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
+ }
+
+ int k = 0;
+ while (right_path[k] != nca) ++k;
+
+ subblossoms.push_back(nca);
+ (*_blossom_data)[nca].next = prev;
+
+ for (int i = k - 2; i >= 0; i -= 2) {
+ subblossoms.push_back(right_path[i + 1]);
+ (*_blossom_data)[right_path[i + 1]].status = EVEN;
+ oddToEven(right_path[i + 1], tree);
+ _tree_set->erase(right_path[i + 1]);
+
+ (*_blossom_data)[right_path[i + 1]].next =
+ (*_blossom_data)[right_path[i + 1]].pred;
+
+ subblossoms.push_back(right_path[i]);
+ _tree_set->erase(right_path[i]);
+ }
+
+ int surface =
+ _blossom_set->join(subblossoms.begin(), subblossoms.end());
+
+ for (int i = 0; i < int(subblossoms.size()); ++i) {
+ if (!_blossom_set->trivial(subblossoms[i])) {
+ (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
+ }
+ (*_blossom_data)[subblossoms[i]].status = MATCHED;
+ }
+
+ (*_blossom_data)[surface].pot = -2 * _delta_sum;
+ (*_blossom_data)[surface].offset = 0;
+ (*_blossom_data)[surface].status = EVEN;
+ (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
+ (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
+
+ _tree_set->insert(surface, tree);
+ _tree_set->erase(nca);
+ }
+
+ void splitBlossom(int blossom) {
+ Arc next = (*_blossom_data)[blossom].next;
+ Arc pred = (*_blossom_data)[blossom].pred;
+
+ int tree = _tree_set->find(blossom);
+
+ (*_blossom_data)[blossom].status = MATCHED;
+ oddToMatched(blossom);
+ if (_delta2->state(blossom) == _delta2->IN_HEAP) {
+ _delta2->erase(blossom);
+ }
+
+ std::vector<int> subblossoms;
+ _blossom_set->split(blossom, std::back_inserter(subblossoms));
+
+ Value offset = (*_blossom_data)[blossom].offset;
+ int b = _blossom_set->find(_graph.source(pred));
+ int d = _blossom_set->find(_graph.source(next));
+
+ int ib = -1, id = -1;
+ for (int i = 0; i < int(subblossoms.size()); ++i) {
+ if (subblossoms[i] == b) ib = i;
+ if (subblossoms[i] == d) id = i;
+
+ (*_blossom_data)[subblossoms[i]].offset = offset;
+ if (!_blossom_set->trivial(subblossoms[i])) {
+ (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
+ }
+ if (_blossom_set->classPrio(subblossoms[i]) !=
+ std::numeric_limits<Value>::max()) {
+ _delta2->push(subblossoms[i],
+ _blossom_set->classPrio(subblossoms[i]) -
+ (*_blossom_data)[subblossoms[i]].offset);
+ }
+ }
+
+ if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
+ for (int i = (id + 1) % subblossoms.size();
+ i != ib; i = (i + 2) % subblossoms.size()) {
+ int sb = subblossoms[i];
+ int tb = subblossoms[(i + 1) % subblossoms.size()];
+ (*_blossom_data)[sb].next =
+ _graph.oppositeArc((*_blossom_data)[tb].next);
+ }
+
+ for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
+ int sb = subblossoms[i];
+ int tb = subblossoms[(i + 1) % subblossoms.size()];
+ int ub = subblossoms[(i + 2) % subblossoms.size()];
+
+ (*_blossom_data)[sb].status = ODD;
+ matchedToOdd(sb);
+ _tree_set->insert(sb, tree);
+ (*_blossom_data)[sb].pred = pred;
+ (*_blossom_data)[sb].next =
+ _graph.oppositeArc((*_blossom_data)[tb].next);
+
+ pred = (*_blossom_data)[ub].next;
+
+ (*_blossom_data)[tb].status = EVEN;
+ matchedToEven(tb, tree);
+ _tree_set->insert(tb, tree);
+ (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
+ }
+
+ (*_blossom_data)[subblossoms[id]].status = ODD;
+ matchedToOdd(subblossoms[id]);
+ _tree_set->insert(subblossoms[id], tree);
+ (*_blossom_data)[subblossoms[id]].next = next;
+ (*_blossom_data)[subblossoms[id]].pred = pred;
+
+ } else {
+
+ for (int i = (ib + 1) % subblossoms.size();
+ i != id; i = (i + 2) % subblossoms.size()) {
+ int sb = subblossoms[i];
+ int tb = subblossoms[(i + 1) % subblossoms.size()];
+ (*_blossom_data)[sb].next =
+ _graph.oppositeArc((*_blossom_data)[tb].next);
+ }
+
+ for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
+ int sb = subblossoms[i];
+ int tb = subblossoms[(i + 1) % subblossoms.size()];
+ int ub = subblossoms[(i + 2) % subblossoms.size()];
+
+ (*_blossom_data)[sb].status = ODD;
+ matchedToOdd(sb);
+ _tree_set->insert(sb, tree);
+ (*_blossom_data)[sb].next = next;
+ (*_blossom_data)[sb].pred =
+ _graph.oppositeArc((*_blossom_data)[tb].next);
+
+ (*_blossom_data)[tb].status = EVEN;
+ matchedToEven(tb, tree);
+ _tree_set->insert(tb, tree);
+ (*_blossom_data)[tb].pred =
+ (*_blossom_data)[tb].next =
+ _graph.oppositeArc((*_blossom_data)[ub].next);
+ next = (*_blossom_data)[ub].next;
+ }
+
+ (*_blossom_data)[subblossoms[ib]].status = ODD;
+ matchedToOdd(subblossoms[ib]);
+ _tree_set->insert(subblossoms[ib], tree);
+ (*_blossom_data)[subblossoms[ib]].next = next;
+ (*_blossom_data)[subblossoms[ib]].pred = pred;
+ }
+ _tree_set->erase(blossom);
+ }
+
+ void extractBlossom(int blossom, const Node& base, const Arc& matching) {
+ if (_blossom_set->trivial(blossom)) {
+ int bi = (*_node_index)[base];
+ Value pot = (*_node_data)[bi].pot;
+
+ (*_matching)[base] = matching;
+ _blossom_node_list.push_back(base);
+ (*_node_potential)[base] = pot;
+ } else {
+
+ Value pot = (*_blossom_data)[blossom].pot;
+ int bn = _blossom_node_list.size();
+
+ std::vector<int> subblossoms;
+ _blossom_set->split(blossom, std::back_inserter(subblossoms));
+ int b = _blossom_set->find(base);
+ int ib = -1;
+ for (int i = 0; i < int(subblossoms.size()); ++i) {
+ if (subblossoms[i] == b) { ib = i; break; }
+ }
+
+ for (int i = 1; i < int(subblossoms.size()); i += 2) {
+ int sb = subblossoms[(ib + i) % subblossoms.size()];
+ int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
+
+ Arc m = (*_blossom_data)[tb].next;
+ extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
+ extractBlossom(tb, _graph.source(m), m);
+ }
+ extractBlossom(subblossoms[ib], base, matching);
+
+ int en = _blossom_node_list.size();
+
+ _blossom_potential.push_back(BlossomVariable(bn, en, pot));
+ }
+ }
+
+ void extractMatching() {
+ std::vector<int> blossoms;
+ for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
+ blossoms.push_back(c);
+ }
+
+ for (int i = 0; i < int(blossoms.size()); ++i) {
+
+ Value offset = (*_blossom_data)[blossoms[i]].offset;
+ (*_blossom_data)[blossoms[i]].pot += 2 * offset;
+ for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
+ n != INVALID; ++n) {
+ (*_node_data)[(*_node_index)[n]].pot -= offset;
+ }
+
+ Arc matching = (*_blossom_data)[blossoms[i]].next;
+ Node base = _graph.source(matching);
+ extractBlossom(blossoms[i], base, matching);
+ }
+ }
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
+ : _graph(graph), _weight(weight), _matching(0),
+ _node_potential(0), _blossom_potential(), _blossom_node_list(),
+ _node_num(0), _blossom_num(0),
+
+ _blossom_index(0), _blossom_set(0), _blossom_data(0),
+ _node_index(0), _node_heap_index(0), _node_data(0),
+ _tree_set_index(0), _tree_set(0),
+
+ _delta2_index(0), _delta2(0),
+ _delta3_index(0), _delta3(0),
+ _delta4_index(0), _delta4(0),
+
+ _delta_sum(), _unmatched(0),
+
+ _fractional(0)
+ {}
+
+ ~MaxWeightedPerfectMatching() {
+ destroyStructures();
+ if (_fractional) {
+ delete _fractional;
+ }
+ }
+
+ /// \name Execution Control
+ /// The simplest way to execute the algorithm is to use the
+ /// \ref run() member function.
+
+ ///@{
+
+ /// \brief Initialize the algorithm
+ ///
+ /// This function initializes the algorithm.
+ void init() {
+ createStructures();
+
+ _blossom_node_list.clear();
+ _blossom_potential.clear();
+
+ for (ArcIt e(_graph); e != INVALID; ++e) {
+ (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
+ }
+ for (EdgeIt e(_graph); e != INVALID; ++e) {
+ (*_delta3_index)[e] = _delta3->PRE_HEAP;
+ }
+ for (int i = 0; i < _blossom_num; ++i) {
+ (*_delta2_index)[i] = _delta2->PRE_HEAP;
+ (*_delta4_index)[i] = _delta4->PRE_HEAP;
+ }
+
+ _unmatched = _node_num;
+
+ _delta2->clear();
+ _delta3->clear();
+ _delta4->clear();
+ _blossom_set->clear();
+ _tree_set->clear();
+
+ int index = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ Value max = - std::numeric_limits<Value>::max();
+ for (OutArcIt e(_graph, n); e != INVALID; ++e) {
+ if (_graph.target(e) == n) continue;
+ if ((dualScale * _weight[e]) / 2 > max) {
+ max = (dualScale * _weight[e]) / 2;
+ }
+ }
+ (*_node_index)[n] = index;
+ (*_node_data)[index].heap_index.clear();
+ (*_node_data)[index].heap.clear();
+ (*_node_data)[index].pot = max;
+ int blossom =
+ _blossom_set->insert(n, std::numeric_limits<Value>::max());
+
+ _tree_set->insert(blossom);
+
+ (*_blossom_data)[blossom].status = EVEN;
+ (*_blossom_data)[blossom].pred = INVALID;
+ (*_blossom_data)[blossom].next = INVALID;
+ (*_blossom_data)[blossom].pot = 0;
+ (*_blossom_data)[blossom].offset = 0;
+ ++index;
+ }
+ for (EdgeIt e(_graph); e != INVALID; ++e) {
+ int si = (*_node_index)[_graph.u(e)];
+ int ti = (*_node_index)[_graph.v(e)];
+ if (_graph.u(e) != _graph.v(e)) {
+ _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
+ dualScale * _weight[e]) / 2);
+ }
+ }
+ }
+
+ /// \brief Initialize the algorithm with fractional matching
+ ///
+ /// This function initializes the algorithm with a fractional
+ /// matching. This initialization is also called jumpstart heuristic.
+ void fractionalInit() {
+ createStructures();
+
+ _blossom_node_list.clear();
+ _blossom_potential.clear();
+
+ if (_fractional == 0) {
+ _fractional = new FractionalMatching(_graph, _weight, false);
+ }
+ if (!_fractional->run()) {
+ _unmatched = -1;
+ return;
+ }
+
+ for (ArcIt e(_graph); e != INVALID; ++e) {
+ (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
+ }
+ for (EdgeIt e(_graph); e != INVALID; ++e) {
+ (*_delta3_index)[e] = _delta3->PRE_HEAP;
+ }
+ for (int i = 0; i < _blossom_num; ++i) {
+ (*_delta2_index)[i] = _delta2->PRE_HEAP;
+ (*_delta4_index)[i] = _delta4->PRE_HEAP;
+ }
+
+ _unmatched = 0;
+
+ _delta2->clear();
+ _delta3->clear();
+ _delta4->clear();
+ _blossom_set->clear();
+ _tree_set->clear();
+
+ int index = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ Value pot = _fractional->nodeValue(n);
+ (*_node_index)[n] = index;
+ (*_node_data)[index].pot = pot;
+ (*_node_data)[index].heap_index.clear();
+ (*_node_data)[index].heap.clear();
+ int blossom =
+ _blossom_set->insert(n, std::numeric_limits<Value>::max());
+
+ (*_blossom_data)[blossom].status = MATCHED;
+ (*_blossom_data)[blossom].pred = INVALID;
+ (*_blossom_data)[blossom].next = _fractional->matching(n);
+ (*_blossom_data)[blossom].pot = 0;
+ (*_blossom_data)[blossom].offset = 0;
+ ++index;
+ }
+
+ typename Graph::template NodeMap<bool> processed(_graph, false);
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if (processed[n]) continue;
+ processed[n] = true;
+ if (_fractional->matching(n) == INVALID) continue;
+ int num = 1;
+ Node v = _graph.target(_fractional->matching(n));
+ while (n != v) {
+ processed[v] = true;
+ v = _graph.target(_fractional->matching(v));
+ ++num;
+ }
+
+ if (num % 2 == 1) {
+ std::vector<int> subblossoms(num);
+
+ subblossoms[--num] = _blossom_set->find(n);
+ v = _graph.target(_fractional->matching(n));
+ while (n != v) {
+ subblossoms[--num] = _blossom_set->find(v);
+ v = _graph.target(_fractional->matching(v));
+ }
+
+ int surface =
+ _blossom_set->join(subblossoms.begin(), subblossoms.end());
+ (*_blossom_data)[surface].status = EVEN;
+ (*_blossom_data)[surface].pred = INVALID;
+ (*_blossom_data)[surface].next = INVALID;
+ (*_blossom_data)[surface].pot = 0;
+ (*_blossom_data)[surface].offset = 0;
+
+ _tree_set->insert(surface);
+ ++_unmatched;
+ }
+ }
+
+ for (EdgeIt e(_graph); e != INVALID; ++e) {
+ int si = (*_node_index)[_graph.u(e)];
+ int sb = _blossom_set->find(_graph.u(e));
+ int ti = (*_node_index)[_graph.v(e)];
+ int tb = _blossom_set->find(_graph.v(e));
+ if ((*_blossom_data)[sb].status == EVEN &&
+ (*_blossom_data)[tb].status == EVEN && sb != tb) {
+ _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
+ dualScale * _weight[e]) / 2);
+ }
+ }
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ int nb = _blossom_set->find(n);
+ if ((*_blossom_data)[nb].status != MATCHED) continue;
+ int ni = (*_node_index)[n];
+
+ for (OutArcIt e(_graph, n); e != INVALID; ++e) {
+ Node v = _graph.target(e);
+ int vb = _blossom_set->find(v);
+ int vi = (*_node_index)[v];
+
+ Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
+ dualScale * _weight[e];
+
+ if ((*_blossom_data)[vb].status == EVEN) {
+
+ int vt = _tree_set->find(vb);
+
+ typename std::map<int, Arc>::iterator it =
+ (*_node_data)[ni].heap_index.find(vt);
+
+ if (it != (*_node_data)[ni].heap_index.end()) {
+ if ((*_node_data)[ni].heap[it->second] > rw) {
+ (*_node_data)[ni].heap.replace(it->second, e);
+ (*_node_data)[ni].heap.decrease(e, rw);
+ it->second = e;
+ }
+ } else {
+ (*_node_data)[ni].heap.push(e, rw);
+ (*_node_data)[ni].heap_index.insert(std::make_pair(vt, e));
+ }
+ }
+ }
+
+ if (!(*_node_data)[ni].heap.empty()) {
+ _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
+ _delta2->push(nb, _blossom_set->classPrio(nb));
+ }
+ }
+ }
+
+ /// \brief Start the algorithm
+ ///
+ /// This function starts the algorithm.
+ ///
+ /// \pre \ref init() or \ref fractionalInit() must be called before
+ /// using this function.
+ bool start() {
+ enum OpType {
+ D2, D3, D4
+ };
+
+ if (_unmatched == -1) return false;
+
+ while (_unmatched > 0) {
+ Value d2 = !_delta2->empty() ?
+ _delta2->prio() : std::numeric_limits<Value>::max();
+
+ Value d3 = !_delta3->empty() ?
+ _delta3->prio() : std::numeric_limits<Value>::max();
+
+ Value d4 = !_delta4->empty() ?
+ _delta4->prio() : std::numeric_limits<Value>::max();
+
+ _delta_sum = d3; OpType ot = D3;
+ if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
+ if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
+
+ if (_delta_sum == std::numeric_limits<Value>::max()) {
+ return false;
+ }
+
+ switch (ot) {
+ case D2:
+ {
+ int blossom = _delta2->top();
+ Node n = _blossom_set->classTop(blossom);
+ Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
+ extendOnArc(e);
+ }
+ break;
+ case D3:
+ {
+ Edge e = _delta3->top();
+
+ int left_blossom = _blossom_set->find(_graph.u(e));
+ int right_blossom = _blossom_set->find(_graph.v(e));
+
+ if (left_blossom == right_blossom) {
+ _delta3->pop();
+ } else {
+ int left_tree = _tree_set->find(left_blossom);
+ int right_tree = _tree_set->find(right_blossom);
+
+ if (left_tree == right_tree) {
+ shrinkOnEdge(e, left_tree);
+ } else {
+ augmentOnEdge(e);
+ _unmatched -= 2;
+ }
+ }
+ } break;
+ case D4:
+ splitBlossom(_delta4->top());
+ break;
+ }
+ }
+ extractMatching();
+ return true;
+ }
+
+ /// \brief Run the algorithm.
+ ///
+ /// This method runs the \c %MaxWeightedPerfectMatching algorithm.
+ ///
+ /// \note mwpm.run() is just a shortcut of the following code.
+ /// \code
+ /// mwpm.fractionalInit();
+ /// mwpm.start();
+ /// \endcode
+ bool run() {
+ fractionalInit();
+ return start();
+ }
+
+ /// @}
+
+ /// \name Primal Solution
+ /// Functions to get the primal solution, i.e. the maximum weighted
+ /// perfect matching.\n
+ /// Either \ref run() or \ref start() function should be called before
+ /// using them.
+
+ /// @{
+
+ /// \brief Return the weight of the matching.
+ ///
+ /// This function returns the weight of the found matching.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Value matchingWeight() const {
+ Value sum = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if ((*_matching)[n] != INVALID) {
+ sum += _weight[(*_matching)[n]];
+ }
+ }
+ return sum / 2;
+ }
+
+ /// \brief Return \c true if the given edge is in the matching.
+ ///
+ /// This function returns \c true if the given edge is in the found
+ /// matching.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ bool matching(const Edge& edge) const {
+ return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
+ }
+
+ /// \brief Return the matching arc (or edge) incident to the given node.
+ ///
+ /// This function returns the matching arc (or edge) incident to the
+ /// given node in the found matching or \c INVALID if the node is
+ /// not covered by the matching.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Arc matching(const Node& node) const {
+ return (*_matching)[node];
+ }
+
+ /// \brief Return a const reference to the matching map.
+ ///
+ /// This function returns a const reference to a node map that stores
+ /// the matching arc (or edge) incident to each node.
+ const MatchingMap& matchingMap() const {
+ return *_matching;
+ }
+
+ /// \brief Return the mate of the given node.
+ ///
+ /// This function returns the mate of the given node in the found
+ /// matching or \c INVALID if the node is not covered by the matching.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Node mate(const Node& node) const {
+ return _graph.target((*_matching)[node]);
+ }
+
+ /// @}
+
+ /// \name Dual Solution
+ /// Functions to get the dual solution.\n
+ /// Either \ref run() or \ref start() function should be called before
+ /// using them.
+
+ /// @{
+
+ /// \brief Return the value of the dual solution.
+ ///
+ /// This function returns the value of the dual solution.
+ /// It should be equal to the primal value scaled by \ref dualScale
+ /// "dual scale".
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Value dualValue() const {
+ Value sum = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ sum += nodeValue(n);
+ }
+ for (int i = 0; i < blossomNum(); ++i) {
+ sum += blossomValue(i) * (blossomSize(i) / 2);
+ }
+ return sum;
+ }
+
+ /// \brief Return the dual value (potential) of the given node.
+ ///
+ /// This function returns the dual value (potential) of the given node.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Value nodeValue(const Node& n) const {
+ return (*_node_potential)[n];
+ }
+
+ /// \brief Return the number of the blossoms in the basis.
+ ///
+ /// This function returns the number of the blossoms in the basis.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ /// \see BlossomIt
+ int blossomNum() const {
+ return _blossom_potential.size();
+ }
+
+ /// \brief Return the number of the nodes in the given blossom.
+ ///
+ /// This function returns the number of the nodes in the given blossom.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ /// \see BlossomIt
+ int blossomSize(int k) const {
+ return _blossom_potential[k].end - _blossom_potential[k].begin;
+ }
+
+ /// \brief Return the dual value (ptential) of the given blossom.
+ ///
+ /// This function returns the dual value (ptential) of the given blossom.
+ ///
+ /// \pre Either run() or start() must be called before using this function.
+ Value blossomValue(int k) const {
+ return _blossom_potential[k].value;
+ }
+
+ /// \brief Iterator for obtaining the nodes of a blossom.
+ ///
+ /// This class provides an iterator for obtaining the nodes of the
+ /// given blossom. It lists a subset of the nodes.
+ /// Before using this iterator, you must allocate a
+ /// MaxWeightedPerfectMatching class and execute it.
+ class BlossomIt {
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor to get the nodes of the given variable.
+ ///
+ /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()"
+ /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()"
+ /// must be called before initializing this iterator.
+ BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
+ : _algorithm(&algorithm)
+ {
+ _index = _algorithm->_blossom_potential[variable].begin;
+ _last = _algorithm->_blossom_potential[variable].end;
+ }
+
+ /// \brief Conversion to \c Node.
+ ///
+ /// Conversion to \c Node.
+ operator Node() const {
+ return _algorithm->_blossom_node_list[_index];
+ }
+
+ /// \brief Increment operator.
+ ///
+ /// Increment operator.
+ BlossomIt& operator++() {
+ ++_index;
+ return *this;
+ }
+
+ /// \brief Validity checking
+ ///
+ /// This function checks whether the iterator is invalid.
+ bool operator==(Invalid) const { return _index == _last; }
+
+ /// \brief Validity checking
+ ///
+ /// This function checks whether the iterator is valid.
+ bool operator!=(Invalid) const { return _index != _last; }
+
+ private:
+ const MaxWeightedPerfectMatching* _algorithm;
+ int _last;
+ int _index;
+ };
+
+ /// @}
+
+ };
+
+} //END OF NAMESPACE LEMON
+
+#endif //LEMON_MATCHING_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/math.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/math.h
new file mode 100644
index 00000000000..5da50b07a9d
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/math.h
@@ -0,0 +1,77 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_MATH_H
+#define LEMON_MATH_H
+
+///\ingroup misc
+///\file
+///\brief Some extensions to the standard \c cmath library.
+///
+///Some extensions to the standard \c cmath library.
+///
+///This file includes the standard math library (cmath).
+
+#include<cmath>
+
+namespace lemon {
+
+ /// \addtogroup misc
+ /// @{
+
+ /// The Euler constant
+ const long double E = 2.7182818284590452353602874713526625L;
+ /// log_2(e)
+ const long double LOG2E = 1.4426950408889634073599246810018921L;
+ /// log_10(e)
+ const long double LOG10E = 0.4342944819032518276511289189166051L;
+ /// ln(2)
+ const long double LN2 = 0.6931471805599453094172321214581766L;
+ /// ln(10)
+ const long double LN10 = 2.3025850929940456840179914546843642L;
+ /// pi
+ const long double PI = 3.1415926535897932384626433832795029L;
+ /// pi/2
+ const long double PI_2 = 1.5707963267948966192313216916397514L;
+ /// pi/4
+ const long double PI_4 = 0.7853981633974483096156608458198757L;
+ /// sqrt(2)
+ const long double SQRT2 = 1.4142135623730950488016887242096981L;
+ /// 1/sqrt(2)
+ const long double SQRT1_2 = 0.7071067811865475244008443621048490L;
+
+ ///Check whether the parameter is NaN or not
+
+ ///This function checks whether the parameter is NaN or not.
+ ///Is should be equivalent with std::isnan(), but it is not
+ ///provided by all compilers.
+ inline bool isNaN(double v)
+ {
+ return v!=v;
+ }
+
+ ///Round a value to its closest integer
+ inline double round(double r) {
+ return (r > 0.0) ? std::floor(r + 0.5) : std::ceil(r - 0.5);
+ }
+
+ /// @}
+
+} //namespace lemon
+
+#endif //LEMON_MATH_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/max_cardinality_search.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/max_cardinality_search.h
new file mode 100644
index 00000000000..bfa9edb7734
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/max_cardinality_search.h
@@ -0,0 +1,794 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_MAX_CARDINALITY_SEARCH_H
+#define LEMON_MAX_CARDINALITY_SEARCH_H
+
+
+/// \ingroup search
+/// \file
+/// \brief Maximum cardinality search in undirected digraphs.
+
+#include <lemon/bin_heap.h>
+#include <lemon/bucket_heap.h>
+
+#include <lemon/error.h>
+#include <lemon/maps.h>
+
+#include <functional>
+
+namespace lemon {
+
+ /// \brief Default traits class of MaxCardinalitySearch class.
+ ///
+ /// Default traits class of MaxCardinalitySearch class.
+ /// \param Digraph Digraph type.
+ /// \param CapacityMap Type of capacity map.
+ template <typename GR, typename CAP>
+ struct MaxCardinalitySearchDefaultTraits {
+ /// The digraph type the algorithm runs on.
+ typedef GR Digraph;
+
+ template <typename CM>
+ struct CapMapSelector {
+
+ typedef CM CapacityMap;
+
+ static CapacityMap *createCapacityMap(const Digraph& g) {
+ return new CapacityMap(g);
+ }
+ };
+
+ template <typename CM>
+ struct CapMapSelector<ConstMap<CM, Const<int, 1> > > {
+
+ typedef ConstMap<CM, Const<int, 1> > CapacityMap;
+
+ static CapacityMap *createCapacityMap(const Digraph&) {
+ return new CapacityMap;
+ }
+ };
+
+ /// \brief The type of the map that stores the arc capacities.
+ ///
+ /// The type of the map that stores the arc capacities.
+ /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
+ typedef typename CapMapSelector<CAP>::CapacityMap CapacityMap;
+
+ /// \brief The type of the capacity of the arcs.
+ typedef typename CapacityMap::Value Value;
+
+ /// \brief Instantiates a CapacityMap.
+ ///
+ /// This function instantiates a \ref CapacityMap.
+ /// \param digraph is the digraph, to which we would like to define
+ /// the CapacityMap.
+ static CapacityMap *createCapacityMap(const Digraph& digraph) {
+ return CapMapSelector<CapacityMap>::createCapacityMap(digraph);
+ }
+
+ /// \brief The cross reference type used by heap.
+ ///
+ /// The cross reference type used by heap.
+ /// Usually it is \c Digraph::NodeMap<int>.
+ typedef typename Digraph::template NodeMap<int> HeapCrossRef;
+
+ /// \brief Instantiates a HeapCrossRef.
+ ///
+ /// This function instantiates a \ref HeapCrossRef.
+ /// \param digraph is the digraph, to which we would like to define the
+ /// HeapCrossRef.
+ static HeapCrossRef *createHeapCrossRef(const Digraph &digraph) {
+ return new HeapCrossRef(digraph);
+ }
+
+ template <typename CapacityMap>
+ struct HeapSelector {
+ template <typename Value, typename Ref>
+ struct Selector {
+ typedef BinHeap<Value, Ref, std::greater<Value> > Heap;
+ };
+ };
+
+ template <typename CapacityKey>
+ struct HeapSelector<ConstMap<CapacityKey, Const<int, 1> > > {
+ template <typename Value, typename Ref>
+ struct Selector {
+ typedef BucketHeap<Ref, false > Heap;
+ };
+ };
+
+ /// \brief The heap type used by MaxCardinalitySearch algorithm.
+ ///
+ /// The heap type used by MaxCardinalitySearch algorithm. It should
+ /// maximalize the priorities. The default heap type is
+ /// the \ref BinHeap, but it is specialized when the
+ /// CapacityMap is ConstMap<Digraph::Node, Const<int, 1> >
+ /// to BucketHeap.
+ ///
+ /// \sa MaxCardinalitySearch
+ typedef typename HeapSelector<CapacityMap>
+ ::template Selector<Value, HeapCrossRef>
+ ::Heap Heap;
+
+ /// \brief Instantiates a Heap.
+ ///
+ /// This function instantiates a \ref Heap.
+ /// \param crossref The cross reference of the heap.
+ static Heap *createHeap(HeapCrossRef& crossref) {
+ return new Heap(crossref);
+ }
+
+ /// \brief The type of the map that stores whether a node is processed.
+ ///
+ /// The type of the map that stores whether a node is processed.
+ /// It must meet the \ref concepts::WriteMap "WriteMap" concept.
+ /// By default it is a NullMap.
+ typedef NullMap<typename Digraph::Node, bool> ProcessedMap;
+
+ /// \brief Instantiates a ProcessedMap.
+ ///
+ /// This function instantiates a \ref ProcessedMap.
+ /// \param digraph is the digraph, to which
+ /// we would like to define the \ref ProcessedMap
+#ifdef DOXYGEN
+ static ProcessedMap *createProcessedMap(const Digraph &digraph)
+#else
+ static ProcessedMap *createProcessedMap(const Digraph &)
+#endif
+ {
+ return new ProcessedMap();
+ }
+
+ /// \brief The type of the map that stores the cardinalities of the nodes.
+ ///
+ /// The type of the map that stores the cardinalities of the nodes.
+ /// It must meet the \ref concepts::WriteMap "WriteMap" concept.
+ typedef typename Digraph::template NodeMap<Value> CardinalityMap;
+
+ /// \brief Instantiates a CardinalityMap.
+ ///
+ /// This function instantiates a \ref CardinalityMap.
+ /// \param digraph is the digraph, to which we would like to
+ /// define the \ref CardinalityMap
+ static CardinalityMap *createCardinalityMap(const Digraph &digraph) {
+ return new CardinalityMap(digraph);
+ }
+
+
+ };
+
+ /// \ingroup search
+ ///
+ /// \brief Maximum Cardinality Search algorithm class.
+ ///
+ /// This class provides an efficient implementation of Maximum Cardinality
+ /// Search algorithm. The maximum cardinality search first chooses any
+ /// node of the digraph. Then every time it chooses one unprocessed node
+ /// with maximum cardinality, i.e the sum of capacities on out arcs
+ /// to the nodes
+ /// which were previusly processed.
+ /// If there is a cut in the digraph the algorithm should choose
+ /// again any unprocessed node of the digraph.
+
+ /// The arc capacities are passed to the algorithm using a
+ /// \ref concepts::ReadMap "ReadMap", so it is easy to change it to any
+ /// kind of capacity.
+ ///
+ /// The type of the capacity is determined by the \ref
+ /// concepts::ReadMap::Value "Value" of the capacity map.
+ ///
+ /// It is also possible to change the underlying priority heap.
+ ///
+ ///
+ /// \param GR The digraph type the algorithm runs on. The value of
+ /// Digraph is not used directly by the search algorithm, it
+ /// is only passed to \ref MaxCardinalitySearchDefaultTraits.
+ /// \param CAP This read-only ArcMap determines the capacities of
+ /// the arcs. It is read once for each arc, so the map may involve in
+ /// relatively time consuming process to compute the arc capacity if
+ /// it is necessary. The default map type is \ref
+ /// ConstMap "ConstMap<concepts::Digraph::Arc, Const<int,1> >". The value
+ /// of CapacityMap is not used directly by search algorithm, it is only
+ /// passed to \ref MaxCardinalitySearchDefaultTraits.
+ /// \param TR Traits class to set various data types used by the
+ /// algorithm. The default traits class is
+ /// \ref MaxCardinalitySearchDefaultTraits
+ /// "MaxCardinalitySearchDefaultTraits<GR, CAP>".
+ /// See \ref MaxCardinalitySearchDefaultTraits
+ /// for the documentation of a MaxCardinalitySearch traits class.
+
+#ifdef DOXYGEN
+ template <typename GR, typename CAP, typename TR>
+#else
+ template <typename GR, typename CAP =
+ ConstMap<typename GR::Arc, Const<int,1> >,
+ typename TR =
+ MaxCardinalitySearchDefaultTraits<GR, CAP> >
+#endif
+ class MaxCardinalitySearch {
+ public:
+
+ typedef TR Traits;
+ ///The type of the underlying digraph.
+ typedef typename Traits::Digraph Digraph;
+
+ ///The type of the capacity of the arcs.
+ typedef typename Traits::CapacityMap::Value Value;
+ ///The type of the map that stores the arc capacities.
+ typedef typename Traits::CapacityMap CapacityMap;
+ ///The type of the map indicating if a node is processed.
+ typedef typename Traits::ProcessedMap ProcessedMap;
+ ///The type of the map that stores the cardinalities of the nodes.
+ typedef typename Traits::CardinalityMap CardinalityMap;
+ ///The cross reference type used for the current heap.
+ typedef typename Traits::HeapCrossRef HeapCrossRef;
+ ///The heap type used by the algorithm. It maximizes the priorities.
+ typedef typename Traits::Heap Heap;
+ private:
+ // Pointer to the underlying digraph.
+ const Digraph *_graph;
+ // Pointer to the capacity map
+ const CapacityMap *_capacity;
+ // Indicates if \ref _capacity is locally allocated (\c true) or not.
+ bool local_capacity;
+ // Pointer to the map of cardinality.
+ CardinalityMap *_cardinality;
+ // Indicates if \ref _cardinality is locally allocated (\c true) or not.
+ bool local_cardinality;
+ // Pointer to the map of processed status of the nodes.
+ ProcessedMap *_processed;
+ // Indicates if \ref _processed is locally allocated (\c true) or not.
+ bool local_processed;
+ // Pointer to the heap cross references.
+ HeapCrossRef *_heap_cross_ref;
+ // Indicates if \ref _heap_cross_ref is locally allocated (\c true) or not.
+ bool local_heap_cross_ref;
+ // Pointer to the heap.
+ Heap *_heap;
+ // Indicates if \ref _heap is locally allocated (\c true) or not.
+ bool local_heap;
+
+ public :
+
+ typedef MaxCardinalitySearch Create;
+
+ ///\name Named template parameters
+
+ ///@{
+
+ template <class T>
+ struct DefCapacityMapTraits : public Traits {
+ typedef T CapacityMap;
+ static CapacityMap *createCapacityMap(const Digraph &) {
+ LEMON_ASSERT(false,"Uninitialized parameter.");
+ return 0;
+ }
+ };
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// CapacityMap type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting CapacityMap type
+ /// for the algorithm.
+ template <class T>
+ struct SetCapacityMap
+ : public MaxCardinalitySearch<Digraph, CapacityMap,
+ DefCapacityMapTraits<T> > {
+ typedef MaxCardinalitySearch<Digraph, CapacityMap,
+ DefCapacityMapTraits<T> > Create;
+ };
+
+ template <class T>
+ struct DefCardinalityMapTraits : public Traits {
+ typedef T CardinalityMap;
+ static CardinalityMap *createCardinalityMap(const Digraph &)
+ {
+ LEMON_ASSERT(false,"Uninitialized parameter.");
+ return 0;
+ }
+ };
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// CardinalityMap type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting CardinalityMap
+ /// type for the algorithm.
+ template <class T>
+ struct SetCardinalityMap
+ : public MaxCardinalitySearch<Digraph, CapacityMap,
+ DefCardinalityMapTraits<T> > {
+ typedef MaxCardinalitySearch<Digraph, CapacityMap,
+ DefCardinalityMapTraits<T> > Create;
+ };
+
+ template <class T>
+ struct DefProcessedMapTraits : public Traits {
+ typedef T ProcessedMap;
+ static ProcessedMap *createProcessedMap(const Digraph &) {
+ LEMON_ASSERT(false,"Uninitialized parameter.");
+ return 0;
+ }
+ };
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// ProcessedMap type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting ProcessedMap type
+ /// for the algorithm.
+ template <class T>
+ struct SetProcessedMap
+ : public MaxCardinalitySearch<Digraph, CapacityMap,
+ DefProcessedMapTraits<T> > {
+ typedef MaxCardinalitySearch<Digraph, CapacityMap,
+ DefProcessedMapTraits<T> > Create;
+ };
+
+ template <class H, class CR>
+ struct DefHeapTraits : public Traits {
+ typedef CR HeapCrossRef;
+ typedef H Heap;
+ static HeapCrossRef *createHeapCrossRef(const Digraph &) {
+ LEMON_ASSERT(false,"Uninitialized parameter.");
+ return 0;
+ }
+ static Heap *createHeap(HeapCrossRef &) {
+ LEMON_ASSERT(false,"Uninitialized parameter.");
+ return 0;
+ }
+ };
+ /// \brief \ref named-templ-param "Named parameter" for setting heap
+ /// and cross reference type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting heap and cross
+ /// reference type for the algorithm.
+ template <class H, class CR = typename Digraph::template NodeMap<int> >
+ struct SetHeap
+ : public MaxCardinalitySearch<Digraph, CapacityMap,
+ DefHeapTraits<H, CR> > {
+ typedef MaxCardinalitySearch< Digraph, CapacityMap,
+ DefHeapTraits<H, CR> > Create;
+ };
+
+ template <class H, class CR>
+ struct DefStandardHeapTraits : public Traits {
+ typedef CR HeapCrossRef;
+ typedef H Heap;
+ static HeapCrossRef *createHeapCrossRef(const Digraph &digraph) {
+ return new HeapCrossRef(digraph);
+ }
+ static Heap *createHeap(HeapCrossRef &crossref) {
+ return new Heap(crossref);
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting heap and
+ /// cross reference type with automatic allocation
+ ///
+ /// \ref named-templ-param "Named parameter" for setting heap and cross
+ /// reference type. It can allocate the heap and the cross reference
+ /// object if the cross reference's constructor waits for the digraph as
+ /// parameter and the heap's constructor waits for the cross reference.
+ template <class H, class CR = typename Digraph::template NodeMap<int> >
+ struct SetStandardHeap
+ : public MaxCardinalitySearch<Digraph, CapacityMap,
+ DefStandardHeapTraits<H, CR> > {
+ typedef MaxCardinalitySearch<Digraph, CapacityMap,
+ DefStandardHeapTraits<H, CR> >
+ Create;
+ };
+
+ ///@}
+
+
+ protected:
+
+ MaxCardinalitySearch() {}
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ ///\param digraph the digraph the algorithm will run on.
+ ///\param capacity the capacity map used by the algorithm.
+ MaxCardinalitySearch(const Digraph& digraph,
+ const CapacityMap& capacity) :
+ _graph(&digraph),
+ _capacity(&capacity), local_capacity(false),
+ _cardinality(0), local_cardinality(false),
+ _processed(0), local_processed(false),
+ _heap_cross_ref(0), local_heap_cross_ref(false),
+ _heap(0), local_heap(false)
+ { }
+
+ /// \brief Constructor.
+ ///
+ ///\param digraph the digraph the algorithm will run on.
+ ///
+ ///A constant 1 capacity map will be allocated.
+ MaxCardinalitySearch(const Digraph& digraph) :
+ _graph(&digraph),
+ _capacity(0), local_capacity(false),
+ _cardinality(0), local_cardinality(false),
+ _processed(0), local_processed(false),
+ _heap_cross_ref(0), local_heap_cross_ref(false),
+ _heap(0), local_heap(false)
+ { }
+
+ /// \brief Destructor.
+ ~MaxCardinalitySearch() {
+ if(local_capacity) delete _capacity;
+ if(local_cardinality) delete _cardinality;
+ if(local_processed) delete _processed;
+ if(local_heap_cross_ref) delete _heap_cross_ref;
+ if(local_heap) delete _heap;
+ }
+
+ /// \brief Sets the capacity map.
+ ///
+ /// Sets the capacity map.
+ /// \return <tt> (*this) </tt>
+ MaxCardinalitySearch &capacityMap(const CapacityMap &m) {
+ if (local_capacity) {
+ delete _capacity;
+ local_capacity=false;
+ }
+ _capacity=&m;
+ return *this;
+ }
+
+ /// \brief Returns a const reference to the capacity map.
+ ///
+ /// Returns a const reference to the capacity map used by
+ /// the algorithm.
+ const CapacityMap &capacityMap() const {
+ return *_capacity;
+ }
+
+ /// \brief Sets the map storing the cardinalities calculated by the
+ /// algorithm.
+ ///
+ /// Sets the map storing the cardinalities calculated by the algorithm.
+ /// If you don't use this function before calling \ref run(),
+ /// it will allocate one. The destuctor deallocates this
+ /// automatically allocated map, of course.
+ /// \return <tt> (*this) </tt>
+ MaxCardinalitySearch &cardinalityMap(CardinalityMap &m) {
+ if(local_cardinality) {
+ delete _cardinality;
+ local_cardinality=false;
+ }
+ _cardinality = &m;
+ return *this;
+ }
+
+ /// \brief Sets the map storing the processed nodes.
+ ///
+ /// Sets the map storing the processed nodes.
+ /// If you don't use this function before calling \ref run(),
+ /// it will allocate one. The destuctor deallocates this
+ /// automatically allocated map, of course.
+ /// \return <tt> (*this) </tt>
+ MaxCardinalitySearch &processedMap(ProcessedMap &m)
+ {
+ if(local_processed) {
+ delete _processed;
+ local_processed=false;
+ }
+ _processed = &m;
+ return *this;
+ }
+
+ /// \brief Returns a const reference to the cardinality map.
+ ///
+ /// Returns a const reference to the cardinality map used by
+ /// the algorithm.
+ const ProcessedMap &processedMap() const {
+ return *_processed;
+ }
+
+ /// \brief Sets the heap and the cross reference used by algorithm.
+ ///
+ /// Sets the heap and the cross reference used by algorithm.
+ /// If you don't use this function before calling \ref run(),
+ /// it will allocate one. The destuctor deallocates this
+ /// automatically allocated map, of course.
+ /// \return <tt> (*this) </tt>
+ MaxCardinalitySearch &heap(Heap& hp, HeapCrossRef &cr) {
+ if(local_heap_cross_ref) {
+ delete _heap_cross_ref;
+ local_heap_cross_ref = false;
+ }
+ _heap_cross_ref = &cr;
+ if(local_heap) {
+ delete _heap;
+ local_heap = false;
+ }
+ _heap = &hp;
+ return *this;
+ }
+
+ /// \brief Returns a const reference to the heap.
+ ///
+ /// Returns a const reference to the heap used by
+ /// the algorithm.
+ const Heap &heap() const {
+ return *_heap;
+ }
+
+ /// \brief Returns a const reference to the cross reference.
+ ///
+ /// Returns a const reference to the cross reference
+ /// of the heap.
+ const HeapCrossRef &heapCrossRef() const {
+ return *_heap_cross_ref;
+ }
+
+ private:
+
+ typedef typename Digraph::Node Node;
+ typedef typename Digraph::NodeIt NodeIt;
+ typedef typename Digraph::Arc Arc;
+ typedef typename Digraph::InArcIt InArcIt;
+
+ void create_maps() {
+ if(!_capacity) {
+ local_capacity = true;
+ _capacity = Traits::createCapacityMap(*_graph);
+ }
+ if(!_cardinality) {
+ local_cardinality = true;
+ _cardinality = Traits::createCardinalityMap(*_graph);
+ }
+ if(!_processed) {
+ local_processed = true;
+ _processed = Traits::createProcessedMap(*_graph);
+ }
+ if (!_heap_cross_ref) {
+ local_heap_cross_ref = true;
+ _heap_cross_ref = Traits::createHeapCrossRef(*_graph);
+ }
+ if (!_heap) {
+ local_heap = true;
+ _heap = Traits::createHeap(*_heap_cross_ref);
+ }
+ }
+
+ void finalizeNodeData(Node node, Value capacity) {
+ _processed->set(node, true);
+ _cardinality->set(node, capacity);
+ }
+
+ public:
+ /// \name Execution control
+ /// The simplest way to execute the algorithm is to use
+ /// one of the member functions called \ref run().
+ /// \n
+ /// If you need more control on the execution,
+ /// first you must call \ref init(), then you can add several source nodes
+ /// with \ref addSource().
+ /// Finally \ref start() will perform the computation.
+
+ ///@{
+
+ /// \brief Initializes the internal data structures.
+ ///
+ /// Initializes the internal data structures, and clears the heap.
+ void init() {
+ create_maps();
+ _heap->clear();
+ for (NodeIt it(*_graph) ; it != INVALID ; ++it) {
+ _processed->set(it, false);
+ _heap_cross_ref->set(it, Heap::PRE_HEAP);
+ }
+ }
+
+ /// \brief Adds a new source node.
+ ///
+ /// Adds a new source node to the priority heap.
+ ///
+ /// It checks if the node has not yet been added to the heap.
+ void addSource(Node source, Value capacity = 0) {
+ if(_heap->state(source) == Heap::PRE_HEAP) {
+ _heap->push(source, capacity);
+ }
+ }
+
+ /// \brief Processes the next node in the priority heap
+ ///
+ /// Processes the next node in the priority heap.
+ ///
+ /// \return The processed node.
+ ///
+ /// \warning The priority heap must not be empty!
+ Node processNextNode() {
+ Node node = _heap->top();
+ finalizeNodeData(node, _heap->prio());
+ _heap->pop();
+
+ for (InArcIt it(*_graph, node); it != INVALID; ++it) {
+ Node source = _graph->source(it);
+ switch (_heap->state(source)) {
+ case Heap::PRE_HEAP:
+ _heap->push(source, (*_capacity)[it]);
+ break;
+ case Heap::IN_HEAP:
+ _heap->decrease(source, (*_heap)[source] + (*_capacity)[it]);
+ break;
+ case Heap::POST_HEAP:
+ break;
+ }
+ }
+ return node;
+ }
+
+ /// \brief Next node to be processed.
+ ///
+ /// Next node to be processed.
+ ///
+ /// \return The next node to be processed or INVALID if the
+ /// priority heap is empty.
+ Node nextNode() {
+ return !_heap->empty() ? _heap->top() : INVALID;
+ }
+
+ /// \brief Returns \c false if there are nodes
+ /// to be processed in the priority heap
+ ///
+ /// Returns \c false if there are nodes
+ /// to be processed in the priority heap
+ bool emptyQueue() { return _heap->empty(); }
+ /// \brief Returns the number of the nodes to be processed
+ /// in the priority heap
+ ///
+ /// Returns the number of the nodes to be processed in the priority heap
+ int emptySize() { return _heap->size(); }
+
+ /// \brief Executes the algorithm.
+ ///
+ /// Executes the algorithm.
+ ///
+ ///\pre init() must be called and at least one node should be added
+ /// with addSource() before using this function.
+ ///
+ /// This method runs the Maximum Cardinality Search algorithm from the
+ /// source node(s).
+ void start() {
+ while ( !_heap->empty() ) processNextNode();
+ }
+
+ /// \brief Executes the algorithm until \c dest is reached.
+ ///
+ /// Executes the algorithm until \c dest is reached.
+ ///
+ /// \pre init() must be called and at least one node should be added
+ /// with addSource() before using this function.
+ ///
+ /// This method runs the %MaxCardinalitySearch algorithm from the source
+ /// nodes.
+ void start(Node dest) {
+ while ( !_heap->empty() && _heap->top()!=dest ) processNextNode();
+ if ( !_heap->empty() ) finalizeNodeData(_heap->top(), _heap->prio());
+ }
+
+ /// \brief Executes the algorithm until a condition is met.
+ ///
+ /// Executes the algorithm until a condition is met.
+ ///
+ /// \pre init() must be called and at least one node should be added
+ /// with addSource() before using this function.
+ ///
+ /// \param nm must be a bool (or convertible) node map. The algorithm
+ /// will stop when it reaches a node \c v with <tt>nm[v]==true</tt>.
+ template <typename NodeBoolMap>
+ void start(const NodeBoolMap &nm) {
+ while ( !_heap->empty() && !nm[_heap->top()] ) processNextNode();
+ if ( !_heap->empty() ) finalizeNodeData(_heap->top(),_heap->prio());
+ }
+
+ /// \brief Runs the maximum cardinality search algorithm from node \c s.
+ ///
+ /// This method runs the %MaxCardinalitySearch algorithm from a root
+ /// node \c s.
+ ///
+ ///\note d.run(s) is just a shortcut of the following code.
+ ///\code
+ /// d.init();
+ /// d.addSource(s);
+ /// d.start();
+ ///\endcode
+ void run(Node s) {
+ init();
+ addSource(s);
+ start();
+ }
+
+ /// \brief Runs the maximum cardinality search algorithm for the
+ /// whole digraph.
+ ///
+ /// This method runs the %MaxCardinalitySearch algorithm from all
+ /// unprocessed node of the digraph.
+ ///
+ ///\note d.run(s) is just a shortcut of the following code.
+ ///\code
+ /// d.init();
+ /// for (NodeIt it(digraph); it != INVALID; ++it) {
+ /// if (!d.reached(it)) {
+ /// d.addSource(s);
+ /// d.start();
+ /// }
+ /// }
+ ///\endcode
+ void run() {
+ init();
+ for (NodeIt it(*_graph); it != INVALID; ++it) {
+ if (!reached(it)) {
+ addSource(it);
+ start();
+ }
+ }
+ }
+
+ ///@}
+
+ /// \name Query Functions
+ /// The results of the maximum cardinality search algorithm can be
+ /// obtained using these functions.
+ /// \n
+ /// Before the use of these functions, either run() or start() must be
+ /// called.
+
+ ///@{
+
+ /// \brief The cardinality of a node.
+ ///
+ /// Returns the cardinality of a node.
+ /// \pre \ref run() must be called before using this function.
+ /// \warning If node \c v in unreachable from the root the return value
+ /// of this funcion is undefined.
+ Value cardinality(Node node) const { return (*_cardinality)[node]; }
+
+ /// \brief The current cardinality of a node.
+ ///
+ /// Returns the current cardinality of a node.
+ /// \pre the given node should be reached but not processed
+ Value currentCardinality(Node node) const { return (*_heap)[node]; }
+
+ /// \brief Returns a reference to the NodeMap of cardinalities.
+ ///
+ /// Returns a reference to the NodeMap of cardinalities. \pre \ref run()
+ /// must be called before using this function.
+ const CardinalityMap &cardinalityMap() const { return *_cardinality;}
+
+ /// \brief Checks if a node is reachable from the root.
+ ///
+ /// Returns \c true if \c v is reachable from the root.
+ /// \warning The source nodes are initated as unreached.
+ /// \pre \ref run() must be called before using this function.
+ bool reached(Node v) { return (*_heap_cross_ref)[v] != Heap::PRE_HEAP; }
+
+ /// \brief Checks if a node is processed.
+ ///
+ /// Returns \c true if \c v is processed, i.e. the shortest
+ /// path to \c v has already found.
+ /// \pre \ref run() must be called before using this function.
+ bool processed(Node v) { return (*_heap_cross_ref)[v] == Heap::POST_HEAP; }
+
+ ///@}
+ };
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/min_cost_arborescence.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/min_cost_arborescence.h
new file mode 100644
index 00000000000..1d0a2b19d81
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/min_cost_arborescence.h
@@ -0,0 +1,808 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_MIN_COST_ARBORESCENCE_H
+#define LEMON_MIN_COST_ARBORESCENCE_H
+
+///\ingroup spantree
+///\file
+///\brief Minimum Cost Arborescence algorithm.
+
+#include <vector>
+
+#include <lemon/list_graph.h>
+#include <lemon/bin_heap.h>
+#include <lemon/assert.h>
+
+namespace lemon {
+
+
+ /// \brief Default traits class for MinCostArborescence class.
+ ///
+ /// Default traits class for MinCostArborescence class.
+ /// \param GR Digraph type.
+ /// \param CM Type of the cost map.
+ template <class GR, class CM>
+ struct MinCostArborescenceDefaultTraits{
+
+ /// \brief The digraph type the algorithm runs on.
+ typedef GR Digraph;
+
+ /// \brief The type of the map that stores the arc costs.
+ ///
+ /// The type of the map that stores the arc costs.
+ /// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
+ typedef CM CostMap;
+
+ /// \brief The value type of the costs.
+ ///
+ /// The value type of the costs.
+ typedef typename CostMap::Value Value;
+
+ /// \brief The type of the map that stores which arcs are in the
+ /// arborescence.
+ ///
+ /// The type of the map that stores which arcs are in the
+ /// arborescence. It must conform to the \ref concepts::WriteMap
+ /// "WriteMap" concept, and its value type must be \c bool
+ /// (or convertible). Initially it will be set to \c false on each
+ /// arc, then it will be set on each arborescence arc once.
+ typedef typename Digraph::template ArcMap<bool> ArborescenceMap;
+
+ /// \brief Instantiates a \c ArborescenceMap.
+ ///
+ /// This function instantiates a \c ArborescenceMap.
+ /// \param digraph The digraph to which we would like to calculate
+ /// the \c ArborescenceMap.
+ static ArborescenceMap *createArborescenceMap(const Digraph &digraph){
+ return new ArborescenceMap(digraph);
+ }
+
+ /// \brief The type of the \c PredMap
+ ///
+ /// The type of the \c PredMap. It must confrom to the
+ /// \ref concepts::WriteMap "WriteMap" concept, and its value type
+ /// must be the \c Arc type of the digraph.
+ typedef typename Digraph::template NodeMap<typename Digraph::Arc> PredMap;
+
+ /// \brief Instantiates a \c PredMap.
+ ///
+ /// This function instantiates a \c PredMap.
+ /// \param digraph The digraph to which we would like to define the
+ /// \c PredMap.
+ static PredMap *createPredMap(const Digraph &digraph){
+ return new PredMap(digraph);
+ }
+
+ };
+
+ /// \ingroup spantree
+ ///
+ /// \brief Minimum Cost Arborescence algorithm class.
+ ///
+ /// This class provides an efficient implementation of the
+ /// Minimum Cost Arborescence algorithm. The arborescence is a tree
+ /// which is directed from a given source node of the digraph. One or
+ /// more sources should be given to the algorithm and it will calculate
+ /// the minimum cost subgraph that is the union of arborescences with the
+ /// given sources and spans all the nodes which are reachable from the
+ /// sources. The time complexity of the algorithm is O(n<sup>2</sup>+m).
+ ///
+ /// The algorithm also provides an optimal dual solution, therefore
+ /// the optimality of the solution can be checked.
+ ///
+ /// \param GR The digraph type the algorithm runs on.
+ /// \param CM A read-only arc map storing the costs of the
+ /// arcs. It is read once for each arc, so the map may involve in
+ /// relatively time consuming process to compute the arc costs if
+ /// it is necessary. The default map type is \ref
+ /// concepts::Digraph::ArcMap "Digraph::ArcMap<int>".
+ /// \tparam TR The traits class that defines various types used by the
+ /// algorithm. By default, it is \ref MinCostArborescenceDefaultTraits
+ /// "MinCostArborescenceDefaultTraits<GR, CM>".
+ /// In most cases, this parameter should not be set directly,
+ /// consider to use the named template parameters instead.
+#ifndef DOXYGEN
+ template <typename GR,
+ typename CM = typename GR::template ArcMap<int>,
+ typename TR =
+ MinCostArborescenceDefaultTraits<GR, CM> >
+#else
+ template <typename GR, typename CM, typename TR>
+#endif
+ class MinCostArborescence {
+ public:
+
+ /// \brief The \ref lemon::MinCostArborescenceDefaultTraits "traits class"
+ /// of the algorithm.
+ typedef TR Traits;
+ /// The type of the underlying digraph.
+ typedef typename Traits::Digraph Digraph;
+ /// The type of the map that stores the arc costs.
+ typedef typename Traits::CostMap CostMap;
+ ///The type of the costs of the arcs.
+ typedef typename Traits::Value Value;
+ ///The type of the predecessor map.
+ typedef typename Traits::PredMap PredMap;
+ ///The type of the map that stores which arcs are in the arborescence.
+ typedef typename Traits::ArborescenceMap ArborescenceMap;
+
+ typedef MinCostArborescence Create;
+
+ private:
+
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+
+ struct CostArc {
+
+ Arc arc;
+ Value value;
+
+ CostArc() {}
+ CostArc(Arc _arc, Value _value) : arc(_arc), value(_value) {}
+
+ };
+
+ const Digraph *_digraph;
+ const CostMap *_cost;
+
+ PredMap *_pred;
+ bool local_pred;
+
+ ArborescenceMap *_arborescence;
+ bool local_arborescence;
+
+ typedef typename Digraph::template ArcMap<int> ArcOrder;
+ ArcOrder *_arc_order;
+
+ typedef typename Digraph::template NodeMap<int> NodeOrder;
+ NodeOrder *_node_order;
+
+ typedef typename Digraph::template NodeMap<CostArc> CostArcMap;
+ CostArcMap *_cost_arcs;
+
+ struct StackLevel {
+
+ std::vector<CostArc> arcs;
+ int node_level;
+
+ };
+
+ std::vector<StackLevel> level_stack;
+ std::vector<Node> queue;
+
+ typedef std::vector<typename Digraph::Node> DualNodeList;
+
+ DualNodeList _dual_node_list;
+
+ struct DualVariable {
+ int begin, end;
+ Value value;
+
+ DualVariable(int _begin, int _end, Value _value)
+ : begin(_begin), end(_end), value(_value) {}
+
+ };
+
+ typedef std::vector<DualVariable> DualVariables;
+
+ DualVariables _dual_variables;
+
+ typedef typename Digraph::template NodeMap<int> HeapCrossRef;
+
+ HeapCrossRef *_heap_cross_ref;
+
+ typedef BinHeap<int, HeapCrossRef> Heap;
+
+ Heap *_heap;
+
+ protected:
+
+ MinCostArborescence() {}
+
+ private:
+
+ void createStructures() {
+ if (!_pred) {
+ local_pred = true;
+ _pred = Traits::createPredMap(*_digraph);
+ }
+ if (!_arborescence) {
+ local_arborescence = true;
+ _arborescence = Traits::createArborescenceMap(*_digraph);
+ }
+ if (!_arc_order) {
+ _arc_order = new ArcOrder(*_digraph);
+ }
+ if (!_node_order) {
+ _node_order = new NodeOrder(*_digraph);
+ }
+ if (!_cost_arcs) {
+ _cost_arcs = new CostArcMap(*_digraph);
+ }
+ if (!_heap_cross_ref) {
+ _heap_cross_ref = new HeapCrossRef(*_digraph, -1);
+ }
+ if (!_heap) {
+ _heap = new Heap(*_heap_cross_ref);
+ }
+ }
+
+ void destroyStructures() {
+ if (local_arborescence) {
+ delete _arborescence;
+ }
+ if (local_pred) {
+ delete _pred;
+ }
+ if (_arc_order) {
+ delete _arc_order;
+ }
+ if (_node_order) {
+ delete _node_order;
+ }
+ if (_cost_arcs) {
+ delete _cost_arcs;
+ }
+ if (_heap) {
+ delete _heap;
+ }
+ if (_heap_cross_ref) {
+ delete _heap_cross_ref;
+ }
+ }
+
+ Arc prepare(Node node) {
+ std::vector<Node> nodes;
+ (*_node_order)[node] = _dual_node_list.size();
+ StackLevel level;
+ level.node_level = _dual_node_list.size();
+ _dual_node_list.push_back(node);
+ for (InArcIt it(*_digraph, node); it != INVALID; ++it) {
+ Arc arc = it;
+ Node source = _digraph->source(arc);
+ Value value = (*_cost)[it];
+ if (source == node || (*_node_order)[source] == -3) continue;
+ if ((*_cost_arcs)[source].arc == INVALID) {
+ (*_cost_arcs)[source].arc = arc;
+ (*_cost_arcs)[source].value = value;
+ nodes.push_back(source);
+ } else {
+ if ((*_cost_arcs)[source].value > value) {
+ (*_cost_arcs)[source].arc = arc;
+ (*_cost_arcs)[source].value = value;
+ }
+ }
+ }
+ CostArc minimum = (*_cost_arcs)[nodes[0]];
+ for (int i = 1; i < int(nodes.size()); ++i) {
+ if ((*_cost_arcs)[nodes[i]].value < minimum.value) {
+ minimum = (*_cost_arcs)[nodes[i]];
+ }
+ }
+ (*_arc_order)[minimum.arc] = _dual_variables.size();
+ DualVariable var(_dual_node_list.size() - 1,
+ _dual_node_list.size(), minimum.value);
+ _dual_variables.push_back(var);
+ for (int i = 0; i < int(nodes.size()); ++i) {
+ (*_cost_arcs)[nodes[i]].value -= minimum.value;
+ level.arcs.push_back((*_cost_arcs)[nodes[i]]);
+ (*_cost_arcs)[nodes[i]].arc = INVALID;
+ }
+ level_stack.push_back(level);
+ return minimum.arc;
+ }
+
+ Arc contract(Node node) {
+ int node_bottom = bottom(node);
+ std::vector<Node> nodes;
+ while (!level_stack.empty() &&
+ level_stack.back().node_level >= node_bottom) {
+ for (int i = 0; i < int(level_stack.back().arcs.size()); ++i) {
+ Arc arc = level_stack.back().arcs[i].arc;
+ Node source = _digraph->source(arc);
+ Value value = level_stack.back().arcs[i].value;
+ if ((*_node_order)[source] >= node_bottom) continue;
+ if ((*_cost_arcs)[source].arc == INVALID) {
+ (*_cost_arcs)[source].arc = arc;
+ (*_cost_arcs)[source].value = value;
+ nodes.push_back(source);
+ } else {
+ if ((*_cost_arcs)[source].value > value) {
+ (*_cost_arcs)[source].arc = arc;
+ (*_cost_arcs)[source].value = value;
+ }
+ }
+ }
+ level_stack.pop_back();
+ }
+ CostArc minimum = (*_cost_arcs)[nodes[0]];
+ for (int i = 1; i < int(nodes.size()); ++i) {
+ if ((*_cost_arcs)[nodes[i]].value < minimum.value) {
+ minimum = (*_cost_arcs)[nodes[i]];
+ }
+ }
+ (*_arc_order)[minimum.arc] = _dual_variables.size();
+ DualVariable var(node_bottom, _dual_node_list.size(), minimum.value);
+ _dual_variables.push_back(var);
+ StackLevel level;
+ level.node_level = node_bottom;
+ for (int i = 0; i < int(nodes.size()); ++i) {
+ (*_cost_arcs)[nodes[i]].value -= minimum.value;
+ level.arcs.push_back((*_cost_arcs)[nodes[i]]);
+ (*_cost_arcs)[nodes[i]].arc = INVALID;
+ }
+ level_stack.push_back(level);
+ return minimum.arc;
+ }
+
+ int bottom(Node node) {
+ int k = level_stack.size() - 1;
+ while (level_stack[k].node_level > (*_node_order)[node]) {
+ --k;
+ }
+ return level_stack[k].node_level;
+ }
+
+ void finalize(Arc arc) {
+ Node node = _digraph->target(arc);
+ _heap->push(node, (*_arc_order)[arc]);
+ _pred->set(node, arc);
+ while (!_heap->empty()) {
+ Node source = _heap->top();
+ _heap->pop();
+ (*_node_order)[source] = -1;
+ for (OutArcIt it(*_digraph, source); it != INVALID; ++it) {
+ if ((*_arc_order)[it] < 0) continue;
+ Node target = _digraph->target(it);
+ switch(_heap->state(target)) {
+ case Heap::PRE_HEAP:
+ _heap->push(target, (*_arc_order)[it]);
+ _pred->set(target, it);
+ break;
+ case Heap::IN_HEAP:
+ if ((*_arc_order)[it] < (*_heap)[target]) {
+ _heap->decrease(target, (*_arc_order)[it]);
+ _pred->set(target, it);
+ }
+ break;
+ case Heap::POST_HEAP:
+ break;
+ }
+ }
+ _arborescence->set((*_pred)[source], true);
+ }
+ }
+
+
+ public:
+
+ /// \name Named Template Parameters
+
+ /// @{
+
+ template <class T>
+ struct SetArborescenceMapTraits : public Traits {
+ typedef T ArborescenceMap;
+ static ArborescenceMap *createArborescenceMap(const Digraph &)
+ {
+ LEMON_ASSERT(false, "ArborescenceMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for
+ /// setting \c ArborescenceMap type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting
+ /// \c ArborescenceMap type.
+ /// It must conform to the \ref concepts::WriteMap "WriteMap" concept,
+ /// and its value type must be \c bool (or convertible).
+ /// Initially it will be set to \c false on each arc,
+ /// then it will be set on each arborescence arc once.
+ template <class T>
+ struct SetArborescenceMap
+ : public MinCostArborescence<Digraph, CostMap,
+ SetArborescenceMapTraits<T> > {
+ };
+
+ template <class T>
+ struct SetPredMapTraits : public Traits {
+ typedef T PredMap;
+ static PredMap *createPredMap(const Digraph &)
+ {
+ LEMON_ASSERT(false, "PredMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for
+ /// setting \c PredMap type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting
+ /// \c PredMap type.
+ /// It must meet the \ref concepts::WriteMap "WriteMap" concept,
+ /// and its value type must be the \c Arc type of the digraph.
+ template <class T>
+ struct SetPredMap
+ : public MinCostArborescence<Digraph, CostMap, SetPredMapTraits<T> > {
+ };
+
+ /// @}
+
+ /// \brief Constructor.
+ ///
+ /// \param digraph The digraph the algorithm will run on.
+ /// \param cost The cost map used by the algorithm.
+ MinCostArborescence(const Digraph& digraph, const CostMap& cost)
+ : _digraph(&digraph), _cost(&cost), _pred(0), local_pred(false),
+ _arborescence(0), local_arborescence(false),
+ _arc_order(0), _node_order(0), _cost_arcs(0),
+ _heap_cross_ref(0), _heap(0) {}
+
+ /// \brief Destructor.
+ ~MinCostArborescence() {
+ destroyStructures();
+ }
+
+ /// \brief Sets the arborescence map.
+ ///
+ /// Sets the arborescence map.
+ /// \return <tt>(*this)</tt>
+ MinCostArborescence& arborescenceMap(ArborescenceMap& m) {
+ if (local_arborescence) {
+ delete _arborescence;
+ }
+ local_arborescence = false;
+ _arborescence = &m;
+ return *this;
+ }
+
+ /// \brief Sets the predecessor map.
+ ///
+ /// Sets the predecessor map.
+ /// \return <tt>(*this)</tt>
+ MinCostArborescence& predMap(PredMap& m) {
+ if (local_pred) {
+ delete _pred;
+ }
+ local_pred = false;
+ _pred = &m;
+ return *this;
+ }
+
+ /// \name Execution Control
+ /// The simplest way to execute the algorithm is to use
+ /// one of the member functions called \c run(...). \n
+ /// If you need better control on the execution,
+ /// you have to call \ref init() first, then you can add several
+ /// source nodes with \ref addSource().
+ /// Finally \ref start() will perform the arborescence
+ /// computation.
+
+ ///@{
+
+ /// \brief Initializes the internal data structures.
+ ///
+ /// Initializes the internal data structures.
+ ///
+ void init() {
+ createStructures();
+ _heap->clear();
+ for (NodeIt it(*_digraph); it != INVALID; ++it) {
+ (*_cost_arcs)[it].arc = INVALID;
+ (*_node_order)[it] = -3;
+ (*_heap_cross_ref)[it] = Heap::PRE_HEAP;
+ _pred->set(it, INVALID);
+ }
+ for (ArcIt it(*_digraph); it != INVALID; ++it) {
+ _arborescence->set(it, false);
+ (*_arc_order)[it] = -1;
+ }
+ _dual_node_list.clear();
+ _dual_variables.clear();
+ }
+
+ /// \brief Adds a new source node.
+ ///
+ /// Adds a new source node to the algorithm.
+ void addSource(Node source) {
+ std::vector<Node> nodes;
+ nodes.push_back(source);
+ while (!nodes.empty()) {
+ Node node = nodes.back();
+ nodes.pop_back();
+ for (OutArcIt it(*_digraph, node); it != INVALID; ++it) {
+ Node target = _digraph->target(it);
+ if ((*_node_order)[target] == -3) {
+ (*_node_order)[target] = -2;
+ nodes.push_back(target);
+ queue.push_back(target);
+ }
+ }
+ }
+ (*_node_order)[source] = -1;
+ }
+
+ /// \brief Processes the next node in the priority queue.
+ ///
+ /// Processes the next node in the priority queue.
+ ///
+ /// \return The processed node.
+ ///
+ /// \warning The queue must not be empty.
+ Node processNextNode() {
+ Node node = queue.back();
+ queue.pop_back();
+ if ((*_node_order)[node] == -2) {
+ Arc arc = prepare(node);
+ Node source = _digraph->source(arc);
+ while ((*_node_order)[source] != -1) {
+ if ((*_node_order)[source] >= 0) {
+ arc = contract(source);
+ } else {
+ arc = prepare(source);
+ }
+ source = _digraph->source(arc);
+ }
+ finalize(arc);
+ level_stack.clear();
+ }
+ return node;
+ }
+
+ /// \brief Returns the number of the nodes to be processed.
+ ///
+ /// Returns the number of the nodes to be processed in the priority
+ /// queue.
+ int queueSize() const {
+ return queue.size();
+ }
+
+ /// \brief Returns \c false if there are nodes to be processed.
+ ///
+ /// Returns \c false if there are nodes to be processed.
+ bool emptyQueue() const {
+ return queue.empty();
+ }
+
+ /// \brief Executes the algorithm.
+ ///
+ /// Executes the algorithm.
+ ///
+ /// \pre init() must be called and at least one node should be added
+ /// with addSource() before using this function.
+ ///
+ ///\note mca.start() is just a shortcut of the following code.
+ ///\code
+ ///while (!mca.emptyQueue()) {
+ /// mca.processNextNode();
+ ///}
+ ///\endcode
+ void start() {
+ while (!emptyQueue()) {
+ processNextNode();
+ }
+ }
+
+ /// \brief Runs %MinCostArborescence algorithm from node \c s.
+ ///
+ /// This method runs the %MinCostArborescence algorithm from
+ /// a root node \c s.
+ ///
+ /// \note mca.run(s) is just a shortcut of the following code.
+ /// \code
+ /// mca.init();
+ /// mca.addSource(s);
+ /// mca.start();
+ /// \endcode
+ void run(Node s) {
+ init();
+ addSource(s);
+ start();
+ }
+
+ ///@}
+
+ /// \name Query Functions
+ /// The result of the %MinCostArborescence algorithm can be obtained
+ /// using these functions.\n
+ /// Either run() or start() must be called before using them.
+
+ /// @{
+
+ /// \brief Returns the cost of the arborescence.
+ ///
+ /// Returns the cost of the arborescence.
+ Value arborescenceCost() const {
+ Value sum = 0;
+ for (ArcIt it(*_digraph); it != INVALID; ++it) {
+ if (arborescence(it)) {
+ sum += (*_cost)[it];
+ }
+ }
+ return sum;
+ }
+
+ /// \brief Returns \c true if the arc is in the arborescence.
+ ///
+ /// Returns \c true if the given arc is in the arborescence.
+ /// \param arc An arc of the digraph.
+ /// \pre \ref run() must be called before using this function.
+ bool arborescence(Arc arc) const {
+ return (*_pred)[_digraph->target(arc)] == arc;
+ }
+
+ /// \brief Returns a const reference to the arborescence map.
+ ///
+ /// Returns a const reference to the arborescence map.
+ /// \pre \ref run() must be called before using this function.
+ const ArborescenceMap& arborescenceMap() const {
+ return *_arborescence;
+ }
+
+ /// \brief Returns the predecessor arc of the given node.
+ ///
+ /// Returns the predecessor arc of the given node.
+ /// \pre \ref run() must be called before using this function.
+ Arc pred(Node node) const {
+ return (*_pred)[node];
+ }
+
+ /// \brief Returns a const reference to the pred map.
+ ///
+ /// Returns a const reference to the pred map.
+ /// \pre \ref run() must be called before using this function.
+ const PredMap& predMap() const {
+ return *_pred;
+ }
+
+ /// \brief Indicates that a node is reachable from the sources.
+ ///
+ /// Indicates that a node is reachable from the sources.
+ bool reached(Node node) const {
+ return (*_node_order)[node] != -3;
+ }
+
+ /// \brief Indicates that a node is processed.
+ ///
+ /// Indicates that a node is processed. The arborescence path exists
+ /// from the source to the given node.
+ bool processed(Node node) const {
+ return (*_node_order)[node] == -1;
+ }
+
+ /// \brief Returns the number of the dual variables in basis.
+ ///
+ /// Returns the number of the dual variables in basis.
+ int dualNum() const {
+ return _dual_variables.size();
+ }
+
+ /// \brief Returns the value of the dual solution.
+ ///
+ /// Returns the value of the dual solution. It should be
+ /// equal to the arborescence value.
+ Value dualValue() const {
+ Value sum = 0;
+ for (int i = 0; i < int(_dual_variables.size()); ++i) {
+ sum += _dual_variables[i].value;
+ }
+ return sum;
+ }
+
+ /// \brief Returns the number of the nodes in the dual variable.
+ ///
+ /// Returns the number of the nodes in the dual variable.
+ int dualSize(int k) const {
+ return _dual_variables[k].end - _dual_variables[k].begin;
+ }
+
+ /// \brief Returns the value of the dual variable.
+ ///
+ /// Returns the the value of the dual variable.
+ Value dualValue(int k) const {
+ return _dual_variables[k].value;
+ }
+
+ /// \brief LEMON iterator for getting a dual variable.
+ ///
+ /// This class provides a common style LEMON iterator for getting a
+ /// dual variable of \ref MinCostArborescence algorithm.
+ /// It iterates over a subset of the nodes.
+ class DualIt {
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor for getting the nodeset of the dual variable
+ /// of \ref MinCostArborescence algorithm.
+ DualIt(const MinCostArborescence& algorithm, int variable)
+ : _algorithm(&algorithm)
+ {
+ _index = _algorithm->_dual_variables[variable].begin;
+ _last = _algorithm->_dual_variables[variable].end;
+ }
+
+ /// \brief Conversion to \c Node.
+ ///
+ /// Conversion to \c Node.
+ operator Node() const {
+ return _algorithm->_dual_node_list[_index];
+ }
+
+ /// \brief Increment operator.
+ ///
+ /// Increment operator.
+ DualIt& operator++() {
+ ++_index;
+ return *this;
+ }
+
+ /// \brief Validity checking
+ ///
+ /// Checks whether the iterator is invalid.
+ bool operator==(Invalid) const {
+ return _index == _last;
+ }
+
+ /// \brief Validity checking
+ ///
+ /// Checks whether the iterator is valid.
+ bool operator!=(Invalid) const {
+ return _index != _last;
+ }
+
+ private:
+ const MinCostArborescence* _algorithm;
+ int _index, _last;
+ };
+
+ /// @}
+
+ };
+
+ /// \ingroup spantree
+ ///
+ /// \brief Function type interface for MinCostArborescence algorithm.
+ ///
+ /// Function type interface for MinCostArborescence algorithm.
+ /// \param digraph The digraph the algorithm runs on.
+ /// \param cost An arc map storing the costs.
+ /// \param source The source node of the arborescence.
+ /// \retval arborescence An arc map with \c bool (or convertible) value
+ /// type that stores the arborescence.
+ /// \return The total cost of the arborescence.
+ ///
+ /// \sa MinCostArborescence
+ template <typename Digraph, typename CostMap, typename ArborescenceMap>
+ typename CostMap::Value minCostArborescence(const Digraph& digraph,
+ const CostMap& cost,
+ typename Digraph::Node source,
+ ArborescenceMap& arborescence) {
+ typename MinCostArborescence<Digraph, CostMap>
+ ::template SetArborescenceMap<ArborescenceMap>
+ ::Create mca(digraph, cost);
+ mca.arborescenceMap(arborescence);
+ mca.run(source);
+ return mca.arborescenceCost();
+ }
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/nagamochi_ibaraki.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/nagamochi_ibaraki.h
new file mode 100644
index 00000000000..57a6ba64d2b
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/nagamochi_ibaraki.h
@@ -0,0 +1,702 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_NAGAMOCHI_IBARAKI_H
+#define LEMON_NAGAMOCHI_IBARAKI_H
+
+
+/// \ingroup min_cut
+/// \file
+/// \brief Implementation of the Nagamochi-Ibaraki algorithm.
+
+#include <lemon/core.h>
+#include <lemon/bin_heap.h>
+#include <lemon/bucket_heap.h>
+#include <lemon/maps.h>
+#include <lemon/radix_sort.h>
+#include <lemon/unionfind.h>
+
+#include <cassert>
+
+namespace lemon {
+
+ /// \brief Default traits class for NagamochiIbaraki class.
+ ///
+ /// Default traits class for NagamochiIbaraki class.
+ /// \param GR The undirected graph type.
+ /// \param CM Type of capacity map.
+ template <typename GR, typename CM>
+ struct NagamochiIbarakiDefaultTraits {
+ /// The type of the capacity map.
+ typedef typename CM::Value Value;
+
+ /// The undirected graph type the algorithm runs on.
+ typedef GR Graph;
+
+ /// \brief The type of the map that stores the edge capacities.
+ ///
+ /// The type of the map that stores the edge capacities.
+ /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
+ typedef CM CapacityMap;
+
+ /// \brief Instantiates a CapacityMap.
+ ///
+ /// This function instantiates a \ref CapacityMap.
+#ifdef DOXYGEN
+ static CapacityMap *createCapacityMap(const Graph& graph)
+#else
+ static CapacityMap *createCapacityMap(const Graph&)
+#endif
+ {
+ LEMON_ASSERT(false, "CapacityMap is not initialized");
+ return 0; // ignore warnings
+ }
+
+ /// \brief The cross reference type used by heap.
+ ///
+ /// The cross reference type used by heap.
+ /// Usually \c Graph::NodeMap<int>.
+ typedef typename Graph::template NodeMap<int> HeapCrossRef;
+
+ /// \brief Instantiates a HeapCrossRef.
+ ///
+ /// This function instantiates a \ref HeapCrossRef.
+ /// \param g is the graph, to which we would like to define the
+ /// \ref HeapCrossRef.
+ static HeapCrossRef *createHeapCrossRef(const Graph& g) {
+ return new HeapCrossRef(g);
+ }
+
+ /// \brief The heap type used by NagamochiIbaraki algorithm.
+ ///
+ /// The heap type used by NagamochiIbaraki algorithm. It has to
+ /// maximize the priorities.
+ ///
+ /// \sa BinHeap
+ /// \sa NagamochiIbaraki
+ typedef BinHeap<Value, HeapCrossRef, std::greater<Value> > Heap;
+
+ /// \brief Instantiates a Heap.
+ ///
+ /// This function instantiates a \ref Heap.
+ /// \param r is the cross reference of the heap.
+ static Heap *createHeap(HeapCrossRef& r) {
+ return new Heap(r);
+ }
+ };
+
+ /// \ingroup min_cut
+ ///
+ /// \brief Calculates the minimum cut in an undirected graph.
+ ///
+ /// Calculates the minimum cut in an undirected graph with the
+ /// Nagamochi-Ibaraki algorithm. The algorithm separates the graph's
+ /// nodes into two partitions with the minimum sum of edge capacities
+ /// between the two partitions. The algorithm can be used to test
+ /// the network reliability, especially to test how many links have
+ /// to be destroyed in the network to split it to at least two
+ /// distinict subnetworks.
+ ///
+ /// The complexity of the algorithm is \f$ O(nm\log(n)) \f$ but with
+ /// \ref FibHeap "Fibonacci heap" it can be decreased to
+ /// \f$ O(nm+n^2\log(n)) \f$. When the edges have unit capacities,
+ /// \c BucketHeap can be used which yields \f$ O(nm) \f$ time
+ /// complexity.
+ ///
+ /// \warning The value type of the capacity map should be able to
+ /// hold any cut value of the graph, otherwise the result can
+ /// overflow.
+ /// \note This capacity is supposed to be integer type.
+#ifdef DOXYGEN
+ template <typename GR, typename CM, typename TR>
+#else
+ template <typename GR,
+ typename CM = typename GR::template EdgeMap<int>,
+ typename TR = NagamochiIbarakiDefaultTraits<GR, CM> >
+#endif
+ class NagamochiIbaraki {
+ public:
+
+ typedef TR Traits;
+ /// The type of the underlying graph.
+ typedef typename Traits::Graph Graph;
+
+ /// The type of the capacity map.
+ typedef typename Traits::CapacityMap CapacityMap;
+ /// The value type of the capacity map.
+ typedef typename Traits::CapacityMap::Value Value;
+
+ /// The heap type used by the algorithm.
+ typedef typename Traits::Heap Heap;
+ /// The cross reference type used for the heap.
+ typedef typename Traits::HeapCrossRef HeapCrossRef;
+
+ ///\name Named template parameters
+
+ ///@{
+
+ struct SetUnitCapacityTraits : public Traits {
+ typedef ConstMap<typename Graph::Edge, Const<int, 1> > CapacityMap;
+ static CapacityMap *createCapacityMap(const Graph&) {
+ return new CapacityMap();
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// the capacity map to a constMap<Edge, int, 1>() instance
+ ///
+ /// \ref named-templ-param "Named parameter" for setting
+ /// the capacity map to a constMap<Edge, int, 1>() instance
+ struct SetUnitCapacity
+ : public NagamochiIbaraki<Graph, CapacityMap,
+ SetUnitCapacityTraits> {
+ typedef NagamochiIbaraki<Graph, CapacityMap,
+ SetUnitCapacityTraits> Create;
+ };
+
+
+ template <class H, class CR>
+ struct SetHeapTraits : public Traits {
+ typedef CR HeapCrossRef;
+ typedef H Heap;
+ static HeapCrossRef *createHeapCrossRef(int num) {
+ LEMON_ASSERT(false, "HeapCrossRef is not initialized");
+ return 0; // ignore warnings
+ }
+ static Heap *createHeap(HeapCrossRef &) {
+ LEMON_ASSERT(false, "Heap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// heap and cross reference type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting heap and
+ /// cross reference type. The heap has to maximize the priorities.
+ template <class H, class CR = RangeMap<int> >
+ struct SetHeap
+ : public NagamochiIbaraki<Graph, CapacityMap, SetHeapTraits<H, CR> > {
+ typedef NagamochiIbaraki< Graph, CapacityMap, SetHeapTraits<H, CR> >
+ Create;
+ };
+
+ template <class H, class CR>
+ struct SetStandardHeapTraits : public Traits {
+ typedef CR HeapCrossRef;
+ typedef H Heap;
+ static HeapCrossRef *createHeapCrossRef(int size) {
+ return new HeapCrossRef(size);
+ }
+ static Heap *createHeap(HeapCrossRef &crossref) {
+ return new Heap(crossref);
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// heap and cross reference type with automatic allocation
+ ///
+ /// \ref named-templ-param "Named parameter" for setting heap and
+ /// cross reference type with automatic allocation. They should
+ /// have standard constructor interfaces to be able to
+ /// automatically created by the algorithm (i.e. the graph should
+ /// be passed to the constructor of the cross reference and the
+ /// cross reference should be passed to the constructor of the
+ /// heap). However, external heap and cross reference objects
+ /// could also be passed to the algorithm using the \ref heap()
+ /// function before calling \ref run() or \ref init(). The heap
+ /// has to maximize the priorities.
+ /// \sa SetHeap
+ template <class H, class CR = RangeMap<int> >
+ struct SetStandardHeap
+ : public NagamochiIbaraki<Graph, CapacityMap,
+ SetStandardHeapTraits<H, CR> > {
+ typedef NagamochiIbaraki<Graph, CapacityMap,
+ SetStandardHeapTraits<H, CR> > Create;
+ };
+
+ ///@}
+
+
+ private:
+
+ const Graph &_graph;
+ const CapacityMap *_capacity;
+ bool _local_capacity; // unit capacity
+
+ struct ArcData {
+ typename Graph::Node target;
+ int prev, next;
+ };
+ struct EdgeData {
+ Value capacity;
+ Value cut;
+ };
+
+ struct NodeData {
+ int first_arc;
+ typename Graph::Node prev, next;
+ int curr_arc;
+ typename Graph::Node last_rep;
+ Value sum;
+ };
+
+ typename Graph::template NodeMap<NodeData> *_nodes;
+ std::vector<ArcData> _arcs;
+ std::vector<EdgeData> _edges;
+
+ typename Graph::Node _first_node;
+ int _node_num;
+
+ Value _min_cut;
+
+ HeapCrossRef *_heap_cross_ref;
+ bool _local_heap_cross_ref;
+ Heap *_heap;
+ bool _local_heap;
+
+ typedef typename Graph::template NodeMap<typename Graph::Node> NodeList;
+ NodeList *_next_rep;
+
+ typedef typename Graph::template NodeMap<bool> MinCutMap;
+ MinCutMap *_cut_map;
+
+ void createStructures() {
+ if (!_nodes) {
+ _nodes = new (typename Graph::template NodeMap<NodeData>)(_graph);
+ }
+ if (!_capacity) {
+ _local_capacity = true;
+ _capacity = Traits::createCapacityMap(_graph);
+ }
+ if (!_heap_cross_ref) {
+ _local_heap_cross_ref = true;
+ _heap_cross_ref = Traits::createHeapCrossRef(_graph);
+ }
+ if (!_heap) {
+ _local_heap = true;
+ _heap = Traits::createHeap(*_heap_cross_ref);
+ }
+ if (!_next_rep) {
+ _next_rep = new NodeList(_graph);
+ }
+ if (!_cut_map) {
+ _cut_map = new MinCutMap(_graph);
+ }
+ }
+
+ protected:
+ //This is here to avoid a gcc-3.3 compilation error.
+ //It should never be called.
+ NagamochiIbaraki() {}
+
+ public:
+
+ typedef NagamochiIbaraki Create;
+
+
+ /// \brief Constructor.
+ ///
+ /// \param graph The graph the algorithm runs on.
+ /// \param capacity The capacity map used by the algorithm.
+ NagamochiIbaraki(const Graph& graph, const CapacityMap& capacity)
+ : _graph(graph), _capacity(&capacity), _local_capacity(false),
+ _nodes(0), _arcs(), _edges(), _min_cut(),
+ _heap_cross_ref(0), _local_heap_cross_ref(false),
+ _heap(0), _local_heap(false),
+ _next_rep(0), _cut_map(0) {}
+
+ /// \brief Constructor.
+ ///
+ /// This constructor can be used only when the Traits class
+ /// defines how can the local capacity map be instantiated.
+ /// If the SetUnitCapacity used the algorithm automatically
+ /// constructs the capacity map.
+ ///
+ ///\param graph The graph the algorithm runs on.
+ NagamochiIbaraki(const Graph& graph)
+ : _graph(graph), _capacity(0), _local_capacity(false),
+ _nodes(0), _arcs(), _edges(), _min_cut(),
+ _heap_cross_ref(0), _local_heap_cross_ref(false),
+ _heap(0), _local_heap(false),
+ _next_rep(0), _cut_map(0) {}
+
+ /// \brief Destructor.
+ ///
+ /// Destructor.
+ ~NagamochiIbaraki() {
+ if (_local_capacity) delete _capacity;
+ if (_nodes) delete _nodes;
+ if (_local_heap) delete _heap;
+ if (_local_heap_cross_ref) delete _heap_cross_ref;
+ if (_next_rep) delete _next_rep;
+ if (_cut_map) delete _cut_map;
+ }
+
+ /// \brief Sets the heap and the cross reference used by algorithm.
+ ///
+ /// Sets the heap and the cross reference used by algorithm.
+ /// If you don't use this function before calling \ref run(),
+ /// it will allocate one. The destuctor deallocates this
+ /// automatically allocated heap and cross reference, of course.
+ /// \return <tt> (*this) </tt>
+ NagamochiIbaraki &heap(Heap& hp, HeapCrossRef &cr)
+ {
+ if (_local_heap_cross_ref) {
+ delete _heap_cross_ref;
+ _local_heap_cross_ref = false;
+ }
+ _heap_cross_ref = &cr;
+ if (_local_heap) {
+ delete _heap;
+ _local_heap = false;
+ }
+ _heap = &hp;
+ return *this;
+ }
+
+ /// \name Execution control
+ /// The simplest way to execute the algorithm is to use
+ /// one of the member functions called \c run().
+ /// \n
+ /// If you need more control on the execution,
+ /// first you must call \ref init() and then call the start()
+ /// or proper times the processNextPhase() member functions.
+
+ ///@{
+
+ /// \brief Initializes the internal data structures.
+ ///
+ /// Initializes the internal data structures.
+ void init() {
+ createStructures();
+
+ int edge_num = countEdges(_graph);
+ _edges.resize(edge_num);
+ _arcs.resize(2 * edge_num);
+
+ typename Graph::Node prev = INVALID;
+ _node_num = 0;
+ for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) {
+ (*_cut_map)[n] = false;
+ (*_next_rep)[n] = INVALID;
+ (*_nodes)[n].last_rep = n;
+ (*_nodes)[n].first_arc = -1;
+ (*_nodes)[n].curr_arc = -1;
+ (*_nodes)[n].prev = prev;
+ if (prev != INVALID) {
+ (*_nodes)[prev].next = n;
+ }
+ (*_nodes)[n].next = INVALID;
+ (*_nodes)[n].sum = 0;
+ prev = n;
+ ++_node_num;
+ }
+
+ _first_node = typename Graph::NodeIt(_graph);
+
+ int index = 0;
+ for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) {
+ for (typename Graph::OutArcIt a(_graph, n); a != INVALID; ++a) {
+ typename Graph::Node m = _graph.target(a);
+
+ if (!(n < m)) continue;
+
+ (*_nodes)[n].sum += (*_capacity)[a];
+ (*_nodes)[m].sum += (*_capacity)[a];
+
+ int c = (*_nodes)[m].curr_arc;
+ if (c != -1 && _arcs[c ^ 1].target == n) {
+ _edges[c >> 1].capacity += (*_capacity)[a];
+ } else {
+ _edges[index].capacity = (*_capacity)[a];
+
+ _arcs[index << 1].prev = -1;
+ if ((*_nodes)[n].first_arc != -1) {
+ _arcs[(*_nodes)[n].first_arc].prev = (index << 1);
+ }
+ _arcs[index << 1].next = (*_nodes)[n].first_arc;
+ (*_nodes)[n].first_arc = (index << 1);
+ _arcs[index << 1].target = m;
+
+ (*_nodes)[m].curr_arc = (index << 1);
+
+ _arcs[(index << 1) | 1].prev = -1;
+ if ((*_nodes)[m].first_arc != -1) {
+ _arcs[(*_nodes)[m].first_arc].prev = ((index << 1) | 1);
+ }
+ _arcs[(index << 1) | 1].next = (*_nodes)[m].first_arc;
+ (*_nodes)[m].first_arc = ((index << 1) | 1);
+ _arcs[(index << 1) | 1].target = n;
+
+ ++index;
+ }
+ }
+ }
+
+ typename Graph::Node cut_node = INVALID;
+ _min_cut = std::numeric_limits<Value>::max();
+
+ for (typename Graph::Node n = _first_node;
+ n != INVALID; n = (*_nodes)[n].next) {
+ if ((*_nodes)[n].sum < _min_cut) {
+ cut_node = n;
+ _min_cut = (*_nodes)[n].sum;
+ }
+ }
+ (*_cut_map)[cut_node] = true;
+ if (_min_cut == 0) {
+ _first_node = INVALID;
+ }
+ }
+
+ public:
+
+ /// \brief Processes the next phase
+ ///
+ /// Processes the next phase in the algorithm. It must be called
+ /// at most one less the number of the nodes in the graph.
+ ///
+ ///\return %True when the algorithm finished.
+ bool processNextPhase() {
+ if (_first_node == INVALID) return true;
+
+ _heap->clear();
+ for (typename Graph::Node n = _first_node;
+ n != INVALID; n = (*_nodes)[n].next) {
+ (*_heap_cross_ref)[n] = Heap::PRE_HEAP;
+ }
+
+ std::vector<typename Graph::Node> order;
+ order.reserve(_node_num);
+ int sep = 0;
+
+ Value alpha = 0;
+ Value pmc = std::numeric_limits<Value>::max();
+
+ _heap->push(_first_node, static_cast<Value>(0));
+ while (!_heap->empty()) {
+ typename Graph::Node n = _heap->top();
+ Value v = _heap->prio();
+
+ _heap->pop();
+ for (int a = (*_nodes)[n].first_arc; a != -1; a = _arcs[a].next) {
+ switch (_heap->state(_arcs[a].target)) {
+ case Heap::PRE_HEAP:
+ {
+ Value nv = _edges[a >> 1].capacity;
+ _heap->push(_arcs[a].target, nv);
+ _edges[a >> 1].cut = nv;
+ } break;
+ case Heap::IN_HEAP:
+ {
+ Value nv = _edges[a >> 1].capacity + (*_heap)[_arcs[a].target];
+ _heap->decrease(_arcs[a].target, nv);
+ _edges[a >> 1].cut = nv;
+ } break;
+ case Heap::POST_HEAP:
+ break;
+ }
+ }
+
+ alpha += (*_nodes)[n].sum;
+ alpha -= 2 * v;
+
+ order.push_back(n);
+ if (!_heap->empty()) {
+ if (alpha < pmc) {
+ pmc = alpha;
+ sep = order.size();
+ }
+ }
+ }
+
+ if (static_cast<int>(order.size()) < _node_num) {
+ _first_node = INVALID;
+ for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) {
+ (*_cut_map)[n] = false;
+ }
+ for (int i = 0; i < static_cast<int>(order.size()); ++i) {
+ typename Graph::Node n = order[i];
+ while (n != INVALID) {
+ (*_cut_map)[n] = true;
+ n = (*_next_rep)[n];
+ }
+ }
+ _min_cut = 0;
+ return true;
+ }
+
+ if (pmc < _min_cut) {
+ for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) {
+ (*_cut_map)[n] = false;
+ }
+ for (int i = 0; i < sep; ++i) {
+ typename Graph::Node n = order[i];
+ while (n != INVALID) {
+ (*_cut_map)[n] = true;
+ n = (*_next_rep)[n];
+ }
+ }
+ _min_cut = pmc;
+ }
+
+ for (typename Graph::Node n = _first_node;
+ n != INVALID; n = (*_nodes)[n].next) {
+ bool merged = false;
+ for (int a = (*_nodes)[n].first_arc; a != -1; a = _arcs[a].next) {
+ if (!(_edges[a >> 1].cut < pmc)) {
+ if (!merged) {
+ for (int b = (*_nodes)[n].first_arc; b != -1; b = _arcs[b].next) {
+ (*_nodes)[_arcs[b].target].curr_arc = b;
+ }
+ merged = true;
+ }
+ typename Graph::Node m = _arcs[a].target;
+ int nb = 0;
+ for (int b = (*_nodes)[m].first_arc; b != -1; b = nb) {
+ nb = _arcs[b].next;
+ if ((b ^ a) == 1) continue;
+ typename Graph::Node o = _arcs[b].target;
+ int c = (*_nodes)[o].curr_arc;
+ if (c != -1 && _arcs[c ^ 1].target == n) {
+ _edges[c >> 1].capacity += _edges[b >> 1].capacity;
+ (*_nodes)[n].sum += _edges[b >> 1].capacity;
+ if (_edges[b >> 1].cut < _edges[c >> 1].cut) {
+ _edges[b >> 1].cut = _edges[c >> 1].cut;
+ }
+ if (_arcs[b ^ 1].prev != -1) {
+ _arcs[_arcs[b ^ 1].prev].next = _arcs[b ^ 1].next;
+ } else {
+ (*_nodes)[o].first_arc = _arcs[b ^ 1].next;
+ }
+ if (_arcs[b ^ 1].next != -1) {
+ _arcs[_arcs[b ^ 1].next].prev = _arcs[b ^ 1].prev;
+ }
+ } else {
+ if (_arcs[a].next != -1) {
+ _arcs[_arcs[a].next].prev = b;
+ }
+ _arcs[b].next = _arcs[a].next;
+ _arcs[b].prev = a;
+ _arcs[a].next = b;
+ _arcs[b ^ 1].target = n;
+
+ (*_nodes)[n].sum += _edges[b >> 1].capacity;
+ (*_nodes)[o].curr_arc = b;
+ }
+ }
+
+ if (_arcs[a].prev != -1) {
+ _arcs[_arcs[a].prev].next = _arcs[a].next;
+ } else {
+ (*_nodes)[n].first_arc = _arcs[a].next;
+ }
+ if (_arcs[a].next != -1) {
+ _arcs[_arcs[a].next].prev = _arcs[a].prev;
+ }
+
+ (*_nodes)[n].sum -= _edges[a >> 1].capacity;
+ (*_next_rep)[(*_nodes)[n].last_rep] = m;
+ (*_nodes)[n].last_rep = (*_nodes)[m].last_rep;
+
+ if ((*_nodes)[m].prev != INVALID) {
+ (*_nodes)[(*_nodes)[m].prev].next = (*_nodes)[m].next;
+ } else{
+ _first_node = (*_nodes)[m].next;
+ }
+ if ((*_nodes)[m].next != INVALID) {
+ (*_nodes)[(*_nodes)[m].next].prev = (*_nodes)[m].prev;
+ }
+ --_node_num;
+ }
+ }
+ }
+
+ if (_node_num == 1) {
+ _first_node = INVALID;
+ return true;
+ }
+
+ return false;
+ }
+
+ /// \brief Executes the algorithm.
+ ///
+ /// Executes the algorithm.
+ ///
+ /// \pre init() must be called
+ void start() {
+ while (!processNextPhase()) {}
+ }
+
+
+ /// \brief Runs %NagamochiIbaraki algorithm.
+ ///
+ /// This method runs the %Min cut algorithm
+ ///
+ /// \note mc.run(s) is just a shortcut of the following code.
+ ///\code
+ /// mc.init();
+ /// mc.start();
+ ///\endcode
+ void run() {
+ init();
+ start();
+ }
+
+ ///@}
+
+ /// \name Query Functions
+ ///
+ /// The result of the %NagamochiIbaraki
+ /// algorithm can be obtained using these functions.\n
+ /// Before the use of these functions, either run() or start()
+ /// must be called.
+
+ ///@{
+
+ /// \brief Returns the min cut value.
+ ///
+ /// Returns the min cut value if the algorithm finished.
+ /// After the first processNextPhase() it is a value of a
+ /// valid cut in the graph.
+ Value minCutValue() const {
+ return _min_cut;
+ }
+
+ /// \brief Returns a min cut in a NodeMap.
+ ///
+ /// It sets the nodes of one of the two partitions to true and
+ /// the other partition to false.
+ /// \param cutMap A \ref concepts::WriteMap "writable" node map with
+ /// \c bool (or convertible) value type.
+ template <typename CutMap>
+ Value minCutMap(CutMap& cutMap) const {
+ for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) {
+ cutMap.set(n, (*_cut_map)[n]);
+ }
+ return minCutValue();
+ }
+
+ ///@}
+
+ };
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/nauty_reader.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/nauty_reader.h
new file mode 100644
index 00000000000..896f2a606bb
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/nauty_reader.h
@@ -0,0 +1,113 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_NAUTY_READER_H
+#define LEMON_NAUTY_READER_H
+
+#include <vector>
+#include <iostream>
+#include <string>
+
+/// \ingroup nauty_group
+/// \file
+/// \brief Nauty file reader.
+
+namespace lemon {
+
+ /// \ingroup nauty_group
+ ///
+ /// \brief Nauty file reader
+ ///
+ /// The \e geng program is in the \e gtools suite of the nauty
+ /// package. This tool can generate all non-isomorphic undirected
+ /// graphs of several classes with given node number (e.g.
+ /// general, connected, biconnected, triangle-free, 4-cycle-free,
+ /// bipartite and graphs with given edge number and degree
+ /// constraints). This function reads a \e nauty \e graph6 \e format
+ /// line from the given stream and builds it in the given graph.
+ ///
+ /// The site of nauty package: http://cs.anu.edu.au/~bdm/nauty/
+ ///
+ /// For example, the number of all non-isomorphic planar graphs
+ /// can be computed with the following code.
+ ///\code
+ /// int num = 0;
+ /// SmartGraph graph;
+ /// while (readNautyGraph(graph, std::cin)) {
+ /// PlanarityChecking<SmartGraph> pc(graph);
+ /// if (pc.run()) ++num;
+ /// }
+ /// std::cout << "Number of planar graphs: " << num << std::endl;
+ ///\endcode
+ ///
+ /// The nauty files are quite huge, therefore instead of the direct
+ /// file generation pipelining is recommended. For example,
+ ///\code
+ /// ./geng -c 10 | ./num_of_planar_graphs
+ ///\endcode
+ template <typename Graph>
+ std::istream& readNautyGraph(Graph& graph, std::istream& is = std::cin) {
+ graph.clear();
+
+ std::string line;
+ if (getline(is, line)) {
+ int index = 0;
+
+ int n;
+
+ if (line[index] == '>') {
+ index += 10;
+ }
+
+ char c = line[index++]; c -= 63;
+ if (c != 63) {
+ n = int(c);
+ } else {
+ c = line[index++]; c -= 63;
+ n = (int(c) << 12);
+ c = line[index++]; c -= 63;
+ n |= (int(c) << 6);
+ c = line[index++]; c -= 63;
+ n |= int(c);
+ }
+
+ std::vector<typename Graph::Node> nodes;
+ for (int i = 0; i < n; ++i) {
+ nodes.push_back(graph.addNode());
+ }
+
+ int bit = -1;
+ for (int j = 0; j < n; ++j) {
+ for (int i = 0; i < j; ++i) {
+ if (bit == -1) {
+ c = line[index++]; c -= 63;
+ bit = 5;
+ }
+ bool b = (c & (1 << (bit--))) != 0;
+
+ if (b) {
+ graph.addEdge(nodes[i], nodes[j]);
+ }
+ }
+ }
+ }
+ return is;
+ }
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/nearest_neighbor_tsp.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/nearest_neighbor_tsp.h
new file mode 100644
index 00000000000..065e145df08
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/nearest_neighbor_tsp.h
@@ -0,0 +1,238 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_NEAREST_NEIGHBOUR_TSP_H
+#define LEMON_NEAREST_NEIGHBOUR_TSP_H
+
+/// \ingroup tsp
+/// \file
+/// \brief Nearest neighbor algorithm for symmetric TSP
+
+#include <deque>
+#include <vector>
+#include <limits>
+#include <lemon/full_graph.h>
+#include <lemon/maps.h>
+
+namespace lemon {
+
+ /// \ingroup tsp
+ ///
+ /// \brief Nearest neighbor algorithm for symmetric TSP.
+ ///
+ /// NearestNeighborTsp implements the nearest neighbor heuristic for solving
+ /// symmetric \ref tsp "TSP".
+ ///
+ /// This is probably the simplest TSP heuristic.
+ /// It starts with a minimum cost edge and at each step, it connects the
+ /// nearest unvisited node to the current path.
+ /// Finally, it connects the two end points of the path to form a tour.
+ ///
+ /// This method runs in O(n<sup>2</sup>) time.
+ /// It quickly finds a relatively short tour for most TSP instances,
+ /// but it could also yield a really bad (or even the worst) solution
+ /// in special cases.
+ ///
+ /// \tparam CM Type of the cost map.
+ template <typename CM>
+ class NearestNeighborTsp
+ {
+ public:
+
+ /// Type of the cost map
+ typedef CM CostMap;
+ /// Type of the edge costs
+ typedef typename CM::Value Cost;
+
+ private:
+
+ GRAPH_TYPEDEFS(FullGraph);
+
+ const FullGraph &_gr;
+ const CostMap &_cost;
+ Cost _sum;
+ std::vector<Node> _path;
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ /// \param gr The \ref FullGraph "full graph" the algorithm runs on.
+ /// \param cost The cost map.
+ NearestNeighborTsp(const FullGraph &gr, const CostMap &cost)
+ : _gr(gr), _cost(cost) {}
+
+ /// \name Execution Control
+ /// @{
+
+ /// \brief Runs the algorithm.
+ ///
+ /// This function runs the algorithm.
+ ///
+ /// \return The total cost of the found tour.
+ Cost run() {
+ _path.clear();
+ if (_gr.nodeNum() == 0) {
+ return _sum = 0;
+ }
+ else if (_gr.nodeNum() == 1) {
+ _path.push_back(_gr(0));
+ return _sum = 0;
+ }
+
+ std::deque<Node> path_dq;
+ Edge min_edge1 = INVALID,
+ min_edge2 = INVALID;
+
+ min_edge1 = mapMin(_gr, _cost);
+ Node n1 = _gr.u(min_edge1),
+ n2 = _gr.v(min_edge1);
+ path_dq.push_back(n1);
+ path_dq.push_back(n2);
+
+ FullGraph::NodeMap<bool> used(_gr, false);
+ used[n1] = true;
+ used[n2] = true;
+
+ min_edge1 = INVALID;
+ while (int(path_dq.size()) != _gr.nodeNum()) {
+ if (min_edge1 == INVALID) {
+ for (IncEdgeIt e(_gr, n1); e != INVALID; ++e) {
+ if (!used[_gr.runningNode(e)] &&
+ (min_edge1 == INVALID || _cost[e] < _cost[min_edge1])) {
+ min_edge1 = e;
+ }
+ }
+ }
+
+ if (min_edge2 == INVALID) {
+ for (IncEdgeIt e(_gr, n2); e != INVALID; ++e) {
+ if (!used[_gr.runningNode(e)] &&
+ (min_edge2 == INVALID||_cost[e] < _cost[min_edge2])) {
+ min_edge2 = e;
+ }
+ }
+ }
+
+ if (_cost[min_edge1] < _cost[min_edge2]) {
+ n1 = _gr.oppositeNode(n1, min_edge1);
+ path_dq.push_front(n1);
+
+ used[n1] = true;
+ min_edge1 = INVALID;
+
+ if (_gr.u(min_edge2) == n1 || _gr.v(min_edge2) == n1)
+ min_edge2 = INVALID;
+ } else {
+ n2 = _gr.oppositeNode(n2, min_edge2);
+ path_dq.push_back(n2);
+
+ used[n2] = true;
+ min_edge2 = INVALID;
+
+ if (_gr.u(min_edge1) == n2 || _gr.v(min_edge1) == n2)
+ min_edge1 = INVALID;
+ }
+ }
+
+ n1 = path_dq.back();
+ n2 = path_dq.front();
+ _path.push_back(n2);
+ _sum = _cost[_gr.edge(n1, n2)];
+ for (int i = 1; i < int(path_dq.size()); ++i) {
+ n1 = n2;
+ n2 = path_dq[i];
+ _path.push_back(n2);
+ _sum += _cost[_gr.edge(n1, n2)];
+ }
+
+ return _sum;
+ }
+
+ /// @}
+
+ /// \name Query Functions
+ /// @{
+
+ /// \brief The total cost of the found tour.
+ ///
+ /// This function returns the total cost of the found tour.
+ ///
+ /// \pre run() must be called before using this function.
+ Cost tourCost() const {
+ return _sum;
+ }
+
+ /// \brief Returns a const reference to the node sequence of the
+ /// found tour.
+ ///
+ /// This function returns a const reference to a vector
+ /// that stores the node sequence of the found tour.
+ ///
+ /// \pre run() must be called before using this function.
+ const std::vector<Node>& tourNodes() const {
+ return _path;
+ }
+
+ /// \brief Gives back the node sequence of the found tour.
+ ///
+ /// This function copies the node sequence of the found tour into
+ /// an STL container through the given output iterator. The
+ /// <tt>value_type</tt> of the container must be <tt>FullGraph::Node</tt>.
+ /// For example,
+ /// \code
+ /// std::vector<FullGraph::Node> nodes(countNodes(graph));
+ /// tsp.tourNodes(nodes.begin());
+ /// \endcode
+ /// or
+ /// \code
+ /// std::list<FullGraph::Node> nodes;
+ /// tsp.tourNodes(std::back_inserter(nodes));
+ /// \endcode
+ ///
+ /// \pre run() must be called before using this function.
+ template <typename Iterator>
+ void tourNodes(Iterator out) const {
+ std::copy(_path.begin(), _path.end(), out);
+ }
+
+ /// \brief Gives back the found tour as a path.
+ ///
+ /// This function copies the found tour as a list of arcs/edges into
+ /// the given \ref lemon::concepts::Path "path structure".
+ ///
+ /// \pre run() must be called before using this function.
+ template <typename Path>
+ void tour(Path &path) const {
+ path.clear();
+ for (int i = 0; i < int(_path.size()) - 1; ++i) {
+ path.addBack(_gr.arc(_path[i], _path[i+1]));
+ }
+ if (int(_path.size()) >= 2) {
+ path.addBack(_gr.arc(_path.back(), _path.front()));
+ }
+ }
+
+ /// @}
+
+ };
+
+}; // namespace lemon
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/network_simplex.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/network_simplex.h
new file mode 100644
index 00000000000..6ccad33e68e
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/network_simplex.h
@@ -0,0 +1,1659 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_NETWORK_SIMPLEX_H
+#define LEMON_NETWORK_SIMPLEX_H
+
+/// \ingroup min_cost_flow_algs
+///
+/// \file
+/// \brief Network Simplex algorithm for finding a minimum cost flow.
+
+#include <vector>
+#include <limits>
+#include <algorithm>
+
+#include <lemon/core.h>
+#include <lemon/math.h>
+
+namespace lemon {
+
+ /// \addtogroup min_cost_flow_algs
+ /// @{
+
+ /// \brief Implementation of the primal Network Simplex algorithm
+ /// for finding a \ref min_cost_flow "minimum cost flow".
+ ///
+ /// \ref NetworkSimplex implements the primal Network Simplex algorithm
+ /// for finding a \ref min_cost_flow "minimum cost flow"
+ /// \cite amo93networkflows, \cite dantzig63linearprog,
+ /// \cite kellyoneill91netsimplex.
+ /// This algorithm is a highly efficient specialized version of the
+ /// linear programming simplex method directly for the minimum cost
+ /// flow problem.
+ ///
+ /// In general, \ref NetworkSimplex and \ref CostScaling are the fastest
+ /// implementations available in LEMON for solving this problem.
+ /// (For more information, see \ref min_cost_flow_algs "the module page".)
+ /// Furthermore, this class supports both directions of the supply/demand
+ /// inequality constraints. For more information, see \ref SupplyType.
+ ///
+ /// Most of the parameters of the problem (except for the digraph)
+ /// can be given using separate functions, and the algorithm can be
+ /// executed using the \ref run() function. If some parameters are not
+ /// specified, then default values will be used.
+ ///
+ /// \tparam GR The digraph type the algorithm runs on.
+ /// \tparam V The number type used for flow amounts, capacity bounds
+ /// and supply values in the algorithm. By default, it is \c int.
+ /// \tparam C The number type used for costs and potentials in the
+ /// algorithm. By default, it is the same as \c V.
+ ///
+ /// \warning Both \c V and \c C must be signed number types.
+ /// \warning All input data (capacities, supply values, and costs) must
+ /// be integer.
+ ///
+ /// \note %NetworkSimplex provides five different pivot rule
+ /// implementations, from which the most efficient one is used
+ /// by default. For more information, see \ref PivotRule.
+ template <typename GR, typename V = int, typename C = V>
+ class NetworkSimplex
+ {
+ public:
+
+ /// The type of the flow amounts, capacity bounds and supply values
+ typedef V Value;
+ /// The type of the arc costs
+ typedef C Cost;
+
+ public:
+
+ /// \brief Problem type constants for the \c run() function.
+ ///
+ /// Enum type containing the problem type constants that can be
+ /// returned by the \ref run() function of the algorithm.
+ enum ProblemType {
+ /// The problem has no feasible solution (flow).
+ INFEASIBLE,
+ /// The problem has optimal solution (i.e. it is feasible and
+ /// bounded), and the algorithm has found optimal flow and node
+ /// potentials (primal and dual solutions).
+ OPTIMAL,
+ /// The objective function of the problem is unbounded, i.e.
+ /// there is a directed cycle having negative total cost and
+ /// infinite upper bound.
+ UNBOUNDED
+ };
+
+ /// \brief Constants for selecting the type of the supply constraints.
+ ///
+ /// Enum type containing constants for selecting the supply type,
+ /// i.e. the direction of the inequalities in the supply/demand
+ /// constraints of the \ref min_cost_flow "minimum cost flow problem".
+ ///
+ /// The default supply type is \c GEQ, the \c LEQ type can be
+ /// selected using \ref supplyType().
+ /// The equality form is a special case of both supply types.
+ enum SupplyType {
+ /// This option means that there are <em>"greater or equal"</em>
+ /// supply/demand constraints in the definition of the problem.
+ GEQ,
+ /// This option means that there are <em>"less or equal"</em>
+ /// supply/demand constraints in the definition of the problem.
+ LEQ
+ };
+
+ /// \brief Constants for selecting the pivot rule.
+ ///
+ /// Enum type containing constants for selecting the pivot rule for
+ /// the \ref run() function.
+ ///
+ /// \ref NetworkSimplex provides five different implementations for
+ /// the pivot strategy that significantly affects the running time
+ /// of the algorithm.
+ /// According to experimental tests conducted on various problem
+ /// instances, \ref BLOCK_SEARCH "Block Search" and
+ /// \ref ALTERING_LIST "Altering Candidate List" rules turned out
+ /// to be the most efficient.
+ /// Since \ref BLOCK_SEARCH "Block Search" is a simpler strategy that
+ /// seemed to be slightly more robust, it is used by default.
+ /// However, another pivot rule can easily be selected using the
+ /// \ref run() function with the proper parameter.
+ enum PivotRule {
+
+ /// The \e First \e Eligible pivot rule.
+ /// The next eligible arc is selected in a wraparound fashion
+ /// in every iteration.
+ FIRST_ELIGIBLE,
+
+ /// The \e Best \e Eligible pivot rule.
+ /// The best eligible arc is selected in every iteration.
+ BEST_ELIGIBLE,
+
+ /// The \e Block \e Search pivot rule.
+ /// A specified number of arcs are examined in every iteration
+ /// in a wraparound fashion and the best eligible arc is selected
+ /// from this block.
+ BLOCK_SEARCH,
+
+ /// The \e Candidate \e List pivot rule.
+ /// In a major iteration a candidate list is built from eligible arcs
+ /// in a wraparound fashion and in the following minor iterations
+ /// the best eligible arc is selected from this list.
+ CANDIDATE_LIST,
+
+ /// The \e Altering \e Candidate \e List pivot rule.
+ /// It is a modified version of the Candidate List method.
+ /// It keeps only a few of the best eligible arcs from the former
+ /// candidate list and extends this list in every iteration.
+ ALTERING_LIST
+ };
+
+ private:
+
+ TEMPLATE_DIGRAPH_TYPEDEFS(GR);
+
+ typedef std::vector<int> IntVector;
+ typedef std::vector<Value> ValueVector;
+ typedef std::vector<Cost> CostVector;
+ typedef std::vector<signed char> CharVector;
+ // Note: vector<signed char> is used instead of vector<ArcState> and
+ // vector<ArcDirection> for efficiency reasons
+
+ // State constants for arcs
+ enum ArcState {
+ STATE_UPPER = -1,
+ STATE_TREE = 0,
+ STATE_LOWER = 1
+ };
+
+ // Direction constants for tree arcs
+ enum ArcDirection {
+ DIR_DOWN = -1,
+ DIR_UP = 1
+ };
+
+ private:
+
+ // Data related to the underlying digraph
+ const GR &_graph;
+ int _node_num;
+ int _arc_num;
+ int _all_arc_num;
+ int _search_arc_num;
+
+ // Parameters of the problem
+ bool _has_lower;
+ SupplyType _stype;
+ Value _sum_supply;
+
+ // Data structures for storing the digraph
+ IntNodeMap _node_id;
+ IntArcMap _arc_id;
+ IntVector _source;
+ IntVector _target;
+ bool _arc_mixing;
+
+ // Node and arc data
+ ValueVector _lower;
+ ValueVector _upper;
+ ValueVector _cap;
+ CostVector _cost;
+ ValueVector _supply;
+ ValueVector _flow;
+ CostVector _pi;
+
+ // Data for storing the spanning tree structure
+ IntVector _parent;
+ IntVector _pred;
+ IntVector _thread;
+ IntVector _rev_thread;
+ IntVector _succ_num;
+ IntVector _last_succ;
+ CharVector _pred_dir;
+ CharVector _state;
+ IntVector _dirty_revs;
+ int _root;
+
+ // Temporary data used in the current pivot iteration
+ int in_arc, join, u_in, v_in, u_out, v_out;
+ Value delta;
+
+ const Value MAX;
+
+ public:
+
+ /// \brief Constant for infinite upper bounds (capacities).
+ ///
+ /// Constant for infinite upper bounds (capacities).
+ /// It is \c std::numeric_limits<Value>::infinity() if available,
+ /// \c std::numeric_limits<Value>::max() otherwise.
+ const Value INF;
+
+ private:
+
+ // Implementation of the First Eligible pivot rule
+ class FirstEligiblePivotRule
+ {
+ private:
+
+ // References to the NetworkSimplex class
+ const IntVector &_source;
+ const IntVector &_target;
+ const CostVector &_cost;
+ const CharVector &_state;
+ const CostVector &_pi;
+ int &_in_arc;
+ int _search_arc_num;
+
+ // Pivot rule data
+ int _next_arc;
+
+ public:
+
+ // Constructor
+ FirstEligiblePivotRule(NetworkSimplex &ns) :
+ _source(ns._source), _target(ns._target),
+ _cost(ns._cost), _state(ns._state), _pi(ns._pi),
+ _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
+ _next_arc(0)
+ {}
+
+ // Find next entering arc
+ bool findEnteringArc() {
+ Cost c;
+ for (int e = _next_arc; e != _search_arc_num; ++e) {
+ c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
+ if (c < 0) {
+ _in_arc = e;
+ _next_arc = e + 1;
+ return true;
+ }
+ }
+ for (int e = 0; e != _next_arc; ++e) {
+ c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
+ if (c < 0) {
+ _in_arc = e;
+ _next_arc = e + 1;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ }; //class FirstEligiblePivotRule
+
+
+ // Implementation of the Best Eligible pivot rule
+ class BestEligiblePivotRule
+ {
+ private:
+
+ // References to the NetworkSimplex class
+ const IntVector &_source;
+ const IntVector &_target;
+ const CostVector &_cost;
+ const CharVector &_state;
+ const CostVector &_pi;
+ int &_in_arc;
+ int _search_arc_num;
+
+ public:
+
+ // Constructor
+ BestEligiblePivotRule(NetworkSimplex &ns) :
+ _source(ns._source), _target(ns._target),
+ _cost(ns._cost), _state(ns._state), _pi(ns._pi),
+ _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num)
+ {}
+
+ // Find next entering arc
+ bool findEnteringArc() {
+ Cost c, min = 0;
+ for (int e = 0; e != _search_arc_num; ++e) {
+ c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
+ if (c < min) {
+ min = c;
+ _in_arc = e;
+ }
+ }
+ return min < 0;
+ }
+
+ }; //class BestEligiblePivotRule
+
+
+ // Implementation of the Block Search pivot rule
+ class BlockSearchPivotRule
+ {
+ private:
+
+ // References to the NetworkSimplex class
+ const IntVector &_source;
+ const IntVector &_target;
+ const CostVector &_cost;
+ const CharVector &_state;
+ const CostVector &_pi;
+ int &_in_arc;
+ int _search_arc_num;
+
+ // Pivot rule data
+ int _block_size;
+ int _next_arc;
+
+ public:
+
+ // Constructor
+ BlockSearchPivotRule(NetworkSimplex &ns) :
+ _source(ns._source), _target(ns._target),
+ _cost(ns._cost), _state(ns._state), _pi(ns._pi),
+ _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
+ _next_arc(0)
+ {
+ // The main parameters of the pivot rule
+ const double BLOCK_SIZE_FACTOR = 1.0;
+ const int MIN_BLOCK_SIZE = 10;
+
+ _block_size = std::max( int(BLOCK_SIZE_FACTOR *
+ std::sqrt(double(_search_arc_num))),
+ MIN_BLOCK_SIZE );
+ }
+
+ // Find next entering arc
+ bool findEnteringArc() {
+ Cost c, min = 0;
+ int cnt = _block_size;
+ int e;
+ for (e = _next_arc; e != _search_arc_num; ++e) {
+ c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
+ if (c < min) {
+ min = c;
+ _in_arc = e;
+ }
+ if (--cnt == 0) {
+ if (min < 0) goto search_end;
+ cnt = _block_size;
+ }
+ }
+ for (e = 0; e != _next_arc; ++e) {
+ c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
+ if (c < min) {
+ min = c;
+ _in_arc = e;
+ }
+ if (--cnt == 0) {
+ if (min < 0) goto search_end;
+ cnt = _block_size;
+ }
+ }
+ if (min >= 0) return false;
+
+ search_end:
+ _next_arc = e;
+ return true;
+ }
+
+ }; //class BlockSearchPivotRule
+
+
+ // Implementation of the Candidate List pivot rule
+ class CandidateListPivotRule
+ {
+ private:
+
+ // References to the NetworkSimplex class
+ const IntVector &_source;
+ const IntVector &_target;
+ const CostVector &_cost;
+ const CharVector &_state;
+ const CostVector &_pi;
+ int &_in_arc;
+ int _search_arc_num;
+
+ // Pivot rule data
+ IntVector _candidates;
+ int _list_length, _minor_limit;
+ int _curr_length, _minor_count;
+ int _next_arc;
+
+ public:
+
+ /// Constructor
+ CandidateListPivotRule(NetworkSimplex &ns) :
+ _source(ns._source), _target(ns._target),
+ _cost(ns._cost), _state(ns._state), _pi(ns._pi),
+ _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
+ _next_arc(0)
+ {
+ // The main parameters of the pivot rule
+ const double LIST_LENGTH_FACTOR = 0.25;
+ const int MIN_LIST_LENGTH = 10;
+ const double MINOR_LIMIT_FACTOR = 0.1;
+ const int MIN_MINOR_LIMIT = 3;
+
+ _list_length = std::max( int(LIST_LENGTH_FACTOR *
+ std::sqrt(double(_search_arc_num))),
+ MIN_LIST_LENGTH );
+ _minor_limit = std::max( int(MINOR_LIMIT_FACTOR * _list_length),
+ MIN_MINOR_LIMIT );
+ _curr_length = _minor_count = 0;
+ _candidates.resize(_list_length);
+ }
+
+ /// Find next entering arc
+ bool findEnteringArc() {
+ Cost min, c;
+ int e;
+ if (_curr_length > 0 && _minor_count < _minor_limit) {
+ // Minor iteration: select the best eligible arc from the
+ // current candidate list
+ ++_minor_count;
+ min = 0;
+ for (int i = 0; i < _curr_length; ++i) {
+ e = _candidates[i];
+ c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
+ if (c < min) {
+ min = c;
+ _in_arc = e;
+ }
+ else if (c >= 0) {
+ _candidates[i--] = _candidates[--_curr_length];
+ }
+ }
+ if (min < 0) return true;
+ }
+
+ // Major iteration: build a new candidate list
+ min = 0;
+ _curr_length = 0;
+ for (e = _next_arc; e != _search_arc_num; ++e) {
+ c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
+ if (c < 0) {
+ _candidates[_curr_length++] = e;
+ if (c < min) {
+ min = c;
+ _in_arc = e;
+ }
+ if (_curr_length == _list_length) goto search_end;
+ }
+ }
+ for (e = 0; e != _next_arc; ++e) {
+ c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
+ if (c < 0) {
+ _candidates[_curr_length++] = e;
+ if (c < min) {
+ min = c;
+ _in_arc = e;
+ }
+ if (_curr_length == _list_length) goto search_end;
+ }
+ }
+ if (_curr_length == 0) return false;
+
+ search_end:
+ _minor_count = 1;
+ _next_arc = e;
+ return true;
+ }
+
+ }; //class CandidateListPivotRule
+
+
+ // Implementation of the Altering Candidate List pivot rule
+ class AlteringListPivotRule
+ {
+ private:
+
+ // References to the NetworkSimplex class
+ const IntVector &_source;
+ const IntVector &_target;
+ const CostVector &_cost;
+ const CharVector &_state;
+ const CostVector &_pi;
+ int &_in_arc;
+ int _search_arc_num;
+
+ // Pivot rule data
+ int _block_size, _head_length, _curr_length;
+ int _next_arc;
+ IntVector _candidates;
+ CostVector _cand_cost;
+
+ // Functor class to compare arcs during sort of the candidate list
+ class SortFunc
+ {
+ private:
+ const CostVector &_map;
+ public:
+ SortFunc(const CostVector &map) : _map(map) {}
+ bool operator()(int left, int right) {
+ return _map[left] < _map[right];
+ }
+ };
+
+ SortFunc _sort_func;
+
+ public:
+
+ // Constructor
+ AlteringListPivotRule(NetworkSimplex &ns) :
+ _source(ns._source), _target(ns._target),
+ _cost(ns._cost), _state(ns._state), _pi(ns._pi),
+ _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
+ _next_arc(0), _cand_cost(ns._search_arc_num), _sort_func(_cand_cost)
+ {
+ // The main parameters of the pivot rule
+ const double BLOCK_SIZE_FACTOR = 1.0;
+ const int MIN_BLOCK_SIZE = 10;
+ const double HEAD_LENGTH_FACTOR = 0.01;
+ const int MIN_HEAD_LENGTH = 3;
+
+ _block_size = std::max( int(BLOCK_SIZE_FACTOR *
+ std::sqrt(double(_search_arc_num))),
+ MIN_BLOCK_SIZE );
+ _head_length = std::max( int(HEAD_LENGTH_FACTOR * _block_size),
+ MIN_HEAD_LENGTH );
+ _candidates.resize(_head_length + _block_size);
+ _curr_length = 0;
+ }
+
+ // Find next entering arc
+ bool findEnteringArc() {
+ // Check the current candidate list
+ int e;
+ Cost c;
+ for (int i = 0; i != _curr_length; ++i) {
+ e = _candidates[i];
+ c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
+ if (c < 0) {
+ _cand_cost[e] = c;
+ } else {
+ _candidates[i--] = _candidates[--_curr_length];
+ }
+ }
+
+ // Extend the list
+ int cnt = _block_size;
+ int limit = _head_length;
+
+ for (e = _next_arc; e != _search_arc_num; ++e) {
+ c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
+ if (c < 0) {
+ _cand_cost[e] = c;
+ _candidates[_curr_length++] = e;
+ }
+ if (--cnt == 0) {
+ if (_curr_length > limit) goto search_end;
+ limit = 0;
+ cnt = _block_size;
+ }
+ }
+ for (e = 0; e != _next_arc; ++e) {
+ c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
+ if (c < 0) {
+ _cand_cost[e] = c;
+ _candidates[_curr_length++] = e;
+ }
+ if (--cnt == 0) {
+ if (_curr_length > limit) goto search_end;
+ limit = 0;
+ cnt = _block_size;
+ }
+ }
+ if (_curr_length == 0) return false;
+
+ search_end:
+
+ // Perform partial sort operation on the candidate list
+ int new_length = std::min(_head_length + 1, _curr_length);
+ std::partial_sort(_candidates.begin(), _candidates.begin() + new_length,
+ _candidates.begin() + _curr_length, _sort_func);
+
+ // Select the entering arc and remove it from the list
+ _in_arc = _candidates[0];
+ _next_arc = e;
+ _candidates[0] = _candidates[new_length - 1];
+ _curr_length = new_length - 1;
+ return true;
+ }
+
+ }; //class AlteringListPivotRule
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// The constructor of the class.
+ ///
+ /// \param graph The digraph the algorithm runs on.
+ /// \param arc_mixing Indicate if the arcs will be stored in a
+ /// mixed order in the internal data structure.
+ /// In general, it leads to similar performance as using the original
+ /// arc order, but it makes the algorithm more robust and in special
+ /// cases, even significantly faster. Therefore, it is enabled by default.
+ NetworkSimplex(const GR& graph, bool arc_mixing = true) :
+ _graph(graph), _node_id(graph), _arc_id(graph),
+ _arc_mixing(arc_mixing),
+ MAX(std::numeric_limits<Value>::max()),
+ INF(std::numeric_limits<Value>::has_infinity ?
+ std::numeric_limits<Value>::infinity() : MAX)
+ {
+ // Check the number types
+ LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
+ "The flow type of NetworkSimplex must be signed");
+ LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
+ "The cost type of NetworkSimplex must be signed");
+
+ // Reset data structures
+ reset();
+ }
+
+ /// \name Parameters
+ /// The parameters of the algorithm can be specified using these
+ /// functions.
+
+ /// @{
+
+ /// \brief Set the lower bounds on the arcs.
+ ///
+ /// This function sets the lower bounds on the arcs.
+ /// If it is not used before calling \ref run(), the lower bounds
+ /// will be set to zero on all arcs.
+ ///
+ /// \param map An arc map storing the lower bounds.
+ /// Its \c Value type must be convertible to the \c Value type
+ /// of the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ template <typename LowerMap>
+ NetworkSimplex& lowerMap(const LowerMap& map) {
+ _has_lower = true;
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ _lower[_arc_id[a]] = map[a];
+ }
+ return *this;
+ }
+
+ /// \brief Set the upper bounds (capacities) on the arcs.
+ ///
+ /// This function sets the upper bounds (capacities) on the arcs.
+ /// If it is not used before calling \ref run(), the upper bounds
+ /// will be set to \ref INF on all arcs (i.e. the flow value will be
+ /// unbounded from above).
+ ///
+ /// \param map An arc map storing the upper bounds.
+ /// Its \c Value type must be convertible to the \c Value type
+ /// of the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ template<typename UpperMap>
+ NetworkSimplex& upperMap(const UpperMap& map) {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ _upper[_arc_id[a]] = map[a];
+ }
+ return *this;
+ }
+
+ /// \brief Set the costs of the arcs.
+ ///
+ /// This function sets the costs of the arcs.
+ /// If it is not used before calling \ref run(), the costs
+ /// will be set to \c 1 on all arcs.
+ ///
+ /// \param map An arc map storing the costs.
+ /// Its \c Value type must be convertible to the \c Cost type
+ /// of the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ template<typename CostMap>
+ NetworkSimplex& costMap(const CostMap& map) {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ _cost[_arc_id[a]] = map[a];
+ }
+ return *this;
+ }
+
+ /// \brief Set the supply values of the nodes.
+ ///
+ /// This function sets the supply values of the nodes.
+ /// If neither this function nor \ref stSupply() is used before
+ /// calling \ref run(), the supply of each node will be set to zero.
+ ///
+ /// \param map A node map storing the supply values.
+ /// Its \c Value type must be convertible to the \c Value type
+ /// of the algorithm.
+ ///
+ /// \return <tt>(*this)</tt>
+ ///
+ /// \sa supplyType()
+ template<typename SupplyMap>
+ NetworkSimplex& supplyMap(const SupplyMap& map) {
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ _supply[_node_id[n]] = map[n];
+ }
+ return *this;
+ }
+
+ /// \brief Set single source and target nodes and a supply value.
+ ///
+ /// This function sets a single source node and a single target node
+ /// and the required flow value.
+ /// If neither this function nor \ref supplyMap() is used before
+ /// calling \ref run(), the supply of each node will be set to zero.
+ ///
+ /// Using this function has the same effect as using \ref supplyMap()
+ /// with a map in which \c k is assigned to \c s, \c -k is
+ /// assigned to \c t and all other nodes have zero supply value.
+ ///
+ /// \param s The source node.
+ /// \param t The target node.
+ /// \param k The required amount of flow from node \c s to node \c t
+ /// (i.e. the supply of \c s and the demand of \c t).
+ ///
+ /// \return <tt>(*this)</tt>
+ NetworkSimplex& stSupply(const Node& s, const Node& t, Value k) {
+ for (int i = 0; i != _node_num; ++i) {
+ _supply[i] = 0;
+ }
+ _supply[_node_id[s]] = k;
+ _supply[_node_id[t]] = -k;
+ return *this;
+ }
+
+ /// \brief Set the type of the supply constraints.
+ ///
+ /// This function sets the type of the supply/demand constraints.
+ /// If it is not used before calling \ref run(), the \ref GEQ supply
+ /// type will be used.
+ ///
+ /// For more information, see \ref SupplyType.
+ ///
+ /// \return <tt>(*this)</tt>
+ NetworkSimplex& supplyType(SupplyType supply_type) {
+ _stype = supply_type;
+ return *this;
+ }
+
+ /// @}
+
+ /// \name Execution Control
+ /// The algorithm can be executed using \ref run().
+
+ /// @{
+
+ /// \brief Run the algorithm.
+ ///
+ /// This function runs the algorithm.
+ /// The paramters can be specified using functions \ref lowerMap(),
+ /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply(),
+ /// \ref supplyType().
+ /// For example,
+ /// \code
+ /// NetworkSimplex<ListDigraph> ns(graph);
+ /// ns.lowerMap(lower).upperMap(upper).costMap(cost)
+ /// .supplyMap(sup).run();
+ /// \endcode
+ ///
+ /// This function can be called more than once. All the given parameters
+ /// are kept for the next call, unless \ref resetParams() or \ref reset()
+ /// is used, thus only the modified parameters have to be set again.
+ /// If the underlying digraph was also modified after the construction
+ /// of the class (or the last \ref reset() call), then the \ref reset()
+ /// function must be called.
+ ///
+ /// \param pivot_rule The pivot rule that will be used during the
+ /// algorithm. For more information, see \ref PivotRule.
+ ///
+ /// \return \c INFEASIBLE if no feasible flow exists,
+ /// \n \c OPTIMAL if the problem has optimal solution
+ /// (i.e. it is feasible and bounded), and the algorithm has found
+ /// optimal flow and node potentials (primal and dual solutions),
+ /// \n \c UNBOUNDED if the objective function of the problem is
+ /// unbounded, i.e. there is a directed cycle having negative total
+ /// cost and infinite upper bound.
+ ///
+ /// \see ProblemType, PivotRule
+ /// \see resetParams(), reset()
+ ProblemType run(PivotRule pivot_rule = BLOCK_SEARCH) {
+ if (!init()) return INFEASIBLE;
+ return start(pivot_rule);
+ }
+
+ /// \brief Reset all the parameters that have been given before.
+ ///
+ /// This function resets all the paramaters that have been given
+ /// before using functions \ref lowerMap(), \ref upperMap(),
+ /// \ref costMap(), \ref supplyMap(), \ref stSupply(), \ref supplyType().
+ ///
+ /// It is useful for multiple \ref run() calls. Basically, all the given
+ /// parameters are kept for the next \ref run() call, unless
+ /// \ref resetParams() or \ref reset() is used.
+ /// If the underlying digraph was also modified after the construction
+ /// of the class or the last \ref reset() call, then the \ref reset()
+ /// function must be used, otherwise \ref resetParams() is sufficient.
+ ///
+ /// For example,
+ /// \code
+ /// NetworkSimplex<ListDigraph> ns(graph);
+ ///
+ /// // First run
+ /// ns.lowerMap(lower).upperMap(upper).costMap(cost)
+ /// .supplyMap(sup).run();
+ ///
+ /// // Run again with modified cost map (resetParams() is not called,
+ /// // so only the cost map have to be set again)
+ /// cost[e] += 100;
+ /// ns.costMap(cost).run();
+ ///
+ /// // Run again from scratch using resetParams()
+ /// // (the lower bounds will be set to zero on all arcs)
+ /// ns.resetParams();
+ /// ns.upperMap(capacity).costMap(cost)
+ /// .supplyMap(sup).run();
+ /// \endcode
+ ///
+ /// \return <tt>(*this)</tt>
+ ///
+ /// \see reset(), run()
+ NetworkSimplex& resetParams() {
+ for (int i = 0; i != _node_num; ++i) {
+ _supply[i] = 0;
+ }
+ for (int i = 0; i != _arc_num; ++i) {
+ _lower[i] = 0;
+ _upper[i] = INF;
+ _cost[i] = 1;
+ }
+ _has_lower = false;
+ _stype = GEQ;
+ return *this;
+ }
+
+ /// \brief Reset the internal data structures and all the parameters
+ /// that have been given before.
+ ///
+ /// This function resets the internal data structures and all the
+ /// paramaters that have been given before using functions \ref lowerMap(),
+ /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply(),
+ /// \ref supplyType().
+ ///
+ /// It is useful for multiple \ref run() calls. Basically, all the given
+ /// parameters are kept for the next \ref run() call, unless
+ /// \ref resetParams() or \ref reset() is used.
+ /// If the underlying digraph was also modified after the construction
+ /// of the class or the last \ref reset() call, then the \ref reset()
+ /// function must be used, otherwise \ref resetParams() is sufficient.
+ ///
+ /// See \ref resetParams() for examples.
+ ///
+ /// \return <tt>(*this)</tt>
+ ///
+ /// \see resetParams(), run()
+ NetworkSimplex& reset() {
+ // Resize vectors
+ _node_num = countNodes(_graph);
+ _arc_num = countArcs(_graph);
+ int all_node_num = _node_num + 1;
+ int max_arc_num = _arc_num + 2 * _node_num;
+
+ _source.resize(max_arc_num);
+ _target.resize(max_arc_num);
+
+ _lower.resize(_arc_num);
+ _upper.resize(_arc_num);
+ _cap.resize(max_arc_num);
+ _cost.resize(max_arc_num);
+ _supply.resize(all_node_num);
+ _flow.resize(max_arc_num);
+ _pi.resize(all_node_num);
+
+ _parent.resize(all_node_num);
+ _pred.resize(all_node_num);
+ _pred_dir.resize(all_node_num);
+ _thread.resize(all_node_num);
+ _rev_thread.resize(all_node_num);
+ _succ_num.resize(all_node_num);
+ _last_succ.resize(all_node_num);
+ _state.resize(max_arc_num);
+
+ // Copy the graph
+ int i = 0;
+ for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
+ _node_id[n] = i;
+ }
+ if (_arc_mixing && _node_num > 1) {
+ // Store the arcs in a mixed order
+ const int skip = std::max(_arc_num / _node_num, 3);
+ int i = 0, j = 0;
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ _arc_id[a] = i;
+ _source[i] = _node_id[_graph.source(a)];
+ _target[i] = _node_id[_graph.target(a)];
+ if ((i += skip) >= _arc_num) i = ++j;
+ }
+ } else {
+ // Store the arcs in the original order
+ int i = 0;
+ for (ArcIt a(_graph); a != INVALID; ++a, ++i) {
+ _arc_id[a] = i;
+ _source[i] = _node_id[_graph.source(a)];
+ _target[i] = _node_id[_graph.target(a)];
+ }
+ }
+
+ // Reset parameters
+ resetParams();
+ return *this;
+ }
+
+ /// @}
+
+ /// \name Query Functions
+ /// The results of the algorithm can be obtained using these
+ /// functions.\n
+ /// The \ref run() function must be called before using them.
+
+ /// @{
+
+ /// \brief Return the total cost of the found flow.
+ ///
+ /// This function returns the total cost of the found flow.
+ /// Its complexity is O(m).
+ ///
+ /// \note The return type of the function can be specified as a
+ /// template parameter. For example,
+ /// \code
+ /// ns.totalCost<double>();
+ /// \endcode
+ /// It is useful if the total cost cannot be stored in the \c Cost
+ /// type of the algorithm, which is the default return type of the
+ /// function.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ template <typename Number>
+ Number totalCost() const {
+ Number c = 0;
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ int i = _arc_id[a];
+ c += Number(_flow[i]) * Number(_cost[i]);
+ }
+ return c;
+ }
+
+#ifndef DOXYGEN
+ Cost totalCost() const {
+ return totalCost<Cost>();
+ }
+#endif
+
+ /// \brief Return the flow on the given arc.
+ ///
+ /// This function returns the flow on the given arc.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ Value flow(const Arc& a) const {
+ return _flow[_arc_id[a]];
+ }
+
+ /// \brief Copy the flow values (the primal solution) into the
+ /// given map.
+ ///
+ /// This function copies the flow value on each arc into the given
+ /// map. The \c Value type of the algorithm must be convertible to
+ /// the \c Value type of the map.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ template <typename FlowMap>
+ void flowMap(FlowMap &map) const {
+ for (ArcIt a(_graph); a != INVALID; ++a) {
+ map.set(a, _flow[_arc_id[a]]);
+ }
+ }
+
+ /// \brief Return the potential (dual value) of the given node.
+ ///
+ /// This function returns the potential (dual value) of the
+ /// given node.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ Cost potential(const Node& n) const {
+ return _pi[_node_id[n]];
+ }
+
+ /// \brief Copy the potential values (the dual solution) into the
+ /// given map.
+ ///
+ /// This function copies the potential (dual value) of each node
+ /// into the given map.
+ /// The \c Cost type of the algorithm must be convertible to the
+ /// \c Value type of the map.
+ ///
+ /// \pre \ref run() must be called before using this function.
+ template <typename PotentialMap>
+ void potentialMap(PotentialMap &map) const {
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ map.set(n, _pi[_node_id[n]]);
+ }
+ }
+
+ /// @}
+
+ private:
+
+ // Initialize internal data structures
+ bool init() {
+ if (_node_num == 0) return false;
+
+ // Check the sum of supply values
+ _sum_supply = 0;
+ for (int i = 0; i != _node_num; ++i) {
+ _sum_supply += _supply[i];
+ }
+ if ( !((_stype == GEQ && _sum_supply <= 0) ||
+ (_stype == LEQ && _sum_supply >= 0)) ) return false;
+
+ // Check lower and upper bounds
+ LEMON_DEBUG(checkBoundMaps(),
+ "Upper bounds must be greater or equal to the lower bounds");
+
+ // Remove non-zero lower bounds
+ if (_has_lower) {
+ for (int i = 0; i != _arc_num; ++i) {
+ Value c = _lower[i];
+ if (c >= 0) {
+ _cap[i] = _upper[i] < MAX ? _upper[i] - c : INF;
+ } else {
+ _cap[i] = _upper[i] < MAX + c ? _upper[i] - c : INF;
+ }
+ _supply[_source[i]] -= c;
+ _supply[_target[i]] += c;
+ }
+ } else {
+ for (int i = 0; i != _arc_num; ++i) {
+ _cap[i] = _upper[i];
+ }
+ }
+
+ // Initialize artifical cost
+ Cost ART_COST;
+ if (std::numeric_limits<Cost>::is_exact) {
+ ART_COST = std::numeric_limits<Cost>::max() / 2 + 1;
+ } else {
+ ART_COST = 0;
+ for (int i = 0; i != _arc_num; ++i) {
+ if (_cost[i] > ART_COST) ART_COST = _cost[i];
+ }
+ ART_COST = (ART_COST + 1) * _node_num;
+ }
+
+ // Initialize arc maps
+ for (int i = 0; i != _arc_num; ++i) {
+ _flow[i] = 0;
+ _state[i] = STATE_LOWER;
+ }
+
+ // Set data for the artificial root node
+ _root = _node_num;
+ _parent[_root] = -1;
+ _pred[_root] = -1;
+ _thread[_root] = 0;
+ _rev_thread[0] = _root;
+ _succ_num[_root] = _node_num + 1;
+ _last_succ[_root] = _root - 1;
+ _supply[_root] = -_sum_supply;
+ _pi[_root] = 0;
+
+ // Add artificial arcs and initialize the spanning tree data structure
+ if (_sum_supply == 0) {
+ // EQ supply constraints
+ _search_arc_num = _arc_num;
+ _all_arc_num = _arc_num + _node_num;
+ for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) {
+ _parent[u] = _root;
+ _pred[u] = e;
+ _thread[u] = u + 1;
+ _rev_thread[u + 1] = u;
+ _succ_num[u] = 1;
+ _last_succ[u] = u;
+ _cap[e] = INF;
+ _state[e] = STATE_TREE;
+ if (_supply[u] >= 0) {
+ _pred_dir[u] = DIR_UP;
+ _pi[u] = 0;
+ _source[e] = u;
+ _target[e] = _root;
+ _flow[e] = _supply[u];
+ _cost[e] = 0;
+ } else {
+ _pred_dir[u] = DIR_DOWN;
+ _pi[u] = ART_COST;
+ _source[e] = _root;
+ _target[e] = u;
+ _flow[e] = -_supply[u];
+ _cost[e] = ART_COST;
+ }
+ }
+ }
+ else if (_sum_supply > 0) {
+ // LEQ supply constraints
+ _search_arc_num = _arc_num + _node_num;
+ int f = _arc_num + _node_num;
+ for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) {
+ _parent[u] = _root;
+ _thread[u] = u + 1;
+ _rev_thread[u + 1] = u;
+ _succ_num[u] = 1;
+ _last_succ[u] = u;
+ if (_supply[u] >= 0) {
+ _pred_dir[u] = DIR_UP;
+ _pi[u] = 0;
+ _pred[u] = e;
+ _source[e] = u;
+ _target[e] = _root;
+ _cap[e] = INF;
+ _flow[e] = _supply[u];
+ _cost[e] = 0;
+ _state[e] = STATE_TREE;
+ } else {
+ _pred_dir[u] = DIR_DOWN;
+ _pi[u] = ART_COST;
+ _pred[u] = f;
+ _source[f] = _root;
+ _target[f] = u;
+ _cap[f] = INF;
+ _flow[f] = -_supply[u];
+ _cost[f] = ART_COST;
+ _state[f] = STATE_TREE;
+ _source[e] = u;
+ _target[e] = _root;
+ _cap[e] = INF;
+ _flow[e] = 0;
+ _cost[e] = 0;
+ _state[e] = STATE_LOWER;
+ ++f;
+ }
+ }
+ _all_arc_num = f;
+ }
+ else {
+ // GEQ supply constraints
+ _search_arc_num = _arc_num + _node_num;
+ int f = _arc_num + _node_num;
+ for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) {
+ _parent[u] = _root;
+ _thread[u] = u + 1;
+ _rev_thread[u + 1] = u;
+ _succ_num[u] = 1;
+ _last_succ[u] = u;
+ if (_supply[u] <= 0) {
+ _pred_dir[u] = DIR_DOWN;
+ _pi[u] = 0;
+ _pred[u] = e;
+ _source[e] = _root;
+ _target[e] = u;
+ _cap[e] = INF;
+ _flow[e] = -_supply[u];
+ _cost[e] = 0;
+ _state[e] = STATE_TREE;
+ } else {
+ _pred_dir[u] = DIR_UP;
+ _pi[u] = -ART_COST;
+ _pred[u] = f;
+ _source[f] = u;
+ _target[f] = _root;
+ _cap[f] = INF;
+ _flow[f] = _supply[u];
+ _state[f] = STATE_TREE;
+ _cost[f] = ART_COST;
+ _source[e] = _root;
+ _target[e] = u;
+ _cap[e] = INF;
+ _flow[e] = 0;
+ _cost[e] = 0;
+ _state[e] = STATE_LOWER;
+ ++f;
+ }
+ }
+ _all_arc_num = f;
+ }
+
+ return true;
+ }
+
+ // Check if the upper bound is greater than or equal to the lower bound
+ // on each arc.
+ bool checkBoundMaps() {
+ for (int j = 0; j != _arc_num; ++j) {
+ if (_upper[j] < _lower[j]) return false;
+ }
+ return true;
+ }
+
+ // Find the join node
+ void findJoinNode() {
+ int u = _source[in_arc];
+ int v = _target[in_arc];
+ while (u != v) {
+ if (_succ_num[u] < _succ_num[v]) {
+ u = _parent[u];
+ } else {
+ v = _parent[v];
+ }
+ }
+ join = u;
+ }
+
+ // Find the leaving arc of the cycle and returns true if the
+ // leaving arc is not the same as the entering arc
+ bool findLeavingArc() {
+ // Initialize first and second nodes according to the direction
+ // of the cycle
+ int first, second;
+ if (_state[in_arc] == STATE_LOWER) {
+ first = _source[in_arc];
+ second = _target[in_arc];
+ } else {
+ first = _target[in_arc];
+ second = _source[in_arc];
+ }
+ delta = _cap[in_arc];
+ int result = 0;
+ Value c, d;
+ int e;
+
+ // Search the cycle form the first node to the join node
+ for (int u = first; u != join; u = _parent[u]) {
+ e = _pred[u];
+ d = _flow[e];
+ if (_pred_dir[u] == DIR_DOWN) {
+ c = _cap[e];
+ d = c >= MAX ? INF : c - d;
+ }
+ if (d < delta) {
+ delta = d;
+ u_out = u;
+ result = 1;
+ }
+ }
+
+ // Search the cycle form the second node to the join node
+ for (int u = second; u != join; u = _parent[u]) {
+ e = _pred[u];
+ d = _flow[e];
+ if (_pred_dir[u] == DIR_UP) {
+ c = _cap[e];
+ d = c >= MAX ? INF : c - d;
+ }
+ if (d <= delta) {
+ delta = d;
+ u_out = u;
+ result = 2;
+ }
+ }
+
+ if (result == 1) {
+ u_in = first;
+ v_in = second;
+ } else {
+ u_in = second;
+ v_in = first;
+ }
+ return result != 0;
+ }
+
+ // Change _flow and _state vectors
+ void changeFlow(bool change) {
+ // Augment along the cycle
+ if (delta > 0) {
+ Value val = _state[in_arc] * delta;
+ _flow[in_arc] += val;
+ for (int u = _source[in_arc]; u != join; u = _parent[u]) {
+ _flow[_pred[u]] -= _pred_dir[u] * val;
+ }
+ for (int u = _target[in_arc]; u != join; u = _parent[u]) {
+ _flow[_pred[u]] += _pred_dir[u] * val;
+ }
+ }
+ // Update the state of the entering and leaving arcs
+ if (change) {
+ _state[in_arc] = STATE_TREE;
+ _state[_pred[u_out]] =
+ (_flow[_pred[u_out]] == 0) ? STATE_LOWER : STATE_UPPER;
+ } else {
+ _state[in_arc] = -_state[in_arc];
+ }
+ }
+
+ // Update the tree structure
+ void updateTreeStructure() {
+ int old_rev_thread = _rev_thread[u_out];
+ int old_succ_num = _succ_num[u_out];
+ int old_last_succ = _last_succ[u_out];
+ v_out = _parent[u_out];
+
+ // Check if u_in and u_out coincide
+ if (u_in == u_out) {
+ // Update _parent, _pred, _pred_dir
+ _parent[u_in] = v_in;
+ _pred[u_in] = in_arc;
+ _pred_dir[u_in] = u_in == _source[in_arc] ? DIR_UP : DIR_DOWN;
+
+ // Update _thread and _rev_thread
+ if (_thread[v_in] != u_out) {
+ int after = _thread[old_last_succ];
+ _thread[old_rev_thread] = after;
+ _rev_thread[after] = old_rev_thread;
+ after = _thread[v_in];
+ _thread[v_in] = u_out;
+ _rev_thread[u_out] = v_in;
+ _thread[old_last_succ] = after;
+ _rev_thread[after] = old_last_succ;
+ }
+ } else {
+ // Handle the case when old_rev_thread equals to v_in
+ // (it also means that join and v_out coincide)
+ int thread_continue = old_rev_thread == v_in ?
+ _thread[old_last_succ] : _thread[v_in];
+
+ // Update _thread and _parent along the stem nodes (i.e. the nodes
+ // between u_in and u_out, whose parent have to be changed)
+ int stem = u_in; // the current stem node
+ int par_stem = v_in; // the new parent of stem
+ int next_stem; // the next stem node
+ int last = _last_succ[u_in]; // the last successor of stem
+ int before, after = _thread[last];
+ _thread[v_in] = u_in;
+ _dirty_revs.clear();
+ _dirty_revs.push_back(v_in);
+ while (stem != u_out) {
+ // Insert the next stem node into the thread list
+ next_stem = _parent[stem];
+ _thread[last] = next_stem;
+ _dirty_revs.push_back(last);
+
+ // Remove the subtree of stem from the thread list
+ before = _rev_thread[stem];
+ _thread[before] = after;
+ _rev_thread[after] = before;
+
+ // Change the parent node and shift stem nodes
+ _parent[stem] = par_stem;
+ par_stem = stem;
+ stem = next_stem;
+
+ // Update last and after
+ last = _last_succ[stem] == _last_succ[par_stem] ?
+ _rev_thread[par_stem] : _last_succ[stem];
+ after = _thread[last];
+ }
+ _parent[u_out] = par_stem;
+ _thread[last] = thread_continue;
+ _rev_thread[thread_continue] = last;
+ _last_succ[u_out] = last;
+
+ // Remove the subtree of u_out from the thread list except for
+ // the case when old_rev_thread equals to v_in
+ if (old_rev_thread != v_in) {
+ _thread[old_rev_thread] = after;
+ _rev_thread[after] = old_rev_thread;
+ }
+
+ // Update _rev_thread using the new _thread values
+ for (int i = 0; i != int(_dirty_revs.size()); ++i) {
+ int u = _dirty_revs[i];
+ _rev_thread[_thread[u]] = u;
+ }
+
+ // Update _pred, _pred_dir, _last_succ and _succ_num for the
+ // stem nodes from u_out to u_in
+ int tmp_sc = 0, tmp_ls = _last_succ[u_out];
+ for (int u = u_out, p = _parent[u]; u != u_in; u = p, p = _parent[u]) {
+ _pred[u] = _pred[p];
+ _pred_dir[u] = -_pred_dir[p];
+ tmp_sc += _succ_num[u] - _succ_num[p];
+ _succ_num[u] = tmp_sc;
+ _last_succ[p] = tmp_ls;
+ }
+ _pred[u_in] = in_arc;
+ _pred_dir[u_in] = u_in == _source[in_arc] ? DIR_UP : DIR_DOWN;
+ _succ_num[u_in] = old_succ_num;
+ }
+
+ // Update _last_succ from v_in towards the root
+ int up_limit_out = _last_succ[join] == v_in ? join : -1;
+ int last_succ_out = _last_succ[u_out];
+ for (int u = v_in; u != -1 && _last_succ[u] == v_in; u = _parent[u]) {
+ _last_succ[u] = last_succ_out;
+ }
+
+ // Update _last_succ from v_out towards the root
+ if (join != old_rev_thread && v_in != old_rev_thread) {
+ for (int u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
+ u = _parent[u]) {
+ _last_succ[u] = old_rev_thread;
+ }
+ }
+ else if (last_succ_out != old_last_succ) {
+ for (int u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
+ u = _parent[u]) {
+ _last_succ[u] = last_succ_out;
+ }
+ }
+
+ // Update _succ_num from v_in to join
+ for (int u = v_in; u != join; u = _parent[u]) {
+ _succ_num[u] += old_succ_num;
+ }
+ // Update _succ_num from v_out to join
+ for (int u = v_out; u != join; u = _parent[u]) {
+ _succ_num[u] -= old_succ_num;
+ }
+ }
+
+ // Update potentials in the subtree that has been moved
+ void updatePotential() {
+ Cost sigma = _pi[v_in] - _pi[u_in] -
+ _pred_dir[u_in] * _cost[in_arc];
+ int end = _thread[_last_succ[u_in]];
+ for (int u = u_in; u != end; u = _thread[u]) {
+ _pi[u] += sigma;
+ }
+ }
+
+ // Heuristic initial pivots
+ bool initialPivots() {
+ Value curr, total = 0;
+ std::vector<Node> supply_nodes, demand_nodes;
+ for (NodeIt u(_graph); u != INVALID; ++u) {
+ curr = _supply[_node_id[u]];
+ if (curr > 0) {
+ total += curr;
+ supply_nodes.push_back(u);
+ }
+ else if (curr < 0) {
+ demand_nodes.push_back(u);
+ }
+ }
+ if (_sum_supply > 0) total -= _sum_supply;
+ if (total <= 0) return true;
+
+ IntVector arc_vector;
+ if (_sum_supply >= 0) {
+ if (supply_nodes.size() == 1 && demand_nodes.size() == 1) {
+ // Perform a reverse graph search from the sink to the source
+ typename GR::template NodeMap<bool> reached(_graph, false);
+ Node s = supply_nodes[0], t = demand_nodes[0];
+ std::vector<Node> stack;
+ reached[t] = true;
+ stack.push_back(t);
+ while (!stack.empty()) {
+ Node u, v = stack.back();
+ stack.pop_back();
+ if (v == s) break;
+ for (InArcIt a(_graph, v); a != INVALID; ++a) {
+ if (reached[u = _graph.source(a)]) continue;
+ int j = _arc_id[a];
+ if (_cap[j] >= total) {
+ arc_vector.push_back(j);
+ reached[u] = true;
+ stack.push_back(u);
+ }
+ }
+ }
+ } else {
+ // Find the min. cost incoming arc for each demand node
+ for (int i = 0; i != int(demand_nodes.size()); ++i) {
+ Node v = demand_nodes[i];
+ Cost c, min_cost = std::numeric_limits<Cost>::max();
+ Arc min_arc = INVALID;
+ for (InArcIt a(_graph, v); a != INVALID; ++a) {
+ c = _cost[_arc_id[a]];
+ if (c < min_cost) {
+ min_cost = c;
+ min_arc = a;
+ }
+ }
+ if (min_arc != INVALID) {
+ arc_vector.push_back(_arc_id[min_arc]);
+ }
+ }
+ }
+ } else {
+ // Find the min. cost outgoing arc for each supply node
+ for (int i = 0; i != int(supply_nodes.size()); ++i) {
+ Node u = supply_nodes[i];
+ Cost c, min_cost = std::numeric_limits<Cost>::max();
+ Arc min_arc = INVALID;
+ for (OutArcIt a(_graph, u); a != INVALID; ++a) {
+ c = _cost[_arc_id[a]];
+ if (c < min_cost) {
+ min_cost = c;
+ min_arc = a;
+ }
+ }
+ if (min_arc != INVALID) {
+ arc_vector.push_back(_arc_id[min_arc]);
+ }
+ }
+ }
+
+ // Perform heuristic initial pivots
+ for (int i = 0; i != int(arc_vector.size()); ++i) {
+ in_arc = arc_vector[i];
+ if (_state[in_arc] * (_cost[in_arc] + _pi[_source[in_arc]] -
+ _pi[_target[in_arc]]) >= 0) continue;
+ findJoinNode();
+ bool change = findLeavingArc();
+ if (delta >= MAX) return false;
+ changeFlow(change);
+ if (change) {
+ updateTreeStructure();
+ updatePotential();
+ }
+ }
+ return true;
+ }
+
+ // Execute the algorithm
+ ProblemType start(PivotRule pivot_rule) {
+ // Select the pivot rule implementation
+ switch (pivot_rule) {
+ case FIRST_ELIGIBLE:
+ return start<FirstEligiblePivotRule>();
+ case BEST_ELIGIBLE:
+ return start<BestEligiblePivotRule>();
+ case BLOCK_SEARCH:
+ return start<BlockSearchPivotRule>();
+ case CANDIDATE_LIST:
+ return start<CandidateListPivotRule>();
+ case ALTERING_LIST:
+ return start<AlteringListPivotRule>();
+ }
+ return INFEASIBLE; // avoid warning
+ }
+
+ template <typename PivotRuleImpl>
+ ProblemType start() {
+ PivotRuleImpl pivot(*this);
+
+ // Perform heuristic initial pivots
+ if (!initialPivots()) return UNBOUNDED;
+
+ // Execute the Network Simplex algorithm
+ while (pivot.findEnteringArc()) {
+ findJoinNode();
+ bool change = findLeavingArc();
+ if (delta >= MAX) return UNBOUNDED;
+ changeFlow(change);
+ if (change) {
+ updateTreeStructure();
+ updatePotential();
+ }
+ }
+
+ // Check feasibility
+ for (int e = _search_arc_num; e != _all_arc_num; ++e) {
+ if (_flow[e] != 0) return INFEASIBLE;
+ }
+
+ // Transform the solution and the supply map to the original form
+ if (_has_lower) {
+ for (int i = 0; i != _arc_num; ++i) {
+ Value c = _lower[i];
+ if (c != 0) {
+ _flow[i] += c;
+ _supply[_source[i]] += c;
+ _supply[_target[i]] -= c;
+ }
+ }
+ }
+
+ // Shift potentials to meet the requirements of the GEQ/LEQ type
+ // optimality conditions
+ if (_sum_supply == 0) {
+ if (_stype == GEQ) {
+ Cost max_pot = -std::numeric_limits<Cost>::max();
+ for (int i = 0; i != _node_num; ++i) {
+ if (_pi[i] > max_pot) max_pot = _pi[i];
+ }
+ if (max_pot > 0) {
+ for (int i = 0; i != _node_num; ++i)
+ _pi[i] -= max_pot;
+ }
+ } else {
+ Cost min_pot = std::numeric_limits<Cost>::max();
+ for (int i = 0; i != _node_num; ++i) {
+ if (_pi[i] < min_pot) min_pot = _pi[i];
+ }
+ if (min_pot < 0) {
+ for (int i = 0; i != _node_num; ++i)
+ _pi[i] -= min_pot;
+ }
+ }
+ }
+
+ return OPTIMAL;
+ }
+
+ }; //class NetworkSimplex
+
+ ///@}
+
+} //namespace lemon
+
+#endif //LEMON_NETWORK_SIMPLEX_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/opt2_tsp.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/opt2_tsp.h
new file mode 100644
index 00000000000..686cc9cb89d
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/opt2_tsp.h
@@ -0,0 +1,367 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_OPT2_TSP_H
+#define LEMON_OPT2_TSP_H
+
+/// \ingroup tsp
+/// \file
+/// \brief 2-opt algorithm for symmetric TSP.
+
+#include <vector>
+#include <lemon/full_graph.h>
+
+namespace lemon {
+
+ /// \ingroup tsp
+ ///
+ /// \brief 2-opt algorithm for symmetric TSP.
+ ///
+ /// Opt2Tsp implements the 2-opt heuristic for solving
+ /// symmetric \ref tsp "TSP".
+ ///
+ /// This algorithm starts with an initial tour and iteratively improves it.
+ /// At each step, it removes two edges and the reconnects the created two
+ /// paths in the other way if the resulting tour is shorter.
+ /// The algorithm finishes when no such 2-opt move can be applied, and so
+ /// the tour is 2-optimal.
+ ///
+ /// If no starting tour is given to the \ref run() function, then the
+ /// algorithm uses the node sequence determined by the node IDs.
+ /// Oherwise, it starts with the given tour.
+ ///
+ /// This is a rather slow but effective method.
+ /// Its typical usage is the improvement of the result of a fast tour
+ /// construction heuristic (e.g. the InsertionTsp algorithm).
+ ///
+ /// \tparam CM Type of the cost map.
+ template <typename CM>
+ class Opt2Tsp
+ {
+ public:
+
+ /// Type of the cost map
+ typedef CM CostMap;
+ /// Type of the edge costs
+ typedef typename CM::Value Cost;
+
+ private:
+
+ GRAPH_TYPEDEFS(FullGraph);
+
+ const FullGraph &_gr;
+ const CostMap &_cost;
+ Cost _sum;
+ std::vector<int> _plist;
+ std::vector<Node> _path;
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ /// \param gr The \ref FullGraph "full graph" the algorithm runs on.
+ /// \param cost The cost map.
+ Opt2Tsp(const FullGraph &gr, const CostMap &cost)
+ : _gr(gr), _cost(cost) {}
+
+ /// \name Execution Control
+ /// @{
+
+ /// \brief Runs the algorithm from scratch.
+ ///
+ /// This function runs the algorithm starting from the tour that is
+ /// determined by the node ID sequence.
+ ///
+ /// \return The total cost of the found tour.
+ Cost run() {
+ _path.clear();
+
+ if (_gr.nodeNum() == 0) return _sum = 0;
+ else if (_gr.nodeNum() == 1) {
+ _path.push_back(_gr(0));
+ return _sum = 0;
+ }
+ else if (_gr.nodeNum() == 2) {
+ _path.push_back(_gr(0));
+ _path.push_back(_gr(1));
+ return _sum = 2 * _cost[_gr.edge(_gr(0), _gr(1))];
+ }
+
+ _plist.resize(2*_gr.nodeNum());
+ for (int i = 1; i < _gr.nodeNum()-1; ++i) {
+ _plist[2*i] = i-1;
+ _plist[2*i+1] = i+1;
+ }
+ _plist[0] = _gr.nodeNum()-1;
+ _plist[1] = 1;
+ _plist[2*_gr.nodeNum()-2] = _gr.nodeNum()-2;
+ _plist[2*_gr.nodeNum()-1] = 0;
+
+ return start();
+ }
+
+ /// \brief Runs the algorithm starting from the given tour.
+ ///
+ /// This function runs the algorithm starting from the given tour.
+ ///
+ /// \param tour The tour as a path structure. It must be a
+ /// \ref checkPath() "valid path" containing excactly n arcs.
+ ///
+ /// \return The total cost of the found tour.
+ template <typename Path>
+ Cost run(const Path& tour) {
+ _path.clear();
+
+ if (_gr.nodeNum() == 0) return _sum = 0;
+ else if (_gr.nodeNum() == 1) {
+ _path.push_back(_gr(0));
+ return _sum = 0;
+ }
+ else if (_gr.nodeNum() == 2) {
+ _path.push_back(_gr(0));
+ _path.push_back(_gr(1));
+ return _sum = 2 * _cost[_gr.edge(_gr(0), _gr(1))];
+ }
+
+ _plist.resize(2*_gr.nodeNum());
+ typename Path::ArcIt it(tour);
+ int first = _gr.id(_gr.source(it)),
+ prev = first,
+ curr = _gr.id(_gr.target(it)),
+ next = -1;
+ _plist[2*first+1] = curr;
+ for (++it; it != INVALID; ++it) {
+ next = _gr.id(_gr.target(it));
+ _plist[2*curr] = prev;
+ _plist[2*curr+1] = next;
+ prev = curr;
+ curr = next;
+ }
+ _plist[2*first] = prev;
+
+ return start();
+ }
+
+ /// \brief Runs the algorithm starting from the given tour.
+ ///
+ /// This function runs the algorithm starting from the given tour
+ /// (node sequence).
+ ///
+ /// \param tour A vector that stores all <tt>Node</tt>s of the graph
+ /// in the desired order.
+ ///
+ /// \return The total cost of the found tour.
+ Cost run(const std::vector<Node>& tour) {
+ _path.clear();
+
+ if (_gr.nodeNum() == 0) return _sum = 0;
+ else if (_gr.nodeNum() == 1) {
+ _path.push_back(_gr(0));
+ return _sum = 0;
+ }
+ else if (_gr.nodeNum() == 2) {
+ _path.push_back(_gr(0));
+ _path.push_back(_gr(1));
+ return _sum = 2 * _cost[_gr.edge(_gr(0), _gr(1))];
+ }
+
+ _plist.resize(2*_gr.nodeNum());
+ typename std::vector<Node>::const_iterator it = tour.begin();
+ int first = _gr.id(*it),
+ prev = first,
+ curr = _gr.id(*(++it)),
+ next = -1;
+ _plist[2*first+1] = curr;
+ for (++it; it != tour.end(); ++it) {
+ next = _gr.id(*it);
+ _plist[2*curr] = prev;
+ _plist[2*curr+1] = next;
+ prev = curr;
+ curr = next;
+ }
+ _plist[2*first] = curr;
+ _plist[2*curr] = prev;
+ _plist[2*curr+1] = first;
+
+ return start();
+ }
+
+ /// @}
+
+ /// \name Query Functions
+ /// @{
+
+ /// \brief The total cost of the found tour.
+ ///
+ /// This function returns the total cost of the found tour.
+ ///
+ /// \pre run() must be called before using this function.
+ Cost tourCost() const {
+ return _sum;
+ }
+
+ /// \brief Returns a const reference to the node sequence of the
+ /// found tour.
+ ///
+ /// This function returns a const reference to a vector
+ /// that stores the node sequence of the found tour.
+ ///
+ /// \pre run() must be called before using this function.
+ const std::vector<Node>& tourNodes() const {
+ return _path;
+ }
+
+ /// \brief Gives back the node sequence of the found tour.
+ ///
+ /// This function copies the node sequence of the found tour into
+ /// an STL container through the given output iterator. The
+ /// <tt>value_type</tt> of the container must be <tt>FullGraph::Node</tt>.
+ /// For example,
+ /// \code
+ /// std::vector<FullGraph::Node> nodes(countNodes(graph));
+ /// tsp.tourNodes(nodes.begin());
+ /// \endcode
+ /// or
+ /// \code
+ /// std::list<FullGraph::Node> nodes;
+ /// tsp.tourNodes(std::back_inserter(nodes));
+ /// \endcode
+ ///
+ /// \pre run() must be called before using this function.
+ template <typename Iterator>
+ void tourNodes(Iterator out) const {
+ std::copy(_path.begin(), _path.end(), out);
+ }
+
+ /// \brief Gives back the found tour as a path.
+ ///
+ /// This function copies the found tour as a list of arcs/edges into
+ /// the given \ref lemon::concepts::Path "path structure".
+ ///
+ /// \pre run() must be called before using this function.
+ template <typename Path>
+ void tour(Path &path) const {
+ path.clear();
+ for (int i = 0; i < int(_path.size()) - 1; ++i) {
+ path.addBack(_gr.arc(_path[i], _path[i+1]));
+ }
+ if (int(_path.size()) >= 2) {
+ path.addBack(_gr.arc(_path.back(), _path.front()));
+ }
+ }
+
+ /// @}
+
+ private:
+
+ // Iterator class for the linked list storage of the tour
+ class PathListIt {
+ public:
+ PathListIt(const std::vector<int> &pl, int i=0)
+ : plist(&pl), act(i), last(pl[2*act]) {}
+ PathListIt(const std::vector<int> &pl, int i, int l)
+ : plist(&pl), act(i), last(l) {}
+
+ int nextIndex() const {
+ return (*plist)[2*act] == last ? 2*act+1 : 2*act;
+ }
+
+ int prevIndex() const {
+ return (*plist)[2*act] == last ? 2*act : 2*act+1;
+ }
+
+ int next() const {
+ int x = (*plist)[2*act];
+ return x == last ? (*plist)[2*act+1] : x;
+ }
+
+ int prev() const {
+ return last;
+ }
+
+ PathListIt& operator++() {
+ int tmp = act;
+ act = next();
+ last = tmp;
+ return *this;
+ }
+
+ operator int() const {
+ return act;
+ }
+
+ private:
+ const std::vector<int> *plist;
+ int act;
+ int last;
+ };
+
+ // Checks and applies 2-opt move (if it improves the tour)
+ bool checkOpt2(const PathListIt& i, const PathListIt& j) {
+ Node u = _gr.nodeFromId(i),
+ un = _gr.nodeFromId(i.next()),
+ v = _gr.nodeFromId(j),
+ vn = _gr.nodeFromId(j.next());
+
+ if (_cost[_gr.edge(u, un)] + _cost[_gr.edge(v, vn)] >
+ _cost[_gr.edge(u, v)] + _cost[_gr.edge(un, vn)])
+ {
+ _plist[PathListIt(_plist, i.next(), i).prevIndex()] = j.next();
+ _plist[PathListIt(_plist, j.next(), j).prevIndex()] = i.next();
+
+ _plist[i.nextIndex()] = j;
+ _plist[j.nextIndex()] = i;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ // Executes the algorithm from the initial tour
+ Cost start() {
+
+ restart_search:
+ for (PathListIt i(_plist); true; ++i) {
+ PathListIt j = i;
+ if (++j == 0 || ++j == 0) break;
+ for (; j != 0 && j != i.prev(); ++j) {
+ if (checkOpt2(i, j))
+ goto restart_search;
+ }
+ }
+
+ PathListIt i(_plist);
+ _path.push_back(_gr.nodeFromId(i));
+ for (++i; i != 0; ++i)
+ _path.push_back(_gr.nodeFromId(i));
+
+ _sum = _cost[_gr.edge(_path.back(), _path.front())];
+ for (int i = 0; i < int(_path.size())-1; ++i) {
+ _sum += _cost[_gr.edge(_path[i], _path[i+1])];
+ }
+
+ return _sum;
+ }
+
+ };
+
+}; // namespace lemon
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/pairing_heap.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/pairing_heap.h
new file mode 100644
index 00000000000..da6ebcb1552
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/pairing_heap.h
@@ -0,0 +1,474 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_PAIRING_HEAP_H
+#define LEMON_PAIRING_HEAP_H
+
+///\file
+///\ingroup heaps
+///\brief Pairing heap implementation.
+
+#include <vector>
+#include <utility>
+#include <functional>
+#include <lemon/math.h>
+
+namespace lemon {
+
+ /// \ingroup heaps
+ ///
+ ///\brief Pairing Heap.
+ ///
+ /// This class implements the \e pairing \e heap data structure.
+ /// It fully conforms to the \ref concepts::Heap "heap concept".
+ ///
+ /// The methods \ref increase() and \ref erase() are not efficient
+ /// in a pairing heap. In case of many calls of these operations,
+ /// it is better to use other heap structure, e.g. \ref BinHeap
+ /// "binary heap".
+ ///
+ /// \tparam PR Type of the priorities of the items.
+ /// \tparam IM A read-writable item map with \c int values, used
+ /// internally to handle the cross references.
+ /// \tparam CMP A functor class for comparing the priorities.
+ /// The default is \c std::less<PR>.
+#ifdef DOXYGEN
+ template <typename PR, typename IM, typename CMP>
+#else
+ template <typename PR, typename IM, typename CMP = std::less<PR> >
+#endif
+ class PairingHeap {
+ public:
+ /// Type of the item-int map.
+ typedef IM ItemIntMap;
+ /// Type of the priorities.
+ typedef PR Prio;
+ /// Type of the items stored in the heap.
+ typedef typename ItemIntMap::Key Item;
+ /// Functor type for comparing the priorities.
+ typedef CMP Compare;
+
+ /// \brief Type to represent the states of the items.
+ ///
+ /// Each item has a state associated to it. It can be "in heap",
+ /// "pre-heap" or "post-heap". The latter two are indifferent from the
+ /// heap's point of view, but may be useful to the user.
+ ///
+ /// The item-int map must be initialized in such way that it assigns
+ /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
+ enum State {
+ IN_HEAP = 0, ///< = 0.
+ PRE_HEAP = -1, ///< = -1.
+ POST_HEAP = -2 ///< = -2.
+ };
+
+ private:
+ class store;
+
+ std::vector<store> _data;
+ int _min;
+ ItemIntMap &_iim;
+ Compare _comp;
+ int _num_items;
+
+ public:
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// \param map A map that assigns \c int values to the items.
+ /// It is used internally to handle the cross references.
+ /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
+ explicit PairingHeap(ItemIntMap &map)
+ : _min(0), _iim(map), _num_items(0) {}
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// \param map A map that assigns \c int values to the items.
+ /// It is used internally to handle the cross references.
+ /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
+ /// \param comp The function object used for comparing the priorities.
+ PairingHeap(ItemIntMap &map, const Compare &comp)
+ : _min(0), _iim(map), _comp(comp), _num_items(0) {}
+
+ /// \brief The number of items stored in the heap.
+ ///
+ /// This function returns the number of items stored in the heap.
+ int size() const { return _num_items; }
+
+ /// \brief Check if the heap is empty.
+ ///
+ /// This function returns \c true if the heap is empty.
+ bool empty() const { return _num_items==0; }
+
+ /// \brief Make the heap empty.
+ ///
+ /// This functon makes the heap empty.
+ /// It does not change the cross reference map. If you want to reuse
+ /// a heap that is not surely empty, you should first clear it and
+ /// then you should set the cross reference map to \c PRE_HEAP
+ /// for each item.
+ void clear() {
+ _data.clear();
+ _min = 0;
+ _num_items = 0;
+ }
+
+ /// \brief Set the priority of an item or insert it, if it is
+ /// not stored in the heap.
+ ///
+ /// This method sets the priority of the given item if it is
+ /// already stored in the heap. Otherwise it inserts the given
+ /// item into the heap with the given priority.
+ /// \param item The item.
+ /// \param value The priority.
+ void set (const Item& item, const Prio& value) {
+ int i=_iim[item];
+ if ( i>=0 && _data[i].in ) {
+ if ( _comp(value, _data[i].prio) ) decrease(item, value);
+ if ( _comp(_data[i].prio, value) ) increase(item, value);
+ } else push(item, value);
+ }
+
+ /// \brief Insert an item into the heap with the given priority.
+ ///
+ /// This function inserts the given item into the heap with the
+ /// given priority.
+ /// \param item The item to insert.
+ /// \param value The priority of the item.
+ /// \pre \e item must not be stored in the heap.
+ void push (const Item& item, const Prio& value) {
+ int i=_iim[item];
+ if( i<0 ) {
+ int s=_data.size();
+ _iim.set(item, s);
+ store st;
+ st.name=item;
+ _data.push_back(st);
+ i=s;
+ } else {
+ _data[i].parent=_data[i].child=-1;
+ _data[i].left_child=false;
+ _data[i].degree=0;
+ _data[i].in=true;
+ }
+
+ _data[i].prio=value;
+
+ if ( _num_items!=0 ) {
+ if ( _comp( value, _data[_min].prio) ) {
+ fuse(i,_min);
+ _min=i;
+ }
+ else fuse(_min,i);
+ }
+ else _min=i;
+
+ ++_num_items;
+ }
+
+ /// \brief Return the item having minimum priority.
+ ///
+ /// This function returns the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ Item top() const { return _data[_min].name; }
+
+ /// \brief The minimum priority.
+ ///
+ /// This function returns the minimum priority.
+ /// \pre The heap must be non-empty.
+ const Prio& prio() const { return _data[_min].prio; }
+
+ /// \brief The priority of the given item.
+ ///
+ /// This function returns the priority of the given item.
+ /// \param item The item.
+ /// \pre \e item must be in the heap.
+ const Prio& operator[](const Item& item) const {
+ return _data[_iim[item]].prio;
+ }
+
+ /// \brief Remove the item having minimum priority.
+ ///
+ /// This function removes the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ void pop() {
+ std::vector<int> trees;
+ int i=0, child_right = 0;
+ _data[_min].in=false;
+
+ if( -1!=_data[_min].child ) {
+ i=_data[_min].child;
+ trees.push_back(i);
+ _data[i].parent = -1;
+ _data[_min].child = -1;
+
+ int ch=-1;
+ while( _data[i].child!=-1 ) {
+ ch=_data[i].child;
+ if( _data[ch].left_child && i==_data[ch].parent ) {
+ break;
+ } else {
+ if( _data[ch].left_child ) {
+ child_right=_data[ch].parent;
+ _data[ch].parent = i;
+ --_data[i].degree;
+ }
+ else {
+ child_right=ch;
+ _data[i].child=-1;
+ _data[i].degree=0;
+ }
+ _data[child_right].parent = -1;
+ trees.push_back(child_right);
+ i = child_right;
+ }
+ }
+
+ int num_child = trees.size();
+ int other;
+ for( i=0; i<num_child-1; i+=2 ) {
+ if ( !_comp(_data[trees[i]].prio, _data[trees[i+1]].prio) ) {
+ other=trees[i];
+ trees[i]=trees[i+1];
+ trees[i+1]=other;
+ }
+ fuse( trees[i], trees[i+1] );
+ }
+
+ i = (0==(num_child % 2)) ? num_child-2 : num_child-1;
+ while(i>=2) {
+ if ( _comp(_data[trees[i]].prio, _data[trees[i-2]].prio) ) {
+ other=trees[i];
+ trees[i]=trees[i-2];
+ trees[i-2]=other;
+ }
+ fuse( trees[i-2], trees[i] );
+ i-=2;
+ }
+ _min = trees[0];
+ }
+ else {
+ _min = _data[_min].child;
+ }
+
+ if (_min >= 0) _data[_min].left_child = false;
+ --_num_items;
+ }
+
+ /// \brief Remove the given item from the heap.
+ ///
+ /// This function removes the given item from the heap if it is
+ /// already stored.
+ /// \param item The item to delete.
+ /// \pre \e item must be in the heap.
+ void erase (const Item& item) {
+ int i=_iim[item];
+ if ( i>=0 && _data[i].in ) {
+ decrease( item, _data[_min].prio-1 );
+ pop();
+ }
+ }
+
+ /// \brief Decrease the priority of an item to the given value.
+ ///
+ /// This function decreases the priority of an item to the given value.
+ /// \param item The item.
+ /// \param value The priority.
+ /// \pre \e item must be stored in the heap with priority at least \e value.
+ void decrease (Item item, const Prio& value) {
+ int i=_iim[item];
+ _data[i].prio=value;
+ int p=_data[i].parent;
+
+ if( _data[i].left_child && i!=_data[p].child ) {
+ p=_data[p].parent;
+ }
+
+ if ( p!=-1 && _comp(value,_data[p].prio) ) {
+ cut(i,p);
+ if ( _comp(_data[_min].prio,value) ) {
+ fuse(_min,i);
+ } else {
+ fuse(i,_min);
+ _min=i;
+ }
+ }
+ }
+
+ /// \brief Increase the priority of an item to the given value.
+ ///
+ /// This function increases the priority of an item to the given value.
+ /// \param item The item.
+ /// \param value The priority.
+ /// \pre \e item must be stored in the heap with priority at most \e value.
+ void increase (Item item, const Prio& value) {
+ erase(item);
+ push(item,value);
+ }
+
+ /// \brief Return the state of an item.
+ ///
+ /// This method returns \c PRE_HEAP if the given item has never
+ /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
+ /// and \c POST_HEAP otherwise.
+ /// In the latter case it is possible that the item will get back
+ /// to the heap again.
+ /// \param item The item.
+ State state(const Item &item) const {
+ int i=_iim[item];
+ if( i>=0 ) {
+ if( _data[i].in ) i=0;
+ else i=-2;
+ }
+ return State(i);
+ }
+
+ /// \brief Set the state of an item in the heap.
+ ///
+ /// This function sets the state of the given item in the heap.
+ /// It can be used to manually clear the heap when it is important
+ /// to achive better time complexity.
+ /// \param i The item.
+ /// \param st The state. It should not be \c IN_HEAP.
+ void state(const Item& i, State st) {
+ switch (st) {
+ case POST_HEAP:
+ case PRE_HEAP:
+ if (state(i) == IN_HEAP) erase(i);
+ _iim[i]=st;
+ break;
+ case IN_HEAP:
+ break;
+ }
+ }
+
+ private:
+
+ void cut(int a, int b) {
+ int child_a;
+ switch (_data[a].degree) {
+ case 2:
+ child_a = _data[_data[a].child].parent;
+ if( _data[a].left_child ) {
+ _data[child_a].left_child=true;
+ _data[b].child=child_a;
+ _data[child_a].parent=_data[a].parent;
+ }
+ else {
+ _data[child_a].left_child=false;
+ _data[child_a].parent=b;
+ if( a!=_data[b].child )
+ _data[_data[b].child].parent=child_a;
+ else
+ _data[b].child=child_a;
+ }
+ --_data[a].degree;
+ _data[_data[a].child].parent=a;
+ break;
+
+ case 1:
+ child_a = _data[a].child;
+ if( !_data[child_a].left_child ) {
+ --_data[a].degree;
+ if( _data[a].left_child ) {
+ _data[child_a].left_child=true;
+ _data[child_a].parent=_data[a].parent;
+ _data[b].child=child_a;
+ }
+ else {
+ _data[child_a].left_child=false;
+ _data[child_a].parent=b;
+ if( a!=_data[b].child )
+ _data[_data[b].child].parent=child_a;
+ else
+ _data[b].child=child_a;
+ }
+ _data[a].child=-1;
+ }
+ else {
+ --_data[b].degree;
+ if( _data[a].left_child ) {
+ _data[b].child =
+ (1==_data[b].degree) ? _data[a].parent : -1;
+ } else {
+ if (1==_data[b].degree)
+ _data[_data[b].child].parent=b;
+ else
+ _data[b].child=-1;
+ }
+ }
+ break;
+
+ case 0:
+ --_data[b].degree;
+ if( _data[a].left_child ) {
+ _data[b].child =
+ (0!=_data[b].degree) ? _data[a].parent : -1;
+ } else {
+ if( 0!=_data[b].degree )
+ _data[_data[b].child].parent=b;
+ else
+ _data[b].child=-1;
+ }
+ break;
+ }
+ _data[a].parent=-1;
+ _data[a].left_child=false;
+ }
+
+ void fuse(int a, int b) {
+ int child_a = _data[a].child;
+ int child_b = _data[b].child;
+ _data[a].child=b;
+ _data[b].parent=a;
+ _data[b].left_child=true;
+
+ if( -1!=child_a ) {
+ _data[b].child=child_a;
+ _data[child_a].parent=b;
+ _data[child_a].left_child=false;
+ ++_data[b].degree;
+
+ if( -1!=child_b ) {
+ _data[b].child=child_b;
+ _data[child_b].parent=child_a;
+ }
+ }
+ else { ++_data[a].degree; }
+ }
+
+ class store {
+ friend class PairingHeap;
+
+ Item name;
+ int parent;
+ int child;
+ bool left_child;
+ int degree;
+ bool in;
+ Prio prio;
+
+ store() : parent(-1), child(-1), left_child(false), degree(0), in(true) {}
+ };
+ };
+
+} //namespace lemon
+
+#endif //LEMON_PAIRING_HEAP_H
+
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/path.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/path.h
new file mode 100644
index 00000000000..baa92c48baa
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/path.h
@@ -0,0 +1,1164 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\ingroup paths
+///\file
+///\brief Classes for representing paths in digraphs.
+///
+
+#ifndef LEMON_PATH_H
+#define LEMON_PATH_H
+
+#include <vector>
+#include <algorithm>
+
+#include <lemon/error.h>
+#include <lemon/core.h>
+#include <lemon/concepts/path.h>
+
+namespace lemon {
+
+ /// \addtogroup paths
+ /// @{
+
+
+ /// \brief A structure for representing directed paths in a digraph.
+ ///
+ /// A structure for representing directed path in a digraph.
+ /// \tparam GR The digraph type in which the path is.
+ ///
+ /// In a sense, the path can be treated as a list of arcs. The
+ /// LEMON path type stores just this list. As a consequence, it
+ /// cannot enumerate the nodes of the path and the source node of
+ /// a zero length path is undefined.
+ ///
+ /// This implementation is a back and front insertable and erasable
+ /// path type. It can be indexed in O(1) time. The front and back
+ /// insertion and erase is done in O(1) (amortized) time. The
+ /// implementation uses two vectors for storing the front and back
+ /// insertions.
+ template <typename GR>
+ class Path {
+ public:
+
+ typedef GR Digraph;
+ typedef typename Digraph::Arc Arc;
+
+ /// \brief Default constructor
+ ///
+ /// Default constructor
+ Path() {}
+
+ /// \brief Copy constructor
+ ///
+ Path(const Path& cpath) {
+ pathCopy(cpath, *this);
+ }
+
+ /// \brief Template copy constructor
+ ///
+ /// This constuctor initializes the path from any other path type.
+ /// It simply makes a copy of the given path.
+ template <typename CPath>
+ Path(const CPath& cpath) {
+ pathCopy(cpath, *this);
+ }
+
+ /// \brief Copy assignment
+ ///
+ Path& operator=(const Path& cpath) {
+ pathCopy(cpath, *this);
+ return *this;
+ }
+
+ /// \brief Template copy assignment
+ ///
+ /// This operator makes a copy of a path of any other type.
+ template <typename CPath>
+ Path& operator=(const CPath& cpath) {
+ pathCopy(cpath, *this);
+ return *this;
+ }
+
+ /// \brief LEMON style iterator for path arcs
+ ///
+ /// This class is used to iterate on the arcs of the paths.
+ class ArcIt {
+ friend class Path;
+ public:
+ /// \brief Default constructor
+ ArcIt() {}
+ /// \brief Invalid constructor
+ ArcIt(Invalid) : path(0), idx(-1) {}
+ /// \brief Initializate the iterator to the first arc of path
+ ArcIt(const Path &_path)
+ : path(&_path), idx(_path.empty() ? -1 : 0) {}
+
+ private:
+
+ ArcIt(const Path &_path, int _idx)
+ : path(&_path), idx(_idx) {}
+
+ public:
+
+ /// \brief Conversion to Arc
+ operator const Arc&() const {
+ return path->nth(idx);
+ }
+
+ /// \brief Next arc
+ ArcIt& operator++() {
+ ++idx;
+ if (idx >= path->length()) idx = -1;
+ return *this;
+ }
+
+ /// \brief Comparison operator
+ bool operator==(const ArcIt& e) const { return idx==e.idx; }
+ /// \brief Comparison operator
+ bool operator!=(const ArcIt& e) const { return idx!=e.idx; }
+ /// \brief Comparison operator
+ bool operator<(const ArcIt& e) const { return idx<e.idx; }
+
+ private:
+ const Path *path;
+ int idx;
+ };
+
+ /// \brief Length of the path.
+ int length() const { return head.size() + tail.size(); }
+ /// \brief Return whether the path is empty.
+ bool empty() const { return head.empty() && tail.empty(); }
+
+ /// \brief Reset the path to an empty one.
+ void clear() { head.clear(); tail.clear(); }
+
+ /// \brief The n-th arc.
+ ///
+ /// \pre \c n is in the <tt>[0..length() - 1]</tt> range.
+ const Arc& nth(int n) const {
+ return n < int(head.size()) ? *(head.rbegin() + n) :
+ *(tail.begin() + (n - head.size()));
+ }
+
+ /// \brief Initialize arc iterator to point to the n-th arc
+ ///
+ /// \pre \c n is in the <tt>[0..length() - 1]</tt> range.
+ ArcIt nthIt(int n) const {
+ return ArcIt(*this, n);
+ }
+
+ /// \brief The first arc of the path
+ const Arc& front() const {
+ return head.empty() ? tail.front() : head.back();
+ }
+
+ /// \brief Add a new arc before the current path
+ void addFront(const Arc& arc) {
+ head.push_back(arc);
+ }
+
+ /// \brief Erase the first arc of the path
+ void eraseFront() {
+ if (!head.empty()) {
+ head.pop_back();
+ } else {
+ head.clear();
+ int halfsize = tail.size() / 2;
+ head.resize(halfsize);
+ std::copy(tail.begin() + 1, tail.begin() + halfsize + 1,
+ head.rbegin());
+ std::copy(tail.begin() + halfsize + 1, tail.end(), tail.begin());
+ tail.resize(tail.size() - halfsize - 1);
+ }
+ }
+
+ /// \brief The last arc of the path
+ const Arc& back() const {
+ return tail.empty() ? head.front() : tail.back();
+ }
+
+ /// \brief Add a new arc behind the current path
+ void addBack(const Arc& arc) {
+ tail.push_back(arc);
+ }
+
+ /// \brief Erase the last arc of the path
+ void eraseBack() {
+ if (!tail.empty()) {
+ tail.pop_back();
+ } else {
+ int halfsize = head.size() / 2;
+ tail.resize(halfsize);
+ std::copy(head.begin() + 1, head.begin() + halfsize + 1,
+ tail.rbegin());
+ std::copy(head.begin() + halfsize + 1, head.end(), head.begin());
+ head.resize(head.size() - halfsize - 1);
+ }
+ }
+
+ typedef True BuildTag;
+
+ template <typename CPath>
+ void build(const CPath& path) {
+ int len = path.length();
+ tail.reserve(len);
+ for (typename CPath::ArcIt it(path); it != INVALID; ++it) {
+ tail.push_back(it);
+ }
+ }
+
+ template <typename CPath>
+ void buildRev(const CPath& path) {
+ int len = path.length();
+ head.reserve(len);
+ for (typename CPath::RevArcIt it(path); it != INVALID; ++it) {
+ head.push_back(it);
+ }
+ }
+
+ protected:
+ typedef std::vector<Arc> Container;
+ Container head, tail;
+
+ };
+
+ /// \brief A structure for representing directed paths in a digraph.
+ ///
+ /// A structure for representing directed path in a digraph.
+ /// \tparam GR The digraph type in which the path is.
+ ///
+ /// In a sense, the path can be treated as a list of arcs. The
+ /// LEMON path type stores just this list. As a consequence it
+ /// cannot enumerate the nodes in the path and the zero length paths
+ /// cannot store the source.
+ ///
+ /// This implementation is a just back insertable and erasable path
+ /// type. It can be indexed in O(1) time. The back insertion and
+ /// erasure is amortized O(1) time. This implementation is faster
+ /// then the \c Path type because it use just one vector for the
+ /// arcs.
+ template <typename GR>
+ class SimplePath {
+ public:
+
+ typedef GR Digraph;
+ typedef typename Digraph::Arc Arc;
+
+ /// \brief Default constructor
+ ///
+ /// Default constructor
+ SimplePath() {}
+
+ /// \brief Copy constructor
+ ///
+ SimplePath(const SimplePath& cpath) {
+ pathCopy(cpath, *this);
+ }
+
+ /// \brief Template copy constructor
+ ///
+ /// This path can be initialized with any other path type. It just
+ /// makes a copy of the given path.
+ template <typename CPath>
+ SimplePath(const CPath& cpath) {
+ pathCopy(cpath, *this);
+ }
+
+ /// \brief Copy assignment
+ ///
+ SimplePath& operator=(const SimplePath& cpath) {
+ pathCopy(cpath, *this);
+ return *this;
+ }
+
+ /// \brief Template copy assignment
+ ///
+ /// This path can be initialized with any other path type. It just
+ /// makes a copy of the given path.
+ template <typename CPath>
+ SimplePath& operator=(const CPath& cpath) {
+ pathCopy(cpath, *this);
+ return *this;
+ }
+
+ /// \brief Iterator class to iterate on the arcs of the paths
+ ///
+ /// This class is used to iterate on the arcs of the paths
+ ///
+ /// Of course it converts to Digraph::Arc
+ class ArcIt {
+ friend class SimplePath;
+ public:
+ /// Default constructor
+ ArcIt() {}
+ /// Invalid constructor
+ ArcIt(Invalid) : path(0), idx(-1) {}
+ /// \brief Initializate the constructor to the first arc of path
+ ArcIt(const SimplePath &_path)
+ : path(&_path), idx(_path.empty() ? -1 : 0) {}
+
+ private:
+
+ /// Constructor with starting point
+ ArcIt(const SimplePath &_path, int _idx)
+ : path(&_path), idx(_idx) {}
+
+ public:
+
+ ///Conversion to Digraph::Arc
+ operator const Arc&() const {
+ return path->nth(idx);
+ }
+
+ /// Next arc
+ ArcIt& operator++() {
+ ++idx;
+ if (idx >= path->length()) idx = -1;
+ return *this;
+ }
+
+ /// Comparison operator
+ bool operator==(const ArcIt& e) const { return idx==e.idx; }
+ /// Comparison operator
+ bool operator!=(const ArcIt& e) const { return idx!=e.idx; }
+ /// Comparison operator
+ bool operator<(const ArcIt& e) const { return idx<e.idx; }
+
+ private:
+ const SimplePath *path;
+ int idx;
+ };
+
+ /// \brief Length of the path.
+ int length() const { return data.size(); }
+ /// \brief Return true if the path is empty.
+ bool empty() const { return data.empty(); }
+
+ /// \brief Reset the path to an empty one.
+ void clear() { data.clear(); }
+
+ /// \brief The n-th arc.
+ ///
+ /// \pre \c n is in the <tt>[0..length() - 1]</tt> range.
+ const Arc& nth(int n) const {
+ return data[n];
+ }
+
+ /// \brief Initializes arc iterator to point to the n-th arc.
+ ArcIt nthIt(int n) const {
+ return ArcIt(*this, n);
+ }
+
+ /// \brief The first arc of the path.
+ const Arc& front() const {
+ return data.front();
+ }
+
+ /// \brief The last arc of the path.
+ const Arc& back() const {
+ return data.back();
+ }
+
+ /// \brief Add a new arc behind the current path.
+ void addBack(const Arc& arc) {
+ data.push_back(arc);
+ }
+
+ /// \brief Erase the last arc of the path
+ void eraseBack() {
+ data.pop_back();
+ }
+
+ typedef True BuildTag;
+
+ template <typename CPath>
+ void build(const CPath& path) {
+ int len = path.length();
+ data.resize(len);
+ int index = 0;
+ for (typename CPath::ArcIt it(path); it != INVALID; ++it) {
+ data[index] = it;;
+ ++index;
+ }
+ }
+
+ template <typename CPath>
+ void buildRev(const CPath& path) {
+ int len = path.length();
+ data.resize(len);
+ int index = len;
+ for (typename CPath::RevArcIt it(path); it != INVALID; ++it) {
+ --index;
+ data[index] = it;;
+ }
+ }
+
+ protected:
+ typedef std::vector<Arc> Container;
+ Container data;
+
+ };
+
+ /// \brief A structure for representing directed paths in a digraph.
+ ///
+ /// A structure for representing directed path in a digraph.
+ /// \tparam GR The digraph type in which the path is.
+ ///
+ /// In a sense, the path can be treated as a list of arcs. The
+ /// LEMON path type stores just this list. As a consequence it
+ /// cannot enumerate the nodes in the path and the zero length paths
+ /// cannot store the source.
+ ///
+ /// This implementation is a back and front insertable and erasable
+ /// path type. It can be indexed in O(k) time, where k is the rank
+ /// of the arc in the path. The length can be computed in O(n)
+ /// time. The front and back insertion and erasure is O(1) time
+ /// and it can be splited and spliced in O(1) time.
+ template <typename GR>
+ class ListPath {
+ public:
+
+ typedef GR Digraph;
+ typedef typename Digraph::Arc Arc;
+
+ protected:
+
+ // the std::list<> is incompatible
+ // hard to create invalid iterator
+ struct Node {
+ Arc arc;
+ Node *next, *prev;
+ };
+
+ Node *first, *last;
+
+ std::allocator<Node> alloc;
+
+ public:
+
+ /// \brief Default constructor
+ ///
+ /// Default constructor
+ ListPath() : first(0), last(0) {}
+
+ /// \brief Copy constructor
+ ///
+ ListPath(const ListPath& cpath) : first(0), last(0) {
+ pathCopy(cpath, *this);
+ }
+
+ /// \brief Template copy constructor
+ ///
+ /// This path can be initialized with any other path type. It just
+ /// makes a copy of the given path.
+ template <typename CPath>
+ ListPath(const CPath& cpath) : first(0), last(0) {
+ pathCopy(cpath, *this);
+ }
+
+ /// \brief Destructor of the path
+ ///
+ /// Destructor of the path
+ ~ListPath() {
+ clear();
+ }
+
+ /// \brief Copy assignment
+ ///
+ ListPath& operator=(const ListPath& cpath) {
+ pathCopy(cpath, *this);
+ return *this;
+ }
+
+ /// \brief Template copy assignment
+ ///
+ /// This path can be initialized with any other path type. It just
+ /// makes a copy of the given path.
+ template <typename CPath>
+ ListPath& operator=(const CPath& cpath) {
+ pathCopy(cpath, *this);
+ return *this;
+ }
+
+ /// \brief Iterator class to iterate on the arcs of the paths
+ ///
+ /// This class is used to iterate on the arcs of the paths
+ ///
+ /// Of course it converts to Digraph::Arc
+ class ArcIt {
+ friend class ListPath;
+ public:
+ /// Default constructor
+ ArcIt() {}
+ /// Invalid constructor
+ ArcIt(Invalid) : path(0), node(0) {}
+ /// \brief Initializate the constructor to the first arc of path
+ ArcIt(const ListPath &_path)
+ : path(&_path), node(_path.first) {}
+
+ protected:
+
+ ArcIt(const ListPath &_path, Node *_node)
+ : path(&_path), node(_node) {}
+
+
+ public:
+
+ ///Conversion to Digraph::Arc
+ operator const Arc&() const {
+ return node->arc;
+ }
+
+ /// Next arc
+ ArcIt& operator++() {
+ node = node->next;
+ return *this;
+ }
+
+ /// Comparison operator
+ bool operator==(const ArcIt& e) const { return node==e.node; }
+ /// Comparison operator
+ bool operator!=(const ArcIt& e) const { return node!=e.node; }
+ /// Comparison operator
+ bool operator<(const ArcIt& e) const { return node<e.node; }
+
+ private:
+ const ListPath *path;
+ Node *node;
+ };
+
+ /// \brief The n-th arc.
+ ///
+ /// This function looks for the n-th arc in O(n) time.
+ /// \pre \c n is in the <tt>[0..length() - 1]</tt> range.
+ const Arc& nth(int n) const {
+ Node *node = first;
+ for (int i = 0; i < n; ++i) {
+ node = node->next;
+ }
+ return node->arc;
+ }
+
+ /// \brief Initializes arc iterator to point to the n-th arc.
+ ArcIt nthIt(int n) const {
+ Node *node = first;
+ for (int i = 0; i < n; ++i) {
+ node = node->next;
+ }
+ return ArcIt(*this, node);
+ }
+
+ /// \brief Length of the path.
+ int length() const {
+ int len = 0;
+ Node *node = first;
+ while (node != 0) {
+ node = node->next;
+ ++len;
+ }
+ return len;
+ }
+
+ /// \brief Return true if the path is empty.
+ bool empty() const { return first == 0; }
+
+ /// \brief Reset the path to an empty one.
+ void clear() {
+ while (first != 0) {
+ last = first->next;
+ alloc.destroy(first);
+ alloc.deallocate(first, 1);
+ first = last;
+ }
+ }
+
+ /// \brief The first arc of the path
+ const Arc& front() const {
+ return first->arc;
+ }
+
+ /// \brief Add a new arc before the current path
+ void addFront(const Arc& arc) {
+ Node *node = alloc.allocate(1);
+ alloc.construct(node, Node());
+ node->prev = 0;
+ node->next = first;
+ node->arc = arc;
+ if (first) {
+ first->prev = node;
+ first = node;
+ } else {
+ first = last = node;
+ }
+ }
+
+ /// \brief Erase the first arc of the path
+ void eraseFront() {
+ Node *node = first;
+ first = first->next;
+ if (first) {
+ first->prev = 0;
+ } else {
+ last = 0;
+ }
+ alloc.destroy(node);
+ alloc.deallocate(node, 1);
+ }
+
+ /// \brief The last arc of the path.
+ const Arc& back() const {
+ return last->arc;
+ }
+
+ /// \brief Add a new arc behind the current path.
+ void addBack(const Arc& arc) {
+ Node *node = alloc.allocate(1);
+ alloc.construct(node, Node());
+ node->next = 0;
+ node->prev = last;
+ node->arc = arc;
+ if (last) {
+ last->next = node;
+ last = node;
+ } else {
+ last = first = node;
+ }
+ }
+
+ /// \brief Erase the last arc of the path
+ void eraseBack() {
+ Node *node = last;
+ last = last->prev;
+ if (last) {
+ last->next = 0;
+ } else {
+ first = 0;
+ }
+ alloc.destroy(node);
+ alloc.deallocate(node, 1);
+ }
+
+ /// \brief Splice a path to the back of the current path.
+ ///
+ /// It splices \c tpath to the back of the current path and \c
+ /// tpath becomes empty. The time complexity of this function is
+ /// O(1).
+ void spliceBack(ListPath& tpath) {
+ if (first) {
+ if (tpath.first) {
+ last->next = tpath.first;
+ tpath.first->prev = last;
+ last = tpath.last;
+ }
+ } else {
+ first = tpath.first;
+ last = tpath.last;
+ }
+ tpath.first = tpath.last = 0;
+ }
+
+ /// \brief Splice a path to the front of the current path.
+ ///
+ /// It splices \c tpath before the current path and \c tpath
+ /// becomes empty. The time complexity of this function
+ /// is O(1).
+ void spliceFront(ListPath& tpath) {
+ if (first) {
+ if (tpath.first) {
+ first->prev = tpath.last;
+ tpath.last->next = first;
+ first = tpath.first;
+ }
+ } else {
+ first = tpath.first;
+ last = tpath.last;
+ }
+ tpath.first = tpath.last = 0;
+ }
+
+ /// \brief Splice a path into the current path.
+ ///
+ /// It splices the \c tpath into the current path before the
+ /// position of \c it iterator and \c tpath becomes empty. The
+ /// time complexity of this function is O(1). If the \c it is
+ /// \c INVALID then it will splice behind the current path.
+ void splice(ArcIt it, ListPath& tpath) {
+ if (it.node) {
+ if (tpath.first) {
+ tpath.first->prev = it.node->prev;
+ if (it.node->prev) {
+ it.node->prev->next = tpath.first;
+ } else {
+ first = tpath.first;
+ }
+ it.node->prev = tpath.last;
+ tpath.last->next = it.node;
+ }
+ } else {
+ if (first) {
+ if (tpath.first) {
+ last->next = tpath.first;
+ tpath.first->prev = last;
+ last = tpath.last;
+ }
+ } else {
+ first = tpath.first;
+ last = tpath.last;
+ }
+ }
+ tpath.first = tpath.last = 0;
+ }
+
+ /// \brief Split the current path.
+ ///
+ /// It splits the current path into two parts. The part before
+ /// the iterator \c it will remain in the current path and the part
+ /// starting with
+ /// \c it will put into \c tpath. If \c tpath have arcs
+ /// before the operation they are removed first. The time
+ /// complexity of this function is O(1) plus the the time of emtying
+ /// \c tpath. If \c it is \c INVALID then it just clears \c tpath
+ void split(ArcIt it, ListPath& tpath) {
+ tpath.clear();
+ if (it.node) {
+ tpath.first = it.node;
+ tpath.last = last;
+ if (it.node->prev) {
+ last = it.node->prev;
+ last->next = 0;
+ } else {
+ first = last = 0;
+ }
+ it.node->prev = 0;
+ }
+ }
+
+
+ typedef True BuildTag;
+
+ template <typename CPath>
+ void build(const CPath& path) {
+ for (typename CPath::ArcIt it(path); it != INVALID; ++it) {
+ addBack(it);
+ }
+ }
+
+ template <typename CPath>
+ void buildRev(const CPath& path) {
+ for (typename CPath::RevArcIt it(path); it != INVALID; ++it) {
+ addFront(it);
+ }
+ }
+
+ };
+
+ /// \brief A structure for representing directed paths in a digraph.
+ ///
+ /// A structure for representing directed path in a digraph.
+ /// \tparam GR The digraph type in which the path is.
+ ///
+ /// In a sense, the path can be treated as a list of arcs. The
+ /// LEMON path type stores just this list. As a consequence it
+ /// cannot enumerate the nodes in the path and the source node of
+ /// a zero length path is undefined.
+ ///
+ /// This implementation is completly static, i.e. it can be copy constucted
+ /// or copy assigned from another path, but otherwise it cannot be
+ /// modified.
+ ///
+ /// Being the the most memory efficient path type in LEMON,
+ /// it is intented to be
+ /// used when you want to store a large number of paths.
+ template <typename GR>
+ class StaticPath {
+ public:
+
+ typedef GR Digraph;
+ typedef typename Digraph::Arc Arc;
+
+ /// \brief Default constructor
+ ///
+ /// Default constructor
+ StaticPath() : len(0), arcs(0) {}
+
+ /// \brief Copy constructor
+ ///
+ StaticPath(const StaticPath& cpath) : arcs(0) {
+ pathCopy(cpath, *this);
+ }
+
+ /// \brief Template copy constructor
+ ///
+ /// This path can be initialized from any other path type.
+ template <typename CPath>
+ StaticPath(const CPath& cpath) : arcs(0) {
+ pathCopy(cpath, *this);
+ }
+
+ /// \brief Destructor of the path
+ ///
+ /// Destructor of the path
+ ~StaticPath() {
+ if (arcs) delete[] arcs;
+ }
+
+ /// \brief Copy assignment
+ ///
+ StaticPath& operator=(const StaticPath& cpath) {
+ pathCopy(cpath, *this);
+ return *this;
+ }
+
+ /// \brief Template copy assignment
+ ///
+ /// This path can be made equal to any other path type. It simply
+ /// makes a copy of the given path.
+ template <typename CPath>
+ StaticPath& operator=(const CPath& cpath) {
+ pathCopy(cpath, *this);
+ return *this;
+ }
+
+ /// \brief Iterator class to iterate on the arcs of the paths
+ ///
+ /// This class is used to iterate on the arcs of the paths
+ ///
+ /// Of course it converts to Digraph::Arc
+ class ArcIt {
+ friend class StaticPath;
+ public:
+ /// Default constructor
+ ArcIt() {}
+ /// Invalid constructor
+ ArcIt(Invalid) : path(0), idx(-1) {}
+ /// Initializate the constructor to the first arc of path
+ ArcIt(const StaticPath &_path)
+ : path(&_path), idx(_path.empty() ? -1 : 0) {}
+
+ private:
+
+ /// Constructor with starting point
+ ArcIt(const StaticPath &_path, int _idx)
+ : idx(_idx), path(&_path) {}
+
+ public:
+
+ ///Conversion to Digraph::Arc
+ operator const Arc&() const {
+ return path->nth(idx);
+ }
+
+ /// Next arc
+ ArcIt& operator++() {
+ ++idx;
+ if (idx >= path->length()) idx = -1;
+ return *this;
+ }
+
+ /// Comparison operator
+ bool operator==(const ArcIt& e) const { return idx==e.idx; }
+ /// Comparison operator
+ bool operator!=(const ArcIt& e) const { return idx!=e.idx; }
+ /// Comparison operator
+ bool operator<(const ArcIt& e) const { return idx<e.idx; }
+
+ private:
+ const StaticPath *path;
+ int idx;
+ };
+
+ /// \brief The n-th arc.
+ ///
+ /// \pre \c n is in the <tt>[0..length() - 1]</tt> range.
+ const Arc& nth(int n) const {
+ return arcs[n];
+ }
+
+ /// \brief The arc iterator pointing to the n-th arc.
+ ArcIt nthIt(int n) const {
+ return ArcIt(*this, n);
+ }
+
+ /// \brief The length of the path.
+ int length() const { return len; }
+
+ /// \brief Return true when the path is empty.
+ int empty() const { return len == 0; }
+
+ /// \brief Erase all arcs in the digraph.
+ void clear() {
+ len = 0;
+ if (arcs) delete[] arcs;
+ arcs = 0;
+ }
+
+ /// \brief The first arc of the path.
+ const Arc& front() const {
+ return arcs[0];
+ }
+
+ /// \brief The last arc of the path.
+ const Arc& back() const {
+ return arcs[len - 1];
+ }
+
+
+ typedef True BuildTag;
+
+ template <typename CPath>
+ void build(const CPath& path) {
+ len = path.length();
+ arcs = new Arc[len];
+ int index = 0;
+ for (typename CPath::ArcIt it(path); it != INVALID; ++it) {
+ arcs[index] = it;
+ ++index;
+ }
+ }
+
+ template <typename CPath>
+ void buildRev(const CPath& path) {
+ len = path.length();
+ arcs = new Arc[len];
+ int index = len;
+ for (typename CPath::RevArcIt it(path); it != INVALID; ++it) {
+ --index;
+ arcs[index] = it;
+ }
+ }
+
+ private:
+ int len;
+ Arc* arcs;
+ };
+
+ ///////////////////////////////////////////////////////////////////////
+ // Additional utilities
+ ///////////////////////////////////////////////////////////////////////
+
+ namespace _path_bits {
+
+ template <typename Path, typename Enable = void>
+ struct RevPathTagIndicator {
+ static const bool value = false;
+ };
+
+ template <typename Path>
+ struct RevPathTagIndicator<
+ Path,
+ typename enable_if<typename Path::RevPathTag, void>::type
+ > {
+ static const bool value = true;
+ };
+
+ template <typename Path, typename Enable = void>
+ struct BuildTagIndicator {
+ static const bool value = false;
+ };
+
+ template <typename Path>
+ struct BuildTagIndicator<
+ Path,
+ typename enable_if<typename Path::BuildTag, void>::type
+ > {
+ static const bool value = true;
+ };
+
+ template <typename From, typename To,
+ bool buildEnable = BuildTagIndicator<To>::value>
+ struct PathCopySelectorForward {
+ static void copy(const From& from, To& to) {
+ to.clear();
+ for (typename From::ArcIt it(from); it != INVALID; ++it) {
+ to.addBack(it);
+ }
+ }
+ };
+
+ template <typename From, typename To>
+ struct PathCopySelectorForward<From, To, true> {
+ static void copy(const From& from, To& to) {
+ to.clear();
+ to.build(from);
+ }
+ };
+
+ template <typename From, typename To,
+ bool buildEnable = BuildTagIndicator<To>::value>
+ struct PathCopySelectorBackward {
+ static void copy(const From& from, To& to) {
+ to.clear();
+ for (typename From::RevArcIt it(from); it != INVALID; ++it) {
+ to.addFront(it);
+ }
+ }
+ };
+
+ template <typename From, typename To>
+ struct PathCopySelectorBackward<From, To, true> {
+ static void copy(const From& from, To& to) {
+ to.clear();
+ to.buildRev(from);
+ }
+ };
+
+
+ template <typename From, typename To,
+ bool revEnable = RevPathTagIndicator<From>::value>
+ struct PathCopySelector {
+ static void copy(const From& from, To& to) {
+ PathCopySelectorForward<From, To>::copy(from, to);
+ }
+ };
+
+ template <typename From, typename To>
+ struct PathCopySelector<From, To, true> {
+ static void copy(const From& from, To& to) {
+ PathCopySelectorBackward<From, To>::copy(from, to);
+ }
+ };
+
+ }
+
+
+ /// \brief Make a copy of a path.
+ ///
+ /// This function makes a copy of a path.
+ template <typename From, typename To>
+ void pathCopy(const From& from, To& to) {
+ checkConcept<concepts::PathDumper<typename From::Digraph>, From>();
+ _path_bits::PathCopySelector<From, To>::copy(from, to);
+ }
+
+ /// \brief Deprecated version of \ref pathCopy().
+ ///
+ /// Deprecated version of \ref pathCopy() (only for reverse compatibility).
+ template <typename To, typename From>
+ void copyPath(To& to, const From& from) {
+ pathCopy(from, to);
+ }
+
+ /// \brief Check the consistency of a path.
+ ///
+ /// This function checks that the target of each arc is the same
+ /// as the source of the next one.
+ ///
+ template <typename Digraph, typename Path>
+ bool checkPath(const Digraph& digraph, const Path& path) {
+ typename Path::ArcIt it(path);
+ if (it == INVALID) return true;
+ typename Digraph::Node node = digraph.target(it);
+ ++it;
+ while (it != INVALID) {
+ if (digraph.source(it) != node) return false;
+ node = digraph.target(it);
+ ++it;
+ }
+ return true;
+ }
+
+ /// \brief The source of a path
+ ///
+ /// This function returns the source node of the given path.
+ /// If the path is empty, then it returns \c INVALID.
+ template <typename Digraph, typename Path>
+ typename Digraph::Node pathSource(const Digraph& digraph, const Path& path) {
+ return path.empty() ? INVALID : digraph.source(path.front());
+ }
+
+ /// \brief The target of a path
+ ///
+ /// This function returns the target node of the given path.
+ /// If the path is empty, then it returns \c INVALID.
+ template <typename Digraph, typename Path>
+ typename Digraph::Node pathTarget(const Digraph& digraph, const Path& path) {
+ return path.empty() ? INVALID : digraph.target(path.back());
+ }
+
+ /// \brief Class which helps to iterate through the nodes of a path
+ ///
+ /// In a sense, the path can be treated as a list of arcs. The
+ /// LEMON path type stores only this list. As a consequence, it
+ /// cannot enumerate the nodes in the path and the zero length paths
+ /// cannot have a source node.
+ ///
+ /// This class implements the node iterator of a path structure. To
+ /// provide this feature, the underlying digraph should be passed to
+ /// the constructor of the iterator.
+ template <typename Path>
+ class PathNodeIt {
+ private:
+ const typename Path::Digraph *_digraph;
+ typename Path::ArcIt _it;
+ typename Path::Digraph::Node _nd;
+
+ public:
+
+ typedef typename Path::Digraph Digraph;
+ typedef typename Digraph::Node Node;
+
+ /// Default constructor
+ PathNodeIt() {}
+ /// Invalid constructor
+ PathNodeIt(Invalid)
+ : _digraph(0), _it(INVALID), _nd(INVALID) {}
+ /// Constructor
+ PathNodeIt(const Digraph& digraph, const Path& path)
+ : _digraph(&digraph), _it(path) {
+ _nd = (_it != INVALID ? _digraph->source(_it) : INVALID);
+ }
+ /// Constructor
+ PathNodeIt(const Digraph& digraph, const Path& path, const Node& src)
+ : _digraph(&digraph), _it(path), _nd(src) {}
+
+ ///Conversion to Digraph::Node
+ operator Node() const {
+ return _nd;
+ }
+
+ /// Next node
+ PathNodeIt& operator++() {
+ if (_it == INVALID) _nd = INVALID;
+ else {
+ _nd = _digraph->target(_it);
+ ++_it;
+ }
+ return *this;
+ }
+
+ /// Comparison operator
+ bool operator==(const PathNodeIt& n) const {
+ return _it == n._it && _nd == n._nd;
+ }
+ /// Comparison operator
+ bool operator!=(const PathNodeIt& n) const {
+ return _it != n._it || _nd != n._nd;
+ }
+ /// Comparison operator
+ bool operator<(const PathNodeIt& n) const {
+ return (_it < n._it && _nd != INVALID);
+ }
+
+ };
+
+ ///@}
+
+} // namespace lemon
+
+#endif // LEMON_PATH_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/planarity.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/planarity.h
new file mode 100644
index 00000000000..bfe8e85dc4d
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/planarity.h
@@ -0,0 +1,2754 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_PLANARITY_H
+#define LEMON_PLANARITY_H
+
+/// \ingroup planar
+/// \file
+/// \brief Planarity checking, embedding, drawing and coloring
+
+#include <vector>
+#include <list>
+
+#include <lemon/dfs.h>
+#include <lemon/bfs.h>
+#include <lemon/radix_sort.h>
+#include <lemon/maps.h>
+#include <lemon/path.h>
+#include <lemon/bucket_heap.h>
+#include <lemon/adaptors.h>
+#include <lemon/edge_set.h>
+#include <lemon/color.h>
+#include <lemon/dim2.h>
+
+namespace lemon {
+
+ namespace _planarity_bits {
+
+ template <typename Graph>
+ struct PlanarityVisitor : DfsVisitor<Graph> {
+
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+ typedef typename Graph::template NodeMap<Arc> PredMap;
+
+ typedef typename Graph::template EdgeMap<bool> TreeMap;
+
+ typedef typename Graph::template NodeMap<int> OrderMap;
+ typedef std::vector<Node> OrderList;
+
+ typedef typename Graph::template NodeMap<int> LowMap;
+ typedef typename Graph::template NodeMap<int> AncestorMap;
+
+ PlanarityVisitor(const Graph& graph,
+ PredMap& pred_map, TreeMap& tree_map,
+ OrderMap& order_map, OrderList& order_list,
+ AncestorMap& ancestor_map, LowMap& low_map)
+ : _graph(graph), _pred_map(pred_map), _tree_map(tree_map),
+ _order_map(order_map), _order_list(order_list),
+ _ancestor_map(ancestor_map), _low_map(low_map) {}
+
+ void reach(const Node& node) {
+ _order_map[node] = _order_list.size();
+ _low_map[node] = _order_list.size();
+ _ancestor_map[node] = _order_list.size();
+ _order_list.push_back(node);
+ }
+
+ void discover(const Arc& arc) {
+ Node target = _graph.target(arc);
+
+ _tree_map[arc] = true;
+ _pred_map[target] = arc;
+ }
+
+ void examine(const Arc& arc) {
+ Node source = _graph.source(arc);
+ Node target = _graph.target(arc);
+
+ if (_order_map[target] < _order_map[source] && !_tree_map[arc]) {
+ if (_low_map[source] > _order_map[target]) {
+ _low_map[source] = _order_map[target];
+ }
+ if (_ancestor_map[source] > _order_map[target]) {
+ _ancestor_map[source] = _order_map[target];
+ }
+ }
+ }
+
+ void backtrack(const Arc& arc) {
+ Node source = _graph.source(arc);
+ Node target = _graph.target(arc);
+
+ if (_low_map[source] > _low_map[target]) {
+ _low_map[source] = _low_map[target];
+ }
+ }
+
+ const Graph& _graph;
+ PredMap& _pred_map;
+ TreeMap& _tree_map;
+ OrderMap& _order_map;
+ OrderList& _order_list;
+ AncestorMap& _ancestor_map;
+ LowMap& _low_map;
+ };
+
+ template <typename Graph, bool embedding = true>
+ struct NodeDataNode {
+ int prev, next;
+ int visited;
+ typename Graph::Arc first;
+ bool inverted;
+ };
+
+ template <typename Graph>
+ struct NodeDataNode<Graph, false> {
+ int prev, next;
+ int visited;
+ };
+
+ template <typename Graph>
+ struct ChildListNode {
+ typedef typename Graph::Node Node;
+ Node first;
+ Node prev, next;
+ };
+
+ template <typename Graph>
+ struct ArcListNode {
+ typename Graph::Arc prev, next;
+ };
+
+ template <typename Graph>
+ class PlanarityChecking {
+ private:
+
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+ const Graph& _graph;
+
+ private:
+
+ typedef typename Graph::template NodeMap<Arc> PredMap;
+
+ typedef typename Graph::template EdgeMap<bool> TreeMap;
+
+ typedef typename Graph::template NodeMap<int> OrderMap;
+ typedef std::vector<Node> OrderList;
+
+ typedef typename Graph::template NodeMap<int> LowMap;
+ typedef typename Graph::template NodeMap<int> AncestorMap;
+
+ typedef _planarity_bits::NodeDataNode<Graph> NodeDataNode;
+ typedef std::vector<NodeDataNode> NodeData;
+
+ typedef _planarity_bits::ChildListNode<Graph> ChildListNode;
+ typedef typename Graph::template NodeMap<ChildListNode> ChildLists;
+
+ typedef typename Graph::template NodeMap<std::list<int> > MergeRoots;
+
+ typedef typename Graph::template NodeMap<bool> EmbedArc;
+
+ public:
+
+ PlanarityChecking(const Graph& graph) : _graph(graph) {}
+
+ bool run() {
+ typedef _planarity_bits::PlanarityVisitor<Graph> Visitor;
+
+ PredMap pred_map(_graph, INVALID);
+ TreeMap tree_map(_graph, false);
+
+ OrderMap order_map(_graph, -1);
+ OrderList order_list;
+
+ AncestorMap ancestor_map(_graph, -1);
+ LowMap low_map(_graph, -1);
+
+ Visitor visitor(_graph, pred_map, tree_map,
+ order_map, order_list, ancestor_map, low_map);
+ DfsVisit<Graph, Visitor> visit(_graph, visitor);
+ visit.run();
+
+ ChildLists child_lists(_graph);
+ createChildLists(tree_map, order_map, low_map, child_lists);
+
+ NodeData node_data(2 * order_list.size());
+
+ EmbedArc embed_arc(_graph, false);
+
+ MergeRoots merge_roots(_graph);
+
+ for (int i = order_list.size() - 1; i >= 0; --i) {
+
+ Node node = order_list[i];
+
+ Node source = node;
+ for (OutArcIt e(_graph, node); e != INVALID; ++e) {
+ Node target = _graph.target(e);
+
+ if (order_map[source] < order_map[target] && tree_map[e]) {
+ initFace(target, node_data, order_map, order_list);
+ }
+ }
+
+ for (OutArcIt e(_graph, node); e != INVALID; ++e) {
+ Node target = _graph.target(e);
+
+ if (order_map[source] < order_map[target] && !tree_map[e]) {
+ embed_arc[target] = true;
+ walkUp(target, source, i, pred_map, low_map,
+ order_map, order_list, node_data, merge_roots);
+ }
+ }
+
+ for (typename MergeRoots::Value::iterator it =
+ merge_roots[node].begin();
+ it != merge_roots[node].end(); ++it) {
+ int rn = *it;
+ walkDown(rn, i, node_data, order_list, child_lists,
+ ancestor_map, low_map, embed_arc, merge_roots);
+ }
+ merge_roots[node].clear();
+
+ for (OutArcIt e(_graph, node); e != INVALID; ++e) {
+ Node target = _graph.target(e);
+
+ if (order_map[source] < order_map[target] && !tree_map[e]) {
+ if (embed_arc[target]) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private:
+
+ void createChildLists(const TreeMap& tree_map, const OrderMap& order_map,
+ const LowMap& low_map, ChildLists& child_lists) {
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ Node source = n;
+
+ std::vector<Node> targets;
+ for (OutArcIt e(_graph, n); e != INVALID; ++e) {
+ Node target = _graph.target(e);
+
+ if (order_map[source] < order_map[target] && tree_map[e]) {
+ targets.push_back(target);
+ }
+ }
+
+ if (targets.size() == 0) {
+ child_lists[source].first = INVALID;
+ } else if (targets.size() == 1) {
+ child_lists[source].first = targets[0];
+ child_lists[targets[0]].prev = INVALID;
+ child_lists[targets[0]].next = INVALID;
+ } else {
+ radixSort(targets.begin(), targets.end(), mapToFunctor(low_map));
+ for (int i = 1; i < int(targets.size()); ++i) {
+ child_lists[targets[i]].prev = targets[i - 1];
+ child_lists[targets[i - 1]].next = targets[i];
+ }
+ child_lists[targets.back()].next = INVALID;
+ child_lists[targets.front()].prev = INVALID;
+ child_lists[source].first = targets.front();
+ }
+ }
+ }
+
+ void walkUp(const Node& node, Node root, int rorder,
+ const PredMap& pred_map, const LowMap& low_map,
+ const OrderMap& order_map, const OrderList& order_list,
+ NodeData& node_data, MergeRoots& merge_roots) {
+
+ int na, nb;
+ bool da, db;
+
+ na = nb = order_map[node];
+ da = true; db = false;
+
+ while (true) {
+
+ if (node_data[na].visited == rorder) break;
+ if (node_data[nb].visited == rorder) break;
+
+ node_data[na].visited = rorder;
+ node_data[nb].visited = rorder;
+
+ int rn = -1;
+
+ if (na >= int(order_list.size())) {
+ rn = na;
+ } else if (nb >= int(order_list.size())) {
+ rn = nb;
+ }
+
+ if (rn == -1) {
+ int nn;
+
+ nn = da ? node_data[na].prev : node_data[na].next;
+ da = node_data[nn].prev != na;
+ na = nn;
+
+ nn = db ? node_data[nb].prev : node_data[nb].next;
+ db = node_data[nn].prev != nb;
+ nb = nn;
+
+ } else {
+
+ Node rep = order_list[rn - order_list.size()];
+ Node parent = _graph.source(pred_map[rep]);
+
+ if (low_map[rep] < rorder) {
+ merge_roots[parent].push_back(rn);
+ } else {
+ merge_roots[parent].push_front(rn);
+ }
+
+ if (parent != root) {
+ na = nb = order_map[parent];
+ da = true; db = false;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ void walkDown(int rn, int rorder, NodeData& node_data,
+ OrderList& order_list, ChildLists& child_lists,
+ AncestorMap& ancestor_map, LowMap& low_map,
+ EmbedArc& embed_arc, MergeRoots& merge_roots) {
+
+ std::vector<std::pair<int, bool> > merge_stack;
+
+ for (int di = 0; di < 2; ++di) {
+ bool rd = di == 0;
+ int pn = rn;
+ int n = rd ? node_data[rn].next : node_data[rn].prev;
+
+ while (n != rn) {
+
+ Node node = order_list[n];
+
+ if (embed_arc[node]) {
+
+ // Merging components on the critical path
+ while (!merge_stack.empty()) {
+
+ // Component root
+ int cn = merge_stack.back().first;
+ bool cd = merge_stack.back().second;
+ merge_stack.pop_back();
+
+ // Parent of component
+ int dn = merge_stack.back().first;
+ bool dd = merge_stack.back().second;
+ merge_stack.pop_back();
+
+ Node parent = order_list[dn];
+
+ // Erasing from merge_roots
+ merge_roots[parent].pop_front();
+
+ Node child = order_list[cn - order_list.size()];
+
+ // Erasing from child_lists
+ if (child_lists[child].prev != INVALID) {
+ child_lists[child_lists[child].prev].next =
+ child_lists[child].next;
+ } else {
+ child_lists[parent].first = child_lists[child].next;
+ }
+
+ if (child_lists[child].next != INVALID) {
+ child_lists[child_lists[child].next].prev =
+ child_lists[child].prev;
+ }
+
+ // Merging external faces
+ {
+ int en = cn;
+ cn = cd ? node_data[cn].prev : node_data[cn].next;
+ cd = node_data[cn].next == en;
+
+ }
+
+ if (cd) node_data[cn].next = dn; else node_data[cn].prev = dn;
+ if (dd) node_data[dn].prev = cn; else node_data[dn].next = cn;
+
+ }
+
+ bool d = pn == node_data[n].prev;
+
+ if (node_data[n].prev == node_data[n].next &&
+ node_data[n].inverted) {
+ d = !d;
+ }
+
+ // Embedding arc into external face
+ if (rd) node_data[rn].next = n; else node_data[rn].prev = n;
+ if (d) node_data[n].prev = rn; else node_data[n].next = rn;
+ pn = rn;
+
+ embed_arc[order_list[n]] = false;
+ }
+
+ if (!merge_roots[node].empty()) {
+
+ bool d = pn == node_data[n].prev;
+
+ merge_stack.push_back(std::make_pair(n, d));
+
+ int rn = merge_roots[node].front();
+
+ int xn = node_data[rn].next;
+ Node xnode = order_list[xn];
+
+ int yn = node_data[rn].prev;
+ Node ynode = order_list[yn];
+
+ bool rd;
+ if (!external(xnode, rorder, child_lists,
+ ancestor_map, low_map)) {
+ rd = true;
+ } else if (!external(ynode, rorder, child_lists,
+ ancestor_map, low_map)) {
+ rd = false;
+ } else if (pertinent(xnode, embed_arc, merge_roots)) {
+ rd = true;
+ } else {
+ rd = false;
+ }
+
+ merge_stack.push_back(std::make_pair(rn, rd));
+
+ pn = rn;
+ n = rd ? xn : yn;
+
+ } else if (!external(node, rorder, child_lists,
+ ancestor_map, low_map)) {
+ int nn = (node_data[n].next != pn ?
+ node_data[n].next : node_data[n].prev);
+
+ bool nd = n == node_data[nn].prev;
+
+ if (nd) node_data[nn].prev = pn;
+ else node_data[nn].next = pn;
+
+ if (n == node_data[pn].prev) node_data[pn].prev = nn;
+ else node_data[pn].next = nn;
+
+ node_data[nn].inverted =
+ (node_data[nn].prev == node_data[nn].next && nd != rd);
+
+ n = nn;
+ }
+ else break;
+
+ }
+
+ if (!merge_stack.empty() || n == rn) {
+ break;
+ }
+ }
+ }
+
+ void initFace(const Node& node, NodeData& node_data,
+ const OrderMap& order_map, const OrderList& order_list) {
+ int n = order_map[node];
+ int rn = n + order_list.size();
+
+ node_data[n].next = node_data[n].prev = rn;
+ node_data[rn].next = node_data[rn].prev = n;
+
+ node_data[n].visited = order_list.size();
+ node_data[rn].visited = order_list.size();
+
+ }
+
+ bool external(const Node& node, int rorder,
+ ChildLists& child_lists, AncestorMap& ancestor_map,
+ LowMap& low_map) {
+ Node child = child_lists[node].first;
+
+ if (child != INVALID) {
+ if (low_map[child] < rorder) return true;
+ }
+
+ if (ancestor_map[node] < rorder) return true;
+
+ return false;
+ }
+
+ bool pertinent(const Node& node, const EmbedArc& embed_arc,
+ const MergeRoots& merge_roots) {
+ return !merge_roots[node].empty() || embed_arc[node];
+ }
+
+ };
+
+ }
+
+ /// \ingroup planar
+ ///
+ /// \brief Planarity checking of an undirected simple graph
+ ///
+ /// This function implements the Boyer-Myrvold algorithm for
+ /// planarity checking of an undirected simple graph. It is a simplified
+ /// version of the PlanarEmbedding algorithm class because neither
+ /// the embedding nor the Kuratowski subdivisons are computed.
+ template <typename GR>
+ bool checkPlanarity(const GR& graph) {
+ _planarity_bits::PlanarityChecking<GR> pc(graph);
+ return pc.run();
+ }
+
+ /// \ingroup planar
+ ///
+ /// \brief Planar embedding of an undirected simple graph
+ ///
+ /// This class implements the Boyer-Myrvold algorithm for planar
+ /// embedding of an undirected simple graph. The planar embedding is an
+ /// ordering of the outgoing edges of the nodes, which is a possible
+ /// configuration to draw the graph in the plane. If there is not
+ /// such ordering then the graph contains a K<sub>5</sub> (full graph
+ /// with 5 nodes) or a K<sub>3,3</sub> (complete bipartite graph on
+ /// 3 Red and 3 Blue nodes) subdivision.
+ ///
+ /// The current implementation calculates either an embedding or a
+ /// Kuratowski subdivision. The running time of the algorithm is O(n).
+ ///
+ /// \see PlanarDrawing, checkPlanarity()
+ template <typename Graph>
+ class PlanarEmbedding {
+ private:
+
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+ const Graph& _graph;
+ typename Graph::template ArcMap<Arc> _embedding;
+
+ typename Graph::template EdgeMap<bool> _kuratowski;
+
+ private:
+
+ typedef typename Graph::template NodeMap<Arc> PredMap;
+
+ typedef typename Graph::template EdgeMap<bool> TreeMap;
+
+ typedef typename Graph::template NodeMap<int> OrderMap;
+ typedef std::vector<Node> OrderList;
+
+ typedef typename Graph::template NodeMap<int> LowMap;
+ typedef typename Graph::template NodeMap<int> AncestorMap;
+
+ typedef _planarity_bits::NodeDataNode<Graph> NodeDataNode;
+ typedef std::vector<NodeDataNode> NodeData;
+
+ typedef _planarity_bits::ChildListNode<Graph> ChildListNode;
+ typedef typename Graph::template NodeMap<ChildListNode> ChildLists;
+
+ typedef typename Graph::template NodeMap<std::list<int> > MergeRoots;
+
+ typedef typename Graph::template NodeMap<Arc> EmbedArc;
+
+ typedef _planarity_bits::ArcListNode<Graph> ArcListNode;
+ typedef typename Graph::template ArcMap<ArcListNode> ArcLists;
+
+ typedef typename Graph::template NodeMap<bool> FlipMap;
+
+ typedef typename Graph::template NodeMap<int> TypeMap;
+
+ enum IsolatorNodeType {
+ HIGHX = 6, LOWX = 7,
+ HIGHY = 8, LOWY = 9,
+ ROOT = 10, PERTINENT = 11,
+ INTERNAL = 12
+ };
+
+ public:
+
+ /// \brief The map type for storing the embedding
+ ///
+ /// The map type for storing the embedding.
+ /// \see embeddingMap()
+ typedef typename Graph::template ArcMap<Arc> EmbeddingMap;
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ /// \pre The graph must be simple, i.e. it should not
+ /// contain parallel or loop arcs.
+ PlanarEmbedding(const Graph& graph)
+ : _graph(graph), _embedding(_graph), _kuratowski(graph, false) {}
+
+ /// \brief Run the algorithm.
+ ///
+ /// This function runs the algorithm.
+ /// \param kuratowski If this parameter is set to \c false, then the
+ /// algorithm does not compute a Kuratowski subdivision.
+ /// \return \c true if the graph is planar.
+ bool run(bool kuratowski = true) {
+ typedef _planarity_bits::PlanarityVisitor<Graph> Visitor;
+
+ PredMap pred_map(_graph, INVALID);
+ TreeMap tree_map(_graph, false);
+
+ OrderMap order_map(_graph, -1);
+ OrderList order_list;
+
+ AncestorMap ancestor_map(_graph, -1);
+ LowMap low_map(_graph, -1);
+
+ Visitor visitor(_graph, pred_map, tree_map,
+ order_map, order_list, ancestor_map, low_map);
+ DfsVisit<Graph, Visitor> visit(_graph, visitor);
+ visit.run();
+
+ ChildLists child_lists(_graph);
+ createChildLists(tree_map, order_map, low_map, child_lists);
+
+ NodeData node_data(2 * order_list.size());
+
+ EmbedArc embed_arc(_graph, INVALID);
+
+ MergeRoots merge_roots(_graph);
+
+ ArcLists arc_lists(_graph);
+
+ FlipMap flip_map(_graph, false);
+
+ for (int i = order_list.size() - 1; i >= 0; --i) {
+
+ Node node = order_list[i];
+
+ node_data[i].first = INVALID;
+
+ Node source = node;
+ for (OutArcIt e(_graph, node); e != INVALID; ++e) {
+ Node target = _graph.target(e);
+
+ if (order_map[source] < order_map[target] && tree_map[e]) {
+ initFace(target, arc_lists, node_data,
+ pred_map, order_map, order_list);
+ }
+ }
+
+ for (OutArcIt e(_graph, node); e != INVALID; ++e) {
+ Node target = _graph.target(e);
+
+ if (order_map[source] < order_map[target] && !tree_map[e]) {
+ embed_arc[target] = e;
+ walkUp(target, source, i, pred_map, low_map,
+ order_map, order_list, node_data, merge_roots);
+ }
+ }
+
+ for (typename MergeRoots::Value::iterator it =
+ merge_roots[node].begin(); it != merge_roots[node].end(); ++it) {
+ int rn = *it;
+ walkDown(rn, i, node_data, arc_lists, flip_map, order_list,
+ child_lists, ancestor_map, low_map, embed_arc, merge_roots);
+ }
+ merge_roots[node].clear();
+
+ for (OutArcIt e(_graph, node); e != INVALID; ++e) {
+ Node target = _graph.target(e);
+
+ if (order_map[source] < order_map[target] && !tree_map[e]) {
+ if (embed_arc[target] != INVALID) {
+ if (kuratowski) {
+ isolateKuratowski(e, node_data, arc_lists, flip_map,
+ order_map, order_list, pred_map, child_lists,
+ ancestor_map, low_map,
+ embed_arc, merge_roots);
+ }
+ return false;
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < int(order_list.size()); ++i) {
+
+ mergeRemainingFaces(order_list[i], node_data, order_list, order_map,
+ child_lists, arc_lists);
+ storeEmbedding(order_list[i], node_data, order_map, pred_map,
+ arc_lists, flip_map);
+ }
+
+ return true;
+ }
+
+ /// \brief Give back the successor of an arc
+ ///
+ /// This function gives back the successor of an arc. It makes
+ /// possible to query the cyclic order of the outgoing arcs from
+ /// a node.
+ Arc next(const Arc& arc) const {
+ return _embedding[arc];
+ }
+
+ /// \brief Give back the calculated embedding map
+ ///
+ /// This function gives back the calculated embedding map, which
+ /// contains the successor of each arc in the cyclic order of the
+ /// outgoing arcs of its source node.
+ const EmbeddingMap& embeddingMap() const {
+ return _embedding;
+ }
+
+ /// \brief Give back \c true if the given edge is in the Kuratowski
+ /// subdivision
+ ///
+ /// This function gives back \c true if the given edge is in the found
+ /// Kuratowski subdivision.
+ /// \pre The \c run() function must be called with \c true parameter
+ /// before using this function.
+ bool kuratowski(const Edge& edge) const {
+ return _kuratowski[edge];
+ }
+
+ private:
+
+ void createChildLists(const TreeMap& tree_map, const OrderMap& order_map,
+ const LowMap& low_map, ChildLists& child_lists) {
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ Node source = n;
+
+ std::vector<Node> targets;
+ for (OutArcIt e(_graph, n); e != INVALID; ++e) {
+ Node target = _graph.target(e);
+
+ if (order_map[source] < order_map[target] && tree_map[e]) {
+ targets.push_back(target);
+ }
+ }
+
+ if (targets.size() == 0) {
+ child_lists[source].first = INVALID;
+ } else if (targets.size() == 1) {
+ child_lists[source].first = targets[0];
+ child_lists[targets[0]].prev = INVALID;
+ child_lists[targets[0]].next = INVALID;
+ } else {
+ radixSort(targets.begin(), targets.end(), mapToFunctor(low_map));
+ for (int i = 1; i < int(targets.size()); ++i) {
+ child_lists[targets[i]].prev = targets[i - 1];
+ child_lists[targets[i - 1]].next = targets[i];
+ }
+ child_lists[targets.back()].next = INVALID;
+ child_lists[targets.front()].prev = INVALID;
+ child_lists[source].first = targets.front();
+ }
+ }
+ }
+
+ void walkUp(const Node& node, Node root, int rorder,
+ const PredMap& pred_map, const LowMap& low_map,
+ const OrderMap& order_map, const OrderList& order_list,
+ NodeData& node_data, MergeRoots& merge_roots) {
+
+ int na, nb;
+ bool da, db;
+
+ na = nb = order_map[node];
+ da = true; db = false;
+
+ while (true) {
+
+ if (node_data[na].visited == rorder) break;
+ if (node_data[nb].visited == rorder) break;
+
+ node_data[na].visited = rorder;
+ node_data[nb].visited = rorder;
+
+ int rn = -1;
+
+ if (na >= int(order_list.size())) {
+ rn = na;
+ } else if (nb >= int(order_list.size())) {
+ rn = nb;
+ }
+
+ if (rn == -1) {
+ int nn;
+
+ nn = da ? node_data[na].prev : node_data[na].next;
+ da = node_data[nn].prev != na;
+ na = nn;
+
+ nn = db ? node_data[nb].prev : node_data[nb].next;
+ db = node_data[nn].prev != nb;
+ nb = nn;
+
+ } else {
+
+ Node rep = order_list[rn - order_list.size()];
+ Node parent = _graph.source(pred_map[rep]);
+
+ if (low_map[rep] < rorder) {
+ merge_roots[parent].push_back(rn);
+ } else {
+ merge_roots[parent].push_front(rn);
+ }
+
+ if (parent != root) {
+ na = nb = order_map[parent];
+ da = true; db = false;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ void walkDown(int rn, int rorder, NodeData& node_data,
+ ArcLists& arc_lists, FlipMap& flip_map,
+ OrderList& order_list, ChildLists& child_lists,
+ AncestorMap& ancestor_map, LowMap& low_map,
+ EmbedArc& embed_arc, MergeRoots& merge_roots) {
+
+ std::vector<std::pair<int, bool> > merge_stack;
+
+ for (int di = 0; di < 2; ++di) {
+ bool rd = di == 0;
+ int pn = rn;
+ int n = rd ? node_data[rn].next : node_data[rn].prev;
+
+ while (n != rn) {
+
+ Node node = order_list[n];
+
+ if (embed_arc[node] != INVALID) {
+
+ // Merging components on the critical path
+ while (!merge_stack.empty()) {
+
+ // Component root
+ int cn = merge_stack.back().first;
+ bool cd = merge_stack.back().second;
+ merge_stack.pop_back();
+
+ // Parent of component
+ int dn = merge_stack.back().first;
+ bool dd = merge_stack.back().second;
+ merge_stack.pop_back();
+
+ Node parent = order_list[dn];
+
+ // Erasing from merge_roots
+ merge_roots[parent].pop_front();
+
+ Node child = order_list[cn - order_list.size()];
+
+ // Erasing from child_lists
+ if (child_lists[child].prev != INVALID) {
+ child_lists[child_lists[child].prev].next =
+ child_lists[child].next;
+ } else {
+ child_lists[parent].first = child_lists[child].next;
+ }
+
+ if (child_lists[child].next != INVALID) {
+ child_lists[child_lists[child].next].prev =
+ child_lists[child].prev;
+ }
+
+ // Merging arcs + flipping
+ Arc de = node_data[dn].first;
+ Arc ce = node_data[cn].first;
+
+ flip_map[order_list[cn - order_list.size()]] = cd != dd;
+ if (cd != dd) {
+ std::swap(arc_lists[ce].prev, arc_lists[ce].next);
+ ce = arc_lists[ce].prev;
+ std::swap(arc_lists[ce].prev, arc_lists[ce].next);
+ }
+
+ {
+ Arc dne = arc_lists[de].next;
+ Arc cne = arc_lists[ce].next;
+
+ arc_lists[de].next = cne;
+ arc_lists[ce].next = dne;
+
+ arc_lists[dne].prev = ce;
+ arc_lists[cne].prev = de;
+ }
+
+ if (dd) {
+ node_data[dn].first = ce;
+ }
+
+ // Merging external faces
+ {
+ int en = cn;
+ cn = cd ? node_data[cn].prev : node_data[cn].next;
+ cd = node_data[cn].next == en;
+
+ if (node_data[cn].prev == node_data[cn].next &&
+ node_data[cn].inverted) {
+ cd = !cd;
+ }
+ }
+
+ if (cd) node_data[cn].next = dn; else node_data[cn].prev = dn;
+ if (dd) node_data[dn].prev = cn; else node_data[dn].next = cn;
+
+ }
+
+ bool d = pn == node_data[n].prev;
+
+ if (node_data[n].prev == node_data[n].next &&
+ node_data[n].inverted) {
+ d = !d;
+ }
+
+ // Add new arc
+ {
+ Arc arc = embed_arc[node];
+ Arc re = node_data[rn].first;
+
+ arc_lists[arc_lists[re].next].prev = arc;
+ arc_lists[arc].next = arc_lists[re].next;
+ arc_lists[arc].prev = re;
+ arc_lists[re].next = arc;
+
+ if (!rd) {
+ node_data[rn].first = arc;
+ }
+
+ Arc rev = _graph.oppositeArc(arc);
+ Arc e = node_data[n].first;
+
+ arc_lists[arc_lists[e].next].prev = rev;
+ arc_lists[rev].next = arc_lists[e].next;
+ arc_lists[rev].prev = e;
+ arc_lists[e].next = rev;
+
+ if (d) {
+ node_data[n].first = rev;
+ }
+
+ }
+
+ // Embedding arc into external face
+ if (rd) node_data[rn].next = n; else node_data[rn].prev = n;
+ if (d) node_data[n].prev = rn; else node_data[n].next = rn;
+ pn = rn;
+
+ embed_arc[order_list[n]] = INVALID;
+ }
+
+ if (!merge_roots[node].empty()) {
+
+ bool d = pn == node_data[n].prev;
+ if (node_data[n].prev == node_data[n].next &&
+ node_data[n].inverted) {
+ d = !d;
+ }
+
+ merge_stack.push_back(std::make_pair(n, d));
+
+ int rn = merge_roots[node].front();
+
+ int xn = node_data[rn].next;
+ Node xnode = order_list[xn];
+
+ int yn = node_data[rn].prev;
+ Node ynode = order_list[yn];
+
+ bool rd;
+ if (!external(xnode, rorder, child_lists, ancestor_map, low_map)) {
+ rd = true;
+ } else if (!external(ynode, rorder, child_lists,
+ ancestor_map, low_map)) {
+ rd = false;
+ } else if (pertinent(xnode, embed_arc, merge_roots)) {
+ rd = true;
+ } else {
+ rd = false;
+ }
+
+ merge_stack.push_back(std::make_pair(rn, rd));
+
+ pn = rn;
+ n = rd ? xn : yn;
+
+ } else if (!external(node, rorder, child_lists,
+ ancestor_map, low_map)) {
+ int nn = (node_data[n].next != pn ?
+ node_data[n].next : node_data[n].prev);
+
+ bool nd = n == node_data[nn].prev;
+
+ if (nd) node_data[nn].prev = pn;
+ else node_data[nn].next = pn;
+
+ if (n == node_data[pn].prev) node_data[pn].prev = nn;
+ else node_data[pn].next = nn;
+
+ node_data[nn].inverted =
+ (node_data[nn].prev == node_data[nn].next && nd != rd);
+
+ n = nn;
+ }
+ else break;
+
+ }
+
+ if (!merge_stack.empty() || n == rn) {
+ break;
+ }
+ }
+ }
+
+ void initFace(const Node& node, ArcLists& arc_lists,
+ NodeData& node_data, const PredMap& pred_map,
+ const OrderMap& order_map, const OrderList& order_list) {
+ int n = order_map[node];
+ int rn = n + order_list.size();
+
+ node_data[n].next = node_data[n].prev = rn;
+ node_data[rn].next = node_data[rn].prev = n;
+
+ node_data[n].visited = order_list.size();
+ node_data[rn].visited = order_list.size();
+
+ node_data[n].inverted = false;
+ node_data[rn].inverted = false;
+
+ Arc arc = pred_map[node];
+ Arc rev = _graph.oppositeArc(arc);
+
+ node_data[rn].first = arc;
+ node_data[n].first = rev;
+
+ arc_lists[arc].prev = arc;
+ arc_lists[arc].next = arc;
+
+ arc_lists[rev].prev = rev;
+ arc_lists[rev].next = rev;
+
+ }
+
+ void mergeRemainingFaces(const Node& node, NodeData& node_data,
+ OrderList& order_list, OrderMap& order_map,
+ ChildLists& child_lists, ArcLists& arc_lists) {
+ while (child_lists[node].first != INVALID) {
+ int dd = order_map[node];
+ Node child = child_lists[node].first;
+ int cd = order_map[child] + order_list.size();
+ child_lists[node].first = child_lists[child].next;
+
+ Arc de = node_data[dd].first;
+ Arc ce = node_data[cd].first;
+
+ if (de != INVALID) {
+ Arc dne = arc_lists[de].next;
+ Arc cne = arc_lists[ce].next;
+
+ arc_lists[de].next = cne;
+ arc_lists[ce].next = dne;
+
+ arc_lists[dne].prev = ce;
+ arc_lists[cne].prev = de;
+ }
+
+ node_data[dd].first = ce;
+
+ }
+ }
+
+ void storeEmbedding(const Node& node, NodeData& node_data,
+ OrderMap& order_map, PredMap& pred_map,
+ ArcLists& arc_lists, FlipMap& flip_map) {
+
+ if (node_data[order_map[node]].first == INVALID) return;
+
+ if (pred_map[node] != INVALID) {
+ Node source = _graph.source(pred_map[node]);
+ flip_map[node] = flip_map[node] != flip_map[source];
+ }
+
+ Arc first = node_data[order_map[node]].first;
+ Arc prev = first;
+
+ Arc arc = flip_map[node] ?
+ arc_lists[prev].prev : arc_lists[prev].next;
+
+ _embedding[prev] = arc;
+
+ while (arc != first) {
+ Arc next = arc_lists[arc].prev == prev ?
+ arc_lists[arc].next : arc_lists[arc].prev;
+ prev = arc; arc = next;
+ _embedding[prev] = arc;
+ }
+ }
+
+
+ bool external(const Node& node, int rorder,
+ ChildLists& child_lists, AncestorMap& ancestor_map,
+ LowMap& low_map) {
+ Node child = child_lists[node].first;
+
+ if (child != INVALID) {
+ if (low_map[child] < rorder) return true;
+ }
+
+ if (ancestor_map[node] < rorder) return true;
+
+ return false;
+ }
+
+ bool pertinent(const Node& node, const EmbedArc& embed_arc,
+ const MergeRoots& merge_roots) {
+ return !merge_roots[node].empty() || embed_arc[node] != INVALID;
+ }
+
+ int lowPoint(const Node& node, OrderMap& order_map, ChildLists& child_lists,
+ AncestorMap& ancestor_map, LowMap& low_map) {
+ int low_point;
+
+ Node child = child_lists[node].first;
+
+ if (child != INVALID) {
+ low_point = low_map[child];
+ } else {
+ low_point = order_map[node];
+ }
+
+ if (low_point > ancestor_map[node]) {
+ low_point = ancestor_map[node];
+ }
+
+ return low_point;
+ }
+
+ int findComponentRoot(Node root, Node node, ChildLists& child_lists,
+ OrderMap& order_map, OrderList& order_list) {
+
+ int order = order_map[root];
+ int norder = order_map[node];
+
+ Node child = child_lists[root].first;
+ while (child != INVALID) {
+ int corder = order_map[child];
+ if (corder > order && corder < norder) {
+ order = corder;
+ }
+ child = child_lists[child].next;
+ }
+ return order + order_list.size();
+ }
+
+ Node findPertinent(Node node, OrderMap& order_map, NodeData& node_data,
+ EmbedArc& embed_arc, MergeRoots& merge_roots) {
+ Node wnode =_graph.target(node_data[order_map[node]].first);
+ while (!pertinent(wnode, embed_arc, merge_roots)) {
+ wnode = _graph.target(node_data[order_map[wnode]].first);
+ }
+ return wnode;
+ }
+
+
+ Node findExternal(Node node, int rorder, OrderMap& order_map,
+ ChildLists& child_lists, AncestorMap& ancestor_map,
+ LowMap& low_map, NodeData& node_data) {
+ Node wnode =_graph.target(node_data[order_map[node]].first);
+ while (!external(wnode, rorder, child_lists, ancestor_map, low_map)) {
+ wnode = _graph.target(node_data[order_map[wnode]].first);
+ }
+ return wnode;
+ }
+
+ void markCommonPath(Node node, int rorder, Node& wnode, Node& znode,
+ OrderList& order_list, OrderMap& order_map,
+ NodeData& node_data, ArcLists& arc_lists,
+ EmbedArc& embed_arc, MergeRoots& merge_roots,
+ ChildLists& child_lists, AncestorMap& ancestor_map,
+ LowMap& low_map) {
+
+ Node cnode = node;
+ Node pred = INVALID;
+
+ while (true) {
+
+ bool pert = pertinent(cnode, embed_arc, merge_roots);
+ bool ext = external(cnode, rorder, child_lists, ancestor_map, low_map);
+
+ if (pert && ext) {
+ if (!merge_roots[cnode].empty()) {
+ int cn = merge_roots[cnode].back();
+
+ if (low_map[order_list[cn - order_list.size()]] < rorder) {
+ Arc arc = node_data[cn].first;
+ _kuratowski.set(arc, true);
+
+ pred = cnode;
+ cnode = _graph.target(arc);
+
+ continue;
+ }
+ }
+ wnode = znode = cnode;
+ return;
+
+ } else if (pert) {
+ wnode = cnode;
+
+ while (!external(cnode, rorder, child_lists, ancestor_map, low_map)) {
+ Arc arc = node_data[order_map[cnode]].first;
+
+ if (_graph.target(arc) == pred) {
+ arc = arc_lists[arc].next;
+ }
+ _kuratowski.set(arc, true);
+
+ Node next = _graph.target(arc);
+ pred = cnode; cnode = next;
+ }
+
+ znode = cnode;
+ return;
+
+ } else if (ext) {
+ znode = cnode;
+
+ while (!pertinent(cnode, embed_arc, merge_roots)) {
+ Arc arc = node_data[order_map[cnode]].first;
+
+ if (_graph.target(arc) == pred) {
+ arc = arc_lists[arc].next;
+ }
+ _kuratowski.set(arc, true);
+
+ Node next = _graph.target(arc);
+ pred = cnode; cnode = next;
+ }
+
+ wnode = cnode;
+ return;
+
+ } else {
+ Arc arc = node_data[order_map[cnode]].first;
+
+ if (_graph.target(arc) == pred) {
+ arc = arc_lists[arc].next;
+ }
+ _kuratowski.set(arc, true);
+
+ Node next = _graph.target(arc);
+ pred = cnode; cnode = next;
+ }
+
+ }
+
+ }
+
+ void orientComponent(Node root, int rn, OrderMap& order_map,
+ PredMap& pred_map, NodeData& node_data,
+ ArcLists& arc_lists, FlipMap& flip_map,
+ TypeMap& type_map) {
+ node_data[order_map[root]].first = node_data[rn].first;
+ type_map[root] = 1;
+
+ std::vector<Node> st, qu;
+
+ st.push_back(root);
+ while (!st.empty()) {
+ Node node = st.back();
+ st.pop_back();
+ qu.push_back(node);
+
+ Arc arc = node_data[order_map[node]].first;
+
+ if (type_map[_graph.target(arc)] == 0) {
+ st.push_back(_graph.target(arc));
+ type_map[_graph.target(arc)] = 1;
+ }
+
+ Arc last = arc, pred = arc;
+ arc = arc_lists[arc].next;
+ while (arc != last) {
+
+ if (type_map[_graph.target(arc)] == 0) {
+ st.push_back(_graph.target(arc));
+ type_map[_graph.target(arc)] = 1;
+ }
+
+ Arc next = arc_lists[arc].next != pred ?
+ arc_lists[arc].next : arc_lists[arc].prev;
+ pred = arc; arc = next;
+ }
+
+ }
+
+ type_map[root] = 2;
+ flip_map[root] = false;
+
+ for (int i = 1; i < int(qu.size()); ++i) {
+
+ Node node = qu[i];
+
+ while (type_map[node] != 2) {
+ st.push_back(node);
+ type_map[node] = 2;
+ node = _graph.source(pred_map[node]);
+ }
+
+ bool flip = flip_map[node];
+
+ while (!st.empty()) {
+ node = st.back();
+ st.pop_back();
+
+ flip_map[node] = flip != flip_map[node];
+ flip = flip_map[node];
+
+ if (flip) {
+ Arc arc = node_data[order_map[node]].first;
+ std::swap(arc_lists[arc].prev, arc_lists[arc].next);
+ arc = arc_lists[arc].prev;
+ std::swap(arc_lists[arc].prev, arc_lists[arc].next);
+ node_data[order_map[node]].first = arc;
+ }
+ }
+ }
+
+ for (int i = 0; i < int(qu.size()); ++i) {
+
+ Arc arc = node_data[order_map[qu[i]]].first;
+ Arc last = arc, pred = arc;
+
+ arc = arc_lists[arc].next;
+ while (arc != last) {
+
+ if (arc_lists[arc].next == pred) {
+ std::swap(arc_lists[arc].next, arc_lists[arc].prev);
+ }
+ pred = arc; arc = arc_lists[arc].next;
+ }
+
+ }
+ }
+
+ void setFaceFlags(Node root, Node wnode, Node ynode, Node xnode,
+ OrderMap& order_map, NodeData& node_data,
+ TypeMap& type_map) {
+ Node node = _graph.target(node_data[order_map[root]].first);
+
+ while (node != ynode) {
+ type_map[node] = HIGHY;
+ node = _graph.target(node_data[order_map[node]].first);
+ }
+
+ while (node != wnode) {
+ type_map[node] = LOWY;
+ node = _graph.target(node_data[order_map[node]].first);
+ }
+
+ node = _graph.target(node_data[order_map[wnode]].first);
+
+ while (node != xnode) {
+ type_map[node] = LOWX;
+ node = _graph.target(node_data[order_map[node]].first);
+ }
+ type_map[node] = LOWX;
+
+ node = _graph.target(node_data[order_map[xnode]].first);
+ while (node != root) {
+ type_map[node] = HIGHX;
+ node = _graph.target(node_data[order_map[node]].first);
+ }
+
+ type_map[wnode] = PERTINENT;
+ type_map[root] = ROOT;
+ }
+
+ void findInternalPath(std::vector<Arc>& ipath,
+ Node wnode, Node root, TypeMap& type_map,
+ OrderMap& order_map, NodeData& node_data,
+ ArcLists& arc_lists) {
+ std::vector<Arc> st;
+
+ Node node = wnode;
+
+ while (node != root) {
+ Arc arc = arc_lists[node_data[order_map[node]].first].next;
+ st.push_back(arc);
+ node = _graph.target(arc);
+ }
+
+ while (true) {
+ Arc arc = st.back();
+ if (type_map[_graph.target(arc)] == LOWX ||
+ type_map[_graph.target(arc)] == HIGHX) {
+ break;
+ }
+ if (type_map[_graph.target(arc)] == 2) {
+ type_map[_graph.target(arc)] = 3;
+
+ arc = arc_lists[_graph.oppositeArc(arc)].next;
+ st.push_back(arc);
+ } else {
+ st.pop_back();
+ arc = arc_lists[arc].next;
+
+ while (_graph.oppositeArc(arc) == st.back()) {
+ arc = st.back();
+ st.pop_back();
+ arc = arc_lists[arc].next;
+ }
+ st.push_back(arc);
+ }
+ }
+
+ for (int i = 0; i < int(st.size()); ++i) {
+ if (type_map[_graph.target(st[i])] != LOWY &&
+ type_map[_graph.target(st[i])] != HIGHY) {
+ for (; i < int(st.size()); ++i) {
+ ipath.push_back(st[i]);
+ }
+ }
+ }
+ }
+
+ void setInternalFlags(std::vector<Arc>& ipath, TypeMap& type_map) {
+ for (int i = 1; i < int(ipath.size()); ++i) {
+ type_map[_graph.source(ipath[i])] = INTERNAL;
+ }
+ }
+
+ void findPilePath(std::vector<Arc>& ppath,
+ Node root, TypeMap& type_map, OrderMap& order_map,
+ NodeData& node_data, ArcLists& arc_lists) {
+ std::vector<Arc> st;
+
+ st.push_back(_graph.oppositeArc(node_data[order_map[root]].first));
+ st.push_back(node_data[order_map[root]].first);
+
+ while (st.size() > 1) {
+ Arc arc = st.back();
+ if (type_map[_graph.target(arc)] == INTERNAL) {
+ break;
+ }
+ if (type_map[_graph.target(arc)] == 3) {
+ type_map[_graph.target(arc)] = 4;
+
+ arc = arc_lists[_graph.oppositeArc(arc)].next;
+ st.push_back(arc);
+ } else {
+ st.pop_back();
+ arc = arc_lists[arc].next;
+
+ while (!st.empty() && _graph.oppositeArc(arc) == st.back()) {
+ arc = st.back();
+ st.pop_back();
+ arc = arc_lists[arc].next;
+ }
+ st.push_back(arc);
+ }
+ }
+
+ for (int i = 1; i < int(st.size()); ++i) {
+ ppath.push_back(st[i]);
+ }
+ }
+
+
+ int markExternalPath(Node node, OrderMap& order_map,
+ ChildLists& child_lists, PredMap& pred_map,
+ AncestorMap& ancestor_map, LowMap& low_map) {
+ int lp = lowPoint(node, order_map, child_lists,
+ ancestor_map, low_map);
+
+ if (ancestor_map[node] != lp) {
+ node = child_lists[node].first;
+ _kuratowski[pred_map[node]] = true;
+
+ while (ancestor_map[node] != lp) {
+ for (OutArcIt e(_graph, node); e != INVALID; ++e) {
+ Node tnode = _graph.target(e);
+ if (order_map[tnode] > order_map[node] && low_map[tnode] == lp) {
+ node = tnode;
+ _kuratowski[e] = true;
+ break;
+ }
+ }
+ }
+ }
+
+ for (OutArcIt e(_graph, node); e != INVALID; ++e) {
+ if (order_map[_graph.target(e)] == lp) {
+ _kuratowski[e] = true;
+ break;
+ }
+ }
+
+ return lp;
+ }
+
+ void markPertinentPath(Node node, OrderMap& order_map,
+ NodeData& node_data, ArcLists& arc_lists,
+ EmbedArc& embed_arc, MergeRoots& merge_roots) {
+ while (embed_arc[node] == INVALID) {
+ int n = merge_roots[node].front();
+ Arc arc = node_data[n].first;
+
+ _kuratowski.set(arc, true);
+
+ Node pred = node;
+ node = _graph.target(arc);
+ while (!pertinent(node, embed_arc, merge_roots)) {
+ arc = node_data[order_map[node]].first;
+ if (_graph.target(arc) == pred) {
+ arc = arc_lists[arc].next;
+ }
+ _kuratowski.set(arc, true);
+ pred = node;
+ node = _graph.target(arc);
+ }
+ }
+ _kuratowski.set(embed_arc[node], true);
+ }
+
+ void markPredPath(Node node, Node snode, PredMap& pred_map) {
+ while (node != snode) {
+ _kuratowski.set(pred_map[node], true);
+ node = _graph.source(pred_map[node]);
+ }
+ }
+
+ void markFacePath(Node ynode, Node xnode,
+ OrderMap& order_map, NodeData& node_data) {
+ Arc arc = node_data[order_map[ynode]].first;
+ Node node = _graph.target(arc);
+ _kuratowski.set(arc, true);
+
+ while (node != xnode) {
+ arc = node_data[order_map[node]].first;
+ _kuratowski.set(arc, true);
+ node = _graph.target(arc);
+ }
+ }
+
+ void markInternalPath(std::vector<Arc>& path) {
+ for (int i = 0; i < int(path.size()); ++i) {
+ _kuratowski.set(path[i], true);
+ }
+ }
+
+ void markPilePath(std::vector<Arc>& path) {
+ for (int i = 0; i < int(path.size()); ++i) {
+ _kuratowski.set(path[i], true);
+ }
+ }
+
+ void isolateKuratowski(Arc arc, NodeData& node_data,
+ ArcLists& arc_lists, FlipMap& flip_map,
+ OrderMap& order_map, OrderList& order_list,
+ PredMap& pred_map, ChildLists& child_lists,
+ AncestorMap& ancestor_map, LowMap& low_map,
+ EmbedArc& embed_arc, MergeRoots& merge_roots) {
+
+ Node root = _graph.source(arc);
+ Node enode = _graph.target(arc);
+
+ int rorder = order_map[root];
+
+ TypeMap type_map(_graph, 0);
+
+ int rn = findComponentRoot(root, enode, child_lists,
+ order_map, order_list);
+
+ Node xnode = order_list[node_data[rn].next];
+ Node ynode = order_list[node_data[rn].prev];
+
+ // Minor-A
+ {
+ while (!merge_roots[xnode].empty() || !merge_roots[ynode].empty()) {
+
+ if (!merge_roots[xnode].empty()) {
+ root = xnode;
+ rn = merge_roots[xnode].front();
+ } else {
+ root = ynode;
+ rn = merge_roots[ynode].front();
+ }
+
+ xnode = order_list[node_data[rn].next];
+ ynode = order_list[node_data[rn].prev];
+ }
+
+ if (root != _graph.source(arc)) {
+ orientComponent(root, rn, order_map, pred_map,
+ node_data, arc_lists, flip_map, type_map);
+ markFacePath(root, root, order_map, node_data);
+ int xlp = markExternalPath(xnode, order_map, child_lists,
+ pred_map, ancestor_map, low_map);
+ int ylp = markExternalPath(ynode, order_map, child_lists,
+ pred_map, ancestor_map, low_map);
+ markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
+ Node lwnode = findPertinent(ynode, order_map, node_data,
+ embed_arc, merge_roots);
+
+ markPertinentPath(lwnode, order_map, node_data, arc_lists,
+ embed_arc, merge_roots);
+
+ return;
+ }
+ }
+
+ orientComponent(root, rn, order_map, pred_map,
+ node_data, arc_lists, flip_map, type_map);
+
+ Node wnode = findPertinent(ynode, order_map, node_data,
+ embed_arc, merge_roots);
+ setFaceFlags(root, wnode, ynode, xnode, order_map, node_data, type_map);
+
+
+ //Minor-B
+ if (!merge_roots[wnode].empty()) {
+ int cn = merge_roots[wnode].back();
+ Node rep = order_list[cn - order_list.size()];
+ if (low_map[rep] < rorder) {
+ markFacePath(root, root, order_map, node_data);
+ int xlp = markExternalPath(xnode, order_map, child_lists,
+ pred_map, ancestor_map, low_map);
+ int ylp = markExternalPath(ynode, order_map, child_lists,
+ pred_map, ancestor_map, low_map);
+
+ Node lwnode, lznode;
+ markCommonPath(wnode, rorder, lwnode, lznode, order_list,
+ order_map, node_data, arc_lists, embed_arc,
+ merge_roots, child_lists, ancestor_map, low_map);
+
+ markPertinentPath(lwnode, order_map, node_data, arc_lists,
+ embed_arc, merge_roots);
+ int zlp = markExternalPath(lznode, order_map, child_lists,
+ pred_map, ancestor_map, low_map);
+
+ int minlp = xlp < ylp ? xlp : ylp;
+ if (zlp < minlp) minlp = zlp;
+
+ int maxlp = xlp > ylp ? xlp : ylp;
+ if (zlp > maxlp) maxlp = zlp;
+
+ markPredPath(order_list[maxlp], order_list[minlp], pred_map);
+
+ return;
+ }
+ }
+
+ Node pxnode, pynode;
+ std::vector<Arc> ipath;
+ findInternalPath(ipath, wnode, root, type_map, order_map,
+ node_data, arc_lists);
+ setInternalFlags(ipath, type_map);
+ pynode = _graph.source(ipath.front());
+ pxnode = _graph.target(ipath.back());
+
+ wnode = findPertinent(pynode, order_map, node_data,
+ embed_arc, merge_roots);
+
+ // Minor-C
+ {
+ if (type_map[_graph.source(ipath.front())] == HIGHY) {
+ if (type_map[_graph.target(ipath.back())] == HIGHX) {
+ markFacePath(xnode, pxnode, order_map, node_data);
+ }
+ markFacePath(root, xnode, order_map, node_data);
+ markPertinentPath(wnode, order_map, node_data, arc_lists,
+ embed_arc, merge_roots);
+ markInternalPath(ipath);
+ int xlp = markExternalPath(xnode, order_map, child_lists,
+ pred_map, ancestor_map, low_map);
+ int ylp = markExternalPath(ynode, order_map, child_lists,
+ pred_map, ancestor_map, low_map);
+ markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
+ return;
+ }
+
+ if (type_map[_graph.target(ipath.back())] == HIGHX) {
+ markFacePath(ynode, root, order_map, node_data);
+ markPertinentPath(wnode, order_map, node_data, arc_lists,
+ embed_arc, merge_roots);
+ markInternalPath(ipath);
+ int xlp = markExternalPath(xnode, order_map, child_lists,
+ pred_map, ancestor_map, low_map);
+ int ylp = markExternalPath(ynode, order_map, child_lists,
+ pred_map, ancestor_map, low_map);
+ markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
+ return;
+ }
+ }
+
+ std::vector<Arc> ppath;
+ findPilePath(ppath, root, type_map, order_map, node_data, arc_lists);
+
+ // Minor-D
+ if (!ppath.empty()) {
+ markFacePath(ynode, xnode, order_map, node_data);
+ markPertinentPath(wnode, order_map, node_data, arc_lists,
+ embed_arc, merge_roots);
+ markPilePath(ppath);
+ markInternalPath(ipath);
+ int xlp = markExternalPath(xnode, order_map, child_lists,
+ pred_map, ancestor_map, low_map);
+ int ylp = markExternalPath(ynode, order_map, child_lists,
+ pred_map, ancestor_map, low_map);
+ markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
+ return;
+ }
+
+ // Minor-E*
+ {
+
+ if (!external(wnode, rorder, child_lists, ancestor_map, low_map)) {
+ Node znode = findExternal(pynode, rorder, order_map,
+ child_lists, ancestor_map,
+ low_map, node_data);
+
+ if (type_map[znode] == LOWY) {
+ markFacePath(root, xnode, order_map, node_data);
+ markPertinentPath(wnode, order_map, node_data, arc_lists,
+ embed_arc, merge_roots);
+ markInternalPath(ipath);
+ int xlp = markExternalPath(xnode, order_map, child_lists,
+ pred_map, ancestor_map, low_map);
+ int zlp = markExternalPath(znode, order_map, child_lists,
+ pred_map, ancestor_map, low_map);
+ markPredPath(root, order_list[xlp < zlp ? xlp : zlp], pred_map);
+ } else {
+ markFacePath(ynode, root, order_map, node_data);
+ markPertinentPath(wnode, order_map, node_data, arc_lists,
+ embed_arc, merge_roots);
+ markInternalPath(ipath);
+ int ylp = markExternalPath(ynode, order_map, child_lists,
+ pred_map, ancestor_map, low_map);
+ int zlp = markExternalPath(znode, order_map, child_lists,
+ pred_map, ancestor_map, low_map);
+ markPredPath(root, order_list[ylp < zlp ? ylp : zlp], pred_map);
+ }
+ return;
+ }
+
+ int xlp = markExternalPath(xnode, order_map, child_lists,
+ pred_map, ancestor_map, low_map);
+ int ylp = markExternalPath(ynode, order_map, child_lists,
+ pred_map, ancestor_map, low_map);
+ int wlp = markExternalPath(wnode, order_map, child_lists,
+ pred_map, ancestor_map, low_map);
+
+ if (wlp > xlp && wlp > ylp) {
+ markFacePath(root, root, order_map, node_data);
+ markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
+ return;
+ }
+
+ markInternalPath(ipath);
+ markPertinentPath(wnode, order_map, node_data, arc_lists,
+ embed_arc, merge_roots);
+
+ if (xlp > ylp && xlp > wlp) {
+ markFacePath(root, pynode, order_map, node_data);
+ markFacePath(wnode, xnode, order_map, node_data);
+ markPredPath(root, order_list[ylp < wlp ? ylp : wlp], pred_map);
+ return;
+ }
+
+ if (ylp > xlp && ylp > wlp) {
+ markFacePath(pxnode, root, order_map, node_data);
+ markFacePath(ynode, wnode, order_map, node_data);
+ markPredPath(root, order_list[xlp < wlp ? xlp : wlp], pred_map);
+ return;
+ }
+
+ if (pynode != ynode) {
+ markFacePath(pxnode, wnode, order_map, node_data);
+
+ int minlp = xlp < ylp ? xlp : ylp;
+ if (wlp < minlp) minlp = wlp;
+
+ int maxlp = xlp > ylp ? xlp : ylp;
+ if (wlp > maxlp) maxlp = wlp;
+
+ markPredPath(order_list[maxlp], order_list[minlp], pred_map);
+ return;
+ }
+
+ if (pxnode != xnode) {
+ markFacePath(wnode, pynode, order_map, node_data);
+
+ int minlp = xlp < ylp ? xlp : ylp;
+ if (wlp < minlp) minlp = wlp;
+
+ int maxlp = xlp > ylp ? xlp : ylp;
+ if (wlp > maxlp) maxlp = wlp;
+
+ markPredPath(order_list[maxlp], order_list[minlp], pred_map);
+ return;
+ }
+
+ markFacePath(root, root, order_map, node_data);
+ int minlp = xlp < ylp ? xlp : ylp;
+ if (wlp < minlp) minlp = wlp;
+ markPredPath(root, order_list[minlp], pred_map);
+ return;
+ }
+
+ }
+
+ };
+
+ namespace _planarity_bits {
+
+ template <typename Graph, typename EmbeddingMap>
+ void makeConnected(Graph& graph, EmbeddingMap& embedding) {
+ DfsVisitor<Graph> null_visitor;
+ DfsVisit<Graph, DfsVisitor<Graph> > dfs(graph, null_visitor);
+ dfs.init();
+
+ typename Graph::Node u = INVALID;
+ for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
+ if (!dfs.reached(n)) {
+ dfs.addSource(n);
+ dfs.start();
+ if (u == INVALID) {
+ u = n;
+ } else {
+ typename Graph::Node v = n;
+
+ typename Graph::Arc ue = typename Graph::OutArcIt(graph, u);
+ typename Graph::Arc ve = typename Graph::OutArcIt(graph, v);
+
+ typename Graph::Arc e = graph.direct(graph.addEdge(u, v), true);
+
+ if (ue != INVALID) {
+ embedding[e] = embedding[ue];
+ embedding[ue] = e;
+ } else {
+ embedding[e] = e;
+ }
+
+ if (ve != INVALID) {
+ embedding[graph.oppositeArc(e)] = embedding[ve];
+ embedding[ve] = graph.oppositeArc(e);
+ } else {
+ embedding[graph.oppositeArc(e)] = graph.oppositeArc(e);
+ }
+ }
+ }
+ }
+ }
+
+ template <typename Graph, typename EmbeddingMap>
+ void makeBiNodeConnected(Graph& graph, EmbeddingMap& embedding) {
+ typename Graph::template ArcMap<bool> processed(graph);
+
+ std::vector<typename Graph::Arc> arcs;
+ for (typename Graph::ArcIt e(graph); e != INVALID; ++e) {
+ arcs.push_back(e);
+ }
+
+ IterableBoolMap<Graph, typename Graph::Node> visited(graph, false);
+
+ for (int i = 0; i < int(arcs.size()); ++i) {
+ typename Graph::Arc pp = arcs[i];
+ if (processed[pp]) continue;
+
+ typename Graph::Arc e = embedding[graph.oppositeArc(pp)];
+ processed[e] = true;
+ visited.set(graph.source(e), true);
+
+ typename Graph::Arc p = e, l = e;
+ e = embedding[graph.oppositeArc(e)];
+
+ while (e != l) {
+ processed[e] = true;
+
+ if (visited[graph.source(e)]) {
+
+ typename Graph::Arc n =
+ graph.direct(graph.addEdge(graph.source(p),
+ graph.target(e)), true);
+ embedding[n] = p;
+ embedding[graph.oppositeArc(pp)] = n;
+
+ embedding[graph.oppositeArc(n)] =
+ embedding[graph.oppositeArc(e)];
+ embedding[graph.oppositeArc(e)] =
+ graph.oppositeArc(n);
+
+ p = n;
+ e = embedding[graph.oppositeArc(n)];
+ } else {
+ visited.set(graph.source(e), true);
+ pp = p;
+ p = e;
+ e = embedding[graph.oppositeArc(e)];
+ }
+ }
+ visited.setAll(false);
+ }
+ }
+
+
+ template <typename Graph, typename EmbeddingMap>
+ void makeMaxPlanar(Graph& graph, EmbeddingMap& embedding) {
+
+ typename Graph::template NodeMap<int> degree(graph);
+
+ for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
+ degree[n] = countIncEdges(graph, n);
+ }
+
+ typename Graph::template ArcMap<bool> processed(graph);
+ IterableBoolMap<Graph, typename Graph::Node> visited(graph, false);
+
+ std::vector<typename Graph::Arc> arcs;
+ for (typename Graph::ArcIt e(graph); e != INVALID; ++e) {
+ arcs.push_back(e);
+ }
+
+ for (int i = 0; i < int(arcs.size()); ++i) {
+ typename Graph::Arc e = arcs[i];
+
+ if (processed[e]) continue;
+ processed[e] = true;
+
+ typename Graph::Arc mine = e;
+ int mind = degree[graph.source(e)];
+
+ int face_size = 1;
+
+ typename Graph::Arc l = e;
+ e = embedding[graph.oppositeArc(e)];
+ while (l != e) {
+ processed[e] = true;
+
+ ++face_size;
+
+ if (degree[graph.source(e)] < mind) {
+ mine = e;
+ mind = degree[graph.source(e)];
+ }
+
+ e = embedding[graph.oppositeArc(e)];
+ }
+
+ if (face_size < 4) {
+ continue;
+ }
+
+ typename Graph::Node s = graph.source(mine);
+ for (typename Graph::OutArcIt e(graph, s); e != INVALID; ++e) {
+ visited.set(graph.target(e), true);
+ }
+
+ typename Graph::Arc oppe = INVALID;
+
+ e = embedding[graph.oppositeArc(mine)];
+ e = embedding[graph.oppositeArc(e)];
+ while (graph.target(e) != s) {
+ if (visited[graph.source(e)]) {
+ oppe = e;
+ break;
+ }
+ e = embedding[graph.oppositeArc(e)];
+ }
+ visited.setAll(false);
+
+ if (oppe == INVALID) {
+
+ e = embedding[graph.oppositeArc(mine)];
+ typename Graph::Arc pn = mine, p = e;
+
+ e = embedding[graph.oppositeArc(e)];
+ while (graph.target(e) != s) {
+ typename Graph::Arc n =
+ graph.direct(graph.addEdge(s, graph.source(e)), true);
+
+ embedding[n] = pn;
+ embedding[graph.oppositeArc(n)] = e;
+ embedding[graph.oppositeArc(p)] = graph.oppositeArc(n);
+
+ pn = n;
+
+ p = e;
+ e = embedding[graph.oppositeArc(e)];
+ }
+
+ embedding[graph.oppositeArc(e)] = pn;
+
+ } else {
+
+ mine = embedding[graph.oppositeArc(mine)];
+ s = graph.source(mine);
+ oppe = embedding[graph.oppositeArc(oppe)];
+ typename Graph::Node t = graph.source(oppe);
+
+ typename Graph::Arc ce = graph.direct(graph.addEdge(s, t), true);
+ embedding[ce] = mine;
+ embedding[graph.oppositeArc(ce)] = oppe;
+
+ typename Graph::Arc pn = ce, p = oppe;
+ e = embedding[graph.oppositeArc(oppe)];
+ while (graph.target(e) != s) {
+ typename Graph::Arc n =
+ graph.direct(graph.addEdge(s, graph.source(e)), true);
+
+ embedding[n] = pn;
+ embedding[graph.oppositeArc(n)] = e;
+ embedding[graph.oppositeArc(p)] = graph.oppositeArc(n);
+
+ pn = n;
+
+ p = e;
+ e = embedding[graph.oppositeArc(e)];
+
+ }
+ embedding[graph.oppositeArc(e)] = pn;
+
+ pn = graph.oppositeArc(ce), p = mine;
+ e = embedding[graph.oppositeArc(mine)];
+ while (graph.target(e) != t) {
+ typename Graph::Arc n =
+ graph.direct(graph.addEdge(t, graph.source(e)), true);
+
+ embedding[n] = pn;
+ embedding[graph.oppositeArc(n)] = e;
+ embedding[graph.oppositeArc(p)] = graph.oppositeArc(n);
+
+ pn = n;
+
+ p = e;
+ e = embedding[graph.oppositeArc(e)];
+
+ }
+ embedding[graph.oppositeArc(e)] = pn;
+ }
+ }
+ }
+
+ }
+
+ /// \ingroup planar
+ ///
+ /// \brief Schnyder's planar drawing algorithm
+ ///
+ /// The planar drawing algorithm calculates positions for the nodes
+ /// in the plane. These coordinates satisfy that if the edges are
+ /// represented with straight lines, then they will not intersect
+ /// each other.
+ ///
+ /// Scnyder's algorithm embeds the graph on an \c (n-2)x(n-2) size grid,
+ /// i.e. each node will be located in the \c [0..n-2]x[0..n-2] square.
+ /// The time complexity of the algorithm is O(n).
+ ///
+ /// \see PlanarEmbedding
+ template <typename Graph>
+ class PlanarDrawing {
+ public:
+
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+ /// \brief The point type for storing coordinates
+ typedef dim2::Point<int> Point;
+ /// \brief The map type for storing the coordinates of the nodes
+ typedef typename Graph::template NodeMap<Point> PointMap;
+
+
+ /// \brief Constructor
+ ///
+ /// Constructor
+ /// \pre The graph must be simple, i.e. it should not
+ /// contain parallel or loop arcs.
+ PlanarDrawing(const Graph& graph)
+ : _graph(graph), _point_map(graph) {}
+
+ private:
+
+ template <typename AuxGraph, typename AuxEmbeddingMap>
+ void drawing(const AuxGraph& graph,
+ const AuxEmbeddingMap& next,
+ PointMap& point_map) {
+ TEMPLATE_GRAPH_TYPEDEFS(AuxGraph);
+
+ typename AuxGraph::template ArcMap<Arc> prev(graph);
+
+ for (NodeIt n(graph); n != INVALID; ++n) {
+ Arc e = OutArcIt(graph, n);
+
+ Arc p = e, l = e;
+
+ e = next[e];
+ while (e != l) {
+ prev[e] = p;
+ p = e;
+ e = next[e];
+ }
+ prev[e] = p;
+ }
+
+ Node anode, bnode, cnode;
+
+ {
+ Arc e = ArcIt(graph);
+ anode = graph.source(e);
+ bnode = graph.target(e);
+ cnode = graph.target(next[graph.oppositeArc(e)]);
+ }
+
+ IterableBoolMap<AuxGraph, Node> proper(graph, false);
+ typename AuxGraph::template NodeMap<int> conn(graph, -1);
+
+ conn[anode] = conn[bnode] = -2;
+ {
+ for (OutArcIt e(graph, anode); e != INVALID; ++e) {
+ Node m = graph.target(e);
+ if (conn[m] == -1) {
+ conn[m] = 1;
+ }
+ }
+ conn[cnode] = 2;
+
+ for (OutArcIt e(graph, bnode); e != INVALID; ++e) {
+ Node m = graph.target(e);
+ if (conn[m] == -1) {
+ conn[m] = 1;
+ } else if (conn[m] != -2) {
+ conn[m] += 1;
+ Arc pe = graph.oppositeArc(e);
+ if (conn[graph.target(next[pe])] == -2) {
+ conn[m] -= 1;
+ }
+ if (conn[graph.target(prev[pe])] == -2) {
+ conn[m] -= 1;
+ }
+
+ proper.set(m, conn[m] == 1);
+ }
+ }
+ }
+
+
+ typename AuxGraph::template ArcMap<int> angle(graph, -1);
+
+ while (proper.trueNum() != 0) {
+ Node n = typename IterableBoolMap<AuxGraph, Node>::TrueIt(proper);
+ proper.set(n, false);
+ conn[n] = -2;
+
+ for (OutArcIt e(graph, n); e != INVALID; ++e) {
+ Node m = graph.target(e);
+ if (conn[m] == -1) {
+ conn[m] = 1;
+ } else if (conn[m] != -2) {
+ conn[m] += 1;
+ Arc pe = graph.oppositeArc(e);
+ if (conn[graph.target(next[pe])] == -2) {
+ conn[m] -= 1;
+ }
+ if (conn[graph.target(prev[pe])] == -2) {
+ conn[m] -= 1;
+ }
+
+ proper.set(m, conn[m] == 1);
+ }
+ }
+
+ {
+ Arc e = OutArcIt(graph, n);
+ Arc p = e, l = e;
+
+ e = next[e];
+ while (e != l) {
+
+ if (conn[graph.target(e)] == -2 && conn[graph.target(p)] == -2) {
+ Arc f = e;
+ angle[f] = 0;
+ f = next[graph.oppositeArc(f)];
+ angle[f] = 1;
+ f = next[graph.oppositeArc(f)];
+ angle[f] = 2;
+ }
+
+ p = e;
+ e = next[e];
+ }
+
+ if (conn[graph.target(e)] == -2 && conn[graph.target(p)] == -2) {
+ Arc f = e;
+ angle[f] = 0;
+ f = next[graph.oppositeArc(f)];
+ angle[f] = 1;
+ f = next[graph.oppositeArc(f)];
+ angle[f] = 2;
+ }
+ }
+ }
+
+ typename AuxGraph::template NodeMap<Node> apred(graph, INVALID);
+ typename AuxGraph::template NodeMap<Node> bpred(graph, INVALID);
+ typename AuxGraph::template NodeMap<Node> cpred(graph, INVALID);
+
+ typename AuxGraph::template NodeMap<int> apredid(graph, -1);
+ typename AuxGraph::template NodeMap<int> bpredid(graph, -1);
+ typename AuxGraph::template NodeMap<int> cpredid(graph, -1);
+
+ for (ArcIt e(graph); e != INVALID; ++e) {
+ if (angle[e] == angle[next[e]]) {
+ switch (angle[e]) {
+ case 2:
+ apred[graph.target(e)] = graph.source(e);
+ apredid[graph.target(e)] = graph.id(graph.source(e));
+ break;
+ case 1:
+ bpred[graph.target(e)] = graph.source(e);
+ bpredid[graph.target(e)] = graph.id(graph.source(e));
+ break;
+ case 0:
+ cpred[graph.target(e)] = graph.source(e);
+ cpredid[graph.target(e)] = graph.id(graph.source(e));
+ break;
+ }
+ }
+ }
+
+ cpred[anode] = INVALID;
+ cpred[bnode] = INVALID;
+
+ std::vector<Node> aorder, border, corder;
+
+ {
+ typename AuxGraph::template NodeMap<bool> processed(graph, false);
+ std::vector<Node> st;
+ for (NodeIt n(graph); n != INVALID; ++n) {
+ if (!processed[n] && n != bnode && n != cnode) {
+ st.push_back(n);
+ processed[n] = true;
+ Node m = apred[n];
+ while (m != INVALID && !processed[m]) {
+ st.push_back(m);
+ processed[m] = true;
+ m = apred[m];
+ }
+ while (!st.empty()) {
+ aorder.push_back(st.back());
+ st.pop_back();
+ }
+ }
+ }
+ }
+
+ {
+ typename AuxGraph::template NodeMap<bool> processed(graph, false);
+ std::vector<Node> st;
+ for (NodeIt n(graph); n != INVALID; ++n) {
+ if (!processed[n] && n != cnode && n != anode) {
+ st.push_back(n);
+ processed[n] = true;
+ Node m = bpred[n];
+ while (m != INVALID && !processed[m]) {
+ st.push_back(m);
+ processed[m] = true;
+ m = bpred[m];
+ }
+ while (!st.empty()) {
+ border.push_back(st.back());
+ st.pop_back();
+ }
+ }
+ }
+ }
+
+ {
+ typename AuxGraph::template NodeMap<bool> processed(graph, false);
+ std::vector<Node> st;
+ for (NodeIt n(graph); n != INVALID; ++n) {
+ if (!processed[n] && n != anode && n != bnode) {
+ st.push_back(n);
+ processed[n] = true;
+ Node m = cpred[n];
+ while (m != INVALID && !processed[m]) {
+ st.push_back(m);
+ processed[m] = true;
+ m = cpred[m];
+ }
+ while (!st.empty()) {
+ corder.push_back(st.back());
+ st.pop_back();
+ }
+ }
+ }
+ }
+
+ typename AuxGraph::template NodeMap<int> atree(graph, 0);
+ for (int i = aorder.size() - 1; i >= 0; --i) {
+ Node n = aorder[i];
+ atree[n] = 1;
+ for (OutArcIt e(graph, n); e != INVALID; ++e) {
+ if (apred[graph.target(e)] == n) {
+ atree[n] += atree[graph.target(e)];
+ }
+ }
+ }
+
+ typename AuxGraph::template NodeMap<int> btree(graph, 0);
+ for (int i = border.size() - 1; i >= 0; --i) {
+ Node n = border[i];
+ btree[n] = 1;
+ for (OutArcIt e(graph, n); e != INVALID; ++e) {
+ if (bpred[graph.target(e)] == n) {
+ btree[n] += btree[graph.target(e)];
+ }
+ }
+ }
+
+ typename AuxGraph::template NodeMap<int> apath(graph, 0);
+ apath[bnode] = apath[cnode] = 1;
+ typename AuxGraph::template NodeMap<int> apath_btree(graph, 0);
+ apath_btree[bnode] = btree[bnode];
+ for (int i = 1; i < int(aorder.size()); ++i) {
+ Node n = aorder[i];
+ apath[n] = apath[apred[n]] + 1;
+ apath_btree[n] = btree[n] + apath_btree[apred[n]];
+ }
+
+ typename AuxGraph::template NodeMap<int> bpath_atree(graph, 0);
+ bpath_atree[anode] = atree[anode];
+ for (int i = 1; i < int(border.size()); ++i) {
+ Node n = border[i];
+ bpath_atree[n] = atree[n] + bpath_atree[bpred[n]];
+ }
+
+ typename AuxGraph::template NodeMap<int> cpath(graph, 0);
+ cpath[anode] = cpath[bnode] = 1;
+ typename AuxGraph::template NodeMap<int> cpath_atree(graph, 0);
+ cpath_atree[anode] = atree[anode];
+ typename AuxGraph::template NodeMap<int> cpath_btree(graph, 0);
+ cpath_btree[bnode] = btree[bnode];
+ for (int i = 1; i < int(corder.size()); ++i) {
+ Node n = corder[i];
+ cpath[n] = cpath[cpred[n]] + 1;
+ cpath_atree[n] = atree[n] + cpath_atree[cpred[n]];
+ cpath_btree[n] = btree[n] + cpath_btree[cpred[n]];
+ }
+
+ typename AuxGraph::template NodeMap<int> third(graph);
+ for (NodeIt n(graph); n != INVALID; ++n) {
+ point_map[n].x =
+ bpath_atree[n] + cpath_atree[n] - atree[n] - cpath[n] + 1;
+ point_map[n].y =
+ cpath_btree[n] + apath_btree[n] - btree[n] - apath[n] + 1;
+ }
+
+ }
+
+ public:
+
+ /// \brief Calculate the node positions
+ ///
+ /// This function calculates the node positions on the plane.
+ /// \return \c true if the graph is planar.
+ bool run() {
+ PlanarEmbedding<Graph> pe(_graph);
+ if (!pe.run()) return false;
+
+ run(pe);
+ return true;
+ }
+
+ /// \brief Calculate the node positions according to a
+ /// combinatorical embedding
+ ///
+ /// This function calculates the node positions on the plane.
+ /// The given \c embedding map should contain a valid combinatorical
+ /// embedding, i.e. a valid cyclic order of the arcs.
+ /// It can be computed using PlanarEmbedding.
+ template <typename EmbeddingMap>
+ void run(const EmbeddingMap& embedding) {
+ typedef SmartEdgeSet<Graph> AuxGraph;
+
+ if (3 * countNodes(_graph) - 6 == countEdges(_graph)) {
+ drawing(_graph, embedding, _point_map);
+ return;
+ }
+
+ AuxGraph aux_graph(_graph);
+ typename AuxGraph::template ArcMap<typename AuxGraph::Arc>
+ aux_embedding(aux_graph);
+
+ {
+
+ typename Graph::template EdgeMap<typename AuxGraph::Edge>
+ ref(_graph);
+
+ for (EdgeIt e(_graph); e != INVALID; ++e) {
+ ref[e] = aux_graph.addEdge(_graph.u(e), _graph.v(e));
+ }
+
+ for (EdgeIt e(_graph); e != INVALID; ++e) {
+ Arc ee = embedding[_graph.direct(e, true)];
+ aux_embedding[aux_graph.direct(ref[e], true)] =
+ aux_graph.direct(ref[ee], _graph.direction(ee));
+ ee = embedding[_graph.direct(e, false)];
+ aux_embedding[aux_graph.direct(ref[e], false)] =
+ aux_graph.direct(ref[ee], _graph.direction(ee));
+ }
+ }
+ _planarity_bits::makeConnected(aux_graph, aux_embedding);
+ _planarity_bits::makeBiNodeConnected(aux_graph, aux_embedding);
+ _planarity_bits::makeMaxPlanar(aux_graph, aux_embedding);
+ drawing(aux_graph, aux_embedding, _point_map);
+ }
+
+ /// \brief The coordinate of the given node
+ ///
+ /// This function returns the coordinate of the given node.
+ Point operator[](const Node& node) const {
+ return _point_map[node];
+ }
+
+ /// \brief Return the grid embedding in a node map
+ ///
+ /// This function returns the grid embedding in a node map of
+ /// \c dim2::Point<int> coordinates.
+ const PointMap& coords() const {
+ return _point_map;
+ }
+
+ private:
+
+ const Graph& _graph;
+ PointMap _point_map;
+
+ };
+
+ namespace _planarity_bits {
+
+ template <typename ColorMap>
+ class KempeFilter {
+ public:
+ typedef typename ColorMap::Key Key;
+ typedef bool Value;
+
+ KempeFilter(const ColorMap& color_map,
+ const typename ColorMap::Value& first,
+ const typename ColorMap::Value& second)
+ : _color_map(color_map), _first(first), _second(second) {}
+
+ Value operator[](const Key& key) const {
+ return _color_map[key] == _first || _color_map[key] == _second;
+ }
+
+ private:
+ const ColorMap& _color_map;
+ typename ColorMap::Value _first, _second;
+ };
+ }
+
+ /// \ingroup planar
+ ///
+ /// \brief Coloring planar graphs
+ ///
+ /// The graph coloring problem is the coloring of the graph nodes
+ /// so that there are no adjacent nodes with the same color. The
+ /// planar graphs can always be colored with four colors, which is
+ /// proved by Appel and Haken. Their proofs provide a quadratic
+ /// time algorithm for four coloring, but it could not be used to
+ /// implement an efficient algorithm. The five and six coloring can be
+ /// made in linear time, but in this class, the five coloring has
+ /// quadratic worst case time complexity. The two coloring (if
+ /// possible) is solvable with a graph search algorithm and it is
+ /// implemented in \ref bipartitePartitions() function in LEMON. To
+ /// decide whether a planar graph is three colorable is NP-complete.
+ ///
+ /// This class contains member functions for calculate colorings
+ /// with five and six colors. The six coloring algorithm is a simple
+ /// greedy coloring on the backward minimum outgoing order of nodes.
+ /// This order can be computed by selecting the node with least
+ /// outgoing arcs to unprocessed nodes in each phase. This order
+ /// guarantees that when a node is chosen for coloring it has at
+ /// most five already colored adjacents. The five coloring algorithm
+ /// use the same method, but if the greedy approach fails to color
+ /// with five colors, i.e. the node has five already different
+ /// colored neighbours, it swaps the colors in one of the connected
+ /// two colored sets with the Kempe recoloring method.
+ template <typename Graph>
+ class PlanarColoring {
+ public:
+
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+ /// \brief The map type for storing color indices
+ typedef typename Graph::template NodeMap<int> IndexMap;
+ /// \brief The map type for storing colors
+ ///
+ /// The map type for storing colors.
+ /// \see Palette, Color
+ typedef ComposeMap<Palette, IndexMap> ColorMap;
+
+ /// \brief Constructor
+ ///
+ /// Constructor.
+ /// \pre The graph must be simple, i.e. it should not
+ /// contain parallel or loop arcs.
+ PlanarColoring(const Graph& graph)
+ : _graph(graph), _color_map(graph), _palette(0) {
+ _palette.add(Color(1,0,0));
+ _palette.add(Color(0,1,0));
+ _palette.add(Color(0,0,1));
+ _palette.add(Color(1,1,0));
+ _palette.add(Color(1,0,1));
+ _palette.add(Color(0,1,1));
+ }
+
+ /// \brief Return the node map of color indices
+ ///
+ /// This function returns the node map of color indices. The values are
+ /// in the range \c [0..4] or \c [0..5] according to the coloring method.
+ IndexMap colorIndexMap() const {
+ return _color_map;
+ }
+
+ /// \brief Return the node map of colors
+ ///
+ /// This function returns the node map of colors. The values are among
+ /// five or six distinct \ref lemon::Color "colors".
+ ColorMap colorMap() const {
+ return composeMap(_palette, _color_map);
+ }
+
+ /// \brief Return the color index of the node
+ ///
+ /// This function returns the color index of the given node. The value is
+ /// in the range \c [0..4] or \c [0..5] according to the coloring method.
+ int colorIndex(const Node& node) const {
+ return _color_map[node];
+ }
+
+ /// \brief Return the color of the node
+ ///
+ /// This function returns the color of the given node. The value is among
+ /// five or six distinct \ref lemon::Color "colors".
+ Color color(const Node& node) const {
+ return _palette[_color_map[node]];
+ }
+
+
+ /// \brief Calculate a coloring with at most six colors
+ ///
+ /// This function calculates a coloring with at most six colors. The time
+ /// complexity of this variant is linear in the size of the graph.
+ /// \return \c true if the algorithm could color the graph with six colors.
+ /// If the algorithm fails, then the graph is not planar.
+ /// \note This function can return \c true if the graph is not
+ /// planar, but it can be colored with at most six colors.
+ bool runSixColoring() {
+
+ typename Graph::template NodeMap<int> heap_index(_graph, -1);
+ BucketHeap<typename Graph::template NodeMap<int> > heap(heap_index);
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ _color_map[n] = -2;
+ heap.push(n, countOutArcs(_graph, n));
+ }
+
+ std::vector<Node> order;
+
+ while (!heap.empty()) {
+ Node n = heap.top();
+ heap.pop();
+ _color_map[n] = -1;
+ order.push_back(n);
+ for (OutArcIt e(_graph, n); e != INVALID; ++e) {
+ Node t = _graph.runningNode(e);
+ if (_color_map[t] == -2) {
+ heap.decrease(t, heap[t] - 1);
+ }
+ }
+ }
+
+ for (int i = order.size() - 1; i >= 0; --i) {
+ std::vector<bool> forbidden(6, false);
+ for (OutArcIt e(_graph, order[i]); e != INVALID; ++e) {
+ Node t = _graph.runningNode(e);
+ if (_color_map[t] != -1) {
+ forbidden[_color_map[t]] = true;
+ }
+ }
+ for (int k = 0; k < 6; ++k) {
+ if (!forbidden[k]) {
+ _color_map[order[i]] = k;
+ break;
+ }
+ }
+ if (_color_map[order[i]] == -1) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private:
+
+ bool recolor(const Node& u, const Node& v) {
+ int ucolor = _color_map[u];
+ int vcolor = _color_map[v];
+ typedef _planarity_bits::KempeFilter<IndexMap> KempeFilter;
+ KempeFilter filter(_color_map, ucolor, vcolor);
+
+ typedef FilterNodes<const Graph, const KempeFilter> KempeGraph;
+ KempeGraph kempe_graph(_graph, filter);
+
+ std::vector<Node> comp;
+ Bfs<KempeGraph> bfs(kempe_graph);
+ bfs.init();
+ bfs.addSource(u);
+ while (!bfs.emptyQueue()) {
+ Node n = bfs.nextNode();
+ if (n == v) return false;
+ comp.push_back(n);
+ bfs.processNextNode();
+ }
+
+ int scolor = ucolor + vcolor;
+ for (int i = 0; i < static_cast<int>(comp.size()); ++i) {
+ _color_map[comp[i]] = scolor - _color_map[comp[i]];
+ }
+
+ return true;
+ }
+
+ template <typename EmbeddingMap>
+ void kempeRecoloring(const Node& node, const EmbeddingMap& embedding) {
+ std::vector<Node> nodes;
+ nodes.reserve(4);
+
+ for (Arc e = OutArcIt(_graph, node); e != INVALID; e = embedding[e]) {
+ Node t = _graph.target(e);
+ if (_color_map[t] != -1) {
+ nodes.push_back(t);
+ if (nodes.size() == 4) break;
+ }
+ }
+
+ int color = _color_map[nodes[0]];
+ if (recolor(nodes[0], nodes[2])) {
+ _color_map[node] = color;
+ } else {
+ color = _color_map[nodes[1]];
+ recolor(nodes[1], nodes[3]);
+ _color_map[node] = color;
+ }
+ }
+
+ public:
+
+ /// \brief Calculate a coloring with at most five colors
+ ///
+ /// This function calculates a coloring with at most five
+ /// colors. The worst case time complexity of this variant is
+ /// quadratic in the size of the graph.
+ /// \param embedding This map should contain a valid combinatorical
+ /// embedding, i.e. a valid cyclic order of the arcs.
+ /// It can be computed using PlanarEmbedding.
+ template <typename EmbeddingMap>
+ void runFiveColoring(const EmbeddingMap& embedding) {
+
+ typename Graph::template NodeMap<int> heap_index(_graph, -1);
+ BucketHeap<typename Graph::template NodeMap<int> > heap(heap_index);
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ _color_map[n] = -2;
+ heap.push(n, countOutArcs(_graph, n));
+ }
+
+ std::vector<Node> order;
+
+ while (!heap.empty()) {
+ Node n = heap.top();
+ heap.pop();
+ _color_map[n] = -1;
+ order.push_back(n);
+ for (OutArcIt e(_graph, n); e != INVALID; ++e) {
+ Node t = _graph.runningNode(e);
+ if (_color_map[t] == -2) {
+ heap.decrease(t, heap[t] - 1);
+ }
+ }
+ }
+
+ for (int i = order.size() - 1; i >= 0; --i) {
+ std::vector<bool> forbidden(5, false);
+ for (OutArcIt e(_graph, order[i]); e != INVALID; ++e) {
+ Node t = _graph.runningNode(e);
+ if (_color_map[t] != -1) {
+ forbidden[_color_map[t]] = true;
+ }
+ }
+ for (int k = 0; k < 5; ++k) {
+ if (!forbidden[k]) {
+ _color_map[order[i]] = k;
+ break;
+ }
+ }
+ if (_color_map[order[i]] == -1) {
+ kempeRecoloring(order[i], embedding);
+ }
+ }
+ }
+
+ /// \brief Calculate a coloring with at most five colors
+ ///
+ /// This function calculates a coloring with at most five
+ /// colors. The worst case time complexity of this variant is
+ /// quadratic in the size of the graph.
+ /// \return \c true if the graph is planar.
+ bool runFiveColoring() {
+ PlanarEmbedding<Graph> pe(_graph);
+ if (!pe.run()) return false;
+
+ runFiveColoring(pe.embeddingMap());
+ return true;
+ }
+
+ private:
+
+ const Graph& _graph;
+ IndexMap _color_map;
+ Palette _palette;
+ };
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/preflow.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/preflow.h
new file mode 100644
index 00000000000..28ccd67dcf1
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/preflow.h
@@ -0,0 +1,985 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_PREFLOW_H
+#define LEMON_PREFLOW_H
+
+#include <lemon/tolerance.h>
+#include <lemon/elevator.h>
+
+/// \file
+/// \ingroup max_flow
+/// \brief Implementation of the preflow algorithm.
+
+namespace lemon {
+
+ /// \brief Default traits class of Preflow class.
+ ///
+ /// Default traits class of Preflow class.
+ /// \tparam GR Digraph type.
+ /// \tparam CAP Capacity map type.
+ template <typename GR, typename CAP>
+ struct PreflowDefaultTraits {
+
+ /// \brief The type of the digraph the algorithm runs on.
+ typedef GR Digraph;
+
+ /// \brief The type of the map that stores the arc capacities.
+ ///
+ /// The type of the map that stores the arc capacities.
+ /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
+ typedef CAP CapacityMap;
+
+ /// \brief The type of the flow values.
+ typedef typename CapacityMap::Value Value;
+
+ /// \brief The type of the map that stores the flow values.
+ ///
+ /// The type of the map that stores the flow values.
+ /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
+#ifdef DOXYGEN
+ typedef GR::ArcMap<Value> FlowMap;
+#else
+ typedef typename Digraph::template ArcMap<Value> FlowMap;
+#endif
+
+ /// \brief Instantiates a FlowMap.
+ ///
+ /// This function instantiates a \ref FlowMap.
+ /// \param digraph The digraph for which we would like to define
+ /// the flow map.
+ static FlowMap* createFlowMap(const Digraph& digraph) {
+ return new FlowMap(digraph);
+ }
+
+ /// \brief The elevator type used by Preflow algorithm.
+ ///
+ /// The elevator type used by Preflow algorithm.
+ ///
+ /// \sa Elevator, LinkedElevator
+#ifdef DOXYGEN
+ typedef lemon::Elevator<GR, GR::Node> Elevator;
+#else
+ typedef lemon::Elevator<Digraph, typename Digraph::Node> Elevator;
+#endif
+
+ /// \brief Instantiates an Elevator.
+ ///
+ /// This function instantiates an \ref Elevator.
+ /// \param digraph The digraph for which we would like to define
+ /// the elevator.
+ /// \param max_level The maximum level of the elevator.
+ static Elevator* createElevator(const Digraph& digraph, int max_level) {
+ return new Elevator(digraph, max_level);
+ }
+
+ /// \brief The tolerance used by the algorithm
+ ///
+ /// The tolerance used by the algorithm to handle inexact computation.
+ typedef lemon::Tolerance<Value> Tolerance;
+
+ };
+
+
+ /// \ingroup max_flow
+ ///
+ /// \brief %Preflow algorithm class.
+ ///
+ /// This class provides an implementation of Goldberg-Tarjan's \e preflow
+ /// \e push-relabel algorithm producing a \ref max_flow
+ /// "flow of maximum value" in a digraph \cite clrs01algorithms,
+ /// \cite amo93networkflows, \cite goldberg88newapproach.
+ /// The preflow algorithms are the fastest known maximum
+ /// flow algorithms. The current implementation uses a mixture of the
+ /// \e "highest label" and the \e "bound decrease" heuristics.
+ /// The worst case time complexity of the algorithm is \f$O(n^2\sqrt{m})\f$.
+ ///
+ /// The algorithm consists of two phases. After the first phase
+ /// the maximum flow value and the minimum cut is obtained. The
+ /// second phase constructs a feasible maximum flow on each arc.
+ ///
+ /// \warning This implementation cannot handle infinite or very large
+ /// capacities (e.g. the maximum value of \c CAP::Value).
+ ///
+ /// \tparam GR The type of the digraph the algorithm runs on.
+ /// \tparam CAP The type of the capacity map. The default map
+ /// type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
+ /// \tparam TR The traits class that defines various types used by the
+ /// algorithm. By default, it is \ref PreflowDefaultTraits
+ /// "PreflowDefaultTraits<GR, CAP>".
+ /// In most cases, this parameter should not be set directly,
+ /// consider to use the named template parameters instead.
+#ifdef DOXYGEN
+ template <typename GR, typename CAP, typename TR>
+#else
+ template <typename GR,
+ typename CAP = typename GR::template ArcMap<int>,
+ typename TR = PreflowDefaultTraits<GR, CAP> >
+#endif
+ class Preflow {
+ public:
+
+ ///The \ref lemon::PreflowDefaultTraits "traits class" of the algorithm.
+ typedef TR Traits;
+ ///The type of the digraph the algorithm runs on.
+ typedef typename Traits::Digraph Digraph;
+ ///The type of the capacity map.
+ typedef typename Traits::CapacityMap CapacityMap;
+ ///The type of the flow values.
+ typedef typename Traits::Value Value;
+
+ ///The type of the flow map.
+ typedef typename Traits::FlowMap FlowMap;
+ ///The type of the elevator.
+ typedef typename Traits::Elevator Elevator;
+ ///The type of the tolerance.
+ typedef typename Traits::Tolerance Tolerance;
+
+ private:
+
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+
+ const Digraph& _graph;
+ const CapacityMap* _capacity;
+
+ int _node_num;
+
+ Node _source, _target;
+
+ FlowMap* _flow;
+ bool _local_flow;
+
+ Elevator* _level;
+ bool _local_level;
+
+ typedef typename Digraph::template NodeMap<Value> ExcessMap;
+ ExcessMap* _excess;
+
+ Tolerance _tolerance;
+
+ bool _phase;
+
+
+ void createStructures() {
+ _node_num = countNodes(_graph);
+
+ if (!_flow) {
+ _flow = Traits::createFlowMap(_graph);
+ _local_flow = true;
+ }
+ if (!_level) {
+ _level = Traits::createElevator(_graph, _node_num);
+ _local_level = true;
+ }
+ if (!_excess) {
+ _excess = new ExcessMap(_graph);
+ }
+ }
+
+ void destroyStructures() {
+ if (_local_flow) {
+ delete _flow;
+ }
+ if (_local_level) {
+ delete _level;
+ }
+ if (_excess) {
+ delete _excess;
+ }
+ }
+
+ public:
+
+ typedef Preflow Create;
+
+ ///\name Named Template Parameters
+
+ ///@{
+
+ template <typename T>
+ struct SetFlowMapTraits : public Traits {
+ typedef T FlowMap;
+ static FlowMap *createFlowMap(const Digraph&) {
+ LEMON_ASSERT(false, "FlowMap is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// FlowMap type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting FlowMap
+ /// type.
+ template <typename T>
+ struct SetFlowMap
+ : public Preflow<Digraph, CapacityMap, SetFlowMapTraits<T> > {
+ typedef Preflow<Digraph, CapacityMap,
+ SetFlowMapTraits<T> > Create;
+ };
+
+ template <typename T>
+ struct SetElevatorTraits : public Traits {
+ typedef T Elevator;
+ static Elevator *createElevator(const Digraph&, int) {
+ LEMON_ASSERT(false, "Elevator is not initialized");
+ return 0; // ignore warnings
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// Elevator type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting Elevator
+ /// type. If this named parameter is used, then an external
+ /// elevator object must be passed to the algorithm using the
+ /// \ref elevator(Elevator&) "elevator()" function before calling
+ /// \ref run() or \ref init().
+ /// \sa SetStandardElevator
+ template <typename T>
+ struct SetElevator
+ : public Preflow<Digraph, CapacityMap, SetElevatorTraits<T> > {
+ typedef Preflow<Digraph, CapacityMap,
+ SetElevatorTraits<T> > Create;
+ };
+
+ template <typename T>
+ struct SetStandardElevatorTraits : public Traits {
+ typedef T Elevator;
+ static Elevator *createElevator(const Digraph& digraph, int max_level) {
+ return new Elevator(digraph, max_level);
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// Elevator type with automatic allocation
+ ///
+ /// \ref named-templ-param "Named parameter" for setting Elevator
+ /// type with automatic allocation.
+ /// The Elevator should have standard constructor interface to be
+ /// able to automatically created by the algorithm (i.e. the
+ /// digraph and the maximum level should be passed to it).
+ /// However, an external elevator object could also be passed to the
+ /// algorithm with the \ref elevator(Elevator&) "elevator()" function
+ /// before calling \ref run() or \ref init().
+ /// \sa SetElevator
+ template <typename T>
+ struct SetStandardElevator
+ : public Preflow<Digraph, CapacityMap,
+ SetStandardElevatorTraits<T> > {
+ typedef Preflow<Digraph, CapacityMap,
+ SetStandardElevatorTraits<T> > Create;
+ };
+
+ /// @}
+
+ protected:
+
+ Preflow() {}
+
+ public:
+
+
+ /// \brief The constructor of the class.
+ ///
+ /// The constructor of the class.
+ /// \param digraph The digraph the algorithm runs on.
+ /// \param capacity The capacity of the arcs.
+ /// \param source The source node.
+ /// \param target The target node.
+ Preflow(const Digraph& digraph, const CapacityMap& capacity,
+ Node source, Node target)
+ : _graph(digraph), _capacity(&capacity),
+ _node_num(0), _source(source), _target(target),
+ _flow(0), _local_flow(false),
+ _level(0), _local_level(false),
+ _excess(0), _tolerance(), _phase() {}
+
+ /// \brief Destructor.
+ ///
+ /// Destructor.
+ ~Preflow() {
+ destroyStructures();
+ }
+
+ /// \brief Sets the capacity map.
+ ///
+ /// Sets the capacity map.
+ /// \return <tt>(*this)</tt>
+ Preflow& capacityMap(const CapacityMap& map) {
+ _capacity = &map;
+ return *this;
+ }
+
+ /// \brief Sets the flow map.
+ ///
+ /// Sets the flow map.
+ /// If you don't use this function before calling \ref run() or
+ /// \ref init(), an instance will be allocated automatically.
+ /// The destructor deallocates this automatically allocated map,
+ /// of course.
+ /// \return <tt>(*this)</tt>
+ Preflow& flowMap(FlowMap& map) {
+ if (_local_flow) {
+ delete _flow;
+ _local_flow = false;
+ }
+ _flow = &map;
+ return *this;
+ }
+
+ /// \brief Sets the source node.
+ ///
+ /// Sets the source node.
+ /// \return <tt>(*this)</tt>
+ Preflow& source(const Node& node) {
+ _source = node;
+ return *this;
+ }
+
+ /// \brief Sets the target node.
+ ///
+ /// Sets the target node.
+ /// \return <tt>(*this)</tt>
+ Preflow& target(const Node& node) {
+ _target = node;
+ return *this;
+ }
+
+ /// \brief Sets the elevator used by algorithm.
+ ///
+ /// Sets the elevator used by algorithm.
+ /// If you don't use this function before calling \ref run() or
+ /// \ref init(), an instance will be allocated automatically.
+ /// The destructor deallocates this automatically allocated elevator,
+ /// of course.
+ /// \return <tt>(*this)</tt>
+ Preflow& elevator(Elevator& elevator) {
+ if (_local_level) {
+ delete _level;
+ _local_level = false;
+ }
+ _level = &elevator;
+ return *this;
+ }
+
+ /// \brief Returns a const reference to the elevator.
+ ///
+ /// Returns a const reference to the elevator.
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ const Elevator& elevator() const {
+ return *_level;
+ }
+
+ /// \brief Sets the tolerance used by the algorithm.
+ ///
+ /// Sets the tolerance object used by the algorithm.
+ /// \return <tt>(*this)</tt>
+ Preflow& tolerance(const Tolerance& tolerance) {
+ _tolerance = tolerance;
+ return *this;
+ }
+
+ /// \brief Returns a const reference to the tolerance.
+ ///
+ /// Returns a const reference to the tolerance object used by
+ /// the algorithm.
+ const Tolerance& tolerance() const {
+ return _tolerance;
+ }
+
+ /// \name Execution Control
+ /// The simplest way to execute the preflow algorithm is to use
+ /// \ref run() or \ref runMinCut().\n
+ /// If you need better control on the initial solution or the execution,
+ /// you have to call one of the \ref init() functions first, then
+ /// \ref startFirstPhase() and if you need it \ref startSecondPhase().
+
+ ///@{
+
+ /// \brief Initializes the internal data structures.
+ ///
+ /// Initializes the internal data structures and sets the initial
+ /// flow to zero on each arc.
+ void init() {
+ createStructures();
+
+ _phase = true;
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ (*_excess)[n] = 0;
+ }
+
+ for (ArcIt e(_graph); e != INVALID; ++e) {
+ _flow->set(e, 0);
+ }
+
+ typename Digraph::template NodeMap<bool> reached(_graph, false);
+
+ _level->initStart();
+ _level->initAddItem(_target);
+
+ std::vector<Node> queue;
+ reached[_source] = true;
+
+ queue.push_back(_target);
+ reached[_target] = true;
+ while (!queue.empty()) {
+ _level->initNewLevel();
+ std::vector<Node> nqueue;
+ for (int i = 0; i < int(queue.size()); ++i) {
+ Node n = queue[i];
+ for (InArcIt e(_graph, n); e != INVALID; ++e) {
+ Node u = _graph.source(e);
+ if (!reached[u] && _tolerance.positive((*_capacity)[e])) {
+ reached[u] = true;
+ _level->initAddItem(u);
+ nqueue.push_back(u);
+ }
+ }
+ }
+ queue.swap(nqueue);
+ }
+ _level->initFinish();
+
+ for (OutArcIt e(_graph, _source); e != INVALID; ++e) {
+ if (_tolerance.positive((*_capacity)[e])) {
+ Node u = _graph.target(e);
+ if ((*_level)[u] == _level->maxLevel()) continue;
+ _flow->set(e, (*_capacity)[e]);
+ (*_excess)[u] += (*_capacity)[e];
+ if (u != _target && !_level->active(u)) {
+ _level->activate(u);
+ }
+ }
+ }
+ }
+
+ /// \brief Initializes the internal data structures using the
+ /// given flow map.
+ ///
+ /// Initializes the internal data structures and sets the initial
+ /// flow to the given \c flowMap. The \c flowMap should contain a
+ /// flow or at least a preflow, i.e. at each node excluding the
+ /// source node the incoming flow should greater or equal to the
+ /// outgoing flow.
+ /// \return \c false if the given \c flowMap is not a preflow.
+ template <typename FlowMap>
+ bool init(const FlowMap& flowMap) {
+ createStructures();
+
+ for (ArcIt e(_graph); e != INVALID; ++e) {
+ _flow->set(e, flowMap[e]);
+ }
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ Value excess = 0;
+ for (InArcIt e(_graph, n); e != INVALID; ++e) {
+ excess += (*_flow)[e];
+ }
+ for (OutArcIt e(_graph, n); e != INVALID; ++e) {
+ excess -= (*_flow)[e];
+ }
+ if (excess < 0 && n != _source) return false;
+ (*_excess)[n] = excess;
+ }
+
+ typename Digraph::template NodeMap<bool> reached(_graph, false);
+
+ _level->initStart();
+ _level->initAddItem(_target);
+
+ std::vector<Node> queue;
+ reached[_source] = true;
+
+ queue.push_back(_target);
+ reached[_target] = true;
+ while (!queue.empty()) {
+ _level->initNewLevel();
+ std::vector<Node> nqueue;
+ for (int i = 0; i < int(queue.size()); ++i) {
+ Node n = queue[i];
+ for (InArcIt e(_graph, n); e != INVALID; ++e) {
+ Node u = _graph.source(e);
+ if (!reached[u] &&
+ _tolerance.positive((*_capacity)[e] - (*_flow)[e])) {
+ reached[u] = true;
+ _level->initAddItem(u);
+ nqueue.push_back(u);
+ }
+ }
+ for (OutArcIt e(_graph, n); e != INVALID; ++e) {
+ Node v = _graph.target(e);
+ if (!reached[v] && _tolerance.positive((*_flow)[e])) {
+ reached[v] = true;
+ _level->initAddItem(v);
+ nqueue.push_back(v);
+ }
+ }
+ }
+ queue.swap(nqueue);
+ }
+ _level->initFinish();
+
+ for (OutArcIt e(_graph, _source); e != INVALID; ++e) {
+ Value rem = (*_capacity)[e] - (*_flow)[e];
+ if (_tolerance.positive(rem)) {
+ Node u = _graph.target(e);
+ if ((*_level)[u] == _level->maxLevel()) continue;
+ _flow->set(e, (*_capacity)[e]);
+ (*_excess)[u] += rem;
+ }
+ }
+ for (InArcIt e(_graph, _source); e != INVALID; ++e) {
+ Value rem = (*_flow)[e];
+ if (_tolerance.positive(rem)) {
+ Node v = _graph.source(e);
+ if ((*_level)[v] == _level->maxLevel()) continue;
+ _flow->set(e, 0);
+ (*_excess)[v] += rem;
+ }
+ }
+ for (NodeIt n(_graph); n != INVALID; ++n)
+ if(n!=_source && n!=_target && _tolerance.positive((*_excess)[n]))
+ _level->activate(n);
+
+ return true;
+ }
+
+ /// \brief Starts the first phase of the preflow algorithm.
+ ///
+ /// The preflow algorithm consists of two phases, this method runs
+ /// the first phase. After the first phase the maximum flow value
+ /// and a minimum value cut can already be computed, although a
+ /// maximum flow is not yet obtained. So after calling this method
+ /// \ref flowValue() returns the value of a maximum flow and \ref
+ /// minCut() returns a minimum cut.
+ /// \pre One of the \ref init() functions must be called before
+ /// using this function.
+ void startFirstPhase() {
+ _phase = true;
+
+ while (true) {
+ int num = _node_num;
+
+ Node n = INVALID;
+ int level = -1;
+
+ while (num > 0) {
+ n = _level->highestActive();
+ if (n == INVALID) goto first_phase_done;
+ level = _level->highestActiveLevel();
+ --num;
+
+ Value excess = (*_excess)[n];
+ int new_level = _level->maxLevel();
+
+ for (OutArcIt e(_graph, n); e != INVALID; ++e) {
+ Value rem = (*_capacity)[e] - (*_flow)[e];
+ if (!_tolerance.positive(rem)) continue;
+ Node v = _graph.target(e);
+ if ((*_level)[v] < level) {
+ if (!_level->active(v) && v != _target) {
+ _level->activate(v);
+ }
+ if (!_tolerance.less(rem, excess)) {
+ _flow->set(e, (*_flow)[e] + excess);
+ (*_excess)[v] += excess;
+ excess = 0;
+ goto no_more_push_1;
+ } else {
+ excess -= rem;
+ (*_excess)[v] += rem;
+ _flow->set(e, (*_capacity)[e]);
+ }
+ } else if (new_level > (*_level)[v]) {
+ new_level = (*_level)[v];
+ }
+ }
+
+ for (InArcIt e(_graph, n); e != INVALID; ++e) {
+ Value rem = (*_flow)[e];
+ if (!_tolerance.positive(rem)) continue;
+ Node v = _graph.source(e);
+ if ((*_level)[v] < level) {
+ if (!_level->active(v) && v != _target) {
+ _level->activate(v);
+ }
+ if (!_tolerance.less(rem, excess)) {
+ _flow->set(e, (*_flow)[e] - excess);
+ (*_excess)[v] += excess;
+ excess = 0;
+ goto no_more_push_1;
+ } else {
+ excess -= rem;
+ (*_excess)[v] += rem;
+ _flow->set(e, 0);
+ }
+ } else if (new_level > (*_level)[v]) {
+ new_level = (*_level)[v];
+ }
+ }
+
+ no_more_push_1:
+
+ (*_excess)[n] = excess;
+
+ if (excess != 0) {
+ if (new_level + 1 < _level->maxLevel()) {
+ _level->liftHighestActive(new_level + 1);
+ } else {
+ _level->liftHighestActiveToTop();
+ }
+ if (_level->emptyLevel(level)) {
+ _level->liftToTop(level);
+ }
+ } else {
+ _level->deactivate(n);
+ }
+ }
+
+ num = _node_num * 20;
+ while (num > 0) {
+ while (level >= 0 && _level->activeFree(level)) {
+ --level;
+ }
+ if (level == -1) {
+ n = _level->highestActive();
+ level = _level->highestActiveLevel();
+ if (n == INVALID) goto first_phase_done;
+ } else {
+ n = _level->activeOn(level);
+ }
+ --num;
+
+ Value excess = (*_excess)[n];
+ int new_level = _level->maxLevel();
+
+ for (OutArcIt e(_graph, n); e != INVALID; ++e) {
+ Value rem = (*_capacity)[e] - (*_flow)[e];
+ if (!_tolerance.positive(rem)) continue;
+ Node v = _graph.target(e);
+ if ((*_level)[v] < level) {
+ if (!_level->active(v) && v != _target) {
+ _level->activate(v);
+ }
+ if (!_tolerance.less(rem, excess)) {
+ _flow->set(e, (*_flow)[e] + excess);
+ (*_excess)[v] += excess;
+ excess = 0;
+ goto no_more_push_2;
+ } else {
+ excess -= rem;
+ (*_excess)[v] += rem;
+ _flow->set(e, (*_capacity)[e]);
+ }
+ } else if (new_level > (*_level)[v]) {
+ new_level = (*_level)[v];
+ }
+ }
+
+ for (InArcIt e(_graph, n); e != INVALID; ++e) {
+ Value rem = (*_flow)[e];
+ if (!_tolerance.positive(rem)) continue;
+ Node v = _graph.source(e);
+ if ((*_level)[v] < level) {
+ if (!_level->active(v) && v != _target) {
+ _level->activate(v);
+ }
+ if (!_tolerance.less(rem, excess)) {
+ _flow->set(e, (*_flow)[e] - excess);
+ (*_excess)[v] += excess;
+ excess = 0;
+ goto no_more_push_2;
+ } else {
+ excess -= rem;
+ (*_excess)[v] += rem;
+ _flow->set(e, 0);
+ }
+ } else if (new_level > (*_level)[v]) {
+ new_level = (*_level)[v];
+ }
+ }
+
+ no_more_push_2:
+
+ (*_excess)[n] = excess;
+
+ if (excess != 0) {
+ if (new_level + 1 < _level->maxLevel()) {
+ _level->liftActiveOn(level, new_level + 1);
+ } else {
+ _level->liftActiveToTop(level);
+ }
+ if (_level->emptyLevel(level)) {
+ _level->liftToTop(level);
+ }
+ } else {
+ _level->deactivate(n);
+ }
+ }
+ }
+ first_phase_done:;
+ }
+
+ /// \brief Starts the second phase of the preflow algorithm.
+ ///
+ /// The preflow algorithm consists of two phases, this method runs
+ /// the second phase. After calling one of the \ref init() functions
+ /// and \ref startFirstPhase() and then \ref startSecondPhase(),
+ /// \ref flowMap() returns a maximum flow, \ref flowValue() returns the
+ /// value of a maximum flow, \ref minCut() returns a minimum cut
+ /// \pre One of the \ref init() functions and \ref startFirstPhase()
+ /// must be called before using this function.
+ void startSecondPhase() {
+ _phase = false;
+
+ typename Digraph::template NodeMap<bool> reached(_graph);
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ reached[n] = (*_level)[n] < _level->maxLevel();
+ }
+
+ _level->initStart();
+ _level->initAddItem(_source);
+
+ std::vector<Node> queue;
+ queue.push_back(_source);
+ reached[_source] = true;
+
+ while (!queue.empty()) {
+ _level->initNewLevel();
+ std::vector<Node> nqueue;
+ for (int i = 0; i < int(queue.size()); ++i) {
+ Node n = queue[i];
+ for (OutArcIt e(_graph, n); e != INVALID; ++e) {
+ Node v = _graph.target(e);
+ if (!reached[v] && _tolerance.positive((*_flow)[e])) {
+ reached[v] = true;
+ _level->initAddItem(v);
+ nqueue.push_back(v);
+ }
+ }
+ for (InArcIt e(_graph, n); e != INVALID; ++e) {
+ Node u = _graph.source(e);
+ if (!reached[u] &&
+ _tolerance.positive((*_capacity)[e] - (*_flow)[e])) {
+ reached[u] = true;
+ _level->initAddItem(u);
+ nqueue.push_back(u);
+ }
+ }
+ }
+ queue.swap(nqueue);
+ }
+ _level->initFinish();
+
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ if (!reached[n]) {
+ _level->dirtyTopButOne(n);
+ } else if ((*_excess)[n] > 0 && _target != n) {
+ _level->activate(n);
+ }
+ }
+
+ Node n;
+ while ((n = _level->highestActive()) != INVALID) {
+ Value excess = (*_excess)[n];
+ int level = _level->highestActiveLevel();
+ int new_level = _level->maxLevel();
+
+ for (OutArcIt e(_graph, n); e != INVALID; ++e) {
+ Value rem = (*_capacity)[e] - (*_flow)[e];
+ if (!_tolerance.positive(rem)) continue;
+ Node v = _graph.target(e);
+ if ((*_level)[v] < level) {
+ if (!_level->active(v) && v != _source) {
+ _level->activate(v);
+ }
+ if (!_tolerance.less(rem, excess)) {
+ _flow->set(e, (*_flow)[e] + excess);
+ (*_excess)[v] += excess;
+ excess = 0;
+ goto no_more_push;
+ } else {
+ excess -= rem;
+ (*_excess)[v] += rem;
+ _flow->set(e, (*_capacity)[e]);
+ }
+ } else if (new_level > (*_level)[v]) {
+ new_level = (*_level)[v];
+ }
+ }
+
+ for (InArcIt e(_graph, n); e != INVALID; ++e) {
+ Value rem = (*_flow)[e];
+ if (!_tolerance.positive(rem)) continue;
+ Node v = _graph.source(e);
+ if ((*_level)[v] < level) {
+ if (!_level->active(v) && v != _source) {
+ _level->activate(v);
+ }
+ if (!_tolerance.less(rem, excess)) {
+ _flow->set(e, (*_flow)[e] - excess);
+ (*_excess)[v] += excess;
+ excess = 0;
+ goto no_more_push;
+ } else {
+ excess -= rem;
+ (*_excess)[v] += rem;
+ _flow->set(e, 0);
+ }
+ } else if (new_level > (*_level)[v]) {
+ new_level = (*_level)[v];
+ }
+ }
+
+ no_more_push:
+
+ (*_excess)[n] = excess;
+
+ if (excess != 0) {
+ if (new_level + 1 < _level->maxLevel()) {
+ _level->liftHighestActive(new_level + 1);
+ } else {
+ // Calculation error
+ _level->liftHighestActiveToTop();
+ }
+ if (_level->emptyLevel(level)) {
+ // Calculation error
+ _level->liftToTop(level);
+ }
+ } else {
+ _level->deactivate(n);
+ }
+
+ }
+ }
+
+ /// \brief Runs the preflow algorithm.
+ ///
+ /// Runs the preflow algorithm.
+ /// \note pf.run() is just a shortcut of the following code.
+ /// \code
+ /// pf.init();
+ /// pf.startFirstPhase();
+ /// pf.startSecondPhase();
+ /// \endcode
+ void run() {
+ init();
+ startFirstPhase();
+ startSecondPhase();
+ }
+
+ /// \brief Runs the preflow algorithm to compute the minimum cut.
+ ///
+ /// Runs the preflow algorithm to compute the minimum cut.
+ /// \note pf.runMinCut() is just a shortcut of the following code.
+ /// \code
+ /// pf.init();
+ /// pf.startFirstPhase();
+ /// \endcode
+ void runMinCut() {
+ init();
+ startFirstPhase();
+ }
+
+ /// @}
+
+ /// \name Query Functions
+ /// The results of the preflow algorithm can be obtained using these
+ /// functions.\n
+ /// Either one of the \ref run() "run*()" functions or one of the
+ /// \ref startFirstPhase() "start*()" functions should be called
+ /// before using them.
+
+ ///@{
+
+ /// \brief Returns the value of the maximum flow.
+ ///
+ /// Returns the value of the maximum flow by returning the excess
+ /// of the target node. This value equals to the value of
+ /// the maximum flow already after the first phase of the algorithm.
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ Value flowValue() const {
+ return (*_excess)[_target];
+ }
+
+ /// \brief Returns the flow value on the given arc.
+ ///
+ /// Returns the flow value on the given arc. This method can
+ /// be called after the second phase of the algorithm.
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ Value flow(const Arc& arc) const {
+ return (*_flow)[arc];
+ }
+
+ /// \brief Returns a const reference to the flow map.
+ ///
+ /// Returns a const reference to the arc map storing the found flow.
+ /// This method can be called after the second phase of the algorithm.
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ const FlowMap& flowMap() const {
+ return *_flow;
+ }
+
+ /// \brief Returns \c true when the node is on the source side of the
+ /// minimum cut.
+ ///
+ /// Returns true when the node is on the source side of the found
+ /// minimum cut. This method can be called both after running \ref
+ /// startFirstPhase() and \ref startSecondPhase().
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ bool minCut(const Node& node) const {
+ return ((*_level)[node] == _level->maxLevel()) == _phase;
+ }
+
+ /// \brief Gives back a minimum value cut.
+ ///
+ /// Sets \c cutMap to the characteristic vector of a minimum value
+ /// cut. \c cutMap should be a \ref concepts::WriteMap "writable"
+ /// node map with \c bool (or convertible) value type.
+ ///
+ /// This method can be called both after running \ref startFirstPhase()
+ /// and \ref startSecondPhase(). The result after the second phase
+ /// could be slightly different if inexact computation is used.
+ ///
+ /// \note This function calls \ref minCut() for each node, so it runs in
+ /// O(n) time.
+ ///
+ /// \pre Either \ref run() or \ref init() must be called before
+ /// using this function.
+ template <typename CutMap>
+ void minCutMap(CutMap& cutMap) const {
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ cutMap.set(n, minCut(n));
+ }
+ }
+
+ /// @}
+ };
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/quad_heap.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/quad_heap.h
new file mode 100644
index 00000000000..27c50fd3f60
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/quad_heap.h
@@ -0,0 +1,343 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_QUAD_HEAP_H
+#define LEMON_QUAD_HEAP_H
+
+///\ingroup heaps
+///\file
+///\brief Fourary (quaternary) heap implementation.
+
+#include <vector>
+#include <utility>
+#include <functional>
+
+namespace lemon {
+
+ /// \ingroup heaps
+ ///
+ ///\brief Fourary (quaternary) heap data structure.
+ ///
+ /// This class implements the \e Fourary (\e quaternary) \e heap
+ /// data structure.
+ /// It fully conforms to the \ref concepts::Heap "heap concept".
+ ///
+ /// The fourary heap is a specialization of the \ref DHeap "D-ary heap"
+ /// for <tt>D=4</tt>. It is similar to the \ref BinHeap "binary heap",
+ /// but its nodes have at most four children, instead of two.
+ ///
+ /// \tparam PR Type of the priorities of the items.
+ /// \tparam IM A read-writable item map with \c int values, used
+ /// internally to handle the cross references.
+ /// \tparam CMP A functor class for comparing the priorities.
+ /// The default is \c std::less<PR>.
+ ///
+ ///\sa BinHeap
+ ///\sa DHeap
+#ifdef DOXYGEN
+ template <typename PR, typename IM, typename CMP>
+#else
+ template <typename PR, typename IM, typename CMP = std::less<PR> >
+#endif
+ class QuadHeap {
+ public:
+ /// Type of the item-int map.
+ typedef IM ItemIntMap;
+ /// Type of the priorities.
+ typedef PR Prio;
+ /// Type of the items stored in the heap.
+ typedef typename ItemIntMap::Key Item;
+ /// Type of the item-priority pairs.
+ typedef std::pair<Item,Prio> Pair;
+ /// Functor type for comparing the priorities.
+ typedef CMP Compare;
+
+ /// \brief Type to represent the states of the items.
+ ///
+ /// Each item has a state associated to it. It can be "in heap",
+ /// "pre-heap" or "post-heap". The latter two are indifferent from the
+ /// heap's point of view, but may be useful to the user.
+ ///
+ /// The item-int map must be initialized in such way that it assigns
+ /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
+ enum State {
+ IN_HEAP = 0, ///< = 0.
+ PRE_HEAP = -1, ///< = -1.
+ POST_HEAP = -2 ///< = -2.
+ };
+
+ private:
+ std::vector<Pair> _data;
+ Compare _comp;
+ ItemIntMap &_iim;
+
+ public:
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// \param map A map that assigns \c int values to the items.
+ /// It is used internally to handle the cross references.
+ /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
+ explicit QuadHeap(ItemIntMap &map) : _iim(map) {}
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// \param map A map that assigns \c int values to the items.
+ /// It is used internally to handle the cross references.
+ /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
+ /// \param comp The function object used for comparing the priorities.
+ QuadHeap(ItemIntMap &map, const Compare &comp)
+ : _iim(map), _comp(comp) {}
+
+ /// \brief The number of items stored in the heap.
+ ///
+ /// This function returns the number of items stored in the heap.
+ int size() const { return _data.size(); }
+
+ /// \brief Check if the heap is empty.
+ ///
+ /// This function returns \c true if the heap is empty.
+ bool empty() const { return _data.empty(); }
+
+ /// \brief Make the heap empty.
+ ///
+ /// This functon makes the heap empty.
+ /// It does not change the cross reference map. If you want to reuse
+ /// a heap that is not surely empty, you should first clear it and
+ /// then you should set the cross reference map to \c PRE_HEAP
+ /// for each item.
+ void clear() { _data.clear(); }
+
+ private:
+ static int parent(int i) { return (i-1)/4; }
+ static int firstChild(int i) { return 4*i+1; }
+
+ bool less(const Pair &p1, const Pair &p2) const {
+ return _comp(p1.second, p2.second);
+ }
+
+ void bubbleUp(int hole, Pair p) {
+ int par = parent(hole);
+ while( hole>0 && less(p,_data[par]) ) {
+ move(_data[par],hole);
+ hole = par;
+ par = parent(hole);
+ }
+ move(p, hole);
+ }
+
+ void bubbleDown(int hole, Pair p, int length) {
+ if( length>1 ) {
+ int child = firstChild(hole);
+ while( child+3<length ) {
+ int min=child;
+ if( less(_data[++child], _data[min]) ) min=child;
+ if( less(_data[++child], _data[min]) ) min=child;
+ if( less(_data[++child], _data[min]) ) min=child;
+ if( !less(_data[min], p) )
+ goto ok;
+ move(_data[min], hole);
+ hole = min;
+ child = firstChild(hole);
+ }
+ if ( child<length ) {
+ int min = child;
+ if( ++child<length && less(_data[child], _data[min]) ) min=child;
+ if( ++child<length && less(_data[child], _data[min]) ) min=child;
+ if( less(_data[min], p) ) {
+ move(_data[min], hole);
+ hole = min;
+ }
+ }
+ }
+ ok:
+ move(p, hole);
+ }
+
+ void move(const Pair &p, int i) {
+ _data[i] = p;
+ _iim.set(p.first, i);
+ }
+
+ public:
+ /// \brief Insert a pair of item and priority into the heap.
+ ///
+ /// This function inserts \c p.first to the heap with priority
+ /// \c p.second.
+ /// \param p The pair to insert.
+ /// \pre \c p.first must not be stored in the heap.
+ void push(const Pair &p) {
+ int n = _data.size();
+ _data.resize(n+1);
+ bubbleUp(n, p);
+ }
+
+ /// \brief Insert an item into the heap with the given priority.
+ ///
+ /// This function inserts the given item into the heap with the
+ /// given priority.
+ /// \param i The item to insert.
+ /// \param p The priority of the item.
+ /// \pre \e i must not be stored in the heap.
+ void push(const Item &i, const Prio &p) { push(Pair(i,p)); }
+
+ /// \brief Return the item having minimum priority.
+ ///
+ /// This function returns the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ Item top() const { return _data[0].first; }
+
+ /// \brief The minimum priority.
+ ///
+ /// This function returns the minimum priority.
+ /// \pre The heap must be non-empty.
+ Prio prio() const { return _data[0].second; }
+
+ /// \brief Remove the item having minimum priority.
+ ///
+ /// This function removes the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ void pop() {
+ int n = _data.size()-1;
+ _iim.set(_data[0].first, POST_HEAP);
+ if (n>0) bubbleDown(0, _data[n], n);
+ _data.pop_back();
+ }
+
+ /// \brief Remove the given item from the heap.
+ ///
+ /// This function removes the given item from the heap if it is
+ /// already stored.
+ /// \param i The item to delete.
+ /// \pre \e i must be in the heap.
+ void erase(const Item &i) {
+ int h = _iim[i];
+ int n = _data.size()-1;
+ _iim.set(_data[h].first, POST_HEAP);
+ if( h<n ) {
+ if( less(_data[parent(h)], _data[n]) )
+ bubbleDown(h, _data[n], n);
+ else
+ bubbleUp(h, _data[n]);
+ }
+ _data.pop_back();
+ }
+
+ /// \brief The priority of the given item.
+ ///
+ /// This function returns the priority of the given item.
+ /// \param i The item.
+ /// \pre \e i must be in the heap.
+ Prio operator[](const Item &i) const {
+ int idx = _iim[i];
+ return _data[idx].second;
+ }
+
+ /// \brief Set the priority of an item or insert it, if it is
+ /// not stored in the heap.
+ ///
+ /// This method sets the priority of the given item if it is
+ /// already stored in the heap. Otherwise it inserts the given
+ /// item into the heap with the given priority.
+ /// \param i The item.
+ /// \param p The priority.
+ void set(const Item &i, const Prio &p) {
+ int idx = _iim[i];
+ if( idx < 0 )
+ push(i,p);
+ else if( _comp(p, _data[idx].second) )
+ bubbleUp(idx, Pair(i,p));
+ else
+ bubbleDown(idx, Pair(i,p), _data.size());
+ }
+
+ /// \brief Decrease the priority of an item to the given value.
+ ///
+ /// This function decreases the priority of an item to the given value.
+ /// \param i The item.
+ /// \param p The priority.
+ /// \pre \e i must be stored in the heap with priority at least \e p.
+ void decrease(const Item &i, const Prio &p) {
+ int idx = _iim[i];
+ bubbleUp(idx, Pair(i,p));
+ }
+
+ /// \brief Increase the priority of an item to the given value.
+ ///
+ /// This function increases the priority of an item to the given value.
+ /// \param i The item.
+ /// \param p The priority.
+ /// \pre \e i must be stored in the heap with priority at most \e p.
+ void increase(const Item &i, const Prio &p) {
+ int idx = _iim[i];
+ bubbleDown(idx, Pair(i,p), _data.size());
+ }
+
+ /// \brief Return the state of an item.
+ ///
+ /// This method returns \c PRE_HEAP if the given item has never
+ /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
+ /// and \c POST_HEAP otherwise.
+ /// In the latter case it is possible that the item will get back
+ /// to the heap again.
+ /// \param i The item.
+ State state(const Item &i) const {
+ int s = _iim[i];
+ if (s>=0) s=0;
+ return State(s);
+ }
+
+ /// \brief Set the state of an item in the heap.
+ ///
+ /// This function sets the state of the given item in the heap.
+ /// It can be used to manually clear the heap when it is important
+ /// to achive better time complexity.
+ /// \param i The item.
+ /// \param st The state. It should not be \c IN_HEAP.
+ void state(const Item& i, State st) {
+ switch (st) {
+ case POST_HEAP:
+ case PRE_HEAP:
+ if (state(i) == IN_HEAP) erase(i);
+ _iim[i] = st;
+ break;
+ case IN_HEAP:
+ break;
+ }
+ }
+
+ /// \brief Replace an item in the heap.
+ ///
+ /// This function replaces item \c i with item \c j.
+ /// Item \c i must be in the heap, while \c j must be out of the heap.
+ /// After calling this method, item \c i will be out of the
+ /// heap and \c j will be in the heap with the same prioriority
+ /// as item \c i had before.
+ void replace(const Item& i, const Item& j) {
+ int idx = _iim[i];
+ _iim.set(i, _iim[j]);
+ _iim.set(j, idx);
+ _data[idx].first = j;
+ }
+
+ }; // class QuadHeap
+
+} // namespace lemon
+
+#endif // LEMON_FOURARY_HEAP_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/radix_heap.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/radix_heap.h
new file mode 100644
index 00000000000..8701ce7474a
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/radix_heap.h
@@ -0,0 +1,438 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_RADIX_HEAP_H
+#define LEMON_RADIX_HEAP_H
+
+///\ingroup heaps
+///\file
+///\brief Radix heap implementation.
+
+#include <vector>
+#include <lemon/error.h>
+
+namespace lemon {
+
+
+ /// \ingroup heaps
+ ///
+ /// \brief Radix heap data structure.
+ ///
+ /// This class implements the \e radix \e heap data structure.
+ /// It practically conforms to the \ref concepts::Heap "heap concept",
+ /// but it has some limitations due its special implementation.
+ /// The type of the priorities must be \c int and the priority of an
+ /// item cannot be decreased under the priority of the last removed item.
+ ///
+ /// \tparam IM A read-writable item map with \c int values, used
+ /// internally to handle the cross references.
+ template <typename IM>
+ class RadixHeap {
+
+ public:
+
+ /// Type of the item-int map.
+ typedef IM ItemIntMap;
+ /// Type of the priorities.
+ typedef int Prio;
+ /// Type of the items stored in the heap.
+ typedef typename ItemIntMap::Key Item;
+
+ /// \brief Exception thrown by RadixHeap.
+ ///
+ /// This exception is thrown when an item is inserted into a
+ /// RadixHeap with a priority smaller than the last erased one.
+ /// \see RadixHeap
+ class PriorityUnderflowError : public Exception {
+ public:
+ virtual const char* what() const throw() {
+ return "lemon::RadixHeap::PriorityUnderflowError";
+ }
+ };
+
+ /// \brief Type to represent the states of the items.
+ ///
+ /// Each item has a state associated to it. It can be "in heap",
+ /// "pre-heap" or "post-heap". The latter two are indifferent from the
+ /// heap's point of view, but may be useful to the user.
+ ///
+ /// The item-int map must be initialized in such way that it assigns
+ /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
+ enum State {
+ IN_HEAP = 0, ///< = 0.
+ PRE_HEAP = -1, ///< = -1.
+ POST_HEAP = -2 ///< = -2.
+ };
+
+ private:
+
+ struct RadixItem {
+ int prev, next, box;
+ Item item;
+ int prio;
+ RadixItem(Item _item, int _prio) : item(_item), prio(_prio) {}
+ };
+
+ struct RadixBox {
+ int first;
+ int min, size;
+ RadixBox(int _min, int _size) : first(-1), min(_min), size(_size) {}
+ };
+
+ std::vector<RadixItem> _data;
+ std::vector<RadixBox> _boxes;
+
+ ItemIntMap &_iim;
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ /// \param map A map that assigns \c int values to the items.
+ /// It is used internally to handle the cross references.
+ /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
+ /// \param minimum The initial minimum value of the heap.
+ /// \param capacity The initial capacity of the heap.
+ RadixHeap(ItemIntMap &map, int minimum = 0, int capacity = 0)
+ : _iim(map)
+ {
+ _boxes.push_back(RadixBox(minimum, 1));
+ _boxes.push_back(RadixBox(minimum + 1, 1));
+ while (lower(_boxes.size() - 1, capacity + minimum - 1)) {
+ extend();
+ }
+ }
+
+ /// \brief The number of items stored in the heap.
+ ///
+ /// This function returns the number of items stored in the heap.
+ int size() const { return _data.size(); }
+
+ /// \brief Check if the heap is empty.
+ ///
+ /// This function returns \c true if the heap is empty.
+ bool empty() const { return _data.empty(); }
+
+ /// \brief Make the heap empty.
+ ///
+ /// This functon makes the heap empty.
+ /// It does not change the cross reference map. If you want to reuse
+ /// a heap that is not surely empty, you should first clear it and
+ /// then you should set the cross reference map to \c PRE_HEAP
+ /// for each item.
+ /// \param minimum The minimum value of the heap.
+ /// \param capacity The capacity of the heap.
+ void clear(int minimum = 0, int capacity = 0) {
+ _data.clear(); _boxes.clear();
+ _boxes.push_back(RadixBox(minimum, 1));
+ _boxes.push_back(RadixBox(minimum + 1, 1));
+ while (lower(_boxes.size() - 1, capacity + minimum - 1)) {
+ extend();
+ }
+ }
+
+ private:
+
+ bool upper(int box, Prio pr) {
+ return pr < _boxes[box].min;
+ }
+
+ bool lower(int box, Prio pr) {
+ return pr >= _boxes[box].min + _boxes[box].size;
+ }
+
+ // Remove item from the box list
+ void remove(int index) {
+ if (_data[index].prev >= 0) {
+ _data[_data[index].prev].next = _data[index].next;
+ } else {
+ _boxes[_data[index].box].first = _data[index].next;
+ }
+ if (_data[index].next >= 0) {
+ _data[_data[index].next].prev = _data[index].prev;
+ }
+ }
+
+ // Insert item into the box list
+ void insert(int box, int index) {
+ if (_boxes[box].first == -1) {
+ _boxes[box].first = index;
+ _data[index].next = _data[index].prev = -1;
+ } else {
+ _data[index].next = _boxes[box].first;
+ _data[_boxes[box].first].prev = index;
+ _data[index].prev = -1;
+ _boxes[box].first = index;
+ }
+ _data[index].box = box;
+ }
+
+ // Add a new box to the box list
+ void extend() {
+ int min = _boxes.back().min + _boxes.back().size;
+ int bs = 2 * _boxes.back().size;
+ _boxes.push_back(RadixBox(min, bs));
+ }
+
+ // Move an item up into the proper box.
+ void bubbleUp(int index) {
+ if (!lower(_data[index].box, _data[index].prio)) return;
+ remove(index);
+ int box = findUp(_data[index].box, _data[index].prio);
+ insert(box, index);
+ }
+
+ // Find up the proper box for the item with the given priority
+ int findUp(int start, int pr) {
+ while (lower(start, pr)) {
+ if (++start == int(_boxes.size())) {
+ extend();
+ }
+ }
+ return start;
+ }
+
+ // Move an item down into the proper box
+ void bubbleDown(int index) {
+ if (!upper(_data[index].box, _data[index].prio)) return;
+ remove(index);
+ int box = findDown(_data[index].box, _data[index].prio);
+ insert(box, index);
+ }
+
+ // Find down the proper box for the item with the given priority
+ int findDown(int start, int pr) {
+ while (upper(start, pr)) {
+ if (--start < 0) throw PriorityUnderflowError();
+ }
+ return start;
+ }
+
+ // Find the first non-empty box
+ int findFirst() {
+ int first = 0;
+ while (_boxes[first].first == -1) ++first;
+ return first;
+ }
+
+ // Gives back the minimum priority of the given box
+ int minValue(int box) {
+ int min = _data[_boxes[box].first].prio;
+ for (int k = _boxes[box].first; k != -1; k = _data[k].next) {
+ if (_data[k].prio < min) min = _data[k].prio;
+ }
+ return min;
+ }
+
+ // Rearrange the items of the heap and make the first box non-empty
+ void moveDown() {
+ int box = findFirst();
+ if (box == 0) return;
+ int min = minValue(box);
+ for (int i = 0; i <= box; ++i) {
+ _boxes[i].min = min;
+ min += _boxes[i].size;
+ }
+ int curr = _boxes[box].first, next;
+ while (curr != -1) {
+ next = _data[curr].next;
+ bubbleDown(curr);
+ curr = next;
+ }
+ }
+
+ void relocateLast(int index) {
+ if (index != int(_data.size()) - 1) {
+ _data[index] = _data.back();
+ if (_data[index].prev != -1) {
+ _data[_data[index].prev].next = index;
+ } else {
+ _boxes[_data[index].box].first = index;
+ }
+ if (_data[index].next != -1) {
+ _data[_data[index].next].prev = index;
+ }
+ _iim[_data[index].item] = index;
+ }
+ _data.pop_back();
+ }
+
+ public:
+
+ /// \brief Insert an item into the heap with the given priority.
+ ///
+ /// This function inserts the given item into the heap with the
+ /// given priority.
+ /// \param i The item to insert.
+ /// \param p The priority of the item.
+ /// \pre \e i must not be stored in the heap.
+ /// \warning This method may throw an \c UnderFlowPriorityException.
+ void push(const Item &i, const Prio &p) {
+ int n = _data.size();
+ _iim.set(i, n);
+ _data.push_back(RadixItem(i, p));
+ while (lower(_boxes.size() - 1, p)) {
+ extend();
+ }
+ int box = findDown(_boxes.size() - 1, p);
+ insert(box, n);
+ }
+
+ /// \brief Return the item having minimum priority.
+ ///
+ /// This function returns the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ Item top() const {
+ const_cast<RadixHeap<ItemIntMap>&>(*this).moveDown();
+ return _data[_boxes[0].first].item;
+ }
+
+ /// \brief The minimum priority.
+ ///
+ /// This function returns the minimum priority.
+ /// \pre The heap must be non-empty.
+ Prio prio() const {
+ const_cast<RadixHeap<ItemIntMap>&>(*this).moveDown();
+ return _data[_boxes[0].first].prio;
+ }
+
+ /// \brief Remove the item having minimum priority.
+ ///
+ /// This function removes the item having minimum priority.
+ /// \pre The heap must be non-empty.
+ void pop() {
+ moveDown();
+ int index = _boxes[0].first;
+ _iim[_data[index].item] = POST_HEAP;
+ remove(index);
+ relocateLast(index);
+ }
+
+ /// \brief Remove the given item from the heap.
+ ///
+ /// This function removes the given item from the heap if it is
+ /// already stored.
+ /// \param i The item to delete.
+ /// \pre \e i must be in the heap.
+ void erase(const Item &i) {
+ int index = _iim[i];
+ _iim[i] = POST_HEAP;
+ remove(index);
+ relocateLast(index);
+ }
+
+ /// \brief The priority of the given item.
+ ///
+ /// This function returns the priority of the given item.
+ /// \param i The item.
+ /// \pre \e i must be in the heap.
+ Prio operator[](const Item &i) const {
+ int idx = _iim[i];
+ return _data[idx].prio;
+ }
+
+ /// \brief Set the priority of an item or insert it, if it is
+ /// not stored in the heap.
+ ///
+ /// This method sets the priority of the given item if it is
+ /// already stored in the heap. Otherwise it inserts the given
+ /// item into the heap with the given priority.
+ /// \param i The item.
+ /// \param p The priority.
+ /// \pre \e i must be in the heap.
+ /// \warning This method may throw an \c UnderFlowPriorityException.
+ void set(const Item &i, const Prio &p) {
+ int idx = _iim[i];
+ if( idx < 0 ) {
+ push(i, p);
+ }
+ else if( p >= _data[idx].prio ) {
+ _data[idx].prio = p;
+ bubbleUp(idx);
+ } else {
+ _data[idx].prio = p;
+ bubbleDown(idx);
+ }
+ }
+
+ /// \brief Decrease the priority of an item to the given value.
+ ///
+ /// This function decreases the priority of an item to the given value.
+ /// \param i The item.
+ /// \param p The priority.
+ /// \pre \e i must be stored in the heap with priority at least \e p.
+ /// \warning This method may throw an \c UnderFlowPriorityException.
+ void decrease(const Item &i, const Prio &p) {
+ int idx = _iim[i];
+ _data[idx].prio = p;
+ bubbleDown(idx);
+ }
+
+ /// \brief Increase the priority of an item to the given value.
+ ///
+ /// This function increases the priority of an item to the given value.
+ /// \param i The item.
+ /// \param p The priority.
+ /// \pre \e i must be stored in the heap with priority at most \e p.
+ void increase(const Item &i, const Prio &p) {
+ int idx = _iim[i];
+ _data[idx].prio = p;
+ bubbleUp(idx);
+ }
+
+ /// \brief Return the state of an item.
+ ///
+ /// This method returns \c PRE_HEAP if the given item has never
+ /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
+ /// and \c POST_HEAP otherwise.
+ /// In the latter case it is possible that the item will get back
+ /// to the heap again.
+ /// \param i The item.
+ State state(const Item &i) const {
+ int s = _iim[i];
+ if( s >= 0 ) s = 0;
+ return State(s);
+ }
+
+ /// \brief Set the state of an item in the heap.
+ ///
+ /// This function sets the state of the given item in the heap.
+ /// It can be used to manually clear the heap when it is important
+ /// to achive better time complexity.
+ /// \param i The item.
+ /// \param st The state. It should not be \c IN_HEAP.
+ void state(const Item& i, State st) {
+ switch (st) {
+ case POST_HEAP:
+ case PRE_HEAP:
+ if (state(i) == IN_HEAP) {
+ erase(i);
+ }
+ _iim[i] = st;
+ break;
+ case IN_HEAP:
+ break;
+ }
+ }
+
+ }; // class RadixHeap
+
+} // namespace lemon
+
+#endif // LEMON_RADIX_HEAP_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/radix_sort.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/radix_sort.h
new file mode 100644
index 00000000000..d80875663b0
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/radix_sort.h
@@ -0,0 +1,487 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef RADIX_SORT_H
+#define RADIX_SORT_H
+
+/// \ingroup auxalg
+/// \file
+/// \brief Radix sort
+///
+/// Linear time sorting algorithms
+
+#include <vector>
+#include <limits>
+#include <iterator>
+#include <algorithm>
+
+namespace lemon {
+
+ namespace _radix_sort_bits {
+
+ template <typename Iterator>
+ bool unitRange(Iterator first, Iterator last) {
+ ++first;
+ return first == last;
+ }
+
+ template <typename Value>
+ struct Identity {
+ const Value& operator()(const Value& val) {
+ return val;
+ }
+ };
+
+
+ template <typename Value, typename Iterator, typename Functor>
+ Iterator radixSortPartition(Iterator first, Iterator last,
+ Functor functor, Value mask) {
+ while (first != last && !(functor(*first) & mask)) {
+ ++first;
+ }
+ if (first == last) {
+ return first;
+ }
+ --last;
+ while (first != last && (functor(*last) & mask)) {
+ --last;
+ }
+ if (first == last) {
+ return first;
+ }
+ std::iter_swap(first, last);
+ ++first;
+ while (true) {
+ while (!(functor(*first) & mask)) {
+ ++first;
+ }
+ --last;
+ while (functor(*last) & mask) {
+ --last;
+ }
+ if (unitRange(last, first)) {
+ return first;
+ }
+ std::iter_swap(first, last);
+ ++first;
+ }
+ }
+
+ template <typename Iterator, typename Functor>
+ Iterator radixSortSignPartition(Iterator first, Iterator last,
+ Functor functor) {
+ while (first != last && functor(*first) < 0) {
+ ++first;
+ }
+ if (first == last) {
+ return first;
+ }
+ --last;
+ while (first != last && functor(*last) >= 0) {
+ --last;
+ }
+ if (first == last) {
+ return first;
+ }
+ std::iter_swap(first, last);
+ ++first;
+ while (true) {
+ while (functor(*first) < 0) {
+ ++first;
+ }
+ --last;
+ while (functor(*last) >= 0) {
+ --last;
+ }
+ if (unitRange(last, first)) {
+ return first;
+ }
+ std::iter_swap(first, last);
+ ++first;
+ }
+ }
+
+ template <typename Value, typename Iterator, typename Functor>
+ void radixIntroSort(Iterator first, Iterator last,
+ Functor functor, Value mask) {
+ while (mask != 0 && first != last && !unitRange(first, last)) {
+ Iterator cut = radixSortPartition(first, last, functor, mask);
+ mask >>= 1;
+ radixIntroSort(first, cut, functor, mask);
+ first = cut;
+ }
+ }
+
+ template <typename Value, typename Iterator, typename Functor>
+ void radixSignedSort(Iterator first, Iterator last, Functor functor) {
+
+ Iterator cut = radixSortSignPartition(first, last, functor);
+
+ Value mask;
+ int max_digit;
+ Iterator it;
+
+ mask = ~0; max_digit = 0;
+ for (it = first; it != cut; ++it) {
+ while ((mask & functor(*it)) != mask) {
+ ++max_digit;
+ mask <<= 1;
+ }
+ }
+ radixIntroSort(first, cut, functor, 1 << max_digit);
+
+ mask = 0; max_digit = 0;
+ for (it = cut; it != last; ++it) {
+ while ((mask | functor(*it)) != mask) {
+ ++max_digit;
+ mask <<= 1; mask |= 1;
+ }
+ }
+ radixIntroSort(cut, last, functor, 1 << max_digit);
+ }
+
+ template <typename Value, typename Iterator, typename Functor>
+ void radixUnsignedSort(Iterator first, Iterator last, Functor functor) {
+
+ Value mask = 0;
+ int max_digit = 0;
+
+ Iterator it;
+ for (it = first; it != last; ++it) {
+ while ((mask | functor(*it)) != mask) {
+ ++max_digit;
+ mask <<= 1; mask |= 1;
+ }
+ }
+ radixIntroSort(first, last, functor, 1 << max_digit);
+ }
+
+
+ template <typename Value,
+ bool sign = std::numeric_limits<Value>::is_signed >
+ struct RadixSortSelector {
+ template <typename Iterator, typename Functor>
+ static void sort(Iterator first, Iterator last, Functor functor) {
+ radixSignedSort<Value>(first, last, functor);
+ }
+ };
+
+ template <typename Value>
+ struct RadixSortSelector<Value, false> {
+ template <typename Iterator, typename Functor>
+ static void sort(Iterator first, Iterator last, Functor functor) {
+ radixUnsignedSort<Value>(first, last, functor);
+ }
+ };
+
+ }
+
+ /// \ingroup auxalg
+ ///
+ /// \brief Sorts the STL compatible range into ascending order.
+ ///
+ /// The \c radixSort sorts an STL compatible range into ascending
+ /// order. The radix sort algorithm can sort items which are mapped
+ /// to integers with an adaptable unary function \c functor and the
+ /// order will be ascending according to these mapped values.
+ ///
+ /// It is also possible to use a normal function instead
+ /// of the functor object. If the functor is not given it will use
+ /// the identity function instead.
+ ///
+ /// This is a special quick sort algorithm where the pivot
+ /// values to split the items are choosen to be 2<sup>k</sup>
+ /// for each \c k.
+ /// Therefore, the time complexity of the algorithm is O(log(c)*n) and
+ /// it uses O(log(c)) additional space, where \c c is the maximal value
+ /// and \c n is the number of the items in the container.
+ ///
+ /// \param first The begin of the given range.
+ /// \param last The end of the given range.
+ /// \param functor An adaptible unary function or a normal function
+ /// which maps the items to any integer type which can be either
+ /// signed or unsigned.
+ ///
+ /// \sa stableRadixSort()
+ template <typename Iterator, typename Functor>
+ void radixSort(Iterator first, Iterator last, Functor functor) {
+ using namespace _radix_sort_bits;
+ typedef typename Functor::result_type Value;
+ RadixSortSelector<Value>::sort(first, last, functor);
+ }
+
+ template <typename Iterator, typename Value, typename Key>
+ void radixSort(Iterator first, Iterator last, Value (*functor)(Key)) {
+ using namespace _radix_sort_bits;
+ RadixSortSelector<Value>::sort(first, last, functor);
+ }
+
+ template <typename Iterator, typename Value, typename Key>
+ void radixSort(Iterator first, Iterator last, Value& (*functor)(Key)) {
+ using namespace _radix_sort_bits;
+ RadixSortSelector<Value>::sort(first, last, functor);
+ }
+
+ template <typename Iterator, typename Value, typename Key>
+ void radixSort(Iterator first, Iterator last, Value (*functor)(Key&)) {
+ using namespace _radix_sort_bits;
+ RadixSortSelector<Value>::sort(first, last, functor);
+ }
+
+ template <typename Iterator, typename Value, typename Key>
+ void radixSort(Iterator first, Iterator last, Value& (*functor)(Key&)) {
+ using namespace _radix_sort_bits;
+ RadixSortSelector<Value>::sort(first, last, functor);
+ }
+
+ template <typename Iterator>
+ void radixSort(Iterator first, Iterator last) {
+ using namespace _radix_sort_bits;
+ typedef typename std::iterator_traits<Iterator>::value_type Value;
+ RadixSortSelector<Value>::sort(first, last, Identity<Value>());
+ }
+
+ namespace _radix_sort_bits {
+
+ template <typename Value>
+ unsigned char valueByte(Value value, int byte) {
+ return value >> (std::numeric_limits<unsigned char>::digits * byte);
+ }
+
+ template <typename Functor, typename Key>
+ void stableRadixIntroSort(Key *first, Key *last, Key *target,
+ int byte, Functor functor) {
+ const int size =
+ unsigned(std::numeric_limits<unsigned char>::max()) + 1;
+ std::vector<int> counter(size);
+ for (int i = 0; i < size; ++i) {
+ counter[i] = 0;
+ }
+ Key *it = first;
+ while (first != last) {
+ ++counter[valueByte(functor(*first), byte)];
+ ++first;
+ }
+ int prev, num = 0;
+ for (int i = 0; i < size; ++i) {
+ prev = num;
+ num += counter[i];
+ counter[i] = prev;
+ }
+ while (it != last) {
+ target[counter[valueByte(functor(*it), byte)]++] = *it;
+ ++it;
+ }
+ }
+
+ template <typename Functor, typename Key>
+ void signedStableRadixIntroSort(Key *first, Key *last, Key *target,
+ int byte, Functor functor) {
+ const int size =
+ unsigned(std::numeric_limits<unsigned char>::max()) + 1;
+ std::vector<int> counter(size);
+ for (int i = 0; i < size; ++i) {
+ counter[i] = 0;
+ }
+ Key *it = first;
+ while (first != last) {
+ counter[valueByte(functor(*first), byte)]++;
+ ++first;
+ }
+ int prev, num = 0;
+ for (int i = size / 2; i < size; ++i) {
+ prev = num;
+ num += counter[i];
+ counter[i] = prev;
+ }
+ for (int i = 0; i < size / 2; ++i) {
+ prev = num;
+ num += counter[i];
+ counter[i] = prev;
+ }
+ while (it != last) {
+ target[counter[valueByte(functor(*it), byte)]++] = *it;
+ ++it;
+ }
+ }
+
+
+ template <typename Value, typename Iterator, typename Functor>
+ void stableRadixSignedSort(Iterator first, Iterator last, Functor functor) {
+ if (first == last) return;
+ typedef typename std::iterator_traits<Iterator>::value_type Key;
+ typedef std::allocator<Key> Allocator;
+ Allocator allocator;
+
+ int length = std::distance(first, last);
+ Key* buffer = allocator.allocate(2 * length);
+ try {
+ bool dir = true;
+ std::copy(first, last, buffer);
+ for (int i = 0; i < int(sizeof(Value)) - 1; ++i) {
+ if (dir) {
+ stableRadixIntroSort(buffer, buffer + length, buffer + length,
+ i, functor);
+ } else {
+ stableRadixIntroSort(buffer + length, buffer + 2 * length, buffer,
+ i, functor);
+ }
+ dir = !dir;
+ }
+ if (dir) {
+ signedStableRadixIntroSort(buffer, buffer + length, buffer + length,
+ sizeof(Value) - 1, functor);
+ std::copy(buffer + length, buffer + 2 * length, first);
+ } else {
+ signedStableRadixIntroSort(buffer + length, buffer + 2 * length,
+ buffer, sizeof(Value) - 1, functor);
+ std::copy(buffer, buffer + length, first);
+ }
+ } catch (...) {
+ allocator.deallocate(buffer, 2 * length);
+ throw;
+ }
+ allocator.deallocate(buffer, 2 * length);
+ }
+
+ template <typename Value, typename Iterator, typename Functor>
+ void stableRadixUnsignedSort(Iterator first, Iterator last,
+ Functor functor) {
+ if (first == last) return;
+ typedef typename std::iterator_traits<Iterator>::value_type Key;
+ typedef std::allocator<Key> Allocator;
+ Allocator allocator;
+
+ int length = std::distance(first, last);
+ Key *buffer = allocator.allocate(2 * length);
+ try {
+ bool dir = true;
+ std::copy(first, last, buffer);
+ for (int i = 0; i < int(sizeof(Value)); ++i) {
+ if (dir) {
+ stableRadixIntroSort(buffer, buffer + length,
+ buffer + length, i, functor);
+ } else {
+ stableRadixIntroSort(buffer + length, buffer + 2 * length,
+ buffer, i, functor);
+ }
+ dir = !dir;
+ }
+ if (dir) {
+ std::copy(buffer, buffer + length, first);
+ } else {
+ std::copy(buffer + length, buffer + 2 * length, first);
+ }
+ } catch (...) {
+ allocator.deallocate(buffer, 2 * length);
+ throw;
+ }
+ allocator.deallocate(buffer, 2 * length);
+ }
+
+
+
+ template <typename Value,
+ bool sign = std::numeric_limits<Value>::is_signed >
+ struct StableRadixSortSelector {
+ template <typename Iterator, typename Functor>
+ static void sort(Iterator first, Iterator last, Functor functor) {
+ stableRadixSignedSort<Value>(first, last, functor);
+ }
+ };
+
+ template <typename Value>
+ struct StableRadixSortSelector<Value, false> {
+ template <typename Iterator, typename Functor>
+ static void sort(Iterator first, Iterator last, Functor functor) {
+ stableRadixUnsignedSort<Value>(first, last, functor);
+ }
+ };
+
+ }
+
+ /// \ingroup auxalg
+ ///
+ /// \brief Sorts the STL compatible range into ascending order in a stable
+ /// way.
+ ///
+ /// This function sorts an STL compatible range into ascending
+ /// order according to an integer mapping in the same as radixSort() does.
+ ///
+ /// This sorting algorithm is stable, i.e. the order of two equal
+ /// elements remains the same after the sorting.
+ ///
+ /// This sort algorithm use a radix forward sort on the
+ /// bytes of the integer number. The algorithm sorts the items
+ /// byte-by-byte. First, it counts how many times a byte value occurs
+ /// in the container, then it copies the corresponding items to
+ /// another container in asceding order in O(n) time.
+ ///
+ /// The time complexity of the algorithm is O(log(c)*n) and
+ /// it uses O(n) additional space, where \c c is the
+ /// maximal value and \c n is the number of the items in the
+ /// container.
+ ///
+
+ /// \param first The begin of the given range.
+ /// \param last The end of the given range.
+ /// \param functor An adaptible unary function or a normal function
+ /// which maps the items to any integer type which can be either
+ /// signed or unsigned.
+ /// \sa radixSort()
+ template <typename Iterator, typename Functor>
+ void stableRadixSort(Iterator first, Iterator last, Functor functor) {
+ using namespace _radix_sort_bits;
+ typedef typename Functor::result_type Value;
+ StableRadixSortSelector<Value>::sort(first, last, functor);
+ }
+
+ template <typename Iterator, typename Value, typename Key>
+ void stableRadixSort(Iterator first, Iterator last, Value (*functor)(Key)) {
+ using namespace _radix_sort_bits;
+ StableRadixSortSelector<Value>::sort(first, last, functor);
+ }
+
+ template <typename Iterator, typename Value, typename Key>
+ void stableRadixSort(Iterator first, Iterator last, Value& (*functor)(Key)) {
+ using namespace _radix_sort_bits;
+ StableRadixSortSelector<Value>::sort(first, last, functor);
+ }
+
+ template <typename Iterator, typename Value, typename Key>
+ void stableRadixSort(Iterator first, Iterator last, Value (*functor)(Key&)) {
+ using namespace _radix_sort_bits;
+ StableRadixSortSelector<Value>::sort(first, last, functor);
+ }
+
+ template <typename Iterator, typename Value, typename Key>
+ void stableRadixSort(Iterator first, Iterator last, Value& (*functor)(Key&)) {
+ using namespace _radix_sort_bits;
+ StableRadixSortSelector<Value>::sort(first, last, functor);
+ }
+
+ template <typename Iterator>
+ void stableRadixSort(Iterator first, Iterator last) {
+ using namespace _radix_sort_bits;
+ typedef typename std::iterator_traits<Iterator>::value_type Value;
+ StableRadixSortSelector<Value>::sort(first, last, Identity<Value>());
+ }
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/random.cc b/extern/quadriflow/3rd/lemon-1.3.1/lemon/random.cc
new file mode 100644
index 00000000000..02951210bdf
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/random.cc
@@ -0,0 +1,29 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\file
+///\brief Instantiation of the Random class.
+
+#include <lemon/random.h>
+
+namespace lemon {
+ /// \brief Global random number generator instance
+ ///
+ /// A global Mersenne Twister random number generator instance.
+ Random rnd;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/random.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/random.h
new file mode 100644
index 00000000000..8de74ede8a9
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/random.h
@@ -0,0 +1,1005 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+/*
+ * This file contains the reimplemented version of the Mersenne Twister
+ * Generator of Matsumoto and Nishimura.
+ *
+ * See the appropriate copyright notice below.
+ *
+ * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The names of its contributors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Any feedback is very welcome.
+ * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
+ * email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
+ */
+
+#ifndef LEMON_RANDOM_H
+#define LEMON_RANDOM_H
+
+#include <algorithm>
+#include <iterator>
+#include <vector>
+#include <limits>
+#include <fstream>
+
+#include <lemon/math.h>
+#include <lemon/dim2.h>
+
+#ifndef WIN32
+#include <sys/time.h>
+#include <ctime>
+#include <sys/types.h>
+#include <unistd.h>
+#else
+#include <lemon/bits/windows.h>
+#endif
+
+///\ingroup misc
+///\file
+///\brief Mersenne Twister random number generator
+
+namespace lemon {
+
+ namespace _random_bits {
+
+ template <typename _Word, int _bits = std::numeric_limits<_Word>::digits>
+ struct RandomTraits {};
+
+ template <typename _Word>
+ struct RandomTraits<_Word, 32> {
+
+ typedef _Word Word;
+ static const int bits = 32;
+
+ static const int length = 624;
+ static const int shift = 397;
+
+ static const Word mul = 0x6c078965u;
+ static const Word arrayInit = 0x012BD6AAu;
+ static const Word arrayMul1 = 0x0019660Du;
+ static const Word arrayMul2 = 0x5D588B65u;
+
+ static const Word mask = 0x9908B0DFu;
+ static const Word loMask = (1u << 31) - 1;
+ static const Word hiMask = ~loMask;
+
+
+ static Word tempering(Word rnd) {
+ rnd ^= (rnd >> 11);
+ rnd ^= (rnd << 7) & 0x9D2C5680u;
+ rnd ^= (rnd << 15) & 0xEFC60000u;
+ rnd ^= (rnd >> 18);
+ return rnd;
+ }
+
+ };
+
+ template <typename _Word>
+ struct RandomTraits<_Word, 64> {
+
+ typedef _Word Word;
+ static const int bits = 64;
+
+ static const int length = 312;
+ static const int shift = 156;
+
+ static const Word mul = Word(0x5851F42Du) << 32 | Word(0x4C957F2Du);
+ static const Word arrayInit = Word(0x00000000u) << 32 |Word(0x012BD6AAu);
+ static const Word arrayMul1 = Word(0x369DEA0Fu) << 32 |Word(0x31A53F85u);
+ static const Word arrayMul2 = Word(0x27BB2EE6u) << 32 |Word(0x87B0B0FDu);
+
+ static const Word mask = Word(0xB5026F5Au) << 32 | Word(0xA96619E9u);
+ static const Word loMask = (Word(1u) << 31) - 1;
+ static const Word hiMask = ~loMask;
+
+ static Word tempering(Word rnd) {
+ rnd ^= (rnd >> 29) & (Word(0x55555555u) << 32 | Word(0x55555555u));
+ rnd ^= (rnd << 17) & (Word(0x71D67FFFu) << 32 | Word(0xEDA60000u));
+ rnd ^= (rnd << 37) & (Word(0xFFF7EEE0u) << 32 | Word(0x00000000u));
+ rnd ^= (rnd >> 43);
+ return rnd;
+ }
+
+ };
+
+ template <typename _Word>
+ class RandomCore {
+ public:
+
+ typedef _Word Word;
+
+ private:
+
+ static const int bits = RandomTraits<Word>::bits;
+
+ static const int length = RandomTraits<Word>::length;
+ static const int shift = RandomTraits<Word>::shift;
+
+ public:
+
+ void initState() {
+ static const Word seedArray[4] = {
+ 0x12345u, 0x23456u, 0x34567u, 0x45678u
+ };
+
+ initState(seedArray, seedArray + 4);
+ }
+
+ void initState(Word seed) {
+
+ static const Word mul = RandomTraits<Word>::mul;
+
+ current = state;
+
+ Word *curr = state + length - 1;
+ curr[0] = seed; --curr;
+ for (int i = 1; i < length; ++i) {
+ curr[0] = (mul * ( curr[1] ^ (curr[1] >> (bits - 2)) ) + i);
+ --curr;
+ }
+ }
+
+ template <typename Iterator>
+ void initState(Iterator begin, Iterator end) {
+
+ static const Word init = RandomTraits<Word>::arrayInit;
+ static const Word mul1 = RandomTraits<Word>::arrayMul1;
+ static const Word mul2 = RandomTraits<Word>::arrayMul2;
+
+
+ Word *curr = state + length - 1; --curr;
+ Iterator it = begin; int cnt = 0;
+ int num;
+
+ initState(init);
+
+ num = length > end - begin ? length : end - begin;
+ while (num--) {
+ curr[0] = (curr[0] ^ ((curr[1] ^ (curr[1] >> (bits - 2))) * mul1))
+ + *it + cnt;
+ ++it; ++cnt;
+ if (it == end) {
+ it = begin; cnt = 0;
+ }
+ if (curr == state) {
+ curr = state + length - 1; curr[0] = state[0];
+ }
+ --curr;
+ }
+
+ num = length - 1; cnt = length - (curr - state) - 1;
+ while (num--) {
+ curr[0] = (curr[0] ^ ((curr[1] ^ (curr[1] >> (bits - 2))) * mul2))
+ - cnt;
+ --curr; ++cnt;
+ if (curr == state) {
+ curr = state + length - 1; curr[0] = state[0]; --curr;
+ cnt = 1;
+ }
+ }
+
+ state[length - 1] = Word(1) << (bits - 1);
+ }
+
+ void copyState(const RandomCore& other) {
+ std::copy(other.state, other.state + length, state);
+ current = state + (other.current - other.state);
+ }
+
+ Word operator()() {
+ if (current == state) fillState();
+ --current;
+ Word rnd = *current;
+ return RandomTraits<Word>::tempering(rnd);
+ }
+
+ private:
+
+
+ void fillState() {
+ static const Word mask[2] = { 0x0ul, RandomTraits<Word>::mask };
+ static const Word loMask = RandomTraits<Word>::loMask;
+ static const Word hiMask = RandomTraits<Word>::hiMask;
+
+ current = state + length;
+
+ register Word *curr = state + length - 1;
+ register long num;
+
+ num = length - shift;
+ while (num--) {
+ curr[0] = (((curr[0] & hiMask) | (curr[-1] & loMask)) >> 1) ^
+ curr[- shift] ^ mask[curr[-1] & 1ul];
+ --curr;
+ }
+ num = shift - 1;
+ while (num--) {
+ curr[0] = (((curr[0] & hiMask) | (curr[-1] & loMask)) >> 1) ^
+ curr[length - shift] ^ mask[curr[-1] & 1ul];
+ --curr;
+ }
+ state[0] = (((state[0] & hiMask) | (curr[length - 1] & loMask)) >> 1) ^
+ curr[length - shift] ^ mask[curr[length - 1] & 1ul];
+
+ }
+
+
+ Word *current;
+ Word state[length];
+
+ };
+
+
+ template <typename Result,
+ int shift = (std::numeric_limits<Result>::digits + 1) / 2>
+ struct Masker {
+ static Result mask(const Result& result) {
+ return Masker<Result, (shift + 1) / 2>::
+ mask(static_cast<Result>(result | (result >> shift)));
+ }
+ };
+
+ template <typename Result>
+ struct Masker<Result, 1> {
+ static Result mask(const Result& result) {
+ return static_cast<Result>(result | (result >> 1));
+ }
+ };
+
+ template <typename Result, typename Word,
+ int rest = std::numeric_limits<Result>::digits, int shift = 0,
+ bool last = rest <= std::numeric_limits<Word>::digits>
+ struct IntConversion {
+ static const int bits = std::numeric_limits<Word>::digits;
+
+ static Result convert(RandomCore<Word>& rnd) {
+ return static_cast<Result>(rnd() >> (bits - rest)) << shift;
+ }
+
+ };
+
+ template <typename Result, typename Word, int rest, int shift>
+ struct IntConversion<Result, Word, rest, shift, false> {
+ static const int bits = std::numeric_limits<Word>::digits;
+
+ static Result convert(RandomCore<Word>& rnd) {
+ return (static_cast<Result>(rnd()) << shift) |
+ IntConversion<Result, Word, rest - bits, shift + bits>::convert(rnd);
+ }
+ };
+
+
+ template <typename Result, typename Word,
+ bool one_word = (std::numeric_limits<Word>::digits <
+ std::numeric_limits<Result>::digits) >
+ struct Mapping {
+ static Result map(RandomCore<Word>& rnd, const Result& bound) {
+ Word max = Word(bound - 1);
+ Result mask = Masker<Result>::mask(bound - 1);
+ Result num;
+ do {
+ num = IntConversion<Result, Word>::convert(rnd) & mask;
+ } while (num > max);
+ return num;
+ }
+ };
+
+ template <typename Result, typename Word>
+ struct Mapping<Result, Word, false> {
+ static Result map(RandomCore<Word>& rnd, const Result& bound) {
+ Word max = Word(bound - 1);
+ Word mask = Masker<Word, (std::numeric_limits<Result>::digits + 1) / 2>
+ ::mask(max);
+ Word num;
+ do {
+ num = rnd() & mask;
+ } while (num > max);
+ return num;
+ }
+ };
+
+ template <typename Result, int exp>
+ struct ShiftMultiplier {
+ static const Result multiplier() {
+ Result res = ShiftMultiplier<Result, exp / 2>::multiplier();
+ res *= res;
+ if ((exp & 1) == 1) res *= static_cast<Result>(0.5);
+ return res;
+ }
+ };
+
+ template <typename Result>
+ struct ShiftMultiplier<Result, 0> {
+ static const Result multiplier() {
+ return static_cast<Result>(1.0);
+ }
+ };
+
+ template <typename Result>
+ struct ShiftMultiplier<Result, 20> {
+ static const Result multiplier() {
+ return static_cast<Result>(1.0/1048576.0);
+ }
+ };
+
+ template <typename Result>
+ struct ShiftMultiplier<Result, 32> {
+ static const Result multiplier() {
+ return static_cast<Result>(1.0/4294967296.0);
+ }
+ };
+
+ template <typename Result>
+ struct ShiftMultiplier<Result, 53> {
+ static const Result multiplier() {
+ return static_cast<Result>(1.0/9007199254740992.0);
+ }
+ };
+
+ template <typename Result>
+ struct ShiftMultiplier<Result, 64> {
+ static const Result multiplier() {
+ return static_cast<Result>(1.0/18446744073709551616.0);
+ }
+ };
+
+ template <typename Result, int exp>
+ struct Shifting {
+ static Result shift(const Result& result) {
+ return result * ShiftMultiplier<Result, exp>::multiplier();
+ }
+ };
+
+ template <typename Result, typename Word,
+ int rest = std::numeric_limits<Result>::digits, int shift = 0,
+ bool last = rest <= std::numeric_limits<Word>::digits>
+ struct RealConversion{
+ static const int bits = std::numeric_limits<Word>::digits;
+
+ static Result convert(RandomCore<Word>& rnd) {
+ return Shifting<Result, shift + rest>::
+ shift(static_cast<Result>(rnd() >> (bits - rest)));
+ }
+ };
+
+ template <typename Result, typename Word, int rest, int shift>
+ struct RealConversion<Result, Word, rest, shift, false> {
+ static const int bits = std::numeric_limits<Word>::digits;
+
+ static Result convert(RandomCore<Word>& rnd) {
+ return Shifting<Result, shift + bits>::
+ shift(static_cast<Result>(rnd())) +
+ RealConversion<Result, Word, rest-bits, shift + bits>::
+ convert(rnd);
+ }
+ };
+
+ template <typename Result, typename Word>
+ struct Initializer {
+
+ template <typename Iterator>
+ static void init(RandomCore<Word>& rnd, Iterator begin, Iterator end) {
+ std::vector<Word> ws;
+ for (Iterator it = begin; it != end; ++it) {
+ ws.push_back(Word(*it));
+ }
+ rnd.initState(ws.begin(), ws.end());
+ }
+
+ static void init(RandomCore<Word>& rnd, Result seed) {
+ rnd.initState(seed);
+ }
+ };
+
+ template <typename Word>
+ struct BoolConversion {
+ static bool convert(RandomCore<Word>& rnd) {
+ return (rnd() & 1) == 1;
+ }
+ };
+
+ template <typename Word>
+ struct BoolProducer {
+ Word buffer;
+ int num;
+
+ BoolProducer() : num(0) {}
+
+ bool convert(RandomCore<Word>& rnd) {
+ if (num == 0) {
+ buffer = rnd();
+ num = RandomTraits<Word>::bits;
+ }
+ bool r = (buffer & 1);
+ buffer >>= 1;
+ --num;
+ return r;
+ }
+ };
+
+ }
+
+ /// \ingroup misc
+ ///
+ /// \brief Mersenne Twister random number generator
+ ///
+ /// The Mersenne Twister is a twisted generalized feedback
+ /// shift-register generator of Matsumoto and Nishimura. The period
+ /// of this generator is \f$ 2^{19937} - 1 \f$ and it is
+ /// equi-distributed in 623 dimensions for 32-bit numbers. The time
+ /// performance of this generator is comparable to the commonly used
+ /// generators.
+ ///
+ /// This implementation is specialized for both 32-bit and 64-bit
+ /// architectures. The generators differ sligthly in the
+ /// initialization and generation phase so they produce two
+ /// completly different sequences.
+ ///
+ /// The generator gives back random numbers of serveral types. To
+ /// get a random number from a range of a floating point type you
+ /// can use one form of the \c operator() or the \c real() member
+ /// function. If you want to get random number from the {0, 1, ...,
+ /// n-1} integer range use the \c operator[] or the \c integer()
+ /// method. And to get random number from the whole range of an
+ /// integer type you can use the argumentless \c integer() or \c
+ /// uinteger() functions. After all you can get random bool with
+ /// equal chance of true and false or given probability of true
+ /// result with the \c boolean() member functions.
+ ///
+ ///\code
+ /// // The commented code is identical to the other
+ /// double a = rnd(); // [0.0, 1.0)
+ /// // double a = rnd.real(); // [0.0, 1.0)
+ /// double b = rnd(100.0); // [0.0, 100.0)
+ /// // double b = rnd.real(100.0); // [0.0, 100.0)
+ /// double c = rnd(1.0, 2.0); // [1.0, 2.0)
+ /// // double c = rnd.real(1.0, 2.0); // [1.0, 2.0)
+ /// int d = rnd[100000]; // 0..99999
+ /// // int d = rnd.integer(100000); // 0..99999
+ /// int e = rnd[6] + 1; // 1..6
+ /// // int e = rnd.integer(1, 1 + 6); // 1..6
+ /// int b = rnd.uinteger<int>(); // 0 .. 2^31 - 1
+ /// int c = rnd.integer<int>(); // - 2^31 .. 2^31 - 1
+ /// bool g = rnd.boolean(); // P(g = true) = 0.5
+ /// bool h = rnd.boolean(0.8); // P(h = true) = 0.8
+ ///\endcode
+ ///
+ /// LEMON provides a global instance of the random number
+ /// generator which name is \ref lemon::rnd "rnd". Usually it is a
+ /// good programming convenience to use this global generator to get
+ /// random numbers.
+ class Random {
+ private:
+
+ // Architecture word
+ typedef unsigned long Word;
+
+ _random_bits::RandomCore<Word> core;
+ _random_bits::BoolProducer<Word> bool_producer;
+
+
+ public:
+
+ ///\name Initialization
+ ///
+ /// @{
+
+ /// \brief Default constructor
+ ///
+ /// Constructor with constant seeding.
+ Random() { core.initState(); }
+
+ /// \brief Constructor with seed
+ ///
+ /// Constructor with seed. The current number type will be converted
+ /// to the architecture word type.
+ template <typename Number>
+ Random(Number seed) {
+ _random_bits::Initializer<Number, Word>::init(core, seed);
+ }
+
+ /// \brief Constructor with array seeding
+ ///
+ /// Constructor with array seeding. The given range should contain
+ /// any number type and the numbers will be converted to the
+ /// architecture word type.
+ template <typename Iterator>
+ Random(Iterator begin, Iterator end) {
+ typedef typename std::iterator_traits<Iterator>::value_type Number;
+ _random_bits::Initializer<Number, Word>::init(core, begin, end);
+ }
+
+ /// \brief Copy constructor
+ ///
+ /// Copy constructor. The generated sequence will be identical to
+ /// the other sequence. It can be used to save the current state
+ /// of the generator and later use it to generate the same
+ /// sequence.
+ Random(const Random& other) {
+ core.copyState(other.core);
+ }
+
+ /// \brief Assign operator
+ ///
+ /// Assign operator. The generated sequence will be identical to
+ /// the other sequence. It can be used to save the current state
+ /// of the generator and later use it to generate the same
+ /// sequence.
+ Random& operator=(const Random& other) {
+ if (&other != this) {
+ core.copyState(other.core);
+ }
+ return *this;
+ }
+
+ /// \brief Seeding random sequence
+ ///
+ /// Seeding the random sequence. The current number type will be
+ /// converted to the architecture word type.
+ template <typename Number>
+ void seed(Number seed) {
+ _random_bits::Initializer<Number, Word>::init(core, seed);
+ }
+
+ /// \brief Seeding random sequence
+ ///
+ /// Seeding the random sequence. The given range should contain
+ /// any number type and the numbers will be converted to the
+ /// architecture word type.
+ template <typename Iterator>
+ void seed(Iterator begin, Iterator end) {
+ typedef typename std::iterator_traits<Iterator>::value_type Number;
+ _random_bits::Initializer<Number, Word>::init(core, begin, end);
+ }
+
+ /// \brief Seeding from file or from process id and time
+ ///
+ /// By default, this function calls the \c seedFromFile() member
+ /// function with the <tt>/dev/urandom</tt> file. If it does not success,
+ /// it uses the \c seedFromTime().
+ /// \return Currently always \c true.
+ bool seed() {
+#ifndef WIN32
+ if (seedFromFile("/dev/urandom", 0)) return true;
+#endif
+ if (seedFromTime()) return true;
+ return false;
+ }
+
+ /// \brief Seeding from file
+ ///
+ /// Seeding the random sequence from file. The linux kernel has two
+ /// devices, <tt>/dev/random</tt> and <tt>/dev/urandom</tt> which
+ /// could give good seed values for pseudo random generators (The
+ /// difference between two devices is that the <tt>random</tt> may
+ /// block the reading operation while the kernel can give good
+ /// source of randomness, while the <tt>urandom</tt> does not
+ /// block the input, but it could give back bytes with worse
+ /// entropy).
+ /// \param file The source file
+ /// \param offset The offset, from the file read.
+ /// \return \c true when the seeding successes.
+#ifndef WIN32
+ bool seedFromFile(const std::string& file = "/dev/urandom", int offset = 0)
+#else
+ bool seedFromFile(const std::string& file = "", int offset = 0)
+#endif
+ {
+ std::ifstream rs(file.c_str());
+ const int size = 4;
+ Word buf[size];
+ if (offset != 0 && !rs.seekg(offset)) return false;
+ if (!rs.read(reinterpret_cast<char*>(buf), sizeof(buf))) return false;
+ seed(buf, buf + size);
+ return true;
+ }
+
+ /// \brief Seding from process id and time
+ ///
+ /// Seding from process id and time. This function uses the
+ /// current process id and the current time for initialize the
+ /// random sequence.
+ /// \return Currently always \c true.
+ bool seedFromTime() {
+#ifndef WIN32
+ timeval tv;
+ gettimeofday(&tv, 0);
+ seed(getpid() + tv.tv_sec + tv.tv_usec);
+#else
+ seed(bits::getWinRndSeed());
+#endif
+ return true;
+ }
+
+ /// @}
+
+ ///\name Uniform Distributions
+ ///
+ /// @{
+
+ /// \brief Returns a random real number from the range [0, 1)
+ ///
+ /// It returns a random real number from the range [0, 1). The
+ /// default Number type is \c double.
+ template <typename Number>
+ Number real() {
+ return _random_bits::RealConversion<Number, Word>::convert(core);
+ }
+
+ double real() {
+ return real<double>();
+ }
+
+ /// \brief Returns a random real number from the range [0, 1)
+ ///
+ /// It returns a random double from the range [0, 1).
+ double operator()() {
+ return real<double>();
+ }
+
+ /// \brief Returns a random real number from the range [0, b)
+ ///
+ /// It returns a random real number from the range [0, b).
+ double operator()(double b) {
+ return real<double>() * b;
+ }
+
+ /// \brief Returns a random real number from the range [a, b)
+ ///
+ /// It returns a random real number from the range [a, b).
+ double operator()(double a, double b) {
+ return real<double>() * (b - a) + a;
+ }
+
+ /// \brief Returns a random integer from a range
+ ///
+ /// It returns a random integer from the range {0, 1, ..., b - 1}.
+ template <typename Number>
+ Number integer(Number b) {
+ return _random_bits::Mapping<Number, Word>::map(core, b);
+ }
+
+ /// \brief Returns a random integer from a range
+ ///
+ /// It returns a random integer from the range {a, a + 1, ..., b - 1}.
+ template <typename Number>
+ Number integer(Number a, Number b) {
+ return _random_bits::Mapping<Number, Word>::map(core, b - a) + a;
+ }
+
+ /// \brief Returns a random integer from a range
+ ///
+ /// It returns a random integer from the range {0, 1, ..., b - 1}.
+ template <typename Number>
+ Number operator[](Number b) {
+ return _random_bits::Mapping<Number, Word>::map(core, b);
+ }
+
+ /// \brief Returns a random non-negative integer
+ ///
+ /// It returns a random non-negative integer uniformly from the
+ /// whole range of the current \c Number type. The default result
+ /// type of this function is <tt>unsigned int</tt>.
+ template <typename Number>
+ Number uinteger() {
+ return _random_bits::IntConversion<Number, Word>::convert(core);
+ }
+
+ unsigned int uinteger() {
+ return uinteger<unsigned int>();
+ }
+
+ /// \brief Returns a random integer
+ ///
+ /// It returns a random integer uniformly from the whole range of
+ /// the current \c Number type. The default result type of this
+ /// function is \c int.
+ template <typename Number>
+ Number integer() {
+ static const int nb = std::numeric_limits<Number>::digits +
+ (std::numeric_limits<Number>::is_signed ? 1 : 0);
+ return _random_bits::IntConversion<Number, Word, nb>::convert(core);
+ }
+
+ int integer() {
+ return integer<int>();
+ }
+
+ /// \brief Returns a random bool
+ ///
+ /// It returns a random bool. The generator holds a buffer for
+ /// random bits. Every time when it become empty the generator makes
+ /// a new random word and fill the buffer up.
+ bool boolean() {
+ return bool_producer.convert(core);
+ }
+
+ /// @}
+
+ ///\name Non-uniform Distributions
+ ///
+ ///@{
+
+ /// \brief Returns a random bool with given probability of true result.
+ ///
+ /// It returns a random bool with given probability of true result.
+ bool boolean(double p) {
+ return operator()() < p;
+ }
+
+ /// Standard normal (Gauss) distribution
+
+ /// Standard normal (Gauss) distribution.
+ /// \note The Cartesian form of the Box-Muller
+ /// transformation is used to generate a random normal distribution.
+ double gauss()
+ {
+ double V1,V2,S;
+ do {
+ V1=2*real<double>()-1;
+ V2=2*real<double>()-1;
+ S=V1*V1+V2*V2;
+ } while(S>=1);
+ return std::sqrt(-2*std::log(S)/S)*V1;
+ }
+ /// Normal (Gauss) distribution with given mean and standard deviation
+
+ /// Normal (Gauss) distribution with given mean and standard deviation.
+ /// \sa gauss()
+ double gauss(double mean,double std_dev)
+ {
+ return gauss()*std_dev+mean;
+ }
+
+ /// Lognormal distribution
+
+ /// Lognormal distribution. The parameters are the mean and the standard
+ /// deviation of <tt>exp(X)</tt>.
+ ///
+ double lognormal(double n_mean,double n_std_dev)
+ {
+ return std::exp(gauss(n_mean,n_std_dev));
+ }
+ /// Lognormal distribution
+
+ /// Lognormal distribution. The parameter is an <tt>std::pair</tt> of
+ /// the mean and the standard deviation of <tt>exp(X)</tt>.
+ ///
+ double lognormal(const std::pair<double,double> &params)
+ {
+ return std::exp(gauss(params.first,params.second));
+ }
+ /// Compute the lognormal parameters from mean and standard deviation
+
+ /// This function computes the lognormal parameters from mean and
+ /// standard deviation. The return value can direcly be passed to
+ /// lognormal().
+ std::pair<double,double> lognormalParamsFromMD(double mean,
+ double std_dev)
+ {
+ double fr=std_dev/mean;
+ fr*=fr;
+ double lg=std::log(1+fr);
+ return std::pair<double,double>(std::log(mean)-lg/2.0,std::sqrt(lg));
+ }
+ /// Lognormal distribution with given mean and standard deviation
+
+ /// Lognormal distribution with given mean and standard deviation.
+ ///
+ double lognormalMD(double mean,double std_dev)
+ {
+ return lognormal(lognormalParamsFromMD(mean,std_dev));
+ }
+
+ /// Exponential distribution with given mean
+
+ /// This function generates an exponential distribution random number
+ /// with mean <tt>1/lambda</tt>.
+ ///
+ double exponential(double lambda=1.0)
+ {
+ return -std::log(1.0-real<double>())/lambda;
+ }
+
+ /// Gamma distribution with given integer shape
+
+ /// This function generates a gamma distribution random number.
+ ///
+ ///\param k shape parameter (<tt>k>0</tt> integer)
+ double gamma(int k)
+ {
+ double s = 0;
+ for(int i=0;i<k;i++) s-=std::log(1.0-real<double>());
+ return s;
+ }
+
+ /// Gamma distribution with given shape and scale parameter
+
+ /// This function generates a gamma distribution random number.
+ ///
+ ///\param k shape parameter (<tt>k>0</tt>)
+ ///\param theta scale parameter
+ ///
+ double gamma(double k,double theta=1.0)
+ {
+ double xi,nu;
+ const double delta = k-std::floor(k);
+ const double v0=E/(E-delta);
+ do {
+ double V0=1.0-real<double>();
+ double V1=1.0-real<double>();
+ double V2=1.0-real<double>();
+ if(V2<=v0)
+ {
+ xi=std::pow(V1,1.0/delta);
+ nu=V0*std::pow(xi,delta-1.0);
+ }
+ else
+ {
+ xi=1.0-std::log(V1);
+ nu=V0*std::exp(-xi);
+ }
+ } while(nu>std::pow(xi,delta-1.0)*std::exp(-xi));
+ return theta*(xi+gamma(int(std::floor(k))));
+ }
+
+ /// Weibull distribution
+
+ /// This function generates a Weibull distribution random number.
+ ///
+ ///\param k shape parameter (<tt>k>0</tt>)
+ ///\param lambda scale parameter (<tt>lambda>0</tt>)
+ ///
+ double weibull(double k,double lambda)
+ {
+ return lambda*pow(-std::log(1.0-real<double>()),1.0/k);
+ }
+
+ /// Pareto distribution
+
+ /// This function generates a Pareto distribution random number.
+ ///
+ ///\param k shape parameter (<tt>k>0</tt>)
+ ///\param x_min location parameter (<tt>x_min>0</tt>)
+ ///
+ double pareto(double k,double x_min)
+ {
+ return exponential(gamma(k,1.0/x_min))+x_min;
+ }
+
+ /// Poisson distribution
+
+ /// This function generates a Poisson distribution random number with
+ /// parameter \c lambda.
+ ///
+ /// The probability mass function of this distribusion is
+ /// \f[ \frac{e^{-\lambda}\lambda^k}{k!} \f]
+ /// \note The algorithm is taken from the book of Donald E. Knuth titled
+ /// ''Seminumerical Algorithms'' (1969). Its running time is linear in the
+ /// return value.
+
+ int poisson(double lambda)
+ {
+ const double l = std::exp(-lambda);
+ int k=0;
+ double p = 1.0;
+ do {
+ k++;
+ p*=real<double>();
+ } while (p>=l);
+ return k-1;
+ }
+
+ ///@}
+
+ ///\name Two Dimensional Distributions
+ ///
+ ///@{
+
+ /// Uniform distribution on the full unit circle
+
+ /// Uniform distribution on the full unit circle.
+ ///
+ dim2::Point<double> disc()
+ {
+ double V1,V2;
+ do {
+ V1=2*real<double>()-1;
+ V2=2*real<double>()-1;
+
+ } while(V1*V1+V2*V2>=1);
+ return dim2::Point<double>(V1,V2);
+ }
+ /// A kind of two dimensional normal (Gauss) distribution
+
+ /// This function provides a turning symmetric two-dimensional distribution.
+ /// Both coordinates are of standard normal distribution, but they are not
+ /// independent.
+ ///
+ /// \note The coordinates are the two random variables provided by
+ /// the Box-Muller method.
+ dim2::Point<double> gauss2()
+ {
+ double V1,V2,S;
+ do {
+ V1=2*real<double>()-1;
+ V2=2*real<double>()-1;
+ S=V1*V1+V2*V2;
+ } while(S>=1);
+ double W=std::sqrt(-2*std::log(S)/S);
+ return dim2::Point<double>(W*V1,W*V2);
+ }
+ /// A kind of two dimensional exponential distribution
+
+ /// This function provides a turning symmetric two-dimensional distribution.
+ /// The x-coordinate is of conditionally exponential distribution
+ /// with the condition that x is positive and y=0. If x is negative and
+ /// y=0 then, -x is of exponential distribution. The same is true for the
+ /// y-coordinate.
+ dim2::Point<double> exponential2()
+ {
+ double V1,V2,S;
+ do {
+ V1=2*real<double>()-1;
+ V2=2*real<double>()-1;
+ S=V1*V1+V2*V2;
+ } while(S>=1);
+ double W=-std::log(S)/S;
+ return dim2::Point<double>(W*V1,W*V2);
+ }
+
+ ///@}
+ };
+
+
+ extern Random rnd;
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/smart_graph.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/smart_graph.h
new file mode 100644
index 00000000000..bdbe369a4df
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/smart_graph.h
@@ -0,0 +1,1344 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_SMART_GRAPH_H
+#define LEMON_SMART_GRAPH_H
+
+///\ingroup graphs
+///\file
+///\brief SmartDigraph and SmartGraph classes.
+
+#include <vector>
+
+#include <lemon/core.h>
+#include <lemon/error.h>
+#include <lemon/bits/graph_extender.h>
+
+namespace lemon {
+
+ class SmartDigraph;
+
+ class SmartDigraphBase {
+ protected:
+
+ struct NodeT
+ {
+ int first_in, first_out;
+ NodeT() {}
+ };
+ struct ArcT
+ {
+ int target, source, next_in, next_out;
+ ArcT() {}
+ };
+
+ std::vector<NodeT> nodes;
+ std::vector<ArcT> arcs;
+
+ public:
+
+ typedef SmartDigraphBase Digraph;
+
+ class Node;
+ class Arc;
+
+ public:
+
+ SmartDigraphBase() : nodes(), arcs() { }
+ SmartDigraphBase(const SmartDigraphBase &_g)
+ : nodes(_g.nodes), arcs(_g.arcs) { }
+
+ typedef True NodeNumTag;
+ typedef True ArcNumTag;
+
+ int nodeNum() const { return nodes.size(); }
+ int arcNum() const { return arcs.size(); }
+
+ int maxNodeId() const { return nodes.size()-1; }
+ int maxArcId() const { return arcs.size()-1; }
+
+ Node addNode() {
+ int n = nodes.size();
+ nodes.push_back(NodeT());
+ nodes[n].first_in = -1;
+ nodes[n].first_out = -1;
+ return Node(n);
+ }
+
+ Arc addArc(Node u, Node v) {
+ int n = arcs.size();
+ arcs.push_back(ArcT());
+ arcs[n].source = u._id;
+ arcs[n].target = v._id;
+ arcs[n].next_out = nodes[u._id].first_out;
+ arcs[n].next_in = nodes[v._id].first_in;
+ nodes[u._id].first_out = nodes[v._id].first_in = n;
+
+ return Arc(n);
+ }
+
+ void clear() {
+ arcs.clear();
+ nodes.clear();
+ }
+
+ Node source(Arc a) const { return Node(arcs[a._id].source); }
+ Node target(Arc a) const { return Node(arcs[a._id].target); }
+
+ static int id(Node v) { return v._id; }
+ static int id(Arc a) { return a._id; }
+
+ static Node nodeFromId(int id) { return Node(id);}
+ static Arc arcFromId(int id) { return Arc(id);}
+
+ bool valid(Node n) const {
+ return n._id >= 0 && n._id < static_cast<int>(nodes.size());
+ }
+ bool valid(Arc a) const {
+ return a._id >= 0 && a._id < static_cast<int>(arcs.size());
+ }
+
+ class Node {
+ friend class SmartDigraphBase;
+ friend class SmartDigraph;
+
+ protected:
+ int _id;
+ explicit Node(int id) : _id(id) {}
+ public:
+ Node() {}
+ Node (Invalid) : _id(-1) {}
+ bool operator==(const Node i) const {return _id == i._id;}
+ bool operator!=(const Node i) const {return _id != i._id;}
+ bool operator<(const Node i) const {return _id < i._id;}
+ };
+
+
+ class Arc {
+ friend class SmartDigraphBase;
+ friend class SmartDigraph;
+
+ protected:
+ int _id;
+ explicit Arc(int id) : _id(id) {}
+ public:
+ Arc() { }
+ Arc (Invalid) : _id(-1) {}
+ bool operator==(const Arc i) const {return _id == i._id;}
+ bool operator!=(const Arc i) const {return _id != i._id;}
+ bool operator<(const Arc i) const {return _id < i._id;}
+ };
+
+ void first(Node& node) const {
+ node._id = nodes.size() - 1;
+ }
+
+ static void next(Node& node) {
+ --node._id;
+ }
+
+ void first(Arc& arc) const {
+ arc._id = arcs.size() - 1;
+ }
+
+ static void next(Arc& arc) {
+ --arc._id;
+ }
+
+ void firstOut(Arc& arc, const Node& node) const {
+ arc._id = nodes[node._id].first_out;
+ }
+
+ void nextOut(Arc& arc) const {
+ arc._id = arcs[arc._id].next_out;
+ }
+
+ void firstIn(Arc& arc, const Node& node) const {
+ arc._id = nodes[node._id].first_in;
+ }
+
+ void nextIn(Arc& arc) const {
+ arc._id = arcs[arc._id].next_in;
+ }
+
+ };
+
+ typedef DigraphExtender<SmartDigraphBase> ExtendedSmartDigraphBase;
+
+ ///\ingroup graphs
+ ///
+ ///\brief A smart directed graph class.
+ ///
+ ///\ref SmartDigraph is a simple and fast digraph implementation.
+ ///It is also quite memory efficient but at the price
+ ///that it does not support node and arc deletion
+ ///(except for the Snapshot feature).
+ ///
+ ///This type fully conforms to the \ref concepts::Digraph "Digraph concept"
+ ///and it also provides some additional functionalities.
+ ///Most of its member functions and nested classes are documented
+ ///only in the concept class.
+ ///
+ ///This class provides constant time counting for nodes and arcs.
+ ///
+ ///\sa concepts::Digraph
+ ///\sa SmartGraph
+ class SmartDigraph : public ExtendedSmartDigraphBase {
+ typedef ExtendedSmartDigraphBase Parent;
+
+ private:
+ /// Digraphs are \e not copy constructible. Use DigraphCopy instead.
+ SmartDigraph(const SmartDigraph &) : ExtendedSmartDigraphBase() {};
+ /// \brief Assignment of a digraph to another one is \e not allowed.
+ /// Use DigraphCopy instead.
+ void operator=(const SmartDigraph &) {}
+
+ public:
+
+ /// Constructor
+
+ /// Constructor.
+ ///
+ SmartDigraph() {};
+
+ ///Add a new node to the digraph.
+
+ ///This function adds a new node to the digraph.
+ ///\return The new node.
+ Node addNode() { return Parent::addNode(); }
+
+ ///Add a new arc to the digraph.
+
+ ///This function adds a new arc to the digraph with source node \c s
+ ///and target node \c t.
+ ///\return The new arc.
+ Arc addArc(Node s, Node t) {
+ return Parent::addArc(s, t);
+ }
+
+ /// \brief Node validity check
+ ///
+ /// This function gives back \c true if the given node is valid,
+ /// i.e. it is a real node of the digraph.
+ ///
+ /// \warning A removed node (using Snapshot) could become valid again
+ /// if new nodes are added to the digraph.
+ bool valid(Node n) const { return Parent::valid(n); }
+
+ /// \brief Arc validity check
+ ///
+ /// This function gives back \c true if the given arc is valid,
+ /// i.e. it is a real arc of the digraph.
+ ///
+ /// \warning A removed arc (using Snapshot) could become valid again
+ /// if new arcs are added to the graph.
+ bool valid(Arc a) const { return Parent::valid(a); }
+
+ ///Split a node.
+
+ ///This function splits the given node. First, a new node is added
+ ///to the digraph, then the source of each outgoing arc of node \c n
+ ///is moved to this new node.
+ ///If the second parameter \c connect is \c true (this is the default
+ ///value), then a new arc from node \c n to the newly created node
+ ///is also added.
+ ///\return The newly created node.
+ ///
+ ///\note All iterators remain valid.
+ ///
+ ///\warning This functionality cannot be used together with the Snapshot
+ ///feature.
+ Node split(Node n, bool connect = true)
+ {
+ Node b = addNode();
+ nodes[b._id].first_out=nodes[n._id].first_out;
+ nodes[n._id].first_out=-1;
+ for(int i=nodes[b._id].first_out; i!=-1; i=arcs[i].next_out) {
+ arcs[i].source=b._id;
+ }
+ if(connect) addArc(n,b);
+ return b;
+ }
+
+ ///Clear the digraph.
+
+ ///This function erases all nodes and arcs from the digraph.
+ ///
+ void clear() {
+ Parent::clear();
+ }
+
+ /// Reserve memory for nodes.
+
+ /// Using this function, it is possible to avoid superfluous memory
+ /// allocation: if you know that the digraph you want to build will
+ /// be large (e.g. it will contain millions of nodes and/or arcs),
+ /// then it is worth reserving space for this amount before starting
+ /// to build the digraph.
+ /// \sa reserveArc()
+ void reserveNode(int n) { nodes.reserve(n); };
+
+ /// Reserve memory for arcs.
+
+ /// Using this function, it is possible to avoid superfluous memory
+ /// allocation: if you know that the digraph you want to build will
+ /// be large (e.g. it will contain millions of nodes and/or arcs),
+ /// then it is worth reserving space for this amount before starting
+ /// to build the digraph.
+ /// \sa reserveNode()
+ void reserveArc(int m) { arcs.reserve(m); };
+
+ public:
+
+ class Snapshot;
+
+ protected:
+
+ void restoreSnapshot(const Snapshot &s)
+ {
+ while(s.arc_num<arcs.size()) {
+ Arc arc = arcFromId(arcs.size()-1);
+ Parent::notifier(Arc()).erase(arc);
+ nodes[arcs.back().source].first_out=arcs.back().next_out;
+ nodes[arcs.back().target].first_in=arcs.back().next_in;
+ arcs.pop_back();
+ }
+ while(s.node_num<nodes.size()) {
+ Node node = nodeFromId(nodes.size()-1);
+ Parent::notifier(Node()).erase(node);
+ nodes.pop_back();
+ }
+ }
+
+ public:
+
+ ///Class to make a snapshot of the digraph and to restore it later.
+
+ ///Class to make a snapshot of the digraph and to restore it later.
+ ///
+ ///The newly added nodes and arcs can be removed using the
+ ///restore() function. This is the only way for deleting nodes and/or
+ ///arcs from a SmartDigraph structure.
+ ///
+ ///\note After a state is restored, you cannot restore a later state,
+ ///i.e. you cannot add the removed nodes and arcs again using
+ ///another Snapshot instance.
+ ///
+ ///\warning Node splitting cannot be restored.
+ ///\warning The validity of the snapshot is not stored due to
+ ///performance reasons. If you do not use the snapshot correctly,
+ ///it can cause broken program, invalid or not restored state of
+ ///the digraph or no change.
+ class Snapshot
+ {
+ SmartDigraph *_graph;
+ protected:
+ friend class SmartDigraph;
+ unsigned int node_num;
+ unsigned int arc_num;
+ public:
+ ///Default constructor.
+
+ ///Default constructor.
+ ///You have to call save() to actually make a snapshot.
+ Snapshot() : _graph(0) {}
+ ///Constructor that immediately makes a snapshot
+
+ ///This constructor immediately makes a snapshot of the given digraph.
+ ///
+ Snapshot(SmartDigraph &gr) : _graph(&gr) {
+ node_num=_graph->nodes.size();
+ arc_num=_graph->arcs.size();
+ }
+
+ ///Make a snapshot.
+
+ ///This function makes a snapshot of the given digraph.
+ ///It can be called more than once. In case of a repeated
+ ///call, the previous snapshot gets lost.
+ void save(SmartDigraph &gr) {
+ _graph=&gr;
+ node_num=_graph->nodes.size();
+ arc_num=_graph->arcs.size();
+ }
+
+ ///Undo the changes until a snapshot.
+
+ ///This function undos the changes until the last snapshot
+ ///created by save() or Snapshot(SmartDigraph&).
+ void restore()
+ {
+ _graph->restoreSnapshot(*this);
+ }
+ };
+ };
+
+
+ class SmartGraphBase {
+
+ protected:
+
+ struct NodeT {
+ int first_out;
+ };
+
+ struct ArcT {
+ int target;
+ int next_out;
+ };
+
+ std::vector<NodeT> nodes;
+ std::vector<ArcT> arcs;
+
+ public:
+
+ typedef SmartGraphBase Graph;
+
+ class Node;
+ class Arc;
+ class Edge;
+
+ class Node {
+ friend class SmartGraphBase;
+ protected:
+
+ int _id;
+ explicit Node(int id) { _id = id;}
+
+ public:
+ Node() {}
+ Node (Invalid) { _id = -1; }
+ bool operator==(const Node& node) const {return _id == node._id;}
+ bool operator!=(const Node& node) const {return _id != node._id;}
+ bool operator<(const Node& node) const {return _id < node._id;}
+ };
+
+ class Edge {
+ friend class SmartGraphBase;
+ protected:
+
+ int _id;
+ explicit Edge(int id) { _id = id;}
+
+ public:
+ Edge() {}
+ Edge (Invalid) { _id = -1; }
+ bool operator==(const Edge& arc) const {return _id == arc._id;}
+ bool operator!=(const Edge& arc) const {return _id != arc._id;}
+ bool operator<(const Edge& arc) const {return _id < arc._id;}
+ };
+
+ class Arc {
+ friend class SmartGraphBase;
+ protected:
+
+ int _id;
+ explicit Arc(int id) { _id = id;}
+
+ public:
+ operator Edge() const {
+ return _id != -1 ? edgeFromId(_id / 2) : INVALID;
+ }
+
+ Arc() {}
+ Arc (Invalid) { _id = -1; }
+ bool operator==(const Arc& arc) const {return _id == arc._id;}
+ bool operator!=(const Arc& arc) const {return _id != arc._id;}
+ bool operator<(const Arc& arc) const {return _id < arc._id;}
+ };
+
+
+
+ SmartGraphBase()
+ : nodes(), arcs() {}
+
+ typedef True NodeNumTag;
+ typedef True EdgeNumTag;
+ typedef True ArcNumTag;
+
+ int nodeNum() const { return nodes.size(); }
+ int edgeNum() const { return arcs.size() / 2; }
+ int arcNum() const { return arcs.size(); }
+
+ int maxNodeId() const { return nodes.size()-1; }
+ int maxEdgeId() const { return arcs.size() / 2 - 1; }
+ int maxArcId() const { return arcs.size()-1; }
+
+ Node source(Arc e) const { return Node(arcs[e._id ^ 1].target); }
+ Node target(Arc e) const { return Node(arcs[e._id].target); }
+
+ Node u(Edge e) const { return Node(arcs[2 * e._id].target); }
+ Node v(Edge e) const { return Node(arcs[2 * e._id + 1].target); }
+
+ static bool direction(Arc e) {
+ return (e._id & 1) == 1;
+ }
+
+ static Arc direct(Edge e, bool d) {
+ return Arc(e._id * 2 + (d ? 1 : 0));
+ }
+
+ void first(Node& node) const {
+ node._id = nodes.size() - 1;
+ }
+
+ static void next(Node& node) {
+ --node._id;
+ }
+
+ void first(Arc& arc) const {
+ arc._id = arcs.size() - 1;
+ }
+
+ static void next(Arc& arc) {
+ --arc._id;
+ }
+
+ void first(Edge& arc) const {
+ arc._id = arcs.size() / 2 - 1;
+ }
+
+ static void next(Edge& arc) {
+ --arc._id;
+ }
+
+ void firstOut(Arc &arc, const Node& v) const {
+ arc._id = nodes[v._id].first_out;
+ }
+ void nextOut(Arc &arc) const {
+ arc._id = arcs[arc._id].next_out;
+ }
+
+ void firstIn(Arc &arc, const Node& v) const {
+ arc._id = ((nodes[v._id].first_out) ^ 1);
+ if (arc._id == -2) arc._id = -1;
+ }
+ void nextIn(Arc &arc) const {
+ arc._id = ((arcs[arc._id ^ 1].next_out) ^ 1);
+ if (arc._id == -2) arc._id = -1;
+ }
+
+ void firstInc(Edge &arc, bool& d, const Node& v) const {
+ int de = nodes[v._id].first_out;
+ if (de != -1) {
+ arc._id = de / 2;
+ d = ((de & 1) == 1);
+ } else {
+ arc._id = -1;
+ d = true;
+ }
+ }
+ void nextInc(Edge &arc, bool& d) const {
+ int de = (arcs[(arc._id * 2) | (d ? 1 : 0)].next_out);
+ if (de != -1) {
+ arc._id = de / 2;
+ d = ((de & 1) == 1);
+ } else {
+ arc._id = -1;
+ d = true;
+ }
+ }
+
+ static int id(Node v) { return v._id; }
+ static int id(Arc e) { return e._id; }
+ static int id(Edge e) { return e._id; }
+
+ static Node nodeFromId(int id) { return Node(id);}
+ static Arc arcFromId(int id) { return Arc(id);}
+ static Edge edgeFromId(int id) { return Edge(id);}
+
+ bool valid(Node n) const {
+ return n._id >= 0 && n._id < static_cast<int>(nodes.size());
+ }
+ bool valid(Arc a) const {
+ return a._id >= 0 && a._id < static_cast<int>(arcs.size());
+ }
+ bool valid(Edge e) const {
+ return e._id >= 0 && 2 * e._id < static_cast<int>(arcs.size());
+ }
+
+ Node addNode() {
+ int n = nodes.size();
+ nodes.push_back(NodeT());
+ nodes[n].first_out = -1;
+
+ return Node(n);
+ }
+
+ Edge addEdge(Node u, Node v) {
+ int n = arcs.size();
+ arcs.push_back(ArcT());
+ arcs.push_back(ArcT());
+
+ arcs[n].target = u._id;
+ arcs[n | 1].target = v._id;
+
+ arcs[n].next_out = nodes[v._id].first_out;
+ nodes[v._id].first_out = n;
+
+ arcs[n | 1].next_out = nodes[u._id].first_out;
+ nodes[u._id].first_out = (n | 1);
+
+ return Edge(n / 2);
+ }
+
+ void clear() {
+ arcs.clear();
+ nodes.clear();
+ }
+
+ };
+
+ typedef GraphExtender<SmartGraphBase> ExtendedSmartGraphBase;
+
+ /// \ingroup graphs
+ ///
+ /// \brief A smart undirected graph class.
+ ///
+ /// \ref SmartGraph is a simple and fast graph implementation.
+ /// It is also quite memory efficient but at the price
+ /// that it does not support node and edge deletion
+ /// (except for the Snapshot feature).
+ ///
+ /// This type fully conforms to the \ref concepts::Graph "Graph concept"
+ /// and it also provides some additional functionalities.
+ /// Most of its member functions and nested classes are documented
+ /// only in the concept class.
+ ///
+ /// This class provides constant time counting for nodes, edges and arcs.
+ ///
+ /// \sa concepts::Graph
+ /// \sa SmartDigraph
+ class SmartGraph : public ExtendedSmartGraphBase {
+ typedef ExtendedSmartGraphBase Parent;
+
+ private:
+ /// Graphs are \e not copy constructible. Use GraphCopy instead.
+ SmartGraph(const SmartGraph &) : ExtendedSmartGraphBase() {};
+ /// \brief Assignment of a graph to another one is \e not allowed.
+ /// Use GraphCopy instead.
+ void operator=(const SmartGraph &) {}
+
+ public:
+
+ /// Constructor
+
+ /// Constructor.
+ ///
+ SmartGraph() {}
+
+ /// \brief Add a new node to the graph.
+ ///
+ /// This function adds a new node to the graph.
+ /// \return The new node.
+ Node addNode() { return Parent::addNode(); }
+
+ /// \brief Add a new edge to the graph.
+ ///
+ /// This function adds a new edge to the graph between nodes
+ /// \c u and \c v with inherent orientation from node \c u to
+ /// node \c v.
+ /// \return The new edge.
+ Edge addEdge(Node u, Node v) {
+ return Parent::addEdge(u, v);
+ }
+
+ /// \brief Node validity check
+ ///
+ /// This function gives back \c true if the given node is valid,
+ /// i.e. it is a real node of the graph.
+ ///
+ /// \warning A removed node (using Snapshot) could become valid again
+ /// if new nodes are added to the graph.
+ bool valid(Node n) const { return Parent::valid(n); }
+
+ /// \brief Edge validity check
+ ///
+ /// This function gives back \c true if the given edge is valid,
+ /// i.e. it is a real edge of the graph.
+ ///
+ /// \warning A removed edge (using Snapshot) could become valid again
+ /// if new edges are added to the graph.
+ bool valid(Edge e) const { return Parent::valid(e); }
+
+ /// \brief Arc validity check
+ ///
+ /// This function gives back \c true if the given arc is valid,
+ /// i.e. it is a real arc of the graph.
+ ///
+ /// \warning A removed arc (using Snapshot) could become valid again
+ /// if new edges are added to the graph.
+ bool valid(Arc a) const { return Parent::valid(a); }
+
+ ///Clear the graph.
+
+ ///This function erases all nodes and arcs from the graph.
+ ///
+ void clear() {
+ Parent::clear();
+ }
+
+ /// Reserve memory for nodes.
+
+ /// Using this function, it is possible to avoid superfluous memory
+ /// allocation: if you know that the graph you want to build will
+ /// be large (e.g. it will contain millions of nodes and/or edges),
+ /// then it is worth reserving space for this amount before starting
+ /// to build the graph.
+ /// \sa reserveEdge()
+ void reserveNode(int n) { nodes.reserve(n); };
+
+ /// Reserve memory for edges.
+
+ /// Using this function, it is possible to avoid superfluous memory
+ /// allocation: if you know that the graph you want to build will
+ /// be large (e.g. it will contain millions of nodes and/or edges),
+ /// then it is worth reserving space for this amount before starting
+ /// to build the graph.
+ /// \sa reserveNode()
+ void reserveEdge(int m) { arcs.reserve(2 * m); };
+
+ public:
+
+ class Snapshot;
+
+ protected:
+
+ void saveSnapshot(Snapshot &s)
+ {
+ s._graph = this;
+ s.node_num = nodes.size();
+ s.arc_num = arcs.size();
+ }
+
+ void restoreSnapshot(const Snapshot &s)
+ {
+ while(s.arc_num<arcs.size()) {
+ int n=arcs.size()-1;
+ Edge arc=edgeFromId(n/2);
+ Parent::notifier(Edge()).erase(arc);
+ std::vector<Arc> dir;
+ dir.push_back(arcFromId(n));
+ dir.push_back(arcFromId(n-1));
+ Parent::notifier(Arc()).erase(dir);
+ nodes[arcs[n-1].target].first_out=arcs[n].next_out;
+ nodes[arcs[n].target].first_out=arcs[n-1].next_out;
+ arcs.pop_back();
+ arcs.pop_back();
+ }
+ while(s.node_num<nodes.size()) {
+ int n=nodes.size()-1;
+ Node node = nodeFromId(n);
+ Parent::notifier(Node()).erase(node);
+ nodes.pop_back();
+ }
+ }
+
+ public:
+
+ ///Class to make a snapshot of the graph and to restore it later.
+
+ ///Class to make a snapshot of the graph and to restore it later.
+ ///
+ ///The newly added nodes and edges can be removed using the
+ ///restore() function. This is the only way for deleting nodes and/or
+ ///edges from a SmartGraph structure.
+ ///
+ ///\note After a state is restored, you cannot restore a later state,
+ ///i.e. you cannot add the removed nodes and edges again using
+ ///another Snapshot instance.
+ ///
+ ///\warning The validity of the snapshot is not stored due to
+ ///performance reasons. If you do not use the snapshot correctly,
+ ///it can cause broken program, invalid or not restored state of
+ ///the graph or no change.
+ class Snapshot
+ {
+ SmartGraph *_graph;
+ protected:
+ friend class SmartGraph;
+ unsigned int node_num;
+ unsigned int arc_num;
+ public:
+ ///Default constructor.
+
+ ///Default constructor.
+ ///You have to call save() to actually make a snapshot.
+ Snapshot() : _graph(0) {}
+ ///Constructor that immediately makes a snapshot
+
+ /// This constructor immediately makes a snapshot of the given graph.
+ ///
+ Snapshot(SmartGraph &gr) {
+ gr.saveSnapshot(*this);
+ }
+
+ ///Make a snapshot.
+
+ ///This function makes a snapshot of the given graph.
+ ///It can be called more than once. In case of a repeated
+ ///call, the previous snapshot gets lost.
+ void save(SmartGraph &gr)
+ {
+ gr.saveSnapshot(*this);
+ }
+
+ ///Undo the changes until the last snapshot.
+
+ ///This function undos the changes until the last snapshot
+ ///created by save() or Snapshot(SmartGraph&).
+ void restore()
+ {
+ _graph->restoreSnapshot(*this);
+ }
+ };
+ };
+
+ class SmartBpGraphBase {
+
+ protected:
+
+ struct NodeT {
+ int first_out;
+ int partition_next;
+ int partition_index;
+ bool red;
+ };
+
+ struct ArcT {
+ int target;
+ int next_out;
+ };
+
+ std::vector<NodeT> nodes;
+ std::vector<ArcT> arcs;
+
+ int first_red, first_blue;
+ int max_red, max_blue;
+
+ public:
+
+ typedef SmartBpGraphBase Graph;
+
+ class Node;
+ class Arc;
+ class Edge;
+
+ class Node {
+ friend class SmartBpGraphBase;
+ protected:
+
+ int _id;
+ explicit Node(int id) { _id = id;}
+
+ public:
+ Node() {}
+ Node (Invalid) { _id = -1; }
+ bool operator==(const Node& node) const {return _id == node._id;}
+ bool operator!=(const Node& node) const {return _id != node._id;}
+ bool operator<(const Node& node) const {return _id < node._id;}
+ };
+
+ class RedNode : public Node {
+ friend class SmartBpGraphBase;
+ protected:
+
+ explicit RedNode(int pid) : Node(pid) {}
+
+ public:
+ RedNode() {}
+ RedNode(const RedNode& node) : Node(node) {}
+ RedNode(Invalid) : Node(INVALID){}
+ };
+
+ class BlueNode : public Node {
+ friend class SmartBpGraphBase;
+ protected:
+
+ explicit BlueNode(int pid) : Node(pid) {}
+
+ public:
+ BlueNode() {}
+ BlueNode(const BlueNode& node) : Node(node) {}
+ BlueNode(Invalid) : Node(INVALID){}
+ };
+
+ class Edge {
+ friend class SmartBpGraphBase;
+ protected:
+
+ int _id;
+ explicit Edge(int id) { _id = id;}
+
+ public:
+ Edge() {}
+ Edge (Invalid) { _id = -1; }
+ bool operator==(const Edge& arc) const {return _id == arc._id;}
+ bool operator!=(const Edge& arc) const {return _id != arc._id;}
+ bool operator<(const Edge& arc) const {return _id < arc._id;}
+ };
+
+ class Arc {
+ friend class SmartBpGraphBase;
+ protected:
+
+ int _id;
+ explicit Arc(int id) { _id = id;}
+
+ public:
+ operator Edge() const {
+ return _id != -1 ? edgeFromId(_id / 2) : INVALID;
+ }
+
+ Arc() {}
+ Arc (Invalid) { _id = -1; }
+ bool operator==(const Arc& arc) const {return _id == arc._id;}
+ bool operator!=(const Arc& arc) const {return _id != arc._id;}
+ bool operator<(const Arc& arc) const {return _id < arc._id;}
+ };
+
+
+
+ SmartBpGraphBase()
+ : nodes(), arcs(), first_red(-1), first_blue(-1),
+ max_red(-1), max_blue(-1) {}
+
+ typedef True NodeNumTag;
+ typedef True EdgeNumTag;
+ typedef True ArcNumTag;
+
+ int nodeNum() const { return nodes.size(); }
+ int redNum() const { return max_red + 1; }
+ int blueNum() const { return max_blue + 1; }
+ int edgeNum() const { return arcs.size() / 2; }
+ int arcNum() const { return arcs.size(); }
+
+ int maxNodeId() const { return nodes.size()-1; }
+ int maxRedId() const { return max_red; }
+ int maxBlueId() const { return max_blue; }
+ int maxEdgeId() const { return arcs.size() / 2 - 1; }
+ int maxArcId() const { return arcs.size()-1; }
+
+ bool red(Node n) const { return nodes[n._id].red; }
+ bool blue(Node n) const { return !nodes[n._id].red; }
+
+ static RedNode asRedNodeUnsafe(Node n) { return RedNode(n._id); }
+ static BlueNode asBlueNodeUnsafe(Node n) { return BlueNode(n._id); }
+
+ Node source(Arc a) const { return Node(arcs[a._id ^ 1].target); }
+ Node target(Arc a) const { return Node(arcs[a._id].target); }
+
+ RedNode redNode(Edge e) const {
+ return RedNode(arcs[2 * e._id].target);
+ }
+ BlueNode blueNode(Edge e) const {
+ return BlueNode(arcs[2 * e._id + 1].target);
+ }
+
+ static bool direction(Arc a) {
+ return (a._id & 1) == 1;
+ }
+
+ static Arc direct(Edge e, bool d) {
+ return Arc(e._id * 2 + (d ? 1 : 0));
+ }
+
+ void first(Node& node) const {
+ node._id = nodes.size() - 1;
+ }
+
+ static void next(Node& node) {
+ --node._id;
+ }
+
+ void first(RedNode& node) const {
+ node._id = first_red;
+ }
+
+ void next(RedNode& node) const {
+ node._id = nodes[node._id].partition_next;
+ }
+
+ void first(BlueNode& node) const {
+ node._id = first_blue;
+ }
+
+ void next(BlueNode& node) const {
+ node._id = nodes[node._id].partition_next;
+ }
+
+ void first(Arc& arc) const {
+ arc._id = arcs.size() - 1;
+ }
+
+ static void next(Arc& arc) {
+ --arc._id;
+ }
+
+ void first(Edge& arc) const {
+ arc._id = arcs.size() / 2 - 1;
+ }
+
+ static void next(Edge& arc) {
+ --arc._id;
+ }
+
+ void firstOut(Arc &arc, const Node& v) const {
+ arc._id = nodes[v._id].first_out;
+ }
+ void nextOut(Arc &arc) const {
+ arc._id = arcs[arc._id].next_out;
+ }
+
+ void firstIn(Arc &arc, const Node& v) const {
+ arc._id = ((nodes[v._id].first_out) ^ 1);
+ if (arc._id == -2) arc._id = -1;
+ }
+ void nextIn(Arc &arc) const {
+ arc._id = ((arcs[arc._id ^ 1].next_out) ^ 1);
+ if (arc._id == -2) arc._id = -1;
+ }
+
+ void firstInc(Edge &arc, bool& d, const Node& v) const {
+ int de = nodes[v._id].first_out;
+ if (de != -1) {
+ arc._id = de / 2;
+ d = ((de & 1) == 1);
+ } else {
+ arc._id = -1;
+ d = true;
+ }
+ }
+ void nextInc(Edge &arc, bool& d) const {
+ int de = (arcs[(arc._id * 2) | (d ? 1 : 0)].next_out);
+ if (de != -1) {
+ arc._id = de / 2;
+ d = ((de & 1) == 1);
+ } else {
+ arc._id = -1;
+ d = true;
+ }
+ }
+
+ static int id(Node v) { return v._id; }
+ int id(RedNode v) const { return nodes[v._id].partition_index; }
+ int id(BlueNode v) const { return nodes[v._id].partition_index; }
+ static int id(Arc e) { return e._id; }
+ static int id(Edge e) { return e._id; }
+
+ static Node nodeFromId(int id) { return Node(id);}
+ static Arc arcFromId(int id) { return Arc(id);}
+ static Edge edgeFromId(int id) { return Edge(id);}
+
+ bool valid(Node n) const {
+ return n._id >= 0 && n._id < static_cast<int>(nodes.size());
+ }
+ bool valid(Arc a) const {
+ return a._id >= 0 && a._id < static_cast<int>(arcs.size());
+ }
+ bool valid(Edge e) const {
+ return e._id >= 0 && 2 * e._id < static_cast<int>(arcs.size());
+ }
+
+ RedNode addRedNode() {
+ int n = nodes.size();
+ nodes.push_back(NodeT());
+ nodes[n].first_out = -1;
+ nodes[n].red = true;
+ nodes[n].partition_index = ++max_red;
+ nodes[n].partition_next = first_red;
+ first_red = n;
+
+ return RedNode(n);
+ }
+
+ BlueNode addBlueNode() {
+ int n = nodes.size();
+ nodes.push_back(NodeT());
+ nodes[n].first_out = -1;
+ nodes[n].red = false;
+ nodes[n].partition_index = ++max_blue;
+ nodes[n].partition_next = first_blue;
+ first_blue = n;
+
+ return BlueNode(n);
+ }
+
+ Edge addEdge(RedNode u, BlueNode v) {
+ int n = arcs.size();
+ arcs.push_back(ArcT());
+ arcs.push_back(ArcT());
+
+ arcs[n].target = u._id;
+ arcs[n | 1].target = v._id;
+
+ arcs[n].next_out = nodes[v._id].first_out;
+ nodes[v._id].first_out = n;
+
+ arcs[n | 1].next_out = nodes[u._id].first_out;
+ nodes[u._id].first_out = (n | 1);
+
+ return Edge(n / 2);
+ }
+
+ void clear() {
+ arcs.clear();
+ nodes.clear();
+ first_red = -1;
+ first_blue = -1;
+ max_blue = -1;
+ max_red = -1;
+ }
+
+ };
+
+ typedef BpGraphExtender<SmartBpGraphBase> ExtendedSmartBpGraphBase;
+
+ /// \ingroup graphs
+ ///
+ /// \brief A smart undirected bipartite graph class.
+ ///
+ /// \ref SmartBpGraph is a simple and fast bipartite graph implementation.
+ /// It is also quite memory efficient but at the price
+ /// that it does not support node and edge deletion
+ /// (except for the Snapshot feature).
+ ///
+ /// This type fully conforms to the \ref concepts::BpGraph "BpGraph concept"
+ /// and it also provides some additional functionalities.
+ /// Most of its member functions and nested classes are documented
+ /// only in the concept class.
+ ///
+ /// This class provides constant time counting for nodes, edges and arcs.
+ ///
+ /// \sa concepts::BpGraph
+ /// \sa SmartGraph
+ class SmartBpGraph : public ExtendedSmartBpGraphBase {
+ typedef ExtendedSmartBpGraphBase Parent;
+
+ private:
+ /// Graphs are \e not copy constructible. Use GraphCopy instead.
+ SmartBpGraph(const SmartBpGraph &) : ExtendedSmartBpGraphBase() {};
+ /// \brief Assignment of a graph to another one is \e not allowed.
+ /// Use GraphCopy instead.
+ void operator=(const SmartBpGraph &) {}
+
+ public:
+
+ /// Constructor
+
+ /// Constructor.
+ ///
+ SmartBpGraph() {}
+
+ /// \brief Add a new red node to the graph.
+ ///
+ /// This function adds a red new node to the graph.
+ /// \return The new node.
+ RedNode addRedNode() { return Parent::addRedNode(); }
+
+ /// \brief Add a new blue node to the graph.
+ ///
+ /// This function adds a blue new node to the graph.
+ /// \return The new node.
+ BlueNode addBlueNode() { return Parent::addBlueNode(); }
+
+ /// \brief Add a new edge to the graph.
+ ///
+ /// This function adds a new edge to the graph between nodes
+ /// \c u and \c v with inherent orientation from node \c u to
+ /// node \c v.
+ /// \return The new edge.
+ Edge addEdge(RedNode u, BlueNode v) {
+ return Parent::addEdge(u, v);
+ }
+ Edge addEdge(BlueNode v, RedNode u) {
+ return Parent::addEdge(u, v);
+ }
+
+ /// \brief Node validity check
+ ///
+ /// This function gives back \c true if the given node is valid,
+ /// i.e. it is a real node of the graph.
+ ///
+ /// \warning A removed node (using Snapshot) could become valid again
+ /// if new nodes are added to the graph.
+ bool valid(Node n) const { return Parent::valid(n); }
+
+ /// \brief Edge validity check
+ ///
+ /// This function gives back \c true if the given edge is valid,
+ /// i.e. it is a real edge of the graph.
+ ///
+ /// \warning A removed edge (using Snapshot) could become valid again
+ /// if new edges are added to the graph.
+ bool valid(Edge e) const { return Parent::valid(e); }
+
+ /// \brief Arc validity check
+ ///
+ /// This function gives back \c true if the given arc is valid,
+ /// i.e. it is a real arc of the graph.
+ ///
+ /// \warning A removed arc (using Snapshot) could become valid again
+ /// if new edges are added to the graph.
+ bool valid(Arc a) const { return Parent::valid(a); }
+
+ ///Clear the graph.
+
+ ///This function erases all nodes and arcs from the graph.
+ ///
+ void clear() {
+ Parent::clear();
+ }
+
+ /// Reserve memory for nodes.
+
+ /// Using this function, it is possible to avoid superfluous memory
+ /// allocation: if you know that the graph you want to build will
+ /// be large (e.g. it will contain millions of nodes and/or edges),
+ /// then it is worth reserving space for this amount before starting
+ /// to build the graph.
+ /// \sa reserveEdge()
+ void reserveNode(int n) { nodes.reserve(n); };
+
+ /// Reserve memory for edges.
+
+ /// Using this function, it is possible to avoid superfluous memory
+ /// allocation: if you know that the graph you want to build will
+ /// be large (e.g. it will contain millions of nodes and/or edges),
+ /// then it is worth reserving space for this amount before starting
+ /// to build the graph.
+ /// \sa reserveNode()
+ void reserveEdge(int m) { arcs.reserve(2 * m); };
+
+ public:
+
+ class Snapshot;
+
+ protected:
+
+ void saveSnapshot(Snapshot &s)
+ {
+ s._graph = this;
+ s.node_num = nodes.size();
+ s.arc_num = arcs.size();
+ }
+
+ void restoreSnapshot(const Snapshot &s)
+ {
+ while(s.arc_num<arcs.size()) {
+ int n=arcs.size()-1;
+ Edge arc=edgeFromId(n/2);
+ Parent::notifier(Edge()).erase(arc);
+ std::vector<Arc> dir;
+ dir.push_back(arcFromId(n));
+ dir.push_back(arcFromId(n-1));
+ Parent::notifier(Arc()).erase(dir);
+ nodes[arcs[n-1].target].first_out=arcs[n].next_out;
+ nodes[arcs[n].target].first_out=arcs[n-1].next_out;
+ arcs.pop_back();
+ arcs.pop_back();
+ }
+ while(s.node_num<nodes.size()) {
+ int n=nodes.size()-1;
+ Node node = nodeFromId(n);
+ if (Parent::red(node)) {
+ first_red = nodes[n].partition_next;
+ if (first_red != -1) {
+ max_red = nodes[first_red].partition_index;
+ } else {
+ max_red = -1;
+ }
+ Parent::notifier(RedNode()).erase(asRedNodeUnsafe(node));
+ } else {
+ first_blue = nodes[n].partition_next;
+ if (first_blue != -1) {
+ max_blue = nodes[first_blue].partition_index;
+ } else {
+ max_blue = -1;
+ }
+ Parent::notifier(BlueNode()).erase(asBlueNodeUnsafe(node));
+ }
+ Parent::notifier(Node()).erase(node);
+ nodes.pop_back();
+ }
+ }
+
+ public:
+
+ ///Class to make a snapshot of the graph and to restore it later.
+
+ ///Class to make a snapshot of the graph and to restore it later.
+ ///
+ ///The newly added nodes and edges can be removed using the
+ ///restore() function. This is the only way for deleting nodes and/or
+ ///edges from a SmartBpGraph structure.
+ ///
+ ///\note After a state is restored, you cannot restore a later state,
+ ///i.e. you cannot add the removed nodes and edges again using
+ ///another Snapshot instance.
+ ///
+ ///\warning The validity of the snapshot is not stored due to
+ ///performance reasons. If you do not use the snapshot correctly,
+ ///it can cause broken program, invalid or not restored state of
+ ///the graph or no change.
+ class Snapshot
+ {
+ SmartBpGraph *_graph;
+ protected:
+ friend class SmartBpGraph;
+ unsigned int node_num;
+ unsigned int arc_num;
+ public:
+ ///Default constructor.
+
+ ///Default constructor.
+ ///You have to call save() to actually make a snapshot.
+ Snapshot() : _graph(0) {}
+ ///Constructor that immediately makes a snapshot
+
+ /// This constructor immediately makes a snapshot of the given graph.
+ ///
+ Snapshot(SmartBpGraph &gr) {
+ gr.saveSnapshot(*this);
+ }
+
+ ///Make a snapshot.
+
+ ///This function makes a snapshot of the given graph.
+ ///It can be called more than once. In case of a repeated
+ ///call, the previous snapshot gets lost.
+ void save(SmartBpGraph &gr)
+ {
+ gr.saveSnapshot(*this);
+ }
+
+ ///Undo the changes until the last snapshot.
+
+ ///This function undos the changes until the last snapshot
+ ///created by save() or Snapshot(SmartBpGraph&).
+ void restore()
+ {
+ _graph->restoreSnapshot(*this);
+ }
+ };
+ };
+
+} //namespace lemon
+
+
+#endif //LEMON_SMART_GRAPH_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/soplex.cc b/extern/quadriflow/3rd/lemon-1.3.1/lemon/soplex.cc
new file mode 100644
index 00000000000..d7517231ce2
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/soplex.cc
@@ -0,0 +1,465 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+#include <lemon/soplex.h>
+
+#include <soplex.h>
+#include <spxout.h>
+
+
+///\file
+///\brief Implementation of the LEMON-SOPLEX lp solver interface.
+namespace lemon {
+
+ SoplexLp::SoplexLp() {
+ soplex = new soplex::SoPlex;
+ messageLevel(MESSAGE_NOTHING);
+ }
+
+ SoplexLp::~SoplexLp() {
+ delete soplex;
+ }
+
+ SoplexLp::SoplexLp(const SoplexLp& lp) {
+ rows = lp.rows;
+ cols = lp.cols;
+
+ soplex = new soplex::SoPlex;
+ (*static_cast<soplex::SPxLP*>(soplex)) = *(lp.soplex);
+
+ _col_names = lp._col_names;
+ _col_names_ref = lp._col_names_ref;
+
+ _row_names = lp._row_names;
+ _row_names_ref = lp._row_names_ref;
+
+ messageLevel(MESSAGE_NOTHING);
+ }
+
+ void SoplexLp::_clear_temporals() {
+ _primal_values.clear();
+ _dual_values.clear();
+ }
+
+ SoplexLp* SoplexLp::newSolver() const {
+ SoplexLp* newlp = new SoplexLp();
+ return newlp;
+ }
+
+ SoplexLp* SoplexLp::cloneSolver() const {
+ SoplexLp* newlp = new SoplexLp(*this);
+ return newlp;
+ }
+
+ const char* SoplexLp::_solverName() const { return "SoplexLp"; }
+
+ int SoplexLp::_addCol() {
+ soplex::LPCol c;
+ c.setLower(-soplex::infinity);
+ c.setUpper(soplex::infinity);
+ soplex->addCol(c);
+
+ _col_names.push_back(std::string());
+
+ return soplex->nCols() - 1;
+ }
+
+ int SoplexLp::_addRow() {
+ soplex::LPRow r;
+ r.setLhs(-soplex::infinity);
+ r.setRhs(soplex::infinity);
+ soplex->addRow(r);
+
+ _row_names.push_back(std::string());
+
+ return soplex->nRows() - 1;
+ }
+
+ int SoplexLp::_addRow(Value l, ExprIterator b, ExprIterator e, Value u) {
+ soplex::DSVector v;
+ for (ExprIterator it = b; it != e; ++it) {
+ v.add(it->first, it->second);
+ }
+ soplex::LPRow r(l, v, u);
+ soplex->addRow(r);
+
+ _row_names.push_back(std::string());
+
+ return soplex->nRows() - 1;
+ }
+
+
+ void SoplexLp::_eraseCol(int i) {
+ soplex->removeCol(i);
+ _col_names_ref.erase(_col_names[i]);
+ _col_names[i] = _col_names.back();
+ _col_names_ref[_col_names.back()] = i;
+ _col_names.pop_back();
+ }
+
+ void SoplexLp::_eraseRow(int i) {
+ soplex->removeRow(i);
+ _row_names_ref.erase(_row_names[i]);
+ _row_names[i] = _row_names.back();
+ _row_names_ref[_row_names.back()] = i;
+ _row_names.pop_back();
+ }
+
+ void SoplexLp::_eraseColId(int i) {
+ cols.eraseIndex(i);
+ cols.relocateIndex(i, cols.maxIndex());
+ }
+ void SoplexLp::_eraseRowId(int i) {
+ rows.eraseIndex(i);
+ rows.relocateIndex(i, rows.maxIndex());
+ }
+
+ void SoplexLp::_getColName(int c, std::string &name) const {
+ name = _col_names[c];
+ }
+
+ void SoplexLp::_setColName(int c, const std::string &name) {
+ _col_names_ref.erase(_col_names[c]);
+ _col_names[c] = name;
+ if (!name.empty()) {
+ _col_names_ref.insert(std::make_pair(name, c));
+ }
+ }
+
+ int SoplexLp::_colByName(const std::string& name) const {
+ std::map<std::string, int>::const_iterator it =
+ _col_names_ref.find(name);
+ if (it != _col_names_ref.end()) {
+ return it->second;
+ } else {
+ return -1;
+ }
+ }
+
+ void SoplexLp::_getRowName(int r, std::string &name) const {
+ name = _row_names[r];
+ }
+
+ void SoplexLp::_setRowName(int r, const std::string &name) {
+ _row_names_ref.erase(_row_names[r]);
+ _row_names[r] = name;
+ if (!name.empty()) {
+ _row_names_ref.insert(std::make_pair(name, r));
+ }
+ }
+
+ int SoplexLp::_rowByName(const std::string& name) const {
+ std::map<std::string, int>::const_iterator it =
+ _row_names_ref.find(name);
+ if (it != _row_names_ref.end()) {
+ return it->second;
+ } else {
+ return -1;
+ }
+ }
+
+
+ void SoplexLp::_setRowCoeffs(int i, ExprIterator b, ExprIterator e) {
+ for (int j = 0; j < soplex->nCols(); ++j) {
+ soplex->changeElement(i, j, 0.0);
+ }
+ for(ExprIterator it = b; it != e; ++it) {
+ soplex->changeElement(i, it->first, it->second);
+ }
+ }
+
+ void SoplexLp::_getRowCoeffs(int i, InsertIterator b) const {
+ const soplex::SVector& vec = soplex->rowVector(i);
+ for (int k = 0; k < vec.size(); ++k) {
+ *b = std::make_pair(vec.index(k), vec.value(k));
+ ++b;
+ }
+ }
+
+ void SoplexLp::_setColCoeffs(int j, ExprIterator b, ExprIterator e) {
+ for (int i = 0; i < soplex->nRows(); ++i) {
+ soplex->changeElement(i, j, 0.0);
+ }
+ for(ExprIterator it = b; it != e; ++it) {
+ soplex->changeElement(it->first, j, it->second);
+ }
+ }
+
+ void SoplexLp::_getColCoeffs(int i, InsertIterator b) const {
+ const soplex::SVector& vec = soplex->colVector(i);
+ for (int k = 0; k < vec.size(); ++k) {
+ *b = std::make_pair(vec.index(k), vec.value(k));
+ ++b;
+ }
+ }
+
+ void SoplexLp::_setCoeff(int i, int j, Value value) {
+ soplex->changeElement(i, j, value);
+ }
+
+ SoplexLp::Value SoplexLp::_getCoeff(int i, int j) const {
+ return soplex->rowVector(i)[j];
+ }
+
+ void SoplexLp::_setColLowerBound(int i, Value value) {
+ LEMON_ASSERT(value != INF, "Invalid bound");
+ soplex->changeLower(i, value != -INF ? value : -soplex::infinity);
+ }
+
+ SoplexLp::Value SoplexLp::_getColLowerBound(int i) const {
+ double value = soplex->lower(i);
+ return value != -soplex::infinity ? value : -INF;
+ }
+
+ void SoplexLp::_setColUpperBound(int i, Value value) {
+ LEMON_ASSERT(value != -INF, "Invalid bound");
+ soplex->changeUpper(i, value != INF ? value : soplex::infinity);
+ }
+
+ SoplexLp::Value SoplexLp::_getColUpperBound(int i) const {
+ double value = soplex->upper(i);
+ return value != soplex::infinity ? value : INF;
+ }
+
+ void SoplexLp::_setRowLowerBound(int i, Value lb) {
+ LEMON_ASSERT(lb != INF, "Invalid bound");
+ soplex->changeRange(i, lb != -INF ? lb : -soplex::infinity, soplex->rhs(i));
+ }
+
+ SoplexLp::Value SoplexLp::_getRowLowerBound(int i) const {
+ double res = soplex->lhs(i);
+ return res == -soplex::infinity ? -INF : res;
+ }
+
+ void SoplexLp::_setRowUpperBound(int i, Value ub) {
+ LEMON_ASSERT(ub != -INF, "Invalid bound");
+ soplex->changeRange(i, soplex->lhs(i), ub != INF ? ub : soplex::infinity);
+ }
+
+ SoplexLp::Value SoplexLp::_getRowUpperBound(int i) const {
+ double res = soplex->rhs(i);
+ return res == soplex::infinity ? INF : res;
+ }
+
+ void SoplexLp::_setObjCoeffs(ExprIterator b, ExprIterator e) {
+ for (int j = 0; j < soplex->nCols(); ++j) {
+ soplex->changeObj(j, 0.0);
+ }
+ for (ExprIterator it = b; it != e; ++it) {
+ soplex->changeObj(it->first, it->second);
+ }
+ }
+
+ void SoplexLp::_getObjCoeffs(InsertIterator b) const {
+ for (int j = 0; j < soplex->nCols(); ++j) {
+ Value coef = soplex->obj(j);
+ if (coef != 0.0) {
+ *b = std::make_pair(j, coef);
+ ++b;
+ }
+ }
+ }
+
+ void SoplexLp::_setObjCoeff(int i, Value obj_coef) {
+ soplex->changeObj(i, obj_coef);
+ }
+
+ SoplexLp::Value SoplexLp::_getObjCoeff(int i) const {
+ return soplex->obj(i);
+ }
+
+ SoplexLp::SolveExitStatus SoplexLp::_solve() {
+
+ _clear_temporals();
+
+ _applyMessageLevel();
+
+ soplex::SPxSolver::Status status = soplex->solve();
+
+ switch (status) {
+ case soplex::SPxSolver::OPTIMAL:
+ case soplex::SPxSolver::INFEASIBLE:
+ case soplex::SPxSolver::UNBOUNDED:
+ return SOLVED;
+ default:
+ return UNSOLVED;
+ }
+ }
+
+ SoplexLp::Value SoplexLp::_getPrimal(int i) const {
+ if (_primal_values.empty()) {
+ _primal_values.resize(soplex->nCols());
+ soplex::Vector pv(_primal_values.size(), &_primal_values.front());
+ soplex->getPrimal(pv);
+ }
+ return _primal_values[i];
+ }
+
+ SoplexLp::Value SoplexLp::_getDual(int i) const {
+ if (_dual_values.empty()) {
+ _dual_values.resize(soplex->nRows());
+ soplex::Vector dv(_dual_values.size(), &_dual_values.front());
+ soplex->getDual(dv);
+ }
+ return _dual_values[i];
+ }
+
+ SoplexLp::Value SoplexLp::_getPrimalValue() const {
+ return soplex->objValue();
+ }
+
+ SoplexLp::VarStatus SoplexLp::_getColStatus(int i) const {
+ switch (soplex->getBasisColStatus(i)) {
+ case soplex::SPxSolver::BASIC:
+ return BASIC;
+ case soplex::SPxSolver::ON_UPPER:
+ return UPPER;
+ case soplex::SPxSolver::ON_LOWER:
+ return LOWER;
+ case soplex::SPxSolver::FIXED:
+ return FIXED;
+ case soplex::SPxSolver::ZERO:
+ return FREE;
+ default:
+ LEMON_ASSERT(false, "Wrong column status");
+ return VarStatus();
+ }
+ }
+
+ SoplexLp::VarStatus SoplexLp::_getRowStatus(int i) const {
+ switch (soplex->getBasisRowStatus(i)) {
+ case soplex::SPxSolver::BASIC:
+ return BASIC;
+ case soplex::SPxSolver::ON_UPPER:
+ return UPPER;
+ case soplex::SPxSolver::ON_LOWER:
+ return LOWER;
+ case soplex::SPxSolver::FIXED:
+ return FIXED;
+ case soplex::SPxSolver::ZERO:
+ return FREE;
+ default:
+ LEMON_ASSERT(false, "Wrong row status");
+ return VarStatus();
+ }
+ }
+
+ SoplexLp::Value SoplexLp::_getPrimalRay(int i) const {
+ if (_primal_ray.empty()) {
+ _primal_ray.resize(soplex->nCols());
+ soplex::Vector pv(_primal_ray.size(), &_primal_ray.front());
+ soplex->getDualfarkas(pv);
+ }
+ return _primal_ray[i];
+ }
+
+ SoplexLp::Value SoplexLp::_getDualRay(int i) const {
+ if (_dual_ray.empty()) {
+ _dual_ray.resize(soplex->nRows());
+ soplex::Vector dv(_dual_ray.size(), &_dual_ray.front());
+ soplex->getDualfarkas(dv);
+ }
+ return _dual_ray[i];
+ }
+
+ SoplexLp::ProblemType SoplexLp::_getPrimalType() const {
+ switch (soplex->status()) {
+ case soplex::SPxSolver::OPTIMAL:
+ return OPTIMAL;
+ case soplex::SPxSolver::UNBOUNDED:
+ return UNBOUNDED;
+ case soplex::SPxSolver::INFEASIBLE:
+ return INFEASIBLE;
+ default:
+ return UNDEFINED;
+ }
+ }
+
+ SoplexLp::ProblemType SoplexLp::_getDualType() const {
+ switch (soplex->status()) {
+ case soplex::SPxSolver::OPTIMAL:
+ return OPTIMAL;
+ case soplex::SPxSolver::UNBOUNDED:
+ return UNBOUNDED;
+ case soplex::SPxSolver::INFEASIBLE:
+ return INFEASIBLE;
+ default:
+ return UNDEFINED;
+ }
+ }
+
+ void SoplexLp::_setSense(Sense sense) {
+ switch (sense) {
+ case MIN:
+ soplex->changeSense(soplex::SPxSolver::MINIMIZE);
+ break;
+ case MAX:
+ soplex->changeSense(soplex::SPxSolver::MAXIMIZE);
+ }
+ }
+
+ SoplexLp::Sense SoplexLp::_getSense() const {
+ switch (soplex->spxSense()) {
+ case soplex::SPxSolver::MAXIMIZE:
+ return MAX;
+ case soplex::SPxSolver::MINIMIZE:
+ return MIN;
+ default:
+ LEMON_ASSERT(false, "Wrong sense.");
+ return SoplexLp::Sense();
+ }
+ }
+
+ void SoplexLp::_clear() {
+ soplex->clear();
+ _col_names.clear();
+ _col_names_ref.clear();
+ _row_names.clear();
+ _row_names_ref.clear();
+ cols.clear();
+ rows.clear();
+ _clear_temporals();
+ }
+
+ void SoplexLp::_messageLevel(MessageLevel level) {
+ switch (level) {
+ case MESSAGE_NOTHING:
+ _message_level = -1;
+ break;
+ case MESSAGE_ERROR:
+ _message_level = soplex::SPxOut::ERROR;
+ break;
+ case MESSAGE_WARNING:
+ _message_level = soplex::SPxOut::WARNING;
+ break;
+ case MESSAGE_NORMAL:
+ _message_level = soplex::SPxOut::INFO2;
+ break;
+ case MESSAGE_VERBOSE:
+ _message_level = soplex::SPxOut::DEBUG;
+ break;
+ }
+ }
+
+ void SoplexLp::_applyMessageLevel() {
+ soplex::Param::setVerbose(_message_level);
+ }
+
+} //namespace lemon
+
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/soplex.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/soplex.h
new file mode 100644
index 00000000000..be73f3abecd
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/soplex.h
@@ -0,0 +1,158 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_SOPLEX_H
+#define LEMON_SOPLEX_H
+
+///\file
+///\brief Header of the LEMON-SOPLEX lp solver interface.
+
+#include <vector>
+#include <string>
+
+#include <lemon/lp_base.h>
+
+// Forward declaration
+namespace soplex {
+ class SoPlex;
+}
+
+namespace lemon {
+
+ /// \ingroup lp_group
+ ///
+ /// \brief Interface for the SOPLEX solver
+ ///
+ /// This class implements an interface for the SoPlex LP solver.
+ /// The SoPlex library is an object oriented lp solver library
+ /// developed at the Konrad-Zuse-Zentrum für Informationstechnik
+ /// Berlin (ZIB). You can find detailed information about it at the
+ /// <tt>http://soplex.zib.de</tt> address.
+ class SoplexLp : public LpSolver {
+ private:
+
+ soplex::SoPlex* soplex;
+
+ std::vector<std::string> _col_names;
+ std::map<std::string, int> _col_names_ref;
+
+ std::vector<std::string> _row_names;
+ std::map<std::string, int> _row_names_ref;
+
+ private:
+
+ // these values cannot be retrieved element by element
+ mutable std::vector<Value> _primal_values;
+ mutable std::vector<Value> _dual_values;
+
+ mutable std::vector<Value> _primal_ray;
+ mutable std::vector<Value> _dual_ray;
+
+ void _clear_temporals();
+
+ public:
+
+ /// \e
+ SoplexLp();
+ /// \e
+ SoplexLp(const SoplexLp&);
+ /// \e
+ ~SoplexLp();
+ /// \e
+ virtual SoplexLp* newSolver() const;
+ /// \e
+ virtual SoplexLp* cloneSolver() const;
+
+ protected:
+
+ virtual const char* _solverName() const;
+
+ virtual int _addCol();
+ virtual int _addRow();
+ virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
+
+ virtual void _eraseCol(int i);
+ virtual void _eraseRow(int i);
+
+ virtual void _eraseColId(int i);
+ virtual void _eraseRowId(int i);
+
+ virtual void _getColName(int col, std::string& name) const;
+ virtual void _setColName(int col, const std::string& name);
+ virtual int _colByName(const std::string& name) const;
+
+ virtual void _getRowName(int row, std::string& name) const;
+ virtual void _setRowName(int row, const std::string& name);
+ virtual int _rowByName(const std::string& name) const;
+
+ virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
+ virtual void _getRowCoeffs(int i, InsertIterator b) const;
+
+ virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
+ virtual void _getColCoeffs(int i, InsertIterator b) const;
+
+ virtual void _setCoeff(int row, int col, Value value);
+ virtual Value _getCoeff(int row, int col) const;
+
+ virtual void _setColLowerBound(int i, Value value);
+ virtual Value _getColLowerBound(int i) const;
+ virtual void _setColUpperBound(int i, Value value);
+ virtual Value _getColUpperBound(int i) const;
+
+ virtual void _setRowLowerBound(int i, Value value);
+ virtual Value _getRowLowerBound(int i) const;
+ virtual void _setRowUpperBound(int i, Value value);
+ virtual Value _getRowUpperBound(int i) const;
+
+ virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
+ virtual void _getObjCoeffs(InsertIterator b) const;
+
+ virtual void _setObjCoeff(int i, Value obj_coef);
+ virtual Value _getObjCoeff(int i) const;
+
+ virtual void _setSense(Sense sense);
+ virtual Sense _getSense() const;
+
+ virtual SolveExitStatus _solve();
+ virtual Value _getPrimal(int i) const;
+ virtual Value _getDual(int i) const;
+
+ virtual Value _getPrimalValue() const;
+
+ virtual Value _getPrimalRay(int i) const;
+ virtual Value _getDualRay(int i) const;
+
+ virtual VarStatus _getColStatus(int i) const;
+ virtual VarStatus _getRowStatus(int i) const;
+
+ virtual ProblemType _getPrimalType() const;
+ virtual ProblemType _getDualType() const;
+
+ virtual void _clear();
+
+ void _messageLevel(MessageLevel m);
+ void _applyMessageLevel();
+
+ int _message_level;
+
+ };
+
+} //END OF NAMESPACE LEMON
+
+#endif //LEMON_SOPLEX_H
+
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/static_graph.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/static_graph.h
new file mode 100644
index 00000000000..1f04e40841c
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/static_graph.h
@@ -0,0 +1,476 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2010
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_STATIC_GRAPH_H
+#define LEMON_STATIC_GRAPH_H
+
+///\ingroup graphs
+///\file
+///\brief StaticDigraph class.
+
+#include <lemon/core.h>
+#include <lemon/bits/graph_extender.h>
+
+namespace lemon {
+
+ class StaticDigraphBase {
+ public:
+
+ StaticDigraphBase()
+ : built(false), node_num(0), arc_num(0),
+ node_first_out(NULL), node_first_in(NULL),
+ arc_source(NULL), arc_target(NULL),
+ arc_next_in(NULL), arc_next_out(NULL) {}
+
+ ~StaticDigraphBase() {
+ if (built) {
+ delete[] node_first_out;
+ delete[] node_first_in;
+ delete[] arc_source;
+ delete[] arc_target;
+ delete[] arc_next_out;
+ delete[] arc_next_in;
+ }
+ }
+
+ class Node {
+ friend class StaticDigraphBase;
+ protected:
+ int id;
+ Node(int _id) : id(_id) {}
+ public:
+ Node() {}
+ Node (Invalid) : id(-1) {}
+ bool operator==(const Node& node) const { return id == node.id; }
+ bool operator!=(const Node& node) const { return id != node.id; }
+ bool operator<(const Node& node) const { return id < node.id; }
+ };
+
+ class Arc {
+ friend class StaticDigraphBase;
+ protected:
+ int id;
+ Arc(int _id) : id(_id) {}
+ public:
+ Arc() { }
+ Arc (Invalid) : id(-1) {}
+ bool operator==(const Arc& arc) const { return id == arc.id; }
+ bool operator!=(const Arc& arc) const { return id != arc.id; }
+ bool operator<(const Arc& arc) const { return id < arc.id; }
+ };
+
+ Node source(const Arc& e) const { return Node(arc_source[e.id]); }
+ Node target(const Arc& e) const { return Node(arc_target[e.id]); }
+
+ void first(Node& n) const { n.id = node_num - 1; }
+ static void next(Node& n) { --n.id; }
+
+ void first(Arc& e) const { e.id = arc_num - 1; }
+ static void next(Arc& e) { --e.id; }
+
+ void firstOut(Arc& e, const Node& n) const {
+ e.id = node_first_out[n.id] != node_first_out[n.id + 1] ?
+ node_first_out[n.id] : -1;
+ }
+ void nextOut(Arc& e) const { e.id = arc_next_out[e.id]; }
+
+ void firstIn(Arc& e, const Node& n) const { e.id = node_first_in[n.id]; }
+ void nextIn(Arc& e) const { e.id = arc_next_in[e.id]; }
+
+ static int id(const Node& n) { return n.id; }
+ static Node nodeFromId(int id) { return Node(id); }
+ int maxNodeId() const { return node_num - 1; }
+
+ static int id(const Arc& e) { return e.id; }
+ static Arc arcFromId(int id) { return Arc(id); }
+ int maxArcId() const { return arc_num - 1; }
+
+ typedef True NodeNumTag;
+ typedef True ArcNumTag;
+
+ int nodeNum() const { return node_num; }
+ int arcNum() const { return arc_num; }
+
+ private:
+
+ template <typename Digraph, typename NodeRefMap>
+ class ArcLess {
+ public:
+ typedef typename Digraph::Arc Arc;
+
+ ArcLess(const Digraph &_graph, const NodeRefMap& _nodeRef)
+ : digraph(_graph), nodeRef(_nodeRef) {}
+
+ bool operator()(const Arc& left, const Arc& right) const {
+ return nodeRef[digraph.target(left)] < nodeRef[digraph.target(right)];
+ }
+ private:
+ const Digraph& digraph;
+ const NodeRefMap& nodeRef;
+ };
+
+ public:
+
+ typedef True BuildTag;
+
+ void clear() {
+ if (built) {
+ delete[] node_first_out;
+ delete[] node_first_in;
+ delete[] arc_source;
+ delete[] arc_target;
+ delete[] arc_next_out;
+ delete[] arc_next_in;
+ }
+ built = false;
+ node_num = 0;
+ arc_num = 0;
+ }
+
+ template <typename Digraph, typename NodeRefMap, typename ArcRefMap>
+ void build(const Digraph& digraph, NodeRefMap& nodeRef, ArcRefMap& arcRef) {
+ typedef typename Digraph::Node GNode;
+ typedef typename Digraph::Arc GArc;
+
+ built = true;
+
+ node_num = countNodes(digraph);
+ arc_num = countArcs(digraph);
+
+ node_first_out = new int[node_num + 1];
+ node_first_in = new int[node_num];
+
+ arc_source = new int[arc_num];
+ arc_target = new int[arc_num];
+ arc_next_out = new int[arc_num];
+ arc_next_in = new int[arc_num];
+
+ int node_index = 0;
+ for (typename Digraph::NodeIt n(digraph); n != INVALID; ++n) {
+ nodeRef[n] = Node(node_index);
+ node_first_in[node_index] = -1;
+ ++node_index;
+ }
+
+ ArcLess<Digraph, NodeRefMap> arcLess(digraph, nodeRef);
+
+ int arc_index = 0;
+ for (typename Digraph::NodeIt n(digraph); n != INVALID; ++n) {
+ int source = nodeRef[n].id;
+ std::vector<GArc> arcs;
+ for (typename Digraph::OutArcIt e(digraph, n); e != INVALID; ++e) {
+ arcs.push_back(e);
+ }
+ if (!arcs.empty()) {
+ node_first_out[source] = arc_index;
+ std::sort(arcs.begin(), arcs.end(), arcLess);
+ for (typename std::vector<GArc>::iterator it = arcs.begin();
+ it != arcs.end(); ++it) {
+ int target = nodeRef[digraph.target(*it)].id;
+ arcRef[*it] = Arc(arc_index);
+ arc_source[arc_index] = source;
+ arc_target[arc_index] = target;
+ arc_next_in[arc_index] = node_first_in[target];
+ node_first_in[target] = arc_index;
+ arc_next_out[arc_index] = arc_index + 1;
+ ++arc_index;
+ }
+ arc_next_out[arc_index - 1] = -1;
+ } else {
+ node_first_out[source] = arc_index;
+ }
+ }
+ node_first_out[node_num] = arc_num;
+ }
+
+ template <typename ArcListIterator>
+ void build(int n, ArcListIterator first, ArcListIterator last) {
+ built = true;
+
+ node_num = n;
+ arc_num = std::distance(first, last);
+
+ node_first_out = new int[node_num + 1];
+ node_first_in = new int[node_num];
+
+ arc_source = new int[arc_num];
+ arc_target = new int[arc_num];
+ arc_next_out = new int[arc_num];
+ arc_next_in = new int[arc_num];
+
+ for (int i = 0; i != node_num; ++i) {
+ node_first_in[i] = -1;
+ }
+
+ int arc_index = 0;
+ for (int i = 0; i != node_num; ++i) {
+ node_first_out[i] = arc_index;
+ for ( ; first != last && (*first).first == i; ++first) {
+ int j = (*first).second;
+ LEMON_ASSERT(j >= 0 && j < node_num,
+ "Wrong arc list for StaticDigraph::build()");
+ arc_source[arc_index] = i;
+ arc_target[arc_index] = j;
+ arc_next_in[arc_index] = node_first_in[j];
+ node_first_in[j] = arc_index;
+ arc_next_out[arc_index] = arc_index + 1;
+ ++arc_index;
+ }
+ if (arc_index > node_first_out[i])
+ arc_next_out[arc_index - 1] = -1;
+ }
+ LEMON_ASSERT(first == last,
+ "Wrong arc list for StaticDigraph::build()");
+ node_first_out[node_num] = arc_num;
+ }
+
+ protected:
+
+ void fastFirstOut(Arc& e, const Node& n) const {
+ e.id = node_first_out[n.id];
+ }
+
+ static void fastNextOut(Arc& e) {
+ ++e.id;
+ }
+ void fastLastOut(Arc& e, const Node& n) const {
+ e.id = node_first_out[n.id + 1];
+ }
+
+ protected:
+ bool built;
+ int node_num;
+ int arc_num;
+ int *node_first_out;
+ int *node_first_in;
+ int *arc_source;
+ int *arc_target;
+ int *arc_next_in;
+ int *arc_next_out;
+ };
+
+ typedef DigraphExtender<StaticDigraphBase> ExtendedStaticDigraphBase;
+
+
+ /// \ingroup graphs
+ ///
+ /// \brief A static directed graph class.
+ ///
+ /// \ref StaticDigraph is a highly efficient digraph implementation,
+ /// but it is fully static.
+ /// It stores only two \c int values for each node and only four \c int
+ /// values for each arc. Moreover it provides faster item iteration than
+ /// \ref ListDigraph and \ref SmartDigraph, especially using \c OutArcIt
+ /// iterators, since its arcs are stored in an appropriate order.
+ /// However it only provides build() and clear() functions and does not
+ /// support any other modification of the digraph.
+ ///
+ /// Since this digraph structure is completely static, its nodes and arcs
+ /// can be indexed with integers from the ranges <tt>[0..nodeNum()-1]</tt>
+ /// and <tt>[0..arcNum()-1]</tt>, respectively.
+ /// The index of an item is the same as its ID, it can be obtained
+ /// using the corresponding \ref index() or \ref concepts::Digraph::id()
+ /// "id()" function. A node or arc with a certain index can be obtained
+ /// using node() or arc().
+ ///
+ /// This type fully conforms to the \ref concepts::Digraph "Digraph concept".
+ /// Most of its member functions and nested classes are documented
+ /// only in the concept class.
+ ///
+ /// This class provides constant time counting for nodes and arcs.
+ ///
+ /// \sa concepts::Digraph
+ class StaticDigraph : public ExtendedStaticDigraphBase {
+ public:
+
+ typedef ExtendedStaticDigraphBase Parent;
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Default constructor.
+ StaticDigraph() : Parent() {}
+
+ /// \brief The node with the given index.
+ ///
+ /// This function returns the node with the given index.
+ /// \sa index()
+ static Node node(int ix) { return Parent::nodeFromId(ix); }
+
+ /// \brief The arc with the given index.
+ ///
+ /// This function returns the arc with the given index.
+ /// \sa index()
+ static Arc arc(int ix) { return Parent::arcFromId(ix); }
+
+ /// \brief The index of the given node.
+ ///
+ /// This function returns the index of the the given node.
+ /// \sa node()
+ static int index(Node node) { return Parent::id(node); }
+
+ /// \brief The index of the given arc.
+ ///
+ /// This function returns the index of the the given arc.
+ /// \sa arc()
+ static int index(Arc arc) { return Parent::id(arc); }
+
+ /// \brief Number of nodes.
+ ///
+ /// This function returns the number of nodes.
+ int nodeNum() const { return node_num; }
+
+ /// \brief Number of arcs.
+ ///
+ /// This function returns the number of arcs.
+ int arcNum() const { return arc_num; }
+
+ /// \brief Build the digraph copying another digraph.
+ ///
+ /// This function builds the digraph copying another digraph of any
+ /// kind. It can be called more than once, but in such case, the whole
+ /// structure and all maps will be cleared and rebuilt.
+ ///
+ /// This method also makes possible to copy a digraph to a StaticDigraph
+ /// structure using \ref DigraphCopy.
+ ///
+ /// \param digraph An existing digraph to be copied.
+ /// \param nodeRef The node references will be copied into this map.
+ /// Its key type must be \c Digraph::Node and its value type must be
+ /// \c StaticDigraph::Node.
+ /// It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap"
+ /// concept.
+ /// \param arcRef The arc references will be copied into this map.
+ /// Its key type must be \c Digraph::Arc and its value type must be
+ /// \c StaticDigraph::Arc.
+ /// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
+ ///
+ /// \note If you do not need the arc references, then you could use
+ /// \ref NullMap for the last parameter. However the node references
+ /// are required by the function itself, thus they must be readable
+ /// from the map.
+ template <typename Digraph, typename NodeRefMap, typename ArcRefMap>
+ void build(const Digraph& digraph, NodeRefMap& nodeRef, ArcRefMap& arcRef) {
+ if (built) Parent::clear();
+ Parent::build(digraph, nodeRef, arcRef);
+ }
+
+ /// \brief Build the digraph from an arc list.
+ ///
+ /// This function builds the digraph from the given arc list.
+ /// It can be called more than once, but in such case, the whole
+ /// structure and all maps will be cleared and rebuilt.
+ ///
+ /// The list of the arcs must be given in the range <tt>[begin, end)</tt>
+ /// specified by STL compatible itartors whose \c value_type must be
+ /// <tt>std::pair<int,int></tt>.
+ /// Each arc must be specified by a pair of integer indices
+ /// from the range <tt>[0..n-1]</tt>. <i>The pairs must be in a
+ /// non-decreasing order with respect to their first values.</i>
+ /// If the k-th pair in the list is <tt>(i,j)</tt>, then
+ /// <tt>arc(k-1)</tt> will connect <tt>node(i)</tt> to <tt>node(j)</tt>.
+ ///
+ /// \param n The number of nodes.
+ /// \param begin An iterator pointing to the beginning of the arc list.
+ /// \param end An iterator pointing to the end of the arc list.
+ ///
+ /// For example, a simple digraph can be constructed like this.
+ /// \code
+ /// std::vector<std::pair<int,int> > arcs;
+ /// arcs.push_back(std::make_pair(0,1));
+ /// arcs.push_back(std::make_pair(0,2));
+ /// arcs.push_back(std::make_pair(1,3));
+ /// arcs.push_back(std::make_pair(1,2));
+ /// arcs.push_back(std::make_pair(3,0));
+ /// StaticDigraph gr;
+ /// gr.build(4, arcs.begin(), arcs.end());
+ /// \endcode
+ template <typename ArcListIterator>
+ void build(int n, ArcListIterator begin, ArcListIterator end) {
+ if (built) Parent::clear();
+ StaticDigraphBase::build(n, begin, end);
+ notifier(Node()).build();
+ notifier(Arc()).build();
+ }
+
+ /// \brief Clear the digraph.
+ ///
+ /// This function erases all nodes and arcs from the digraph.
+ void clear() {
+ Parent::clear();
+ }
+
+ protected:
+
+ using Parent::fastFirstOut;
+ using Parent::fastNextOut;
+ using Parent::fastLastOut;
+
+ public:
+
+ class OutArcIt : public Arc {
+ public:
+
+ OutArcIt() { }
+
+ OutArcIt(Invalid i) : Arc(i) { }
+
+ OutArcIt(const StaticDigraph& digraph, const Node& node) {
+ digraph.fastFirstOut(*this, node);
+ digraph.fastLastOut(last, node);
+ if (last == *this) *this = INVALID;
+ }
+
+ OutArcIt(const StaticDigraph& digraph, const Arc& arc) : Arc(arc) {
+ if (arc != INVALID) {
+ digraph.fastLastOut(last, digraph.source(arc));
+ }
+ }
+
+ OutArcIt& operator++() {
+ StaticDigraph::fastNextOut(*this);
+ if (last == *this) *this = INVALID;
+ return *this;
+ }
+
+ private:
+ Arc last;
+ };
+
+ Node baseNode(const OutArcIt &arc) const {
+ return Parent::source(static_cast<const Arc&>(arc));
+ }
+
+ Node runningNode(const OutArcIt &arc) const {
+ return Parent::target(static_cast<const Arc&>(arc));
+ }
+
+ Node baseNode(const InArcIt &arc) const {
+ return Parent::target(static_cast<const Arc&>(arc));
+ }
+
+ Node runningNode(const InArcIt &arc) const {
+ return Parent::source(static_cast<const Arc&>(arc));
+ }
+
+ };
+
+}
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/suurballe.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/suurballe.h
new file mode 100644
index 00000000000..f1338a2948f
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/suurballe.h
@@ -0,0 +1,776 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_SUURBALLE_H
+#define LEMON_SUURBALLE_H
+
+///\ingroup shortest_path
+///\file
+///\brief An algorithm for finding arc-disjoint paths between two
+/// nodes having minimum total length.
+
+#include <vector>
+#include <limits>
+#include <lemon/bin_heap.h>
+#include <lemon/path.h>
+#include <lemon/list_graph.h>
+#include <lemon/dijkstra.h>
+#include <lemon/maps.h>
+
+namespace lemon {
+
+ /// \brief Default traits class of Suurballe algorithm.
+ ///
+ /// Default traits class of Suurballe algorithm.
+ /// \tparam GR The digraph type the algorithm runs on.
+ /// \tparam LEN The type of the length map.
+ /// The default value is <tt>GR::ArcMap<int></tt>.
+#ifdef DOXYGEN
+ template <typename GR, typename LEN>
+#else
+ template < typename GR,
+ typename LEN = typename GR::template ArcMap<int> >
+#endif
+ struct SuurballeDefaultTraits
+ {
+ /// The type of the digraph.
+ typedef GR Digraph;
+ /// The type of the length map.
+ typedef LEN LengthMap;
+ /// The type of the lengths.
+ typedef typename LEN::Value Length;
+ /// The type of the flow map.
+ typedef typename GR::template ArcMap<int> FlowMap;
+ /// The type of the potential map.
+ typedef typename GR::template NodeMap<Length> PotentialMap;
+
+ /// \brief The path type
+ ///
+ /// The type used for storing the found arc-disjoint paths.
+ /// It must conform to the \ref lemon::concepts::Path "Path" concept
+ /// and it must have an \c addBack() function.
+ typedef lemon::Path<Digraph> Path;
+
+ /// The cross reference type used for the heap.
+ typedef typename GR::template NodeMap<int> HeapCrossRef;
+
+ /// \brief The heap type used for internal Dijkstra computations.
+ ///
+ /// The type of the heap used for internal Dijkstra computations.
+ /// It must conform to the \ref lemon::concepts::Heap "Heap" concept
+ /// and its priority type must be \c Length.
+ typedef BinHeap<Length, HeapCrossRef> Heap;
+ };
+
+ /// \addtogroup shortest_path
+ /// @{
+
+ /// \brief Algorithm for finding arc-disjoint paths between two nodes
+ /// having minimum total length.
+ ///
+ /// \ref lemon::Suurballe "Suurballe" implements an algorithm for
+ /// finding arc-disjoint paths having minimum total length (cost)
+ /// from a given source node to a given target node in a digraph.
+ ///
+ /// Note that this problem is a special case of the \ref min_cost_flow
+ /// "minimum cost flow problem". This implementation is actually an
+ /// efficient specialized version of the \ref CapacityScaling
+ /// "successive shortest path" algorithm directly for this problem.
+ /// Therefore this class provides query functions for flow values and
+ /// node potentials (the dual solution) just like the minimum cost flow
+ /// algorithms.
+ ///
+ /// \tparam GR The digraph type the algorithm runs on.
+ /// \tparam LEN The type of the length map.
+ /// The default value is <tt>GR::ArcMap<int></tt>.
+ ///
+ /// \warning Length values should be \e non-negative.
+ ///
+ /// \note For finding \e node-disjoint paths, this algorithm can be used
+ /// along with the \ref SplitNodes adaptor.
+#ifdef DOXYGEN
+ template <typename GR, typename LEN, typename TR>
+#else
+ template < typename GR,
+ typename LEN = typename GR::template ArcMap<int>,
+ typename TR = SuurballeDefaultTraits<GR, LEN> >
+#endif
+ class Suurballe
+ {
+ TEMPLATE_DIGRAPH_TYPEDEFS(GR);
+
+ typedef ConstMap<Arc, int> ConstArcMap;
+ typedef typename GR::template NodeMap<Arc> PredMap;
+
+ public:
+
+ /// The type of the digraph.
+ typedef typename TR::Digraph Digraph;
+ /// The type of the length map.
+ typedef typename TR::LengthMap LengthMap;
+ /// The type of the lengths.
+ typedef typename TR::Length Length;
+
+ /// The type of the flow map.
+ typedef typename TR::FlowMap FlowMap;
+ /// The type of the potential map.
+ typedef typename TR::PotentialMap PotentialMap;
+ /// The type of the path structures.
+ typedef typename TR::Path Path;
+ /// The cross reference type used for the heap.
+ typedef typename TR::HeapCrossRef HeapCrossRef;
+ /// The heap type used for internal Dijkstra computations.
+ typedef typename TR::Heap Heap;
+
+ /// The \ref lemon::SuurballeDefaultTraits "traits class" of the algorithm.
+ typedef TR Traits;
+
+ private:
+
+ // ResidualDijkstra is a special implementation of the
+ // Dijkstra algorithm for finding shortest paths in the
+ // residual network with respect to the reduced arc lengths
+ // and modifying the node potentials according to the
+ // distance of the nodes.
+ class ResidualDijkstra
+ {
+ private:
+
+ const Digraph &_graph;
+ const LengthMap &_length;
+ const FlowMap &_flow;
+ PotentialMap &_pi;
+ PredMap &_pred;
+ Node _s;
+ Node _t;
+
+ PotentialMap _dist;
+ std::vector<Node> _proc_nodes;
+
+ public:
+
+ // Constructor
+ ResidualDijkstra(Suurballe &srb) :
+ _graph(srb._graph), _length(srb._length),
+ _flow(*srb._flow), _pi(*srb._potential), _pred(srb._pred),
+ _s(srb._s), _t(srb._t), _dist(_graph) {}
+
+ // Run the algorithm and return true if a path is found
+ // from the source node to the target node.
+ bool run(int cnt) {
+ return cnt == 0 ? startFirst() : start();
+ }
+
+ private:
+
+ // Execute the algorithm for the first time (the flow and potential
+ // functions have to be identically zero).
+ bool startFirst() {
+ HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP);
+ Heap heap(heap_cross_ref);
+ heap.push(_s, 0);
+ _pred[_s] = INVALID;
+ _proc_nodes.clear();
+
+ // Process nodes
+ while (!heap.empty() && heap.top() != _t) {
+ Node u = heap.top(), v;
+ Length d = heap.prio(), dn;
+ _dist[u] = heap.prio();
+ _proc_nodes.push_back(u);
+ heap.pop();
+
+ // Traverse outgoing arcs
+ for (OutArcIt e(_graph, u); e != INVALID; ++e) {
+ v = _graph.target(e);
+ switch(heap.state(v)) {
+ case Heap::PRE_HEAP:
+ heap.push(v, d + _length[e]);
+ _pred[v] = e;
+ break;
+ case Heap::IN_HEAP:
+ dn = d + _length[e];
+ if (dn < heap[v]) {
+ heap.decrease(v, dn);
+ _pred[v] = e;
+ }
+ break;
+ case Heap::POST_HEAP:
+ break;
+ }
+ }
+ }
+ if (heap.empty()) return false;
+
+ // Update potentials of processed nodes
+ Length t_dist = heap.prio();
+ for (int i = 0; i < int(_proc_nodes.size()); ++i)
+ _pi[_proc_nodes[i]] = _dist[_proc_nodes[i]] - t_dist;
+ return true;
+ }
+
+ // Execute the algorithm.
+ bool start() {
+ HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP);
+ Heap heap(heap_cross_ref);
+ heap.push(_s, 0);
+ _pred[_s] = INVALID;
+ _proc_nodes.clear();
+
+ // Process nodes
+ while (!heap.empty() && heap.top() != _t) {
+ Node u = heap.top(), v;
+ Length d = heap.prio() + _pi[u], dn;
+ _dist[u] = heap.prio();
+ _proc_nodes.push_back(u);
+ heap.pop();
+
+ // Traverse outgoing arcs
+ for (OutArcIt e(_graph, u); e != INVALID; ++e) {
+ if (_flow[e] == 0) {
+ v = _graph.target(e);
+ switch(heap.state(v)) {
+ case Heap::PRE_HEAP:
+ heap.push(v, d + _length[e] - _pi[v]);
+ _pred[v] = e;
+ break;
+ case Heap::IN_HEAP:
+ dn = d + _length[e] - _pi[v];
+ if (dn < heap[v]) {
+ heap.decrease(v, dn);
+ _pred[v] = e;
+ }
+ break;
+ case Heap::POST_HEAP:
+ break;
+ }
+ }
+ }
+
+ // Traverse incoming arcs
+ for (InArcIt e(_graph, u); e != INVALID; ++e) {
+ if (_flow[e] == 1) {
+ v = _graph.source(e);
+ switch(heap.state(v)) {
+ case Heap::PRE_HEAP:
+ heap.push(v, d - _length[e] - _pi[v]);
+ _pred[v] = e;
+ break;
+ case Heap::IN_HEAP:
+ dn = d - _length[e] - _pi[v];
+ if (dn < heap[v]) {
+ heap.decrease(v, dn);
+ _pred[v] = e;
+ }
+ break;
+ case Heap::POST_HEAP:
+ break;
+ }
+ }
+ }
+ }
+ if (heap.empty()) return false;
+
+ // Update potentials of processed nodes
+ Length t_dist = heap.prio();
+ for (int i = 0; i < int(_proc_nodes.size()); ++i)
+ _pi[_proc_nodes[i]] += _dist[_proc_nodes[i]] - t_dist;
+ return true;
+ }
+
+ }; //class ResidualDijkstra
+
+ public:
+
+ /// \name Named Template Parameters
+ /// @{
+
+ template <typename T>
+ struct SetFlowMapTraits : public Traits {
+ typedef T FlowMap;
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// \c FlowMap type.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting
+ /// \c FlowMap type.
+ template <typename T>
+ struct SetFlowMap
+ : public Suurballe<GR, LEN, SetFlowMapTraits<T> > {
+ typedef Suurballe<GR, LEN, SetFlowMapTraits<T> > Create;
+ };
+
+ template <typename T>
+ struct SetPotentialMapTraits : public Traits {
+ typedef T PotentialMap;
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// \c PotentialMap type.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting
+ /// \c PotentialMap type.
+ template <typename T>
+ struct SetPotentialMap
+ : public Suurballe<GR, LEN, SetPotentialMapTraits<T> > {
+ typedef Suurballe<GR, LEN, SetPotentialMapTraits<T> > Create;
+ };
+
+ template <typename T>
+ struct SetPathTraits : public Traits {
+ typedef T Path;
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// \c %Path type.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting \c %Path type.
+ /// It must conform to the \ref lemon::concepts::Path "Path" concept
+ /// and it must have an \c addBack() function.
+ template <typename T>
+ struct SetPath
+ : public Suurballe<GR, LEN, SetPathTraits<T> > {
+ typedef Suurballe<GR, LEN, SetPathTraits<T> > Create;
+ };
+
+ template <typename H, typename CR>
+ struct SetHeapTraits : public Traits {
+ typedef H Heap;
+ typedef CR HeapCrossRef;
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// \c Heap and \c HeapCrossRef types.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting \c Heap
+ /// and \c HeapCrossRef types with automatic allocation.
+ /// They will be used for internal Dijkstra computations.
+ /// The heap type must conform to the \ref lemon::concepts::Heap "Heap"
+ /// concept and its priority type must be \c Length.
+ template <typename H,
+ typename CR = typename Digraph::template NodeMap<int> >
+ struct SetHeap
+ : public Suurballe<GR, LEN, SetHeapTraits<H, CR> > {
+ typedef Suurballe<GR, LEN, SetHeapTraits<H, CR> > Create;
+ };
+
+ /// @}
+
+ private:
+
+ // The digraph the algorithm runs on
+ const Digraph &_graph;
+ // The length map
+ const LengthMap &_length;
+
+ // Arc map of the current flow
+ FlowMap *_flow;
+ bool _local_flow;
+ // Node map of the current potentials
+ PotentialMap *_potential;
+ bool _local_potential;
+
+ // The source node
+ Node _s;
+ // The target node
+ Node _t;
+
+ // Container to store the found paths
+ std::vector<Path> _paths;
+ int _path_num;
+
+ // The pred arc map
+ PredMap _pred;
+
+ // Data for full init
+ PotentialMap *_init_dist;
+ PredMap *_init_pred;
+ bool _full_init;
+
+ protected:
+
+ Suurballe() {}
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ /// Constructor.
+ ///
+ /// \param graph The digraph the algorithm runs on.
+ /// \param length The length (cost) values of the arcs.
+ Suurballe( const Digraph &graph,
+ const LengthMap &length ) :
+ _graph(graph), _length(length), _flow(0), _local_flow(false),
+ _potential(0), _local_potential(false), _pred(graph),
+ _init_dist(0), _init_pred(0)
+ {}
+
+ /// Destructor.
+ ~Suurballe() {
+ if (_local_flow) delete _flow;
+ if (_local_potential) delete _potential;
+ delete _init_dist;
+ delete _init_pred;
+ }
+
+ /// \brief Set the flow map.
+ ///
+ /// This function sets the flow map.
+ /// If it is not used before calling \ref run() or \ref init(),
+ /// an instance will be allocated automatically. The destructor
+ /// deallocates this automatically allocated map, of course.
+ ///
+ /// The found flow contains only 0 and 1 values, since it is the
+ /// union of the found arc-disjoint paths.
+ ///
+ /// \return <tt>(*this)</tt>
+ Suurballe& flowMap(FlowMap &map) {
+ if (_local_flow) {
+ delete _flow;
+ _local_flow = false;
+ }
+ _flow = &map;
+ return *this;
+ }
+
+ /// \brief Set the potential map.
+ ///
+ /// This function sets the potential map.
+ /// If it is not used before calling \ref run() or \ref init(),
+ /// an instance will be allocated automatically. The destructor
+ /// deallocates this automatically allocated map, of course.
+ ///
+ /// The node potentials provide the dual solution of the underlying
+ /// \ref min_cost_flow "minimum cost flow problem".
+ ///
+ /// \return <tt>(*this)</tt>
+ Suurballe& potentialMap(PotentialMap &map) {
+ if (_local_potential) {
+ delete _potential;
+ _local_potential = false;
+ }
+ _potential = &map;
+ return *this;
+ }
+
+ /// \name Execution Control
+ /// The simplest way to execute the algorithm is to call the run()
+ /// function.\n
+ /// If you need to execute the algorithm many times using the same
+ /// source node, then you may call fullInit() once and start()
+ /// for each target node.\n
+ /// If you only need the flow that is the union of the found
+ /// arc-disjoint paths, then you may call findFlow() instead of
+ /// start().
+
+ /// @{
+
+ /// \brief Run the algorithm.
+ ///
+ /// This function runs the algorithm.
+ ///
+ /// \param s The source node.
+ /// \param t The target node.
+ /// \param k The number of paths to be found.
+ ///
+ /// \return \c k if there are at least \c k arc-disjoint paths from
+ /// \c s to \c t in the digraph. Otherwise it returns the number of
+ /// arc-disjoint paths found.
+ ///
+ /// \note Apart from the return value, <tt>s.run(s, t, k)</tt> is
+ /// just a shortcut of the following code.
+ /// \code
+ /// s.init(s);
+ /// s.start(t, k);
+ /// \endcode
+ int run(const Node& s, const Node& t, int k = 2) {
+ init(s);
+ start(t, k);
+ return _path_num;
+ }
+
+ /// \brief Initialize the algorithm.
+ ///
+ /// This function initializes the algorithm with the given source node.
+ ///
+ /// \param s The source node.
+ void init(const Node& s) {
+ _s = s;
+
+ // Initialize maps
+ if (!_flow) {
+ _flow = new FlowMap(_graph);
+ _local_flow = true;
+ }
+ if (!_potential) {
+ _potential = new PotentialMap(_graph);
+ _local_potential = true;
+ }
+ _full_init = false;
+ }
+
+ /// \brief Initialize the algorithm and perform Dijkstra.
+ ///
+ /// This function initializes the algorithm and performs a full
+ /// Dijkstra search from the given source node. It makes consecutive
+ /// executions of \ref start() "start(t, k)" faster, since they
+ /// have to perform %Dijkstra only k-1 times.
+ ///
+ /// This initialization is usually worth using instead of \ref init()
+ /// if the algorithm is executed many times using the same source node.
+ ///
+ /// \param s The source node.
+ void fullInit(const Node& s) {
+ // Initialize maps
+ init(s);
+ if (!_init_dist) {
+ _init_dist = new PotentialMap(_graph);
+ }
+ if (!_init_pred) {
+ _init_pred = new PredMap(_graph);
+ }
+
+ // Run a full Dijkstra
+ typename Dijkstra<Digraph, LengthMap>
+ ::template SetStandardHeap<Heap>
+ ::template SetDistMap<PotentialMap>
+ ::template SetPredMap<PredMap>
+ ::Create dijk(_graph, _length);
+ dijk.distMap(*_init_dist).predMap(*_init_pred);
+ dijk.run(s);
+
+ _full_init = true;
+ }
+
+ /// \brief Execute the algorithm.
+ ///
+ /// This function executes the algorithm.
+ ///
+ /// \param t The target node.
+ /// \param k The number of paths to be found.
+ ///
+ /// \return \c k if there are at least \c k arc-disjoint paths from
+ /// \c s to \c t in the digraph. Otherwise it returns the number of
+ /// arc-disjoint paths found.
+ ///
+ /// \note Apart from the return value, <tt>s.start(t, k)</tt> is
+ /// just a shortcut of the following code.
+ /// \code
+ /// s.findFlow(t, k);
+ /// s.findPaths();
+ /// \endcode
+ int start(const Node& t, int k = 2) {
+ findFlow(t, k);
+ findPaths();
+ return _path_num;
+ }
+
+ /// \brief Execute the algorithm to find an optimal flow.
+ ///
+ /// This function executes the successive shortest path algorithm to
+ /// find a minimum cost flow, which is the union of \c k (or less)
+ /// arc-disjoint paths.
+ ///
+ /// \param t The target node.
+ /// \param k The number of paths to be found.
+ ///
+ /// \return \c k if there are at least \c k arc-disjoint paths from
+ /// the source node to the given node \c t in the digraph.
+ /// Otherwise it returns the number of arc-disjoint paths found.
+ ///
+ /// \pre \ref init() must be called before using this function.
+ int findFlow(const Node& t, int k = 2) {
+ _t = t;
+ ResidualDijkstra dijkstra(*this);
+
+ // Initialization
+ for (ArcIt e(_graph); e != INVALID; ++e) {
+ (*_flow)[e] = 0;
+ }
+ if (_full_init) {
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ (*_potential)[n] = (*_init_dist)[n];
+ }
+ Node u = _t;
+ Arc e;
+ while ((e = (*_init_pred)[u]) != INVALID) {
+ (*_flow)[e] = 1;
+ u = _graph.source(e);
+ }
+ _path_num = 1;
+ } else {
+ for (NodeIt n(_graph); n != INVALID; ++n) {
+ (*_potential)[n] = 0;
+ }
+ _path_num = 0;
+ }
+
+ // Find shortest paths
+ while (_path_num < k) {
+ // Run Dijkstra
+ if (!dijkstra.run(_path_num)) break;
+ ++_path_num;
+
+ // Set the flow along the found shortest path
+ Node u = _t;
+ Arc e;
+ while ((e = _pred[u]) != INVALID) {
+ if (u == _graph.target(e)) {
+ (*_flow)[e] = 1;
+ u = _graph.source(e);
+ } else {
+ (*_flow)[e] = 0;
+ u = _graph.target(e);
+ }
+ }
+ }
+ return _path_num;
+ }
+
+ /// \brief Compute the paths from the flow.
+ ///
+ /// This function computes arc-disjoint paths from the found minimum
+ /// cost flow, which is the union of them.
+ ///
+ /// \pre \ref init() and \ref findFlow() must be called before using
+ /// this function.
+ void findPaths() {
+ FlowMap res_flow(_graph);
+ for(ArcIt a(_graph); a != INVALID; ++a) res_flow[a] = (*_flow)[a];
+
+ _paths.clear();
+ _paths.resize(_path_num);
+ for (int i = 0; i < _path_num; ++i) {
+ Node n = _s;
+ while (n != _t) {
+ OutArcIt e(_graph, n);
+ for ( ; res_flow[e] == 0; ++e) ;
+ n = _graph.target(e);
+ _paths[i].addBack(e);
+ res_flow[e] = 0;
+ }
+ }
+ }
+
+ /// @}
+
+ /// \name Query Functions
+ /// The results of the algorithm can be obtained using these
+ /// functions.
+ /// \n The algorithm should be executed before using them.
+
+ /// @{
+
+ /// \brief Return the total length of the found paths.
+ ///
+ /// This function returns the total length of the found paths, i.e.
+ /// the total cost of the found flow.
+ /// The complexity of the function is O(m).
+ ///
+ /// \pre \ref run() or \ref findFlow() must be called before using
+ /// this function.
+ Length totalLength() const {
+ Length c = 0;
+ for (ArcIt e(_graph); e != INVALID; ++e)
+ c += (*_flow)[e] * _length[e];
+ return c;
+ }
+
+ /// \brief Return the flow value on the given arc.
+ ///
+ /// This function returns the flow value on the given arc.
+ /// It is \c 1 if the arc is involved in one of the found arc-disjoint
+ /// paths, otherwise it is \c 0.
+ ///
+ /// \pre \ref run() or \ref findFlow() must be called before using
+ /// this function.
+ int flow(const Arc& arc) const {
+ return (*_flow)[arc];
+ }
+
+ /// \brief Return a const reference to an arc map storing the
+ /// found flow.
+ ///
+ /// This function returns a const reference to an arc map storing
+ /// the flow that is the union of the found arc-disjoint paths.
+ ///
+ /// \pre \ref run() or \ref findFlow() must be called before using
+ /// this function.
+ const FlowMap& flowMap() const {
+ return *_flow;
+ }
+
+ /// \brief Return the potential of the given node.
+ ///
+ /// This function returns the potential of the given node.
+ /// The node potentials provide the dual solution of the
+ /// underlying \ref min_cost_flow "minimum cost flow problem".
+ ///
+ /// \pre \ref run() or \ref findFlow() must be called before using
+ /// this function.
+ Length potential(const Node& node) const {
+ return (*_potential)[node];
+ }
+
+ /// \brief Return a const reference to a node map storing the
+ /// found potentials (the dual solution).
+ ///
+ /// This function returns a const reference to a node map storing
+ /// the found potentials that provide the dual solution of the
+ /// underlying \ref min_cost_flow "minimum cost flow problem".
+ ///
+ /// \pre \ref run() or \ref findFlow() must be called before using
+ /// this function.
+ const PotentialMap& potentialMap() const {
+ return *_potential;
+ }
+
+ /// \brief Return the number of the found paths.
+ ///
+ /// This function returns the number of the found paths.
+ ///
+ /// \pre \ref run() or \ref findFlow() must be called before using
+ /// this function.
+ int pathNum() const {
+ return _path_num;
+ }
+
+ /// \brief Return a const reference to the specified path.
+ ///
+ /// This function returns a const reference to the specified path.
+ ///
+ /// \param i The function returns the <tt>i</tt>-th path.
+ /// \c i must be between \c 0 and <tt>%pathNum()-1</tt>.
+ ///
+ /// \pre \ref run() or \ref findPaths() must be called before using
+ /// this function.
+ const Path& path(int i) const {
+ return _paths[i];
+ }
+
+ /// @}
+
+ }; //class Suurballe
+
+ ///@}
+
+} //namespace lemon
+
+#endif //LEMON_SUURBALLE_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/time_measure.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/time_measure.h
new file mode 100644
index 00000000000..3f7f0778999
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/time_measure.h
@@ -0,0 +1,610 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_TIME_MEASURE_H
+#define LEMON_TIME_MEASURE_H
+
+///\ingroup timecount
+///\file
+///\brief Tools for measuring cpu usage
+
+#ifdef WIN32
+#include <lemon/bits/windows.h>
+#else
+#include <unistd.h>
+#include <sys/times.h>
+#include <sys/time.h>
+#endif
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <lemon/math.h>
+
+namespace lemon {
+
+ /// \addtogroup timecount
+ /// @{
+
+ /// A class to store (cpu)time instances.
+
+ /// This class stores five time values.
+ /// - a real time
+ /// - a user cpu time
+ /// - a system cpu time
+ /// - a user cpu time of children
+ /// - a system cpu time of children
+ ///
+ /// TimeStamp's can be added to or substracted from each other and
+ /// they can be pushed to a stream.
+ ///
+ /// In most cases, perhaps the \ref Timer or the \ref TimeReport
+ /// class is what you want to use instead.
+
+ class TimeStamp
+ {
+ double utime;
+ double stime;
+ double cutime;
+ double cstime;
+ double rtime;
+
+ public:
+ ///Display format specifier
+
+ ///\e
+ ///
+ enum Format {
+ /// Reports all measured values
+ NORMAL = 0,
+ /// Only real time and an error indicator is displayed
+ SHORT = 1
+ };
+
+ private:
+ static Format _format;
+
+ void _reset() {
+ utime = stime = cutime = cstime = rtime = 0;
+ }
+
+ public:
+
+ ///Set output format
+
+ ///Set output format.
+ ///
+ ///The output format is global for all timestamp instances.
+ static void format(Format f) { _format = f; }
+ ///Retrieve the current output format
+
+ ///Retrieve the current output format
+ ///
+ ///The output format is global for all timestamp instances.
+ static Format format() { return _format; }
+
+
+ ///Read the current time values of the process
+ void stamp()
+ {
+#ifndef WIN32
+ timeval tv;
+ gettimeofday(&tv, 0);
+ rtime=tv.tv_sec+double(tv.tv_usec)/1e6;
+
+ tms ts;
+ double tck=sysconf(_SC_CLK_TCK);
+ times(&ts);
+ utime=ts.tms_utime/tck;
+ stime=ts.tms_stime/tck;
+ cutime=ts.tms_cutime/tck;
+ cstime=ts.tms_cstime/tck;
+#else
+ bits::getWinProcTimes(rtime, utime, stime, cutime, cstime);
+#endif
+ }
+
+ /// Constructor initializing with zero
+ TimeStamp()
+ { _reset(); }
+ ///Constructor initializing with the current time values of the process
+ TimeStamp(void *) { stamp();}
+
+ ///Set every time value to zero
+ TimeStamp &reset() {_reset();return *this;}
+
+ ///\e
+ TimeStamp &operator+=(const TimeStamp &b)
+ {
+ utime+=b.utime;
+ stime+=b.stime;
+ cutime+=b.cutime;
+ cstime+=b.cstime;
+ rtime+=b.rtime;
+ return *this;
+ }
+ ///\e
+ TimeStamp operator+(const TimeStamp &b) const
+ {
+ TimeStamp t(*this);
+ return t+=b;
+ }
+ ///\e
+ TimeStamp &operator-=(const TimeStamp &b)
+ {
+ utime-=b.utime;
+ stime-=b.stime;
+ cutime-=b.cutime;
+ cstime-=b.cstime;
+ rtime-=b.rtime;
+ return *this;
+ }
+ ///\e
+ TimeStamp operator-(const TimeStamp &b) const
+ {
+ TimeStamp t(*this);
+ return t-=b;
+ }
+ ///\e
+ TimeStamp &operator*=(double b)
+ {
+ utime*=b;
+ stime*=b;
+ cutime*=b;
+ cstime*=b;
+ rtime*=b;
+ return *this;
+ }
+ ///\e
+ TimeStamp operator*(double b) const
+ {
+ TimeStamp t(*this);
+ return t*=b;
+ }
+ friend TimeStamp operator*(double b,const TimeStamp &t);
+ ///\e
+ TimeStamp &operator/=(double b)
+ {
+ utime/=b;
+ stime/=b;
+ cutime/=b;
+ cstime/=b;
+ rtime/=b;
+ return *this;
+ }
+ ///\e
+ TimeStamp operator/(double b) const
+ {
+ TimeStamp t(*this);
+ return t/=b;
+ }
+ ///The time ellapsed since the last call of stamp()
+ TimeStamp ellapsed() const
+ {
+ TimeStamp t(NULL);
+ return t-*this;
+ }
+
+ friend std::ostream& operator<<(std::ostream& os,const TimeStamp &t);
+
+ ///Gives back the user time of the process
+ double userTime() const
+ {
+ return utime;
+ }
+ ///Gives back the system time of the process
+ double systemTime() const
+ {
+ return stime;
+ }
+ ///Gives back the user time of the process' children
+
+ ///\note On <tt>WIN32</tt> platform this value is not calculated.
+ ///
+ double cUserTime() const
+ {
+ return cutime;
+ }
+ ///Gives back the user time of the process' children
+
+ ///\note On <tt>WIN32</tt> platform this value is not calculated.
+ ///
+ double cSystemTime() const
+ {
+ return cstime;
+ }
+ ///Gives back the real time
+ double realTime() const {return rtime;}
+ };
+
+ inline TimeStamp operator*(double b,const TimeStamp &t)
+ {
+ return t*b;
+ }
+
+ ///Prints the time counters
+
+ ///Prints the time counters in the following form:
+ ///
+ /// <tt>u: XX.XXs s: XX.XXs cu: XX.XXs cs: XX.XXs real: XX.XXs</tt>
+ ///
+ /// where the values are the
+ /// \li \c u: user cpu time,
+ /// \li \c s: system cpu time,
+ /// \li \c cu: user cpu time of children,
+ /// \li \c cs: system cpu time of children,
+ /// \li \c real: real time.
+ /// \relates TimeStamp
+ /// \note On <tt>WIN32</tt> platform the cummulative values are not
+ /// calculated.
+ inline std::ostream& operator<<(std::ostream& os,const TimeStamp &t)
+ {
+ switch(t._format)
+ {
+ case TimeStamp::NORMAL:
+ os << "u: " << t.userTime() <<
+ "s, s: " << t.systemTime() <<
+ "s, cu: " << t.cUserTime() <<
+ "s, cs: " << t.cSystemTime() <<
+ "s, real: " << t.realTime() << "s";
+ break;
+ case TimeStamp::SHORT:
+ double total = t.userTime()+t.systemTime()+
+ t.cUserTime()+t.cSystemTime();
+ os << t.realTime()
+ << "s (err: " << round((t.realTime()-total)/
+ t.realTime()*10000)/100
+ << "%)";
+ break;
+ }
+ return os;
+ }
+
+ ///Class for measuring the cpu time and real time usage of the process
+
+ ///Class for measuring the cpu time and real time usage of the process.
+ ///It is quite easy-to-use, here is a short example.
+ ///\code
+ /// #include<lemon/time_measure.h>
+ /// #include<iostream>
+ ///
+ /// int main()
+ /// {
+ ///
+ /// ...
+ ///
+ /// Timer t;
+ /// doSomething();
+ /// std::cout << t << '\n';
+ /// t.restart();
+ /// doSomethingElse();
+ /// std::cout << t << '\n';
+ ///
+ /// ...
+ ///
+ /// }
+ ///\endcode
+ ///
+ ///The \ref Timer can also be \ref stop() "stopped" and
+ ///\ref start() "started" again, so it is possible to compute collected
+ ///running times.
+ ///
+ ///\warning Depending on the operation system and its actual configuration
+ ///the time counters have a certain (10ms on a typical Linux system)
+ ///granularity.
+ ///Therefore this tool is not appropriate to measure very short times.
+ ///Also, if you start and stop the timer very frequently, it could lead to
+ ///distorted results.
+ ///
+ ///\note If you want to measure the running time of the execution of a certain
+ ///function, consider the usage of \ref TimeReport instead.
+ ///
+ ///\sa TimeReport
+ class Timer
+ {
+ int _running; //Timer is running iff _running>0; (_running>=0 always holds)
+ TimeStamp start_time; //This is the relativ start-time if the timer
+ //is _running, the collected _running time otherwise.
+
+ void _reset() {if(_running) start_time.stamp(); else start_time.reset();}
+
+ public:
+ ///Constructor.
+
+ ///\param run indicates whether or not the timer starts immediately.
+ ///
+ Timer(bool run=true) :_running(run) {_reset();}
+
+ ///\name Control the State of the Timer
+ ///Basically a Timer can be either running or stopped,
+ ///but it provides a bit finer control on the execution.
+ ///The \ref lemon::Timer "Timer" also counts the number of
+ ///\ref lemon::Timer::start() "start()" executions, and it stops
+ ///only after the same amount (or more) \ref lemon::Timer::stop()
+ ///"stop()"s. This can be useful e.g. to compute the running time
+ ///of recursive functions.
+
+ ///@{
+
+ ///Reset and stop the time counters
+
+ ///This function resets and stops the time counters
+ ///\sa restart()
+ void reset()
+ {
+ _running=0;
+ _reset();
+ }
+
+ ///Start the time counters
+
+ ///This function starts the time counters.
+ ///
+ ///If the timer is started more than ones, it will remain running
+ ///until the same amount of \ref stop() is called.
+ ///\sa stop()
+ void start()
+ {
+ if(_running) _running++;
+ else {
+ _running=1;
+ TimeStamp t;
+ t.stamp();
+ start_time=t-start_time;
+ }
+ }
+
+
+ ///Stop the time counters
+
+ ///This function stops the time counters. If start() was executed more than
+ ///once, then the same number of stop() execution is necessary the really
+ ///stop the timer.
+ ///
+ ///\sa halt()
+ ///\sa start()
+ ///\sa restart()
+ ///\sa reset()
+
+ void stop()
+ {
+ if(_running && !--_running) {
+ TimeStamp t;
+ t.stamp();
+ start_time=t-start_time;
+ }
+ }
+
+ ///Halt (i.e stop immediately) the time counters
+
+ ///This function stops immediately the time counters, i.e. <tt>t.halt()</tt>
+ ///is a faster
+ ///equivalent of the following.
+ ///\code
+ /// while(t.running()) t.stop()
+ ///\endcode
+ ///
+ ///
+ ///\sa stop()
+ ///\sa restart()
+ ///\sa reset()
+
+ void halt()
+ {
+ if(_running) {
+ _running=0;
+ TimeStamp t;
+ t.stamp();
+ start_time=t-start_time;
+ }
+ }
+
+ ///Returns the running state of the timer
+
+ ///This function returns the number of stop() exections that is
+ ///necessary to really stop the timer.
+ ///For example, the timer
+ ///is running if and only if the return value is \c true
+ ///(i.e. greater than
+ ///zero).
+ int running() { return _running; }
+
+
+ ///Restart the time counters
+
+ ///This function is a shorthand for
+ ///a reset() and a start() calls.
+ ///
+ void restart()
+ {
+ reset();
+ start();
+ }
+
+ ///@}
+
+ ///\name Query Functions for the Ellapsed Time
+
+ ///@{
+
+ ///Gives back the ellapsed user time of the process
+ double userTime() const
+ {
+ return operator TimeStamp().userTime();
+ }
+ ///Gives back the ellapsed system time of the process
+ double systemTime() const
+ {
+ return operator TimeStamp().systemTime();
+ }
+ ///Gives back the ellapsed user time of the process' children
+
+ ///\note On <tt>WIN32</tt> platform this value is not calculated.
+ ///
+ double cUserTime() const
+ {
+ return operator TimeStamp().cUserTime();
+ }
+ ///Gives back the ellapsed user time of the process' children
+
+ ///\note On <tt>WIN32</tt> platform this value is not calculated.
+ ///
+ double cSystemTime() const
+ {
+ return operator TimeStamp().cSystemTime();
+ }
+ ///Gives back the ellapsed real time
+ double realTime() const
+ {
+ return operator TimeStamp().realTime();
+ }
+ ///Computes the ellapsed time
+
+ ///This conversion computes the ellapsed time, therefore you can print
+ ///the ellapsed time like this.
+ ///\code
+ /// Timer t;
+ /// doSomething();
+ /// std::cout << t << '\n';
+ ///\endcode
+ operator TimeStamp () const
+ {
+ TimeStamp t;
+ t.stamp();
+ return _running?t-start_time:start_time;
+ }
+
+
+ ///@}
+ };
+
+ ///Same as Timer but prints a report on destruction.
+
+ ///Same as \ref Timer but prints a report on destruction.
+ ///This example shows its usage.
+ ///\code
+ /// void myAlg(ListGraph &g,int n)
+ /// {
+ /// TimeReport tr("Running time of myAlg: ");
+ /// ... //Here comes the algorithm
+ /// }
+ ///\endcode
+ ///
+ ///\sa Timer
+ ///\sa NoTimeReport
+ class TimeReport : public Timer
+ {
+ std::string _title;
+ std::ostream &_os;
+ bool _active;
+ public:
+ ///Constructor
+
+ ///Constructor.
+ ///\param title This text will be printed before the ellapsed time.
+ ///\param os The stream to print the report to.
+ ///\param run Sets whether the timer should start immediately.
+ ///\param active Sets whether the report should actually be printed
+ /// on destruction.
+ TimeReport(std::string title,std::ostream &os=std::cerr,bool run=true,
+ bool active=true)
+ : Timer(run), _title(title), _os(os), _active(active) {}
+ ///Destructor that prints the ellapsed time
+ ~TimeReport()
+ {
+ if(_active) _os << _title << *this << std::endl;
+ }
+
+ ///Retrieve the activity status
+
+ ///\e
+ ///
+ bool active() const { return _active; }
+ ///Set the activity status
+
+ /// This function set whether the time report should actually be printed
+ /// on destruction.
+ void active(bool a) { _active=a; }
+ };
+
+ ///'Do nothing' version of TimeReport
+
+ ///\sa TimeReport
+ ///
+ class NoTimeReport
+ {
+ public:
+ ///\e
+ NoTimeReport(std::string,std::ostream &,bool) {}
+ ///\e
+ NoTimeReport(std::string,std::ostream &) {}
+ ///\e
+ NoTimeReport(std::string) {}
+ ///\e Do nothing.
+ ~NoTimeReport() {}
+
+ operator TimeStamp () const { return TimeStamp(); }
+ void reset() {}
+ void start() {}
+ void stop() {}
+ void halt() {}
+ int running() { return 0; }
+ void restart() {}
+ double userTime() const { return 0; }
+ double systemTime() const { return 0; }
+ double cUserTime() const { return 0; }
+ double cSystemTime() const { return 0; }
+ double realTime() const { return 0; }
+ };
+
+ ///Tool to measure the running time more exactly.
+
+ ///This function calls \c f several times and returns the average
+ ///running time. The number of the executions will be choosen in such a way
+ ///that the full real running time will be roughly between \c min_time
+ ///and <tt>2*min_time</tt>.
+ ///\param f the function object to be measured.
+ ///\param min_time the minimum total running time.
+ ///\retval num if it is not \c NULL, then the actual
+ /// number of execution of \c f will be written into <tt>*num</tt>.
+ ///\retval full_time if it is not \c NULL, then the actual
+ /// total running time will be written into <tt>*full_time</tt>.
+ ///\return The average running time of \c f.
+
+ template<class F>
+ TimeStamp runningTimeTest(F f,double min_time=10,unsigned int *num = NULL,
+ TimeStamp *full_time=NULL)
+ {
+ TimeStamp full;
+ unsigned int total=0;
+ Timer t;
+ for(unsigned int tn=1;tn <= 1U<<31 && full.realTime()<=min_time; tn*=2) {
+ for(;total<tn;total++) f();
+ full=t;
+ }
+ if(num) *num=total;
+ if(full_time) *full_time=full;
+ return full/total;
+ }
+
+ /// @}
+
+
+} //namespace lemon
+
+#endif //LEMON_TIME_MEASURE_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/tolerance.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/tolerance.h
new file mode 100644
index 00000000000..36a7512872e
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/tolerance.h
@@ -0,0 +1,242 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_TOLERANCE_H
+#define LEMON_TOLERANCE_H
+
+///\ingroup misc
+///\file
+///\brief A basic tool to handle the anomalies of calculation with
+///floating point numbers.
+///
+
+namespace lemon {
+
+ /// \addtogroup misc
+ /// @{
+
+ ///\brief A class to provide a basic way to
+ ///handle the comparison of numbers that are obtained
+ ///as a result of a probably inexact computation.
+ ///
+ ///\ref Tolerance is a class to provide a basic way to
+ ///handle the comparison of numbers that are obtained
+ ///as a result of a probably inexact computation.
+ ///
+ ///The general implementation is suitable only if the data type is exact,
+ ///like the integer types, otherwise a specialized version must be
+ ///implemented. These specialized classes like
+ ///Tolerance<double> may offer additional tuning parameters.
+ ///
+ ///\sa Tolerance<float>
+ ///\sa Tolerance<double>
+ ///\sa Tolerance<long double>
+
+ template<class T>
+ class Tolerance
+ {
+ public:
+ typedef T Value;
+
+ ///\name Comparisons
+ ///The concept is that these bool functions return \c true only if
+ ///the related comparisons hold even if some numerical error appeared
+ ///during the computations.
+
+ ///@{
+
+ ///Returns \c true if \c a is \e surely strictly less than \c b
+ static bool less(Value a,Value b) {return a<b;}
+ ///Returns \c true if \c a is \e surely different from \c b
+ static bool different(Value a,Value b) {return a!=b;}
+ ///Returns \c true if \c a is \e surely positive
+ static bool positive(Value a) {return static_cast<Value>(0) < a;}
+ ///Returns \c true if \c a is \e surely negative
+ static bool negative(Value a) {return a < static_cast<Value>(0);}
+ ///Returns \c true if \c a is \e surely non-zero
+ static bool nonZero(Value a) {return a != static_cast<Value>(0);}
+
+ ///@}
+
+ ///Returns the zero value.
+ static Value zero() {return static_cast<Value>(0);}
+
+ // static bool finite(Value a) {}
+ // static Value big() {}
+ // static Value negativeBig() {}
+ };
+
+
+ ///Float specialization of Tolerance.
+
+ ///Float specialization of Tolerance.
+ ///\sa Tolerance
+ ///\relates Tolerance
+ template<>
+ class Tolerance<float>
+ {
+ static float def_epsilon;
+ float _epsilon;
+ public:
+ ///\e
+ typedef float Value;
+
+ ///Constructor setting the epsilon tolerance to the default value.
+ Tolerance() : _epsilon(def_epsilon) {}
+ ///Constructor setting the epsilon tolerance to the given value.
+ Tolerance(float e) : _epsilon(e) {}
+
+ ///Returns the epsilon value.
+ Value epsilon() const {return _epsilon;}
+ ///Sets the epsilon value.
+ void epsilon(Value e) {_epsilon=e;}
+
+ ///Returns the default epsilon value.
+ static Value defaultEpsilon() {return def_epsilon;}
+ ///Sets the default epsilon value.
+ static void defaultEpsilon(Value e) {def_epsilon=e;}
+
+ ///\name Comparisons
+ ///See \ref lemon::Tolerance "Tolerance" for more details.
+
+ ///@{
+
+ ///Returns \c true if \c a is \e surely strictly less than \c b
+ bool less(Value a,Value b) const {return a+_epsilon<b;}
+ ///Returns \c true if \c a is \e surely different from \c b
+ bool different(Value a,Value b) const { return less(a,b)||less(b,a); }
+ ///Returns \c true if \c a is \e surely positive
+ bool positive(Value a) const { return _epsilon<a; }
+ ///Returns \c true if \c a is \e surely negative
+ bool negative(Value a) const { return -_epsilon>a; }
+ ///Returns \c true if \c a is \e surely non-zero
+ bool nonZero(Value a) const { return positive(a)||negative(a); }
+
+ ///@}
+
+ ///Returns zero
+ static Value zero() {return 0;}
+ };
+
+ ///Double specialization of Tolerance.
+
+ ///Double specialization of Tolerance.
+ ///\sa Tolerance
+ ///\relates Tolerance
+ template<>
+ class Tolerance<double>
+ {
+ static double def_epsilon;
+ double _epsilon;
+ public:
+ ///\e
+ typedef double Value;
+
+ ///Constructor setting the epsilon tolerance to the default value.
+ Tolerance() : _epsilon(def_epsilon) {}
+ ///Constructor setting the epsilon tolerance to the given value.
+ Tolerance(double e) : _epsilon(e) {}
+
+ ///Returns the epsilon value.
+ Value epsilon() const {return _epsilon;}
+ ///Sets the epsilon value.
+ void epsilon(Value e) {_epsilon=e;}
+
+ ///Returns the default epsilon value.
+ static Value defaultEpsilon() {return def_epsilon;}
+ ///Sets the default epsilon value.
+ static void defaultEpsilon(Value e) {def_epsilon=e;}
+
+ ///\name Comparisons
+ ///See \ref lemon::Tolerance "Tolerance" for more details.
+
+ ///@{
+
+ ///Returns \c true if \c a is \e surely strictly less than \c b
+ bool less(Value a,Value b) const {return a+_epsilon<b;}
+ ///Returns \c true if \c a is \e surely different from \c b
+ bool different(Value a,Value b) const { return less(a,b)||less(b,a); }
+ ///Returns \c true if \c a is \e surely positive
+ bool positive(Value a) const { return _epsilon<a; }
+ ///Returns \c true if \c a is \e surely negative
+ bool negative(Value a) const { return -_epsilon>a; }
+ ///Returns \c true if \c a is \e surely non-zero
+ bool nonZero(Value a) const { return positive(a)||negative(a); }
+
+ ///@}
+
+ ///Returns zero
+ static Value zero() {return 0;}
+ };
+
+ ///Long double specialization of Tolerance.
+
+ ///Long double specialization of Tolerance.
+ ///\sa Tolerance
+ ///\relates Tolerance
+ template<>
+ class Tolerance<long double>
+ {
+ static long double def_epsilon;
+ long double _epsilon;
+ public:
+ ///\e
+ typedef long double Value;
+
+ ///Constructor setting the epsilon tolerance to the default value.
+ Tolerance() : _epsilon(def_epsilon) {}
+ ///Constructor setting the epsilon tolerance to the given value.
+ Tolerance(long double e) : _epsilon(e) {}
+
+ ///Returns the epsilon value.
+ Value epsilon() const {return _epsilon;}
+ ///Sets the epsilon value.
+ void epsilon(Value e) {_epsilon=e;}
+
+ ///Returns the default epsilon value.
+ static Value defaultEpsilon() {return def_epsilon;}
+ ///Sets the default epsilon value.
+ static void defaultEpsilon(Value e) {def_epsilon=e;}
+
+ ///\name Comparisons
+ ///See \ref lemon::Tolerance "Tolerance" for more details.
+
+ ///@{
+
+ ///Returns \c true if \c a is \e surely strictly less than \c b
+ bool less(Value a,Value b) const {return a+_epsilon<b;}
+ ///Returns \c true if \c a is \e surely different from \c b
+ bool different(Value a,Value b) const { return less(a,b)||less(b,a); }
+ ///Returns \c true if \c a is \e surely positive
+ bool positive(Value a) const { return _epsilon<a; }
+ ///Returns \c true if \c a is \e surely negative
+ bool negative(Value a) const { return -_epsilon>a; }
+ ///Returns \c true if \c a is \e surely non-zero
+ bool nonZero(Value a) const { return positive(a)||negative(a); }
+
+ ///@}
+
+ ///Returns zero
+ static Value zero() {return 0;}
+ };
+
+ /// @}
+
+} //namespace lemon
+
+#endif //LEMON_TOLERANCE_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/unionfind.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/unionfind.h
new file mode 100644
index 00000000000..3d96b372b2d
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/unionfind.h
@@ -0,0 +1,1824 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_UNION_FIND_H
+#define LEMON_UNION_FIND_H
+
+//!\ingroup auxdat
+//!\file
+//!\brief Union-Find data structures.
+//!
+
+#include <vector>
+#include <list>
+#include <utility>
+#include <algorithm>
+#include <functional>
+
+#include <lemon/core.h>
+
+namespace lemon {
+
+ /// \ingroup auxdat
+ ///
+ /// \brief A \e Union-Find data structure implementation
+ ///
+ /// The class implements the \e Union-Find data structure.
+ /// The union operation uses rank heuristic, while
+ /// the find operation uses path compression.
+ /// This is a very simple but efficient implementation, providing
+ /// only four methods: join (union), find, insert and size.
+ /// For more features, see the \ref UnionFindEnum class.
+ ///
+ /// It is primarily used in Kruskal algorithm for finding minimal
+ /// cost spanning tree in a graph.
+ /// \sa kruskal()
+ ///
+ /// \pre You need to add all the elements by the \ref insert()
+ /// method.
+ template <typename IM>
+ class UnionFind {
+ public:
+
+ ///\e
+ typedef IM ItemIntMap;
+ ///\e
+ typedef typename ItemIntMap::Key Item;
+
+ private:
+ // If the items vector stores negative value for an item then
+ // that item is root item and it has -items[it] component size.
+ // Else the items[it] contains the index of the parent.
+ std::vector<int> items;
+ ItemIntMap& index;
+
+ bool rep(int idx) const {
+ return items[idx] < 0;
+ }
+
+ int repIndex(int idx) const {
+ int k = idx;
+ while (!rep(k)) {
+ k = items[k] ;
+ }
+ while (idx != k) {
+ int next = items[idx];
+ const_cast<int&>(items[idx]) = k;
+ idx = next;
+ }
+ return k;
+ }
+
+ public:
+
+ /// \brief Constructor
+ ///
+ /// Constructor of the UnionFind class. You should give an item to
+ /// integer map which will be used from the data structure. If you
+ /// modify directly this map that may cause segmentation fault,
+ /// invalid data structure, or infinite loop when you use again
+ /// the union-find.
+ UnionFind(ItemIntMap& m) : index(m) {}
+
+ /// \brief Returns the index of the element's component.
+ ///
+ /// The method returns the index of the element's component.
+ /// This is an integer between zero and the number of inserted elements.
+ ///
+ int find(const Item& a) {
+ return repIndex(index[a]);
+ }
+
+ /// \brief Clears the union-find data structure
+ ///
+ /// Erase each item from the data structure.
+ void clear() {
+ items.clear();
+ }
+
+ /// \brief Inserts a new element into the structure.
+ ///
+ /// This method inserts a new element into the data structure.
+ ///
+ /// The method returns the index of the new component.
+ int insert(const Item& a) {
+ int n = items.size();
+ items.push_back(-1);
+ index.set(a,n);
+ return n;
+ }
+
+ /// \brief Joining the components of element \e a and element \e b.
+ ///
+ /// This is the \e union operation of the Union-Find structure.
+ /// Joins the component of element \e a and component of
+ /// element \e b. If \e a and \e b are in the same component then
+ /// it returns false otherwise it returns true.
+ bool join(const Item& a, const Item& b) {
+ int ka = repIndex(index[a]);
+ int kb = repIndex(index[b]);
+
+ if ( ka == kb )
+ return false;
+
+ if (items[ka] < items[kb]) {
+ items[ka] += items[kb];
+ items[kb] = ka;
+ } else {
+ items[kb] += items[ka];
+ items[ka] = kb;
+ }
+ return true;
+ }
+
+ /// \brief Returns the size of the component of element \e a.
+ ///
+ /// Returns the size of the component of element \e a.
+ int size(const Item& a) {
+ int k = repIndex(index[a]);
+ return - items[k];
+ }
+
+ };
+
+ /// \ingroup auxdat
+ ///
+ /// \brief A \e Union-Find data structure implementation which
+ /// is able to enumerate the components.
+ ///
+ /// The class implements a \e Union-Find data structure
+ /// which is able to enumerate the components and the items in
+ /// a component. If you don't need this feature then perhaps it's
+ /// better to use the \ref UnionFind class which is more efficient.
+ ///
+ /// The union operation uses rank heuristic, while
+ /// the find operation uses path compression.
+ ///
+ /// \pre You need to add all the elements by the \ref insert()
+ /// method.
+ ///
+ template <typename IM>
+ class UnionFindEnum {
+ public:
+
+ ///\e
+ typedef IM ItemIntMap;
+ ///\e
+ typedef typename ItemIntMap::Key Item;
+
+ private:
+
+ ItemIntMap& index;
+
+ // If the parent stores negative value for an item then that item
+ // is root item and it has ~(items[it].parent) component id. Else
+ // the items[it].parent contains the index of the parent.
+ //
+ // The \c next and \c prev provides the double-linked
+ // cyclic list of one component's items.
+ struct ItemT {
+ int parent;
+ Item item;
+
+ int next, prev;
+ };
+
+ std::vector<ItemT> items;
+ int firstFreeItem;
+
+ struct ClassT {
+ int size;
+ int firstItem;
+ int next, prev;
+ };
+
+ std::vector<ClassT> classes;
+ int firstClass, firstFreeClass;
+
+ int newClass() {
+ if (firstFreeClass == -1) {
+ int cdx = classes.size();
+ classes.push_back(ClassT());
+ return cdx;
+ } else {
+ int cdx = firstFreeClass;
+ firstFreeClass = classes[firstFreeClass].next;
+ return cdx;
+ }
+ }
+
+ int newItem() {
+ if (firstFreeItem == -1) {
+ int idx = items.size();
+ items.push_back(ItemT());
+ return idx;
+ } else {
+ int idx = firstFreeItem;
+ firstFreeItem = items[firstFreeItem].next;
+ return idx;
+ }
+ }
+
+
+ bool rep(int idx) const {
+ return items[idx].parent < 0;
+ }
+
+ int repIndex(int idx) const {
+ int k = idx;
+ while (!rep(k)) {
+ k = items[k].parent;
+ }
+ while (idx != k) {
+ int next = items[idx].parent;
+ const_cast<int&>(items[idx].parent) = k;
+ idx = next;
+ }
+ return k;
+ }
+
+ int classIndex(int idx) const {
+ return ~(items[repIndex(idx)].parent);
+ }
+
+ void singletonItem(int idx) {
+ items[idx].next = idx;
+ items[idx].prev = idx;
+ }
+
+ void laceItem(int idx, int rdx) {
+ items[idx].prev = rdx;
+ items[idx].next = items[rdx].next;
+ items[items[rdx].next].prev = idx;
+ items[rdx].next = idx;
+ }
+
+ void unlaceItem(int idx) {
+ items[items[idx].prev].next = items[idx].next;
+ items[items[idx].next].prev = items[idx].prev;
+
+ items[idx].next = firstFreeItem;
+ firstFreeItem = idx;
+ }
+
+ void spliceItems(int ak, int bk) {
+ items[items[ak].prev].next = bk;
+ items[items[bk].prev].next = ak;
+ int tmp = items[ak].prev;
+ items[ak].prev = items[bk].prev;
+ items[bk].prev = tmp;
+
+ }
+
+ void laceClass(int cls) {
+ if (firstClass != -1) {
+ classes[firstClass].prev = cls;
+ }
+ classes[cls].next = firstClass;
+ classes[cls].prev = -1;
+ firstClass = cls;
+ }
+
+ void unlaceClass(int cls) {
+ if (classes[cls].prev != -1) {
+ classes[classes[cls].prev].next = classes[cls].next;
+ } else {
+ firstClass = classes[cls].next;
+ }
+ if (classes[cls].next != -1) {
+ classes[classes[cls].next].prev = classes[cls].prev;
+ }
+
+ classes[cls].next = firstFreeClass;
+ firstFreeClass = cls;
+ }
+
+ public:
+
+ UnionFindEnum(ItemIntMap& _index)
+ : index(_index), items(), firstFreeItem(-1),
+ firstClass(-1), firstFreeClass(-1) {}
+
+ /// \brief Inserts the given element into a new component.
+ ///
+ /// This method creates a new component consisting only of the
+ /// given element.
+ ///
+ int insert(const Item& item) {
+ int idx = newItem();
+
+ index.set(item, idx);
+
+ singletonItem(idx);
+ items[idx].item = item;
+
+ int cdx = newClass();
+
+ items[idx].parent = ~cdx;
+
+ laceClass(cdx);
+ classes[cdx].size = 1;
+ classes[cdx].firstItem = idx;
+
+ firstClass = cdx;
+
+ return cdx;
+ }
+
+ /// \brief Inserts the given element into the component of the others.
+ ///
+ /// This methods inserts the element \e a into the component of the
+ /// element \e comp.
+ void insert(const Item& item, int cls) {
+ int rdx = classes[cls].firstItem;
+ int idx = newItem();
+
+ index.set(item, idx);
+
+ laceItem(idx, rdx);
+
+ items[idx].item = item;
+ items[idx].parent = rdx;
+
+ ++classes[~(items[rdx].parent)].size;
+ }
+
+ /// \brief Clears the union-find data structure
+ ///
+ /// Erase each item from the data structure.
+ void clear() {
+ items.clear();
+ firstClass = -1;
+ firstFreeItem = -1;
+ }
+
+ /// \brief Finds the component of the given element.
+ ///
+ /// The method returns the component id of the given element.
+ int find(const Item &item) const {
+ return ~(items[repIndex(index[item])].parent);
+ }
+
+ /// \brief Joining the component of element \e a and element \e b.
+ ///
+ /// This is the \e union operation of the Union-Find structure.
+ /// Joins the component of element \e a and component of
+ /// element \e b. If \e a and \e b are in the same component then
+ /// returns -1 else returns the remaining class.
+ int join(const Item& a, const Item& b) {
+
+ int ak = repIndex(index[a]);
+ int bk = repIndex(index[b]);
+
+ if (ak == bk) {
+ return -1;
+ }
+
+ int acx = ~(items[ak].parent);
+ int bcx = ~(items[bk].parent);
+
+ int rcx;
+
+ if (classes[acx].size > classes[bcx].size) {
+ classes[acx].size += classes[bcx].size;
+ items[bk].parent = ak;
+ unlaceClass(bcx);
+ rcx = acx;
+ } else {
+ classes[bcx].size += classes[acx].size;
+ items[ak].parent = bk;
+ unlaceClass(acx);
+ rcx = bcx;
+ }
+ spliceItems(ak, bk);
+
+ return rcx;
+ }
+
+ /// \brief Returns the size of the class.
+ ///
+ /// Returns the size of the class.
+ int size(int cls) const {
+ return classes[cls].size;
+ }
+
+ /// \brief Splits up the component.
+ ///
+ /// Splitting the component into singleton components (component
+ /// of size one).
+ void split(int cls) {
+ int fdx = classes[cls].firstItem;
+ int idx = items[fdx].next;
+ while (idx != fdx) {
+ int next = items[idx].next;
+
+ singletonItem(idx);
+
+ int cdx = newClass();
+ items[idx].parent = ~cdx;
+
+ laceClass(cdx);
+ classes[cdx].size = 1;
+ classes[cdx].firstItem = idx;
+
+ idx = next;
+ }
+
+ items[idx].prev = idx;
+ items[idx].next = idx;
+
+ classes[~(items[idx].parent)].size = 1;
+
+ }
+
+ /// \brief Removes the given element from the structure.
+ ///
+ /// Removes the element from its component and if the component becomes
+ /// empty then removes that component from the component list.
+ ///
+ /// \warning It is an error to remove an element which is not in
+ /// the structure.
+ /// \warning This running time of this operation is proportional to the
+ /// number of the items in this class.
+ void erase(const Item& item) {
+ int idx = index[item];
+ int fdx = items[idx].next;
+
+ int cdx = classIndex(idx);
+ if (idx == fdx) {
+ unlaceClass(cdx);
+ items[idx].next = firstFreeItem;
+ firstFreeItem = idx;
+ return;
+ } else {
+ classes[cdx].firstItem = fdx;
+ --classes[cdx].size;
+ items[fdx].parent = ~cdx;
+
+ unlaceItem(idx);
+ idx = items[fdx].next;
+ while (idx != fdx) {
+ items[idx].parent = fdx;
+ idx = items[idx].next;
+ }
+
+ }
+
+ }
+
+ /// \brief Gives back a representant item of the component.
+ ///
+ /// Gives back a representant item of the component.
+ Item item(int cls) const {
+ return items[classes[cls].firstItem].item;
+ }
+
+ /// \brief Removes the component of the given element from the structure.
+ ///
+ /// Removes the component of the given element from the structure.
+ ///
+ /// \warning It is an error to give an element which is not in the
+ /// structure.
+ void eraseClass(int cls) {
+ int fdx = classes[cls].firstItem;
+ unlaceClass(cls);
+ items[items[fdx].prev].next = firstFreeItem;
+ firstFreeItem = fdx;
+ }
+
+ /// \brief LEMON style iterator for the representant items.
+ ///
+ /// ClassIt is a lemon style iterator for the components. It iterates
+ /// on the ids of the classes.
+ class ClassIt {
+ public:
+ /// \brief Constructor of the iterator
+ ///
+ /// Constructor of the iterator
+ ClassIt(const UnionFindEnum& ufe) : unionFind(&ufe) {
+ cdx = unionFind->firstClass;
+ }
+
+ /// \brief Constructor to get invalid iterator
+ ///
+ /// Constructor to get invalid iterator
+ ClassIt(Invalid) : unionFind(0), cdx(-1) {}
+
+ /// \brief Increment operator
+ ///
+ /// It steps to the next representant item.
+ ClassIt& operator++() {
+ cdx = unionFind->classes[cdx].next;
+ return *this;
+ }
+
+ /// \brief Conversion operator
+ ///
+ /// It converts the iterator to the current representant item.
+ operator int() const {
+ return cdx;
+ }
+
+ /// \brief Equality operator
+ ///
+ /// Equality operator
+ bool operator==(const ClassIt& i) {
+ return i.cdx == cdx;
+ }
+
+ /// \brief Inequality operator
+ ///
+ /// Inequality operator
+ bool operator!=(const ClassIt& i) {
+ return i.cdx != cdx;
+ }
+
+ private:
+ const UnionFindEnum* unionFind;
+ int cdx;
+ };
+
+ /// \brief LEMON style iterator for the items of a component.
+ ///
+ /// ClassIt is a lemon style iterator for the components. It iterates
+ /// on the items of a class. By example if you want to iterate on
+ /// each items of each classes then you may write the next code.
+ ///\code
+ /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
+ /// std::cout << "Class: ";
+ /// for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
+ /// std::cout << toString(iit) << ' ' << std::endl;
+ /// }
+ /// std::cout << std::endl;
+ /// }
+ ///\endcode
+ class ItemIt {
+ public:
+ /// \brief Constructor of the iterator
+ ///
+ /// Constructor of the iterator. The iterator iterates
+ /// on the class of the \c item.
+ ItemIt(const UnionFindEnum& ufe, int cls) : unionFind(&ufe) {
+ fdx = idx = unionFind->classes[cls].firstItem;
+ }
+
+ /// \brief Constructor to get invalid iterator
+ ///
+ /// Constructor to get invalid iterator
+ ItemIt(Invalid) : unionFind(0), idx(-1) {}
+
+ /// \brief Increment operator
+ ///
+ /// It steps to the next item in the class.
+ ItemIt& operator++() {
+ idx = unionFind->items[idx].next;
+ if (idx == fdx) idx = -1;
+ return *this;
+ }
+
+ /// \brief Conversion operator
+ ///
+ /// It converts the iterator to the current item.
+ operator const Item&() const {
+ return unionFind->items[idx].item;
+ }
+
+ /// \brief Equality operator
+ ///
+ /// Equality operator
+ bool operator==(const ItemIt& i) {
+ return i.idx == idx;
+ }
+
+ /// \brief Inequality operator
+ ///
+ /// Inequality operator
+ bool operator!=(const ItemIt& i) {
+ return i.idx != idx;
+ }
+
+ private:
+ const UnionFindEnum* unionFind;
+ int idx, fdx;
+ };
+
+ };
+
+ /// \ingroup auxdat
+ ///
+ /// \brief A \e Extend-Find data structure implementation which
+ /// is able to enumerate the components.
+ ///
+ /// The class implements an \e Extend-Find data structure which is
+ /// able to enumerate the components and the items in a
+ /// component. The data structure is a simplification of the
+ /// Union-Find structure, and it does not allow to merge two components.
+ ///
+ /// \pre You need to add all the elements by the \ref insert()
+ /// method.
+ template <typename IM>
+ class ExtendFindEnum {
+ public:
+
+ ///\e
+ typedef IM ItemIntMap;
+ ///\e
+ typedef typename ItemIntMap::Key Item;
+
+ private:
+
+ ItemIntMap& index;
+
+ struct ItemT {
+ int cls;
+ Item item;
+ int next, prev;
+ };
+
+ std::vector<ItemT> items;
+ int firstFreeItem;
+
+ struct ClassT {
+ int firstItem;
+ int next, prev;
+ };
+
+ std::vector<ClassT> classes;
+
+ int firstClass, firstFreeClass;
+
+ int newClass() {
+ if (firstFreeClass != -1) {
+ int cdx = firstFreeClass;
+ firstFreeClass = classes[cdx].next;
+ return cdx;
+ } else {
+ classes.push_back(ClassT());
+ return classes.size() - 1;
+ }
+ }
+
+ int newItem() {
+ if (firstFreeItem != -1) {
+ int idx = firstFreeItem;
+ firstFreeItem = items[idx].next;
+ return idx;
+ } else {
+ items.push_back(ItemT());
+ return items.size() - 1;
+ }
+ }
+
+ public:
+
+ /// \brief Constructor
+ ExtendFindEnum(ItemIntMap& _index)
+ : index(_index), items(), firstFreeItem(-1),
+ classes(), firstClass(-1), firstFreeClass(-1) {}
+
+ /// \brief Inserts the given element into a new component.
+ ///
+ /// This method creates a new component consisting only of the
+ /// given element.
+ int insert(const Item& item) {
+ int cdx = newClass();
+ classes[cdx].prev = -1;
+ classes[cdx].next = firstClass;
+ if (firstClass != -1) {
+ classes[firstClass].prev = cdx;
+ }
+ firstClass = cdx;
+
+ int idx = newItem();
+ items[idx].item = item;
+ items[idx].cls = cdx;
+ items[idx].prev = idx;
+ items[idx].next = idx;
+
+ classes[cdx].firstItem = idx;
+
+ index.set(item, idx);
+
+ return cdx;
+ }
+
+ /// \brief Inserts the given element into the given component.
+ ///
+ /// This methods inserts the element \e item a into the \e cls class.
+ void insert(const Item& item, int cls) {
+ int idx = newItem();
+ int rdx = classes[cls].firstItem;
+ items[idx].item = item;
+ items[idx].cls = cls;
+
+ items[idx].prev = rdx;
+ items[idx].next = items[rdx].next;
+ items[items[rdx].next].prev = idx;
+ items[rdx].next = idx;
+
+ index.set(item, idx);
+ }
+
+ /// \brief Clears the union-find data structure
+ ///
+ /// Erase each item from the data structure.
+ void clear() {
+ items.clear();
+ classes.clear();
+ firstClass = firstFreeClass = firstFreeItem = -1;
+ }
+
+ /// \brief Gives back the class of the \e item.
+ ///
+ /// Gives back the class of the \e item.
+ int find(const Item &item) const {
+ return items[index[item]].cls;
+ }
+
+ /// \brief Gives back a representant item of the component.
+ ///
+ /// Gives back a representant item of the component.
+ Item item(int cls) const {
+ return items[classes[cls].firstItem].item;
+ }
+
+ /// \brief Removes the given element from the structure.
+ ///
+ /// Removes the element from its component and if the component becomes
+ /// empty then removes that component from the component list.
+ ///
+ /// \warning It is an error to remove an element which is not in
+ /// the structure.
+ void erase(const Item &item) {
+ int idx = index[item];
+ int cdx = items[idx].cls;
+
+ if (idx == items[idx].next) {
+ if (classes[cdx].prev != -1) {
+ classes[classes[cdx].prev].next = classes[cdx].next;
+ } else {
+ firstClass = classes[cdx].next;
+ }
+ if (classes[cdx].next != -1) {
+ classes[classes[cdx].next].prev = classes[cdx].prev;
+ }
+ classes[cdx].next = firstFreeClass;
+ firstFreeClass = cdx;
+ } else {
+ classes[cdx].firstItem = items[idx].next;
+ items[items[idx].next].prev = items[idx].prev;
+ items[items[idx].prev].next = items[idx].next;
+ }
+ items[idx].next = firstFreeItem;
+ firstFreeItem = idx;
+
+ }
+
+
+ /// \brief Removes the component of the given element from the structure.
+ ///
+ /// Removes the component of the given element from the structure.
+ ///
+ /// \warning It is an error to give an element which is not in the
+ /// structure.
+ void eraseClass(int cdx) {
+ int idx = classes[cdx].firstItem;
+ items[items[idx].prev].next = firstFreeItem;
+ firstFreeItem = idx;
+
+ if (classes[cdx].prev != -1) {
+ classes[classes[cdx].prev].next = classes[cdx].next;
+ } else {
+ firstClass = classes[cdx].next;
+ }
+ if (classes[cdx].next != -1) {
+ classes[classes[cdx].next].prev = classes[cdx].prev;
+ }
+ classes[cdx].next = firstFreeClass;
+ firstFreeClass = cdx;
+ }
+
+ /// \brief LEMON style iterator for the classes.
+ ///
+ /// ClassIt is a lemon style iterator for the components. It iterates
+ /// on the ids of classes.
+ class ClassIt {
+ public:
+ /// \brief Constructor of the iterator
+ ///
+ /// Constructor of the iterator
+ ClassIt(const ExtendFindEnum& ufe) : extendFind(&ufe) {
+ cdx = extendFind->firstClass;
+ }
+
+ /// \brief Constructor to get invalid iterator
+ ///
+ /// Constructor to get invalid iterator
+ ClassIt(Invalid) : extendFind(0), cdx(-1) {}
+
+ /// \brief Increment operator
+ ///
+ /// It steps to the next representant item.
+ ClassIt& operator++() {
+ cdx = extendFind->classes[cdx].next;
+ return *this;
+ }
+
+ /// \brief Conversion operator
+ ///
+ /// It converts the iterator to the current class id.
+ operator int() const {
+ return cdx;
+ }
+
+ /// \brief Equality operator
+ ///
+ /// Equality operator
+ bool operator==(const ClassIt& i) {
+ return i.cdx == cdx;
+ }
+
+ /// \brief Inequality operator
+ ///
+ /// Inequality operator
+ bool operator!=(const ClassIt& i) {
+ return i.cdx != cdx;
+ }
+
+ private:
+ const ExtendFindEnum* extendFind;
+ int cdx;
+ };
+
+ /// \brief LEMON style iterator for the items of a component.
+ ///
+ /// ClassIt is a lemon style iterator for the components. It iterates
+ /// on the items of a class. By example if you want to iterate on
+ /// each items of each classes then you may write the next code.
+ ///\code
+ /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
+ /// std::cout << "Class: ";
+ /// for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
+ /// std::cout << toString(iit) << ' ' << std::endl;
+ /// }
+ /// std::cout << std::endl;
+ /// }
+ ///\endcode
+ class ItemIt {
+ public:
+ /// \brief Constructor of the iterator
+ ///
+ /// Constructor of the iterator. The iterator iterates
+ /// on the class of the \c item.
+ ItemIt(const ExtendFindEnum& ufe, int cls) : extendFind(&ufe) {
+ fdx = idx = extendFind->classes[cls].firstItem;
+ }
+
+ /// \brief Constructor to get invalid iterator
+ ///
+ /// Constructor to get invalid iterator
+ ItemIt(Invalid) : extendFind(0), idx(-1) {}
+
+ /// \brief Increment operator
+ ///
+ /// It steps to the next item in the class.
+ ItemIt& operator++() {
+ idx = extendFind->items[idx].next;
+ if (fdx == idx) idx = -1;
+ return *this;
+ }
+
+ /// \brief Conversion operator
+ ///
+ /// It converts the iterator to the current item.
+ operator const Item&() const {
+ return extendFind->items[idx].item;
+ }
+
+ /// \brief Equality operator
+ ///
+ /// Equality operator
+ bool operator==(const ItemIt& i) {
+ return i.idx == idx;
+ }
+
+ /// \brief Inequality operator
+ ///
+ /// Inequality operator
+ bool operator!=(const ItemIt& i) {
+ return i.idx != idx;
+ }
+
+ private:
+ const ExtendFindEnum* extendFind;
+ int idx, fdx;
+ };
+
+ };
+
+ /// \ingroup auxdat
+ ///
+ /// \brief A \e Union-Find data structure implementation which
+ /// is able to store a priority for each item and retrieve the minimum of
+ /// each class.
+ ///
+ /// A \e Union-Find data structure implementation which is able to
+ /// store a priority for each item and retrieve the minimum of each
+ /// class. In addition, it supports the joining and splitting the
+ /// components. If you don't need this feature then you makes
+ /// better to use the \ref UnionFind class which is more efficient.
+ ///
+ /// The union-find data strcuture based on a (2, 16)-tree with a
+ /// tournament minimum selection on the internal nodes. The insert
+ /// operation takes O(1), the find, set, decrease and increase takes
+ /// O(log(n)), where n is the number of nodes in the current
+ /// component. The complexity of join and split is O(log(n)*k),
+ /// where n is the sum of the number of the nodes and k is the
+ /// number of joined components or the number of the components
+ /// after the split.
+ ///
+ /// \pre You need to add all the elements by the \ref insert()
+ /// method.
+ template <typename V, typename IM, typename Comp = std::less<V> >
+ class HeapUnionFind {
+ public:
+
+ ///\e
+ typedef V Value;
+ ///\e
+ typedef typename IM::Key Item;
+ ///\e
+ typedef IM ItemIntMap;
+ ///\e
+ typedef Comp Compare;
+
+ private:
+
+ static const int cmax = 16;
+
+ ItemIntMap& index;
+
+ struct ClassNode {
+ int parent;
+ int depth;
+
+ int left, right;
+ int next, prev;
+ };
+
+ int first_class;
+ int first_free_class;
+ std::vector<ClassNode> classes;
+
+ int newClass() {
+ if (first_free_class < 0) {
+ int id = classes.size();
+ classes.push_back(ClassNode());
+ return id;
+ } else {
+ int id = first_free_class;
+ first_free_class = classes[id].next;
+ return id;
+ }
+ }
+
+ void deleteClass(int id) {
+ classes[id].next = first_free_class;
+ first_free_class = id;
+ }
+
+ struct ItemNode {
+ int parent;
+ Item item;
+ Value prio;
+ int next, prev;
+ int left, right;
+ int size;
+ };
+
+ int first_free_node;
+ std::vector<ItemNode> nodes;
+
+ int newNode() {
+ if (first_free_node < 0) {
+ int id = nodes.size();
+ nodes.push_back(ItemNode());
+ return id;
+ } else {
+ int id = first_free_node;
+ first_free_node = nodes[id].next;
+ return id;
+ }
+ }
+
+ void deleteNode(int id) {
+ nodes[id].next = first_free_node;
+ first_free_node = id;
+ }
+
+ Comp comp;
+
+ int findClass(int id) const {
+ int kd = id;
+ while (kd >= 0) {
+ kd = nodes[kd].parent;
+ }
+ return ~kd;
+ }
+
+ int leftNode(int id) const {
+ int kd = ~(classes[id].parent);
+ for (int i = 0; i < classes[id].depth; ++i) {
+ kd = nodes[kd].left;
+ }
+ return kd;
+ }
+
+ int nextNode(int id) const {
+ int depth = 0;
+ while (id >= 0 && nodes[id].next == -1) {
+ id = nodes[id].parent;
+ ++depth;
+ }
+ if (id < 0) {
+ return -1;
+ }
+ id = nodes[id].next;
+ while (depth--) {
+ id = nodes[id].left;
+ }
+ return id;
+ }
+
+
+ void setPrio(int id) {
+ int jd = nodes[id].left;
+ nodes[id].prio = nodes[jd].prio;
+ nodes[id].item = nodes[jd].item;
+ jd = nodes[jd].next;
+ while (jd != -1) {
+ if (comp(nodes[jd].prio, nodes[id].prio)) {
+ nodes[id].prio = nodes[jd].prio;
+ nodes[id].item = nodes[jd].item;
+ }
+ jd = nodes[jd].next;
+ }
+ }
+
+ void push(int id, int jd) {
+ nodes[id].size = 1;
+ nodes[id].left = nodes[id].right = jd;
+ nodes[jd].next = nodes[jd].prev = -1;
+ nodes[jd].parent = id;
+ }
+
+ void pushAfter(int id, int jd) {
+ int kd = nodes[id].parent;
+ if (nodes[id].next != -1) {
+ nodes[nodes[id].next].prev = jd;
+ if (kd >= 0) {
+ nodes[kd].size += 1;
+ }
+ } else {
+ if (kd >= 0) {
+ nodes[kd].right = jd;
+ nodes[kd].size += 1;
+ }
+ }
+ nodes[jd].next = nodes[id].next;
+ nodes[jd].prev = id;
+ nodes[id].next = jd;
+ nodes[jd].parent = kd;
+ }
+
+ void pushRight(int id, int jd) {
+ nodes[id].size += 1;
+ nodes[jd].prev = nodes[id].right;
+ nodes[jd].next = -1;
+ nodes[nodes[id].right].next = jd;
+ nodes[id].right = jd;
+ nodes[jd].parent = id;
+ }
+
+ void popRight(int id) {
+ nodes[id].size -= 1;
+ int jd = nodes[id].right;
+ nodes[nodes[jd].prev].next = -1;
+ nodes[id].right = nodes[jd].prev;
+ }
+
+ void splice(int id, int jd) {
+ nodes[id].size += nodes[jd].size;
+ nodes[nodes[id].right].next = nodes[jd].left;
+ nodes[nodes[jd].left].prev = nodes[id].right;
+ int kd = nodes[jd].left;
+ while (kd != -1) {
+ nodes[kd].parent = id;
+ kd = nodes[kd].next;
+ }
+ nodes[id].right = nodes[jd].right;
+ }
+
+ void split(int id, int jd) {
+ int kd = nodes[id].parent;
+ nodes[kd].right = nodes[id].prev;
+ nodes[nodes[id].prev].next = -1;
+
+ nodes[jd].left = id;
+ nodes[id].prev = -1;
+ int num = 0;
+ while (id != -1) {
+ nodes[id].parent = jd;
+ nodes[jd].right = id;
+ id = nodes[id].next;
+ ++num;
+ }
+ nodes[kd].size -= num;
+ nodes[jd].size = num;
+ }
+
+ void pushLeft(int id, int jd) {
+ nodes[id].size += 1;
+ nodes[jd].next = nodes[id].left;
+ nodes[jd].prev = -1;
+ nodes[nodes[id].left].prev = jd;
+ nodes[id].left = jd;
+ nodes[jd].parent = id;
+ }
+
+ void popLeft(int id) {
+ nodes[id].size -= 1;
+ int jd = nodes[id].left;
+ nodes[nodes[jd].next].prev = -1;
+ nodes[id].left = nodes[jd].next;
+ }
+
+ void repairLeft(int id) {
+ int jd = ~(classes[id].parent);
+ while (nodes[jd].left != -1) {
+ int kd = nodes[jd].left;
+ if (nodes[jd].size == 1) {
+ if (nodes[jd].parent < 0) {
+ classes[id].parent = ~kd;
+ classes[id].depth -= 1;
+ nodes[kd].parent = ~id;
+ deleteNode(jd);
+ jd = kd;
+ } else {
+ int pd = nodes[jd].parent;
+ if (nodes[nodes[jd].next].size < cmax) {
+ pushLeft(nodes[jd].next, nodes[jd].left);
+ if (less(jd, nodes[jd].next) ||
+ nodes[jd].item == nodes[pd].item) {
+ nodes[nodes[jd].next].prio = nodes[jd].prio;
+ nodes[nodes[jd].next].item = nodes[jd].item;
+ }
+ popLeft(pd);
+ deleteNode(jd);
+ jd = pd;
+ } else {
+ int ld = nodes[nodes[jd].next].left;
+ popLeft(nodes[jd].next);
+ pushRight(jd, ld);
+ if (less(ld, nodes[jd].left) ||
+ nodes[ld].item == nodes[pd].item) {
+ nodes[jd].item = nodes[ld].item;
+ nodes[jd].prio = nodes[ld].prio;
+ }
+ if (nodes[nodes[jd].next].item == nodes[ld].item) {
+ setPrio(nodes[jd].next);
+ }
+ jd = nodes[jd].left;
+ }
+ }
+ } else {
+ jd = nodes[jd].left;
+ }
+ }
+ }
+
+ void repairRight(int id) {
+ int jd = ~(classes[id].parent);
+ while (nodes[jd].right != -1) {
+ int kd = nodes[jd].right;
+ if (nodes[jd].size == 1) {
+ if (nodes[jd].parent < 0) {
+ classes[id].parent = ~kd;
+ classes[id].depth -= 1;
+ nodes[kd].parent = ~id;
+ deleteNode(jd);
+ jd = kd;
+ } else {
+ int pd = nodes[jd].parent;
+ if (nodes[nodes[jd].prev].size < cmax) {
+ pushRight(nodes[jd].prev, nodes[jd].right);
+ if (less(jd, nodes[jd].prev) ||
+ nodes[jd].item == nodes[pd].item) {
+ nodes[nodes[jd].prev].prio = nodes[jd].prio;
+ nodes[nodes[jd].prev].item = nodes[jd].item;
+ }
+ popRight(pd);
+ deleteNode(jd);
+ jd = pd;
+ } else {
+ int ld = nodes[nodes[jd].prev].right;
+ popRight(nodes[jd].prev);
+ pushLeft(jd, ld);
+ if (less(ld, nodes[jd].right) ||
+ nodes[ld].item == nodes[pd].item) {
+ nodes[jd].item = nodes[ld].item;
+ nodes[jd].prio = nodes[ld].prio;
+ }
+ if (nodes[nodes[jd].prev].item == nodes[ld].item) {
+ setPrio(nodes[jd].prev);
+ }
+ jd = nodes[jd].right;
+ }
+ }
+ } else {
+ jd = nodes[jd].right;
+ }
+ }
+ }
+
+
+ bool less(int id, int jd) const {
+ return comp(nodes[id].prio, nodes[jd].prio);
+ }
+
+ public:
+
+ /// \brief Returns true when the given class is alive.
+ ///
+ /// Returns true when the given class is alive, ie. the class is
+ /// not nested into other class.
+ bool alive(int cls) const {
+ return classes[cls].parent < 0;
+ }
+
+ /// \brief Returns true when the given class is trivial.
+ ///
+ /// Returns true when the given class is trivial, ie. the class
+ /// contains just one item directly.
+ bool trivial(int cls) const {
+ return classes[cls].left == -1;
+ }
+
+ /// \brief Constructs the union-find.
+ ///
+ /// Constructs the union-find.
+ /// \brief _index The index map of the union-find. The data
+ /// structure uses internally for store references.
+ HeapUnionFind(ItemIntMap& _index)
+ : index(_index), first_class(-1),
+ first_free_class(-1), first_free_node(-1) {}
+
+ /// \brief Clears the union-find data structure
+ ///
+ /// Erase each item from the data structure.
+ void clear() {
+ nodes.clear();
+ classes.clear();
+ first_free_node = first_free_class = first_class = -1;
+ }
+
+ /// \brief Insert a new node into a new component.
+ ///
+ /// Insert a new node into a new component.
+ /// \param item The item of the new node.
+ /// \param prio The priority of the new node.
+ /// \return The class id of the one-item-heap.
+ int insert(const Item& item, const Value& prio) {
+ int id = newNode();
+ nodes[id].item = item;
+ nodes[id].prio = prio;
+ nodes[id].size = 0;
+
+ nodes[id].prev = -1;
+ nodes[id].next = -1;
+
+ nodes[id].left = -1;
+ nodes[id].right = -1;
+
+ nodes[id].item = item;
+ index[item] = id;
+
+ int class_id = newClass();
+ classes[class_id].parent = ~id;
+ classes[class_id].depth = 0;
+
+ classes[class_id].left = -1;
+ classes[class_id].right = -1;
+
+ if (first_class != -1) {
+ classes[first_class].prev = class_id;
+ }
+ classes[class_id].next = first_class;
+ classes[class_id].prev = -1;
+ first_class = class_id;
+
+ nodes[id].parent = ~class_id;
+
+ return class_id;
+ }
+
+ /// \brief The class of the item.
+ ///
+ /// \return The alive class id of the item, which is not nested into
+ /// other classes.
+ ///
+ /// The time complexity is O(log(n)).
+ int find(const Item& item) const {
+ return findClass(index[item]);
+ }
+
+ /// \brief Joins the classes.
+ ///
+ /// The current function joins the given classes. The parameter is
+ /// an STL range which should be contains valid class ids. The
+ /// time complexity is O(log(n)*k) where n is the overall number
+ /// of the joined nodes and k is the number of classes.
+ /// \return The class of the joined classes.
+ /// \pre The range should contain at least two class ids.
+ template <typename Iterator>
+ int join(Iterator begin, Iterator end) {
+ std::vector<int> cs;
+ for (Iterator it = begin; it != end; ++it) {
+ cs.push_back(*it);
+ }
+
+ int class_id = newClass();
+ { // creation union-find
+
+ if (first_class != -1) {
+ classes[first_class].prev = class_id;
+ }
+ classes[class_id].next = first_class;
+ classes[class_id].prev = -1;
+ first_class = class_id;
+
+ classes[class_id].depth = classes[cs[0]].depth;
+ classes[class_id].parent = classes[cs[0]].parent;
+ nodes[~(classes[class_id].parent)].parent = ~class_id;
+
+ int l = cs[0];
+
+ classes[class_id].left = l;
+ classes[class_id].right = l;
+
+ if (classes[l].next != -1) {
+ classes[classes[l].next].prev = classes[l].prev;
+ }
+ classes[classes[l].prev].next = classes[l].next;
+
+ classes[l].prev = -1;
+ classes[l].next = -1;
+
+ classes[l].depth = leftNode(l);
+ classes[l].parent = class_id;
+
+ }
+
+ { // merging of heap
+ int l = class_id;
+ for (int ci = 1; ci < int(cs.size()); ++ci) {
+ int r = cs[ci];
+ int rln = leftNode(r);
+ if (classes[l].depth > classes[r].depth) {
+ int id = ~(classes[l].parent);
+ for (int i = classes[r].depth + 1; i < classes[l].depth; ++i) {
+ id = nodes[id].right;
+ }
+ while (id >= 0 && nodes[id].size == cmax) {
+ int new_id = newNode();
+ int right_id = nodes[id].right;
+
+ popRight(id);
+ if (nodes[id].item == nodes[right_id].item) {
+ setPrio(id);
+ }
+ push(new_id, right_id);
+ pushRight(new_id, ~(classes[r].parent));
+
+ if (less(~classes[r].parent, right_id)) {
+ nodes[new_id].item = nodes[~classes[r].parent].item;
+ nodes[new_id].prio = nodes[~classes[r].parent].prio;
+ } else {
+ nodes[new_id].item = nodes[right_id].item;
+ nodes[new_id].prio = nodes[right_id].prio;
+ }
+
+ id = nodes[id].parent;
+ classes[r].parent = ~new_id;
+ }
+ if (id < 0) {
+ int new_parent = newNode();
+ nodes[new_parent].next = -1;
+ nodes[new_parent].prev = -1;
+ nodes[new_parent].parent = ~l;
+
+ push(new_parent, ~(classes[l].parent));
+ pushRight(new_parent, ~(classes[r].parent));
+ setPrio(new_parent);
+
+ classes[l].parent = ~new_parent;
+ classes[l].depth += 1;
+ } else {
+ pushRight(id, ~(classes[r].parent));
+ while (id >= 0 && less(~(classes[r].parent), id)) {
+ nodes[id].prio = nodes[~(classes[r].parent)].prio;
+ nodes[id].item = nodes[~(classes[r].parent)].item;
+ id = nodes[id].parent;
+ }
+ }
+ } else if (classes[r].depth > classes[l].depth) {
+ int id = ~(classes[r].parent);
+ for (int i = classes[l].depth + 1; i < classes[r].depth; ++i) {
+ id = nodes[id].left;
+ }
+ while (id >= 0 && nodes[id].size == cmax) {
+ int new_id = newNode();
+ int left_id = nodes[id].left;
+
+ popLeft(id);
+ if (nodes[id].prio == nodes[left_id].prio) {
+ setPrio(id);
+ }
+ push(new_id, left_id);
+ pushLeft(new_id, ~(classes[l].parent));
+
+ if (less(~classes[l].parent, left_id)) {
+ nodes[new_id].item = nodes[~classes[l].parent].item;
+ nodes[new_id].prio = nodes[~classes[l].parent].prio;
+ } else {
+ nodes[new_id].item = nodes[left_id].item;
+ nodes[new_id].prio = nodes[left_id].prio;
+ }
+
+ id = nodes[id].parent;
+ classes[l].parent = ~new_id;
+
+ }
+ if (id < 0) {
+ int new_parent = newNode();
+ nodes[new_parent].next = -1;
+ nodes[new_parent].prev = -1;
+ nodes[new_parent].parent = ~l;
+
+ push(new_parent, ~(classes[r].parent));
+ pushLeft(new_parent, ~(classes[l].parent));
+ setPrio(new_parent);
+
+ classes[r].parent = ~new_parent;
+ classes[r].depth += 1;
+ } else {
+ pushLeft(id, ~(classes[l].parent));
+ while (id >= 0 && less(~(classes[l].parent), id)) {
+ nodes[id].prio = nodes[~(classes[l].parent)].prio;
+ nodes[id].item = nodes[~(classes[l].parent)].item;
+ id = nodes[id].parent;
+ }
+ }
+ nodes[~(classes[r].parent)].parent = ~l;
+ classes[l].parent = classes[r].parent;
+ classes[l].depth = classes[r].depth;
+ } else {
+ if (classes[l].depth != 0 &&
+ nodes[~(classes[l].parent)].size +
+ nodes[~(classes[r].parent)].size <= cmax) {
+ splice(~(classes[l].parent), ~(classes[r].parent));
+ deleteNode(~(classes[r].parent));
+ if (less(~(classes[r].parent), ~(classes[l].parent))) {
+ nodes[~(classes[l].parent)].prio =
+ nodes[~(classes[r].parent)].prio;
+ nodes[~(classes[l].parent)].item =
+ nodes[~(classes[r].parent)].item;
+ }
+ } else {
+ int new_parent = newNode();
+ nodes[new_parent].next = nodes[new_parent].prev = -1;
+ push(new_parent, ~(classes[l].parent));
+ pushRight(new_parent, ~(classes[r].parent));
+ setPrio(new_parent);
+
+ classes[l].parent = ~new_parent;
+ classes[l].depth += 1;
+ nodes[new_parent].parent = ~l;
+ }
+ }
+ if (classes[r].next != -1) {
+ classes[classes[r].next].prev = classes[r].prev;
+ }
+ classes[classes[r].prev].next = classes[r].next;
+
+ classes[r].prev = classes[l].right;
+ classes[classes[l].right].next = r;
+ classes[l].right = r;
+ classes[r].parent = l;
+
+ classes[r].next = -1;
+ classes[r].depth = rln;
+ }
+ }
+ return class_id;
+ }
+
+ /// \brief Split the class to subclasses.
+ ///
+ /// The current function splits the given class. The join, which
+ /// made the current class, stored a reference to the
+ /// subclasses. The \c splitClass() member restores the classes
+ /// and creates the heaps. The parameter is an STL output iterator
+ /// which will be filled with the subclass ids. The time
+ /// complexity is O(log(n)*k) where n is the overall number of
+ /// nodes in the splitted classes and k is the number of the
+ /// classes.
+ template <typename Iterator>
+ void split(int cls, Iterator out) {
+ std::vector<int> cs;
+ { // splitting union-find
+ int id = cls;
+ int l = classes[id].left;
+
+ classes[l].parent = classes[id].parent;
+ classes[l].depth = classes[id].depth;
+
+ nodes[~(classes[l].parent)].parent = ~l;
+
+ *out++ = l;
+
+ while (l != -1) {
+ cs.push_back(l);
+ l = classes[l].next;
+ }
+
+ classes[classes[id].right].next = first_class;
+ classes[first_class].prev = classes[id].right;
+ first_class = classes[id].left;
+
+ if (classes[id].next != -1) {
+ classes[classes[id].next].prev = classes[id].prev;
+ }
+ classes[classes[id].prev].next = classes[id].next;
+
+ deleteClass(id);
+ }
+
+ {
+ for (int i = 1; i < int(cs.size()); ++i) {
+ int l = classes[cs[i]].depth;
+ while (nodes[nodes[l].parent].left == l) {
+ l = nodes[l].parent;
+ }
+ int r = l;
+ while (nodes[l].parent >= 0) {
+ l = nodes[l].parent;
+ int new_node = newNode();
+
+ nodes[new_node].prev = -1;
+ nodes[new_node].next = -1;
+
+ split(r, new_node);
+ pushAfter(l, new_node);
+ setPrio(l);
+ setPrio(new_node);
+ r = new_node;
+ }
+ classes[cs[i]].parent = ~r;
+ classes[cs[i]].depth = classes[~(nodes[l].parent)].depth;
+ nodes[r].parent = ~cs[i];
+
+ nodes[l].next = -1;
+ nodes[r].prev = -1;
+
+ repairRight(~(nodes[l].parent));
+ repairLeft(cs[i]);
+
+ *out++ = cs[i];
+ }
+ }
+ }
+
+ /// \brief Gives back the priority of the current item.
+ ///
+ /// Gives back the priority of the current item.
+ const Value& operator[](const Item& item) const {
+ return nodes[index[item]].prio;
+ }
+
+ /// \brief Sets the priority of the current item.
+ ///
+ /// Sets the priority of the current item.
+ void set(const Item& item, const Value& prio) {
+ if (comp(prio, nodes[index[item]].prio)) {
+ decrease(item, prio);
+ } else if (!comp(prio, nodes[index[item]].prio)) {
+ increase(item, prio);
+ }
+ }
+
+ /// \brief Increase the priority of the current item.
+ ///
+ /// Increase the priority of the current item.
+ void increase(const Item& item, const Value& prio) {
+ int id = index[item];
+ int kd = nodes[id].parent;
+ nodes[id].prio = prio;
+ while (kd >= 0 && nodes[kd].item == item) {
+ setPrio(kd);
+ kd = nodes[kd].parent;
+ }
+ }
+
+ /// \brief Increase the priority of the current item.
+ ///
+ /// Increase the priority of the current item.
+ void decrease(const Item& item, const Value& prio) {
+ int id = index[item];
+ int kd = nodes[id].parent;
+ nodes[id].prio = prio;
+ while (kd >= 0 && less(id, kd)) {
+ nodes[kd].prio = prio;
+ nodes[kd].item = item;
+ kd = nodes[kd].parent;
+ }
+ }
+
+ /// \brief Gives back the minimum priority of the class.
+ ///
+ /// Gives back the minimum priority of the class.
+ const Value& classPrio(int cls) const {
+ return nodes[~(classes[cls].parent)].prio;
+ }
+
+ /// \brief Gives back the minimum priority item of the class.
+ ///
+ /// \return Gives back the minimum priority item of the class.
+ const Item& classTop(int cls) const {
+ return nodes[~(classes[cls].parent)].item;
+ }
+
+ /// \brief Gives back a representant item of the class.
+ ///
+ /// Gives back a representant item of the class.
+ /// The representant is indpendent from the priorities of the
+ /// items.
+ const Item& classRep(int id) const {
+ int parent = classes[id].parent;
+ return nodes[parent >= 0 ? classes[id].depth : leftNode(id)].item;
+ }
+
+ /// \brief LEMON style iterator for the items of a class.
+ ///
+ /// ClassIt is a lemon style iterator for the components. It iterates
+ /// on the items of a class. By example if you want to iterate on
+ /// each items of each classes then you may write the next code.
+ ///\code
+ /// for (ClassIt cit(huf); cit != INVALID; ++cit) {
+ /// std::cout << "Class: ";
+ /// for (ItemIt iit(huf, cit); iit != INVALID; ++iit) {
+ /// std::cout << toString(iit) << ' ' << std::endl;
+ /// }
+ /// std::cout << std::endl;
+ /// }
+ ///\endcode
+ class ItemIt {
+ private:
+
+ const HeapUnionFind* _huf;
+ int _id, _lid;
+
+ public:
+
+ /// \brief Default constructor
+ ///
+ /// Default constructor
+ ItemIt() {}
+
+ ItemIt(const HeapUnionFind& huf, int cls) : _huf(&huf) {
+ int id = cls;
+ int parent = _huf->classes[id].parent;
+ if (parent >= 0) {
+ _id = _huf->classes[id].depth;
+ if (_huf->classes[id].next != -1) {
+ _lid = _huf->classes[_huf->classes[id].next].depth;
+ } else {
+ _lid = -1;
+ }
+ } else {
+ _id = _huf->leftNode(id);
+ _lid = -1;
+ }
+ }
+
+ /// \brief Increment operator
+ ///
+ /// It steps to the next item in the class.
+ ItemIt& operator++() {
+ _id = _huf->nextNode(_id);
+ return *this;
+ }
+
+ /// \brief Conversion operator
+ ///
+ /// It converts the iterator to the current item.
+ operator const Item&() const {
+ return _huf->nodes[_id].item;
+ }
+
+ /// \brief Equality operator
+ ///
+ /// Equality operator
+ bool operator==(const ItemIt& i) {
+ return i._id == _id;
+ }
+
+ /// \brief Inequality operator
+ ///
+ /// Inequality operator
+ bool operator!=(const ItemIt& i) {
+ return i._id != _id;
+ }
+
+ /// \brief Equality operator
+ ///
+ /// Equality operator
+ bool operator==(Invalid) {
+ return _id == _lid;
+ }
+
+ /// \brief Inequality operator
+ ///
+ /// Inequality operator
+ bool operator!=(Invalid) {
+ return _id != _lid;
+ }
+
+ };
+
+ /// \brief Class iterator
+ ///
+ /// The iterator stores
+ class ClassIt {
+ private:
+
+ const HeapUnionFind* _huf;
+ int _id;
+
+ public:
+
+ ClassIt(const HeapUnionFind& huf)
+ : _huf(&huf), _id(huf.first_class) {}
+
+ ClassIt(const HeapUnionFind& huf, int cls)
+ : _huf(&huf), _id(huf.classes[cls].left) {}
+
+ ClassIt(Invalid) : _huf(0), _id(-1) {}
+
+ const ClassIt& operator++() {
+ _id = _huf->classes[_id].next;
+ return *this;
+ }
+
+ /// \brief Equality operator
+ ///
+ /// Equality operator
+ bool operator==(const ClassIt& i) {
+ return i._id == _id;
+ }
+
+ /// \brief Inequality operator
+ ///
+ /// Inequality operator
+ bool operator!=(const ClassIt& i) {
+ return i._id != _id;
+ }
+
+ operator int() const {
+ return _id;
+ }
+
+ };
+
+ };
+
+ //! @}
+
+} //namespace lemon
+
+#endif //LEMON_UNION_FIND_H
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/scripts/unify-sources.sh b/extern/quadriflow/3rd/lemon-1.3.1/scripts/unify-sources.sh
new file mode 100755
index 00000000000..6aae63ab641
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/scripts/unify-sources.sh
@@ -0,0 +1,390 @@
+#!/bin/bash
+#
+# This file is a part of LEMON, a generic C++ optimization library.
+#
+# Copyright (C) 2003-2009
+# Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+# (Egervary Research Group on Combinatorial Optimization, EGRES).
+#
+# Permission to use, modify and distribute this software is granted
+# provided that this copyright notice appears in all copies. For
+# precise terms see the accompanying LICENSE file.
+#
+# This software is provided "AS IS" with no warranty of any kind,
+# express or implied, and with no claim as to its suitability for any
+# purpose.
+
+YEAR=`date +%Y`
+HGROOT=`hg root`
+
+function hg_year() {
+ if [ -n "$(hg st $1)" ]; then
+ echo $YEAR
+ else
+ hg log -l 1 --template='{date|isodate}\n' $1 |
+ cut -d '-' -f 1
+ fi
+}
+
+# file enumaration modes
+
+function all_files() {
+ hg status -a -m -c |
+ cut -d ' ' -f 2 | grep -E '(\.(cc|h|dox)$|Makefile\.am$)' |
+ while read file; do echo $HGROOT/$file; done
+}
+
+function modified_files() {
+ hg status -a -m |
+ cut -d ' ' -f 2 | grep -E '(\.(cc|h|dox)$|Makefile\.am$)' |
+ while read file; do echo $HGROOT/$file; done
+}
+
+function changed_files() {
+ {
+ if [ -n "$HG_PARENT1" ]
+ then
+ hg status --rev $HG_PARENT1:$HG_NODE -a -m
+ fi
+ if [ -n "$HG_PARENT2" ]
+ then
+ hg status --rev $HG_PARENT2:$HG_NODE -a -m
+ fi
+ } | cut -d ' ' -f 2 | grep -E '(\.(cc|h|dox)$|Makefile\.am$)' |
+ sort | uniq |
+ while read file; do echo $HGROOT/$file; done
+}
+
+function given_files() {
+ for file in $GIVEN_FILES
+ do
+ echo $file
+ done
+}
+
+# actions
+
+function update_action() {
+ if ! diff -q $1 $2 >/dev/null
+ then
+ echo -n " [$3 updated]"
+ rm $2
+ mv $1 $2
+ CHANGED=YES
+ fi
+}
+
+function update_warning() {
+ echo -n " [$2 warning]"
+ WARNED=YES
+}
+
+function update_init() {
+ echo Update source files...
+ TOTAL_FILES=0
+ CHANGED_FILES=0
+ WARNED_FILES=0
+}
+
+function update_done() {
+ echo $CHANGED_FILES out of $TOTAL_FILES files has been changed.
+ echo $WARNED_FILES out of $TOTAL_FILES files triggered warnings.
+}
+
+function update_begin() {
+ ((TOTAL_FILES++))
+ CHANGED=NO
+ WARNED=NO
+}
+
+function update_end() {
+ if [ $CHANGED == YES ]
+ then
+ ((++CHANGED_FILES))
+ fi
+ if [ $WARNED == YES ]
+ then
+ ((++WARNED_FILES))
+ fi
+}
+
+function check_action() {
+ if [ "$3" == 'tabs' ]
+ then
+ if echo $2 | grep -q -v -E 'Makefile\.am$'
+ then
+ PATTERN=$(echo -e '\t')
+ else
+ PATTERN=' '
+ fi
+ elif [ "$3" == 'trailing spaces' ]
+ then
+ PATTERN='\ +$'
+ else
+ PATTERN='*'
+ fi
+
+ if ! diff -q $1 $2 >/dev/null
+ then
+ if [ "$PATTERN" == '*' ]
+ then
+ diff $1 $2 | grep '^[0-9]' | sed "s|^\(.*\)c.*$|$2:\1: check failed: $3|g" |
+ sed "s/:\([0-9]*\),\([0-9]*\):\(.*\)$/:\1:\3 (until line \2)/g"
+ else
+ grep -n -E "$PATTERN" $2 | sed "s|^\([0-9]*\):.*$|$2:\1: check failed: $3|g"
+ fi
+ FAILED=YES
+ fi
+}
+
+function check_warning() {
+ if [ "$2" == 'long lines' ]
+ then
+ grep -n -E '.{81,}' $1 | sed "s|^\([0-9]*\):.*$|$1:\1: warning: $2|g"
+ else
+ echo "$1: warning: $2"
+ fi
+ WARNED=YES
+}
+
+function check_init() {
+ echo Check source files...
+ FAILED_FILES=0
+ WARNED_FILES=0
+ TOTAL_FILES=0
+}
+
+function check_done() {
+ echo $FAILED_FILES out of $TOTAL_FILES files has been failed.
+ echo $WARNED_FILES out of $TOTAL_FILES files triggered warnings.
+
+ if [ $WARNED_FILES -gt 0 -o $FAILED_FILES -gt 0 ]
+ then
+ if [ "$WARNING" == 'INTERACTIVE' ]
+ then
+ echo -n "Are the files with errors/warnings acceptable? (yes/no) "
+ while read answer
+ do
+ if [ "$answer" == 'yes' ]
+ then
+ return 0
+ elif [ "$answer" == 'no' ]
+ then
+ return 1
+ fi
+ echo -n "Are the files with errors/warnings acceptable? (yes/no) "
+ done
+ elif [ "$WARNING" == 'WERROR' ]
+ then
+ return 1
+ fi
+ fi
+}
+
+function check_begin() {
+ ((TOTAL_FILES++))
+ FAILED=NO
+ WARNED=NO
+}
+
+function check_end() {
+ if [ $FAILED == YES ]
+ then
+ ((++FAILED_FILES))
+ fi
+ if [ $WARNED == YES ]
+ then
+ ((++WARNED_FILES))
+ fi
+}
+
+
+
+# checks
+
+function header_check() {
+ if echo $1 | grep -q -E 'Makefile\.am$'
+ then
+ return
+ fi
+
+ TMP_FILE=`mktemp`
+
+ (echo "/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-"$(hg_year $1)"
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided \"AS IS\" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+"
+ awk 'BEGIN { pm=0; }
+ pm==3 { print }
+ /\/\* / && pm==0 { pm=1;}
+ /[^:blank:]/ && (pm==0 || pm==2) { pm=3; print;}
+ /\*\// && pm==1 { pm=2;}
+ ' $1
+ ) >$TMP_FILE
+
+ "$ACTION"_action "$TMP_FILE" "$1" header
+}
+
+function tabs_check() {
+ if echo $1 | grep -q -v -E 'Makefile\.am$'
+ then
+ OLD_PATTERN=$(echo -e '\t')
+ NEW_PATTERN=' '
+ else
+ OLD_PATTERN=' '
+ NEW_PATTERN=$(echo -e '\t')
+ fi
+ TMP_FILE=`mktemp`
+ cat $1 | sed -e "s/$OLD_PATTERN/$NEW_PATTERN/g" >$TMP_FILE
+
+ "$ACTION"_action "$TMP_FILE" "$1" 'tabs'
+}
+
+function spaces_check() {
+ TMP_FILE=`mktemp`
+ cat $1 | sed -e 's/ \+$//g' >$TMP_FILE
+
+ "$ACTION"_action "$TMP_FILE" "$1" 'trailing spaces'
+}
+
+function long_lines_check() {
+ if cat $1 | grep -q -E '.{81,}'
+ then
+ "$ACTION"_warning $1 'long lines'
+ fi
+}
+
+# process the file
+
+function process_file() {
+ if [ "$ACTION" == 'update' ]
+ then
+ echo -n " $ACTION $1..."
+ else
+ echo " $ACTION $1..."
+ fi
+
+ CHECKING="header tabs spaces long_lines"
+
+ "$ACTION"_begin $1
+ for check in $CHECKING
+ do
+ "$check"_check $1
+ done
+ "$ACTION"_end $1
+ if [ "$ACTION" == 'update' ]
+ then
+ echo
+ fi
+}
+
+function process_all {
+ "$ACTION"_init
+ while read file
+ do
+ process_file $file
+ done < <($FILES)
+ "$ACTION"_done
+}
+
+while [ $# -gt 0 ]
+do
+
+ if [ "$1" == '--help' ] || [ "$1" == '-h' ]
+ then
+ echo -n \
+"Usage:
+ $0 [OPTIONS] [files]
+Options:
+ --dry-run|-n
+ Check the files, but do not modify them.
+ --interactive|-i
+ If --dry-run is specified and the checker emits warnings,
+ then the user is asked if the warnings should be considered
+ errors.
+ --werror|-w
+ Make all warnings into errors.
+ --all|-a
+ Check all source files in the repository.
+ --modified|-m
+ Check only the modified (and new) source files. This option is
+ useful to check the modification before making a commit.
+ --changed|-c
+ Check only the changed source files compared to the parent(s) of
+ the current hg node. This option is useful as hg hook script.
+ To automatically check all your changes before making a commit,
+ add the following section to the appropriate .hg/hgrc file.
+
+ [hooks]
+ pretxncommit.checksources = scripts/unify-sources.sh -c -n -i
+
+ --help|-h
+ Print this help message.
+ files
+ The files to check/unify. If no file names are given, the modified
+ source files will be checked/unified (just like using the
+ --modified|-m option).
+"
+ exit 0
+ elif [ "$1" == '--dry-run' ] || [ "$1" == '-n' ]
+ then
+ [ -n "$ACTION" ] && echo "Conflicting action options" >&2 && exit 1
+ ACTION=check
+ elif [ "$1" == "--all" ] || [ "$1" == '-a' ]
+ then
+ [ -n "$FILES" ] && echo "Conflicting target options" >&2 && exit 1
+ FILES=all_files
+ elif [ "$1" == "--changed" ] || [ "$1" == '-c' ]
+ then
+ [ -n "$FILES" ] && echo "Conflicting target options" >&2 && exit 1
+ FILES=changed_files
+ elif [ "$1" == "--modified" ] || [ "$1" == '-m' ]
+ then
+ [ -n "$FILES" ] && echo "Conflicting target options" >&2 && exit 1
+ FILES=modified_files
+ elif [ "$1" == "--interactive" ] || [ "$1" == "-i" ]
+ then
+ [ -n "$WARNING" ] && echo "Conflicting warning options" >&2 && exit 1
+ WARNING='INTERACTIVE'
+ elif [ "$1" == "--werror" ] || [ "$1" == "-w" ]
+ then
+ [ -n "$WARNING" ] && echo "Conflicting warning options" >&2 && exit 1
+ WARNING='WERROR'
+ elif [ $(echo x$1 | cut -c 2) == '-' ]
+ then
+ echo "Invalid option $1" >&2 && exit 1
+ else
+ [ -n "$FILES" ] && echo "Invalid option $1" >&2 && exit 1
+ GIVEN_FILES=$@
+ FILES=given_files
+ break
+ fi
+
+ shift
+done
+
+if [ -z $FILES ]
+then
+ FILES=modified_files
+fi
+
+if [ -z $ACTION ]
+then
+ ACTION=update
+fi
+
+process_all
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/scripts/valgrind-wrapper.sh b/extern/quadriflow/3rd/lemon-1.3.1/scripts/valgrind-wrapper.sh
new file mode 100755
index 00000000000..bbb12229066
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/scripts/valgrind-wrapper.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Run in valgrind, with leak checking enabled
+
+valgrind -q --leak-check=full "$@" 2> .valgrind-log
+
+# Save the test result
+
+result="$?"
+
+# Valgrind should generate no error messages
+
+log_contents="`cat .valgrind-log`"
+
+if [ "$log_contents" != "" ]; then
+ cat .valgrind-log >&2
+ result=1
+fi
+
+rm -f .valgrind-log
+
+exit $result
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/CMakeLists.txt b/extern/quadriflow/3rd/lemon-1.3.1/test/CMakeLists.txt
new file mode 100644
index 00000000000..96fc5dd486c
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/CMakeLists.txt
@@ -0,0 +1,161 @@
+INCLUDE_DIRECTORIES(
+ ${PROJECT_SOURCE_DIR}
+ ${PROJECT_BINARY_DIR}
+)
+
+LINK_DIRECTORIES(
+ ${PROJECT_BINARY_DIR}/lemon
+)
+
+SET(TEST_WITH_VALGRIND "NO" CACHE STRING
+ "Run the test with valgrind (YES/NO).")
+SET(VALGRIND_FLAGS "" CACHE STRING "Valgrind flags used by the tests.")
+
+SET(TESTS
+ adaptors_test
+ arc_look_up_test
+ bellman_ford_test
+ bfs_test
+ bpgraph_test
+ circulation_test
+ connectivity_test
+ counter_test
+ dfs_test
+ digraph_test
+ dijkstra_test
+ dim_test
+ edge_set_test
+ error_test
+ euler_test
+ fractional_matching_test
+ gomory_hu_test
+ graph_copy_test
+ graph_test
+ graph_utils_test
+ hao_orlin_test
+ heap_test
+ kruskal_test
+ lgf_reader_writer_test
+ lgf_test
+ maps_test
+ matching_test
+ max_cardinality_search_test
+ max_clique_test
+ max_flow_test
+ min_cost_arborescence_test
+ min_cost_flow_test
+ min_mean_cycle_test
+ nagamochi_ibaraki_test
+ path_test
+ planarity_test
+ radix_sort_test
+ random_test
+ suurballe_test
+ time_measure_test
+ tsp_test
+ unionfind_test
+)
+
+IF(LEMON_HAVE_LP)
+ IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer")
+ ADD_EXECUTABLE(lp_test lp_test.cc)
+ ELSE()
+ ADD_EXECUTABLE(lp_test EXCLUDE_FROM_ALL lp_test.cc)
+ ENDIF()
+
+ SET(LP_TEST_LIBS lemon)
+
+ IF(LEMON_HAVE_GLPK)
+ SET(LP_TEST_LIBS ${LP_TEST_LIBS} ${GLPK_LIBRARIES})
+ ENDIF()
+ IF(LEMON_HAVE_CPLEX)
+ SET(LP_TEST_LIBS ${LP_TEST_LIBS} ${ILOG_LIBRARIES})
+ ENDIF()
+ IF(LEMON_HAVE_CLP)
+ SET(LP_TEST_LIBS ${LP_TEST_LIBS} ${COIN_CLP_LIBRARIES})
+ ENDIF()
+ IF(LEMON_HAVE_SOPLEX)
+ SET(LP_TEST_LIBS ${LP_TEST_LIBS} ${SOPLEX_LIBRARIES})
+ ENDIF()
+
+ TARGET_LINK_LIBRARIES(lp_test ${LP_TEST_LIBS})
+ ADD_TEST(lp_test lp_test)
+ ADD_DEPENDENCIES(check lp_test)
+
+ IF(WIN32 AND LEMON_HAVE_GLPK)
+ GET_TARGET_PROPERTY(TARGET_LOC lp_test LOCATION)
+ GET_FILENAME_COMPONENT(TARGET_PATH ${TARGET_LOC} PATH)
+ ADD_CUSTOM_COMMAND(TARGET lp_test POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/glpk.dll ${TARGET_PATH}
+ COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/libltdl3.dll ${TARGET_PATH}
+ COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/zlib1.dll ${TARGET_PATH}
+ )
+ ENDIF()
+
+ IF(WIN32 AND LEMON_HAVE_CPLEX)
+ GET_TARGET_PROPERTY(TARGET_LOC lp_test LOCATION)
+ GET_FILENAME_COMPONENT(TARGET_PATH ${TARGET_LOC} PATH)
+ ADD_CUSTOM_COMMAND(TARGET lp_test POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${ILOG_CPLEX_DLL} ${TARGET_PATH}
+ )
+ ENDIF()
+ENDIF()
+
+IF(LEMON_HAVE_MIP)
+ IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer")
+ ADD_EXECUTABLE(mip_test mip_test.cc)
+ ELSE()
+ ADD_EXECUTABLE(mip_test EXCLUDE_FROM_ALL mip_test.cc)
+ ENDIF()
+
+ SET(MIP_TEST_LIBS lemon)
+
+ IF(LEMON_HAVE_GLPK)
+ SET(MIP_TEST_LIBS ${MIP_TEST_LIBS} ${GLPK_LIBRARIES})
+ ENDIF()
+ IF(LEMON_HAVE_CPLEX)
+ SET(MIP_TEST_LIBS ${MIP_TEST_LIBS} ${ILOG_LIBRARIES})
+ ENDIF()
+ IF(LEMON_HAVE_CBC)
+ SET(MIP_TEST_LIBS ${MIP_TEST_LIBS} ${COIN_CBC_LIBRARIES})
+ ENDIF()
+
+ TARGET_LINK_LIBRARIES(mip_test ${MIP_TEST_LIBS})
+ ADD_TEST(mip_test mip_test)
+ ADD_DEPENDENCIES(check mip_test)
+
+ IF(WIN32 AND LEMON_HAVE_GLPK)
+ GET_TARGET_PROPERTY(TARGET_LOC mip_test LOCATION)
+ GET_FILENAME_COMPONENT(TARGET_PATH ${TARGET_LOC} PATH)
+ ADD_CUSTOM_COMMAND(TARGET mip_test POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/glpk.dll ${TARGET_PATH}
+ COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/libltdl3.dll ${TARGET_PATH}
+ COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/zlib1.dll ${TARGET_PATH}
+ )
+ ENDIF()
+
+ IF(WIN32 AND LEMON_HAVE_CPLEX)
+ GET_TARGET_PROPERTY(TARGET_LOC mip_test LOCATION)
+ GET_FILENAME_COMPONENT(TARGET_PATH ${TARGET_LOC} PATH)
+ ADD_CUSTOM_COMMAND(TARGET mip_test POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${ILOG_CPLEX_DLL} ${TARGET_PATH}
+ )
+ ENDIF()
+ENDIF()
+
+FOREACH(TEST_NAME ${TESTS})
+ IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer")
+ ADD_EXECUTABLE(${TEST_NAME} ${TEST_NAME}.cc)
+ ELSE()
+ ADD_EXECUTABLE(${TEST_NAME} EXCLUDE_FROM_ALL ${TEST_NAME}.cc)
+ ENDIF()
+ TARGET_LINK_LIBRARIES(${TEST_NAME} lemon)
+ IF(TEST_WITH_VALGRIND)
+ ADD_TEST(${TEST_NAME}
+ valgrind --error-exitcode=1 ${VALGRIND_FLAGS}
+ ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME} )
+ ELSE()
+ ADD_TEST(${TEST_NAME} ${TEST_NAME})
+ ENDIF()
+ ADD_DEPENDENCIES(check ${TEST_NAME})
+ENDFOREACH()
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/adaptors_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/adaptors_test.cc
new file mode 100644
index 00000000000..9077db96eff
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/adaptors_test.cc
@@ -0,0 +1,1468 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+#include <limits>
+
+#include <lemon/list_graph.h>
+#include <lemon/grid_graph.h>
+#include <lemon/bfs.h>
+#include <lemon/path.h>
+
+#include <lemon/concepts/digraph.h>
+#include <lemon/concepts/graph.h>
+#include <lemon/concepts/graph_components.h>
+#include <lemon/concepts/maps.h>
+#include <lemon/concept_check.h>
+
+#include <lemon/adaptors.h>
+
+#include "test/test_tools.h"
+#include "test/graph_test.h"
+
+using namespace lemon;
+
+void checkReverseDigraph() {
+ // Check concepts
+ checkConcept<concepts::Digraph, ReverseDigraph<concepts::Digraph> >();
+ checkConcept<concepts::Digraph, ReverseDigraph<ListDigraph> >();
+ checkConcept<concepts::AlterableDigraphComponent<>,
+ ReverseDigraph<ListDigraph> >();
+ checkConcept<concepts::ExtendableDigraphComponent<>,
+ ReverseDigraph<ListDigraph> >();
+ checkConcept<concepts::ErasableDigraphComponent<>,
+ ReverseDigraph<ListDigraph> >();
+ checkConcept<concepts::ClearableDigraphComponent<>,
+ ReverseDigraph<ListDigraph> >();
+
+ // Create a digraph and an adaptor
+ typedef ListDigraph Digraph;
+ typedef ReverseDigraph<Digraph> Adaptor;
+
+ Digraph digraph;
+ Adaptor adaptor(digraph);
+
+ // Add nodes and arcs to the original digraph
+ Digraph::Node n1 = digraph.addNode();
+ Digraph::Node n2 = digraph.addNode();
+ Digraph::Node n3 = digraph.addNode();
+
+ Digraph::Arc a1 = digraph.addArc(n1, n2);
+ Digraph::Arc a2 = digraph.addArc(n1, n3);
+ Digraph::Arc a3 = digraph.addArc(n2, n3);
+ ::lemon::ignore_unused_variable_warning(a3);
+
+ // Check the adaptor
+ checkGraphNodeList(adaptor, 3);
+ checkGraphArcList(adaptor, 3);
+ checkGraphConArcList(adaptor, 3);
+
+ checkGraphOutArcList(adaptor, n1, 0);
+ checkGraphOutArcList(adaptor, n2, 1);
+ checkGraphOutArcList(adaptor, n3, 2);
+
+ checkGraphInArcList(adaptor, n1, 2);
+ checkGraphInArcList(adaptor, n2, 1);
+ checkGraphInArcList(adaptor, n3, 0);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+
+ // Check the orientation of the arcs
+ for (Adaptor::ArcIt a(adaptor); a != INVALID; ++a) {
+ check(adaptor.source(a) == digraph.target(a), "Wrong reverse");
+ check(adaptor.target(a) == digraph.source(a), "Wrong reverse");
+ }
+
+ // Add and erase nodes and arcs in the digraph through the adaptor
+ Adaptor::Node n4 = adaptor.addNode();
+
+ Adaptor::Arc a4 = adaptor.addArc(n4, n3);
+ Adaptor::Arc a5 = adaptor.addArc(n2, n4);
+ Adaptor::Arc a6 = adaptor.addArc(n2, n4);
+ Adaptor::Arc a7 = adaptor.addArc(n1, n4);
+ Adaptor::Arc a8 = adaptor.addArc(n1, n2);
+ ::lemon::ignore_unused_variable_warning(a6,a7,a8);
+
+ adaptor.erase(a1);
+ adaptor.erase(n3);
+
+ // Check the adaptor
+ checkGraphNodeList(adaptor, 3);
+ checkGraphArcList(adaptor, 4);
+ checkGraphConArcList(adaptor, 4);
+
+ checkGraphOutArcList(adaptor, n1, 2);
+ checkGraphOutArcList(adaptor, n2, 2);
+ checkGraphOutArcList(adaptor, n4, 0);
+
+ checkGraphInArcList(adaptor, n1, 0);
+ checkGraphInArcList(adaptor, n2, 1);
+ checkGraphInArcList(adaptor, n4, 3);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+
+ // Check the digraph
+ checkGraphNodeList(digraph, 3);
+ checkGraphArcList(digraph, 4);
+ checkGraphConArcList(digraph, 4);
+
+ checkGraphOutArcList(digraph, n1, 0);
+ checkGraphOutArcList(digraph, n2, 1);
+ checkGraphOutArcList(digraph, n4, 3);
+
+ checkGraphInArcList(digraph, n1, 2);
+ checkGraphInArcList(digraph, n2, 2);
+ checkGraphInArcList(digraph, n4, 0);
+
+ checkNodeIds(digraph);
+ checkArcIds(digraph);
+
+ checkGraphNodeMap(digraph);
+ checkGraphArcMap(digraph);
+
+ // Check the conversion of nodes and arcs
+ Digraph::Node nd = n4;
+ nd = n4;
+ Adaptor::Node na = n1;
+ na = n2;
+ Digraph::Arc ad = a4;
+ ad = a5;
+ Adaptor::Arc aa = a1;
+ aa = a2;
+}
+
+void checkSubDigraph() {
+ // Check concepts
+ checkConcept<concepts::Digraph, SubDigraph<concepts::Digraph> >();
+ checkConcept<concepts::Digraph, SubDigraph<ListDigraph> >();
+ checkConcept<concepts::AlterableDigraphComponent<>,
+ SubDigraph<ListDigraph> >();
+ checkConcept<concepts::ExtendableDigraphComponent<>,
+ SubDigraph<ListDigraph> >();
+ checkConcept<concepts::ErasableDigraphComponent<>,
+ SubDigraph<ListDigraph> >();
+ checkConcept<concepts::ClearableDigraphComponent<>,
+ SubDigraph<ListDigraph> >();
+
+ // Create a digraph and an adaptor
+ typedef ListDigraph Digraph;
+ typedef Digraph::NodeMap<bool> NodeFilter;
+ typedef Digraph::ArcMap<bool> ArcFilter;
+ typedef SubDigraph<Digraph, NodeFilter, ArcFilter> Adaptor;
+
+ Digraph digraph;
+ NodeFilter node_filter(digraph);
+ ArcFilter arc_filter(digraph);
+ Adaptor adaptor(digraph, node_filter, arc_filter);
+
+ // Add nodes and arcs to the original digraph and the adaptor
+ Digraph::Node n1 = digraph.addNode();
+ Digraph::Node n2 = digraph.addNode();
+ Adaptor::Node n3 = adaptor.addNode();
+
+ node_filter[n1] = node_filter[n2] = node_filter[n3] = true;
+
+ Digraph::Arc a1 = digraph.addArc(n1, n2);
+ Digraph::Arc a2 = digraph.addArc(n1, n3);
+ Adaptor::Arc a3 = adaptor.addArc(n2, n3);
+
+ arc_filter[a1] = arc_filter[a2] = arc_filter[a3] = true;
+
+ checkGraphNodeList(adaptor, 3);
+ checkGraphArcList(adaptor, 3);
+ checkGraphConArcList(adaptor, 3);
+
+ checkGraphOutArcList(adaptor, n1, 2);
+ checkGraphOutArcList(adaptor, n2, 1);
+ checkGraphOutArcList(adaptor, n3, 0);
+
+ checkGraphInArcList(adaptor, n1, 0);
+ checkGraphInArcList(adaptor, n2, 1);
+ checkGraphInArcList(adaptor, n3, 2);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+
+ // Hide an arc
+ adaptor.status(a2, false);
+ adaptor.disable(a3);
+ if (!adaptor.status(a3)) adaptor.enable(a3);
+
+ checkGraphNodeList(adaptor, 3);
+ checkGraphArcList(adaptor, 2);
+ checkGraphConArcList(adaptor, 2);
+
+ checkGraphOutArcList(adaptor, n1, 1);
+ checkGraphOutArcList(adaptor, n2, 1);
+ checkGraphOutArcList(adaptor, n3, 0);
+
+ checkGraphInArcList(adaptor, n1, 0);
+ checkGraphInArcList(adaptor, n2, 1);
+ checkGraphInArcList(adaptor, n3, 1);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+
+ // Hide a node
+ adaptor.status(n1, false);
+ adaptor.disable(n3);
+ if (!adaptor.status(n3)) adaptor.enable(n3);
+
+ checkGraphNodeList(adaptor, 2);
+ checkGraphArcList(adaptor, 1);
+ checkGraphConArcList(adaptor, 1);
+
+ checkGraphOutArcList(adaptor, n2, 1);
+ checkGraphOutArcList(adaptor, n3, 0);
+
+ checkGraphInArcList(adaptor, n2, 0);
+ checkGraphInArcList(adaptor, n3, 1);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+
+ // Hide all nodes and arcs
+ node_filter[n1] = node_filter[n2] = node_filter[n3] = false;
+ arc_filter[a1] = arc_filter[a2] = arc_filter[a3] = false;
+
+ checkGraphNodeList(adaptor, 0);
+ checkGraphArcList(adaptor, 0);
+ checkGraphConArcList(adaptor, 0);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+
+ // Check the conversion of nodes and arcs
+ Digraph::Node nd = n3;
+ nd = n3;
+ Adaptor::Node na = n1;
+ na = n2;
+ Digraph::Arc ad = a3;
+ ad = a3;
+ Adaptor::Arc aa = a1;
+ aa = a2;
+}
+
+void checkFilterNodes1() {
+ // Check concepts
+ checkConcept<concepts::Digraph, FilterNodes<concepts::Digraph> >();
+ checkConcept<concepts::Digraph, FilterNodes<ListDigraph> >();
+ checkConcept<concepts::AlterableDigraphComponent<>,
+ FilterNodes<ListDigraph> >();
+ checkConcept<concepts::ExtendableDigraphComponent<>,
+ FilterNodes<ListDigraph> >();
+ checkConcept<concepts::ErasableDigraphComponent<>,
+ FilterNodes<ListDigraph> >();
+ checkConcept<concepts::ClearableDigraphComponent<>,
+ FilterNodes<ListDigraph> >();
+
+ // Create a digraph and an adaptor
+ typedef ListDigraph Digraph;
+ typedef Digraph::NodeMap<bool> NodeFilter;
+ typedef FilterNodes<Digraph, NodeFilter> Adaptor;
+
+ Digraph digraph;
+ NodeFilter node_filter(digraph);
+ Adaptor adaptor(digraph, node_filter);
+
+ // Add nodes and arcs to the original digraph and the adaptor
+ Digraph::Node n1 = digraph.addNode();
+ Digraph::Node n2 = digraph.addNode();
+ Adaptor::Node n3 = adaptor.addNode();
+
+ node_filter[n1] = node_filter[n2] = node_filter[n3] = true;
+
+ Digraph::Arc a1 = digraph.addArc(n1, n2);
+ Digraph::Arc a2 = digraph.addArc(n1, n3);
+ Adaptor::Arc a3 = adaptor.addArc(n2, n3);
+
+ checkGraphNodeList(adaptor, 3);
+ checkGraphArcList(adaptor, 3);
+ checkGraphConArcList(adaptor, 3);
+
+ checkGraphOutArcList(adaptor, n1, 2);
+ checkGraphOutArcList(adaptor, n2, 1);
+ checkGraphOutArcList(adaptor, n3, 0);
+
+ checkGraphInArcList(adaptor, n1, 0);
+ checkGraphInArcList(adaptor, n2, 1);
+ checkGraphInArcList(adaptor, n3, 2);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+
+ // Hide a node
+ adaptor.status(n1, false);
+ adaptor.disable(n3);
+ if (!adaptor.status(n3)) adaptor.enable(n3);
+
+ checkGraphNodeList(adaptor, 2);
+ checkGraphArcList(adaptor, 1);
+ checkGraphConArcList(adaptor, 1);
+
+ checkGraphOutArcList(adaptor, n2, 1);
+ checkGraphOutArcList(adaptor, n3, 0);
+
+ checkGraphInArcList(adaptor, n2, 0);
+ checkGraphInArcList(adaptor, n3, 1);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+
+ // Hide all nodes
+ node_filter[n1] = node_filter[n2] = node_filter[n3] = false;
+
+ checkGraphNodeList(adaptor, 0);
+ checkGraphArcList(adaptor, 0);
+ checkGraphConArcList(adaptor, 0);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+
+ // Check the conversion of nodes and arcs
+ Digraph::Node nd = n3;
+ nd = n3;
+ Adaptor::Node na = n1;
+ na = n2;
+ Digraph::Arc ad = a3;
+ ad = a3;
+ Adaptor::Arc aa = a1;
+ aa = a2;
+}
+
+void checkFilterArcs() {
+ // Check concepts
+ checkConcept<concepts::Digraph, FilterArcs<concepts::Digraph> >();
+ checkConcept<concepts::Digraph, FilterArcs<ListDigraph> >();
+ checkConcept<concepts::AlterableDigraphComponent<>,
+ FilterArcs<ListDigraph> >();
+ checkConcept<concepts::ExtendableDigraphComponent<>,
+ FilterArcs<ListDigraph> >();
+ checkConcept<concepts::ErasableDigraphComponent<>,
+ FilterArcs<ListDigraph> >();
+ checkConcept<concepts::ClearableDigraphComponent<>,
+ FilterArcs<ListDigraph> >();
+
+ // Create a digraph and an adaptor
+ typedef ListDigraph Digraph;
+ typedef Digraph::ArcMap<bool> ArcFilter;
+ typedef FilterArcs<Digraph, ArcFilter> Adaptor;
+
+ Digraph digraph;
+ ArcFilter arc_filter(digraph);
+ Adaptor adaptor(digraph, arc_filter);
+
+ // Add nodes and arcs to the original digraph and the adaptor
+ Digraph::Node n1 = digraph.addNode();
+ Digraph::Node n2 = digraph.addNode();
+ Adaptor::Node n3 = adaptor.addNode();
+
+ Digraph::Arc a1 = digraph.addArc(n1, n2);
+ Digraph::Arc a2 = digraph.addArc(n1, n3);
+ Adaptor::Arc a3 = adaptor.addArc(n2, n3);
+
+ arc_filter[a1] = arc_filter[a2] = arc_filter[a3] = true;
+
+ checkGraphNodeList(adaptor, 3);
+ checkGraphArcList(adaptor, 3);
+ checkGraphConArcList(adaptor, 3);
+
+ checkGraphOutArcList(adaptor, n1, 2);
+ checkGraphOutArcList(adaptor, n2, 1);
+ checkGraphOutArcList(adaptor, n3, 0);
+
+ checkGraphInArcList(adaptor, n1, 0);
+ checkGraphInArcList(adaptor, n2, 1);
+ checkGraphInArcList(adaptor, n3, 2);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+
+ // Hide an arc
+ adaptor.status(a2, false);
+ adaptor.disable(a3);
+ if (!adaptor.status(a3)) adaptor.enable(a3);
+
+ checkGraphNodeList(adaptor, 3);
+ checkGraphArcList(adaptor, 2);
+ checkGraphConArcList(adaptor, 2);
+
+ checkGraphOutArcList(adaptor, n1, 1);
+ checkGraphOutArcList(adaptor, n2, 1);
+ checkGraphOutArcList(adaptor, n3, 0);
+
+ checkGraphInArcList(adaptor, n1, 0);
+ checkGraphInArcList(adaptor, n2, 1);
+ checkGraphInArcList(adaptor, n3, 1);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+
+ // Hide all arcs
+ arc_filter[a1] = arc_filter[a2] = arc_filter[a3] = false;
+
+ checkGraphNodeList(adaptor, 3);
+ checkGraphArcList(adaptor, 0);
+ checkGraphConArcList(adaptor, 0);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+
+ // Check the conversion of nodes and arcs
+ Digraph::Node nd = n3;
+ nd = n3;
+ Adaptor::Node na = n1;
+ na = n2;
+ Digraph::Arc ad = a3;
+ ad = a3;
+ Adaptor::Arc aa = a1;
+ aa = a2;
+}
+
+void checkUndirector() {
+ // Check concepts
+ checkConcept<concepts::Graph, Undirector<concepts::Digraph> >();
+ checkConcept<concepts::Graph, Undirector<ListDigraph> >();
+ checkConcept<concepts::AlterableGraphComponent<>,
+ Undirector<ListDigraph> >();
+ checkConcept<concepts::ExtendableGraphComponent<>,
+ Undirector<ListDigraph> >();
+ checkConcept<concepts::ErasableGraphComponent<>,
+ Undirector<ListDigraph> >();
+ checkConcept<concepts::ClearableGraphComponent<>,
+ Undirector<ListDigraph> >();
+
+
+ // Create a digraph and an adaptor
+ typedef ListDigraph Digraph;
+ typedef Undirector<Digraph> Adaptor;
+
+ Digraph digraph;
+ Adaptor adaptor(digraph);
+
+ // Add nodes and arcs/edges to the original digraph and the adaptor
+ Digraph::Node n1 = digraph.addNode();
+ Digraph::Node n2 = digraph.addNode();
+ Adaptor::Node n3 = adaptor.addNode();
+
+ Digraph::Arc a1 = digraph.addArc(n1, n2);
+ Digraph::Arc a2 = digraph.addArc(n1, n3);
+ Adaptor::Edge e3 = adaptor.addEdge(n2, n3);
+
+ // Check the original digraph
+ checkGraphNodeList(digraph, 3);
+ checkGraphArcList(digraph, 3);
+ checkGraphConArcList(digraph, 3);
+
+ checkGraphOutArcList(digraph, n1, 2);
+ checkGraphOutArcList(digraph, n2, 1);
+ checkGraphOutArcList(digraph, n3, 0);
+
+ checkGraphInArcList(digraph, n1, 0);
+ checkGraphInArcList(digraph, n2, 1);
+ checkGraphInArcList(digraph, n3, 2);
+
+ checkNodeIds(digraph);
+ checkArcIds(digraph);
+
+ checkGraphNodeMap(digraph);
+ checkGraphArcMap(digraph);
+
+ // Check the adaptor
+ checkGraphNodeList(adaptor, 3);
+ checkGraphArcList(adaptor, 6);
+ checkGraphEdgeList(adaptor, 3);
+ checkGraphConArcList(adaptor, 6);
+ checkGraphConEdgeList(adaptor, 3);
+
+ checkGraphIncEdgeArcLists(adaptor, n1, 2);
+ checkGraphIncEdgeArcLists(adaptor, n2, 2);
+ checkGraphIncEdgeArcLists(adaptor, n3, 2);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+ checkEdgeIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+ checkGraphEdgeMap(adaptor);
+
+ // Check the edges of the adaptor
+ for (Adaptor::EdgeIt e(adaptor); e != INVALID; ++e) {
+ check(adaptor.u(e) == digraph.source(e), "Wrong undir");
+ check(adaptor.v(e) == digraph.target(e), "Wrong undir");
+ }
+
+ // Check CombinedArcMap
+ typedef Adaptor::CombinedArcMap
+ <Digraph::ArcMap<int>, Digraph::ArcMap<int> > IntCombinedMap;
+ typedef Adaptor::CombinedArcMap
+ <Digraph::ArcMap<bool>, Digraph::ArcMap<bool> > BoolCombinedMap;
+ checkConcept<concepts::ReferenceMap<Adaptor::Arc, int, int&, const int&>,
+ IntCombinedMap>();
+ checkConcept<concepts::ReferenceMap<Adaptor::Arc, bool, bool&, const bool&>,
+ BoolCombinedMap>();
+
+ Digraph::ArcMap<int> fw_map(digraph), bk_map(digraph);
+ for (Digraph::ArcIt a(digraph); a != INVALID; ++a) {
+ fw_map[a] = digraph.id(a);
+ bk_map[a] = -digraph.id(a);
+ }
+
+ Adaptor::CombinedArcMap<Digraph::ArcMap<int>, Digraph::ArcMap<int> >
+ comb_map(fw_map, bk_map);
+ for (Adaptor::ArcIt a(adaptor); a != INVALID; ++a) {
+ if (adaptor.source(a) == digraph.source(a)) {
+ check(comb_map[a] == fw_map[a], "Wrong combined map");
+ } else {
+ check(comb_map[a] == bk_map[a], "Wrong combined map");
+ }
+ }
+
+ // Check the conversion of nodes and arcs/edges
+ Digraph::Node nd = n3;
+ nd = n3;
+ Adaptor::Node na = n1;
+ na = n2;
+ Digraph::Arc ad = e3;
+ ad = e3;
+ Adaptor::Edge ea = a1;
+ ea = a2;
+}
+
+void checkResidualDigraph() {
+ // Check concepts
+ checkConcept<concepts::Digraph, ResidualDigraph<concepts::Digraph> >();
+ checkConcept<concepts::Digraph, ResidualDigraph<ListDigraph> >();
+
+ // Create a digraph and an adaptor
+ typedef ListDigraph Digraph;
+ typedef Digraph::ArcMap<int> IntArcMap;
+ typedef ResidualDigraph<Digraph, IntArcMap> Adaptor;
+
+ Digraph digraph;
+ IntArcMap capacity(digraph), flow(digraph);
+ Adaptor adaptor(digraph, capacity, flow);
+
+ Digraph::Node n1 = digraph.addNode();
+ Digraph::Node n2 = digraph.addNode();
+ Digraph::Node n3 = digraph.addNode();
+ Digraph::Node n4 = digraph.addNode();
+
+ Digraph::Arc a1 = digraph.addArc(n1, n2);
+ Digraph::Arc a2 = digraph.addArc(n1, n3);
+ Digraph::Arc a3 = digraph.addArc(n1, n4);
+ Digraph::Arc a4 = digraph.addArc(n2, n3);
+ Digraph::Arc a5 = digraph.addArc(n2, n4);
+ Digraph::Arc a6 = digraph.addArc(n3, n4);
+
+ capacity[a1] = 8;
+ capacity[a2] = 6;
+ capacity[a3] = 4;
+ capacity[a4] = 4;
+ capacity[a5] = 6;
+ capacity[a6] = 10;
+
+ // Check the adaptor with various flow values
+ for (Digraph::ArcIt a(digraph); a != INVALID; ++a) {
+ flow[a] = 0;
+ }
+
+ checkGraphNodeList(adaptor, 4);
+ checkGraphArcList(adaptor, 6);
+ checkGraphConArcList(adaptor, 6);
+
+ checkGraphOutArcList(adaptor, n1, 3);
+ checkGraphOutArcList(adaptor, n2, 2);
+ checkGraphOutArcList(adaptor, n3, 1);
+ checkGraphOutArcList(adaptor, n4, 0);
+
+ checkGraphInArcList(adaptor, n1, 0);
+ checkGraphInArcList(adaptor, n2, 1);
+ checkGraphInArcList(adaptor, n3, 2);
+ checkGraphInArcList(adaptor, n4, 3);
+
+ for (Digraph::ArcIt a(digraph); a != INVALID; ++a) {
+ flow[a] = capacity[a] / 2;
+ }
+
+ checkGraphNodeList(adaptor, 4);
+ checkGraphArcList(adaptor, 12);
+ checkGraphConArcList(adaptor, 12);
+
+ checkGraphOutArcList(adaptor, n1, 3);
+ checkGraphOutArcList(adaptor, n2, 3);
+ checkGraphOutArcList(adaptor, n3, 3);
+ checkGraphOutArcList(adaptor, n4, 3);
+
+ checkGraphInArcList(adaptor, n1, 3);
+ checkGraphInArcList(adaptor, n2, 3);
+ checkGraphInArcList(adaptor, n3, 3);
+ checkGraphInArcList(adaptor, n4, 3);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+
+ for (Digraph::ArcIt a(digraph); a != INVALID; ++a) {
+ flow[a] = capacity[a];
+ }
+
+ checkGraphNodeList(adaptor, 4);
+ checkGraphArcList(adaptor, 6);
+ checkGraphConArcList(adaptor, 6);
+
+ checkGraphOutArcList(adaptor, n1, 0);
+ checkGraphOutArcList(adaptor, n2, 1);
+ checkGraphOutArcList(adaptor, n3, 2);
+ checkGraphOutArcList(adaptor, n4, 3);
+
+ checkGraphInArcList(adaptor, n1, 3);
+ checkGraphInArcList(adaptor, n2, 2);
+ checkGraphInArcList(adaptor, n3, 1);
+ checkGraphInArcList(adaptor, n4, 0);
+
+ // Saturate all backward arcs
+ // (set the flow to zero on all forward arcs)
+ for (Adaptor::ArcIt a(adaptor); a != INVALID; ++a) {
+ if (adaptor.backward(a))
+ adaptor.augment(a, adaptor.residualCapacity(a));
+ }
+
+ checkGraphNodeList(adaptor, 4);
+ checkGraphArcList(adaptor, 6);
+ checkGraphConArcList(adaptor, 6);
+
+ checkGraphOutArcList(adaptor, n1, 3);
+ checkGraphOutArcList(adaptor, n2, 2);
+ checkGraphOutArcList(adaptor, n3, 1);
+ checkGraphOutArcList(adaptor, n4, 0);
+
+ checkGraphInArcList(adaptor, n1, 0);
+ checkGraphInArcList(adaptor, n2, 1);
+ checkGraphInArcList(adaptor, n3, 2);
+ checkGraphInArcList(adaptor, n4, 3);
+
+ // Find maximum flow by augmenting along shortest paths
+ int flow_value = 0;
+ Adaptor::ResidualCapacity res_cap(adaptor);
+ while (true) {
+
+ Bfs<Adaptor> bfs(adaptor);
+ bfs.run(n1, n4);
+
+ if (!bfs.reached(n4)) break;
+
+ Path<Adaptor> p = bfs.path(n4);
+
+ int min = std::numeric_limits<int>::max();
+ for (Path<Adaptor>::ArcIt a(p); a != INVALID; ++a) {
+ if (res_cap[a] < min) min = res_cap[a];
+ }
+
+ for (Path<Adaptor>::ArcIt a(p); a != INVALID; ++a) {
+ adaptor.augment(a, min);
+ }
+ flow_value += min;
+ }
+
+ check(flow_value == 18, "Wrong flow with res graph adaptor");
+
+ // Check forward() and backward()
+ for (Adaptor::ArcIt a(adaptor); a != INVALID; ++a) {
+ check(adaptor.forward(a) != adaptor.backward(a),
+ "Wrong forward() or backward()");
+ check((adaptor.forward(a) && adaptor.forward(Digraph::Arc(a)) == a) ||
+ (adaptor.backward(a) && adaptor.backward(Digraph::Arc(a)) == a),
+ "Wrong forward() or backward()");
+ }
+
+ // Check the conversion of nodes and arcs
+ Digraph::Node nd = Adaptor::NodeIt(adaptor);
+ nd = ++Adaptor::NodeIt(adaptor);
+ Adaptor::Node na = n1;
+ na = n2;
+ Digraph::Arc ad = Adaptor::ArcIt(adaptor);
+ ad = ++Adaptor::ArcIt(adaptor);
+}
+
+void checkSplitNodes() {
+ // Check concepts
+ checkConcept<concepts::Digraph, SplitNodes<concepts::Digraph> >();
+ checkConcept<concepts::Digraph, SplitNodes<ListDigraph> >();
+
+ // Create a digraph and an adaptor
+ typedef ListDigraph Digraph;
+ typedef SplitNodes<Digraph> Adaptor;
+
+ Digraph digraph;
+ Adaptor adaptor(digraph);
+
+ Digraph::Node n1 = digraph.addNode();
+ Digraph::Node n2 = digraph.addNode();
+ Digraph::Node n3 = digraph.addNode();
+
+ Digraph::Arc a1 = digraph.addArc(n1, n2);
+ Digraph::Arc a2 = digraph.addArc(n1, n3);
+ Digraph::Arc a3 = digraph.addArc(n2, n3);
+ ::lemon::ignore_unused_variable_warning(a1,a2,a3);
+
+ checkGraphNodeList(adaptor, 6);
+ checkGraphArcList(adaptor, 6);
+ checkGraphConArcList(adaptor, 6);
+
+ checkGraphOutArcList(adaptor, adaptor.inNode(n1), 1);
+ checkGraphOutArcList(adaptor, adaptor.outNode(n1), 2);
+ checkGraphOutArcList(adaptor, adaptor.inNode(n2), 1);
+ checkGraphOutArcList(adaptor, adaptor.outNode(n2), 1);
+ checkGraphOutArcList(adaptor, adaptor.inNode(n3), 1);
+ checkGraphOutArcList(adaptor, adaptor.outNode(n3), 0);
+
+ checkGraphInArcList(adaptor, adaptor.inNode(n1), 0);
+ checkGraphInArcList(adaptor, adaptor.outNode(n1), 1);
+ checkGraphInArcList(adaptor, adaptor.inNode(n2), 1);
+ checkGraphInArcList(adaptor, adaptor.outNode(n2), 1);
+ checkGraphInArcList(adaptor, adaptor.inNode(n3), 2);
+ checkGraphInArcList(adaptor, adaptor.outNode(n3), 1);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+
+ // Check split
+ for (Adaptor::ArcIt a(adaptor); a != INVALID; ++a) {
+ if (adaptor.origArc(a)) {
+ Digraph::Arc oa = a;
+ check(adaptor.source(a) == adaptor.outNode(digraph.source(oa)),
+ "Wrong split");
+ check(adaptor.target(a) == adaptor.inNode(digraph.target(oa)),
+ "Wrong split");
+ } else {
+ Digraph::Node on = a;
+ check(adaptor.source(a) == adaptor.inNode(on), "Wrong split");
+ check(adaptor.target(a) == adaptor.outNode(on), "Wrong split");
+ }
+ }
+
+ // Check combined node map
+ typedef Adaptor::CombinedNodeMap
+ <Digraph::NodeMap<int>, Digraph::NodeMap<int> > IntCombinedNodeMap;
+ typedef Adaptor::CombinedNodeMap
+ <Digraph::NodeMap<bool>, Digraph::NodeMap<bool> > BoolCombinedNodeMap;
+ checkConcept<concepts::ReferenceMap<Adaptor::Node, int, int&, const int&>,
+ IntCombinedNodeMap>();
+//checkConcept<concepts::ReferenceMap<Adaptor::Node, bool, bool&, const bool&>,
+// BoolCombinedNodeMap>();
+ checkConcept<concepts::ReadWriteMap<Adaptor::Node, bool>,
+ BoolCombinedNodeMap>();
+
+ Digraph::NodeMap<int> in_map(digraph), out_map(digraph);
+ for (Digraph::NodeIt n(digraph); n != INVALID; ++n) {
+ in_map[n] = digraph.id(n);
+ out_map[n] = -digraph.id(n);
+ }
+
+ Adaptor::CombinedNodeMap<Digraph::NodeMap<int>, Digraph::NodeMap<int> >
+ node_map(in_map, out_map);
+ for (Adaptor::NodeIt n(adaptor); n != INVALID; ++n) {
+ if (adaptor.inNode(n)) {
+ check(node_map[n] == in_map[n], "Wrong combined node map");
+ } else {
+ check(node_map[n] == out_map[n], "Wrong combined node map");
+ }
+ }
+
+ // Check combined arc map
+ typedef Adaptor::CombinedArcMap
+ <Digraph::ArcMap<int>, Digraph::NodeMap<int> > IntCombinedArcMap;
+ typedef Adaptor::CombinedArcMap
+ <Digraph::ArcMap<bool>, Digraph::NodeMap<bool> > BoolCombinedArcMap;
+ checkConcept<concepts::ReferenceMap<Adaptor::Arc, int, int&, const int&>,
+ IntCombinedArcMap>();
+//checkConcept<concepts::ReferenceMap<Adaptor::Arc, bool, bool&, const bool&>,
+// BoolCombinedArcMap>();
+ checkConcept<concepts::ReadWriteMap<Adaptor::Arc, bool>,
+ BoolCombinedArcMap>();
+
+ Digraph::ArcMap<int> a_map(digraph);
+ for (Digraph::ArcIt a(digraph); a != INVALID; ++a) {
+ a_map[a] = digraph.id(a);
+ }
+
+ Adaptor::CombinedArcMap<Digraph::ArcMap<int>, Digraph::NodeMap<int> >
+ arc_map(a_map, out_map);
+ for (Digraph::ArcIt a(digraph); a != INVALID; ++a) {
+ check(arc_map[adaptor.arc(a)] == a_map[a], "Wrong combined arc map");
+ }
+ for (Digraph::NodeIt n(digraph); n != INVALID; ++n) {
+ check(arc_map[adaptor.arc(n)] == out_map[n], "Wrong combined arc map");
+ }
+
+ // Check the conversion of nodes
+ Digraph::Node nd = adaptor.inNode(n1);
+ check (nd == n1, "Wrong node conversion");
+ nd = adaptor.outNode(n2);
+ check (nd == n2, "Wrong node conversion");
+}
+
+void checkSubGraph() {
+ // Check concepts
+ checkConcept<concepts::Graph, SubGraph<concepts::Graph> >();
+ checkConcept<concepts::Graph, SubGraph<ListGraph> >();
+ checkConcept<concepts::AlterableGraphComponent<>,
+ SubGraph<ListGraph> >();
+ checkConcept<concepts::ExtendableGraphComponent<>,
+ SubGraph<ListGraph> >();
+ checkConcept<concepts::ErasableGraphComponent<>,
+ SubGraph<ListGraph> >();
+ checkConcept<concepts::ClearableGraphComponent<>,
+ SubGraph<ListGraph> >();
+
+ // Create a graph and an adaptor
+ typedef ListGraph Graph;
+ typedef Graph::NodeMap<bool> NodeFilter;
+ typedef Graph::EdgeMap<bool> EdgeFilter;
+ typedef SubGraph<Graph, NodeFilter, EdgeFilter> Adaptor;
+
+ Graph graph;
+ NodeFilter node_filter(graph);
+ EdgeFilter edge_filter(graph);
+ Adaptor adaptor(graph, node_filter, edge_filter);
+
+ // Add nodes and edges to the original graph and the adaptor
+ Graph::Node n1 = graph.addNode();
+ Graph::Node n2 = graph.addNode();
+ Adaptor::Node n3 = adaptor.addNode();
+ Adaptor::Node n4 = adaptor.addNode();
+
+ node_filter[n1] = node_filter[n2] = node_filter[n3] = node_filter[n4] = true;
+
+ Graph::Edge e1 = graph.addEdge(n1, n2);
+ Graph::Edge e2 = graph.addEdge(n1, n3);
+ Adaptor::Edge e3 = adaptor.addEdge(n2, n3);
+ Adaptor::Edge e4 = adaptor.addEdge(n3, n4);
+
+ edge_filter[e1] = edge_filter[e2] = edge_filter[e3] = edge_filter[e4] = true;
+
+ checkGraphNodeList(adaptor, 4);
+ checkGraphArcList(adaptor, 8);
+ checkGraphEdgeList(adaptor, 4);
+ checkGraphConArcList(adaptor, 8);
+ checkGraphConEdgeList(adaptor, 4);
+
+ checkGraphIncEdgeArcLists(adaptor, n1, 2);
+ checkGraphIncEdgeArcLists(adaptor, n2, 2);
+ checkGraphIncEdgeArcLists(adaptor, n3, 3);
+ checkGraphIncEdgeArcLists(adaptor, n4, 1);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+ checkEdgeIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+ checkGraphEdgeMap(adaptor);
+
+ // Hide an edge
+ adaptor.status(e2, false);
+ adaptor.disable(e3);
+ if (!adaptor.status(e3)) adaptor.enable(e3);
+
+ checkGraphNodeList(adaptor, 4);
+ checkGraphArcList(adaptor, 6);
+ checkGraphEdgeList(adaptor, 3);
+ checkGraphConArcList(adaptor, 6);
+ checkGraphConEdgeList(adaptor, 3);
+
+ checkGraphIncEdgeArcLists(adaptor, n1, 1);
+ checkGraphIncEdgeArcLists(adaptor, n2, 2);
+ checkGraphIncEdgeArcLists(adaptor, n3, 2);
+ checkGraphIncEdgeArcLists(adaptor, n4, 1);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+ checkEdgeIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+ checkGraphEdgeMap(adaptor);
+
+ // Hide a node
+ adaptor.status(n1, false);
+ adaptor.disable(n3);
+ if (!adaptor.status(n3)) adaptor.enable(n3);
+
+ checkGraphNodeList(adaptor, 3);
+ checkGraphArcList(adaptor, 4);
+ checkGraphEdgeList(adaptor, 2);
+ checkGraphConArcList(adaptor, 4);
+ checkGraphConEdgeList(adaptor, 2);
+
+ checkGraphIncEdgeArcLists(adaptor, n2, 1);
+ checkGraphIncEdgeArcLists(adaptor, n3, 2);
+ checkGraphIncEdgeArcLists(adaptor, n4, 1);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+ checkEdgeIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+ checkGraphEdgeMap(adaptor);
+
+ // Hide all nodes and edges
+ node_filter[n1] = node_filter[n2] = node_filter[n3] = node_filter[n4] = false;
+ edge_filter[e1] = edge_filter[e2] = edge_filter[e3] = edge_filter[e4] = false;
+
+ checkGraphNodeList(adaptor, 0);
+ checkGraphArcList(adaptor, 0);
+ checkGraphEdgeList(adaptor, 0);
+ checkGraphConArcList(adaptor, 0);
+ checkGraphConEdgeList(adaptor, 0);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+ checkEdgeIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+ checkGraphEdgeMap(adaptor);
+
+ // Check the conversion of nodes and edges
+ Graph::Node ng = n3;
+ ng = n4;
+ Adaptor::Node na = n1;
+ na = n2;
+ Graph::Edge eg = e3;
+ eg = e4;
+ Adaptor::Edge ea = e1;
+ ea = e2;
+}
+
+void checkFilterNodes2() {
+ // Check concepts
+ checkConcept<concepts::Graph, FilterNodes<concepts::Graph> >();
+ checkConcept<concepts::Graph, FilterNodes<ListGraph> >();
+ checkConcept<concepts::AlterableGraphComponent<>,
+ FilterNodes<ListGraph> >();
+ checkConcept<concepts::ExtendableGraphComponent<>,
+ FilterNodes<ListGraph> >();
+ checkConcept<concepts::ErasableGraphComponent<>,
+ FilterNodes<ListGraph> >();
+ checkConcept<concepts::ClearableGraphComponent<>,
+ FilterNodes<ListGraph> >();
+
+ // Create a graph and an adaptor
+ typedef ListGraph Graph;
+ typedef Graph::NodeMap<bool> NodeFilter;
+ typedef FilterNodes<Graph, NodeFilter> Adaptor;
+
+ // Add nodes and edges to the original graph and the adaptor
+ Graph graph;
+ NodeFilter node_filter(graph);
+ Adaptor adaptor(graph, node_filter);
+
+ Graph::Node n1 = graph.addNode();
+ Graph::Node n2 = graph.addNode();
+ Adaptor::Node n3 = adaptor.addNode();
+ Adaptor::Node n4 = adaptor.addNode();
+
+ node_filter[n1] = node_filter[n2] = node_filter[n3] = node_filter[n4] = true;
+
+ Graph::Edge e1 = graph.addEdge(n1, n2);
+ Graph::Edge e2 = graph.addEdge(n1, n3);
+ Adaptor::Edge e3 = adaptor.addEdge(n2, n3);
+ Adaptor::Edge e4 = adaptor.addEdge(n3, n4);
+
+ checkGraphNodeList(adaptor, 4);
+ checkGraphArcList(adaptor, 8);
+ checkGraphEdgeList(adaptor, 4);
+ checkGraphConArcList(adaptor, 8);
+ checkGraphConEdgeList(adaptor, 4);
+
+ checkGraphIncEdgeArcLists(adaptor, n1, 2);
+ checkGraphIncEdgeArcLists(adaptor, n2, 2);
+ checkGraphIncEdgeArcLists(adaptor, n3, 3);
+ checkGraphIncEdgeArcLists(adaptor, n4, 1);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+ checkEdgeIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+ checkGraphEdgeMap(adaptor);
+
+ // Hide a node
+ adaptor.status(n1, false);
+ adaptor.disable(n3);
+ if (!adaptor.status(n3)) adaptor.enable(n3);
+
+ checkGraphNodeList(adaptor, 3);
+ checkGraphArcList(adaptor, 4);
+ checkGraphEdgeList(adaptor, 2);
+ checkGraphConArcList(adaptor, 4);
+ checkGraphConEdgeList(adaptor, 2);
+
+ checkGraphIncEdgeArcLists(adaptor, n2, 1);
+ checkGraphIncEdgeArcLists(adaptor, n3, 2);
+ checkGraphIncEdgeArcLists(adaptor, n4, 1);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+ checkEdgeIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+ checkGraphEdgeMap(adaptor);
+
+ // Hide all nodes
+ node_filter[n1] = node_filter[n2] = node_filter[n3] = node_filter[n4] = false;
+
+ checkGraphNodeList(adaptor, 0);
+ checkGraphArcList(adaptor, 0);
+ checkGraphEdgeList(adaptor, 0);
+ checkGraphConArcList(adaptor, 0);
+ checkGraphConEdgeList(adaptor, 0);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+ checkEdgeIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+ checkGraphEdgeMap(adaptor);
+
+ // Check the conversion of nodes and edges
+ Graph::Node ng = n3;
+ ng = n4;
+ Adaptor::Node na = n1;
+ na = n2;
+ Graph::Edge eg = e3;
+ eg = e4;
+ Adaptor::Edge ea = e1;
+ ea = e2;
+}
+
+void checkFilterEdges() {
+ // Check concepts
+ checkConcept<concepts::Graph, FilterEdges<concepts::Graph> >();
+ checkConcept<concepts::Graph, FilterEdges<ListGraph> >();
+ checkConcept<concepts::AlterableGraphComponent<>,
+ FilterEdges<ListGraph> >();
+ checkConcept<concepts::ExtendableGraphComponent<>,
+ FilterEdges<ListGraph> >();
+ checkConcept<concepts::ErasableGraphComponent<>,
+ FilterEdges<ListGraph> >();
+ checkConcept<concepts::ClearableGraphComponent<>,
+ FilterEdges<ListGraph> >();
+
+ // Create a graph and an adaptor
+ typedef ListGraph Graph;
+ typedef Graph::EdgeMap<bool> EdgeFilter;
+ typedef FilterEdges<Graph, EdgeFilter> Adaptor;
+
+ Graph graph;
+ EdgeFilter edge_filter(graph);
+ Adaptor adaptor(graph, edge_filter);
+
+ // Add nodes and edges to the original graph and the adaptor
+ Graph::Node n1 = graph.addNode();
+ Graph::Node n2 = graph.addNode();
+ Adaptor::Node n3 = adaptor.addNode();
+ Adaptor::Node n4 = adaptor.addNode();
+
+ Graph::Edge e1 = graph.addEdge(n1, n2);
+ Graph::Edge e2 = graph.addEdge(n1, n3);
+ Adaptor::Edge e3 = adaptor.addEdge(n2, n3);
+ Adaptor::Edge e4 = adaptor.addEdge(n3, n4);
+
+ edge_filter[e1] = edge_filter[e2] = edge_filter[e3] = edge_filter[e4] = true;
+
+ checkGraphNodeList(adaptor, 4);
+ checkGraphArcList(adaptor, 8);
+ checkGraphEdgeList(adaptor, 4);
+ checkGraphConArcList(adaptor, 8);
+ checkGraphConEdgeList(adaptor, 4);
+
+ checkGraphIncEdgeArcLists(adaptor, n1, 2);
+ checkGraphIncEdgeArcLists(adaptor, n2, 2);
+ checkGraphIncEdgeArcLists(adaptor, n3, 3);
+ checkGraphIncEdgeArcLists(adaptor, n4, 1);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+ checkEdgeIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+ checkGraphEdgeMap(adaptor);
+
+ // Hide an edge
+ adaptor.status(e2, false);
+ adaptor.disable(e3);
+ if (!adaptor.status(e3)) adaptor.enable(e3);
+
+ checkGraphNodeList(adaptor, 4);
+ checkGraphArcList(adaptor, 6);
+ checkGraphEdgeList(adaptor, 3);
+ checkGraphConArcList(adaptor, 6);
+ checkGraphConEdgeList(adaptor, 3);
+
+ checkGraphIncEdgeArcLists(adaptor, n1, 1);
+ checkGraphIncEdgeArcLists(adaptor, n2, 2);
+ checkGraphIncEdgeArcLists(adaptor, n3, 2);
+ checkGraphIncEdgeArcLists(adaptor, n4, 1);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+ checkEdgeIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+ checkGraphEdgeMap(adaptor);
+
+ // Hide all edges
+ edge_filter[e1] = edge_filter[e2] = edge_filter[e3] = edge_filter[e4] = false;
+
+ checkGraphNodeList(adaptor, 4);
+ checkGraphArcList(adaptor, 0);
+ checkGraphEdgeList(adaptor, 0);
+ checkGraphConArcList(adaptor, 0);
+ checkGraphConEdgeList(adaptor, 0);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+ checkEdgeIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+ checkGraphEdgeMap(adaptor);
+
+ // Check the conversion of nodes and edges
+ Graph::Node ng = n3;
+ ng = n4;
+ Adaptor::Node na = n1;
+ na = n2;
+ Graph::Edge eg = e3;
+ eg = e4;
+ Adaptor::Edge ea = e1;
+ ea = e2;
+}
+
+void checkOrienter() {
+ // Check concepts
+ checkConcept<concepts::Digraph, Orienter<concepts::Graph> >();
+ checkConcept<concepts::Digraph, Orienter<ListGraph> >();
+ checkConcept<concepts::AlterableDigraphComponent<>,
+ Orienter<ListGraph> >();
+ checkConcept<concepts::ExtendableDigraphComponent<>,
+ Orienter<ListGraph> >();
+ checkConcept<concepts::ErasableDigraphComponent<>,
+ Orienter<ListGraph> >();
+ checkConcept<concepts::ClearableDigraphComponent<>,
+ Orienter<ListGraph> >();
+
+ // Create a graph and an adaptor
+ typedef ListGraph Graph;
+ typedef ListGraph::EdgeMap<bool> DirMap;
+ typedef Orienter<Graph> Adaptor;
+
+ Graph graph;
+ DirMap dir(graph);
+ Adaptor adaptor(graph, dir);
+
+ // Add nodes and edges to the original graph and the adaptor
+ Graph::Node n1 = graph.addNode();
+ Graph::Node n2 = graph.addNode();
+ Adaptor::Node n3 = adaptor.addNode();
+
+ Graph::Edge e1 = graph.addEdge(n1, n2);
+ Graph::Edge e2 = graph.addEdge(n1, n3);
+ Adaptor::Arc e3 = adaptor.addArc(n2, n3);
+
+ dir[e1] = dir[e2] = dir[e3] = true;
+
+ // Check the original graph
+ checkGraphNodeList(graph, 3);
+ checkGraphArcList(graph, 6);
+ checkGraphConArcList(graph, 6);
+ checkGraphEdgeList(graph, 3);
+ checkGraphConEdgeList(graph, 3);
+
+ checkGraphIncEdgeArcLists(graph, n1, 2);
+ checkGraphIncEdgeArcLists(graph, n2, 2);
+ checkGraphIncEdgeArcLists(graph, n3, 2);
+
+ checkNodeIds(graph);
+ checkArcIds(graph);
+ checkEdgeIds(graph);
+
+ checkGraphNodeMap(graph);
+ checkGraphArcMap(graph);
+ checkGraphEdgeMap(graph);
+
+ // Check the adaptor
+ checkGraphNodeList(adaptor, 3);
+ checkGraphArcList(adaptor, 3);
+ checkGraphConArcList(adaptor, 3);
+
+ checkGraphOutArcList(adaptor, n1, 2);
+ checkGraphOutArcList(adaptor, n2, 1);
+ checkGraphOutArcList(adaptor, n3, 0);
+
+ checkGraphInArcList(adaptor, n1, 0);
+ checkGraphInArcList(adaptor, n2, 1);
+ checkGraphInArcList(adaptor, n3, 2);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+
+ // Check direction changing
+ {
+ dir[e1] = true;
+ Adaptor::Node u = adaptor.source(e1);
+ Adaptor::Node v = adaptor.target(e1);
+
+ dir[e1] = false;
+ check (u == adaptor.target(e1), "Wrong dir");
+ check (v == adaptor.source(e1), "Wrong dir");
+
+ check ((u == n1 && v == n2) || (u == n2 && v == n1), "Wrong dir");
+ dir[e1] = n1 == u;
+ }
+
+ {
+ dir[e2] = true;
+ Adaptor::Node u = adaptor.source(e2);
+ Adaptor::Node v = adaptor.target(e2);
+
+ dir[e2] = false;
+ check (u == adaptor.target(e2), "Wrong dir");
+ check (v == adaptor.source(e2), "Wrong dir");
+
+ check ((u == n1 && v == n3) || (u == n3 && v == n1), "Wrong dir");
+ dir[e2] = n3 == u;
+ }
+
+ {
+ dir[e3] = true;
+ Adaptor::Node u = adaptor.source(e3);
+ Adaptor::Node v = adaptor.target(e3);
+
+ dir[e3] = false;
+ check (u == adaptor.target(e3), "Wrong dir");
+ check (v == adaptor.source(e3), "Wrong dir");
+
+ check ((u == n2 && v == n3) || (u == n3 && v == n2), "Wrong dir");
+ dir[e3] = n2 == u;
+ }
+
+ // Check the adaptor again
+ checkGraphNodeList(adaptor, 3);
+ checkGraphArcList(adaptor, 3);
+ checkGraphConArcList(adaptor, 3);
+
+ checkGraphOutArcList(adaptor, n1, 1);
+ checkGraphOutArcList(adaptor, n2, 1);
+ checkGraphOutArcList(adaptor, n3, 1);
+
+ checkGraphInArcList(adaptor, n1, 1);
+ checkGraphInArcList(adaptor, n2, 1);
+ checkGraphInArcList(adaptor, n3, 1);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+
+ // Check reverseArc()
+ adaptor.reverseArc(e2);
+ adaptor.reverseArc(e3);
+ adaptor.reverseArc(e2);
+
+ checkGraphNodeList(adaptor, 3);
+ checkGraphArcList(adaptor, 3);
+ checkGraphConArcList(adaptor, 3);
+
+ checkGraphOutArcList(adaptor, n1, 1);
+ checkGraphOutArcList(adaptor, n2, 0);
+ checkGraphOutArcList(adaptor, n3, 2);
+
+ checkGraphInArcList(adaptor, n1, 1);
+ checkGraphInArcList(adaptor, n2, 2);
+ checkGraphInArcList(adaptor, n3, 0);
+
+ // Check the conversion of nodes and arcs/edges
+ Graph::Node ng = n3;
+ ng = n3;
+ Adaptor::Node na = n1;
+ na = n2;
+ Graph::Edge eg = e3;
+ eg = e3;
+ Adaptor::Arc aa = e1;
+ aa = e2;
+}
+
+void checkCombiningAdaptors() {
+ // Create a grid graph
+ GridGraph graph(2,2);
+ GridGraph::Node n1 = graph(0,0);
+ GridGraph::Node n2 = graph(0,1);
+ GridGraph::Node n3 = graph(1,0);
+ GridGraph::Node n4 = graph(1,1);
+
+ GridGraph::EdgeMap<bool> dir_map(graph);
+ dir_map[graph.right(n1)] = graph.u(graph.right(n1)) != n1;
+ dir_map[graph.up(n1)] = graph.u(graph.up(n1)) == n1;
+ dir_map[graph.left(n4)] = graph.u(graph.left(n4)) == n4;
+ dir_map[graph.down(n4)] = graph.u(graph.down(n4)) == n4;
+
+ // Apply several adaptors on the grid graph
+ typedef Orienter< const GridGraph, GridGraph::EdgeMap<bool> >
+ OrientedGridGraph;
+ typedef SplitNodes<OrientedGridGraph> SplitGridGraph;
+ typedef Undirector<const SplitGridGraph> USplitGridGraph;
+ checkConcept<concepts::Digraph, SplitGridGraph>();
+ checkConcept<concepts::Graph, USplitGridGraph>();
+
+ OrientedGridGraph oadaptor = orienter(graph, dir_map);
+ SplitGridGraph adaptor = splitNodes(oadaptor);
+ USplitGridGraph uadaptor = undirector(adaptor);
+
+ // Check adaptor
+ checkGraphNodeList(adaptor, 8);
+ checkGraphArcList(adaptor, 8);
+ checkGraphConArcList(adaptor, 8);
+
+ checkGraphOutArcList(adaptor, adaptor.inNode(n1), 1);
+ checkGraphOutArcList(adaptor, adaptor.outNode(n1), 1);
+ checkGraphOutArcList(adaptor, adaptor.inNode(n2), 1);
+ checkGraphOutArcList(adaptor, adaptor.outNode(n2), 0);
+ checkGraphOutArcList(adaptor, adaptor.inNode(n3), 1);
+ checkGraphOutArcList(adaptor, adaptor.outNode(n3), 1);
+ checkGraphOutArcList(adaptor, adaptor.inNode(n4), 1);
+ checkGraphOutArcList(adaptor, adaptor.outNode(n4), 2);
+
+ checkGraphInArcList(adaptor, adaptor.inNode(n1), 1);
+ checkGraphInArcList(adaptor, adaptor.outNode(n1), 1);
+ checkGraphInArcList(adaptor, adaptor.inNode(n2), 2);
+ checkGraphInArcList(adaptor, adaptor.outNode(n2), 1);
+ checkGraphInArcList(adaptor, adaptor.inNode(n3), 1);
+ checkGraphInArcList(adaptor, adaptor.outNode(n3), 1);
+ checkGraphInArcList(adaptor, adaptor.inNode(n4), 0);
+ checkGraphInArcList(adaptor, adaptor.outNode(n4), 1);
+
+ checkNodeIds(adaptor);
+ checkArcIds(adaptor);
+
+ checkGraphNodeMap(adaptor);
+ checkGraphArcMap(adaptor);
+
+ // Check uadaptor
+ checkGraphNodeList(uadaptor, 8);
+ checkGraphEdgeList(uadaptor, 8);
+ checkGraphArcList(uadaptor, 16);
+ checkGraphConEdgeList(uadaptor, 8);
+ checkGraphConArcList(uadaptor, 16);
+
+ checkNodeIds(uadaptor);
+ checkEdgeIds(uadaptor);
+ checkArcIds(uadaptor);
+
+ checkGraphNodeMap(uadaptor);
+ checkGraphEdgeMap(uadaptor);
+ checkGraphArcMap(uadaptor);
+
+ checkGraphIncEdgeArcLists(uadaptor, adaptor.inNode(n1), 2);
+ checkGraphIncEdgeArcLists(uadaptor, adaptor.outNode(n1), 2);
+ checkGraphIncEdgeArcLists(uadaptor, adaptor.inNode(n2), 3);
+ checkGraphIncEdgeArcLists(uadaptor, adaptor.outNode(n2), 1);
+ checkGraphIncEdgeArcLists(uadaptor, adaptor.inNode(n3), 2);
+ checkGraphIncEdgeArcLists(uadaptor, adaptor.outNode(n3), 2);
+ checkGraphIncEdgeArcLists(uadaptor, adaptor.inNode(n4), 1);
+ checkGraphIncEdgeArcLists(uadaptor, adaptor.outNode(n4), 3);
+}
+
+int main(int, const char **) {
+ // Check the digraph adaptors (using ListDigraph)
+ checkReverseDigraph();
+ checkSubDigraph();
+ checkFilterNodes1();
+ checkFilterArcs();
+ checkUndirector();
+ checkResidualDigraph();
+ checkSplitNodes();
+
+ // Check the graph adaptors (using ListGraph)
+ checkSubGraph();
+ checkFilterNodes2();
+ checkFilterEdges();
+ checkOrienter();
+
+ // Combine adaptors (using GridGraph)
+ checkCombiningAdaptors();
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/arc_look_up_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/arc_look_up_test.cc
new file mode 100644
index 00000000000..2f4edf52d66
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/arc_look_up_test.cc
@@ -0,0 +1,84 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+#include "lemon/list_graph.h"
+#include "lemon/lgf_reader.h"
+
+#include "test_tools.h"
+
+using namespace lemon;
+
+const std::string lgf =
+ "@nodes\n"
+"label\n"
+"0\n"
+"1\n"
+"2\n"
+"3\n"
+"4\n"
+"5\n"
+"6\n"
+"@arcs\n"
+"label\n"
+"5 6 0\n"
+"5 4 1\n"
+"4 6 2\n"
+"3 4 3\n"
+"3 4 4\n"
+"3 2 5\n"
+"3 5 6\n"
+"3 5 7\n"
+"3 5 8\n"
+"3 5 9\n"
+"2 4 10\n"
+"2 4 11\n"
+"2 4 12\n"
+"2 4 13\n"
+"1 2 14\n"
+"1 2 15\n"
+"1 0 16\n"
+"1 3 17\n"
+"1 3 18\n"
+"1 3 19\n"
+"1 3 20\n"
+"0 2 21\n"
+"0 2 22\n"
+"0 2 23\n"
+"0 2 24\n";
+
+
+int main() {
+ ListDigraph graph;
+ std::istringstream lgfs(lgf);
+ DigraphReader<ListDigraph>(graph, lgfs).run();
+
+ AllArcLookUp<ListDigraph> lookup(graph);
+
+ int numArcs = countArcs(graph);
+
+ int arcCnt = 0;
+ for(ListDigraph::NodeIt n1(graph); n1 != INVALID; ++n1)
+ for(ListDigraph::NodeIt n2(graph); n2 != INVALID; ++n2)
+ for(ListDigraph::Arc a = lookup(n1, n2); a != INVALID;
+ a = lookup(n1, n2, a))
+ ++arcCnt;
+ check(arcCnt==numArcs, "Wrong total number of arcs");
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/bellman_ford_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/bellman_ford_test.cc
new file mode 100644
index 00000000000..14faa07c961
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/bellman_ford_test.cc
@@ -0,0 +1,289 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/concepts/digraph.h>
+#include <lemon/smart_graph.h>
+#include <lemon/list_graph.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/bellman_ford.h>
+#include <lemon/path.h>
+
+#include "graph_test.h"
+#include "test_tools.h"
+
+using namespace lemon;
+
+char test_lgf[] =
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "@arcs\n"
+ " length\n"
+ "0 1 3\n"
+ "1 2 -3\n"
+ "1 2 -5\n"
+ "1 3 -2\n"
+ "0 2 -1\n"
+ "1 2 -4\n"
+ "0 3 2\n"
+ "4 2 -5\n"
+ "2 3 1\n"
+ "@attributes\n"
+ "source 0\n"
+ "target 3\n";
+
+
+void checkBellmanFordCompile()
+{
+ typedef int Value;
+ typedef concepts::Digraph Digraph;
+ typedef concepts::ReadMap<Digraph::Arc,Value> LengthMap;
+ typedef BellmanFord<Digraph, LengthMap> BF;
+ typedef Digraph::Node Node;
+ typedef Digraph::Arc Arc;
+
+ Digraph gr;
+ Node s, t, n;
+ Arc e;
+ Value l;
+ ::lemon::ignore_unused_variable_warning(l);
+ int k=3;
+ bool b;
+ ::lemon::ignore_unused_variable_warning(b);
+ BF::DistMap d(gr);
+ BF::PredMap p(gr);
+ LengthMap length;
+ concepts::Path<Digraph> pp;
+
+ {
+ BF bf_test(gr,length);
+ const BF& const_bf_test = bf_test;
+
+ bf_test.run(s);
+ bf_test.run(s,k);
+
+ bf_test.init();
+ bf_test.addSource(s);
+ bf_test.addSource(s, 1);
+ b = bf_test.processNextRound();
+ b = bf_test.processNextWeakRound();
+
+ bf_test.start();
+ bf_test.checkedStart();
+ bf_test.limitedStart(k);
+
+ l = const_bf_test.dist(t);
+ e = const_bf_test.predArc(t);
+ s = const_bf_test.predNode(t);
+ b = const_bf_test.reached(t);
+ d = const_bf_test.distMap();
+ p = const_bf_test.predMap();
+ pp = const_bf_test.path(t);
+ pp = const_bf_test.negativeCycle();
+
+ for (BF::ActiveIt it(const_bf_test); it != INVALID; ++it) {}
+ }
+ {
+ BF::SetPredMap<concepts::ReadWriteMap<Node,Arc> >
+ ::SetDistMap<concepts::ReadWriteMap<Node,Value> >
+ ::SetOperationTraits<BellmanFordDefaultOperationTraits<Value> >
+ ::Create bf_test(gr,length);
+
+ LengthMap length_map;
+ concepts::ReadWriteMap<Node,Arc> pred_map;
+ concepts::ReadWriteMap<Node,Value> dist_map;
+
+ bf_test
+ .lengthMap(length_map)
+ .predMap(pred_map)
+ .distMap(dist_map);
+
+ bf_test.run(s);
+ bf_test.run(s,k);
+
+ bf_test.init();
+ bf_test.addSource(s);
+ bf_test.addSource(s, 1);
+ b = bf_test.processNextRound();
+ b = bf_test.processNextWeakRound();
+
+ bf_test.start();
+ bf_test.checkedStart();
+ bf_test.limitedStart(k);
+
+ l = bf_test.dist(t);
+ e = bf_test.predArc(t);
+ s = bf_test.predNode(t);
+ b = bf_test.reached(t);
+ pp = bf_test.path(t);
+ pp = bf_test.negativeCycle();
+ }
+}
+
+void checkBellmanFordFunctionCompile()
+{
+ typedef int Value;
+ typedef concepts::Digraph Digraph;
+ typedef Digraph::Arc Arc;
+ typedef Digraph::Node Node;
+ typedef concepts::ReadMap<Digraph::Arc,Value> LengthMap;
+
+ Digraph g;
+ bool b;
+ ::lemon::ignore_unused_variable_warning(b);
+
+ bellmanFord(g,LengthMap()).run(Node());
+ b = bellmanFord(g,LengthMap()).run(Node(),Node());
+ bellmanFord(g,LengthMap())
+ .predMap(concepts::ReadWriteMap<Node,Arc>())
+ .distMap(concepts::ReadWriteMap<Node,Value>())
+ .run(Node());
+ b=bellmanFord(g,LengthMap())
+ .predMap(concepts::ReadWriteMap<Node,Arc>())
+ .distMap(concepts::ReadWriteMap<Node,Value>())
+ .path(concepts::Path<Digraph>())
+ .dist(Value())
+ .run(Node(),Node());
+}
+
+
+template <typename Digraph, typename Value>
+void checkBellmanFord() {
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+ typedef typename Digraph::template ArcMap<Value> LengthMap;
+
+ Digraph gr;
+ Node s, t;
+ LengthMap length(gr);
+
+ std::istringstream input(test_lgf);
+ digraphReader(gr, input).
+ arcMap("length", length).
+ node("source", s).
+ node("target", t).
+ run();
+
+ BellmanFord<Digraph, LengthMap>
+ bf(gr, length);
+ bf.run(s);
+ Path<Digraph> p = bf.path(t);
+
+ check(bf.reached(t) && bf.dist(t) == -1, "Bellman-Ford found a wrong path.");
+ check(p.length() == 3, "path() found a wrong path.");
+ check(checkPath(gr, p), "path() found a wrong path.");
+ check(pathSource(gr, p) == s, "path() found a wrong path.");
+ check(pathTarget(gr, p) == t, "path() found a wrong path.");
+
+ ListPath<Digraph> path;
+ Value dist = 0;
+ bool reached = bellmanFord(gr,length).path(path).dist(dist).run(s,t);
+
+ check(reached && dist == -1, "Bellman-Ford found a wrong path.");
+ check(path.length() == 3, "path() found a wrong path.");
+ check(checkPath(gr, path), "path() found a wrong path.");
+ check(pathSource(gr, path) == s, "path() found a wrong path.");
+ check(pathTarget(gr, path) == t, "path() found a wrong path.");
+
+ for(ArcIt e(gr); e!=INVALID; ++e) {
+ Node u=gr.source(e);
+ Node v=gr.target(e);
+ check(!bf.reached(u) || (bf.dist(v) - bf.dist(u) <= length[e]),
+ "Wrong output. dist(target)-dist(source)-arc_length=" <<
+ bf.dist(v) - bf.dist(u) - length[e]);
+ }
+
+ for(NodeIt v(gr); v!=INVALID; ++v) {
+ if (bf.reached(v)) {
+ check(v==s || bf.predArc(v)!=INVALID, "Wrong tree.");
+ if (bf.predArc(v)!=INVALID ) {
+ Arc e=bf.predArc(v);
+ Node u=gr.source(e);
+ check(u==bf.predNode(v),"Wrong tree.");
+ check(bf.dist(v) - bf.dist(u) == length[e],
+ "Wrong distance! Difference: " <<
+ bf.dist(v) - bf.dist(u) - length[e]);
+ }
+ }
+ }
+}
+
+void checkBellmanFordNegativeCycle() {
+ DIGRAPH_TYPEDEFS(SmartDigraph);
+
+ SmartDigraph gr;
+ IntArcMap length(gr);
+
+ Node n1 = gr.addNode();
+ Node n2 = gr.addNode();
+ Node n3 = gr.addNode();
+ Node n4 = gr.addNode();
+
+ Arc a1 = gr.addArc(n1, n2);
+ Arc a2 = gr.addArc(n2, n2);
+
+ length[a1] = 2;
+ length[a2] = -1;
+
+ {
+ BellmanFord<SmartDigraph, IntArcMap> bf(gr, length);
+ bf.run(n1);
+ StaticPath<SmartDigraph> p = bf.negativeCycle();
+ check(p.length() == 1 && p.front() == p.back() && p.front() == a2,
+ "Wrong negative cycle.");
+ }
+
+ length[a2] = 0;
+
+ {
+ BellmanFord<SmartDigraph, IntArcMap> bf(gr, length);
+ bf.run(n1);
+ check(bf.negativeCycle().empty(),
+ "Negative cycle should not be found.");
+ }
+
+ length[gr.addArc(n1, n3)] = 5;
+ length[gr.addArc(n4, n3)] = 1;
+ length[gr.addArc(n2, n4)] = 2;
+ length[gr.addArc(n3, n2)] = -4;
+
+ {
+ BellmanFord<SmartDigraph, IntArcMap> bf(gr, length);
+ bf.init();
+ bf.addSource(n1);
+ for (int i = 0; i < 4; ++i) {
+ check(bf.negativeCycle().empty(),
+ "Negative cycle should not be found.");
+ bf.processNextRound();
+ }
+ StaticPath<SmartDigraph> p = bf.negativeCycle();
+ check(p.length() == 3, "Wrong negative cycle.");
+ check(length[p.nth(0)] + length[p.nth(1)] + length[p.nth(2)] == -1,
+ "Wrong negative cycle.");
+ }
+}
+
+int main() {
+ checkBellmanFord<ListDigraph, int>();
+ checkBellmanFord<SmartDigraph, double>();
+ checkBellmanFordNegativeCycle();
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/bfs_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/bfs_test.cc
new file mode 100644
index 00000000000..976fa88b637
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/bfs_test.cc
@@ -0,0 +1,239 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/concepts/digraph.h>
+#include <lemon/smart_graph.h>
+#include <lemon/list_graph.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/bfs.h>
+#include <lemon/path.h>
+
+#include "graph_test.h"
+#include "test_tools.h"
+
+using namespace lemon;
+
+char test_lgf[] =
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "@arcs\n"
+ " label\n"
+ "0 1 0\n"
+ "1 2 1\n"
+ "2 3 2\n"
+ "3 4 3\n"
+ "0 3 4\n"
+ "0 3 5\n"
+ "5 2 6\n"
+ "@attributes\n"
+ "source 0\n"
+ "target 4\n";
+
+void checkBfsCompile()
+{
+ typedef concepts::Digraph Digraph;
+ typedef Bfs<Digraph> BType;
+ typedef Digraph::Node Node;
+ typedef Digraph::Arc Arc;
+
+ Digraph G;
+ Node s, t, n;
+ Arc e;
+ int l, i;
+ ::lemon::ignore_unused_variable_warning(l,i);
+ bool b;
+ BType::DistMap d(G);
+ BType::PredMap p(G);
+ Path<Digraph> pp;
+ concepts::ReadMap<Node,bool> nm;
+
+ {
+ BType bfs_test(G);
+ const BType& const_bfs_test = bfs_test;
+
+ bfs_test.run(s);
+ bfs_test.run(s,t);
+ bfs_test.run();
+
+ bfs_test.init();
+ bfs_test.addSource(s);
+ n = bfs_test.processNextNode();
+ n = bfs_test.processNextNode(t, b);
+ n = bfs_test.processNextNode(nm, n);
+ n = const_bfs_test.nextNode();
+ b = const_bfs_test.emptyQueue();
+ i = const_bfs_test.queueSize();
+
+ bfs_test.start();
+ bfs_test.start(t);
+ bfs_test.start(nm);
+
+ l = const_bfs_test.dist(t);
+ e = const_bfs_test.predArc(t);
+ s = const_bfs_test.predNode(t);
+ b = const_bfs_test.reached(t);
+ d = const_bfs_test.distMap();
+ p = const_bfs_test.predMap();
+ pp = const_bfs_test.path(t);
+ }
+ {
+ BType
+ ::SetPredMap<concepts::ReadWriteMap<Node,Arc> >
+ ::SetDistMap<concepts::ReadWriteMap<Node,int> >
+ ::SetReachedMap<concepts::ReadWriteMap<Node,bool> >
+ ::SetStandardProcessedMap
+ ::SetProcessedMap<concepts::WriteMap<Node,bool> >
+ ::Create bfs_test(G);
+
+ concepts::ReadWriteMap<Node,Arc> pred_map;
+ concepts::ReadWriteMap<Node,int> dist_map;
+ concepts::ReadWriteMap<Node,bool> reached_map;
+ concepts::WriteMap<Node,bool> processed_map;
+
+ bfs_test
+ .predMap(pred_map)
+ .distMap(dist_map)
+ .reachedMap(reached_map)
+ .processedMap(processed_map);
+
+ bfs_test.run(s);
+ bfs_test.run(s,t);
+ bfs_test.run();
+
+ bfs_test.init();
+ bfs_test.addSource(s);
+ n = bfs_test.processNextNode();
+ n = bfs_test.processNextNode(t, b);
+ n = bfs_test.processNextNode(nm, n);
+ n = bfs_test.nextNode();
+ b = bfs_test.emptyQueue();
+ i = bfs_test.queueSize();
+
+ bfs_test.start();
+ bfs_test.start(t);
+ bfs_test.start(nm);
+
+ l = bfs_test.dist(t);
+ e = bfs_test.predArc(t);
+ s = bfs_test.predNode(t);
+ b = bfs_test.reached(t);
+ pp = bfs_test.path(t);
+ }
+}
+
+void checkBfsFunctionCompile()
+{
+ typedef int VType;
+ typedef concepts::Digraph Digraph;
+ typedef Digraph::Arc Arc;
+ typedef Digraph::Node Node;
+
+ Digraph g;
+ bool b;
+ ::lemon::ignore_unused_variable_warning(b);
+
+ bfs(g).run(Node());
+ b=bfs(g).run(Node(),Node());
+ bfs(g).run();
+ bfs(g)
+ .predMap(concepts::ReadWriteMap<Node,Arc>())
+ .distMap(concepts::ReadWriteMap<Node,VType>())
+ .reachedMap(concepts::ReadWriteMap<Node,bool>())
+ .processedMap(concepts::WriteMap<Node,bool>())
+ .run(Node());
+ b=bfs(g)
+ .predMap(concepts::ReadWriteMap<Node,Arc>())
+ .distMap(concepts::ReadWriteMap<Node,VType>())
+ .reachedMap(concepts::ReadWriteMap<Node,bool>())
+ .processedMap(concepts::WriteMap<Node,bool>())
+ .path(concepts::Path<Digraph>())
+ .dist(VType())
+ .run(Node(),Node());
+ bfs(g)
+ .predMap(concepts::ReadWriteMap<Node,Arc>())
+ .distMap(concepts::ReadWriteMap<Node,VType>())
+ .reachedMap(concepts::ReadWriteMap<Node,bool>())
+ .processedMap(concepts::WriteMap<Node,bool>())
+ .run();
+}
+
+template <class Digraph>
+void checkBfs() {
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+
+ Digraph G;
+ Node s, t;
+
+ std::istringstream input(test_lgf);
+ digraphReader(G, input).
+ node("source", s).
+ node("target", t).
+ run();
+
+ Bfs<Digraph> bfs_test(G);
+ bfs_test.run(s);
+
+ check(bfs_test.dist(t)==2,"Bfs found a wrong path.");
+
+ Path<Digraph> p = bfs_test.path(t);
+ check(p.length()==2,"path() found a wrong path.");
+ check(checkPath(G, p),"path() found a wrong path.");
+ check(pathSource(G, p) == s,"path() found a wrong path.");
+ check(pathTarget(G, p) == t,"path() found a wrong path.");
+
+
+ for(ArcIt a(G); a!=INVALID; ++a) {
+ Node u=G.source(a);
+ Node v=G.target(a);
+ check( !bfs_test.reached(u) ||
+ (bfs_test.dist(v) <= bfs_test.dist(u)+1),
+ "Wrong output. " << G.id(u) << "->" << G.id(v));
+ }
+
+ for(NodeIt v(G); v!=INVALID; ++v) {
+ if (bfs_test.reached(v)) {
+ check(v==s || bfs_test.predArc(v)!=INVALID, "Wrong tree.");
+ if (bfs_test.predArc(v)!=INVALID ) {
+ Arc a=bfs_test.predArc(v);
+ Node u=G.source(a);
+ check(u==bfs_test.predNode(v),"Wrong tree.");
+ check(bfs_test.dist(v) - bfs_test.dist(u) == 1,
+ "Wrong distance. Difference: "
+ << std::abs(bfs_test.dist(v) - bfs_test.dist(u) - 1));
+ }
+ }
+ }
+
+ {
+ NullMap<Node,Arc> myPredMap;
+ bfs(G).predMap(myPredMap).run(s);
+ }
+}
+
+int main()
+{
+ checkBfs<ListDigraph>();
+ checkBfs<SmartDigraph>();
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/bpgraph_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/bpgraph_test.cc
new file mode 100644
index 00000000000..45fc5b855d4
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/bpgraph_test.cc
@@ -0,0 +1,456 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/concepts/bpgraph.h>
+#include <lemon/list_graph.h>
+#include <lemon/smart_graph.h>
+#include <lemon/full_graph.h>
+
+#include "test_tools.h"
+#include "graph_test.h"
+
+using namespace lemon;
+using namespace lemon::concepts;
+
+template <class BpGraph>
+void checkBpGraphBuild() {
+ TEMPLATE_BPGRAPH_TYPEDEFS(BpGraph);
+
+ BpGraph G;
+ checkGraphNodeList(G, 0);
+ checkGraphRedNodeList(G, 0);
+ checkGraphBlueNodeList(G, 0);
+ checkGraphEdgeList(G, 0);
+ checkGraphArcList(G, 0);
+
+ G.reserveNode(3);
+ G.reserveEdge(3);
+
+ RedNode
+ rn1 = G.addRedNode();
+ checkGraphNodeList(G, 1);
+ checkGraphRedNodeList(G, 1);
+ checkGraphBlueNodeList(G, 0);
+ checkGraphEdgeList(G, 0);
+ checkGraphArcList(G, 0);
+
+ BlueNode
+ bn1 = G.addBlueNode(),
+ bn2 = G.addBlueNode();
+ checkGraphNodeList(G, 3);
+ checkGraphRedNodeList(G, 1);
+ checkGraphBlueNodeList(G, 2);
+ checkGraphEdgeList(G, 0);
+ checkGraphArcList(G, 0);
+
+ Edge e1 = G.addEdge(rn1, bn2);
+ check(G.redNode(e1) == rn1 && G.blueNode(e1) == bn2, "Wrong edge");
+ check(G.u(e1) == rn1 && G.v(e1) == bn2, "Wrong edge");
+
+ checkGraphNodeList(G, 3);
+ checkGraphRedNodeList(G, 1);
+ checkGraphBlueNodeList(G, 2);
+ checkGraphEdgeList(G, 1);
+ checkGraphArcList(G, 2);
+
+ checkGraphIncEdgeArcLists(G, rn1, 1);
+ checkGraphIncEdgeArcLists(G, bn1, 0);
+ checkGraphIncEdgeArcLists(G, bn2, 1);
+
+ checkGraphConEdgeList(G, 1);
+ checkGraphConArcList(G, 2);
+
+ Edge
+ e2 = G.addEdge(bn1, rn1),
+ e3 = G.addEdge(rn1, bn2);
+ ::lemon::ignore_unused_variable_warning(e2,e3);
+
+ checkGraphNodeList(G, 3);
+ checkGraphRedNodeList(G, 1);
+ checkGraphBlueNodeList(G, 2);
+ checkGraphEdgeList(G, 3);
+ checkGraphArcList(G, 6);
+
+ checkGraphIncEdgeArcLists(G, rn1, 3);
+ checkGraphIncEdgeArcLists(G, bn1, 1);
+ checkGraphIncEdgeArcLists(G, bn2, 2);
+
+ checkGraphConEdgeList(G, 3);
+ checkGraphConArcList(G, 6);
+
+ checkArcDirections(G);
+
+ checkNodeIds(G);
+ checkRedNodeIds(G);
+ checkBlueNodeIds(G);
+ checkArcIds(G);
+ checkEdgeIds(G);
+
+ checkGraphNodeMap(G);
+ checkGraphRedNodeMap(G);
+ checkGraphBlueNodeMap(G);
+ checkGraphArcMap(G);
+ checkGraphEdgeMap(G);
+}
+
+template <class BpGraph>
+void checkBpGraphErase() {
+ TEMPLATE_BPGRAPH_TYPEDEFS(BpGraph);
+
+ BpGraph G;
+ RedNode
+ n1 = G.addRedNode(), n4 = G.addRedNode();
+ BlueNode
+ n2 = G.addBlueNode(), n3 = G.addBlueNode();
+ Edge
+ e1 = G.addEdge(n1, n2), e2 = G.addEdge(n1, n3),
+ e3 = G.addEdge(n4, n2), e4 = G.addEdge(n4, n3);
+ ::lemon::ignore_unused_variable_warning(e1,e3,e4);
+
+ // Check edge deletion
+ G.erase(e2);
+
+ checkGraphNodeList(G, 4);
+ checkGraphRedNodeList(G, 2);
+ checkGraphBlueNodeList(G, 2);
+ checkGraphEdgeList(G, 3);
+ checkGraphArcList(G, 6);
+
+ checkGraphIncEdgeArcLists(G, n1, 1);
+ checkGraphIncEdgeArcLists(G, n2, 2);
+ checkGraphIncEdgeArcLists(G, n3, 1);
+ checkGraphIncEdgeArcLists(G, n4, 2);
+
+ checkGraphConEdgeList(G, 3);
+ checkGraphConArcList(G, 6);
+
+ // Check node deletion
+ G.erase(n3);
+
+ checkGraphNodeList(G, 3);
+ checkGraphRedNodeList(G, 2);
+ checkGraphBlueNodeList(G, 1);
+ checkGraphEdgeList(G, 2);
+ checkGraphArcList(G, 4);
+
+ checkGraphIncEdgeArcLists(G, n1, 1);
+ checkGraphIncEdgeArcLists(G, n2, 2);
+ checkGraphIncEdgeArcLists(G, n4, 1);
+
+ checkGraphConEdgeList(G, 2);
+ checkGraphConArcList(G, 4);
+
+}
+
+template <class BpGraph>
+void checkBpGraphAlter() {
+ TEMPLATE_BPGRAPH_TYPEDEFS(BpGraph);
+
+ BpGraph G;
+ RedNode
+ n1 = G.addRedNode(), n4 = G.addRedNode();
+ BlueNode
+ n2 = G.addBlueNode(), n3 = G.addBlueNode();
+ Edge
+ e1 = G.addEdge(n1, n2), e2 = G.addEdge(n1, n3),
+ e3 = G.addEdge(n4, n2), e4 = G.addEdge(n4, n3);
+ ::lemon::ignore_unused_variable_warning(e1,e3,e4);
+
+ G.changeRed(e2, n4);
+ check(G.redNode(e2) == n4, "Wrong red node");
+ check(G.blueNode(e2) == n3, "Wrong blue node");
+
+ checkGraphNodeList(G, 4);
+ checkGraphRedNodeList(G, 2);
+ checkGraphBlueNodeList(G, 2);
+ checkGraphEdgeList(G, 4);
+ checkGraphArcList(G, 8);
+
+ checkGraphIncEdgeArcLists(G, n1, 1);
+ checkGraphIncEdgeArcLists(G, n2, 2);
+ checkGraphIncEdgeArcLists(G, n3, 2);
+ checkGraphIncEdgeArcLists(G, n4, 3);
+
+ checkGraphConEdgeList(G, 4);
+ checkGraphConArcList(G, 8);
+
+ G.changeBlue(e2, n2);
+ check(G.redNode(e2) == n4, "Wrong red node");
+ check(G.blueNode(e2) == n2, "Wrong blue node");
+
+ checkGraphNodeList(G, 4);
+ checkGraphRedNodeList(G, 2);
+ checkGraphBlueNodeList(G, 2);
+ checkGraphEdgeList(G, 4);
+ checkGraphArcList(G, 8);
+
+ checkGraphIncEdgeArcLists(G, n1, 1);
+ checkGraphIncEdgeArcLists(G, n2, 3);
+ checkGraphIncEdgeArcLists(G, n3, 1);
+ checkGraphIncEdgeArcLists(G, n4, 3);
+
+ checkGraphConEdgeList(G, 4);
+ checkGraphConArcList(G, 8);
+}
+
+
+template <class BpGraph>
+void checkBpGraphSnapshot() {
+ TEMPLATE_BPGRAPH_TYPEDEFS(BpGraph);
+
+ BpGraph G;
+ RedNode
+ n1 = G.addRedNode();
+ BlueNode
+ n2 = G.addBlueNode(),
+ n3 = G.addBlueNode();
+ Edge
+ e1 = G.addEdge(n1, n2),
+ e2 = G.addEdge(n1, n3);
+ ::lemon::ignore_unused_variable_warning(e1,e2);
+
+ checkGraphNodeList(G, 3);
+ checkGraphRedNodeList(G, 1);
+ checkGraphBlueNodeList(G, 2);
+ checkGraphEdgeList(G, 2);
+ checkGraphArcList(G, 4);
+
+ typename BpGraph::Snapshot snapshot(G);
+
+ RedNode n4 = G.addRedNode();
+ G.addEdge(n4, n2);
+ G.addEdge(n4, n3);
+
+ checkGraphNodeList(G, 4);
+ checkGraphRedNodeList(G, 2);
+ checkGraphBlueNodeList(G, 2);
+ checkGraphEdgeList(G, 4);
+ checkGraphArcList(G, 8);
+
+ snapshot.restore();
+
+ checkGraphNodeList(G, 3);
+ checkGraphRedNodeList(G, 1);
+ checkGraphBlueNodeList(G, 2);
+ checkGraphEdgeList(G, 2);
+ checkGraphArcList(G, 4);
+
+ checkGraphIncEdgeArcLists(G, n1, 2);
+ checkGraphIncEdgeArcLists(G, n2, 1);
+ checkGraphIncEdgeArcLists(G, n3, 1);
+
+ checkGraphConEdgeList(G, 2);
+ checkGraphConArcList(G, 4);
+
+ checkNodeIds(G);
+ checkRedNodeIds(G);
+ checkBlueNodeIds(G);
+ checkArcIds(G);
+ checkEdgeIds(G);
+
+ checkGraphNodeMap(G);
+ checkGraphRedNodeMap(G);
+ checkGraphBlueNodeMap(G);
+ checkGraphArcMap(G);
+ checkGraphEdgeMap(G);
+
+ G.addRedNode();
+ snapshot.save(G);
+
+ G.addEdge(G.addRedNode(), G.addBlueNode());
+
+ snapshot.restore();
+ snapshot.save(G);
+
+ checkGraphNodeList(G, 4);
+ checkGraphRedNodeList(G, 2);
+ checkGraphBlueNodeList(G, 2);
+ checkGraphEdgeList(G, 2);
+ checkGraphArcList(G, 4);
+
+ G.addEdge(G.addRedNode(), G.addBlueNode());
+
+ snapshot.restore();
+
+ checkGraphNodeList(G, 4);
+ checkGraphRedNodeList(G, 2);
+ checkGraphBlueNodeList(G, 2);
+ checkGraphEdgeList(G, 2);
+ checkGraphArcList(G, 4);
+}
+
+template <typename BpGraph>
+void checkBpGraphValidity() {
+ TEMPLATE_BPGRAPH_TYPEDEFS(BpGraph);
+ BpGraph g;
+
+ RedNode
+ n1 = g.addRedNode();
+ BlueNode
+ n2 = g.addBlueNode(),
+ n3 = g.addBlueNode();
+
+ Edge
+ e1 = g.addEdge(n1, n2),
+ e2 = g.addEdge(n1, n3);
+ ::lemon::ignore_unused_variable_warning(e2);
+
+ check(g.valid(n1), "Wrong validity check");
+ check(g.valid(e1), "Wrong validity check");
+ check(g.valid(g.direct(e1, true)), "Wrong validity check");
+
+ check(!g.valid(g.nodeFromId(-1)), "Wrong validity check");
+ check(!g.valid(g.edgeFromId(-1)), "Wrong validity check");
+ check(!g.valid(g.arcFromId(-1)), "Wrong validity check");
+}
+
+void checkConcepts() {
+ { // Checking graph components
+ checkConcept<BaseBpGraphComponent, BaseBpGraphComponent >();
+
+ checkConcept<IDableBpGraphComponent<>,
+ IDableBpGraphComponent<> >();
+
+ checkConcept<IterableBpGraphComponent<>,
+ IterableBpGraphComponent<> >();
+
+ checkConcept<AlterableBpGraphComponent<>,
+ AlterableBpGraphComponent<> >();
+
+ checkConcept<MappableBpGraphComponent<>,
+ MappableBpGraphComponent<> >();
+
+ checkConcept<ExtendableBpGraphComponent<>,
+ ExtendableBpGraphComponent<> >();
+
+ checkConcept<ErasableBpGraphComponent<>,
+ ErasableBpGraphComponent<> >();
+
+ checkConcept<ClearableBpGraphComponent<>,
+ ClearableBpGraphComponent<> >();
+
+ }
+ { // Checking skeleton graph
+ checkConcept<BpGraph, BpGraph>();
+ }
+ { // Checking SmartBpGraph
+ checkConcept<BpGraph, SmartBpGraph>();
+ checkConcept<AlterableBpGraphComponent<>, SmartBpGraph>();
+ checkConcept<ExtendableBpGraphComponent<>, SmartBpGraph>();
+ checkConcept<ClearableBpGraphComponent<>, SmartBpGraph>();
+ }
+}
+
+void checkFullBpGraph(int redNum, int blueNum) {
+ typedef FullBpGraph BpGraph;
+ BPGRAPH_TYPEDEFS(BpGraph);
+
+ BpGraph G(redNum, blueNum);
+ checkGraphNodeList(G, redNum + blueNum);
+ checkGraphRedNodeList(G, redNum);
+ checkGraphBlueNodeList(G, blueNum);
+ checkGraphEdgeList(G, redNum * blueNum);
+ checkGraphArcList(G, 2 * redNum * blueNum);
+
+ G.resize(redNum, blueNum);
+ checkGraphNodeList(G, redNum + blueNum);
+ checkGraphRedNodeList(G, redNum);
+ checkGraphBlueNodeList(G, blueNum);
+ checkGraphEdgeList(G, redNum * blueNum);
+ checkGraphArcList(G, 2 * redNum * blueNum);
+
+ for (RedNodeIt n(G); n != INVALID; ++n) {
+ checkGraphOutArcList(G, n, blueNum);
+ checkGraphInArcList(G, n, blueNum);
+ checkGraphIncEdgeList(G, n, blueNum);
+ }
+
+ for (BlueNodeIt n(G); n != INVALID; ++n) {
+ checkGraphOutArcList(G, n, redNum);
+ checkGraphInArcList(G, n, redNum);
+ checkGraphIncEdgeList(G, n, redNum);
+ }
+
+ checkGraphConArcList(G, 2 * redNum * blueNum);
+ checkGraphConEdgeList(G, redNum * blueNum);
+
+ checkArcDirections(G);
+
+ checkNodeIds(G);
+ checkRedNodeIds(G);
+ checkBlueNodeIds(G);
+ checkArcIds(G);
+ checkEdgeIds(G);
+
+ checkGraphNodeMap(G);
+ checkGraphRedNodeMap(G);
+ checkGraphBlueNodeMap(G);
+ checkGraphArcMap(G);
+ checkGraphEdgeMap(G);
+
+ for (int i = 0; i < G.redNum(); ++i) {
+ check(G.red(G.redNode(i)), "Wrong node");
+ check(G.index(G.redNode(i)) == i, "Wrong index");
+ }
+
+ for (int i = 0; i < G.blueNum(); ++i) {
+ check(G.blue(G.blueNode(i)), "Wrong node");
+ check(G.index(G.blueNode(i)) == i, "Wrong index");
+ }
+
+ for (NodeIt u(G); u != INVALID; ++u) {
+ for (NodeIt v(G); v != INVALID; ++v) {
+ Edge e = G.edge(u, v);
+ Arc a = G.arc(u, v);
+ if (G.red(u) == G.red(v)) {
+ check(e == INVALID, "Wrong edge lookup");
+ check(a == INVALID, "Wrong arc lookup");
+ } else {
+ check((G.u(e) == u && G.v(e) == v) ||
+ (G.u(e) == v && G.v(e) == u), "Wrong edge lookup");
+ check(G.source(a) == u && G.target(a) == v, "Wrong arc lookup");
+ }
+ }
+ }
+
+}
+
+void checkGraphs() {
+ { // Checking ListGraph
+ checkBpGraphBuild<ListBpGraph>();
+ checkBpGraphErase<ListBpGraph>();
+ checkBpGraphAlter<ListBpGraph>();
+ checkBpGraphSnapshot<ListBpGraph>();
+ checkBpGraphValidity<ListBpGraph>();
+ }
+ { // Checking SmartGraph
+ checkBpGraphBuild<SmartBpGraph>();
+ checkBpGraphSnapshot<SmartBpGraph>();
+ checkBpGraphValidity<SmartBpGraph>();
+ }
+ { // Checking FullBpGraph
+ checkFullBpGraph(6, 8);
+ checkFullBpGraph(7, 4);
+ }
+}
+
+int main() {
+ checkConcepts();
+ checkGraphs();
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/circulation_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/circulation_test.cc
new file mode 100644
index 00000000000..3b3a4a97216
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/circulation_test.cc
@@ -0,0 +1,169 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+
+#include "test_tools.h"
+#include <lemon/list_graph.h>
+#include <lemon/circulation.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/concepts/digraph.h>
+#include <lemon/concepts/maps.h>
+
+using namespace lemon;
+
+char test_lgf[] =
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "@arcs\n"
+ " lcap ucap\n"
+ "0 1 2 10\n"
+ "0 2 2 6\n"
+ "1 3 4 7\n"
+ "1 4 0 5\n"
+ "2 4 1 3\n"
+ "3 5 3 8\n"
+ "4 5 3 7\n"
+ "@attributes\n"
+ "source 0\n"
+ "sink 5\n";
+
+void checkCirculationCompile()
+{
+ typedef int VType;
+ typedef concepts::Digraph Digraph;
+
+ typedef Digraph::Node Node;
+ typedef Digraph::Arc Arc;
+ typedef concepts::ReadMap<Arc,VType> CapMap;
+ typedef concepts::ReadMap<Node,VType> SupplyMap;
+ typedef concepts::ReadWriteMap<Arc,VType> FlowMap;
+ typedef concepts::WriteMap<Node,bool> BarrierMap;
+
+ typedef Elevator<Digraph, Digraph::Node> Elev;
+ typedef LinkedElevator<Digraph, Digraph::Node> LinkedElev;
+
+ Digraph g;
+ Node n;
+ Arc a;
+ CapMap lcap, ucap;
+ SupplyMap supply;
+ FlowMap flow;
+ BarrierMap bar;
+ VType v;
+ bool b;
+ ::lemon::ignore_unused_variable_warning(v,b);
+
+ typedef Circulation<Digraph, CapMap, CapMap, SupplyMap>
+ ::SetFlowMap<FlowMap>
+ ::SetElevator<Elev>
+ ::SetStandardElevator<LinkedElev>
+ ::Create CirculationType;
+ CirculationType circ_test(g, lcap, ucap, supply);
+ const CirculationType& const_circ_test = circ_test;
+
+ circ_test
+ .lowerMap(lcap)
+ .upperMap(ucap)
+ .supplyMap(supply)
+ .flowMap(flow);
+
+ const CirculationType::Elevator& elev = const_circ_test.elevator();
+ circ_test.elevator(const_cast<CirculationType::Elevator&>(elev));
+ CirculationType::Tolerance tol = const_circ_test.tolerance();
+ circ_test.tolerance(tol);
+
+ circ_test.init();
+ circ_test.greedyInit();
+ circ_test.start();
+ circ_test.run();
+
+ v = const_circ_test.flow(a);
+ const FlowMap& fm = const_circ_test.flowMap();
+ b = const_circ_test.barrier(n);
+ const_circ_test.barrierMap(bar);
+
+ ::lemon::ignore_unused_variable_warning(fm);
+}
+
+template <class G, class LM, class UM, class DM>
+void checkCirculation(const G& g, const LM& lm, const UM& um,
+ const DM& dm, bool find)
+{
+ Circulation<G, LM, UM, DM> circ(g, lm, um, dm);
+ bool ret = circ.run();
+ if (find) {
+ check(ret, "A feasible solution should have been found.");
+ check(circ.checkFlow(), "The found flow is corrupt.");
+ check(!circ.checkBarrier(), "A barrier should not have been found.");
+ } else {
+ check(!ret, "A feasible solution should not have been found.");
+ check(circ.checkBarrier(), "The found barrier is corrupt.");
+ }
+}
+
+int main (int, char*[])
+{
+ typedef ListDigraph Digraph;
+ DIGRAPH_TYPEDEFS(Digraph);
+
+ Digraph g;
+ IntArcMap lo(g), up(g);
+ IntNodeMap delta(g, 0);
+ Node s, t;
+
+ std::istringstream input(test_lgf);
+ DigraphReader<Digraph>(g,input).
+ arcMap("lcap", lo).
+ arcMap("ucap", up).
+ node("source",s).
+ node("sink",t).
+ run();
+
+ delta[s] = 7; delta[t] = -7;
+ checkCirculation(g, lo, up, delta, true);
+
+ delta[s] = 13; delta[t] = -13;
+ checkCirculation(g, lo, up, delta, true);
+
+ delta[s] = 6; delta[t] = -6;
+ checkCirculation(g, lo, up, delta, false);
+
+ delta[s] = 14; delta[t] = -14;
+ checkCirculation(g, lo, up, delta, false);
+
+ delta[s] = 7; delta[t] = -13;
+ checkCirculation(g, lo, up, delta, true);
+
+ delta[s] = 5; delta[t] = -15;
+ checkCirculation(g, lo, up, delta, true);
+
+ delta[s] = 10; delta[t] = -11;
+ checkCirculation(g, lo, up, delta, true);
+
+ delta[s] = 11; delta[t] = -10;
+ checkCirculation(g, lo, up, delta, false);
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/connectivity_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/connectivity_test.cc
new file mode 100644
index 00000000000..4ab343ee0fd
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/connectivity_test.cc
@@ -0,0 +1,316 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/connectivity.h>
+#include <lemon/list_graph.h>
+#include <lemon/adaptors.h>
+
+#include "test_tools.h"
+
+using namespace lemon;
+
+
+int main()
+{
+ typedef ListDigraph Digraph;
+ typedef Undirector<Digraph> Graph;
+
+ {
+ Digraph d;
+ Digraph::NodeMap<int> order(d);
+ Graph g(d);
+
+ check(stronglyConnected(d), "The empty digraph is strongly connected");
+ check(countStronglyConnectedComponents(d) == 0,
+ "The empty digraph has 0 strongly connected component");
+ check(connected(g), "The empty graph is connected");
+ check(countConnectedComponents(g) == 0,
+ "The empty graph has 0 connected component");
+
+ check(biNodeConnected(g), "The empty graph is bi-node-connected");
+ check(countBiNodeConnectedComponents(g) == 0,
+ "The empty graph has 0 bi-node-connected component");
+ check(biEdgeConnected(g), "The empty graph is bi-edge-connected");
+ check(countBiEdgeConnectedComponents(g) == 0,
+ "The empty graph has 0 bi-edge-connected component");
+
+ check(dag(d), "The empty digraph is DAG.");
+ check(checkedTopologicalSort(d, order), "The empty digraph is DAG.");
+ check(loopFree(d), "The empty digraph is loop-free.");
+ check(parallelFree(d), "The empty digraph is parallel-free.");
+ check(simpleGraph(d), "The empty digraph is simple.");
+
+ check(acyclic(g), "The empty graph is acyclic.");
+ check(tree(g), "The empty graph is tree.");
+ check(bipartite(g), "The empty graph is bipartite.");
+ check(loopFree(g), "The empty graph is loop-free.");
+ check(parallelFree(g), "The empty graph is parallel-free.");
+ check(simpleGraph(g), "The empty graph is simple.");
+ }
+
+ {
+ Digraph d;
+ Digraph::NodeMap<int> order(d);
+ Graph g(d);
+ Digraph::Node n = d.addNode();
+ ::lemon::ignore_unused_variable_warning(n);
+
+ check(stronglyConnected(d), "This digraph is strongly connected");
+ check(countStronglyConnectedComponents(d) == 1,
+ "This digraph has 1 strongly connected component");
+ check(connected(g), "This graph is connected");
+ check(countConnectedComponents(g) == 1,
+ "This graph has 1 connected component");
+
+ check(biNodeConnected(g), "This graph is bi-node-connected");
+ check(countBiNodeConnectedComponents(g) == 0,
+ "This graph has 0 bi-node-connected component");
+ check(biEdgeConnected(g), "This graph is bi-edge-connected");
+ check(countBiEdgeConnectedComponents(g) == 1,
+ "This graph has 1 bi-edge-connected component");
+
+ check(dag(d), "This digraph is DAG.");
+ check(checkedTopologicalSort(d, order), "This digraph is DAG.");
+ check(loopFree(d), "This digraph is loop-free.");
+ check(parallelFree(d), "This digraph is parallel-free.");
+ check(simpleGraph(d), "This digraph is simple.");
+
+ check(acyclic(g), "This graph is acyclic.");
+ check(tree(g), "This graph is tree.");
+ check(bipartite(g), "This graph is bipartite.");
+ check(loopFree(g), "This graph is loop-free.");
+ check(parallelFree(g), "This graph is parallel-free.");
+ check(simpleGraph(g), "This graph is simple.");
+ }
+
+ {
+ ListGraph g;
+ ListGraph::NodeMap<bool> map(g);
+
+ ListGraph::Node n1 = g.addNode();
+ ListGraph::Node n2 = g.addNode();
+
+ ListGraph::Edge e1 = g.addEdge(n1, n2);
+ ::lemon::ignore_unused_variable_warning(e1);
+ check(biNodeConnected(g), "Graph is bi-node-connected");
+
+ ListGraph::Node n3 = g.addNode();
+ ::lemon::ignore_unused_variable_warning(n3);
+ check(!biNodeConnected(g), "Graph is not bi-node-connected");
+ }
+
+
+ {
+ Digraph d;
+ Digraph::NodeMap<int> order(d);
+ Graph g(d);
+
+ Digraph::Node n1 = d.addNode();
+ Digraph::Node n2 = d.addNode();
+ Digraph::Node n3 = d.addNode();
+ Digraph::Node n4 = d.addNode();
+ Digraph::Node n5 = d.addNode();
+ Digraph::Node n6 = d.addNode();
+
+ d.addArc(n1, n3);
+ d.addArc(n3, n2);
+ d.addArc(n2, n1);
+ d.addArc(n4, n2);
+ d.addArc(n4, n3);
+ d.addArc(n5, n6);
+ d.addArc(n6, n5);
+
+ check(!stronglyConnected(d), "This digraph is not strongly connected");
+ check(countStronglyConnectedComponents(d) == 3,
+ "This digraph has 3 strongly connected components");
+ check(!connected(g), "This graph is not connected");
+ check(countConnectedComponents(g) == 2,
+ "This graph has 2 connected components");
+
+ check(!dag(d), "This digraph is not DAG.");
+ check(!checkedTopologicalSort(d, order), "This digraph is not DAG.");
+ check(loopFree(d), "This digraph is loop-free.");
+ check(parallelFree(d), "This digraph is parallel-free.");
+ check(simpleGraph(d), "This digraph is simple.");
+
+ check(!acyclic(g), "This graph is not acyclic.");
+ check(!tree(g), "This graph is not tree.");
+ check(!bipartite(g), "This graph is not bipartite.");
+ check(loopFree(g), "This graph is loop-free.");
+ check(!parallelFree(g), "This graph is not parallel-free.");
+ check(!simpleGraph(g), "This graph is not simple.");
+
+ d.addArc(n3, n3);
+
+ check(!loopFree(d), "This digraph is not loop-free.");
+ check(!loopFree(g), "This graph is not loop-free.");
+ check(!simpleGraph(d), "This digraph is not simple.");
+
+ d.addArc(n3, n2);
+
+ check(!parallelFree(d), "This digraph is not parallel-free.");
+ }
+
+ {
+ Digraph d;
+ Digraph::ArcMap<bool> cutarcs(d, false);
+ Graph g(d);
+
+ Digraph::Node n1 = d.addNode();
+ Digraph::Node n2 = d.addNode();
+ Digraph::Node n3 = d.addNode();
+ Digraph::Node n4 = d.addNode();
+ Digraph::Node n5 = d.addNode();
+ Digraph::Node n6 = d.addNode();
+ Digraph::Node n7 = d.addNode();
+ Digraph::Node n8 = d.addNode();
+
+ d.addArc(n1, n2);
+ d.addArc(n5, n1);
+ d.addArc(n2, n8);
+ d.addArc(n8, n5);
+ d.addArc(n6, n4);
+ d.addArc(n4, n6);
+ d.addArc(n2, n5);
+ d.addArc(n1, n8);
+ d.addArc(n6, n7);
+ d.addArc(n7, n6);
+
+ check(!stronglyConnected(d), "This digraph is not strongly connected");
+ check(countStronglyConnectedComponents(d) == 3,
+ "This digraph has 3 strongly connected components");
+ Digraph::NodeMap<int> scomp1(d);
+ check(stronglyConnectedComponents(d, scomp1) == 3,
+ "This digraph has 3 strongly connected components");
+ check(scomp1[n1] != scomp1[n3] && scomp1[n1] != scomp1[n4] &&
+ scomp1[n3] != scomp1[n4], "Wrong stronglyConnectedComponents()");
+ check(scomp1[n1] == scomp1[n2] && scomp1[n1] == scomp1[n5] &&
+ scomp1[n1] == scomp1[n8], "Wrong stronglyConnectedComponents()");
+ check(scomp1[n4] == scomp1[n6] && scomp1[n4] == scomp1[n7],
+ "Wrong stronglyConnectedComponents()");
+ Digraph::ArcMap<bool> scut1(d, false);
+ check(stronglyConnectedCutArcs(d, scut1) == 0,
+ "This digraph has 0 strongly connected cut arc.");
+ for (Digraph::ArcIt a(d); a != INVALID; ++a) {
+ check(!scut1[a], "Wrong stronglyConnectedCutArcs()");
+ }
+
+ check(!connected(g), "This graph is not connected");
+ check(countConnectedComponents(g) == 3,
+ "This graph has 3 connected components");
+ Graph::NodeMap<int> comp(g);
+ check(connectedComponents(g, comp) == 3,
+ "This graph has 3 connected components");
+ check(comp[n1] != comp[n3] && comp[n1] != comp[n4] &&
+ comp[n3] != comp[n4], "Wrong connectedComponents()");
+ check(comp[n1] == comp[n2] && comp[n1] == comp[n5] &&
+ comp[n1] == comp[n8], "Wrong connectedComponents()");
+ check(comp[n4] == comp[n6] && comp[n4] == comp[n7],
+ "Wrong connectedComponents()");
+
+ cutarcs[d.addArc(n3, n1)] = true;
+ cutarcs[d.addArc(n3, n5)] = true;
+ cutarcs[d.addArc(n3, n8)] = true;
+ cutarcs[d.addArc(n8, n6)] = true;
+ cutarcs[d.addArc(n8, n7)] = true;
+
+ check(!stronglyConnected(d), "This digraph is not strongly connected");
+ check(countStronglyConnectedComponents(d) == 3,
+ "This digraph has 3 strongly connected components");
+ Digraph::NodeMap<int> scomp2(d);
+ check(stronglyConnectedComponents(d, scomp2) == 3,
+ "This digraph has 3 strongly connected components");
+ check(scomp2[n3] == 0, "Wrong stronglyConnectedComponents()");
+ check(scomp2[n1] == 1 && scomp2[n2] == 1 && scomp2[n5] == 1 &&
+ scomp2[n8] == 1, "Wrong stronglyConnectedComponents()");
+ check(scomp2[n4] == 2 && scomp2[n6] == 2 && scomp2[n7] == 2,
+ "Wrong stronglyConnectedComponents()");
+ Digraph::ArcMap<bool> scut2(d, false);
+ check(stronglyConnectedCutArcs(d, scut2) == 5,
+ "This digraph has 5 strongly connected cut arcs.");
+ for (Digraph::ArcIt a(d); a != INVALID; ++a) {
+ check(scut2[a] == cutarcs[a], "Wrong stronglyConnectedCutArcs()");
+ }
+ }
+
+ {
+ // DAG example for topological sort from the book New Algorithms
+ // (T. H. Cormen, C. E. Leiserson, R. L. Rivest, C. Stein)
+ Digraph d;
+ Digraph::NodeMap<int> order(d);
+
+ Digraph::Node belt = d.addNode();
+ Digraph::Node trousers = d.addNode();
+ Digraph::Node necktie = d.addNode();
+ Digraph::Node coat = d.addNode();
+ Digraph::Node socks = d.addNode();
+ Digraph::Node shirt = d.addNode();
+ Digraph::Node shoe = d.addNode();
+ Digraph::Node watch = d.addNode();
+ Digraph::Node pants = d.addNode();
+ ::lemon::ignore_unused_variable_warning(watch);
+
+ d.addArc(socks, shoe);
+ d.addArc(pants, shoe);
+ d.addArc(pants, trousers);
+ d.addArc(trousers, shoe);
+ d.addArc(trousers, belt);
+ d.addArc(belt, coat);
+ d.addArc(shirt, belt);
+ d.addArc(shirt, necktie);
+ d.addArc(necktie, coat);
+
+ check(dag(d), "This digraph is DAG.");
+ topologicalSort(d, order);
+ for (Digraph::ArcIt a(d); a != INVALID; ++a) {
+ check(order[d.source(a)] < order[d.target(a)],
+ "Wrong topologicalSort()");
+ }
+ }
+
+ {
+ ListGraph g;
+ ListGraph::NodeMap<bool> map(g);
+
+ ListGraph::Node n1 = g.addNode();
+ ListGraph::Node n2 = g.addNode();
+ ListGraph::Node n3 = g.addNode();
+ ListGraph::Node n4 = g.addNode();
+ ListGraph::Node n5 = g.addNode();
+ ListGraph::Node n6 = g.addNode();
+ ListGraph::Node n7 = g.addNode();
+
+ g.addEdge(n1, n3);
+ g.addEdge(n1, n4);
+ g.addEdge(n2, n5);
+ g.addEdge(n3, n6);
+ g.addEdge(n4, n6);
+ g.addEdge(n4, n7);
+ g.addEdge(n5, n7);
+
+ check(bipartite(g), "This graph is bipartite");
+ check(bipartitePartitions(g, map), "This graph is bipartite");
+
+ check(map[n1] == map[n2] && map[n1] == map[n6] && map[n1] == map[n7],
+ "Wrong bipartitePartitions()");
+ check(map[n3] == map[n4] && map[n3] == map[n5],
+ "Wrong bipartitePartitions()");
+ }
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/counter_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/counter_test.cc
new file mode 100644
index 00000000000..df31dd4d39e
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/counter_test.cc
@@ -0,0 +1,118 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/counter.h>
+#include <vector>
+#include <sstream>
+
+#include "test/test_tools.h"
+
+using namespace lemon;
+
+template <typename T>
+void bubbleSort(std::vector<T>& v) {
+ std::stringstream s1, s2, s3;
+ {
+ Counter op("Bubble Sort - Operations: ", s1);
+ Counter::SubCounter as(op, "Assignments: ", s2);
+ Counter::SubCounter co(op, "Comparisons: ", s3);
+ for (int i = v.size()-1; i > 0; --i) {
+ for (int j = 0; j < i; ++j) {
+ if (v[j] > v[j+1]) {
+ T tmp = v[j];
+ v[j] = v[j+1];
+ v[j+1] = tmp;
+ as += 3;
+ }
+ ++co;
+ }
+ }
+ }
+ check(s1.str() == "Bubble Sort - Operations: 102\n", "Wrong counter");
+ check(s2.str() == "Assignments: 57\n", "Wrong subcounter");
+ check(s3.str() == "Comparisons: 45\n", "Wrong subcounter");
+}
+
+template <typename T>
+void insertionSort(std::vector<T>& v) {
+ std::stringstream s1, s2, s3;
+ {
+ Counter op("Insertion Sort - Operations: ", s1);
+ Counter::SubCounter as(op, "Assignments: ", s2);
+ Counter::SubCounter co(op, "Comparisons: ", s3);
+ for (int i = 1; i < int(v.size()); ++i) {
+ T value = v[i];
+ ++as;
+ int j = i;
+ while (j > 0 && v[j-1] > value) {
+ v[j] = v[j-1];
+ --j;
+ ++co; ++as;
+ }
+ v[j] = value;
+ ++as;
+ }
+ }
+ check(s1.str() == "Insertion Sort - Operations: 56\n", "Wrong counter");
+ check(s2.str() == "Assignments: 37\n", "Wrong subcounter");
+ check(s3.str() == "Comparisons: 19\n", "Wrong subcounter");
+}
+
+template <typename MyCounter>
+void counterTest(bool output) {
+ std::stringstream s1, s2, s3;
+ {
+ MyCounter c("Main Counter: ", s1);
+ c++;
+ typename MyCounter::SubCounter d(c, "SubCounter: ", s2);
+ d++;
+ typename MyCounter::SubCounter::NoSubCounter e(d, "SubSubCounter: ", s3);
+ e++;
+ d+=3;
+ c-=4;
+ e-=2;
+ c.reset(2);
+ c.reset();
+ }
+ if (output) {
+ check(s1.str() == "Main Counter: 3\n", "Wrong Counter");
+ check(s2.str() == "SubCounter: 3\n", "Wrong SubCounter");
+ check(s3.str() == "", "Wrong NoSubCounter");
+ } else {
+ check(s1.str() == "", "Wrong NoCounter");
+ check(s2.str() == "", "Wrong SubCounter");
+ check(s3.str() == "", "Wrong NoSubCounter");
+ }
+}
+
+void init(std::vector<int>& v) {
+ v[0] = 10; v[1] = 60; v[2] = 20; v[3] = 90; v[4] = 100;
+ v[5] = 80; v[6] = 40; v[7] = 30; v[8] = 50; v[9] = 70;
+}
+
+int main()
+{
+ counterTest<Counter>(true);
+ counterTest<NoCounter>(false);
+
+ std::vector<int> x(10);
+ init(x); bubbleSort(x);
+ init(x); insertionSort(x);
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/dfs_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/dfs_test.cc
new file mode 100644
index 00000000000..ef5049a000a
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/dfs_test.cc
@@ -0,0 +1,238 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/concepts/digraph.h>
+#include <lemon/smart_graph.h>
+#include <lemon/list_graph.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/dfs.h>
+#include <lemon/path.h>
+
+#include "graph_test.h"
+#include "test_tools.h"
+
+using namespace lemon;
+
+char test_lgf[] =
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "6\n"
+ "@arcs\n"
+ " label\n"
+ "0 1 0\n"
+ "1 2 1\n"
+ "2 3 2\n"
+ "1 4 3\n"
+ "4 2 4\n"
+ "4 5 5\n"
+ "5 0 6\n"
+ "6 3 7\n"
+ "@attributes\n"
+ "source 0\n"
+ "target 5\n"
+ "source1 6\n"
+ "target1 3\n";
+
+
+void checkDfsCompile()
+{
+ typedef concepts::Digraph Digraph;
+ typedef Dfs<Digraph> DType;
+ typedef Digraph::Node Node;
+ typedef Digraph::Arc Arc;
+
+ Digraph G;
+ Node s, t;
+ Arc e;
+ int l, i;
+ bool b;
+ ::lemon::ignore_unused_variable_warning(l,i,b);
+
+ DType::DistMap d(G);
+ DType::PredMap p(G);
+ Path<Digraph> pp;
+ concepts::ReadMap<Arc,bool> am;
+
+ {
+ DType dfs_test(G);
+ const DType& const_dfs_test = dfs_test;
+
+ dfs_test.run(s);
+ dfs_test.run(s,t);
+ dfs_test.run();
+
+ dfs_test.init();
+ dfs_test.addSource(s);
+ e = dfs_test.processNextArc();
+ e = const_dfs_test.nextArc();
+ b = const_dfs_test.emptyQueue();
+ i = const_dfs_test.queueSize();
+
+ dfs_test.start();
+ dfs_test.start(t);
+ dfs_test.start(am);
+
+ l = const_dfs_test.dist(t);
+ e = const_dfs_test.predArc(t);
+ s = const_dfs_test.predNode(t);
+ b = const_dfs_test.reached(t);
+ d = const_dfs_test.distMap();
+ p = const_dfs_test.predMap();
+ pp = const_dfs_test.path(t);
+ }
+ {
+ DType
+ ::SetPredMap<concepts::ReadWriteMap<Node,Arc> >
+ ::SetDistMap<concepts::ReadWriteMap<Node,int> >
+ ::SetReachedMap<concepts::ReadWriteMap<Node,bool> >
+ ::SetStandardProcessedMap
+ ::SetProcessedMap<concepts::WriteMap<Node,bool> >
+ ::Create dfs_test(G);
+
+ concepts::ReadWriteMap<Node,Arc> pred_map;
+ concepts::ReadWriteMap<Node,int> dist_map;
+ concepts::ReadWriteMap<Node,bool> reached_map;
+ concepts::WriteMap<Node,bool> processed_map;
+
+ dfs_test
+ .predMap(pred_map)
+ .distMap(dist_map)
+ .reachedMap(reached_map)
+ .processedMap(processed_map);
+
+ dfs_test.run(s);
+ dfs_test.run(s,t);
+ dfs_test.run();
+ dfs_test.init();
+
+ dfs_test.addSource(s);
+ e = dfs_test.processNextArc();
+ e = dfs_test.nextArc();
+ b = dfs_test.emptyQueue();
+ i = dfs_test.queueSize();
+
+ dfs_test.start();
+ dfs_test.start(t);
+ dfs_test.start(am);
+
+ l = dfs_test.dist(t);
+ e = dfs_test.predArc(t);
+ s = dfs_test.predNode(t);
+ b = dfs_test.reached(t);
+ pp = dfs_test.path(t);
+ }
+}
+
+void checkDfsFunctionCompile()
+{
+ typedef int VType;
+ typedef concepts::Digraph Digraph;
+ typedef Digraph::Arc Arc;
+ typedef Digraph::Node Node;
+
+ Digraph g;
+ bool b;
+ ::lemon::ignore_unused_variable_warning(b);
+
+ dfs(g).run(Node());
+ b=dfs(g).run(Node(),Node());
+ dfs(g).run();
+ dfs(g)
+ .predMap(concepts::ReadWriteMap<Node,Arc>())
+ .distMap(concepts::ReadWriteMap<Node,VType>())
+ .reachedMap(concepts::ReadWriteMap<Node,bool>())
+ .processedMap(concepts::WriteMap<Node,bool>())
+ .run(Node());
+ b=dfs(g)
+ .predMap(concepts::ReadWriteMap<Node,Arc>())
+ .distMap(concepts::ReadWriteMap<Node,VType>())
+ .reachedMap(concepts::ReadWriteMap<Node,bool>())
+ .processedMap(concepts::WriteMap<Node,bool>())
+ .path(concepts::Path<Digraph>())
+ .dist(VType())
+ .run(Node(),Node());
+ dfs(g)
+ .predMap(concepts::ReadWriteMap<Node,Arc>())
+ .distMap(concepts::ReadWriteMap<Node,VType>())
+ .reachedMap(concepts::ReadWriteMap<Node,bool>())
+ .processedMap(concepts::WriteMap<Node,bool>())
+ .run();
+}
+
+template <class Digraph>
+void checkDfs() {
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+
+ Digraph G;
+ Node s, t;
+ Node s1, t1;
+
+ std::istringstream input(test_lgf);
+ digraphReader(G, input).
+ node("source", s).
+ node("target", t).
+ node("source1", s1).
+ node("target1", t1).
+ run();
+
+ Dfs<Digraph> dfs_test(G);
+ dfs_test.run(s);
+
+ Path<Digraph> p = dfs_test.path(t);
+ check(p.length() == dfs_test.dist(t),"path() found a wrong path.");
+ check(checkPath(G, p),"path() found a wrong path.");
+ check(pathSource(G, p) == s,"path() found a wrong path.");
+ check(pathTarget(G, p) == t,"path() found a wrong path.");
+
+ for(NodeIt v(G); v!=INVALID; ++v) {
+ if (dfs_test.reached(v)) {
+ check(v==s || dfs_test.predArc(v)!=INVALID, "Wrong tree.");
+ if (dfs_test.predArc(v)!=INVALID ) {
+ Arc e=dfs_test.predArc(v);
+ Node u=G.source(e);
+ check(u==dfs_test.predNode(v),"Wrong tree.");
+ check(dfs_test.dist(v) - dfs_test.dist(u) == 1,
+ "Wrong distance. (" << dfs_test.dist(u) << "->"
+ << dfs_test.dist(v) << ")");
+ }
+ }
+ }
+
+ {
+ Dfs<Digraph> dfs(G);
+ check(dfs.run(s1,t1) && dfs.reached(t1),"Node 3 is reachable from Node 6.");
+ }
+
+ {
+ NullMap<Node,Arc> myPredMap;
+ dfs(G).predMap(myPredMap).run(s);
+ }
+}
+
+int main()
+{
+ checkDfs<ListDigraph>();
+ checkDfs<SmartDigraph>();
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/digraph_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/digraph_test.cc
new file mode 100644
index 00000000000..e3ff54577ea
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/digraph_test.cc
@@ -0,0 +1,569 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/concepts/digraph.h>
+#include <lemon/list_graph.h>
+#include <lemon/smart_graph.h>
+#include <lemon/static_graph.h>
+#include <lemon/full_graph.h>
+
+#include "test_tools.h"
+#include "graph_test.h"
+
+using namespace lemon;
+using namespace lemon::concepts;
+
+template <class Digraph>
+void checkDigraphBuild() {
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+ Digraph G;
+
+ checkGraphNodeList(G, 0);
+ checkGraphArcList(G, 0);
+
+ G.reserveNode(3);
+ G.reserveArc(4);
+
+ Node
+ n1 = G.addNode(),
+ n2 = G.addNode(),
+ n3 = G.addNode();
+ checkGraphNodeList(G, 3);
+ checkGraphArcList(G, 0);
+
+ Arc a1 = G.addArc(n1, n2);
+ check(G.source(a1) == n1 && G.target(a1) == n2, "Wrong arc");
+ checkGraphNodeList(G, 3);
+ checkGraphArcList(G, 1);
+
+ checkGraphOutArcList(G, n1, 1);
+ checkGraphOutArcList(G, n2, 0);
+ checkGraphOutArcList(G, n3, 0);
+
+ checkGraphInArcList(G, n1, 0);
+ checkGraphInArcList(G, n2, 1);
+ checkGraphInArcList(G, n3, 0);
+
+ checkGraphConArcList(G, 1);
+
+ Arc a2 = G.addArc(n2, n1),
+ a3 = G.addArc(n2, n3),
+ a4 = G.addArc(n2, n3);
+ ::lemon::ignore_unused_variable_warning(a2,a3,a4);
+
+ checkGraphNodeList(G, 3);
+ checkGraphArcList(G, 4);
+
+ checkGraphOutArcList(G, n1, 1);
+ checkGraphOutArcList(G, n2, 3);
+ checkGraphOutArcList(G, n3, 0);
+
+ checkGraphInArcList(G, n1, 1);
+ checkGraphInArcList(G, n2, 1);
+ checkGraphInArcList(G, n3, 2);
+
+ checkGraphConArcList(G, 4);
+
+ checkNodeIds(G);
+ checkArcIds(G);
+ checkGraphNodeMap(G);
+ checkGraphArcMap(G);
+}
+
+template <class Digraph>
+void checkDigraphSplit() {
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+
+ Digraph G;
+ Node n1 = G.addNode(), n2 = G.addNode(), n3 = G.addNode();
+ Arc a1 = G.addArc(n1, n2), a2 = G.addArc(n2, n1),
+ a3 = G.addArc(n2, n3), a4 = G.addArc(n2, n3);
+ ::lemon::ignore_unused_variable_warning(a1,a2,a3,a4);
+
+ Node n4 = G.split(n2);
+
+ check(G.target(OutArcIt(G, n2)) == n4 &&
+ G.source(InArcIt(G, n4)) == n2,
+ "Wrong split.");
+
+ checkGraphNodeList(G, 4);
+ checkGraphArcList(G, 5);
+
+ checkGraphOutArcList(G, n1, 1);
+ checkGraphOutArcList(G, n2, 1);
+ checkGraphOutArcList(G, n3, 0);
+ checkGraphOutArcList(G, n4, 3);
+
+ checkGraphInArcList(G, n1, 1);
+ checkGraphInArcList(G, n2, 1);
+ checkGraphInArcList(G, n3, 2);
+ checkGraphInArcList(G, n4, 1);
+
+ checkGraphConArcList(G, 5);
+}
+
+template <class Digraph>
+void checkDigraphAlter() {
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+
+ Digraph G;
+ Node n1 = G.addNode(), n2 = G.addNode(),
+ n3 = G.addNode(), n4 = G.addNode();
+ Arc a1 = G.addArc(n1, n2), a2 = G.addArc(n4, n1),
+ a3 = G.addArc(n4, n3), a4 = G.addArc(n4, n3),
+ a5 = G.addArc(n2, n4);
+ ::lemon::ignore_unused_variable_warning(a1,a2,a3,a5);
+
+ checkGraphNodeList(G, 4);
+ checkGraphArcList(G, 5);
+
+ // Check changeSource() and changeTarget()
+ G.changeTarget(a4, n1);
+
+ checkGraphNodeList(G, 4);
+ checkGraphArcList(G, 5);
+
+ checkGraphOutArcList(G, n1, 1);
+ checkGraphOutArcList(G, n2, 1);
+ checkGraphOutArcList(G, n3, 0);
+ checkGraphOutArcList(G, n4, 3);
+
+ checkGraphInArcList(G, n1, 2);
+ checkGraphInArcList(G, n2, 1);
+ checkGraphInArcList(G, n3, 1);
+ checkGraphInArcList(G, n4, 1);
+
+ checkGraphConArcList(G, 5);
+
+ G.changeSource(a4, n3);
+
+ checkGraphNodeList(G, 4);
+ checkGraphArcList(G, 5);
+
+ checkGraphOutArcList(G, n1, 1);
+ checkGraphOutArcList(G, n2, 1);
+ checkGraphOutArcList(G, n3, 1);
+ checkGraphOutArcList(G, n4, 2);
+
+ checkGraphInArcList(G, n1, 2);
+ checkGraphInArcList(G, n2, 1);
+ checkGraphInArcList(G, n3, 1);
+ checkGraphInArcList(G, n4, 1);
+
+ checkGraphConArcList(G, 5);
+
+ // Check contract()
+ G.contract(n2, n4, false);
+
+ checkGraphNodeList(G, 3);
+ checkGraphArcList(G, 5);
+
+ checkGraphOutArcList(G, n1, 1);
+ checkGraphOutArcList(G, n2, 3);
+ checkGraphOutArcList(G, n3, 1);
+
+ checkGraphInArcList(G, n1, 2);
+ checkGraphInArcList(G, n2, 2);
+ checkGraphInArcList(G, n3, 1);
+
+ checkGraphConArcList(G, 5);
+
+ G.contract(n2, n1);
+
+ checkGraphNodeList(G, 2);
+ checkGraphArcList(G, 3);
+
+ checkGraphOutArcList(G, n2, 2);
+ checkGraphOutArcList(G, n3, 1);
+
+ checkGraphInArcList(G, n2, 2);
+ checkGraphInArcList(G, n3, 1);
+
+ checkGraphConArcList(G, 3);
+}
+
+template <class Digraph>
+void checkDigraphErase() {
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+
+ Digraph G;
+ Node n1 = G.addNode(), n2 = G.addNode(),
+ n3 = G.addNode(), n4 = G.addNode();
+ Arc a1 = G.addArc(n1, n2), a2 = G.addArc(n4, n1),
+ a3 = G.addArc(n4, n3), a4 = G.addArc(n3, n1),
+ a5 = G.addArc(n2, n4);
+ ::lemon::ignore_unused_variable_warning(a2,a3,a4,a5);
+
+ // Check arc deletion
+ G.erase(a1);
+
+ checkGraphNodeList(G, 4);
+ checkGraphArcList(G, 4);
+
+ checkGraphOutArcList(G, n1, 0);
+ checkGraphOutArcList(G, n2, 1);
+ checkGraphOutArcList(G, n3, 1);
+ checkGraphOutArcList(G, n4, 2);
+
+ checkGraphInArcList(G, n1, 2);
+ checkGraphInArcList(G, n2, 0);
+ checkGraphInArcList(G, n3, 1);
+ checkGraphInArcList(G, n4, 1);
+
+ checkGraphConArcList(G, 4);
+
+ // Check node deletion
+ G.erase(n4);
+
+ checkGraphNodeList(G, 3);
+ checkGraphArcList(G, 1);
+
+ checkGraphOutArcList(G, n1, 0);
+ checkGraphOutArcList(G, n2, 0);
+ checkGraphOutArcList(G, n3, 1);
+ checkGraphOutArcList(G, n4, 0);
+
+ checkGraphInArcList(G, n1, 1);
+ checkGraphInArcList(G, n2, 0);
+ checkGraphInArcList(G, n3, 0);
+ checkGraphInArcList(G, n4, 0);
+
+ checkGraphConArcList(G, 1);
+}
+
+
+template <class Digraph>
+void checkDigraphSnapshot() {
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+
+ Digraph G;
+ Node n1 = G.addNode(), n2 = G.addNode(), n3 = G.addNode();
+ Arc a1 = G.addArc(n1, n2), a2 = G.addArc(n2, n1),
+ a3 = G.addArc(n2, n3), a4 = G.addArc(n2, n3);
+ ::lemon::ignore_unused_variable_warning(a1,a2,a3,a4);
+
+ typename Digraph::Snapshot snapshot(G);
+
+ Node n = G.addNode();
+ G.addArc(n3, n);
+ G.addArc(n, n3);
+
+ checkGraphNodeList(G, 4);
+ checkGraphArcList(G, 6);
+
+ snapshot.restore();
+
+ checkGraphNodeList(G, 3);
+ checkGraphArcList(G, 4);
+
+ checkGraphOutArcList(G, n1, 1);
+ checkGraphOutArcList(G, n2, 3);
+ checkGraphOutArcList(G, n3, 0);
+
+ checkGraphInArcList(G, n1, 1);
+ checkGraphInArcList(G, n2, 1);
+ checkGraphInArcList(G, n3, 2);
+
+ checkGraphConArcList(G, 4);
+
+ checkNodeIds(G);
+ checkArcIds(G);
+ checkGraphNodeMap(G);
+ checkGraphArcMap(G);
+
+ G.addNode();
+ snapshot.save(G);
+
+ G.addArc(G.addNode(), G.addNode());
+
+ snapshot.restore();
+ snapshot.save(G);
+
+ checkGraphNodeList(G, 4);
+ checkGraphArcList(G, 4);
+
+ G.addArc(G.addNode(), G.addNode());
+
+ snapshot.restore();
+
+ checkGraphNodeList(G, 4);
+ checkGraphArcList(G, 4);
+}
+
+void checkConcepts() {
+ { // Checking digraph components
+ checkConcept<BaseDigraphComponent, BaseDigraphComponent >();
+
+ checkConcept<IDableDigraphComponent<>,
+ IDableDigraphComponent<> >();
+
+ checkConcept<IterableDigraphComponent<>,
+ IterableDigraphComponent<> >();
+
+ checkConcept<MappableDigraphComponent<>,
+ MappableDigraphComponent<> >();
+ }
+ { // Checking skeleton digraph
+ checkConcept<Digraph, Digraph>();
+ }
+ { // Checking ListDigraph
+ checkConcept<Digraph, ListDigraph>();
+ checkConcept<AlterableDigraphComponent<>, ListDigraph>();
+ checkConcept<ExtendableDigraphComponent<>, ListDigraph>();
+ checkConcept<ClearableDigraphComponent<>, ListDigraph>();
+ checkConcept<ErasableDigraphComponent<>, ListDigraph>();
+ }
+ { // Checking SmartDigraph
+ checkConcept<Digraph, SmartDigraph>();
+ checkConcept<AlterableDigraphComponent<>, SmartDigraph>();
+ checkConcept<ExtendableDigraphComponent<>, SmartDigraph>();
+ checkConcept<ClearableDigraphComponent<>, SmartDigraph>();
+ }
+ { // Checking StaticDigraph
+ checkConcept<Digraph, StaticDigraph>();
+ checkConcept<ClearableDigraphComponent<>, StaticDigraph>();
+ }
+ { // Checking FullDigraph
+ checkConcept<Digraph, FullDigraph>();
+ }
+}
+
+template <typename Digraph>
+void checkDigraphValidity() {
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+ Digraph g;
+
+ Node
+ n1 = g.addNode(),
+ n2 = g.addNode(),
+ n3 = g.addNode();
+
+ Arc
+ e1 = g.addArc(n1, n2),
+ e2 = g.addArc(n2, n3);
+ ::lemon::ignore_unused_variable_warning(e2);
+
+ check(g.valid(n1), "Wrong validity check");
+ check(g.valid(e1), "Wrong validity check");
+
+ check(!g.valid(g.nodeFromId(-1)), "Wrong validity check");
+ check(!g.valid(g.arcFromId(-1)), "Wrong validity check");
+}
+
+template <typename Digraph>
+void checkDigraphValidityErase() {
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+ Digraph g;
+
+ Node
+ n1 = g.addNode(),
+ n2 = g.addNode(),
+ n3 = g.addNode();
+
+ Arc
+ e1 = g.addArc(n1, n2),
+ e2 = g.addArc(n2, n3);
+
+ check(g.valid(n1), "Wrong validity check");
+ check(g.valid(e1), "Wrong validity check");
+
+ g.erase(n1);
+
+ check(!g.valid(n1), "Wrong validity check");
+ check(g.valid(n2), "Wrong validity check");
+ check(g.valid(n3), "Wrong validity check");
+ check(!g.valid(e1), "Wrong validity check");
+ check(g.valid(e2), "Wrong validity check");
+
+ check(!g.valid(g.nodeFromId(-1)), "Wrong validity check");
+ check(!g.valid(g.arcFromId(-1)), "Wrong validity check");
+}
+
+void checkStaticDigraph() {
+ SmartDigraph g;
+ SmartDigraph::NodeMap<StaticDigraph::Node> nref(g);
+ SmartDigraph::ArcMap<StaticDigraph::Arc> aref(g);
+
+ StaticDigraph G;
+
+ checkGraphNodeList(G, 0);
+ checkGraphArcList(G, 0);
+
+ G.build(g, nref, aref);
+
+ checkGraphNodeList(G, 0);
+ checkGraphArcList(G, 0);
+
+ SmartDigraph::Node
+ n1 = g.addNode(),
+ n2 = g.addNode(),
+ n3 = g.addNode();
+
+ G.build(g, nref, aref);
+
+ checkGraphNodeList(G, 3);
+ checkGraphArcList(G, 0);
+
+ SmartDigraph::Arc a1 = g.addArc(n1, n2);
+
+ G.build(g, nref, aref);
+
+ check(G.source(aref[a1]) == nref[n1] && G.target(aref[a1]) == nref[n2],
+ "Wrong arc or wrong references");
+ checkGraphNodeList(G, 3);
+ checkGraphArcList(G, 1);
+
+ checkGraphOutArcList(G, nref[n1], 1);
+ checkGraphOutArcList(G, nref[n2], 0);
+ checkGraphOutArcList(G, nref[n3], 0);
+
+ checkGraphInArcList(G, nref[n1], 0);
+ checkGraphInArcList(G, nref[n2], 1);
+ checkGraphInArcList(G, nref[n3], 0);
+
+ checkGraphConArcList(G, 1);
+
+ SmartDigraph::Arc
+ a2 = g.addArc(n2, n1),
+ a3 = g.addArc(n2, n3),
+ a4 = g.addArc(n2, n3);
+ ::lemon::ignore_unused_variable_warning(a2,a3,a4);
+
+ digraphCopy(g, G).nodeRef(nref).run();
+
+ checkGraphNodeList(G, 3);
+ checkGraphArcList(G, 4);
+
+ checkGraphOutArcList(G, nref[n1], 1);
+ checkGraphOutArcList(G, nref[n2], 3);
+ checkGraphOutArcList(G, nref[n3], 0);
+
+ checkGraphInArcList(G, nref[n1], 1);
+ checkGraphInArcList(G, nref[n2], 1);
+ checkGraphInArcList(G, nref[n3], 2);
+
+ checkGraphConArcList(G, 4);
+
+ std::vector<std::pair<int,int> > arcs;
+ arcs.push_back(std::make_pair(0,1));
+ arcs.push_back(std::make_pair(0,2));
+ arcs.push_back(std::make_pair(1,3));
+ arcs.push_back(std::make_pair(1,2));
+ arcs.push_back(std::make_pair(3,0));
+ arcs.push_back(std::make_pair(3,3));
+ arcs.push_back(std::make_pair(4,2));
+ arcs.push_back(std::make_pair(4,3));
+ arcs.push_back(std::make_pair(4,1));
+
+ G.build(6, arcs.begin(), arcs.end());
+
+ checkGraphNodeList(G, 6);
+ checkGraphArcList(G, 9);
+
+ checkGraphOutArcList(G, G.node(0), 2);
+ checkGraphOutArcList(G, G.node(1), 2);
+ checkGraphOutArcList(G, G.node(2), 0);
+ checkGraphOutArcList(G, G.node(3), 2);
+ checkGraphOutArcList(G, G.node(4), 3);
+ checkGraphOutArcList(G, G.node(5), 0);
+
+ checkGraphInArcList(G, G.node(0), 1);
+ checkGraphInArcList(G, G.node(1), 2);
+ checkGraphInArcList(G, G.node(2), 3);
+ checkGraphInArcList(G, G.node(3), 3);
+ checkGraphInArcList(G, G.node(4), 0);
+ checkGraphInArcList(G, G.node(5), 0);
+
+ checkGraphConArcList(G, 9);
+
+ checkNodeIds(G);
+ checkArcIds(G);
+ checkGraphNodeMap(G);
+ checkGraphArcMap(G);
+
+ int n = G.nodeNum();
+ int m = G.arcNum();
+ check(G.index(G.node(n-1)) == n-1, "Wrong index.");
+ check(G.index(G.arc(m-1)) == m-1, "Wrong index.");
+}
+
+void checkFullDigraph(int num) {
+ typedef FullDigraph Digraph;
+ DIGRAPH_TYPEDEFS(Digraph);
+
+ Digraph G(num);
+ check(G.nodeNum() == num && G.arcNum() == num * num, "Wrong size");
+
+ G.resize(num);
+ check(G.nodeNum() == num && G.arcNum() == num * num, "Wrong size");
+
+ checkGraphNodeList(G, num);
+ checkGraphArcList(G, num * num);
+
+ for (NodeIt n(G); n != INVALID; ++n) {
+ checkGraphOutArcList(G, n, num);
+ checkGraphInArcList(G, n, num);
+ }
+
+ checkGraphConArcList(G, num * num);
+
+ checkNodeIds(G);
+ checkArcIds(G);
+ checkGraphNodeMap(G);
+ checkGraphArcMap(G);
+
+ for (int i = 0; i < G.nodeNum(); ++i) {
+ check(G.index(G(i)) == i, "Wrong index");
+ }
+
+ for (NodeIt s(G); s != INVALID; ++s) {
+ for (NodeIt t(G); t != INVALID; ++t) {
+ Arc a = G.arc(s, t);
+ check(G.source(a) == s && G.target(a) == t, "Wrong arc lookup");
+ }
+ }
+}
+
+void checkDigraphs() {
+ { // Checking ListDigraph
+ checkDigraphBuild<ListDigraph>();
+ checkDigraphSplit<ListDigraph>();
+ checkDigraphAlter<ListDigraph>();
+ checkDigraphErase<ListDigraph>();
+ checkDigraphSnapshot<ListDigraph>();
+ checkDigraphValidityErase<ListDigraph>();
+ }
+ { // Checking SmartDigraph
+ checkDigraphBuild<SmartDigraph>();
+ checkDigraphSplit<SmartDigraph>();
+ checkDigraphSnapshot<SmartDigraph>();
+ checkDigraphValidity<SmartDigraph>();
+ }
+ { // Checking StaticDigraph
+ checkStaticDigraph();
+ }
+ { // Checking FullDigraph
+ checkFullDigraph(8);
+ }
+}
+
+int main() {
+ checkDigraphs();
+ checkConcepts();
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/dijkstra_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/dijkstra_test.cc
new file mode 100644
index 00000000000..20cc76b36a8
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/dijkstra_test.cc
@@ -0,0 +1,246 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/concepts/digraph.h>
+#include <lemon/smart_graph.h>
+#include <lemon/list_graph.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/dijkstra.h>
+#include <lemon/path.h>
+#include <lemon/bin_heap.h>
+
+#include "graph_test.h"
+#include "test_tools.h"
+
+using namespace lemon;
+
+char test_lgf[] =
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "@arcs\n"
+ " label length\n"
+ "0 1 0 1\n"
+ "1 2 1 1\n"
+ "2 3 2 1\n"
+ "0 3 4 5\n"
+ "0 3 5 10\n"
+ "0 3 6 7\n"
+ "4 2 7 1\n"
+ "@attributes\n"
+ "source 0\n"
+ "target 3\n";
+
+void checkDijkstraCompile()
+{
+ typedef int VType;
+ typedef concepts::Digraph Digraph;
+ typedef concepts::ReadMap<Digraph::Arc,VType> LengthMap;
+ typedef Dijkstra<Digraph, LengthMap> DType;
+ typedef Digraph::Node Node;
+ typedef Digraph::Arc Arc;
+
+ Digraph G;
+ Node s, t, n;
+ Arc e;
+ VType l;
+ int i;
+ bool b;
+ ::lemon::ignore_unused_variable_warning(l,i,b);
+
+ DType::DistMap d(G);
+ DType::PredMap p(G);
+ LengthMap length;
+ Path<Digraph> pp;
+ concepts::ReadMap<Node,bool> nm;
+
+ {
+ DType dijkstra_test(G,length);
+ const DType& const_dijkstra_test = dijkstra_test;
+
+ dijkstra_test.run(s);
+ dijkstra_test.run(s,t);
+
+ dijkstra_test.init();
+ dijkstra_test.addSource(s);
+ dijkstra_test.addSource(s, 1);
+ n = dijkstra_test.processNextNode();
+ n = const_dijkstra_test.nextNode();
+ b = const_dijkstra_test.emptyQueue();
+ i = const_dijkstra_test.queueSize();
+
+ dijkstra_test.start();
+ dijkstra_test.start(t);
+ dijkstra_test.start(nm);
+
+ l = const_dijkstra_test.dist(t);
+ e = const_dijkstra_test.predArc(t);
+ s = const_dijkstra_test.predNode(t);
+ b = const_dijkstra_test.reached(t);
+ b = const_dijkstra_test.processed(t);
+ d = const_dijkstra_test.distMap();
+ p = const_dijkstra_test.predMap();
+ pp = const_dijkstra_test.path(t);
+ l = const_dijkstra_test.currentDist(t);
+ }
+ {
+ DType
+ ::SetPredMap<concepts::ReadWriteMap<Node,Arc> >
+ ::SetDistMap<concepts::ReadWriteMap<Node,VType> >
+ ::SetStandardProcessedMap
+ ::SetProcessedMap<concepts::WriteMap<Node,bool> >
+ ::SetOperationTraits<DijkstraDefaultOperationTraits<VType> >
+ ::SetHeap<BinHeap<VType, concepts::ReadWriteMap<Node,int> > >
+ ::SetStandardHeap<BinHeap<VType, concepts::ReadWriteMap<Node,int> > >
+ ::SetHeap<BinHeap<VType, concepts::ReadWriteMap<Node,int> >,
+ concepts::ReadWriteMap<Node,int> >
+ ::Create dijkstra_test(G,length);
+
+ LengthMap length_map;
+ concepts::ReadWriteMap<Node,Arc> pred_map;
+ concepts::ReadWriteMap<Node,VType> dist_map;
+ concepts::WriteMap<Node,bool> processed_map;
+ concepts::ReadWriteMap<Node,int> heap_cross_ref;
+ BinHeap<VType, concepts::ReadWriteMap<Node,int> > heap(heap_cross_ref);
+
+ dijkstra_test
+ .lengthMap(length_map)
+ .predMap(pred_map)
+ .distMap(dist_map)
+ .processedMap(processed_map)
+ .heap(heap, heap_cross_ref);
+
+ dijkstra_test.run(s);
+ dijkstra_test.run(s,t);
+
+ dijkstra_test.addSource(s);
+ dijkstra_test.addSource(s, 1);
+ n = dijkstra_test.processNextNode();
+ n = dijkstra_test.nextNode();
+ b = dijkstra_test.emptyQueue();
+ i = dijkstra_test.queueSize();
+
+ dijkstra_test.start();
+ dijkstra_test.start(t);
+ dijkstra_test.start(nm);
+
+ l = dijkstra_test.dist(t);
+ e = dijkstra_test.predArc(t);
+ s = dijkstra_test.predNode(t);
+ b = dijkstra_test.reached(t);
+ b = dijkstra_test.processed(t);
+ pp = dijkstra_test.path(t);
+ l = dijkstra_test.currentDist(t);
+ }
+
+}
+
+void checkDijkstraFunctionCompile()
+{
+ typedef int VType;
+ typedef concepts::Digraph Digraph;
+ typedef Digraph::Arc Arc;
+ typedef Digraph::Node Node;
+ typedef concepts::ReadMap<Digraph::Arc,VType> LengthMap;
+
+ Digraph g;
+ bool b;
+ ::lemon::ignore_unused_variable_warning(b);
+
+ dijkstra(g,LengthMap()).run(Node());
+ b=dijkstra(g,LengthMap()).run(Node(),Node());
+ dijkstra(g,LengthMap())
+ .predMap(concepts::ReadWriteMap<Node,Arc>())
+ .distMap(concepts::ReadWriteMap<Node,VType>())
+ .processedMap(concepts::WriteMap<Node,bool>())
+ .run(Node());
+ b=dijkstra(g,LengthMap())
+ .predMap(concepts::ReadWriteMap<Node,Arc>())
+ .distMap(concepts::ReadWriteMap<Node,VType>())
+ .processedMap(concepts::WriteMap<Node,bool>())
+ .path(concepts::Path<Digraph>())
+ .dist(VType())
+ .run(Node(),Node());
+}
+
+template <class Digraph>
+void checkDijkstra() {
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+ typedef typename Digraph::template ArcMap<int> LengthMap;
+
+ Digraph G;
+ Node s, t;
+ LengthMap length(G);
+
+ std::istringstream input(test_lgf);
+ digraphReader(G, input).
+ arcMap("length", length).
+ node("source", s).
+ node("target", t).
+ run();
+
+ Dijkstra<Digraph, LengthMap>
+ dijkstra_test(G, length);
+ dijkstra_test.run(s);
+
+ check(dijkstra_test.dist(t)==3,"Dijkstra found a wrong path.");
+
+ Path<Digraph> p = dijkstra_test.path(t);
+ check(p.length()==3,"path() found a wrong path.");
+ check(checkPath(G, p),"path() found a wrong path.");
+ check(pathSource(G, p) == s,"path() found a wrong path.");
+ check(pathTarget(G, p) == t,"path() found a wrong path.");
+
+ for(ArcIt e(G); e!=INVALID; ++e) {
+ Node u=G.source(e);
+ Node v=G.target(e);
+ check( !dijkstra_test.reached(u) ||
+ (dijkstra_test.dist(v) - dijkstra_test.dist(u) <= length[e]),
+ "Wrong output. dist(target)-dist(source)-arc_length=" <<
+ dijkstra_test.dist(v) - dijkstra_test.dist(u) - length[e]);
+ }
+
+ for(NodeIt v(G); v!=INVALID; ++v) {
+ if (dijkstra_test.reached(v)) {
+ check(v==s || dijkstra_test.predArc(v)!=INVALID, "Wrong tree.");
+ if (dijkstra_test.predArc(v)!=INVALID ) {
+ Arc e=dijkstra_test.predArc(v);
+ Node u=G.source(e);
+ check(u==dijkstra_test.predNode(v),"Wrong tree.");
+ check(dijkstra_test.dist(v) - dijkstra_test.dist(u) == length[e],
+ "Wrong distance! Difference: " <<
+ std::abs(dijkstra_test.dist(v)-dijkstra_test.dist(u)-length[e]));
+ }
+ }
+ }
+
+ {
+ NullMap<Node,Arc> myPredMap;
+ dijkstra(G,length).predMap(myPredMap).run(s);
+ }
+}
+
+int main() {
+ checkDijkstra<ListDigraph>();
+ checkDijkstra<SmartDigraph>();
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/dim_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/dim_test.cc
new file mode 100644
index 00000000000..0b2b9250feb
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/dim_test.cc
@@ -0,0 +1,87 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/dim2.h>
+#include <iostream>
+#include "test_tools.h"
+
+using namespace std;
+using namespace lemon;
+
+int main()
+{
+ typedef dim2::Point<int> Point;
+
+ Point p;
+ check(p.size()==2, "Wrong dim2::Point initialization.");
+
+ Point a(1,2);
+ Point b(3,4);
+ check(a[0]==1 && a[1]==2, "Wrong dim2::Point initialization.");
+
+ p = a+b;
+ check(p.x==4 && p.y==6, "Wrong dim2::Point addition.");
+
+ p = a-b;
+ check(p.x==-2 && p.y==-2, "Wrong dim2::Point subtraction.");
+
+ check(a.normSquare()==5,"Wrong dim2::Point norm calculation.");
+ check(a*b==11, "Wrong dim2::Point scalar product.");
+
+ int l=2;
+ p = a*l;
+ check(p.x==2 && p.y==4, "Wrong dim2::Point multiplication by a scalar.");
+
+ p = b/l;
+ check(p.x==1 && p.y==2, "Wrong dim2::Point division by a scalar.");
+
+ typedef dim2::Box<int> Box;
+ Box box1;
+ check(box1.empty(), "Wrong empty() in dim2::Box.");
+
+ box1.add(a);
+ check(!box1.empty(), "Wrong empty() in dim2::Box.");
+ box1.add(b);
+
+ check(box1.left()==1 && box1.bottom()==2 &&
+ box1.right()==3 && box1.top()==4,
+ "Wrong addition of points to dim2::Box.");
+
+ check(box1.inside(Point(2,3)), "Wrong inside() in dim2::Box.");
+ check(box1.inside(Point(1,3)), "Wrong inside() in dim2::Box.");
+ check(!box1.inside(Point(0,3)), "Wrong inside() in dim2::Box.");
+
+ Box box2(Point(2,2));
+ check(!box2.empty(), "Wrong empty() in dim2::Box.");
+
+ box2.bottomLeft(Point(2,0));
+ box2.topRight(Point(5,3));
+ Box box3 = box1 & box2;
+ check(!box3.empty() &&
+ box3.left()==2 && box3.bottom()==2 &&
+ box3.right()==3 && box3.top()==3,
+ "Wrong intersection of two dim2::Box objects.");
+
+ box1.add(box2);
+ check(!box1.empty() &&
+ box1.left()==1 && box1.bottom()==0 &&
+ box1.right()==5 && box1.top()==4,
+ "Wrong addition of two dim2::Box objects.");
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/edge_set_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/edge_set_test.cc
new file mode 100644
index 00000000000..dbe74a9fcb5
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/edge_set_test.cc
@@ -0,0 +1,396 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+#include <vector>
+
+#include <lemon/concepts/digraph.h>
+#include <lemon/concepts/graph.h>
+#include <lemon/concept_check.h>
+
+#include <lemon/list_graph.h>
+
+#include <lemon/edge_set.h>
+
+#include "graph_test.h"
+#include "test_tools.h"
+
+using namespace lemon;
+
+void checkSmartArcSet() {
+ checkConcept<concepts::Digraph, SmartArcSet<ListDigraph> >();
+
+ typedef ListDigraph Digraph;
+ typedef SmartArcSet<Digraph> ArcSet;
+
+ Digraph digraph;
+ Digraph::Node
+ n1 = digraph.addNode(),
+ n2 = digraph.addNode();
+
+ Digraph::Arc ga1 = digraph.addArc(n1, n2);
+ ::lemon::ignore_unused_variable_warning(ga1);
+
+ ArcSet arc_set(digraph);
+
+ Digraph::Arc ga2 = digraph.addArc(n2, n1);
+ ::lemon::ignore_unused_variable_warning(ga2);
+
+ checkGraphNodeList(arc_set, 2);
+ checkGraphArcList(arc_set, 0);
+
+ Digraph::Node
+ n3 = digraph.addNode();
+ checkGraphNodeList(arc_set, 3);
+ checkGraphArcList(arc_set, 0);
+
+ ArcSet::Arc a1 = arc_set.addArc(n1, n2);
+ check(arc_set.source(a1) == n1 && arc_set.target(a1) == n2, "Wrong arc");
+ checkGraphNodeList(arc_set, 3);
+ checkGraphArcList(arc_set, 1);
+
+ checkGraphOutArcList(arc_set, n1, 1);
+ checkGraphOutArcList(arc_set, n2, 0);
+ checkGraphOutArcList(arc_set, n3, 0);
+
+ checkGraphInArcList(arc_set, n1, 0);
+ checkGraphInArcList(arc_set, n2, 1);
+ checkGraphInArcList(arc_set, n3, 0);
+
+ checkGraphConArcList(arc_set, 1);
+
+ ArcSet::Arc a2 = arc_set.addArc(n2, n1),
+ a3 = arc_set.addArc(n2, n3),
+ a4 = arc_set.addArc(n2, n3);
+ ::lemon::ignore_unused_variable_warning(a2,a3,a4);
+
+ checkGraphNodeList(arc_set, 3);
+ checkGraphArcList(arc_set, 4);
+
+ checkGraphOutArcList(arc_set, n1, 1);
+ checkGraphOutArcList(arc_set, n2, 3);
+ checkGraphOutArcList(arc_set, n3, 0);
+
+ checkGraphInArcList(arc_set, n1, 1);
+ checkGraphInArcList(arc_set, n2, 1);
+ checkGraphInArcList(arc_set, n3, 2);
+
+ checkGraphConArcList(arc_set, 4);
+
+ checkNodeIds(arc_set);
+ checkArcIds(arc_set);
+ checkGraphNodeMap(arc_set);
+ checkGraphArcMap(arc_set);
+
+ check(arc_set.valid(), "Wrong validity");
+ digraph.erase(n1);
+ check(!arc_set.valid(), "Wrong validity");
+}
+
+void checkListArcSet() {
+ checkConcept<concepts::Digraph, SmartArcSet<ListDigraph> >();
+
+ typedef ListDigraph Digraph;
+ typedef ListArcSet<Digraph> ArcSet;
+
+ Digraph digraph;
+ Digraph::Node
+ n1 = digraph.addNode(),
+ n2 = digraph.addNode();
+
+ Digraph::Arc ga1 = digraph.addArc(n1, n2);
+ ::lemon::ignore_unused_variable_warning(ga1);
+
+ ArcSet arc_set(digraph);
+
+ Digraph::Arc ga2 = digraph.addArc(n2, n1);
+ ::lemon::ignore_unused_variable_warning(ga2);
+
+ checkGraphNodeList(arc_set, 2);
+ checkGraphArcList(arc_set, 0);
+
+ Digraph::Node
+ n3 = digraph.addNode();
+ checkGraphNodeList(arc_set, 3);
+ checkGraphArcList(arc_set, 0);
+
+ ArcSet::Arc a1 = arc_set.addArc(n1, n2);
+ check(arc_set.source(a1) == n1 && arc_set.target(a1) == n2, "Wrong arc");
+ checkGraphNodeList(arc_set, 3);
+ checkGraphArcList(arc_set, 1);
+
+ checkGraphOutArcList(arc_set, n1, 1);
+ checkGraphOutArcList(arc_set, n2, 0);
+ checkGraphOutArcList(arc_set, n3, 0);
+
+ checkGraphInArcList(arc_set, n1, 0);
+ checkGraphInArcList(arc_set, n2, 1);
+ checkGraphInArcList(arc_set, n3, 0);
+
+ checkGraphConArcList(arc_set, 1);
+
+ ArcSet::Arc a2 = arc_set.addArc(n2, n1),
+ a3 = arc_set.addArc(n2, n3),
+ a4 = arc_set.addArc(n2, n3);
+ ::lemon::ignore_unused_variable_warning(a2,a3,a4);
+
+ checkGraphNodeList(arc_set, 3);
+ checkGraphArcList(arc_set, 4);
+
+ checkGraphOutArcList(arc_set, n1, 1);
+ checkGraphOutArcList(arc_set, n2, 3);
+ checkGraphOutArcList(arc_set, n3, 0);
+
+ checkGraphInArcList(arc_set, n1, 1);
+ checkGraphInArcList(arc_set, n2, 1);
+ checkGraphInArcList(arc_set, n3, 2);
+
+ checkGraphConArcList(arc_set, 4);
+
+ checkNodeIds(arc_set);
+ checkArcIds(arc_set);
+ checkGraphNodeMap(arc_set);
+ checkGraphArcMap(arc_set);
+
+ digraph.erase(n1);
+
+ checkGraphNodeList(arc_set, 2);
+ checkGraphArcList(arc_set, 2);
+
+ checkGraphOutArcList(arc_set, n2, 2);
+ checkGraphOutArcList(arc_set, n3, 0);
+
+ checkGraphInArcList(arc_set, n2, 0);
+ checkGraphInArcList(arc_set, n3, 2);
+
+ checkNodeIds(arc_set);
+ checkArcIds(arc_set);
+ checkGraphNodeMap(arc_set);
+ checkGraphArcMap(arc_set);
+
+ checkGraphConArcList(arc_set, 2);
+}
+
+void checkSmartEdgeSet() {
+ checkConcept<concepts::Digraph, SmartEdgeSet<ListDigraph> >();
+
+ typedef ListDigraph Digraph;
+ typedef SmartEdgeSet<Digraph> EdgeSet;
+
+ Digraph digraph;
+ Digraph::Node
+ n1 = digraph.addNode(),
+ n2 = digraph.addNode();
+
+ Digraph::Arc ga1 = digraph.addArc(n1, n2);
+ ::lemon::ignore_unused_variable_warning(ga1);
+
+ EdgeSet edge_set(digraph);
+
+ Digraph::Arc ga2 = digraph.addArc(n2, n1);
+ ::lemon::ignore_unused_variable_warning(ga2);
+
+ checkGraphNodeList(edge_set, 2);
+ checkGraphArcList(edge_set, 0);
+ checkGraphEdgeList(edge_set, 0);
+
+ Digraph::Node
+ n3 = digraph.addNode();
+ checkGraphNodeList(edge_set, 3);
+ checkGraphArcList(edge_set, 0);
+ checkGraphEdgeList(edge_set, 0);
+
+ EdgeSet::Edge e1 = edge_set.addEdge(n1, n2);
+ check((edge_set.u(e1) == n1 && edge_set.v(e1) == n2) ||
+ (edge_set.v(e1) == n1 && edge_set.u(e1) == n2), "Wrong edge");
+ checkGraphNodeList(edge_set, 3);
+ checkGraphArcList(edge_set, 2);
+ checkGraphEdgeList(edge_set, 1);
+
+ checkGraphOutArcList(edge_set, n1, 1);
+ checkGraphOutArcList(edge_set, n2, 1);
+ checkGraphOutArcList(edge_set, n3, 0);
+
+ checkGraphInArcList(edge_set, n1, 1);
+ checkGraphInArcList(edge_set, n2, 1);
+ checkGraphInArcList(edge_set, n3, 0);
+
+ checkGraphIncEdgeList(edge_set, n1, 1);
+ checkGraphIncEdgeList(edge_set, n2, 1);
+ checkGraphIncEdgeList(edge_set, n3, 0);
+
+ checkGraphConEdgeList(edge_set, 1);
+ checkGraphConArcList(edge_set, 2);
+
+ EdgeSet::Edge e2 = edge_set.addEdge(n2, n1),
+ e3 = edge_set.addEdge(n2, n3),
+ e4 = edge_set.addEdge(n2, n3);
+ ::lemon::ignore_unused_variable_warning(e2,e3,e4);
+
+ checkGraphNodeList(edge_set, 3);
+ checkGraphEdgeList(edge_set, 4);
+
+ checkGraphOutArcList(edge_set, n1, 2);
+ checkGraphOutArcList(edge_set, n2, 4);
+ checkGraphOutArcList(edge_set, n3, 2);
+
+ checkGraphInArcList(edge_set, n1, 2);
+ checkGraphInArcList(edge_set, n2, 4);
+ checkGraphInArcList(edge_set, n3, 2);
+
+ checkGraphIncEdgeList(edge_set, n1, 2);
+ checkGraphIncEdgeList(edge_set, n2, 4);
+ checkGraphIncEdgeList(edge_set, n3, 2);
+
+ checkGraphConEdgeList(edge_set, 4);
+ checkGraphConArcList(edge_set, 8);
+
+ checkArcDirections(edge_set);
+
+ checkNodeIds(edge_set);
+ checkArcIds(edge_set);
+ checkEdgeIds(edge_set);
+ checkGraphNodeMap(edge_set);
+ checkGraphArcMap(edge_set);
+ checkGraphEdgeMap(edge_set);
+
+ check(edge_set.valid(), "Wrong validity");
+ digraph.erase(n1);
+ check(!edge_set.valid(), "Wrong validity");
+}
+
+void checkListEdgeSet() {
+ checkConcept<concepts::Digraph, ListEdgeSet<ListDigraph> >();
+
+ typedef ListDigraph Digraph;
+ typedef ListEdgeSet<Digraph> EdgeSet;
+
+ Digraph digraph;
+ Digraph::Node
+ n1 = digraph.addNode(),
+ n2 = digraph.addNode();
+
+ Digraph::Arc ga1 = digraph.addArc(n1, n2);
+ ::lemon::ignore_unused_variable_warning(ga1);
+
+ EdgeSet edge_set(digraph);
+
+ Digraph::Arc ga2 = digraph.addArc(n2, n1);
+ ::lemon::ignore_unused_variable_warning(ga2);
+
+ checkGraphNodeList(edge_set, 2);
+ checkGraphArcList(edge_set, 0);
+ checkGraphEdgeList(edge_set, 0);
+
+ Digraph::Node
+ n3 = digraph.addNode();
+ checkGraphNodeList(edge_set, 3);
+ checkGraphArcList(edge_set, 0);
+ checkGraphEdgeList(edge_set, 0);
+
+ EdgeSet::Edge e1 = edge_set.addEdge(n1, n2);
+ check((edge_set.u(e1) == n1 && edge_set.v(e1) == n2) ||
+ (edge_set.v(e1) == n1 && edge_set.u(e1) == n2), "Wrong edge");
+ checkGraphNodeList(edge_set, 3);
+ checkGraphArcList(edge_set, 2);
+ checkGraphEdgeList(edge_set, 1);
+
+ checkGraphOutArcList(edge_set, n1, 1);
+ checkGraphOutArcList(edge_set, n2, 1);
+ checkGraphOutArcList(edge_set, n3, 0);
+
+ checkGraphInArcList(edge_set, n1, 1);
+ checkGraphInArcList(edge_set, n2, 1);
+ checkGraphInArcList(edge_set, n3, 0);
+
+ checkGraphIncEdgeList(edge_set, n1, 1);
+ checkGraphIncEdgeList(edge_set, n2, 1);
+ checkGraphIncEdgeList(edge_set, n3, 0);
+
+ checkGraphConEdgeList(edge_set, 1);
+ checkGraphConArcList(edge_set, 2);
+
+ EdgeSet::Edge e2 = edge_set.addEdge(n2, n1),
+ e3 = edge_set.addEdge(n2, n3),
+ e4 = edge_set.addEdge(n2, n3);
+ ::lemon::ignore_unused_variable_warning(e2,e3,e4);
+
+ checkGraphNodeList(edge_set, 3);
+ checkGraphEdgeList(edge_set, 4);
+
+ checkGraphOutArcList(edge_set, n1, 2);
+ checkGraphOutArcList(edge_set, n2, 4);
+ checkGraphOutArcList(edge_set, n3, 2);
+
+ checkGraphInArcList(edge_set, n1, 2);
+ checkGraphInArcList(edge_set, n2, 4);
+ checkGraphInArcList(edge_set, n3, 2);
+
+ checkGraphIncEdgeList(edge_set, n1, 2);
+ checkGraphIncEdgeList(edge_set, n2, 4);
+ checkGraphIncEdgeList(edge_set, n3, 2);
+
+ checkGraphConEdgeList(edge_set, 4);
+ checkGraphConArcList(edge_set, 8);
+
+ checkArcDirections(edge_set);
+
+ checkNodeIds(edge_set);
+ checkArcIds(edge_set);
+ checkEdgeIds(edge_set);
+ checkGraphNodeMap(edge_set);
+ checkGraphArcMap(edge_set);
+ checkGraphEdgeMap(edge_set);
+
+ digraph.erase(n1);
+
+ checkGraphNodeList(edge_set, 2);
+ checkGraphArcList(edge_set, 4);
+ checkGraphEdgeList(edge_set, 2);
+
+ checkGraphOutArcList(edge_set, n2, 2);
+ checkGraphOutArcList(edge_set, n3, 2);
+
+ checkGraphInArcList(edge_set, n2, 2);
+ checkGraphInArcList(edge_set, n3, 2);
+
+ checkGraphIncEdgeList(edge_set, n2, 2);
+ checkGraphIncEdgeList(edge_set, n3, 2);
+
+ checkNodeIds(edge_set);
+ checkArcIds(edge_set);
+ checkEdgeIds(edge_set);
+ checkGraphNodeMap(edge_set);
+ checkGraphArcMap(edge_set);
+ checkGraphEdgeMap(edge_set);
+
+ checkGraphConEdgeList(edge_set, 2);
+ checkGraphConArcList(edge_set, 4);
+
+}
+
+
+int main() {
+
+ checkSmartArcSet();
+ checkListArcSet();
+ checkSmartEdgeSet();
+ checkListEdgeSet();
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/error_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/error_test.cc
new file mode 100644
index 00000000000..1527519812b
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/error_test.cc
@@ -0,0 +1,90 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+
+#include <lemon/error.h>
+#include "test_tools.h"
+
+using namespace lemon;
+
+#ifdef LEMON_ENABLE_ASSERTS
+#undef LEMON_ENABLE_ASSERTS
+#endif
+
+#ifdef LEMON_DISABLE_ASSERTS
+#undef LEMON_DISABLE_ASSERTS
+#endif
+
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+//checking disabled asserts
+#define LEMON_DISABLE_ASSERTS
+#include <lemon/assert.h>
+
+void no_assertion_text_disable() {
+ LEMON_ASSERT(true, "This is a fault message");
+}
+
+void assertion_text_disable() {
+ LEMON_ASSERT(false, "This is a fault message");
+}
+
+void check_assertion_disable() {
+ no_assertion_text_disable();
+ assertion_text_disable();
+}
+#undef LEMON_DISABLE_ASSERTS
+
+//checking custom assert handler
+#define LEMON_ASSERT_CUSTOM
+
+static int cnt = 0;
+void my_assert_handler(const char*, int, const char*,
+ const char*, const char*) {
+ ++cnt;
+}
+
+#define LEMON_CUSTOM_ASSERT_HANDLER my_assert_handler
+#include <lemon/assert.h>
+
+void no_assertion_text_custom() {
+ LEMON_ASSERT(true, "This is a fault message");
+}
+
+void assertion_text_custom() {
+ LEMON_ASSERT(false, "This is a fault message");
+}
+
+void check_assertion_custom() {
+ no_assertion_text_custom();
+ assertion_text_custom();
+ check(cnt == 1, "The custom assert handler does not work");
+}
+
+#undef LEMON_ASSERT_CUSTOM
+
+
+int main() {
+ check_assertion_disable();
+ check_assertion_custom();
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/euler_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/euler_test.cc
new file mode 100644
index 00000000000..11a39e47081
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/euler_test.cc
@@ -0,0 +1,225 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/euler.h>
+#include <lemon/list_graph.h>
+#include <lemon/adaptors.h>
+#include "test_tools.h"
+
+using namespace lemon;
+
+template <typename Digraph>
+void checkDiEulerIt(const Digraph& g,
+ const typename Digraph::Node& start = INVALID)
+{
+ typename Digraph::template ArcMap<int> visitationNumber(g, 0);
+
+ DiEulerIt<Digraph> e(g, start);
+ if (e == INVALID) return;
+ typename Digraph::Node firstNode = g.source(e);
+ typename Digraph::Node lastNode = g.target(e);
+ if (start != INVALID) {
+ check(firstNode == start, "checkDiEulerIt: Wrong first node");
+ }
+
+ for (; e != INVALID; ++e) {
+ if (e != INVALID) lastNode = g.target(e);
+ ++visitationNumber[e];
+ }
+
+ check(firstNode == lastNode,
+ "checkDiEulerIt: First and last nodes are not the same");
+
+ for (typename Digraph::ArcIt a(g); a != INVALID; ++a)
+ {
+ check(visitationNumber[a] == 1,
+ "checkDiEulerIt: Not visited or multiple times visited arc found");
+ }
+}
+
+template <typename Graph>
+void checkEulerIt(const Graph& g,
+ const typename Graph::Node& start = INVALID)
+{
+ typename Graph::template EdgeMap<int> visitationNumber(g, 0);
+
+ EulerIt<Graph> e(g, start);
+ if (e == INVALID) return;
+ typename Graph::Node firstNode = g.source(typename Graph::Arc(e));
+ typename Graph::Node lastNode = g.target(typename Graph::Arc(e));
+ if (start != INVALID) {
+ check(firstNode == start, "checkEulerIt: Wrong first node");
+ }
+
+ for (; e != INVALID; ++e) {
+ if (e != INVALID) lastNode = g.target(typename Graph::Arc(e));
+ ++visitationNumber[e];
+ }
+
+ check(firstNode == lastNode,
+ "checkEulerIt: First and last nodes are not the same");
+
+ for (typename Graph::EdgeIt e(g); e != INVALID; ++e)
+ {
+ check(visitationNumber[e] == 1,
+ "checkEulerIt: Not visited or multiple times visited edge found");
+ }
+}
+
+int main()
+{
+ typedef ListDigraph Digraph;
+ typedef Undirector<Digraph> Graph;
+
+ {
+ Digraph d;
+ Graph g(d);
+
+ checkDiEulerIt(d);
+ checkDiEulerIt(g);
+ checkEulerIt(g);
+
+ check(eulerian(d), "This graph is Eulerian");
+ check(eulerian(g), "This graph is Eulerian");
+ }
+ {
+ Digraph d;
+ Graph g(d);
+ Digraph::Node n = d.addNode();
+ ::lemon::ignore_unused_variable_warning(n);
+
+ checkDiEulerIt(d);
+ checkDiEulerIt(g);
+ checkEulerIt(g);
+
+ check(eulerian(d), "This graph is Eulerian");
+ check(eulerian(g), "This graph is Eulerian");
+ }
+ {
+ Digraph d;
+ Graph g(d);
+ Digraph::Node n = d.addNode();
+ d.addArc(n, n);
+
+ checkDiEulerIt(d);
+ checkDiEulerIt(g);
+ checkEulerIt(g);
+
+ check(eulerian(d), "This graph is Eulerian");
+ check(eulerian(g), "This graph is Eulerian");
+ }
+ {
+ Digraph d;
+ Graph g(d);
+ Digraph::Node n1 = d.addNode();
+ Digraph::Node n2 = d.addNode();
+ Digraph::Node n3 = d.addNode();
+
+ d.addArc(n1, n2);
+ d.addArc(n2, n1);
+ d.addArc(n2, n3);
+ d.addArc(n3, n2);
+
+ checkDiEulerIt(d);
+ checkDiEulerIt(d, n2);
+ checkDiEulerIt(g);
+ checkDiEulerIt(g, n2);
+ checkEulerIt(g);
+ checkEulerIt(g, n2);
+
+ check(eulerian(d), "This graph is Eulerian");
+ check(eulerian(g), "This graph is Eulerian");
+ }
+ {
+ Digraph d;
+ Graph g(d);
+ Digraph::Node n1 = d.addNode();
+ Digraph::Node n2 = d.addNode();
+ Digraph::Node n3 = d.addNode();
+ Digraph::Node n4 = d.addNode();
+ Digraph::Node n5 = d.addNode();
+ Digraph::Node n6 = d.addNode();
+
+ d.addArc(n1, n2);
+ d.addArc(n2, n4);
+ d.addArc(n1, n3);
+ d.addArc(n3, n4);
+ d.addArc(n4, n1);
+ d.addArc(n3, n5);
+ d.addArc(n5, n2);
+ d.addArc(n4, n6);
+ d.addArc(n2, n6);
+ d.addArc(n6, n1);
+ d.addArc(n6, n3);
+
+ checkDiEulerIt(d);
+ checkDiEulerIt(d, n1);
+ checkDiEulerIt(d, n5);
+
+ checkDiEulerIt(g);
+ checkDiEulerIt(g, n1);
+ checkDiEulerIt(g, n5);
+ checkEulerIt(g);
+ checkEulerIt(g, n1);
+ checkEulerIt(g, n5);
+
+ check(eulerian(d), "This graph is Eulerian");
+ check(eulerian(g), "This graph is Eulerian");
+ }
+ {
+ Digraph d;
+ Graph g(d);
+ Digraph::Node n0 = d.addNode();
+ Digraph::Node n1 = d.addNode();
+ Digraph::Node n2 = d.addNode();
+ Digraph::Node n3 = d.addNode();
+ Digraph::Node n4 = d.addNode();
+ Digraph::Node n5 = d.addNode();
+ ::lemon::ignore_unused_variable_warning(n0,n4,n5);
+
+ d.addArc(n1, n2);
+ d.addArc(n2, n3);
+ d.addArc(n3, n1);
+
+ checkDiEulerIt(d);
+ checkDiEulerIt(d, n2);
+
+ checkDiEulerIt(g);
+ checkDiEulerIt(g, n2);
+ checkEulerIt(g);
+ checkEulerIt(g, n2);
+
+ check(!eulerian(d), "This graph is not Eulerian");
+ check(!eulerian(g), "This graph is not Eulerian");
+ }
+ {
+ Digraph d;
+ Graph g(d);
+ Digraph::Node n1 = d.addNode();
+ Digraph::Node n2 = d.addNode();
+ Digraph::Node n3 = d.addNode();
+
+ d.addArc(n1, n2);
+ d.addArc(n2, n3);
+
+ check(!eulerian(d), "This graph is not Eulerian");
+ check(!eulerian(g), "This graph is not Eulerian");
+ }
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/fractional_matching_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/fractional_matching_test.cc
new file mode 100644
index 00000000000..bee866c0149
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/fractional_matching_test.cc
@@ -0,0 +1,527 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <queue>
+#include <cstdlib>
+
+#include <lemon/fractional_matching.h>
+#include <lemon/smart_graph.h>
+#include <lemon/concepts/graph.h>
+#include <lemon/concepts/maps.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/math.h>
+
+#include "test_tools.h"
+
+using namespace std;
+using namespace lemon;
+
+GRAPH_TYPEDEFS(SmartGraph);
+
+
+const int lgfn = 4;
+const std::string lgf[lgfn] = {
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "6\n"
+ "7\n"
+ "@edges\n"
+ " label weight\n"
+ "7 4 0 984\n"
+ "0 7 1 73\n"
+ "7 1 2 204\n"
+ "2 3 3 583\n"
+ "2 7 4 565\n"
+ "2 1 5 582\n"
+ "0 4 6 551\n"
+ "2 5 7 385\n"
+ "1 5 8 561\n"
+ "5 3 9 484\n"
+ "7 5 10 904\n"
+ "3 6 11 47\n"
+ "7 6 12 888\n"
+ "3 0 13 747\n"
+ "6 1 14 310\n",
+
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "6\n"
+ "7\n"
+ "@edges\n"
+ " label weight\n"
+ "2 5 0 710\n"
+ "0 5 1 241\n"
+ "2 4 2 856\n"
+ "2 6 3 762\n"
+ "4 1 4 747\n"
+ "6 1 5 962\n"
+ "4 7 6 723\n"
+ "1 7 7 661\n"
+ "2 3 8 376\n"
+ "1 0 9 416\n"
+ "6 7 10 391\n",
+
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "6\n"
+ "7\n"
+ "@edges\n"
+ " label weight\n"
+ "6 2 0 553\n"
+ "0 7 1 653\n"
+ "6 3 2 22\n"
+ "4 7 3 846\n"
+ "7 2 4 981\n"
+ "7 6 5 250\n"
+ "5 2 6 539\n",
+
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "@edges\n"
+ " label weight\n"
+ "0 0 0 100\n"
+};
+
+void checkMaxFractionalMatchingCompile()
+{
+ typedef concepts::Graph Graph;
+ typedef Graph::Node Node;
+ typedef Graph::Edge Edge;
+
+ Graph g;
+ Node n;
+ Edge e;
+
+ MaxFractionalMatching<Graph> mat_test(g);
+ const MaxFractionalMatching<Graph>&
+ const_mat_test = mat_test;
+
+ mat_test.init();
+ mat_test.start();
+ mat_test.start(true);
+ mat_test.startPerfect();
+ mat_test.startPerfect(true);
+ mat_test.run();
+ mat_test.run(true);
+ mat_test.runPerfect();
+ mat_test.runPerfect(true);
+
+ const_mat_test.matchingSize();
+ const_mat_test.matching(e);
+ const_mat_test.matching(n);
+ const MaxFractionalMatching<Graph>::MatchingMap& mmap =
+ const_mat_test.matchingMap();
+ e = mmap[n];
+
+ const_mat_test.barrier(n);
+}
+
+void checkMaxWeightedFractionalMatchingCompile()
+{
+ typedef concepts::Graph Graph;
+ typedef Graph::Node Node;
+ typedef Graph::Edge Edge;
+ typedef Graph::EdgeMap<int> WeightMap;
+
+ Graph g;
+ Node n;
+ Edge e;
+ WeightMap w(g);
+
+ MaxWeightedFractionalMatching<Graph> mat_test(g, w);
+ const MaxWeightedFractionalMatching<Graph>&
+ const_mat_test = mat_test;
+
+ mat_test.init();
+ mat_test.start();
+ mat_test.run();
+
+ const_mat_test.matchingWeight();
+ const_mat_test.matchingSize();
+ const_mat_test.matching(e);
+ const_mat_test.matching(n);
+ const MaxWeightedFractionalMatching<Graph>::MatchingMap& mmap =
+ const_mat_test.matchingMap();
+ e = mmap[n];
+
+ const_mat_test.dualValue();
+ const_mat_test.nodeValue(n);
+}
+
+void checkMaxWeightedPerfectFractionalMatchingCompile()
+{
+ typedef concepts::Graph Graph;
+ typedef Graph::Node Node;
+ typedef Graph::Edge Edge;
+ typedef Graph::EdgeMap<int> WeightMap;
+
+ Graph g;
+ Node n;
+ Edge e;
+ WeightMap w(g);
+
+ MaxWeightedPerfectFractionalMatching<Graph> mat_test(g, w);
+ const MaxWeightedPerfectFractionalMatching<Graph>&
+ const_mat_test = mat_test;
+
+ mat_test.init();
+ mat_test.start();
+ mat_test.run();
+
+ const_mat_test.matchingWeight();
+ const_mat_test.matching(e);
+ const_mat_test.matching(n);
+ const MaxWeightedPerfectFractionalMatching<Graph>::MatchingMap& mmap =
+ const_mat_test.matchingMap();
+ e = mmap[n];
+
+ const_mat_test.dualValue();
+ const_mat_test.nodeValue(n);
+}
+
+void checkFractionalMatching(const SmartGraph& graph,
+ const MaxFractionalMatching<SmartGraph>& mfm,
+ bool allow_loops = true) {
+ int pv = 0;
+ for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
+ int indeg = 0;
+ for (InArcIt a(graph, n); a != INVALID; ++a) {
+ if (mfm.matching(graph.source(a)) == a) {
+ ++indeg;
+ }
+ }
+ if (mfm.matching(n) != INVALID) {
+ check(indeg == 1, "Invalid matching");
+ ++pv;
+ } else {
+ check(indeg == 0, "Invalid matching");
+ }
+ }
+ check(pv == mfm.matchingSize(), "Wrong matching size");
+
+ for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
+ check((e == mfm.matching(graph.u(e)) ? 1 : 0) +
+ (e == mfm.matching(graph.v(e)) ? 1 : 0) ==
+ mfm.matching(e), "Invalid matching");
+ }
+
+ SmartGraph::NodeMap<bool> processed(graph, false);
+ for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
+ if (processed[n]) continue;
+ processed[n] = true;
+ if (mfm.matching(n) == INVALID) continue;
+ int num = 1;
+ Node v = graph.target(mfm.matching(n));
+ while (v != n) {
+ processed[v] = true;
+ ++num;
+ v = graph.target(mfm.matching(v));
+ }
+ check(num == 2 || num % 2 == 1, "Wrong cycle size");
+ check(allow_loops || num != 1, "Wrong cycle size");
+ }
+
+ int anum = 0, bnum = 0;
+ SmartGraph::NodeMap<bool> neighbours(graph, false);
+ for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
+ if (!mfm.barrier(n)) continue;
+ ++anum;
+ for (SmartGraph::InArcIt a(graph, n); a != INVALID; ++a) {
+ Node u = graph.source(a);
+ if (!allow_loops && u == n) continue;
+ if (!neighbours[u]) {
+ neighbours[u] = true;
+ ++bnum;
+ }
+ }
+ }
+ check(anum - bnum + mfm.matchingSize() == countNodes(graph),
+ "Wrong barrier");
+}
+
+void checkPerfectFractionalMatching(const SmartGraph& graph,
+ const MaxFractionalMatching<SmartGraph>& mfm,
+ bool perfect, bool allow_loops = true) {
+ if (perfect) {
+ for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
+ int indeg = 0;
+ for (InArcIt a(graph, n); a != INVALID; ++a) {
+ if (mfm.matching(graph.source(a)) == a) {
+ ++indeg;
+ }
+ }
+ check(mfm.matching(n) != INVALID, "Invalid matching");
+ check(indeg == 1, "Invalid matching");
+ }
+ for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
+ check((e == mfm.matching(graph.u(e)) ? 1 : 0) +
+ (e == mfm.matching(graph.v(e)) ? 1 : 0) ==
+ mfm.matching(e), "Invalid matching");
+ }
+ } else {
+ int anum = 0, bnum = 0;
+ SmartGraph::NodeMap<bool> neighbours(graph, false);
+ for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
+ if (!mfm.barrier(n)) continue;
+ ++anum;
+ for (SmartGraph::InArcIt a(graph, n); a != INVALID; ++a) {
+ Node u = graph.source(a);
+ if (!allow_loops && u == n) continue;
+ if (!neighbours[u]) {
+ neighbours[u] = true;
+ ++bnum;
+ }
+ }
+ }
+ check(anum - bnum > 0, "Wrong barrier");
+ }
+}
+
+void checkWeightedFractionalMatching(const SmartGraph& graph,
+ const SmartGraph::EdgeMap<int>& weight,
+ const MaxWeightedFractionalMatching<SmartGraph>& mwfm,
+ bool allow_loops = true) {
+ for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
+ if (graph.u(e) == graph.v(e) && !allow_loops) continue;
+ int rw = mwfm.nodeValue(graph.u(e)) + mwfm.nodeValue(graph.v(e))
+ - weight[e] * mwfm.dualScale;
+
+ check(rw >= 0, "Negative reduced weight");
+ check(rw == 0 || !mwfm.matching(e),
+ "Non-zero reduced weight on matching edge");
+ }
+
+ int pv = 0;
+ for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
+ int indeg = 0;
+ for (InArcIt a(graph, n); a != INVALID; ++a) {
+ if (mwfm.matching(graph.source(a)) == a) {
+ ++indeg;
+ }
+ }
+ check(indeg <= 1, "Invalid matching");
+ if (mwfm.matching(n) != INVALID) {
+ check(mwfm.nodeValue(n) >= 0, "Invalid node value");
+ check(indeg == 1, "Invalid matching");
+ pv += weight[mwfm.matching(n)];
+ SmartGraph::Node o = graph.target(mwfm.matching(n));
+ ::lemon::ignore_unused_variable_warning(o);
+ } else {
+ check(mwfm.nodeValue(n) == 0, "Invalid matching");
+ check(indeg == 0, "Invalid matching");
+ }
+ }
+
+ for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
+ check((e == mwfm.matching(graph.u(e)) ? 1 : 0) +
+ (e == mwfm.matching(graph.v(e)) ? 1 : 0) ==
+ mwfm.matching(e), "Invalid matching");
+ }
+
+ int dv = 0;
+ for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
+ dv += mwfm.nodeValue(n);
+ }
+
+ check(pv * mwfm.dualScale == dv * 2, "Wrong duality");
+
+ SmartGraph::NodeMap<bool> processed(graph, false);
+ for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
+ if (processed[n]) continue;
+ processed[n] = true;
+ if (mwfm.matching(n) == INVALID) continue;
+ int num = 1;
+ Node v = graph.target(mwfm.matching(n));
+ while (v != n) {
+ processed[v] = true;
+ ++num;
+ v = graph.target(mwfm.matching(v));
+ }
+ check(num == 2 || num % 2 == 1, "Wrong cycle size");
+ check(allow_loops || num != 1, "Wrong cycle size");
+ }
+
+ return;
+}
+
+void checkWeightedPerfectFractionalMatching(const SmartGraph& graph,
+ const SmartGraph::EdgeMap<int>& weight,
+ const MaxWeightedPerfectFractionalMatching<SmartGraph>& mwpfm,
+ bool allow_loops = true) {
+ for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
+ if (graph.u(e) == graph.v(e) && !allow_loops) continue;
+ int rw = mwpfm.nodeValue(graph.u(e)) + mwpfm.nodeValue(graph.v(e))
+ - weight[e] * mwpfm.dualScale;
+
+ check(rw >= 0, "Negative reduced weight");
+ check(rw == 0 || !mwpfm.matching(e),
+ "Non-zero reduced weight on matching edge");
+ }
+
+ int pv = 0;
+ for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
+ int indeg = 0;
+ for (InArcIt a(graph, n); a != INVALID; ++a) {
+ if (mwpfm.matching(graph.source(a)) == a) {
+ ++indeg;
+ }
+ }
+ check(mwpfm.matching(n) != INVALID, "Invalid perfect matching");
+ check(indeg == 1, "Invalid perfect matching");
+ pv += weight[mwpfm.matching(n)];
+ SmartGraph::Node o = graph.target(mwpfm.matching(n));
+ ::lemon::ignore_unused_variable_warning(o);
+ }
+
+ for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
+ check((e == mwpfm.matching(graph.u(e)) ? 1 : 0) +
+ (e == mwpfm.matching(graph.v(e)) ? 1 : 0) ==
+ mwpfm.matching(e), "Invalid matching");
+ }
+
+ int dv = 0;
+ for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
+ dv += mwpfm.nodeValue(n);
+ }
+
+ check(pv * mwpfm.dualScale == dv * 2, "Wrong duality");
+
+ SmartGraph::NodeMap<bool> processed(graph, false);
+ for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
+ if (processed[n]) continue;
+ processed[n] = true;
+ if (mwpfm.matching(n) == INVALID) continue;
+ int num = 1;
+ Node v = graph.target(mwpfm.matching(n));
+ while (v != n) {
+ processed[v] = true;
+ ++num;
+ v = graph.target(mwpfm.matching(v));
+ }
+ check(num == 2 || num % 2 == 1, "Wrong cycle size");
+ check(allow_loops || num != 1, "Wrong cycle size");
+ }
+
+ return;
+}
+
+
+int main() {
+
+ for (int i = 0; i < lgfn; ++i) {
+ SmartGraph graph;
+ SmartGraph::EdgeMap<int> weight(graph);
+
+ istringstream lgfs(lgf[i]);
+ graphReader(graph, lgfs).
+ edgeMap("weight", weight).run();
+
+ bool perfect_with_loops;
+ {
+ MaxFractionalMatching<SmartGraph> mfm(graph, true);
+ mfm.run();
+ checkFractionalMatching(graph, mfm, true);
+ perfect_with_loops = mfm.matchingSize() == countNodes(graph);
+ }
+
+ bool perfect_without_loops;
+ {
+ MaxFractionalMatching<SmartGraph> mfm(graph, false);
+ mfm.run();
+ checkFractionalMatching(graph, mfm, false);
+ perfect_without_loops = mfm.matchingSize() == countNodes(graph);
+ }
+
+ {
+ MaxFractionalMatching<SmartGraph> mfm(graph, true);
+ bool result = mfm.runPerfect();
+ checkPerfectFractionalMatching(graph, mfm, result, true);
+ check(result == perfect_with_loops, "Wrong perfect matching");
+ }
+
+ {
+ MaxFractionalMatching<SmartGraph> mfm(graph, false);
+ bool result = mfm.runPerfect();
+ checkPerfectFractionalMatching(graph, mfm, result, false);
+ check(result == perfect_without_loops, "Wrong perfect matching");
+ }
+
+ {
+ MaxWeightedFractionalMatching<SmartGraph> mwfm(graph, weight, true);
+ mwfm.run();
+ checkWeightedFractionalMatching(graph, weight, mwfm, true);
+ }
+
+ {
+ MaxWeightedFractionalMatching<SmartGraph> mwfm(graph, weight, false);
+ mwfm.run();
+ checkWeightedFractionalMatching(graph, weight, mwfm, false);
+ }
+
+ {
+ MaxWeightedPerfectFractionalMatching<SmartGraph> mwpfm(graph, weight,
+ true);
+ bool perfect = mwpfm.run();
+ check(perfect == (mwpfm.matchingSize() == countNodes(graph)),
+ "Perfect matching found");
+ check(perfect == perfect_with_loops, "Wrong perfect matching");
+
+ if (perfect) {
+ checkWeightedPerfectFractionalMatching(graph, weight, mwpfm, true);
+ }
+ }
+
+ {
+ MaxWeightedPerfectFractionalMatching<SmartGraph> mwpfm(graph, weight,
+ false);
+ bool perfect = mwpfm.run();
+ check(perfect == (mwpfm.matchingSize() == countNodes(graph)),
+ "Perfect matching found");
+ check(perfect == perfect_without_loops, "Wrong perfect matching");
+
+ if (perfect) {
+ checkWeightedPerfectFractionalMatching(graph, weight, mwpfm, false);
+ }
+ }
+
+ }
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/gomory_hu_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/gomory_hu_test.cc
new file mode 100644
index 00000000000..178f21fec6f
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/gomory_hu_test.cc
@@ -0,0 +1,142 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+
+#include "test_tools.h"
+#include <lemon/smart_graph.h>
+#include <lemon/concepts/graph.h>
+#include <lemon/concepts/maps.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/gomory_hu.h>
+#include <cstdlib>
+
+using namespace std;
+using namespace lemon;
+
+typedef SmartGraph Graph;
+
+char test_lgf[] =
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "@arcs\n"
+ " label capacity\n"
+ "0 1 0 1\n"
+ "1 2 1 1\n"
+ "2 3 2 1\n"
+ "0 3 4 5\n"
+ "0 3 5 10\n"
+ "0 3 6 7\n"
+ "4 2 7 1\n"
+ "@attributes\n"
+ "source 0\n"
+ "target 3\n";
+
+void checkGomoryHuCompile()
+{
+ typedef int Value;
+ typedef concepts::Graph Graph;
+
+ typedef Graph::Node Node;
+ typedef Graph::Edge Edge;
+ typedef concepts::ReadMap<Edge, Value> CapMap;
+ typedef concepts::ReadWriteMap<Node, bool> CutMap;
+
+ Graph g;
+ Node n;
+ CapMap cap;
+ CutMap cut;
+ Value v;
+ int d;
+ ::lemon::ignore_unused_variable_warning(v,d);
+
+ GomoryHu<Graph, CapMap> gh_test(g, cap);
+ const GomoryHu<Graph, CapMap>&
+ const_gh_test = gh_test;
+
+ gh_test.run();
+
+ n = const_gh_test.predNode(n);
+ v = const_gh_test.predValue(n);
+ d = const_gh_test.rootDist(n);
+ v = const_gh_test.minCutValue(n, n);
+ v = const_gh_test.minCutMap(n, n, cut);
+}
+
+GRAPH_TYPEDEFS(Graph);
+typedef Graph::EdgeMap<int> IntEdgeMap;
+typedef Graph::NodeMap<bool> BoolNodeMap;
+
+int cutValue(const Graph& graph, const BoolNodeMap& cut,
+ const IntEdgeMap& capacity) {
+
+ int sum = 0;
+ for (EdgeIt e(graph); e != INVALID; ++e) {
+ Node s = graph.u(e);
+ Node t = graph.v(e);
+
+ if (cut[s] != cut[t]) {
+ sum += capacity[e];
+ }
+ }
+ return sum;
+}
+
+
+int main() {
+ Graph graph;
+ IntEdgeMap capacity(graph);
+
+ std::istringstream input(test_lgf);
+ GraphReader<Graph>(graph, input).
+ edgeMap("capacity", capacity).run();
+
+ GomoryHu<Graph> ght(graph, capacity);
+ ght.run();
+
+ for (NodeIt u(graph); u != INVALID; ++u) {
+ for (NodeIt v(graph); v != u; ++v) {
+ Preflow<Graph, IntEdgeMap> pf(graph, capacity, u, v);
+ pf.runMinCut();
+ BoolNodeMap cm(graph);
+ ght.minCutMap(u, v, cm);
+ check(pf.flowValue() == ght.minCutValue(u, v), "Wrong cut 1");
+ check(cm[u] != cm[v], "Wrong cut 2");
+ check(pf.flowValue() == cutValue(graph, cm, capacity), "Wrong cut 3");
+
+ int sum=0;
+ for(GomoryHu<Graph>::MinCutEdgeIt a(ght, u, v);a!=INVALID;++a)
+ sum+=capacity[a];
+ check(sum == ght.minCutValue(u, v), "Problem with MinCutEdgeIt");
+
+ sum=0;
+ for(GomoryHu<Graph>::MinCutNodeIt n(ght, u, v,true);n!=INVALID;++n)
+ sum++;
+ for(GomoryHu<Graph>::MinCutNodeIt n(ght, u, v,false);n!=INVALID;++n)
+ sum++;
+ check(sum == countNodes(graph), "Problem with MinCutNodeIt");
+ }
+ }
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/graph_copy_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/graph_copy_test.cc
new file mode 100644
index 00000000000..9a7d8155e0f
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/graph_copy_test.cc
@@ -0,0 +1,388 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/smart_graph.h>
+#include <lemon/list_graph.h>
+#include <lemon/static_graph.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/error.h>
+
+#include "test_tools.h"
+
+using namespace std;
+using namespace lemon;
+
+template <typename GR>
+void digraph_copy_test() {
+ const int nn = 10;
+
+ // Build a digraph
+ SmartDigraph from;
+ SmartDigraph::NodeMap<int> fnm(from);
+ SmartDigraph::ArcMap<int> fam(from);
+ SmartDigraph::Node fn = INVALID;
+ SmartDigraph::Arc fa = INVALID;
+
+ std::vector<SmartDigraph::Node> fnv;
+ for (int i = 0; i < nn; ++i) {
+ SmartDigraph::Node node = from.addNode();
+ fnv.push_back(node);
+ fnm[node] = i * i;
+ if (i == 0) fn = node;
+ }
+
+ for (int i = 0; i < nn; ++i) {
+ for (int j = 0; j < nn; ++j) {
+ SmartDigraph::Arc arc = from.addArc(fnv[i], fnv[j]);
+ fam[arc] = i + j * j;
+ if (i == 0 && j == 0) fa = arc;
+ }
+ }
+
+ // Test digraph copy
+ GR to;
+ typename GR::template NodeMap<int> tnm(to);
+ typename GR::template ArcMap<int> tam(to);
+ typename GR::Node tn;
+ typename GR::Arc ta;
+
+ SmartDigraph::NodeMap<typename GR::Node> nr(from);
+ SmartDigraph::ArcMap<typename GR::Arc> er(from);
+
+ typename GR::template NodeMap<SmartDigraph::Node> ncr(to);
+ typename GR::template ArcMap<SmartDigraph::Arc> ecr(to);
+
+ digraphCopy(from, to).
+ nodeMap(fnm, tnm).arcMap(fam, tam).
+ nodeRef(nr).arcRef(er).
+ nodeCrossRef(ncr).arcCrossRef(ecr).
+ node(fn, tn).arc(fa, ta).run();
+
+ check(countNodes(from) == countNodes(to), "Wrong copy.");
+ check(countArcs(from) == countArcs(to), "Wrong copy.");
+
+ for (SmartDigraph::NodeIt it(from); it != INVALID; ++it) {
+ check(ncr[nr[it]] == it, "Wrong copy.");
+ check(fnm[it] == tnm[nr[it]], "Wrong copy.");
+ }
+
+ for (SmartDigraph::ArcIt it(from); it != INVALID; ++it) {
+ check(ecr[er[it]] == it, "Wrong copy.");
+ check(fam[it] == tam[er[it]], "Wrong copy.");
+ check(nr[from.source(it)] == to.source(er[it]), "Wrong copy.");
+ check(nr[from.target(it)] == to.target(er[it]), "Wrong copy.");
+ }
+
+ for (typename GR::NodeIt it(to); it != INVALID; ++it) {
+ check(nr[ncr[it]] == it, "Wrong copy.");
+ }
+
+ for (typename GR::ArcIt it(to); it != INVALID; ++it) {
+ check(er[ecr[it]] == it, "Wrong copy.");
+ }
+ check(tn == nr[fn], "Wrong copy.");
+ check(ta == er[fa], "Wrong copy.");
+
+ // Test repeated copy
+ digraphCopy(from, to).run();
+
+ check(countNodes(from) == countNodes(to), "Wrong copy.");
+ check(countArcs(from) == countArcs(to), "Wrong copy.");
+}
+
+template <typename GR>
+void graph_copy_test() {
+ const int nn = 10;
+
+ // Build a graph
+ SmartGraph from;
+ SmartGraph::NodeMap<int> fnm(from);
+ SmartGraph::ArcMap<int> fam(from);
+ SmartGraph::EdgeMap<int> fem(from);
+ SmartGraph::Node fn = INVALID;
+ SmartGraph::Arc fa = INVALID;
+ SmartGraph::Edge fe = INVALID;
+
+ std::vector<SmartGraph::Node> fnv;
+ for (int i = 0; i < nn; ++i) {
+ SmartGraph::Node node = from.addNode();
+ fnv.push_back(node);
+ fnm[node] = i * i;
+ if (i == 0) fn = node;
+ }
+
+ for (int i = 0; i < nn; ++i) {
+ for (int j = 0; j < nn; ++j) {
+ SmartGraph::Edge edge = from.addEdge(fnv[i], fnv[j]);
+ fem[edge] = i * i + j * j;
+ fam[from.direct(edge, true)] = i + j * j;
+ fam[from.direct(edge, false)] = i * i + j;
+ if (i == 0 && j == 0) fa = from.direct(edge, true);
+ if (i == 0 && j == 0) fe = edge;
+ }
+ }
+
+ // Test graph copy
+ GR to;
+ typename GR::template NodeMap<int> tnm(to);
+ typename GR::template ArcMap<int> tam(to);
+ typename GR::template EdgeMap<int> tem(to);
+ typename GR::Node tn;
+ typename GR::Arc ta;
+ typename GR::Edge te;
+
+ SmartGraph::NodeMap<typename GR::Node> nr(from);
+ SmartGraph::ArcMap<typename GR::Arc> ar(from);
+ SmartGraph::EdgeMap<typename GR::Edge> er(from);
+
+ typename GR::template NodeMap<SmartGraph::Node> ncr(to);
+ typename GR::template ArcMap<SmartGraph::Arc> acr(to);
+ typename GR::template EdgeMap<SmartGraph::Edge> ecr(to);
+
+ graphCopy(from, to).
+ nodeMap(fnm, tnm).arcMap(fam, tam).edgeMap(fem, tem).
+ nodeRef(nr).arcRef(ar).edgeRef(er).
+ nodeCrossRef(ncr).arcCrossRef(acr).edgeCrossRef(ecr).
+ node(fn, tn).arc(fa, ta).edge(fe, te).run();
+
+ check(countNodes(from) == countNodes(to), "Wrong copy.");
+ check(countEdges(from) == countEdges(to), "Wrong copy.");
+ check(countArcs(from) == countArcs(to), "Wrong copy.");
+
+ for (SmartGraph::NodeIt it(from); it != INVALID; ++it) {
+ check(ncr[nr[it]] == it, "Wrong copy.");
+ check(fnm[it] == tnm[nr[it]], "Wrong copy.");
+ }
+
+ for (SmartGraph::ArcIt it(from); it != INVALID; ++it) {
+ check(acr[ar[it]] == it, "Wrong copy.");
+ check(fam[it] == tam[ar[it]], "Wrong copy.");
+ check(nr[from.source(it)] == to.source(ar[it]), "Wrong copy.");
+ check(nr[from.target(it)] == to.target(ar[it]), "Wrong copy.");
+ }
+
+ for (SmartGraph::EdgeIt it(from); it != INVALID; ++it) {
+ check(ecr[er[it]] == it, "Wrong copy.");
+ check(fem[it] == tem[er[it]], "Wrong copy.");
+ check(nr[from.u(it)] == to.u(er[it]) || nr[from.u(it)] == to.v(er[it]),
+ "Wrong copy.");
+ check(nr[from.v(it)] == to.u(er[it]) || nr[from.v(it)] == to.v(er[it]),
+ "Wrong copy.");
+ check((from.u(it) != from.v(it)) == (to.u(er[it]) != to.v(er[it])),
+ "Wrong copy.");
+ }
+
+ for (typename GR::NodeIt it(to); it != INVALID; ++it) {
+ check(nr[ncr[it]] == it, "Wrong copy.");
+ }
+
+ for (typename GR::ArcIt it(to); it != INVALID; ++it) {
+ check(ar[acr[it]] == it, "Wrong copy.");
+ }
+ for (typename GR::EdgeIt it(to); it != INVALID; ++it) {
+ check(er[ecr[it]] == it, "Wrong copy.");
+ }
+ check(tn == nr[fn], "Wrong copy.");
+ check(ta == ar[fa], "Wrong copy.");
+ check(te == er[fe], "Wrong copy.");
+
+ // Test repeated copy
+ graphCopy(from, to).run();
+
+ check(countNodes(from) == countNodes(to), "Wrong copy.");
+ check(countEdges(from) == countEdges(to), "Wrong copy.");
+ check(countArcs(from) == countArcs(to), "Wrong copy.");
+}
+
+template <typename GR>
+void bpgraph_copy_test() {
+ const int nn = 10;
+
+ // Build a graph
+ SmartBpGraph from;
+ SmartBpGraph::NodeMap<int> fnm(from);
+ SmartBpGraph::RedNodeMap<int> frnm(from);
+ SmartBpGraph::BlueNodeMap<int> fbnm(from);
+ SmartBpGraph::ArcMap<int> fam(from);
+ SmartBpGraph::EdgeMap<int> fem(from);
+ SmartBpGraph::Node fn = INVALID;
+ SmartBpGraph::RedNode frn = INVALID;
+ SmartBpGraph::BlueNode fbn = INVALID;
+ SmartBpGraph::Arc fa = INVALID;
+ SmartBpGraph::Edge fe = INVALID;
+
+ std::vector<SmartBpGraph::RedNode> frnv;
+ for (int i = 0; i < nn; ++i) {
+ SmartBpGraph::RedNode node = from.addRedNode();
+ frnv.push_back(node);
+ fnm[node] = i * i;
+ frnm[node] = i + i;
+ if (i == 0) {
+ fn = node;
+ frn = node;
+ }
+ }
+
+ std::vector<SmartBpGraph::BlueNode> fbnv;
+ for (int i = 0; i < nn; ++i) {
+ SmartBpGraph::BlueNode node = from.addBlueNode();
+ fbnv.push_back(node);
+ fnm[node] = i * i;
+ fbnm[node] = i + i;
+ if (i == 0) fbn = node;
+ }
+
+ for (int i = 0; i < nn; ++i) {
+ for (int j = 0; j < nn; ++j) {
+ SmartBpGraph::Edge edge = from.addEdge(frnv[i], fbnv[j]);
+ fem[edge] = i * i + j * j;
+ fam[from.direct(edge, true)] = i + j * j;
+ fam[from.direct(edge, false)] = i * i + j;
+ if (i == 0 && j == 0) fa = from.direct(edge, true);
+ if (i == 0 && j == 0) fe = edge;
+ }
+ }
+
+ // Test graph copy
+ GR to;
+ typename GR::template NodeMap<int> tnm(to);
+ typename GR::template RedNodeMap<int> trnm(to);
+ typename GR::template BlueNodeMap<int> tbnm(to);
+ typename GR::template ArcMap<int> tam(to);
+ typename GR::template EdgeMap<int> tem(to);
+ typename GR::Node tn;
+ typename GR::RedNode trn;
+ typename GR::BlueNode tbn;
+ typename GR::Arc ta;
+ typename GR::Edge te;
+
+ SmartBpGraph::NodeMap<typename GR::Node> nr(from);
+ SmartBpGraph::RedNodeMap<typename GR::RedNode> rnr(from);
+ SmartBpGraph::BlueNodeMap<typename GR::BlueNode> bnr(from);
+ SmartBpGraph::ArcMap<typename GR::Arc> ar(from);
+ SmartBpGraph::EdgeMap<typename GR::Edge> er(from);
+
+ typename GR::template NodeMap<SmartBpGraph::Node> ncr(to);
+ typename GR::template RedNodeMap<SmartBpGraph::RedNode> rncr(to);
+ typename GR::template BlueNodeMap<SmartBpGraph::BlueNode> bncr(to);
+ typename GR::template ArcMap<SmartBpGraph::Arc> acr(to);
+ typename GR::template EdgeMap<SmartBpGraph::Edge> ecr(to);
+
+ bpGraphCopy(from, to).
+ nodeMap(fnm, tnm).
+ redNodeMap(frnm, trnm).blueNodeMap(fbnm, tbnm).
+ arcMap(fam, tam).edgeMap(fem, tem).
+ nodeRef(nr).redRef(rnr).blueRef(bnr).
+ arcRef(ar).edgeRef(er).
+ nodeCrossRef(ncr).redCrossRef(rncr).blueCrossRef(bncr).
+ arcCrossRef(acr).edgeCrossRef(ecr).
+ node(fn, tn).redNode(frn, trn).blueNode(fbn, tbn).
+ arc(fa, ta).edge(fe, te).run();
+
+ check(countNodes(from) == countNodes(to), "Wrong copy.");
+ check(countRedNodes(from) == countRedNodes(to), "Wrong copy.");
+ check(countBlueNodes(from) == countBlueNodes(to), "Wrong copy.");
+ check(countEdges(from) == countEdges(to), "Wrong copy.");
+ check(countArcs(from) == countArcs(to), "Wrong copy.");
+
+ for (SmartBpGraph::NodeIt it(from); it != INVALID; ++it) {
+ check(ncr[nr[it]] == it, "Wrong copy.");
+ check(fnm[it] == tnm[nr[it]], "Wrong copy.");
+ }
+
+ for (SmartBpGraph::RedNodeIt it(from); it != INVALID; ++it) {
+ check(ncr[nr[it]] == it, "Wrong copy.");
+ check(fnm[it] == tnm[nr[it]], "Wrong copy.");
+ check(rnr[it] == nr[it], "Wrong copy.");
+ check(rncr[rnr[it]] == it, "Wrong copy.");
+ check(frnm[it] == trnm[rnr[it]], "Wrong copy.");
+ check(to.red(rnr[it]), "Wrong copy.");
+ }
+
+ for (SmartBpGraph::BlueNodeIt it(from); it != INVALID; ++it) {
+ check(ncr[nr[it]] == it, "Wrong copy.");
+ check(fnm[it] == tnm[nr[it]], "Wrong copy.");
+ check(bnr[it] == nr[it], "Wrong copy.");
+ check(bncr[bnr[it]] == it, "Wrong copy.");
+ check(fbnm[it] == tbnm[bnr[it]], "Wrong copy.");
+ check(to.blue(bnr[it]), "Wrong copy.");
+ }
+
+ for (SmartBpGraph::ArcIt it(from); it != INVALID; ++it) {
+ check(acr[ar[it]] == it, "Wrong copy.");
+ check(fam[it] == tam[ar[it]], "Wrong copy.");
+ check(nr[from.source(it)] == to.source(ar[it]), "Wrong copy.");
+ check(nr[from.target(it)] == to.target(ar[it]), "Wrong copy.");
+ }
+
+ for (SmartBpGraph::EdgeIt it(from); it != INVALID; ++it) {
+ check(ecr[er[it]] == it, "Wrong copy.");
+ check(fem[it] == tem[er[it]], "Wrong copy.");
+ check(nr[from.u(it)] == to.u(er[it]) || nr[from.u(it)] == to.v(er[it]),
+ "Wrong copy.");
+ check(nr[from.v(it)] == to.u(er[it]) || nr[from.v(it)] == to.v(er[it]),
+ "Wrong copy.");
+ check((from.u(it) != from.v(it)) == (to.u(er[it]) != to.v(er[it])),
+ "Wrong copy.");
+ }
+
+ for (typename GR::NodeIt it(to); it != INVALID; ++it) {
+ check(nr[ncr[it]] == it, "Wrong copy.");
+ }
+ for (typename GR::RedNodeIt it(to); it != INVALID; ++it) {
+ check(rncr[it] == ncr[it], "Wrong copy.");
+ check(rnr[rncr[it]] == it, "Wrong copy.");
+ }
+ for (typename GR::BlueNodeIt it(to); it != INVALID; ++it) {
+ check(bncr[it] == ncr[it], "Wrong copy.");
+ check(bnr[bncr[it]] == it, "Wrong copy.");
+ }
+ for (typename GR::ArcIt it(to); it != INVALID; ++it) {
+ check(ar[acr[it]] == it, "Wrong copy.");
+ }
+ for (typename GR::EdgeIt it(to); it != INVALID; ++it) {
+ check(er[ecr[it]] == it, "Wrong copy.");
+ }
+ check(tn == nr[fn], "Wrong copy.");
+ check(trn == rnr[frn], "Wrong copy.");
+ check(tbn == bnr[fbn], "Wrong copy.");
+ check(ta == ar[fa], "Wrong copy.");
+ check(te == er[fe], "Wrong copy.");
+
+ // Test repeated copy
+ bpGraphCopy(from, to).run();
+
+ check(countNodes(from) == countNodes(to), "Wrong copy.");
+ check(countRedNodes(from) == countRedNodes(to), "Wrong copy.");
+ check(countBlueNodes(from) == countBlueNodes(to), "Wrong copy.");
+ check(countEdges(from) == countEdges(to), "Wrong copy.");
+ check(countArcs(from) == countArcs(to), "Wrong copy.");
+}
+
+
+int main() {
+ digraph_copy_test<SmartDigraph>();
+ digraph_copy_test<ListDigraph>();
+ digraph_copy_test<StaticDigraph>();
+ graph_copy_test<SmartGraph>();
+ graph_copy_test<ListGraph>();
+ bpgraph_copy_test<SmartBpGraph>();
+ bpgraph_copy_test<ListBpGraph>();
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/graph_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/graph_test.cc
new file mode 100644
index 00000000000..283b02ef58a
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/graph_test.cc
@@ -0,0 +1,603 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/concepts/graph.h>
+#include <lemon/list_graph.h>
+#include <lemon/smart_graph.h>
+#include <lemon/full_graph.h>
+#include <lemon/grid_graph.h>
+#include <lemon/hypercube_graph.h>
+
+#include "test_tools.h"
+#include "graph_test.h"
+
+using namespace lemon;
+using namespace lemon::concepts;
+
+template <class Graph>
+void checkGraphBuild() {
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+ Graph G;
+ checkGraphNodeList(G, 0);
+ checkGraphEdgeList(G, 0);
+ checkGraphArcList(G, 0);
+
+ G.reserveNode(3);
+ G.reserveEdge(3);
+
+ Node
+ n1 = G.addNode(),
+ n2 = G.addNode(),
+ n3 = G.addNode();
+ checkGraphNodeList(G, 3);
+ checkGraphEdgeList(G, 0);
+ checkGraphArcList(G, 0);
+
+ Edge e1 = G.addEdge(n1, n2);
+ check((G.u(e1) == n1 && G.v(e1) == n2) || (G.u(e1) == n2 && G.v(e1) == n1),
+ "Wrong edge");
+
+ checkGraphNodeList(G, 3);
+ checkGraphEdgeList(G, 1);
+ checkGraphArcList(G, 2);
+
+ checkGraphIncEdgeArcLists(G, n1, 1);
+ checkGraphIncEdgeArcLists(G, n2, 1);
+ checkGraphIncEdgeArcLists(G, n3, 0);
+
+ checkGraphConEdgeList(G, 1);
+ checkGraphConArcList(G, 2);
+
+ Edge e2 = G.addEdge(n2, n1),
+ e3 = G.addEdge(n2, n3);
+ ::lemon::ignore_unused_variable_warning(e2,e3);
+
+ checkGraphNodeList(G, 3);
+ checkGraphEdgeList(G, 3);
+ checkGraphArcList(G, 6);
+
+ checkGraphIncEdgeArcLists(G, n1, 2);
+ checkGraphIncEdgeArcLists(G, n2, 3);
+ checkGraphIncEdgeArcLists(G, n3, 1);
+
+ checkGraphConEdgeList(G, 3);
+ checkGraphConArcList(G, 6);
+
+ checkArcDirections(G);
+
+ checkNodeIds(G);
+ checkArcIds(G);
+ checkEdgeIds(G);
+ checkGraphNodeMap(G);
+ checkGraphArcMap(G);
+ checkGraphEdgeMap(G);
+}
+
+template <class Graph>
+void checkGraphAlter() {
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+ Graph G;
+ Node n1 = G.addNode(), n2 = G.addNode(),
+ n3 = G.addNode(), n4 = G.addNode();
+ Edge e1 = G.addEdge(n1, n2), e2 = G.addEdge(n2, n1),
+ e3 = G.addEdge(n2, n3), e4 = G.addEdge(n1, n4),
+ e5 = G.addEdge(n4, n3);
+ ::lemon::ignore_unused_variable_warning(e1,e3,e4,e5);
+
+ checkGraphNodeList(G, 4);
+ checkGraphEdgeList(G, 5);
+ checkGraphArcList(G, 10);
+
+ // Check changeU() and changeV()
+ if (G.u(e2) == n2) {
+ G.changeU(e2, n3);
+ } else {
+ G.changeV(e2, n3);
+ }
+
+ checkGraphNodeList(G, 4);
+ checkGraphEdgeList(G, 5);
+ checkGraphArcList(G, 10);
+
+ checkGraphIncEdgeArcLists(G, n1, 3);
+ checkGraphIncEdgeArcLists(G, n2, 2);
+ checkGraphIncEdgeArcLists(G, n3, 3);
+ checkGraphIncEdgeArcLists(G, n4, 2);
+
+ checkGraphConEdgeList(G, 5);
+ checkGraphConArcList(G, 10);
+
+ if (G.u(e2) == n1) {
+ G.changeU(e2, n2);
+ } else {
+ G.changeV(e2, n2);
+ }
+
+ checkGraphNodeList(G, 4);
+ checkGraphEdgeList(G, 5);
+ checkGraphArcList(G, 10);
+
+ checkGraphIncEdgeArcLists(G, n1, 2);
+ checkGraphIncEdgeArcLists(G, n2, 3);
+ checkGraphIncEdgeArcLists(G, n3, 3);
+ checkGraphIncEdgeArcLists(G, n4, 2);
+
+ checkGraphConEdgeList(G, 5);
+ checkGraphConArcList(G, 10);
+
+ // Check contract()
+ G.contract(n1, n4, false);
+
+ checkGraphNodeList(G, 3);
+ checkGraphEdgeList(G, 5);
+ checkGraphArcList(G, 10);
+
+ checkGraphIncEdgeArcLists(G, n1, 4);
+ checkGraphIncEdgeArcLists(G, n2, 3);
+ checkGraphIncEdgeArcLists(G, n3, 3);
+
+ checkGraphConEdgeList(G, 5);
+ checkGraphConArcList(G, 10);
+
+ G.contract(n2, n3);
+
+ checkGraphNodeList(G, 2);
+ checkGraphEdgeList(G, 3);
+ checkGraphArcList(G, 6);
+
+ checkGraphIncEdgeArcLists(G, n1, 4);
+ checkGraphIncEdgeArcLists(G, n2, 2);
+
+ checkGraphConEdgeList(G, 3);
+ checkGraphConArcList(G, 6);
+}
+
+template <class Graph>
+void checkGraphErase() {
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+ Graph G;
+ Node n1 = G.addNode(), n2 = G.addNode(),
+ n3 = G.addNode(), n4 = G.addNode();
+ Edge e1 = G.addEdge(n1, n2), e2 = G.addEdge(n2, n1),
+ e3 = G.addEdge(n2, n3), e4 = G.addEdge(n1, n4),
+ e5 = G.addEdge(n4, n3);
+ ::lemon::ignore_unused_variable_warning(e1,e3,e4,e5);
+
+ // Check edge deletion
+ G.erase(e2);
+
+ checkGraphNodeList(G, 4);
+ checkGraphEdgeList(G, 4);
+ checkGraphArcList(G, 8);
+
+ checkGraphIncEdgeArcLists(G, n1, 2);
+ checkGraphIncEdgeArcLists(G, n2, 2);
+ checkGraphIncEdgeArcLists(G, n3, 2);
+ checkGraphIncEdgeArcLists(G, n4, 2);
+
+ checkGraphConEdgeList(G, 4);
+ checkGraphConArcList(G, 8);
+
+ // Check node deletion
+ G.erase(n3);
+
+ checkGraphNodeList(G, 3);
+ checkGraphEdgeList(G, 2);
+ checkGraphArcList(G, 4);
+
+ checkGraphIncEdgeArcLists(G, n1, 2);
+ checkGraphIncEdgeArcLists(G, n2, 1);
+ checkGraphIncEdgeArcLists(G, n4, 1);
+
+ checkGraphConEdgeList(G, 2);
+ checkGraphConArcList(G, 4);
+}
+
+
+template <class Graph>
+void checkGraphSnapshot() {
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+ Graph G;
+ Node n1 = G.addNode(), n2 = G.addNode(), n3 = G.addNode();
+ Edge e1 = G.addEdge(n1, n2), e2 = G.addEdge(n2, n1),
+ e3 = G.addEdge(n2, n3);
+ ::lemon::ignore_unused_variable_warning(e1,e2,e3);
+
+ checkGraphNodeList(G, 3);
+ checkGraphEdgeList(G, 3);
+ checkGraphArcList(G, 6);
+
+ typename Graph::Snapshot snapshot(G);
+
+ Node n = G.addNode();
+ G.addEdge(n3, n);
+ G.addEdge(n, n3);
+ G.addEdge(n3, n2);
+
+ checkGraphNodeList(G, 4);
+ checkGraphEdgeList(G, 6);
+ checkGraphArcList(G, 12);
+
+ snapshot.restore();
+
+ checkGraphNodeList(G, 3);
+ checkGraphEdgeList(G, 3);
+ checkGraphArcList(G, 6);
+
+ checkGraphIncEdgeArcLists(G, n1, 2);
+ checkGraphIncEdgeArcLists(G, n2, 3);
+ checkGraphIncEdgeArcLists(G, n3, 1);
+
+ checkGraphConEdgeList(G, 3);
+ checkGraphConArcList(G, 6);
+
+ checkNodeIds(G);
+ checkEdgeIds(G);
+ checkArcIds(G);
+ checkGraphNodeMap(G);
+ checkGraphEdgeMap(G);
+ checkGraphArcMap(G);
+
+ G.addNode();
+ snapshot.save(G);
+
+ G.addEdge(G.addNode(), G.addNode());
+
+ snapshot.restore();
+ snapshot.save(G);
+
+ checkGraphNodeList(G, 4);
+ checkGraphEdgeList(G, 3);
+ checkGraphArcList(G, 6);
+
+ G.addEdge(G.addNode(), G.addNode());
+
+ snapshot.restore();
+
+ checkGraphNodeList(G, 4);
+ checkGraphEdgeList(G, 3);
+ checkGraphArcList(G, 6);
+}
+
+void checkFullGraph(int num) {
+ typedef FullGraph Graph;
+ GRAPH_TYPEDEFS(Graph);
+
+ Graph G(num);
+ check(G.nodeNum() == num && G.edgeNum() == num * (num - 1) / 2,
+ "Wrong size");
+
+ G.resize(num);
+ check(G.nodeNum() == num && G.edgeNum() == num * (num - 1) / 2,
+ "Wrong size");
+
+ checkGraphNodeList(G, num);
+ checkGraphEdgeList(G, num * (num - 1) / 2);
+
+ for (NodeIt n(G); n != INVALID; ++n) {
+ checkGraphOutArcList(G, n, num - 1);
+ checkGraphInArcList(G, n, num - 1);
+ checkGraphIncEdgeList(G, n, num - 1);
+ }
+
+ checkGraphConArcList(G, num * (num - 1));
+ checkGraphConEdgeList(G, num * (num - 1) / 2);
+
+ checkArcDirections(G);
+
+ checkNodeIds(G);
+ checkArcIds(G);
+ checkEdgeIds(G);
+ checkGraphNodeMap(G);
+ checkGraphArcMap(G);
+ checkGraphEdgeMap(G);
+
+
+ for (int i = 0; i < G.nodeNum(); ++i) {
+ check(G.index(G(i)) == i, "Wrong index");
+ }
+
+ for (NodeIt u(G); u != INVALID; ++u) {
+ for (NodeIt v(G); v != INVALID; ++v) {
+ Edge e = G.edge(u, v);
+ Arc a = G.arc(u, v);
+ if (u == v) {
+ check(e == INVALID, "Wrong edge lookup");
+ check(a == INVALID, "Wrong arc lookup");
+ } else {
+ check((G.u(e) == u && G.v(e) == v) ||
+ (G.u(e) == v && G.v(e) == u), "Wrong edge lookup");
+ check(G.source(a) == u && G.target(a) == v, "Wrong arc lookup");
+ }
+ }
+ }
+}
+
+void checkConcepts() {
+ { // Checking graph components
+ checkConcept<BaseGraphComponent, BaseGraphComponent >();
+
+ checkConcept<IDableGraphComponent<>,
+ IDableGraphComponent<> >();
+
+ checkConcept<IterableGraphComponent<>,
+ IterableGraphComponent<> >();
+
+ checkConcept<MappableGraphComponent<>,
+ MappableGraphComponent<> >();
+ }
+ { // Checking skeleton graph
+ checkConcept<Graph, Graph>();
+ }
+ { // Checking ListGraph
+ checkConcept<Graph, ListGraph>();
+ checkConcept<AlterableGraphComponent<>, ListGraph>();
+ checkConcept<ExtendableGraphComponent<>, ListGraph>();
+ checkConcept<ClearableGraphComponent<>, ListGraph>();
+ checkConcept<ErasableGraphComponent<>, ListGraph>();
+ }
+ { // Checking SmartGraph
+ checkConcept<Graph, SmartGraph>();
+ checkConcept<AlterableGraphComponent<>, SmartGraph>();
+ checkConcept<ExtendableGraphComponent<>, SmartGraph>();
+ checkConcept<ClearableGraphComponent<>, SmartGraph>();
+ }
+ { // Checking FullGraph
+ checkConcept<Graph, FullGraph>();
+ }
+ { // Checking GridGraph
+ checkConcept<Graph, GridGraph>();
+ }
+ { // Checking HypercubeGraph
+ checkConcept<Graph, HypercubeGraph>();
+ }
+}
+
+template <typename Graph>
+void checkGraphValidity() {
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+ Graph g;
+
+ Node
+ n1 = g.addNode(),
+ n2 = g.addNode(),
+ n3 = g.addNode();
+
+ Edge
+ e1 = g.addEdge(n1, n2),
+ e2 = g.addEdge(n2, n3);
+ ::lemon::ignore_unused_variable_warning(e2);
+
+ check(g.valid(n1), "Wrong validity check");
+ check(g.valid(e1), "Wrong validity check");
+ check(g.valid(g.direct(e1, true)), "Wrong validity check");
+
+ check(!g.valid(g.nodeFromId(-1)), "Wrong validity check");
+ check(!g.valid(g.edgeFromId(-1)), "Wrong validity check");
+ check(!g.valid(g.arcFromId(-1)), "Wrong validity check");
+}
+
+template <typename Graph>
+void checkGraphValidityErase() {
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+ Graph g;
+
+ Node
+ n1 = g.addNode(),
+ n2 = g.addNode(),
+ n3 = g.addNode();
+
+ Edge
+ e1 = g.addEdge(n1, n2),
+ e2 = g.addEdge(n2, n3);
+
+ check(g.valid(n1), "Wrong validity check");
+ check(g.valid(e1), "Wrong validity check");
+ check(g.valid(g.direct(e1, true)), "Wrong validity check");
+
+ g.erase(n1);
+
+ check(!g.valid(n1), "Wrong validity check");
+ check(g.valid(n2), "Wrong validity check");
+ check(g.valid(n3), "Wrong validity check");
+ check(!g.valid(e1), "Wrong validity check");
+ check(g.valid(e2), "Wrong validity check");
+
+ check(!g.valid(g.nodeFromId(-1)), "Wrong validity check");
+ check(!g.valid(g.edgeFromId(-1)), "Wrong validity check");
+ check(!g.valid(g.arcFromId(-1)), "Wrong validity check");
+}
+
+void checkGridGraph(int width, int height) {
+ typedef GridGraph Graph;
+ GRAPH_TYPEDEFS(Graph);
+ Graph G(width, height);
+
+ check(G.width() == width, "Wrong column number");
+ check(G.height() == height, "Wrong row number");
+
+ G.resize(width, height);
+ check(G.width() == width, "Wrong column number");
+ check(G.height() == height, "Wrong row number");
+
+ for (int i = 0; i < width; ++i) {
+ for (int j = 0; j < height; ++j) {
+ check(G.col(G(i, j)) == i, "Wrong column");
+ check(G.row(G(i, j)) == j, "Wrong row");
+ check(G.pos(G(i, j)).x == i, "Wrong column");
+ check(G.pos(G(i, j)).y == j, "Wrong row");
+ }
+ }
+
+ for (int j = 0; j < height; ++j) {
+ for (int i = 0; i < width - 1; ++i) {
+ check(G.source(G.right(G(i, j))) == G(i, j), "Wrong right");
+ check(G.target(G.right(G(i, j))) == G(i + 1, j), "Wrong right");
+ }
+ check(G.right(G(width - 1, j)) == INVALID, "Wrong right");
+ }
+
+ for (int j = 0; j < height; ++j) {
+ for (int i = 1; i < width; ++i) {
+ check(G.source(G.left(G(i, j))) == G(i, j), "Wrong left");
+ check(G.target(G.left(G(i, j))) == G(i - 1, j), "Wrong left");
+ }
+ check(G.left(G(0, j)) == INVALID, "Wrong left");
+ }
+
+ for (int i = 0; i < width; ++i) {
+ for (int j = 0; j < height - 1; ++j) {
+ check(G.source(G.up(G(i, j))) == G(i, j), "Wrong up");
+ check(G.target(G.up(G(i, j))) == G(i, j + 1), "Wrong up");
+ }
+ check(G.up(G(i, height - 1)) == INVALID, "Wrong up");
+ }
+
+ for (int i = 0; i < width; ++i) {
+ for (int j = 1; j < height; ++j) {
+ check(G.source(G.down(G(i, j))) == G(i, j), "Wrong down");
+ check(G.target(G.down(G(i, j))) == G(i, j - 1), "Wrong down");
+ }
+ check(G.down(G(i, 0)) == INVALID, "Wrong down");
+ }
+
+ checkGraphNodeList(G, width * height);
+ checkGraphEdgeList(G, width * (height - 1) + (width - 1) * height);
+ checkGraphArcList(G, 2 * (width * (height - 1) + (width - 1) * height));
+
+ for (NodeIt n(G); n != INVALID; ++n) {
+ int nb = 4;
+ if (G.col(n) == 0) --nb;
+ if (G.col(n) == width - 1) --nb;
+ if (G.row(n) == 0) --nb;
+ if (G.row(n) == height - 1) --nb;
+
+ checkGraphOutArcList(G, n, nb);
+ checkGraphInArcList(G, n, nb);
+ checkGraphIncEdgeList(G, n, nb);
+ }
+
+ checkArcDirections(G);
+
+ checkGraphConArcList(G, 2 * (width * (height - 1) + (width - 1) * height));
+ checkGraphConEdgeList(G, width * (height - 1) + (width - 1) * height);
+
+ checkNodeIds(G);
+ checkArcIds(G);
+ checkEdgeIds(G);
+ checkGraphNodeMap(G);
+ checkGraphArcMap(G);
+ checkGraphEdgeMap(G);
+
+}
+
+void checkHypercubeGraph(int dim) {
+ GRAPH_TYPEDEFS(HypercubeGraph);
+
+ HypercubeGraph G(dim);
+ check(G.dimension() == dim, "Wrong dimension");
+
+ G.resize(dim);
+ check(G.dimension() == dim, "Wrong dimension");
+
+ checkGraphNodeList(G, 1 << dim);
+ checkGraphEdgeList(G, dim * (1 << (dim-1)));
+ checkGraphArcList(G, dim * (1 << dim));
+
+ Node n = G.nodeFromId(dim);
+ ::lemon::ignore_unused_variable_warning(n);
+
+ for (NodeIt n(G); n != INVALID; ++n) {
+ checkGraphIncEdgeList(G, n, dim);
+ for (IncEdgeIt e(G, n); e != INVALID; ++e) {
+ check( (G.u(e) == n &&
+ G.id(G.v(e)) == (G.id(n) ^ (1 << G.dimension(e)))) ||
+ (G.v(e) == n &&
+ G.id(G.u(e)) == (G.id(n) ^ (1 << G.dimension(e)))),
+ "Wrong edge or wrong dimension");
+ }
+
+ checkGraphOutArcList(G, n, dim);
+ for (OutArcIt a(G, n); a != INVALID; ++a) {
+ check(G.source(a) == n &&
+ G.id(G.target(a)) == (G.id(n) ^ (1 << G.dimension(a))),
+ "Wrong arc or wrong dimension");
+ }
+
+ checkGraphInArcList(G, n, dim);
+ for (InArcIt a(G, n); a != INVALID; ++a) {
+ check(G.target(a) == n &&
+ G.id(G.source(a)) == (G.id(n) ^ (1 << G.dimension(a))),
+ "Wrong arc or wrong dimension");
+ }
+ }
+
+ checkGraphConArcList(G, (1 << dim) * dim);
+ checkGraphConEdgeList(G, dim * (1 << (dim-1)));
+
+ checkArcDirections(G);
+
+ checkNodeIds(G);
+ checkArcIds(G);
+ checkEdgeIds(G);
+ checkGraphNodeMap(G);
+ checkGraphArcMap(G);
+ checkGraphEdgeMap(G);
+}
+
+void checkGraphs() {
+ { // Checking ListGraph
+ checkGraphBuild<ListGraph>();
+ checkGraphAlter<ListGraph>();
+ checkGraphErase<ListGraph>();
+ checkGraphSnapshot<ListGraph>();
+ checkGraphValidityErase<ListGraph>();
+ }
+ { // Checking SmartGraph
+ checkGraphBuild<SmartGraph>();
+ checkGraphSnapshot<SmartGraph>();
+ checkGraphValidity<SmartGraph>();
+ }
+ { // Checking FullGraph
+ checkFullGraph(7);
+ checkFullGraph(8);
+ }
+ { // Checking GridGraph
+ checkGridGraph(5, 8);
+ checkGridGraph(8, 5);
+ checkGridGraph(5, 5);
+ checkGridGraph(0, 0);
+ checkGridGraph(1, 1);
+ }
+ { // Checking HypercubeGraph
+ checkHypercubeGraph(1);
+ checkHypercubeGraph(2);
+ checkHypercubeGraph(3);
+ checkHypercubeGraph(4);
+ }
+}
+
+int main() {
+ checkConcepts();
+ checkGraphs();
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/graph_test.h b/extern/quadriflow/3rd/lemon-1.3.1/test/graph_test.h
new file mode 100644
index 00000000000..70558b768e8
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/graph_test.h
@@ -0,0 +1,421 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_TEST_GRAPH_TEST_H
+#define LEMON_TEST_GRAPH_TEST_H
+
+#include <set>
+
+#include <lemon/core.h>
+#include <lemon/maps.h>
+
+#include "test_tools.h"
+
+namespace lemon {
+
+ template<class Graph>
+ void checkGraphNodeList(const Graph &G, int cnt)
+ {
+ typename Graph::NodeIt n(G);
+ for(int i=0;i<cnt;i++) {
+ check(n!=INVALID,"Wrong Node list linking.");
+ ++n;
+ }
+ check(n==INVALID,"Wrong Node list linking.");
+ check(countNodes(G)==cnt,"Wrong Node number.");
+ }
+
+ template<class Graph>
+ void checkGraphRedNodeList(const Graph &G, int cnt)
+ {
+ typename Graph::RedNodeIt n(G);
+ for(int i=0;i<cnt;i++) {
+ check(n!=INVALID,"Wrong red Node list linking.");
+ check(G.red(n),"Wrong node set check.");
+ check(!G.blue(n),"Wrong node set check.");
+ typename Graph::Node nn = n;
+ check(G.asRedNodeUnsafe(nn) == n,"Wrong node conversion.");
+ check(G.asRedNode(nn) == n,"Wrong node conversion.");
+ check(G.asBlueNode(nn) == INVALID,"Wrong node conversion.");
+ ++n;
+ }
+ check(n==INVALID,"Wrong red Node list linking.");
+ check(countRedNodes(G)==cnt,"Wrong red Node number.");
+ }
+
+ template<class Graph>
+ void checkGraphBlueNodeList(const Graph &G, int cnt)
+ {
+ typename Graph::BlueNodeIt n(G);
+ for(int i=0;i<cnt;i++) {
+ check(n!=INVALID,"Wrong blue Node list linking.");
+ check(G.blue(n),"Wrong node set check.");
+ check(!G.red(n),"Wrong node set check.");
+ typename Graph::Node nn = n;
+ check(G.asBlueNodeUnsafe(nn) == n,"Wrong node conversion.");
+ check(G.asBlueNode(nn) == n,"Wrong node conversion.");
+ check(G.asRedNode(nn) == INVALID,"Wrong node conversion.");
+ ++n;
+ }
+ check(n==INVALID,"Wrong blue Node list linking.");
+ check(countBlueNodes(G)==cnt,"Wrong blue Node number.");
+ }
+
+ template<class Graph>
+ void checkGraphArcList(const Graph &G, int cnt)
+ {
+ typename Graph::ArcIt e(G);
+ for(int i=0;i<cnt;i++) {
+ check(e!=INVALID,"Wrong Arc list linking.");
+ check(G.oppositeNode(G.source(e), e) == G.target(e),
+ "Wrong opposite node");
+ check(G.oppositeNode(G.target(e), e) == G.source(e),
+ "Wrong opposite node");
+ ++e;
+ }
+ check(e==INVALID,"Wrong Arc list linking.");
+ check(countArcs(G)==cnt,"Wrong Arc number.");
+ }
+
+ template<class Graph>
+ void checkGraphOutArcList(const Graph &G, typename Graph::Node n, int cnt)
+ {
+ typename Graph::OutArcIt e(G,n);
+ for(int i=0;i<cnt;i++) {
+ check(e!=INVALID,"Wrong OutArc list linking.");
+ check(n==G.source(e),"Wrong OutArc list linking.");
+ check(n==G.baseNode(e),"Wrong OutArc list linking.");
+ check(G.target(e)==G.runningNode(e),"Wrong OutArc list linking.");
+ ++e;
+ }
+ check(e==INVALID,"Wrong OutArc list linking.");
+ check(countOutArcs(G,n)==cnt,"Wrong OutArc number.");
+ }
+
+ template<class Graph>
+ void checkGraphInArcList(const Graph &G, typename Graph::Node n, int cnt)
+ {
+ typename Graph::InArcIt e(G,n);
+ for(int i=0;i<cnt;i++) {
+ check(e!=INVALID,"Wrong InArc list linking.");
+ check(n==G.target(e),"Wrong InArc list linking.");
+ check(n==G.baseNode(e),"Wrong OutArc list linking.");
+ check(G.source(e)==G.runningNode(e),"Wrong OutArc list linking.");
+ ++e;
+ }
+ check(e==INVALID,"Wrong InArc list linking.");
+ check(countInArcs(G,n)==cnt,"Wrong InArc number.");
+ }
+
+ template<class Graph>
+ void checkGraphEdgeList(const Graph &G, int cnt)
+ {
+ typename Graph::EdgeIt e(G);
+ for(int i=0;i<cnt;i++) {
+ check(e!=INVALID,"Wrong Edge list linking.");
+ check(G.oppositeNode(G.u(e), e) == G.v(e), "Wrong opposite node");
+ check(G.oppositeNode(G.v(e), e) == G.u(e), "Wrong opposite node");
+ ++e;
+ }
+ check(e==INVALID,"Wrong Edge list linking.");
+ check(countEdges(G)==cnt,"Wrong Edge number.");
+ }
+
+ template<class Graph>
+ void checkGraphIncEdgeList(const Graph &G, typename Graph::Node n, int cnt)
+ {
+ typename Graph::IncEdgeIt e(G,n);
+ for(int i=0;i<cnt;i++) {
+ check(e!=INVALID,"Wrong IncEdge list linking.");
+ check(n==G.u(e) || n==G.v(e),"Wrong IncEdge list linking.");
+ check(n==G.baseNode(e),"Wrong OutArc list linking.");
+ check(G.u(e)==G.runningNode(e) || G.v(e)==G.runningNode(e),
+ "Wrong OutArc list linking.");
+ ++e;
+ }
+ check(e==INVALID,"Wrong IncEdge list linking.");
+ check(countIncEdges(G,n)==cnt,"Wrong IncEdge number.");
+ }
+
+ template <class Graph>
+ void checkGraphIncEdgeArcLists(const Graph &G, typename Graph::Node n,
+ int cnt)
+ {
+ checkGraphIncEdgeList(G, n, cnt);
+ checkGraphOutArcList(G, n, cnt);
+ checkGraphInArcList(G, n, cnt);
+ }
+
+ template <class Graph>
+ void checkGraphConArcList(const Graph &G, int cnt) {
+ int i = 0;
+ for (typename Graph::NodeIt u(G); u != INVALID; ++u) {
+ for (typename Graph::NodeIt v(G); v != INVALID; ++v) {
+ for (ConArcIt<Graph> a(G, u, v); a != INVALID; ++a) {
+ check(G.source(a) == u, "Wrong iterator.");
+ check(G.target(a) == v, "Wrong iterator.");
+ ++i;
+ }
+ }
+ }
+ check(cnt == i, "Wrong iterator.");
+ }
+
+ template <class Graph>
+ void checkGraphConEdgeList(const Graph &G, int cnt) {
+ int i = 0;
+ for (typename Graph::NodeIt u(G); u != INVALID; ++u) {
+ for (typename Graph::NodeIt v(G); v != INVALID; ++v) {
+ for (ConEdgeIt<Graph> e(G, u, v); e != INVALID; ++e) {
+ check((G.u(e) == u && G.v(e) == v) ||
+ (G.u(e) == v && G.v(e) == u), "Wrong iterator.");
+ i += u == v ? 2 : 1;
+ }
+ }
+ }
+ check(2 * cnt == i, "Wrong iterator.");
+ }
+
+ template <typename Graph>
+ void checkArcDirections(const Graph& G) {
+ for (typename Graph::ArcIt a(G); a != INVALID; ++a) {
+ check(G.source(a) == G.target(G.oppositeArc(a)), "Wrong direction");
+ check(G.target(a) == G.source(G.oppositeArc(a)), "Wrong direction");
+ check(G.direct(a, G.direction(a)) == a, "Wrong direction");
+ }
+ }
+
+ template <typename Graph>
+ void checkNodeIds(const Graph& G) {
+ typedef typename Graph::Node Node;
+ std::set<int> values;
+ for (typename Graph::NodeIt n(G); n != INVALID; ++n) {
+ check(G.nodeFromId(G.id(n)) == n, "Wrong id");
+ check(values.find(G.id(n)) == values.end(), "Wrong id");
+ check(G.id(n) <= G.maxNodeId(), "Wrong maximum id");
+ values.insert(G.id(n));
+ }
+ check(G.maxId(Node()) <= G.maxNodeId(), "Wrong maximum id");
+ }
+
+ template <typename Graph>
+ void checkRedNodeIds(const Graph& G) {
+ typedef typename Graph::RedNode RedNode;
+ std::set<int> values;
+ for (typename Graph::RedNodeIt n(G); n != INVALID; ++n) {
+ check(G.red(n), "Wrong partition");
+ check(values.find(G.id(n)) == values.end(), "Wrong id");
+ check(G.id(n) <= G.maxRedId(), "Wrong maximum id");
+ values.insert(G.id(n));
+ }
+ check(G.maxId(RedNode()) == G.maxRedId(), "Wrong maximum id");
+ }
+
+ template <typename Graph>
+ void checkBlueNodeIds(const Graph& G) {
+ typedef typename Graph::BlueNode BlueNode;
+ std::set<int> values;
+ for (typename Graph::BlueNodeIt n(G); n != INVALID; ++n) {
+ check(G.blue(n), "Wrong partition");
+ check(values.find(G.id(n)) == values.end(), "Wrong id");
+ check(G.id(n) <= G.maxBlueId(), "Wrong maximum id");
+ values.insert(G.id(n));
+ }
+ check(G.maxId(BlueNode()) == G.maxBlueId(), "Wrong maximum id");
+ }
+
+ template <typename Graph>
+ void checkArcIds(const Graph& G) {
+ typedef typename Graph::Arc Arc;
+ std::set<int> values;
+ for (typename Graph::ArcIt a(G); a != INVALID; ++a) {
+ check(G.arcFromId(G.id(a)) == a, "Wrong id");
+ check(values.find(G.id(a)) == values.end(), "Wrong id");
+ check(G.id(a) <= G.maxArcId(), "Wrong maximum id");
+ values.insert(G.id(a));
+ }
+ check(G.maxId(Arc()) <= G.maxArcId(), "Wrong maximum id");
+ }
+
+ template <typename Graph>
+ void checkEdgeIds(const Graph& G) {
+ typedef typename Graph::Edge Edge;
+ std::set<int> values;
+ for (typename Graph::EdgeIt e(G); e != INVALID; ++e) {
+ check(G.edgeFromId(G.id(e)) == e, "Wrong id");
+ check(values.find(G.id(e)) == values.end(), "Wrong id");
+ check(G.id(e) <= G.maxEdgeId(), "Wrong maximum id");
+ values.insert(G.id(e));
+ }
+ check(G.maxId(Edge()) <= G.maxEdgeId(), "Wrong maximum id");
+ }
+
+ template <typename Graph>
+ void checkGraphNodeMap(const Graph& G) {
+ typedef typename Graph::Node Node;
+ typedef typename Graph::NodeIt NodeIt;
+
+ typedef typename Graph::template NodeMap<int> IntNodeMap;
+ IntNodeMap map(G, 42);
+ for (NodeIt it(G); it != INVALID; ++it) {
+ check(map[it] == 42, "Wrong map constructor.");
+ }
+ int s = 0;
+ for (NodeIt it(G); it != INVALID; ++it) {
+ map[it] = 0;
+ check(map[it] == 0, "Wrong operator[].");
+ map.set(it, s);
+ check(map[it] == s, "Wrong set.");
+ ++s;
+ }
+ s = s * (s - 1) / 2;
+ for (NodeIt it(G); it != INVALID; ++it) {
+ s -= map[it];
+ }
+ check(s == 0, "Wrong sum.");
+
+ // map = constMap<Node>(12);
+ // for (NodeIt it(G); it != INVALID; ++it) {
+ // check(map[it] == 12, "Wrong operator[].");
+ // }
+ }
+
+ template <typename Graph>
+ void checkGraphRedNodeMap(const Graph& G) {
+ typedef typename Graph::Node Node;
+ typedef typename Graph::RedNodeIt RedNodeIt;
+
+ typedef typename Graph::template RedNodeMap<int> IntRedNodeMap;
+ IntRedNodeMap map(G, 42);
+ for (RedNodeIt it(G); it != INVALID; ++it) {
+ check(map[it] == 42, "Wrong map constructor.");
+ }
+ int s = 0;
+ for (RedNodeIt it(G); it != INVALID; ++it) {
+ map[it] = 0;
+ check(map[it] == 0, "Wrong operator[].");
+ map.set(it, s);
+ check(map[it] == s, "Wrong set.");
+ ++s;
+ }
+ s = s * (s - 1) / 2;
+ for (RedNodeIt it(G); it != INVALID; ++it) {
+ s -= map[it];
+ }
+ check(s == 0, "Wrong sum.");
+
+ // map = constMap<Node>(12);
+ // for (NodeIt it(G); it != INVALID; ++it) {
+ // check(map[it] == 12, "Wrong operator[].");
+ // }
+ }
+
+ template <typename Graph>
+ void checkGraphBlueNodeMap(const Graph& G) {
+ typedef typename Graph::Node Node;
+ typedef typename Graph::BlueNodeIt BlueNodeIt;
+
+ typedef typename Graph::template BlueNodeMap<int> IntBlueNodeMap;
+ IntBlueNodeMap map(G, 42);
+ for (BlueNodeIt it(G); it != INVALID; ++it) {
+ check(map[it] == 42, "Wrong map constructor.");
+ }
+ int s = 0;
+ for (BlueNodeIt it(G); it != INVALID; ++it) {
+ map[it] = 0;
+ check(map[it] == 0, "Wrong operator[].");
+ map.set(it, s);
+ check(map[it] == s, "Wrong set.");
+ ++s;
+ }
+ s = s * (s - 1) / 2;
+ for (BlueNodeIt it(G); it != INVALID; ++it) {
+ s -= map[it];
+ }
+ check(s == 0, "Wrong sum.");
+
+ // map = constMap<Node>(12);
+ // for (NodeIt it(G); it != INVALID; ++it) {
+ // check(map[it] == 12, "Wrong operator[].");
+ // }
+ }
+
+ template <typename Graph>
+ void checkGraphArcMap(const Graph& G) {
+ typedef typename Graph::Arc Arc;
+ typedef typename Graph::ArcIt ArcIt;
+
+ typedef typename Graph::template ArcMap<int> IntArcMap;
+ IntArcMap map(G, 42);
+ for (ArcIt it(G); it != INVALID; ++it) {
+ check(map[it] == 42, "Wrong map constructor.");
+ }
+ int s = 0;
+ for (ArcIt it(G); it != INVALID; ++it) {
+ map[it] = 0;
+ check(map[it] == 0, "Wrong operator[].");
+ map.set(it, s);
+ check(map[it] == s, "Wrong set.");
+ ++s;
+ }
+ s = s * (s - 1) / 2;
+ for (ArcIt it(G); it != INVALID; ++it) {
+ s -= map[it];
+ }
+ check(s == 0, "Wrong sum.");
+
+ // map = constMap<Arc>(12);
+ // for (ArcIt it(G); it != INVALID; ++it) {
+ // check(map[it] == 12, "Wrong operator[].");
+ // }
+ }
+
+ template <typename Graph>
+ void checkGraphEdgeMap(const Graph& G) {
+ typedef typename Graph::Edge Edge;
+ typedef typename Graph::EdgeIt EdgeIt;
+
+ typedef typename Graph::template EdgeMap<int> IntEdgeMap;
+ IntEdgeMap map(G, 42);
+ for (EdgeIt it(G); it != INVALID; ++it) {
+ check(map[it] == 42, "Wrong map constructor.");
+ }
+ int s = 0;
+ for (EdgeIt it(G); it != INVALID; ++it) {
+ map[it] = 0;
+ check(map[it] == 0, "Wrong operator[].");
+ map.set(it, s);
+ check(map[it] == s, "Wrong set.");
+ ++s;
+ }
+ s = s * (s - 1) / 2;
+ for (EdgeIt it(G); it != INVALID; ++it) {
+ s -= map[it];
+ }
+ check(s == 0, "Wrong sum.");
+
+ // map = constMap<Edge>(12);
+ // for (EdgeIt it(G); it != INVALID; ++it) {
+ // check(map[it] == 12, "Wrong operator[].");
+ // }
+ }
+
+
+} //namespace lemon
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/graph_utils_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/graph_utils_test.cc
new file mode 100644
index 00000000000..19a934a235a
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/graph_utils_test.cc
@@ -0,0 +1,217 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <cstdlib>
+#include <ctime>
+
+#include <lemon/random.h>
+#include <lemon/list_graph.h>
+#include <lemon/smart_graph.h>
+#include <lemon/maps.h>
+
+#include "graph_test.h"
+#include "test_tools.h"
+
+using namespace lemon;
+
+template <typename Digraph>
+void checkFindArcs() {
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+
+ {
+ Digraph digraph;
+ for (int i = 0; i < 10; ++i) {
+ digraph.addNode();
+ }
+ RangeIdMap<Digraph, Node> nodes(digraph);
+ typename RangeIdMap<Digraph, Node>::InverseMap invNodes(nodes);
+ for (int i = 0; i < 100; ++i) {
+ int src = rnd[invNodes.size()];
+ int trg = rnd[invNodes.size()];
+ digraph.addArc(invNodes[src], invNodes[trg]);
+ }
+ typename Digraph::template ArcMap<bool> found(digraph, false);
+ RangeIdMap<Digraph, Arc> arcs(digraph);
+ for (NodeIt src(digraph); src != INVALID; ++src) {
+ for (NodeIt trg(digraph); trg != INVALID; ++trg) {
+ for (ConArcIt<Digraph> con(digraph, src, trg); con != INVALID; ++con) {
+ check(digraph.source(con) == src, "Wrong source.");
+ check(digraph.target(con) == trg, "Wrong target.");
+ check(found[con] == false, "The arc found already.");
+ found[con] = true;
+ }
+ }
+ }
+ for (ArcIt it(digraph); it != INVALID; ++it) {
+ check(found[it] == true, "The arc is not found.");
+ }
+ }
+
+ {
+ int num = 5;
+ Digraph fg;
+ std::vector<Node> nodes;
+ for (int i = 0; i < num; ++i) {
+ nodes.push_back(fg.addNode());
+ }
+ for (int i = 0; i < num * num; ++i) {
+ fg.addArc(nodes[i / num], nodes[i % num]);
+ }
+ check(countNodes(fg) == num, "Wrong node number.");
+ check(countArcs(fg) == num*num, "Wrong arc number.");
+ for (NodeIt src(fg); src != INVALID; ++src) {
+ for (NodeIt trg(fg); trg != INVALID; ++trg) {
+ ConArcIt<Digraph> con(fg, src, trg);
+ check(con != INVALID, "There is no connecting arc.");
+ check(fg.source(con) == src, "Wrong source.");
+ check(fg.target(con) == trg, "Wrong target.");
+ check(++con == INVALID, "There is more connecting arc.");
+ }
+ }
+ ArcLookUp<Digraph> al1(fg);
+ DynArcLookUp<Digraph> al2(fg);
+ AllArcLookUp<Digraph> al3(fg);
+ for (NodeIt src(fg); src != INVALID; ++src) {
+ for (NodeIt trg(fg); trg != INVALID; ++trg) {
+ Arc con1 = al1(src, trg);
+ Arc con2 = al2(src, trg);
+ Arc con3 = al3(src, trg);
+ Arc con4 = findArc(fg, src, trg);
+ check(con1 == con2 && con2 == con3 && con3 == con4,
+ "Different results.")
+ check(con1 != INVALID, "There is no connecting arc.");
+ check(fg.source(con1) == src, "Wrong source.");
+ check(fg.target(con1) == trg, "Wrong target.");
+ check(al3(src, trg, con3) == INVALID,
+ "There is more connecting arc.");
+ check(findArc(fg, src, trg, con4) == INVALID,
+ "There is more connecting arc.");
+ }
+ }
+ }
+}
+
+template <typename Graph>
+void checkFindEdges() {
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+ Graph graph;
+ for (int i = 0; i < 10; ++i) {
+ graph.addNode();
+ }
+ RangeIdMap<Graph, Node> nodes(graph);
+ typename RangeIdMap<Graph, Node>::InverseMap invNodes(nodes);
+ for (int i = 0; i < 100; ++i) {
+ int src = rnd[invNodes.size()];
+ int trg = rnd[invNodes.size()];
+ graph.addEdge(invNodes[src], invNodes[trg]);
+ }
+ typename Graph::template EdgeMap<int> found(graph, 0);
+ RangeIdMap<Graph, Edge> edges(graph);
+ for (NodeIt src(graph); src != INVALID; ++src) {
+ for (NodeIt trg(graph); trg != INVALID; ++trg) {
+ for (ConEdgeIt<Graph> con(graph, src, trg); con != INVALID; ++con) {
+ check( (graph.u(con) == src && graph.v(con) == trg) ||
+ (graph.v(con) == src && graph.u(con) == trg),
+ "Wrong end nodes.");
+ ++found[con];
+ check(found[con] <= 2, "The edge found more than twice.");
+ }
+ }
+ }
+ for (EdgeIt it(graph); it != INVALID; ++it) {
+ check( (graph.u(it) != graph.v(it) && found[it] == 2) ||
+ (graph.u(it) == graph.v(it) && found[it] == 1),
+ "The edge is not found correctly.");
+ }
+}
+
+template <class Digraph>
+void checkDeg()
+{
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+
+ const int nodeNum = 10;
+ const int arcNum = 100;
+ Digraph digraph;
+ InDegMap<Digraph> inDeg(digraph);
+ OutDegMap<Digraph> outDeg(digraph);
+ std::vector<Node> nodes(nodeNum);
+ for (int i = 0; i < nodeNum; ++i) {
+ nodes[i] = digraph.addNode();
+ }
+ std::vector<Arc> arcs(arcNum);
+ for (int i = 0; i < arcNum; ++i) {
+ arcs[i] = digraph.addArc(nodes[rnd[nodeNum]], nodes[rnd[nodeNum]]);
+ }
+ for (int i = 0; i < nodeNum; ++i) {
+ check(inDeg[nodes[i]] == countInArcs(digraph, nodes[i]),
+ "Wrong in degree map");
+ }
+ for (int i = 0; i < nodeNum; ++i) {
+ check(outDeg[nodes[i]] == countOutArcs(digraph, nodes[i]),
+ "Wrong out degree map");
+ }
+}
+
+template <class Digraph>
+void checkSnapDeg()
+{
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+
+ Digraph g;
+ Node n1=g.addNode();
+ Node n2=g.addNode();
+
+ InDegMap<Digraph> ind(g);
+
+ g.addArc(n1,n2);
+
+ typename Digraph::Snapshot snap(g);
+
+ OutDegMap<Digraph> outd(g);
+
+ check(ind[n1]==0 && ind[n2]==1, "Wrong InDegMap value.");
+ check(outd[n1]==1 && outd[n2]==0, "Wrong OutDegMap value.");
+
+ g.addArc(n1,n2);
+ g.addArc(n2,n1);
+
+ check(ind[n1]==1 && ind[n2]==2, "Wrong InDegMap value.");
+ check(outd[n1]==2 && outd[n2]==1, "Wrong OutDegMap value.");
+
+ snap.restore();
+
+ check(ind[n1]==0 && ind[n2]==1, "Wrong InDegMap value.");
+ check(outd[n1]==1 && outd[n2]==0, "Wrong OutDegMap value.");
+}
+
+int main() {
+ // Checking ConArcIt, ConEdgeIt, ArcLookUp, AllArcLookUp, and DynArcLookUp
+ checkFindArcs<ListDigraph>();
+ checkFindArcs<SmartDigraph>();
+ checkFindEdges<ListGraph>();
+ checkFindEdges<SmartGraph>();
+
+ // Checking In/OutDegMap (and Snapshot feature)
+ checkDeg<ListDigraph>();
+ checkDeg<SmartDigraph>();
+ checkSnapDeg<ListDigraph>();
+ checkSnapDeg<SmartDigraph>();
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/hao_orlin_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/hao_orlin_test.cc
new file mode 100644
index 00000000000..c245cb7a727
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/hao_orlin_test.cc
@@ -0,0 +1,164 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <sstream>
+
+#include <lemon/smart_graph.h>
+#include <lemon/adaptors.h>
+#include <lemon/concepts/digraph.h>
+#include <lemon/concepts/maps.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/hao_orlin.h>
+
+#include "test_tools.h"
+
+using namespace lemon;
+using namespace std;
+
+const std::string lgf =
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "@edges\n"
+ " cap1 cap2 cap3\n"
+ "0 1 1 1 1 \n"
+ "0 2 2 2 4 \n"
+ "1 2 4 4 4 \n"
+ "3 4 1 1 1 \n"
+ "3 5 2 2 4 \n"
+ "4 5 4 4 4 \n"
+ "5 4 4 4 4 \n"
+ "2 3 1 6 6 \n"
+ "4 0 1 6 6 \n";
+
+void checkHaoOrlinCompile()
+{
+ typedef int Value;
+ typedef concepts::Digraph Digraph;
+
+ typedef Digraph::Node Node;
+ typedef Digraph::Arc Arc;
+ typedef concepts::ReadMap<Arc, Value> CapMap;
+ typedef concepts::WriteMap<Node, bool> CutMap;
+
+ Digraph g;
+ Node n;
+ CapMap cap;
+ CutMap cut;
+ Value v;
+ ::lemon::ignore_unused_variable_warning(v);
+
+ HaoOrlin<Digraph, CapMap> ho_test(g, cap);
+ const HaoOrlin<Digraph, CapMap>&
+ const_ho_test = ho_test;
+
+ ho_test.init();
+ ho_test.init(n);
+ ho_test.calculateOut();
+ ho_test.calculateIn();
+ ho_test.run();
+ ho_test.run(n);
+
+ v = const_ho_test.minCutValue();
+ v = const_ho_test.minCutMap(cut);
+}
+
+template <typename Graph, typename CapMap, typename CutMap>
+typename CapMap::Value
+ cutValue(const Graph& graph, const CapMap& cap, const CutMap& cut)
+{
+ typename CapMap::Value sum = 0;
+ for (typename Graph::ArcIt a(graph); a != INVALID; ++a) {
+ if (cut[graph.source(a)] && !cut[graph.target(a)])
+ sum += cap[a];
+ }
+ return sum;
+}
+
+int main() {
+ SmartDigraph graph;
+ SmartDigraph::ArcMap<int> cap1(graph), cap2(graph), cap3(graph);
+ SmartDigraph::NodeMap<bool> cut(graph);
+
+ istringstream input(lgf);
+ digraphReader(graph, input)
+ .arcMap("cap1", cap1)
+ .arcMap("cap2", cap2)
+ .arcMap("cap3", cap3)
+ .run();
+
+ {
+ HaoOrlin<SmartDigraph> ho(graph, cap1);
+ ho.run();
+ ho.minCutMap(cut);
+
+ check(ho.minCutValue() == 1, "Wrong cut value");
+ check(ho.minCutValue() == cutValue(graph, cap1, cut), "Wrong cut value");
+ }
+ {
+ HaoOrlin<SmartDigraph> ho(graph, cap2);
+ ho.run();
+ ho.minCutMap(cut);
+
+ check(ho.minCutValue() == 1, "Wrong cut value");
+ check(ho.minCutValue() == cutValue(graph, cap2, cut), "Wrong cut value");
+ }
+ {
+ HaoOrlin<SmartDigraph> ho(graph, cap3);
+ ho.run();
+ ho.minCutMap(cut);
+
+ check(ho.minCutValue() == 1, "Wrong cut value");
+ check(ho.minCutValue() == cutValue(graph, cap3, cut), "Wrong cut value");
+ }
+
+ typedef Undirector<SmartDigraph> UGraph;
+ UGraph ugraph(graph);
+
+ {
+ HaoOrlin<UGraph, SmartDigraph::ArcMap<int> > ho(ugraph, cap1);
+ ho.run();
+ ho.minCutMap(cut);
+
+ check(ho.minCutValue() == 2, "Wrong cut value");
+ check(ho.minCutValue() == cutValue(ugraph, cap1, cut), "Wrong cut value");
+ }
+ {
+ HaoOrlin<UGraph, SmartDigraph::ArcMap<int> > ho(ugraph, cap2);
+ ho.run();
+ ho.minCutMap(cut);
+
+ check(ho.minCutValue() == 5, "Wrong cut value");
+ check(ho.minCutValue() == cutValue(ugraph, cap2, cut), "Wrong cut value");
+ }
+ {
+ HaoOrlin<UGraph, SmartDigraph::ArcMap<int> > ho(ugraph, cap3);
+ ho.run();
+ ho.minCutMap(cut);
+
+ check(ho.minCutValue() == 5, "Wrong cut value");
+ check(ho.minCutValue() == cutValue(ugraph, cap3, cut), "Wrong cut value");
+ }
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/heap_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/heap_test.cc
new file mode 100644
index 00000000000..38e15771a8a
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/heap_test.cc
@@ -0,0 +1,310 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+#include <lemon/concept_check.h>
+#include <lemon/concepts/heap.h>
+
+#include <lemon/smart_graph.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/dijkstra.h>
+#include <lemon/maps.h>
+
+#include <lemon/bin_heap.h>
+#include <lemon/quad_heap.h>
+#include <lemon/dheap.h>
+#include <lemon/fib_heap.h>
+#include <lemon/pairing_heap.h>
+#include <lemon/radix_heap.h>
+#include <lemon/binomial_heap.h>
+#include <lemon/bucket_heap.h>
+
+#include "test_tools.h"
+
+using namespace lemon;
+using namespace lemon::concepts;
+
+typedef ListDigraph Digraph;
+DIGRAPH_TYPEDEFS(Digraph);
+
+char test_lgf[] =
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "6\n"
+ "7\n"
+ "8\n"
+ "9\n"
+ "@arcs\n"
+ " label capacity\n"
+ "0 5 0 94\n"
+ "3 9 1 11\n"
+ "8 7 2 83\n"
+ "1 2 3 94\n"
+ "5 7 4 35\n"
+ "7 4 5 84\n"
+ "9 5 6 38\n"
+ "0 4 7 96\n"
+ "6 7 8 6\n"
+ "3 1 9 27\n"
+ "5 2 10 77\n"
+ "5 6 11 69\n"
+ "6 5 12 41\n"
+ "4 6 13 70\n"
+ "3 2 14 45\n"
+ "7 9 15 93\n"
+ "5 9 16 50\n"
+ "9 0 17 94\n"
+ "9 6 18 67\n"
+ "0 9 19 86\n"
+ "@attributes\n"
+ "source 3\n";
+
+int test_seq[] = { 2, 28, 19, 27, 33, 25, 13, 41, 10, 26, 1, 9, 4, 34};
+int test_inc[] = {20, 28, 34, 16, 0, 46, 44, 0, 42, 32, 14, 8, 6, 37};
+
+int test_len = sizeof(test_seq) / sizeof(test_seq[0]);
+
+template <typename Heap>
+void heapSortTest() {
+ RangeMap<int> map(test_len, -1);
+ Heap heap(map);
+
+ std::vector<int> v(test_len);
+ for (int i = 0; i < test_len; ++i) {
+ v[i] = test_seq[i];
+ heap.push(i, v[i]);
+ }
+ std::sort(v.begin(), v.end());
+ for (int i = 0; i < test_len; ++i) {
+ check(v[i] == heap.prio(), "Wrong order in heap sort.");
+ heap.pop();
+ }
+}
+
+template <typename Heap>
+void heapIncreaseTest() {
+ RangeMap<int> map(test_len, -1);
+
+ Heap heap(map);
+
+ std::vector<int> v(test_len);
+ for (int i = 0; i < test_len; ++i) {
+ v[i] = test_seq[i];
+ heap.push(i, v[i]);
+ }
+ for (int i = 0; i < test_len; ++i) {
+ v[i] += test_inc[i];
+ heap.increase(i, v[i]);
+ }
+ std::sort(v.begin(), v.end());
+ for (int i = 0; i < test_len; ++i) {
+ check(v[i] == heap.prio(), "Wrong order in heap increase test.");
+ heap.pop();
+ }
+}
+
+template <typename Heap>
+void dijkstraHeapTest(const Digraph& digraph, const IntArcMap& length,
+ Node source) {
+
+ typename Dijkstra<Digraph, IntArcMap>::template SetStandardHeap<Heap>::
+ Create dijkstra(digraph, length);
+
+ dijkstra.run(source);
+
+ for(ArcIt a(digraph); a != INVALID; ++a) {
+ Node s = digraph.source(a);
+ Node t = digraph.target(a);
+ if (dijkstra.reached(s)) {
+ check( dijkstra.dist(t) - dijkstra.dist(s) <= length[a],
+ "Error in shortest path tree.");
+ }
+ }
+
+ for(NodeIt n(digraph); n != INVALID; ++n) {
+ if ( dijkstra.reached(n) && dijkstra.predArc(n) != INVALID ) {
+ Arc a = dijkstra.predArc(n);
+ Node s = digraph.source(a);
+ check( dijkstra.dist(n) - dijkstra.dist(s) == length[a],
+ "Error in shortest path tree.");
+ }
+ }
+
+}
+
+int main() {
+
+ typedef int Item;
+ typedef int Prio;
+ typedef RangeMap<int> ItemIntMap;
+
+ Digraph digraph;
+ IntArcMap length(digraph);
+ Node source;
+
+ std::istringstream input(test_lgf);
+ digraphReader(digraph, input).
+ arcMap("capacity", length).
+ node("source", source).
+ run();
+
+ // BinHeap
+ {
+ typedef BinHeap<Prio, ItemIntMap> IntHeap;
+ checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
+ heapSortTest<IntHeap>();
+ heapIncreaseTest<IntHeap>();
+
+ typedef BinHeap<Prio, IntNodeMap > NodeHeap;
+ checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
+ dijkstraHeapTest<NodeHeap>(digraph, length, source);
+ }
+
+ // QuadHeap
+ {
+ typedef QuadHeap<Prio, ItemIntMap> IntHeap;
+ checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
+ heapSortTest<IntHeap>();
+ heapIncreaseTest<IntHeap>();
+
+ typedef QuadHeap<Prio, IntNodeMap > NodeHeap;
+ checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
+ dijkstraHeapTest<NodeHeap>(digraph, length, source);
+ }
+
+ // DHeap
+ {
+ typedef DHeap<Prio, ItemIntMap> IntHeap;
+ checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
+ heapSortTest<IntHeap>();
+ heapIncreaseTest<IntHeap>();
+
+ typedef DHeap<Prio, IntNodeMap > NodeHeap;
+ checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
+ dijkstraHeapTest<NodeHeap>(digraph, length, source);
+ }
+
+ // FibHeap
+ {
+ typedef FibHeap<Prio, ItemIntMap> IntHeap;
+ checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
+ heapSortTest<IntHeap>();
+ heapIncreaseTest<IntHeap>();
+
+ typedef FibHeap<Prio, IntNodeMap > NodeHeap;
+ checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
+ dijkstraHeapTest<NodeHeap>(digraph, length, source);
+ }
+
+ // PairingHeap
+ {
+ typedef PairingHeap<Prio, ItemIntMap> IntHeap;
+ checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
+ heapSortTest<IntHeap>();
+ heapIncreaseTest<IntHeap>();
+
+ typedef PairingHeap<Prio, IntNodeMap > NodeHeap;
+ checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
+ dijkstraHeapTest<NodeHeap>(digraph, length, source);
+ }
+
+ // RadixHeap
+ {
+ typedef RadixHeap<ItemIntMap> IntHeap;
+ checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
+ heapSortTest<IntHeap>();
+ heapIncreaseTest<IntHeap>();
+
+ typedef RadixHeap<IntNodeMap > NodeHeap;
+ checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
+ dijkstraHeapTest<NodeHeap>(digraph, length, source);
+ }
+
+ // BinomialHeap
+ {
+ typedef BinomialHeap<Prio, ItemIntMap> IntHeap;
+ checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
+ heapSortTest<IntHeap>();
+ heapIncreaseTest<IntHeap>();
+
+ typedef BinomialHeap<Prio, IntNodeMap > NodeHeap;
+ checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
+ dijkstraHeapTest<NodeHeap>(digraph, length, source);
+ }
+
+ // BucketHeap, SimpleBucketHeap
+ {
+ typedef BucketHeap<ItemIntMap> IntHeap;
+ checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
+ heapSortTest<IntHeap>();
+ heapIncreaseTest<IntHeap>();
+
+ typedef BucketHeap<IntNodeMap > NodeHeap;
+ checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
+ dijkstraHeapTest<NodeHeap>(digraph, length, source);
+
+ typedef SimpleBucketHeap<ItemIntMap> SimpleIntHeap;
+ heapSortTest<SimpleIntHeap>();
+ }
+
+ {
+ typedef FibHeap<Prio, ItemIntMap> IntHeap;
+ checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
+ heapSortTest<IntHeap>();
+ heapIncreaseTest<IntHeap>();
+
+ typedef FibHeap<Prio, IntNodeMap > NodeHeap;
+ checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
+ dijkstraHeapTest<NodeHeap>(digraph, length, source);
+ }
+
+ {
+ typedef RadixHeap<ItemIntMap> IntHeap;
+ checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
+ heapSortTest<IntHeap>();
+ heapIncreaseTest<IntHeap>();
+
+ typedef RadixHeap<IntNodeMap > NodeHeap;
+ checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
+ dijkstraHeapTest<NodeHeap>(digraph, length, source);
+ }
+
+ {
+ typedef BucketHeap<ItemIntMap> IntHeap;
+ checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
+ heapSortTest<IntHeap>();
+ heapIncreaseTest<IntHeap>();
+
+ typedef BucketHeap<IntNodeMap > NodeHeap;
+ checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
+ dijkstraHeapTest<NodeHeap>(digraph, length, source);
+ }
+
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/kruskal_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/kruskal_test.cc
new file mode 100644
index 00000000000..af36c72fd7c
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/kruskal_test.cc
@@ -0,0 +1,147 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+#include <vector>
+
+#include "test_tools.h"
+#include <lemon/maps.h>
+#include <lemon/kruskal.h>
+#include <lemon/list_graph.h>
+
+#include <lemon/concepts/maps.h>
+#include <lemon/concepts/digraph.h>
+#include <lemon/concepts/graph.h>
+
+using namespace std;
+using namespace lemon;
+
+void checkCompileKruskal()
+{
+ concepts::WriteMap<concepts::Digraph::Arc,bool> w;
+ concepts::WriteMap<concepts::Graph::Edge,bool> uw;
+
+ concepts::ReadMap<concepts::Digraph::Arc,int> r;
+ concepts::ReadMap<concepts::Graph::Edge,int> ur;
+
+ concepts::Digraph g;
+ concepts::Graph ug;
+
+ kruskal(g, r, w);
+ kruskal(ug, ur, uw);
+
+ std::vector<std::pair<concepts::Digraph::Arc, int> > rs;
+ std::vector<std::pair<concepts::Graph::Edge, int> > urs;
+
+ kruskal(g, rs, w);
+ kruskal(ug, urs, uw);
+
+ std::vector<concepts::Digraph::Arc> ws;
+ std::vector<concepts::Graph::Edge> uws;
+
+ kruskal(g, r, ws.begin());
+ kruskal(ug, ur, uws.begin());
+}
+
+int main() {
+
+ typedef ListGraph::Node Node;
+ typedef ListGraph::Edge Edge;
+ typedef ListGraph::NodeIt NodeIt;
+ typedef ListGraph::ArcIt ArcIt;
+
+ ListGraph G;
+
+ Node s=G.addNode();
+ Node v1=G.addNode();
+ Node v2=G.addNode();
+ Node v3=G.addNode();
+ Node v4=G.addNode();
+ Node t=G.addNode();
+
+ Edge e1 = G.addEdge(s, v1);
+ Edge e2 = G.addEdge(s, v2);
+ Edge e3 = G.addEdge(v1, v2);
+ Edge e4 = G.addEdge(v2, v1);
+ Edge e5 = G.addEdge(v1, v3);
+ Edge e6 = G.addEdge(v3, v2);
+ Edge e7 = G.addEdge(v2, v4);
+ Edge e8 = G.addEdge(v4, v3);
+ Edge e9 = G.addEdge(v3, t);
+ Edge e10 = G.addEdge(v4, t);
+
+ typedef ListGraph::EdgeMap<int> ECostMap;
+ typedef ListGraph::EdgeMap<bool> EBoolMap;
+
+ ECostMap edge_cost_map(G, 2);
+ EBoolMap tree_map(G);
+
+
+ //Test with const map.
+ check(kruskal(G, ConstMap<ListGraph::Edge,int>(2), tree_map)==10,
+ "Total cost should be 10");
+ //Test with an edge map (filled with uniform costs).
+ check(kruskal(G, edge_cost_map, tree_map)==10,
+ "Total cost should be 10");
+
+ edge_cost_map[e1] = -10;
+ edge_cost_map[e2] = -9;
+ edge_cost_map[e3] = -8;
+ edge_cost_map[e4] = -7;
+ edge_cost_map[e5] = -6;
+ edge_cost_map[e6] = -5;
+ edge_cost_map[e7] = -4;
+ edge_cost_map[e8] = -3;
+ edge_cost_map[e9] = -2;
+ edge_cost_map[e10] = -1;
+
+ vector<Edge> tree_edge_vec(5);
+
+ //Test with a edge map and inserter.
+ check(kruskal(G, edge_cost_map,
+ tree_edge_vec.begin())
+ ==-31,
+ "Total cost should be -31.");
+
+ tree_edge_vec.clear();
+
+ check(kruskal(G, edge_cost_map,
+ back_inserter(tree_edge_vec))
+ ==-31,
+ "Total cost should be -31.");
+
+// tree_edge_vec.clear();
+
+// //The above test could also be coded like this:
+// check(kruskal(G,
+// makeKruskalMapInput(G, edge_cost_map),
+// makeKruskalSequenceOutput(back_inserter(tree_edge_vec)))
+// ==-31,
+// "Total cost should be -31.");
+
+ check(tree_edge_vec.size()==5,"The tree should have 5 edges.");
+
+ check(tree_edge_vec[0]==e1 &&
+ tree_edge_vec[1]==e2 &&
+ tree_edge_vec[2]==e5 &&
+ tree_edge_vec[3]==e7 &&
+ tree_edge_vec[4]==e9,
+ "Wrong tree.");
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/lgf_reader_writer_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/lgf_reader_writer_test.cc
new file mode 100644
index 00000000000..25d9423ac0c
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/lgf_reader_writer_test.cc
@@ -0,0 +1,578 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <string>
+
+#include <lemon/concepts/digraph.h>
+#include <lemon/concepts/graph.h>
+#include <lemon/concepts/bpgraph.h>
+
+#include <lemon/list_graph.h>
+#include <lemon/smart_graph.h>
+#include <lemon/lgf_reader.h>
+
+#include "test_tools.h"
+
+struct ReaderConverter {
+ int operator()(const std::string& str) const {
+ return str.length();
+ }
+};
+
+struct WriterConverter {
+ std::string operator()(int value) const {
+ return std::string(value, '*');
+ }
+};
+
+void checkDigraphReaderCompile() {
+ typedef lemon::concepts::ExtendableDigraphComponent<
+ lemon::concepts::Digraph> Digraph;
+ Digraph digraph;
+ Digraph::NodeMap<int> node_map(digraph);
+ Digraph::ArcMap<int> arc_map(digraph);
+ Digraph::Node node;
+ Digraph::Arc arc;
+ int attr;
+
+ lemon::DigraphReader<Digraph> reader(digraph, "filename");
+ reader.nodeMap("node_map", node_map);
+ reader.nodeMap("node_map", node_map, ReaderConverter());
+ reader.arcMap("arc_map", arc_map);
+ reader.arcMap("arc_map", arc_map, ReaderConverter());
+ reader.attribute("attr", attr);
+ reader.attribute("attr", attr, ReaderConverter());
+ reader.node("node", node);
+ reader.arc("arc", arc);
+
+ reader.nodes("alt_nodes_caption");
+ reader.arcs("alt_arcs_caption");
+ reader.attributes("alt_attrs_caption");
+
+ reader.useNodes(node_map);
+ reader.useNodes(node_map, WriterConverter());
+ reader.useArcs(arc_map);
+ reader.useArcs(arc_map, WriterConverter());
+
+ reader.skipNodes();
+ reader.skipArcs();
+
+ reader.run();
+
+ lemon::DigraphReader<Digraph> reader2(digraph, std::cin);
+}
+
+void checkDigraphWriterCompile() {
+ typedef lemon::concepts::Digraph Digraph;
+ Digraph digraph;
+ Digraph::NodeMap<int> node_map(digraph);
+ Digraph::ArcMap<int> arc_map(digraph);
+ Digraph::Node node;
+ Digraph::Arc arc;
+ int attr;
+
+ lemon::DigraphWriter<Digraph> writer(digraph, "filename");
+ writer.nodeMap("node_map", node_map);
+ writer.nodeMap("node_map", node_map, WriterConverter());
+ writer.arcMap("arc_map", arc_map);
+ writer.arcMap("arc_map", arc_map, WriterConverter());
+ writer.attribute("attr", attr);
+ writer.attribute("attr", attr, WriterConverter());
+ writer.node("node", node);
+ writer.arc("arc", arc);
+
+ writer.nodes("alt_nodes_caption");
+ writer.arcs("alt_arcs_caption");
+ writer.attributes("alt_attrs_caption");
+
+ writer.skipNodes();
+ writer.skipArcs();
+
+ writer.run();
+}
+
+void checkGraphReaderCompile() {
+ typedef lemon::concepts::ExtendableGraphComponent<
+ lemon::concepts::Graph> Graph;
+ Graph graph;
+ Graph::NodeMap<int> node_map(graph);
+ Graph::ArcMap<int> arc_map(graph);
+ Graph::EdgeMap<int> edge_map(graph);
+ Graph::Node node;
+ Graph::Arc arc;
+ Graph::Edge edge;
+ int attr;
+
+ lemon::GraphReader<Graph> reader(graph, "filename");
+ reader.nodeMap("node_map", node_map);
+ reader.nodeMap("node_map", node_map, ReaderConverter());
+ reader.arcMap("arc_map", arc_map);
+ reader.arcMap("arc_map", arc_map, ReaderConverter());
+ reader.edgeMap("edge_map", edge_map);
+ reader.edgeMap("edge_map", edge_map, ReaderConverter());
+ reader.attribute("attr", attr);
+ reader.attribute("attr", attr, ReaderConverter());
+ reader.node("node", node);
+ reader.arc("arc", arc);
+
+ reader.nodes("alt_nodes_caption");
+ reader.edges("alt_edges_caption");
+ reader.attributes("alt_attrs_caption");
+
+ reader.useNodes(node_map);
+ reader.useNodes(node_map, WriterConverter());
+ reader.useEdges(edge_map);
+ reader.useEdges(edge_map, WriterConverter());
+
+ reader.skipNodes();
+ reader.skipEdges();
+
+ reader.run();
+
+ lemon::GraphReader<Graph> reader2(graph, std::cin);
+}
+
+void checkGraphWriterCompile() {
+ typedef lemon::concepts::Graph Graph;
+ Graph graph;
+ Graph::NodeMap<int> node_map(graph);
+ Graph::ArcMap<int> arc_map(graph);
+ Graph::EdgeMap<int> edge_map(graph);
+ Graph::Node node;
+ Graph::Arc arc;
+ Graph::Edge edge;
+ int attr;
+
+ lemon::GraphWriter<Graph> writer(graph, "filename");
+ writer.nodeMap("node_map", node_map);
+ writer.nodeMap("node_map", node_map, WriterConverter());
+ writer.arcMap("arc_map", arc_map);
+ writer.arcMap("arc_map", arc_map, WriterConverter());
+ writer.edgeMap("edge_map", edge_map);
+ writer.edgeMap("edge_map", edge_map, WriterConverter());
+ writer.attribute("attr", attr);
+ writer.attribute("attr", attr, WriterConverter());
+ writer.node("node", node);
+ writer.arc("arc", arc);
+ writer.edge("edge", edge);
+
+ writer.nodes("alt_nodes_caption");
+ writer.edges("alt_edges_caption");
+ writer.attributes("alt_attrs_caption");
+
+ writer.skipNodes();
+ writer.skipEdges();
+
+ writer.run();
+
+ lemon::GraphWriter<Graph> writer2(graph, std::cout);
+}
+
+void checkBpGraphReaderCompile() {
+ typedef lemon::concepts::ExtendableBpGraphComponent<
+ lemon::concepts::BpGraph> BpGraph;
+ BpGraph graph;
+ BpGraph::NodeMap<int> node_map(graph);
+ BpGraph::RedNodeMap<int> red_node_map(graph);
+ BpGraph::BlueNodeMap<int> blue_node_map(graph);
+ BpGraph::ArcMap<int> arc_map(graph);
+ BpGraph::EdgeMap<int> edge_map(graph);
+ BpGraph::Node node;
+ BpGraph::RedNode red_node;
+ BpGraph::BlueNode blue_node;
+ BpGraph::Arc arc;
+ BpGraph::Edge edge;
+ int attr;
+
+ lemon::BpGraphReader<BpGraph> reader(graph, "filename");
+ reader.nodeMap("node_map", node_map);
+ reader.nodeMap("node_map", node_map, ReaderConverter());
+ reader.redNodeMap("red_node_map", red_node_map);
+ reader.redNodeMap("red_node_map", red_node_map, ReaderConverter());
+ reader.blueNodeMap("blue_node_map", blue_node_map);
+ reader.blueNodeMap("blue_node_map", blue_node_map, ReaderConverter());
+ reader.arcMap("arc_map", arc_map);
+ reader.arcMap("arc_map", arc_map, ReaderConverter());
+ reader.edgeMap("edge_map", edge_map);
+ reader.edgeMap("edge_map", edge_map, ReaderConverter());
+ reader.attribute("attr", attr);
+ reader.attribute("attr", attr, ReaderConverter());
+ reader.node("node", node);
+ reader.redNode("red_node", red_node);
+ reader.blueNode("blue_node", blue_node);
+ reader.arc("arc", arc);
+
+ reader.nodes("alt_nodes_caption");
+ reader.edges("alt_edges_caption");
+ reader.attributes("alt_attrs_caption");
+
+ reader.useNodes(node_map);
+ reader.useNodes(node_map, WriterConverter());
+ reader.useEdges(edge_map);
+ reader.useEdges(edge_map, WriterConverter());
+
+ reader.skipNodes();
+ reader.skipEdges();
+
+ reader.run();
+
+ lemon::BpGraphReader<BpGraph> reader2(graph, std::cin);
+}
+
+void checkBpGraphWriterCompile() {
+ typedef lemon::concepts::BpGraph BpGraph;
+ BpGraph graph;
+ BpGraph::NodeMap<int> node_map(graph);
+ BpGraph::RedNodeMap<int> red_node_map(graph);
+ BpGraph::BlueNodeMap<int> blue_node_map(graph);
+ BpGraph::ArcMap<int> arc_map(graph);
+ BpGraph::EdgeMap<int> edge_map(graph);
+ BpGraph::Node node;
+ BpGraph::RedNode red_node;
+ BpGraph::BlueNode blue_node;
+ BpGraph::Arc arc;
+ BpGraph::Edge edge;
+ int attr;
+
+ lemon::BpGraphWriter<BpGraph> writer(graph, "filename");
+ writer.nodeMap("node_map", node_map);
+ writer.nodeMap("node_map", node_map, WriterConverter());
+ writer.redNodeMap("red_node_map", red_node_map);
+ writer.redNodeMap("red_node_map", red_node_map, WriterConverter());
+ writer.blueNodeMap("blue_node_map", blue_node_map);
+ writer.blueNodeMap("blue_node_map", blue_node_map, WriterConverter());
+ writer.arcMap("arc_map", arc_map);
+ writer.arcMap("arc_map", arc_map, WriterConverter());
+ writer.edgeMap("edge_map", edge_map);
+ writer.edgeMap("edge_map", edge_map, WriterConverter());
+ writer.attribute("attr", attr);
+ writer.attribute("attr", attr, WriterConverter());
+ writer.node("node", node);
+ writer.redNode("red_node", red_node);
+ writer.blueNode("blue_node", blue_node);
+ writer.arc("arc", arc);
+
+ writer.nodes("alt_nodes_caption");
+ writer.edges("alt_edges_caption");
+ writer.attributes("alt_attrs_caption");
+
+ writer.skipNodes();
+ writer.skipEdges();
+
+ writer.run();
+
+ lemon::BpGraphWriter<BpGraph> writer2(graph, std::cout);
+}
+
+void checkDigraphReaderWriter() {
+ typedef lemon::SmartDigraph Digraph;
+ Digraph digraph;
+ Digraph::Node n1 = digraph.addNode();
+ Digraph::Node n2 = digraph.addNode();
+ Digraph::Node n3 = digraph.addNode();
+
+ Digraph::Arc a1 = digraph.addArc(n1, n2);
+ Digraph::Arc a2 = digraph.addArc(n2, n3);
+
+ Digraph::NodeMap<int> node_map(digraph);
+ node_map[n1] = 11;
+ node_map[n2] = 12;
+ node_map[n3] = 13;
+
+ Digraph::ArcMap<int> arc_map(digraph);
+ arc_map[a1] = 21;
+ arc_map[a2] = 22;
+
+ int attr = 100;
+
+ std::ostringstream os;
+ lemon::DigraphWriter<Digraph> writer(digraph, os);
+
+ writer.nodeMap("node_map1", node_map);
+ writer.nodeMap("node_map2", node_map, WriterConverter());
+ writer.arcMap("arc_map1", arc_map);
+ writer.arcMap("arc_map2", arc_map, WriterConverter());
+ writer.node("node", n2);
+ writer.arc("arc", a1);
+ writer.attribute("attr1", attr);
+ writer.attribute("attr2", attr, WriterConverter());
+
+ writer.run();
+
+ typedef lemon::ListDigraph ExpDigraph;
+ ExpDigraph exp_digraph;
+ ExpDigraph::NodeMap<int> exp_node_map1(exp_digraph);
+ ExpDigraph::NodeMap<int> exp_node_map2(exp_digraph);
+ ExpDigraph::ArcMap<int> exp_arc_map1(exp_digraph);
+ ExpDigraph::ArcMap<int> exp_arc_map2(exp_digraph);
+ ExpDigraph::Node exp_n2;
+ ExpDigraph::Arc exp_a1;
+ int exp_attr1;
+ int exp_attr2;
+
+ std::istringstream is(os.str());
+ lemon::DigraphReader<ExpDigraph> reader(exp_digraph, is);
+
+ reader.nodeMap("node_map1", exp_node_map1);
+ reader.nodeMap("node_map2", exp_node_map2, ReaderConverter());
+ reader.arcMap("arc_map1", exp_arc_map1);
+ reader.arcMap("arc_map2", exp_arc_map2, ReaderConverter());
+ reader.node("node", exp_n2);
+ reader.arc("arc", exp_a1);
+ reader.attribute("attr1", exp_attr1);
+ reader.attribute("attr2", exp_attr2, ReaderConverter());
+
+ reader.run();
+
+ check(lemon::countNodes(exp_digraph) == 3, "Wrong number of nodes");
+ check(lemon::countArcs(exp_digraph) == 2, "Wrong number of arcs");
+ check(exp_node_map1[exp_n2] == 12, "Wrong map value");
+ check(exp_node_map2[exp_n2] == 12, "Wrong map value");
+ check(exp_arc_map1[exp_a1] == 21, "Wrong map value");
+ check(exp_arc_map2[exp_a1] == 21, "Wrong map value");
+ check(exp_attr1 == 100, "Wrong attr value");
+ check(exp_attr2 == 100, "Wrong attr value");
+}
+
+void checkGraphReaderWriter() {
+ typedef lemon::SmartGraph Graph;
+ Graph graph;
+ Graph::Node n1 = graph.addNode();
+ Graph::Node n2 = graph.addNode();
+ Graph::Node n3 = graph.addNode();
+
+ Graph::Edge e1 = graph.addEdge(n1, n2);
+ Graph::Edge e2 = graph.addEdge(n2, n3);
+
+ Graph::NodeMap<int> node_map(graph);
+ node_map[n1] = 11;
+ node_map[n2] = 12;
+ node_map[n3] = 13;
+
+ Graph::EdgeMap<int> edge_map(graph);
+ edge_map[e1] = 21;
+ edge_map[e2] = 22;
+
+ Graph::ArcMap<int> arc_map(graph);
+ arc_map[graph.direct(e1, true)] = 211;
+ arc_map[graph.direct(e1, false)] = 212;
+ arc_map[graph.direct(e2, true)] = 221;
+ arc_map[graph.direct(e2, false)] = 222;
+
+ int attr = 100;
+
+ std::ostringstream os;
+ lemon::GraphWriter<Graph> writer(graph, os);
+
+ writer.nodeMap("node_map1", node_map);
+ writer.nodeMap("node_map2", node_map, WriterConverter());
+ writer.edgeMap("edge_map1", edge_map);
+ writer.edgeMap("edge_map2", edge_map, WriterConverter());
+ writer.arcMap("arc_map1", arc_map);
+ writer.arcMap("arc_map2", arc_map, WriterConverter());
+ writer.node("node", n2);
+ writer.edge("edge", e1);
+ writer.arc("arc", graph.direct(e1, false));
+ writer.attribute("attr1", attr);
+ writer.attribute("attr2", attr, WriterConverter());
+
+ writer.run();
+
+ typedef lemon::ListGraph ExpGraph;
+ ExpGraph exp_graph;
+ ExpGraph::NodeMap<int> exp_node_map1(exp_graph);
+ ExpGraph::NodeMap<int> exp_node_map2(exp_graph);
+ ExpGraph::EdgeMap<int> exp_edge_map1(exp_graph);
+ ExpGraph::EdgeMap<int> exp_edge_map2(exp_graph);
+ ExpGraph::ArcMap<int> exp_arc_map1(exp_graph);
+ ExpGraph::ArcMap<int> exp_arc_map2(exp_graph);
+ ExpGraph::Node exp_n2;
+ ExpGraph::Edge exp_e1;
+ ExpGraph::Arc exp_a1;
+ int exp_attr1;
+ int exp_attr2;
+
+ std::istringstream is(os.str());
+ lemon::GraphReader<ExpGraph> reader(exp_graph, is);
+
+ reader.nodeMap("node_map1", exp_node_map1);
+ reader.nodeMap("node_map2", exp_node_map2, ReaderConverter());
+ reader.edgeMap("edge_map1", exp_edge_map1);
+ reader.edgeMap("edge_map2", exp_edge_map2, ReaderConverter());
+ reader.arcMap("arc_map1", exp_arc_map1);
+ reader.arcMap("arc_map2", exp_arc_map2, ReaderConverter());
+ reader.node("node", exp_n2);
+ reader.edge("edge", exp_e1);
+ reader.arc("arc", exp_a1);
+ reader.attribute("attr1", exp_attr1);
+ reader.attribute("attr2", exp_attr2, ReaderConverter());
+
+ reader.run();
+
+ check(lemon::countNodes(exp_graph) == 3, "Wrong number of nodes");
+ check(lemon::countEdges(exp_graph) == 2, "Wrong number of edges");
+ check(lemon::countArcs(exp_graph) == 4, "Wrong number of arcs");
+ check(exp_node_map1[exp_n2] == 12, "Wrong map value");
+ check(exp_node_map2[exp_n2] == 12, "Wrong map value");
+ check(exp_edge_map1[exp_e1] == 21, "Wrong map value");
+ check(exp_edge_map2[exp_e1] == 21, "Wrong map value");
+ check(exp_arc_map1[exp_a1] == 212, "Wrong map value");
+ check(exp_arc_map2[exp_a1] == 212, "Wrong map value");
+ check(exp_attr1 == 100, "Wrong attr value");
+ check(exp_attr2 == 100, "Wrong attr value");
+}
+
+void checkBpGraphReaderWriter() {
+ typedef lemon::SmartBpGraph Graph;
+ Graph graph;
+ Graph::RedNode rn1 = graph.addRedNode();
+ Graph::RedNode rn2 = graph.addRedNode();
+ Graph::RedNode rn3 = graph.addRedNode();
+ Graph::BlueNode bn1 = graph.addBlueNode();
+ Graph::BlueNode bn2 = graph.addBlueNode();
+ Graph::Node n = bn1;
+
+ Graph::Edge e1 = graph.addEdge(rn1, bn1);
+ Graph::Edge e2 = graph.addEdge(rn2, bn1);
+
+ Graph::NodeMap<int> node_map(graph);
+ node_map[rn1] = 11;
+ node_map[rn2] = 12;
+ node_map[rn3] = 13;
+ node_map[bn1] = 14;
+ node_map[bn2] = 15;
+
+ Graph::NodeMap<int> red_node_map(graph);
+ red_node_map[rn1] = 411;
+ red_node_map[rn2] = 412;
+ red_node_map[rn3] = 413;
+
+ Graph::NodeMap<int> blue_node_map(graph);
+ blue_node_map[bn1] = 414;
+ blue_node_map[bn2] = 415;
+
+ Graph::EdgeMap<int> edge_map(graph);
+ edge_map[e1] = 21;
+ edge_map[e2] = 22;
+
+ Graph::ArcMap<int> arc_map(graph);
+ arc_map[graph.direct(e1, true)] = 211;
+ arc_map[graph.direct(e1, false)] = 212;
+ arc_map[graph.direct(e2, true)] = 221;
+ arc_map[graph.direct(e2, false)] = 222;
+
+ int attr = 100;
+
+ std::ostringstream os;
+ lemon::BpGraphWriter<Graph> writer(graph, os);
+
+ writer.nodeMap("node_map1", node_map);
+ writer.nodeMap("node_map2", node_map, WriterConverter());
+ writer.nodeMap("red_node_map1", red_node_map);
+ writer.nodeMap("red_node_map2", red_node_map, WriterConverter());
+ writer.nodeMap("blue_node_map1", blue_node_map);
+ writer.nodeMap("blue_node_map2", blue_node_map, WriterConverter());
+ writer.edgeMap("edge_map1", edge_map);
+ writer.edgeMap("edge_map2", edge_map, WriterConverter());
+ writer.arcMap("arc_map1", arc_map);
+ writer.arcMap("arc_map2", arc_map, WriterConverter());
+ writer.node("node", n);
+ writer.redNode("red_node", rn1);
+ writer.blueNode("blue_node", bn2);
+ writer.edge("edge", e1);
+ writer.arc("arc", graph.direct(e1, false));
+ writer.attribute("attr1", attr);
+ writer.attribute("attr2", attr, WriterConverter());
+
+ writer.run();
+
+ typedef lemon::ListBpGraph ExpGraph;
+ ExpGraph exp_graph;
+ ExpGraph::NodeMap<int> exp_node_map1(exp_graph);
+ ExpGraph::NodeMap<int> exp_node_map2(exp_graph);
+ ExpGraph::RedNodeMap<int> exp_red_node_map1(exp_graph);
+ ExpGraph::RedNodeMap<int> exp_red_node_map2(exp_graph);
+ ExpGraph::BlueNodeMap<int> exp_blue_node_map1(exp_graph);
+ ExpGraph::BlueNodeMap<int> exp_blue_node_map2(exp_graph);
+ ExpGraph::EdgeMap<int> exp_edge_map1(exp_graph);
+ ExpGraph::EdgeMap<int> exp_edge_map2(exp_graph);
+ ExpGraph::ArcMap<int> exp_arc_map1(exp_graph);
+ ExpGraph::ArcMap<int> exp_arc_map2(exp_graph);
+ ExpGraph::Node exp_n;
+ ExpGraph::RedNode exp_rn1;
+ ExpGraph::BlueNode exp_bn2;
+ ExpGraph::Edge exp_e1;
+ ExpGraph::Arc exp_a1;
+ int exp_attr1;
+ int exp_attr2;
+
+ std::istringstream is(os.str());
+ lemon::BpGraphReader<ExpGraph> reader(exp_graph, is);
+
+ reader.nodeMap("node_map1", exp_node_map1);
+ reader.nodeMap("node_map2", exp_node_map2, ReaderConverter());
+ reader.redNodeMap("red_node_map1", exp_red_node_map1);
+ reader.redNodeMap("red_node_map2", exp_red_node_map2, ReaderConverter());
+ reader.blueNodeMap("blue_node_map1", exp_blue_node_map1);
+ reader.blueNodeMap("blue_node_map2", exp_blue_node_map2, ReaderConverter());
+ reader.edgeMap("edge_map1", exp_edge_map1);
+ reader.edgeMap("edge_map2", exp_edge_map2, ReaderConverter());
+ reader.arcMap("arc_map1", exp_arc_map1);
+ reader.arcMap("arc_map2", exp_arc_map2, ReaderConverter());
+ reader.node("node", exp_n);
+ reader.redNode("red_node", exp_rn1);
+ reader.blueNode("blue_node", exp_bn2);
+ reader.edge("edge", exp_e1);
+ reader.arc("arc", exp_a1);
+ reader.attribute("attr1", exp_attr1);
+ reader.attribute("attr2", exp_attr2, ReaderConverter());
+
+ reader.run();
+
+ check(lemon::countNodes(exp_graph) == 5, "Wrong number of nodes");
+ check(lemon::countRedNodes(exp_graph) == 3, "Wrong number of red nodes");
+ check(lemon::countBlueNodes(exp_graph) == 2, "Wrong number of blue nodes");
+ check(lemon::countEdges(exp_graph) == 2, "Wrong number of edges");
+ check(lemon::countArcs(exp_graph) == 4, "Wrong number of arcs");
+ check(exp_node_map1[exp_n] == 14, "Wrong map value");
+ check(exp_node_map2[exp_n] == 14, "Wrong map value");
+ check(exp_red_node_map1[exp_rn1] == 411, "Wrong map value");
+ check(exp_red_node_map2[exp_rn1] == 411, "Wrong map value");
+ check(exp_blue_node_map1[exp_bn2] == 415, "Wrong map value");
+ check(exp_blue_node_map2[exp_bn2] == 415, "Wrong map value");
+ check(exp_edge_map1[exp_e1] == 21, "Wrong map value");
+ check(exp_edge_map2[exp_e1] == 21, "Wrong map value");
+ check(exp_arc_map1[exp_a1] == 212, "Wrong map value");
+ check(exp_arc_map2[exp_a1] == 212, "Wrong map value");
+ check(exp_attr1 == 100, "Wrong attr value");
+ check(exp_attr2 == 100, "Wrong attr value");
+}
+
+
+int main() {
+ { // Check digrpah
+ checkDigraphReaderWriter();
+ }
+ { // Check graph
+ checkGraphReaderWriter();
+ }
+ { // Check bipartite graph
+ checkBpGraphReaderWriter();
+ }
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/lgf_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/lgf_test.cc
new file mode 100644
index 00000000000..839afb15242
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/lgf_test.cc
@@ -0,0 +1,169 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/list_graph.h>
+#include <lemon/lgf_reader.h>
+#include "test_tools.h"
+
+using namespace lemon;
+
+char test_lgf[] =
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "@arcs\n"
+ " label\n"
+ "0 1 0\n"
+ "1 0 1\n"
+ "@attributes\n"
+ "source 0\n"
+ "target 1\n";
+
+char test_lgf_nomap[] =
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "@arcs\n"
+ " -\n"
+ "0 1\n";
+
+char test_lgf_bad1[] =
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "@arcs\n"
+ " - another\n"
+ "0 1\n";
+
+char test_lgf_bad2[] =
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "@arcs\n"
+ " label -\n"
+ "0 1\n";
+
+
+int main()
+{
+ {
+ ListDigraph d;
+ ListDigraph::Node s,t;
+ ListDigraph::ArcMap<int> label(d);
+ std::istringstream input(test_lgf);
+ digraphReader(d, input).
+ node("source", s).
+ node("target", t).
+ arcMap("label", label).
+ run();
+ check(countNodes(d) == 2,"There should be 2 nodes");
+ check(countArcs(d) == 2,"There should be 2 arcs");
+ }
+ {
+ ListGraph g;
+ ListGraph::Node s,t;
+ ListGraph::EdgeMap<int> label(g);
+ std::istringstream input(test_lgf);
+ graphReader(g, input).
+ node("source", s).
+ node("target", t).
+ edgeMap("label", label).
+ run();
+ check(countNodes(g) == 2,"There should be 2 nodes");
+ check(countEdges(g) == 2,"There should be 2 arcs");
+ }
+
+ {
+ ListDigraph d;
+ std::istringstream input(test_lgf_nomap);
+ digraphReader(d, input).
+ run();
+ check(countNodes(d) == 2,"There should be 2 nodes");
+ check(countArcs(d) == 1,"There should be 1 arc");
+ }
+ {
+ ListGraph g;
+ std::istringstream input(test_lgf_nomap);
+ graphReader(g, input).
+ run();
+ check(countNodes(g) == 2,"There should be 2 nodes");
+ check(countEdges(g) == 1,"There should be 1 edge");
+ }
+
+ {
+ ListDigraph d;
+ std::istringstream input(test_lgf_bad1);
+ bool ok=false;
+ try {
+ digraphReader(d, input).
+ run();
+ }
+ catch (FormatError&)
+ {
+ ok = true;
+ }
+ check(ok,"FormatError exception should have occured");
+ }
+ {
+ ListGraph g;
+ std::istringstream input(test_lgf_bad1);
+ bool ok=false;
+ try {
+ graphReader(g, input).
+ run();
+ }
+ catch (FormatError&)
+ {
+ ok = true;
+ }
+ check(ok,"FormatError exception should have occured");
+ }
+
+ {
+ ListDigraph d;
+ std::istringstream input(test_lgf_bad2);
+ bool ok=false;
+ try {
+ digraphReader(d, input).
+ run();
+ }
+ catch (FormatError&)
+ {
+ ok = true;
+ }
+ check(ok,"FormatError exception should have occured");
+ }
+ {
+ ListGraph g;
+ std::istringstream input(test_lgf_bad2);
+ bool ok=false;
+ try {
+ graphReader(g, input).
+ run();
+ }
+ catch (FormatError&)
+ {
+ ok = true;
+ }
+ check(ok,"FormatError exception should have occured");
+ }
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/lp_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/lp_test.cc
new file mode 100644
index 00000000000..914a37643df
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/lp_test.cc
@@ -0,0 +1,470 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <sstream>
+#include <lemon/lp_skeleton.h>
+#include "test_tools.h"
+#include <lemon/tolerance.h>
+
+#include <lemon/config.h>
+
+#ifdef LEMON_HAVE_GLPK
+#include <lemon/glpk.h>
+#endif
+
+#ifdef LEMON_HAVE_CPLEX
+#include <lemon/cplex.h>
+#endif
+
+#ifdef LEMON_HAVE_SOPLEX
+#include <lemon/soplex.h>
+#endif
+
+#ifdef LEMON_HAVE_CLP
+#include <lemon/clp.h>
+#endif
+
+#ifdef LEMON_HAVE_LP
+#include <lemon/lp.h>
+#endif
+using namespace lemon;
+
+int countCols(LpBase & lp) {
+ int count=0;
+ for (LpBase::ColIt c(lp); c!=INVALID; ++c) ++count;
+ return count;
+}
+
+int countRows(LpBase & lp) {
+ int count=0;
+ for (LpBase::RowIt r(lp); r!=INVALID; ++r) ++count;
+ return count;
+}
+
+
+void lpTest(LpSolver& lp)
+{
+
+ typedef LpSolver LP;
+
+ // Test LpBase::clear()
+ check(countRows(lp)==0, "Wrong number of rows");
+ check(countCols(lp)==0, "Wrong number of cols");
+ lp.addCol(); lp.addRow(); lp.addRow();
+ check(countRows(lp)==2, "Wrong number of rows");
+ check(countCols(lp)==1, "Wrong number of cols");
+ lp.clear();
+ check(countRows(lp)==0, "Wrong number of rows");
+ check(countCols(lp)==0, "Wrong number of cols");
+ lp.addCol(); lp.addCol(); lp.addCol(); lp.addRow();
+ check(countRows(lp)==1, "Wrong number of rows");
+ check(countCols(lp)==3, "Wrong number of cols");
+ lp.clear();
+
+ std::vector<LP::Col> x(10);
+ // for(int i=0;i<10;i++) x.push_back(lp.addCol());
+ lp.addColSet(x);
+ lp.colLowerBound(x,1);
+ lp.colUpperBound(x,1);
+ lp.colBounds(x,1,2);
+
+ std::vector<LP::Col> y(10);
+ lp.addColSet(y);
+
+ lp.colLowerBound(y,1);
+ lp.colUpperBound(y,1);
+ lp.colBounds(y,1,2);
+
+ std::map<int,LP::Col> z;
+
+ z.insert(std::make_pair(12,INVALID));
+ z.insert(std::make_pair(2,INVALID));
+ z.insert(std::make_pair(7,INVALID));
+ z.insert(std::make_pair(5,INVALID));
+
+ lp.addColSet(z);
+
+ lp.colLowerBound(z,1);
+ lp.colUpperBound(z,1);
+ lp.colBounds(z,1,2);
+
+ {
+ LP::Expr e,f,g;
+ LP::Col p1,p2,p3,p4,p5;
+ LP::Constr c;
+
+ p1=lp.addCol();
+ p2=lp.addCol();
+ p3=lp.addCol();
+ p4=lp.addCol();
+ p5=lp.addCol();
+
+ e[p1]=2;
+ *e=12;
+ e[p1]+=2;
+ *e+=12;
+ e[p1]-=2;
+ *e-=12;
+
+ e=2;
+ e=2.2;
+ e=p1;
+ e=f;
+
+ e+=2;
+ e+=2.2;
+ e+=p1;
+ e+=f;
+
+ e-=2;
+ e-=2.2;
+ e-=p1;
+ e-=f;
+
+ e*=2;
+ e*=2.2;
+ e/=2;
+ e/=2.2;
+
+ e=((p1+p2)+(p1-p2)+(p1+12)+(12+p1)+(p1-12)+(12-p1)+
+ (f+12)+(12+f)+(p1+f)+(f+p1)+(f+g)+
+ (f-12)+(12-f)+(p1-f)+(f-p1)+(f-g)+
+ 2.2*f+f*2.2+f/2.2+
+ 2*f+f*2+f/2+
+ 2.2*p1+p1*2.2+p1/2.2+
+ 2*p1+p1*2+p1/2
+ );
+
+
+ c = (e <= f );
+ c = (e <= 2.2);
+ c = (e <= 2 );
+ c = (e <= p1 );
+ c = (2.2<= f );
+ c = (2 <= f );
+ c = (p1 <= f );
+ c = (p1 <= p2 );
+ c = (p1 <= 2.2);
+ c = (p1 <= 2 );
+ c = (2.2<= p2 );
+ c = (2 <= p2 );
+
+ c = (e >= f );
+ c = (e >= 2.2);
+ c = (e >= 2 );
+ c = (e >= p1 );
+ c = (2.2>= f );
+ c = (2 >= f );
+ c = (p1 >= f );
+ c = (p1 >= p2 );
+ c = (p1 >= 2.2);
+ c = (p1 >= 2 );
+ c = (2.2>= p2 );
+ c = (2 >= p2 );
+
+ c = (e == f );
+ c = (e == 2.2);
+ c = (e == 2 );
+ c = (e == p1 );
+ c = (2.2== f );
+ c = (2 == f );
+ c = (p1 == f );
+ //c = (p1 == p2 );
+ c = (p1 == 2.2);
+ c = (p1 == 2 );
+ c = (2.2== p2 );
+ c = (2 == p2 );
+
+ c = ((2 <= e) <= 3);
+ c = ((2 <= p1) <= 3);
+
+ c = ((2 >= e) >= 3);
+ c = ((2 >= p1) >= 3);
+
+ { //Tests for #430
+ LP::Col v=lp.addCol();
+ LP::Constr c = v >= -3;
+ c = c <= 4;
+ LP::Constr c2;
+#if ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ == 3 )
+ c2 = ( -3 <= v ) <= 4;
+#else
+ c2 = -3 <= v <= 4;
+#endif
+
+ }
+
+ e[x[3]]=2;
+ e[x[3]]=4;
+ e[x[3]]=1;
+ *e=12;
+
+ lp.addRow(-LP::INF,e,23);
+ lp.addRow(-LP::INF,3.0*(x[1]+x[2]/2)-x[3],23);
+ lp.addRow(-LP::INF,3.0*(x[1]+x[2]*2-5*x[3]+12-x[4]/3)+2*x[4]-4,23);
+
+ lp.addRow(x[1]+x[3]<=x[5]-3);
+ lp.addRow((-7<=x[1]+x[3]-12)<=3);
+ lp.addRow(x[1]<=x[5]);
+
+ std::ostringstream buf;
+
+
+ e=((p1+p2)+(p1-0.99*p2));
+ //e.prettyPrint(std::cout);
+ //(e<=2).prettyPrint(std::cout);
+ double tolerance=0.001;
+ e.simplify(tolerance);
+ buf << "Coeff. of p2 should be 0.01";
+ check(e[p2]>0, buf.str());
+
+ tolerance=0.02;
+ e.simplify(tolerance);
+ buf << "Coeff. of p2 should be 0";
+ check(const_cast<const LpSolver::Expr&>(e)[p2]==0, buf.str());
+
+ //Test for clone/new
+ LP* lpnew = lp.newSolver();
+ LP* lpclone = lp.cloneSolver();
+ delete lpnew;
+ delete lpclone;
+
+ }
+
+ {
+ LP::DualExpr e,f,g;
+ LP::Row p1 = INVALID, p2 = INVALID;
+
+ e[p1]=2;
+ e[p1]+=2;
+ e[p1]-=2;
+
+ e=p1;
+ e=f;
+
+ e+=p1;
+ e+=f;
+
+ e-=p1;
+ e-=f;
+
+ e*=2;
+ e*=2.2;
+ e/=2;
+ e/=2.2;
+
+ e=((p1+p2)+(p1-p2)+
+ (p1+f)+(f+p1)+(f+g)+
+ (p1-f)+(f-p1)+(f-g)+
+ 2.2*f+f*2.2+f/2.2+
+ 2*f+f*2+f/2+
+ 2.2*p1+p1*2.2+p1/2.2+
+ 2*p1+p1*2+p1/2
+ );
+ }
+
+}
+
+void solveAndCheck(LpSolver& lp, LpSolver::ProblemType stat,
+ double exp_opt) {
+ using std::string;
+ lp.solve();
+
+ std::ostringstream buf;
+ buf << "PrimalType should be: " << int(stat) << int(lp.primalType());
+
+ check(lp.primalType()==stat, buf.str());
+
+ if (stat == LpSolver::OPTIMAL) {
+ std::ostringstream sbuf;
+ sbuf << "Wrong optimal value (" << lp.primal() <<") with "
+ << lp.solverName() <<"\n the right optimum is " << exp_opt;
+ check(std::abs(lp.primal()-exp_opt) < 1e-3, sbuf.str());
+ }
+}
+
+void aTest(LpSolver & lp)
+{
+ typedef LpSolver LP;
+
+ //The following example is very simple
+
+ typedef LpSolver::Row Row;
+ typedef LpSolver::Col Col;
+
+
+ Col x1 = lp.addCol();
+ Col x2 = lp.addCol();
+
+
+ //Constraints
+ Row upright=lp.addRow(x1+2*x2 <=1);
+ lp.addRow(x1+x2 >=-1);
+ lp.addRow(x1-x2 <=1);
+ lp.addRow(x1-x2 >=-1);
+ //Nonnegativity of the variables
+ lp.colLowerBound(x1, 0);
+ lp.colLowerBound(x2, 0);
+ //Objective function
+ lp.obj(x1+x2);
+
+ lp.sense(lp.MAX);
+
+ //Testing the problem retrieving routines
+ check(lp.objCoeff(x1)==1,"First term should be 1 in the obj function!");
+ check(lp.sense() == lp.MAX,"This is a maximization!");
+ check(lp.coeff(upright,x1)==1,"The coefficient in question is 1!");
+ check(lp.colLowerBound(x1)==0,
+ "The lower bound for variable x1 should be 0.");
+ check(lp.colUpperBound(x1)==LpSolver::INF,
+ "The upper bound for variable x1 should be infty.");
+ check(lp.rowLowerBound(upright) == -LpSolver::INF,
+ "The lower bound for the first row should be -infty.");
+ check(lp.rowUpperBound(upright)==1,
+ "The upper bound for the first row should be 1.");
+ LpSolver::Expr e = lp.row(upright);
+ check(e[x1] == 1, "The first coefficient should 1.");
+ check(e[x2] == 2, "The second coefficient should 1.");
+
+ lp.row(upright, x1+x2 <=1);
+ e = lp.row(upright);
+ check(e[x1] == 1, "The first coefficient should 1.");
+ check(e[x2] == 1, "The second coefficient should 1.");
+
+ LpSolver::DualExpr de = lp.col(x1);
+ check( de[upright] == 1, "The first coefficient should 1.");
+
+ LpSolver* clp = lp.cloneSolver();
+
+ //Testing the problem retrieving routines
+ check(clp->objCoeff(x1)==1,"First term should be 1 in the obj function!");
+ check(clp->sense() == clp->MAX,"This is a maximization!");
+ check(clp->coeff(upright,x1)==1,"The coefficient in question is 1!");
+ // std::cout<<lp.colLowerBound(x1)<<std::endl;
+ check(clp->colLowerBound(x1)==0,
+ "The lower bound for variable x1 should be 0.");
+ check(clp->colUpperBound(x1)==LpSolver::INF,
+ "The upper bound for variable x1 should be infty.");
+
+ check(lp.rowLowerBound(upright)==-LpSolver::INF,
+ "The lower bound for the first row should be -infty.");
+ check(lp.rowUpperBound(upright)==1,
+ "The upper bound for the first row should be 1.");
+ e = clp->row(upright);
+ check(e[x1] == 1, "The first coefficient should 1.");
+ check(e[x2] == 1, "The second coefficient should 1.");
+
+ de = clp->col(x1);
+ check(de[upright] == 1, "The first coefficient should 1.");
+
+ delete clp;
+
+ //Maximization of x1+x2
+ //over the triangle with vertices (0,0) (0,1) (1,0)
+ double expected_opt=1;
+ solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
+
+ //Minimization
+ lp.sense(lp.MIN);
+ expected_opt=0;
+ solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
+
+ //Vertex (-1,0) instead of (0,0)
+ lp.colLowerBound(x1, -LpSolver::INF);
+ expected_opt=-1;
+ solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
+
+ //Erase one constraint and return to maximization
+ lp.erase(upright);
+ lp.sense(lp.MAX);
+ expected_opt=LpSolver::INF;
+ solveAndCheck(lp, LpSolver::UNBOUNDED, expected_opt);
+
+ //Infeasibilty
+ lp.addRow(x1+x2 <=-2);
+ solveAndCheck(lp, LpSolver::INFEASIBLE, expected_opt);
+
+}
+
+template<class LP>
+void cloneTest()
+{
+ //Test for clone/new
+
+ LP* lp = new LP();
+ LP* lpnew = lp->newSolver();
+ LP* lpclone = lp->cloneSolver();
+ delete lp;
+ delete lpnew;
+ delete lpclone;
+}
+
+int main()
+{
+ LpSkeleton lp_skel;
+ lpTest(lp_skel);
+
+#ifdef LEMON_HAVE_LP
+ {
+ Lp lp,lp2;
+ lpTest(lp);
+ aTest(lp2);
+ cloneTest<Lp>();
+ }
+#endif
+
+#ifdef LEMON_HAVE_GLPK
+ {
+ GlpkLp lp_glpk1,lp_glpk2;
+ lpTest(lp_glpk1);
+ aTest(lp_glpk2);
+ cloneTest<GlpkLp>();
+ }
+#endif
+
+#ifdef LEMON_HAVE_CPLEX
+ try {
+ CplexLp lp_cplex1,lp_cplex2;
+ lpTest(lp_cplex1);
+ aTest(lp_cplex2);
+ cloneTest<CplexLp>();
+ } catch (CplexEnv::LicenseError& error) {
+ check(false, error.what());
+ }
+#endif
+
+#ifdef LEMON_HAVE_SOPLEX
+ {
+ SoplexLp lp_soplex1,lp_soplex2;
+ lpTest(lp_soplex1);
+ aTest(lp_soplex2);
+ cloneTest<SoplexLp>();
+ }
+#endif
+
+#ifdef LEMON_HAVE_CLP
+ {
+ ClpLp lp_clp1,lp_clp2;
+ lpTest(lp_clp1);
+ aTest(lp_clp2);
+ cloneTest<ClpLp>();
+ }
+#endif
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/maps_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/maps_test.cc
new file mode 100644
index 00000000000..5502e046fde
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/maps_test.cc
@@ -0,0 +1,1022 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <deque>
+#include <set>
+
+#include <lemon/concept_check.h>
+#include <lemon/concepts/maps.h>
+#include <lemon/maps.h>
+#include <lemon/list_graph.h>
+#include <lemon/smart_graph.h>
+#include <lemon/adaptors.h>
+#include <lemon/dfs.h>
+#include <algorithm>
+
+#include "test_tools.h"
+
+using namespace lemon;
+using namespace lemon::concepts;
+
+struct A {};
+inline bool operator<(A, A) { return true; }
+struct B {};
+
+class C {
+ int _x;
+public:
+ C(int x) : _x(x) {}
+ int get() const { return _x; }
+};
+inline bool operator<(C c1, C c2) { return c1.get() < c2.get(); }
+inline bool operator==(C c1, C c2) { return c1.get() == c2.get(); }
+
+C createC(int x) { return C(x); }
+
+template <typename T>
+class Less {
+ T _t;
+public:
+ Less(T t): _t(t) {}
+ bool operator()(const T& t) const { return t < _t; }
+};
+
+class F {
+public:
+ typedef A argument_type;
+ typedef B result_type;
+
+ B operator()(const A&) const { return B(); }
+private:
+ F& operator=(const F&);
+};
+
+int func(A) { return 3; }
+
+int binc(int a, B) { return a+1; }
+
+template <typename T>
+class Sum {
+ T& _sum;
+public:
+ Sum(T& sum) : _sum(sum) {}
+ void operator()(const T& t) { _sum += t; }
+};
+
+typedef ReadMap<A, double> DoubleMap;
+typedef ReadWriteMap<A, double> DoubleWriteMap;
+typedef ReferenceMap<A, double, double&, const double&> DoubleRefMap;
+
+typedef ReadMap<A, bool> BoolMap;
+typedef ReadWriteMap<A, bool> BoolWriteMap;
+typedef ReferenceMap<A, bool, bool&, const bool&> BoolRefMap;
+
+int main()
+{
+ // Map concepts
+ checkConcept<ReadMap<A,B>, ReadMap<A,B> >();
+ checkConcept<ReadMap<A,C>, ReadMap<A,C> >();
+ checkConcept<WriteMap<A,B>, WriteMap<A,B> >();
+ checkConcept<WriteMap<A,C>, WriteMap<A,C> >();
+ checkConcept<ReadWriteMap<A,B>, ReadWriteMap<A,B> >();
+ checkConcept<ReadWriteMap<A,C>, ReadWriteMap<A,C> >();
+ checkConcept<ReferenceMap<A,B,B&,const B&>, ReferenceMap<A,B,B&,const B&> >();
+ checkConcept<ReferenceMap<A,C,C&,const C&>, ReferenceMap<A,C,C&,const C&> >();
+
+ // NullMap
+ {
+ checkConcept<ReadWriteMap<A,B>, NullMap<A,B> >();
+ NullMap<A,B> map1;
+ NullMap<A,B> map2 = map1;
+ ::lemon::ignore_unused_variable_warning(map2);
+ map1 = nullMap<A,B>();
+ }
+
+ // ConstMap
+ {
+ checkConcept<ReadWriteMap<A,B>, ConstMap<A,B> >();
+ checkConcept<ReadWriteMap<A,C>, ConstMap<A,C> >();
+ ConstMap<A,B> map1;
+ ConstMap<A,B> map2 = B();
+ ConstMap<A,B> map3 = map1;
+ ::lemon::ignore_unused_variable_warning(map2,map3);
+
+ map1 = constMap<A>(B());
+ map1 = constMap<A,B>();
+ map1.setAll(B());
+ ConstMap<A,C> map4(C(1));
+ ConstMap<A,C> map5 = map4;
+ ::lemon::ignore_unused_variable_warning(map5);
+
+ map4 = constMap<A>(C(2));
+ map4.setAll(C(3));
+
+ checkConcept<ReadWriteMap<A,int>, ConstMap<A,int> >();
+ check(constMap<A>(10)[A()] == 10, "Something is wrong with ConstMap");
+
+ checkConcept<ReadWriteMap<A,int>, ConstMap<A,Const<int,10> > >();
+ ConstMap<A,Const<int,10> > map6;
+ ConstMap<A,Const<int,10> > map7 = map6;
+ map6 = constMap<A,int,10>();
+ map7 = constMap<A,Const<int,10> >();
+ check(map6[A()] == 10 && map7[A()] == 10,
+ "Something is wrong with ConstMap");
+ }
+
+ // IdentityMap
+ {
+ checkConcept<ReadMap<A,A>, IdentityMap<A> >();
+ IdentityMap<A> map1;
+ IdentityMap<A> map2 = map1;
+ ::lemon::ignore_unused_variable_warning(map2);
+
+ map1 = identityMap<A>();
+
+ checkConcept<ReadMap<double,double>, IdentityMap<double> >();
+ check(identityMap<double>()[1.0] == 1.0 &&
+ identityMap<double>()[3.14] == 3.14,
+ "Something is wrong with IdentityMap");
+ }
+
+ // RangeMap
+ {
+ checkConcept<ReferenceMap<int,B,B&,const B&>, RangeMap<B> >();
+ RangeMap<B> map1;
+ RangeMap<B> map2(10);
+ RangeMap<B> map3(10,B());
+ RangeMap<B> map4 = map1;
+ RangeMap<B> map5 = rangeMap<B>();
+ RangeMap<B> map6 = rangeMap<B>(10);
+ RangeMap<B> map7 = rangeMap(10,B());
+
+ checkConcept< ReferenceMap<int, double, double&, const double&>,
+ RangeMap<double> >();
+ std::vector<double> v(10, 0);
+ v[5] = 100;
+ RangeMap<double> map8(v);
+ RangeMap<double> map9 = rangeMap(v);
+ check(map9.size() == 10 && map9[2] == 0 && map9[5] == 100,
+ "Something is wrong with RangeMap");
+ }
+
+ // SparseMap
+ {
+ checkConcept<ReferenceMap<A,B,B&,const B&>, SparseMap<A,B> >();
+ SparseMap<A,B> map1;
+ SparseMap<A,B> map2 = B();
+ SparseMap<A,B> map3 = sparseMap<A,B>();
+ SparseMap<A,B> map4 = sparseMap<A>(B());
+
+ checkConcept< ReferenceMap<double, int, int&, const int&>,
+ SparseMap<double, int> >();
+ std::map<double, int> m;
+ SparseMap<double, int> map5(m);
+ SparseMap<double, int> map6(m,10);
+ SparseMap<double, int> map7 = sparseMap(m);
+ SparseMap<double, int> map8 = sparseMap(m,10);
+
+ check(map5[1.0] == 0 && map5[3.14] == 0 &&
+ map6[1.0] == 10 && map6[3.14] == 10,
+ "Something is wrong with SparseMap");
+ map5[1.0] = map6[3.14] = 100;
+ check(map5[1.0] == 100 && map5[3.14] == 0 &&
+ map6[1.0] == 10 && map6[3.14] == 100,
+ "Something is wrong with SparseMap");
+ }
+
+ // ComposeMap
+ {
+ typedef ComposeMap<DoubleMap, ReadMap<B,A> > CompMap;
+ checkConcept<ReadMap<B,double>, CompMap>();
+ CompMap map1 = CompMap(DoubleMap(),ReadMap<B,A>());
+ ::lemon::ignore_unused_variable_warning(map1);
+ CompMap map2 = composeMap(DoubleMap(), ReadMap<B,A>());
+ ::lemon::ignore_unused_variable_warning(map2);
+
+ SparseMap<double, bool> m1(false); m1[3.14] = true;
+ RangeMap<double> m2(2); m2[0] = 3.0; m2[1] = 3.14;
+ check(!composeMap(m1,m2)[0] && composeMap(m1,m2)[1],
+ "Something is wrong with ComposeMap")
+ }
+
+ // CombineMap
+ {
+ typedef CombineMap<DoubleMap, DoubleMap, std::plus<double> > CombMap;
+ checkConcept<ReadMap<A,double>, CombMap>();
+ CombMap map1 = CombMap(DoubleMap(), DoubleMap());
+ ::lemon::ignore_unused_variable_warning(map1);
+ CombMap map2 = combineMap(DoubleMap(), DoubleMap(), std::plus<double>());
+ ::lemon::ignore_unused_variable_warning(map2);
+
+ check(combineMap(constMap<B,int,2>(), identityMap<B>(), &binc)[B()] == 3,
+ "Something is wrong with CombineMap");
+ }
+
+ // FunctorToMap, MapToFunctor
+ {
+ checkConcept<ReadMap<A,B>, FunctorToMap<F,A,B> >();
+ checkConcept<ReadMap<A,B>, FunctorToMap<F> >();
+ FunctorToMap<F> map1;
+ FunctorToMap<F> map2 = FunctorToMap<F>(F());
+ ::lemon::ignore_unused_variable_warning(map2);
+
+ B b = functorToMap(F())[A()];
+ ::lemon::ignore_unused_variable_warning(b);
+
+ checkConcept<ReadMap<A,B>, MapToFunctor<ReadMap<A,B> > >();
+ MapToFunctor<ReadMap<A,B> > map =
+ MapToFunctor<ReadMap<A,B> >(ReadMap<A,B>());
+ ::lemon::ignore_unused_variable_warning(map);
+
+ check(functorToMap(&func)[A()] == 3,
+ "Something is wrong with FunctorToMap");
+ check(mapToFunctor(constMap<A,int>(2))(A()) == 2,
+ "Something is wrong with MapToFunctor");
+ check(mapToFunctor(functorToMap(&func))(A()) == 3 &&
+ mapToFunctor(functorToMap(&func))[A()] == 3,
+ "Something is wrong with FunctorToMap or MapToFunctor");
+ check(functorToMap(mapToFunctor(constMap<A,int>(2)))[A()] == 2,
+ "Something is wrong with FunctorToMap or MapToFunctor");
+ }
+
+ // ConvertMap
+ {
+ checkConcept<ReadMap<double,double>,
+ ConvertMap<ReadMap<double, int>, double> >();
+ ConvertMap<RangeMap<bool>, int> map1(rangeMap(1, true));
+ ::lemon::ignore_unused_variable_warning(map1);
+ ConvertMap<RangeMap<bool>, int> map2 = convertMap<int>(rangeMap(2, false));
+ ::lemon::ignore_unused_variable_warning(map2);
+
+ }
+
+ // ForkMap
+ {
+ checkConcept<DoubleWriteMap, ForkMap<DoubleWriteMap, DoubleWriteMap> >();
+
+ typedef RangeMap<double> RM;
+ typedef SparseMap<int, double> SM;
+ RM m1(10, -1);
+ SM m2(-1);
+ checkConcept<ReadWriteMap<int, double>, ForkMap<RM, SM> >();
+ checkConcept<ReadWriteMap<int, double>, ForkMap<SM, RM> >();
+ ForkMap<RM, SM> map1(m1,m2);
+ ForkMap<SM, RM> map2 = forkMap(m2,m1);
+ map2.set(5, 10);
+ check(m1[1] == -1 && m1[5] == 10 && m2[1] == -1 &&
+ m2[5] == 10 && map2[1] == -1 && map2[5] == 10,
+ "Something is wrong with ForkMap");
+ }
+
+ // Arithmetic maps:
+ // - AddMap, SubMap, MulMap, DivMap
+ // - ShiftMap, ShiftWriteMap, ScaleMap, ScaleWriteMap
+ // - NegMap, NegWriteMap, AbsMap
+ {
+ checkConcept<DoubleMap, AddMap<DoubleMap,DoubleMap> >();
+ checkConcept<DoubleMap, SubMap<DoubleMap,DoubleMap> >();
+ checkConcept<DoubleMap, MulMap<DoubleMap,DoubleMap> >();
+ checkConcept<DoubleMap, DivMap<DoubleMap,DoubleMap> >();
+
+ ConstMap<int, double> c1(1.0), c2(3.14);
+ IdentityMap<int> im;
+ ConvertMap<IdentityMap<int>, double> id(im);
+ check(addMap(c1,id)[0] == 1.0 && addMap(c1,id)[10] == 11.0,
+ "Something is wrong with AddMap");
+ check(subMap(id,c1)[0] == -1.0 && subMap(id,c1)[10] == 9.0,
+ "Something is wrong with SubMap");
+ check(mulMap(id,c2)[0] == 0 && mulMap(id,c2)[2] == 6.28,
+ "Something is wrong with MulMap");
+ check(divMap(c2,id)[1] == 3.14 && divMap(c2,id)[2] == 1.57,
+ "Something is wrong with DivMap");
+
+ checkConcept<DoubleMap, ShiftMap<DoubleMap> >();
+ checkConcept<DoubleWriteMap, ShiftWriteMap<DoubleWriteMap> >();
+ checkConcept<DoubleMap, ScaleMap<DoubleMap> >();
+ checkConcept<DoubleWriteMap, ScaleWriteMap<DoubleWriteMap> >();
+ checkConcept<DoubleMap, NegMap<DoubleMap> >();
+ checkConcept<DoubleWriteMap, NegWriteMap<DoubleWriteMap> >();
+ checkConcept<DoubleMap, AbsMap<DoubleMap> >();
+
+ check(shiftMap(id, 2.0)[1] == 3.0 && shiftMap(id, 2.0)[10] == 12.0,
+ "Something is wrong with ShiftMap");
+ check(shiftWriteMap(id, 2.0)[1] == 3.0 &&
+ shiftWriteMap(id, 2.0)[10] == 12.0,
+ "Something is wrong with ShiftWriteMap");
+ check(scaleMap(id, 2.0)[1] == 2.0 && scaleMap(id, 2.0)[10] == 20.0,
+ "Something is wrong with ScaleMap");
+ check(scaleWriteMap(id, 2.0)[1] == 2.0 &&
+ scaleWriteMap(id, 2.0)[10] == 20.0,
+ "Something is wrong with ScaleWriteMap");
+ check(negMap(id)[1] == -1.0 && negMap(id)[-10] == 10.0,
+ "Something is wrong with NegMap");
+ check(negWriteMap(id)[1] == -1.0 && negWriteMap(id)[-10] == 10.0,
+ "Something is wrong with NegWriteMap");
+ check(absMap(id)[1] == 1.0 && absMap(id)[-10] == 10.0,
+ "Something is wrong with AbsMap");
+ }
+
+ // Logical maps:
+ // - TrueMap, FalseMap
+ // - AndMap, OrMap
+ // - NotMap, NotWriteMap
+ // - EqualMap, LessMap
+ {
+ checkConcept<BoolMap, TrueMap<A> >();
+ checkConcept<BoolMap, FalseMap<A> >();
+ checkConcept<BoolMap, AndMap<BoolMap,BoolMap> >();
+ checkConcept<BoolMap, OrMap<BoolMap,BoolMap> >();
+ checkConcept<BoolMap, NotMap<BoolMap> >();
+ checkConcept<BoolWriteMap, NotWriteMap<BoolWriteMap> >();
+ checkConcept<BoolMap, EqualMap<DoubleMap,DoubleMap> >();
+ checkConcept<BoolMap, LessMap<DoubleMap,DoubleMap> >();
+
+ TrueMap<int> tm;
+ FalseMap<int> fm;
+ RangeMap<bool> rm(2);
+ rm[0] = true; rm[1] = false;
+ check(andMap(tm,rm)[0] && !andMap(tm,rm)[1] &&
+ !andMap(fm,rm)[0] && !andMap(fm,rm)[1],
+ "Something is wrong with AndMap");
+ check(orMap(tm,rm)[0] && orMap(tm,rm)[1] &&
+ orMap(fm,rm)[0] && !orMap(fm,rm)[1],
+ "Something is wrong with OrMap");
+ check(!notMap(rm)[0] && notMap(rm)[1],
+ "Something is wrong with NotMap");
+ check(!notWriteMap(rm)[0] && notWriteMap(rm)[1],
+ "Something is wrong with NotWriteMap");
+
+ ConstMap<int, double> cm(2.0);
+ IdentityMap<int> im;
+ ConvertMap<IdentityMap<int>, double> id(im);
+ check(lessMap(id,cm)[1] && !lessMap(id,cm)[2] && !lessMap(id,cm)[3],
+ "Something is wrong with LessMap");
+ check(!equalMap(id,cm)[1] && equalMap(id,cm)[2] && !equalMap(id,cm)[3],
+ "Something is wrong with EqualMap");
+ }
+
+ // LoggerBoolMap
+ {
+ typedef std::vector<int> vec;
+ checkConcept<WriteMap<int, bool>, LoggerBoolMap<vec::iterator> >();
+ checkConcept<WriteMap<int, bool>,
+ LoggerBoolMap<std::back_insert_iterator<vec> > >();
+
+ vec v1;
+ vec v2(10);
+ LoggerBoolMap<std::back_insert_iterator<vec> >
+ map1(std::back_inserter(v1));
+ LoggerBoolMap<vec::iterator> map2(v2.begin());
+ map1.set(10, false);
+ map1.set(20, true); map2.set(20, true);
+ map1.set(30, false); map2.set(40, false);
+ map1.set(50, true); map2.set(50, true);
+ map1.set(60, true); map2.set(60, true);
+ check(v1.size() == 3 && v2.size() == 10 &&
+ v1[0]==20 && v1[1]==50 && v1[2]==60 &&
+ v2[0]==20 && v2[1]==50 && v2[2]==60,
+ "Something is wrong with LoggerBoolMap");
+
+ int i = 0;
+ for ( LoggerBoolMap<vec::iterator>::Iterator it = map2.begin();
+ it != map2.end(); ++it )
+ check(v1[i++] == *it, "Something is wrong with LoggerBoolMap");
+
+ typedef ListDigraph Graph;
+ DIGRAPH_TYPEDEFS(Graph);
+ Graph gr;
+
+ Node n0 = gr.addNode();
+ Node n1 = gr.addNode();
+ Node n2 = gr.addNode();
+ Node n3 = gr.addNode();
+
+ gr.addArc(n3, n0);
+ gr.addArc(n3, n2);
+ gr.addArc(n0, n2);
+ gr.addArc(n2, n1);
+ gr.addArc(n0, n1);
+
+ {
+ std::vector<Node> v;
+ dfs(gr).processedMap(loggerBoolMap(std::back_inserter(v))).run();
+
+ check(v.size()==4 && v[0]==n1 && v[1]==n2 && v[2]==n0 && v[3]==n3,
+ "Something is wrong with LoggerBoolMap");
+ }
+ {
+ std::vector<Node> v(countNodes(gr));
+ dfs(gr).processedMap(loggerBoolMap(v.begin())).run();
+
+ check(v.size()==4 && v[0]==n1 && v[1]==n2 && v[2]==n0 && v[3]==n3,
+ "Something is wrong with LoggerBoolMap");
+ }
+ }
+
+ // IdMap, RangeIdMap
+ {
+ typedef ListDigraph Graph;
+ DIGRAPH_TYPEDEFS(Graph);
+
+ checkConcept<ReadMap<Node, int>, IdMap<Graph, Node> >();
+ checkConcept<ReadMap<Arc, int>, IdMap<Graph, Arc> >();
+ checkConcept<ReadMap<Node, int>, RangeIdMap<Graph, Node> >();
+ checkConcept<ReadMap<Arc, int>, RangeIdMap<Graph, Arc> >();
+
+ Graph gr;
+ IdMap<Graph, Node> nmap(gr);
+ IdMap<Graph, Arc> amap(gr);
+ RangeIdMap<Graph, Node> nrmap(gr);
+ RangeIdMap<Graph, Arc> armap(gr);
+
+ Node n0 = gr.addNode();
+ Node n1 = gr.addNode();
+ Node n2 = gr.addNode();
+
+ Arc a0 = gr.addArc(n0, n1);
+ Arc a1 = gr.addArc(n0, n2);
+ Arc a2 = gr.addArc(n2, n1);
+ Arc a3 = gr.addArc(n2, n0);
+
+ check(nmap[n0] == gr.id(n0) && nmap(gr.id(n0)) == n0, "Wrong IdMap");
+ check(nmap[n1] == gr.id(n1) && nmap(gr.id(n1)) == n1, "Wrong IdMap");
+ check(nmap[n2] == gr.id(n2) && nmap(gr.id(n2)) == n2, "Wrong IdMap");
+
+ check(amap[a0] == gr.id(a0) && amap(gr.id(a0)) == a0, "Wrong IdMap");
+ check(amap[a1] == gr.id(a1) && amap(gr.id(a1)) == a1, "Wrong IdMap");
+ check(amap[a2] == gr.id(a2) && amap(gr.id(a2)) == a2, "Wrong IdMap");
+ check(amap[a3] == gr.id(a3) && amap(gr.id(a3)) == a3, "Wrong IdMap");
+
+ check(nmap.inverse()[gr.id(n0)] == n0, "Wrong IdMap::InverseMap");
+ check(amap.inverse()[gr.id(a0)] == a0, "Wrong IdMap::InverseMap");
+
+ check(nrmap.size() == 3 && armap.size() == 4,
+ "Wrong RangeIdMap::size()");
+
+ check(nrmap[n0] == 0 && nrmap(0) == n0, "Wrong RangeIdMap");
+ check(nrmap[n1] == 1 && nrmap(1) == n1, "Wrong RangeIdMap");
+ check(nrmap[n2] == 2 && nrmap(2) == n2, "Wrong RangeIdMap");
+
+ check(armap[a0] == 0 && armap(0) == a0, "Wrong RangeIdMap");
+ check(armap[a1] == 1 && armap(1) == a1, "Wrong RangeIdMap");
+ check(armap[a2] == 2 && armap(2) == a2, "Wrong RangeIdMap");
+ check(armap[a3] == 3 && armap(3) == a3, "Wrong RangeIdMap");
+
+ check(nrmap.inverse()[0] == n0, "Wrong RangeIdMap::InverseMap");
+ check(armap.inverse()[0] == a0, "Wrong RangeIdMap::InverseMap");
+
+ gr.erase(n1);
+
+ if (nrmap[n0] == 1) nrmap.swap(n0, n2);
+ nrmap.swap(n2, n0);
+ if (armap[a1] == 1) armap.swap(a1, a3);
+ armap.swap(a3, a1);
+
+ check(nrmap.size() == 2 && armap.size() == 2,
+ "Wrong RangeIdMap::size()");
+
+ check(nrmap[n0] == 1 && nrmap(1) == n0, "Wrong RangeIdMap");
+ check(nrmap[n2] == 0 && nrmap(0) == n2, "Wrong RangeIdMap");
+
+ check(armap[a1] == 1 && armap(1) == a1, "Wrong RangeIdMap");
+ check(armap[a3] == 0 && armap(0) == a3, "Wrong RangeIdMap");
+
+ check(nrmap.inverse()[0] == n2, "Wrong RangeIdMap::InverseMap");
+ check(armap.inverse()[0] == a3, "Wrong RangeIdMap::InverseMap");
+ }
+
+ // SourceMap, TargetMap, ForwardMap, BackwardMap, InDegMap, OutDegMap
+ {
+ typedef ListGraph Graph;
+ GRAPH_TYPEDEFS(Graph);
+
+ checkConcept<ReadMap<Arc, Node>, SourceMap<Graph> >();
+ checkConcept<ReadMap<Arc, Node>, TargetMap<Graph> >();
+ checkConcept<ReadMap<Edge, Arc>, ForwardMap<Graph> >();
+ checkConcept<ReadMap<Edge, Arc>, BackwardMap<Graph> >();
+ checkConcept<ReadMap<Node, int>, InDegMap<Graph> >();
+ checkConcept<ReadMap<Node, int>, OutDegMap<Graph> >();
+
+ Graph gr;
+ Node n0 = gr.addNode();
+ Node n1 = gr.addNode();
+ Node n2 = gr.addNode();
+
+ gr.addEdge(n0,n1);
+ gr.addEdge(n1,n2);
+ gr.addEdge(n0,n2);
+ gr.addEdge(n2,n1);
+ gr.addEdge(n1,n2);
+ gr.addEdge(n0,n1);
+
+ for (EdgeIt e(gr); e != INVALID; ++e) {
+ check(forwardMap(gr)[e] == gr.direct(e, true), "Wrong ForwardMap");
+ check(backwardMap(gr)[e] == gr.direct(e, false), "Wrong BackwardMap");
+ }
+
+ check(mapCompare(gr,
+ sourceMap(orienter(gr, constMap<Edge, bool>(true))),
+ targetMap(orienter(gr, constMap<Edge, bool>(false)))),
+ "Wrong SourceMap or TargetMap");
+
+ typedef Orienter<Graph, const ConstMap<Edge, bool> > Digraph;
+ ConstMap<Edge, bool> true_edge_map(true);
+ Digraph dgr(gr, true_edge_map);
+ OutDegMap<Digraph> odm(dgr);
+ InDegMap<Digraph> idm(dgr);
+
+ check(odm[n0] == 3 && odm[n1] == 2 && odm[n2] == 1, "Wrong OutDegMap");
+ check(idm[n0] == 0 && idm[n1] == 3 && idm[n2] == 3, "Wrong InDegMap");
+
+ gr.addEdge(n2, n0);
+
+ check(odm[n0] == 3 && odm[n1] == 2 && odm[n2] == 2, "Wrong OutDegMap");
+ check(idm[n0] == 1 && idm[n1] == 3 && idm[n2] == 3, "Wrong InDegMap");
+ }
+
+ // CrossRefMap
+ {
+ typedef ListDigraph Graph;
+ DIGRAPH_TYPEDEFS(Graph);
+
+ checkConcept<ReadWriteMap<Node, int>,
+ CrossRefMap<Graph, Node, int> >();
+ checkConcept<ReadWriteMap<Node, bool>,
+ CrossRefMap<Graph, Node, bool> >();
+ checkConcept<ReadWriteMap<Node, double>,
+ CrossRefMap<Graph, Node, double> >();
+
+ Graph gr;
+ typedef CrossRefMap<Graph, Node, char> CRMap;
+ CRMap map(gr);
+
+ Node n0 = gr.addNode();
+ Node n1 = gr.addNode();
+ Node n2 = gr.addNode();
+
+ map.set(n0, 'A');
+ map.set(n1, 'B');
+ map.set(n2, 'C');
+
+ check(map[n0] == 'A' && map('A') == n0 && map.inverse()['A'] == n0,
+ "Wrong CrossRefMap");
+ check(map[n1] == 'B' && map('B') == n1 && map.inverse()['B'] == n1,
+ "Wrong CrossRefMap");
+ check(map[n2] == 'C' && map('C') == n2 && map.inverse()['C'] == n2,
+ "Wrong CrossRefMap");
+ check(map.count('A') == 1 && map.count('B') == 1 && map.count('C') == 1,
+ "Wrong CrossRefMap::count()");
+
+ CRMap::ValueIt it = map.beginValue();
+ check(*it++ == 'A' && *it++ == 'B' && *it++ == 'C' &&
+ it == map.endValue(), "Wrong value iterator");
+
+ map.set(n2, 'A');
+
+ check(map[n0] == 'A' && map[n1] == 'B' && map[n2] == 'A',
+ "Wrong CrossRefMap");
+ check(map('A') == n0 && map.inverse()['A'] == n0, "Wrong CrossRefMap");
+ check(map('B') == n1 && map.inverse()['B'] == n1, "Wrong CrossRefMap");
+ check(map('C') == INVALID && map.inverse()['C'] == INVALID,
+ "Wrong CrossRefMap");
+ check(map.count('A') == 2 && map.count('B') == 1 && map.count('C') == 0,
+ "Wrong CrossRefMap::count()");
+
+ it = map.beginValue();
+ check(*it++ == 'A' && *it++ == 'A' && *it++ == 'B' &&
+ it == map.endValue(), "Wrong value iterator");
+
+ map.set(n0, 'C');
+
+ check(map[n0] == 'C' && map[n1] == 'B' && map[n2] == 'A',
+ "Wrong CrossRefMap");
+ check(map('A') == n2 && map.inverse()['A'] == n2, "Wrong CrossRefMap");
+ check(map('B') == n1 && map.inverse()['B'] == n1, "Wrong CrossRefMap");
+ check(map('C') == n0 && map.inverse()['C'] == n0, "Wrong CrossRefMap");
+ check(map.count('A') == 1 && map.count('B') == 1 && map.count('C') == 1,
+ "Wrong CrossRefMap::count()");
+
+ it = map.beginValue();
+ check(*it++ == 'A' && *it++ == 'B' && *it++ == 'C' &&
+ it == map.endValue(), "Wrong value iterator");
+ }
+
+ // CrossRefMap
+ {
+ typedef SmartDigraph Graph;
+ DIGRAPH_TYPEDEFS(Graph);
+
+ checkConcept<ReadWriteMap<Node, int>,
+ CrossRefMap<Graph, Node, int> >();
+
+ Graph gr;
+ typedef CrossRefMap<Graph, Node, char> CRMap;
+ typedef CRMap::ValueIterator ValueIt;
+ CRMap map(gr);
+
+ Node n0 = gr.addNode();
+ Node n1 = gr.addNode();
+ Node n2 = gr.addNode();
+
+ map.set(n0, 'A');
+ map.set(n1, 'B');
+ map.set(n2, 'C');
+ map.set(n2, 'A');
+ map.set(n0, 'C');
+
+ check(map[n0] == 'C' && map[n1] == 'B' && map[n2] == 'A',
+ "Wrong CrossRefMap");
+ check(map('A') == n2 && map.inverse()['A'] == n2, "Wrong CrossRefMap");
+ check(map('B') == n1 && map.inverse()['B'] == n1, "Wrong CrossRefMap");
+ check(map('C') == n0 && map.inverse()['C'] == n0, "Wrong CrossRefMap");
+
+ ValueIt it = map.beginValue();
+ check(*it++ == 'A' && *it++ == 'B' && *it++ == 'C' &&
+ it == map.endValue(), "Wrong value iterator");
+ }
+
+ // Iterable bool map
+ {
+ typedef SmartGraph Graph;
+ typedef SmartGraph::Node Item;
+
+ typedef IterableBoolMap<SmartGraph, SmartGraph::Node> Ibm;
+ checkConcept<ReferenceMap<Item, bool, bool&, const bool&>, Ibm>();
+
+ const int num = 10;
+ Graph g;
+ Ibm map0(g, true);
+ std::vector<Item> items;
+ for (int i = 0; i < num; ++i) {
+ items.push_back(g.addNode());
+ }
+
+ Ibm map1(g, true);
+ int n = 0;
+ for (Ibm::TrueIt it(map1); it != INVALID; ++it) {
+ check(map1[static_cast<Item>(it)], "Wrong TrueIt");
+ ++n;
+ }
+ check(n == num, "Wrong number");
+
+ n = 0;
+ for (Ibm::ItemIt it(map1, true); it != INVALID; ++it) {
+ check(map1[static_cast<Item>(it)], "Wrong ItemIt for true");
+ ++n;
+ }
+ check(n == num, "Wrong number");
+ check(Ibm::FalseIt(map1) == INVALID, "Wrong FalseIt");
+ check(Ibm::ItemIt(map1, false) == INVALID, "Wrong ItemIt for false");
+
+ map1[items[5]] = true;
+
+ n = 0;
+ for (Ibm::ItemIt it(map1, true); it != INVALID; ++it) {
+ check(map1[static_cast<Item>(it)], "Wrong ItemIt for true");
+ ++n;
+ }
+ check(n == num, "Wrong number");
+
+ map1[items[num / 2]] = false;
+ check(map1[items[num / 2]] == false, "Wrong map value");
+
+ n = 0;
+ for (Ibm::TrueIt it(map1); it != INVALID; ++it) {
+ check(map1[static_cast<Item>(it)], "Wrong TrueIt for true");
+ ++n;
+ }
+ check(n == num - 1, "Wrong number");
+
+ n = 0;
+ for (Ibm::FalseIt it(map1); it != INVALID; ++it) {
+ check(!map1[static_cast<Item>(it)], "Wrong FalseIt for true");
+ ++n;
+ }
+ check(n == 1, "Wrong number");
+
+ map1[items[0]] = false;
+ check(map1[items[0]] == false, "Wrong map value");
+
+ map1[items[num - 1]] = false;
+ check(map1[items[num - 1]] == false, "Wrong map value");
+
+ n = 0;
+ for (Ibm::TrueIt it(map1); it != INVALID; ++it) {
+ check(map1[static_cast<Item>(it)], "Wrong TrueIt for true");
+ ++n;
+ }
+ check(n == num - 3, "Wrong number");
+ check(map1.trueNum() == num - 3, "Wrong number");
+
+ n = 0;
+ for (Ibm::FalseIt it(map1); it != INVALID; ++it) {
+ check(!map1[static_cast<Item>(it)], "Wrong FalseIt for true");
+ ++n;
+ }
+ check(n == 3, "Wrong number");
+ check(map1.falseNum() == 3, "Wrong number");
+ }
+
+ // Iterable int map
+ {
+ typedef SmartGraph Graph;
+ typedef SmartGraph::Node Item;
+ typedef IterableIntMap<SmartGraph, SmartGraph::Node> Iim;
+
+ checkConcept<ReferenceMap<Item, int, int&, const int&>, Iim>();
+
+ const int num = 10;
+ Graph g;
+ Iim map0(g, 0);
+ std::vector<Item> items;
+ for (int i = 0; i < num; ++i) {
+ items.push_back(g.addNode());
+ }
+
+ Iim map1(g);
+ check(map1.size() == 0, "Wrong size");
+
+ for (int i = 0; i < num; ++i) {
+ map1[items[i]] = i;
+ }
+ check(map1.size() == num, "Wrong size");
+
+ for (int i = 0; i < num; ++i) {
+ Iim::ItemIt it(map1, i);
+ check(static_cast<Item>(it) == items[i], "Wrong value");
+ ++it;
+ check(static_cast<Item>(it) == INVALID, "Wrong value");
+ }
+
+ for (int i = 0; i < num; ++i) {
+ map1[items[i]] = i % 2;
+ }
+ check(map1.size() == 2, "Wrong size");
+
+ int n = 0;
+ for (Iim::ItemIt it(map1, 0); it != INVALID; ++it) {
+ check(map1[static_cast<Item>(it)] == 0, "Wrong value");
+ ++n;
+ }
+ check(n == (num + 1) / 2, "Wrong number");
+
+ for (Iim::ItemIt it(map1, 1); it != INVALID; ++it) {
+ check(map1[static_cast<Item>(it)] == 1, "Wrong value");
+ ++n;
+ }
+ check(n == num, "Wrong number");
+
+ }
+
+ // Iterable value map
+ {
+ typedef SmartGraph Graph;
+ typedef SmartGraph::Node Item;
+ typedef IterableValueMap<SmartGraph, SmartGraph::Node, double> Ivm;
+
+ checkConcept<ReadWriteMap<Item, double>, Ivm>();
+
+ const int num = 10;
+ Graph g;
+ Ivm map0(g, 0.0);
+ std::vector<Item> items;
+ for (int i = 0; i < num; ++i) {
+ items.push_back(g.addNode());
+ }
+
+ Ivm map1(g, 0.0);
+ check(distance(map1.beginValue(), map1.endValue()) == 1, "Wrong size");
+ check(*map1.beginValue() == 0.0, "Wrong value");
+
+ for (int i = 0; i < num; ++i) {
+ map1.set(items[i], static_cast<double>(i));
+ }
+ check(distance(map1.beginValue(), map1.endValue()) == num, "Wrong size");
+
+ for (int i = 0; i < num; ++i) {
+ Ivm::ItemIt it(map1, static_cast<double>(i));
+ check(static_cast<Item>(it) == items[i], "Wrong value");
+ ++it;
+ check(static_cast<Item>(it) == INVALID, "Wrong value");
+ }
+
+ for (Ivm::ValueIt vit = map1.beginValue();
+ vit != map1.endValue(); ++vit) {
+ check(map1[static_cast<Item>(Ivm::ItemIt(map1, *vit))] == *vit,
+ "Wrong ValueIt");
+ }
+
+ for (int i = 0; i < num; ++i) {
+ map1.set(items[i], static_cast<double>(i % 2));
+ }
+ check(distance(map1.beginValue(), map1.endValue()) == 2, "Wrong size");
+
+ int n = 0;
+ for (Ivm::ItemIt it(map1, 0.0); it != INVALID; ++it) {
+ check(map1[static_cast<Item>(it)] == 0.0, "Wrong value");
+ ++n;
+ }
+ check(n == (num + 1) / 2, "Wrong number");
+
+ for (Ivm::ItemIt it(map1, 1.0); it != INVALID; ++it) {
+ check(map1[static_cast<Item>(it)] == 1.0, "Wrong value");
+ ++n;
+ }
+ check(n == num, "Wrong number");
+
+ }
+
+ // Graph map utilities:
+ // mapMin(), mapMax(), mapMinValue(), mapMaxValue()
+ // mapFind(), mapFindIf(), mapCount(), mapCountIf()
+ // mapCopy(), mapCompare(), mapFill()
+ {
+ DIGRAPH_TYPEDEFS(SmartDigraph);
+
+ SmartDigraph g;
+ Node n1 = g.addNode();
+ Node n2 = g.addNode();
+ Node n3 = g.addNode();
+
+ SmartDigraph::NodeMap<int> map1(g);
+ SmartDigraph::ArcMap<char> map2(g);
+ ConstMap<Node, A> cmap1 = A();
+ ConstMap<Arc, C> cmap2 = C(0);
+
+ map1[n1] = 10;
+ map1[n2] = 5;
+ map1[n3] = 12;
+
+ // mapMin(), mapMax(), mapMinValue(), mapMaxValue()
+ check(mapMin(g, map1) == n2, "Wrong mapMin()");
+ check(mapMax(g, map1) == n3, "Wrong mapMax()");
+ check(mapMin(g, map1, std::greater<int>()) == n3, "Wrong mapMin()");
+ check(mapMax(g, map1, std::greater<int>()) == n2, "Wrong mapMax()");
+ check(mapMinValue(g, map1) == 5, "Wrong mapMinValue()");
+ check(mapMaxValue(g, map1) == 12, "Wrong mapMaxValue()");
+
+ check(mapMin(g, map2) == INVALID, "Wrong mapMin()");
+ check(mapMax(g, map2) == INVALID, "Wrong mapMax()");
+
+ check(mapMin(g, cmap1) != INVALID, "Wrong mapMin()");
+ check(mapMax(g, cmap2) == INVALID, "Wrong mapMax()");
+
+ Arc a1 = g.addArc(n1, n2);
+ Arc a2 = g.addArc(n1, n3);
+ Arc a3 = g.addArc(n2, n3);
+ Arc a4 = g.addArc(n3, n1);
+
+ map2[a1] = 'b';
+ map2[a2] = 'a';
+ map2[a3] = 'b';
+ map2[a4] = 'c';
+
+ // mapMin(), mapMax(), mapMinValue(), mapMaxValue()
+ check(mapMin(g, map2) == a2, "Wrong mapMin()");
+ check(mapMax(g, map2) == a4, "Wrong mapMax()");
+ check(mapMin(g, map2, std::greater<int>()) == a4, "Wrong mapMin()");
+ check(mapMax(g, map2, std::greater<int>()) == a2, "Wrong mapMax()");
+ check(mapMinValue(g, map2, std::greater<int>()) == 'c',
+ "Wrong mapMinValue()");
+ check(mapMaxValue(g, map2, std::greater<int>()) == 'a',
+ "Wrong mapMaxValue()");
+
+ check(mapMin(g, cmap1) != INVALID, "Wrong mapMin()");
+ check(mapMax(g, cmap2) != INVALID, "Wrong mapMax()");
+ check(mapMaxValue(g, cmap2) == C(0), "Wrong mapMaxValue()");
+
+ check(mapMin(g, composeMap(functorToMap(&createC), map2)) == a2,
+ "Wrong mapMin()");
+ check(mapMax(g, composeMap(functorToMap(&createC), map2)) == a4,
+ "Wrong mapMax()");
+ check(mapMinValue(g, composeMap(functorToMap(&createC), map2)) == C('a'),
+ "Wrong mapMinValue()");
+ check(mapMaxValue(g, composeMap(functorToMap(&createC), map2)) == C('c'),
+ "Wrong mapMaxValue()");
+
+ // mapFind(), mapFindIf()
+ check(mapFind(g, map1, 5) == n2, "Wrong mapFind()");
+ check(mapFind(g, map1, 6) == INVALID, "Wrong mapFind()");
+ check(mapFind(g, map2, 'a') == a2, "Wrong mapFind()");
+ check(mapFind(g, map2, 'e') == INVALID, "Wrong mapFind()");
+ check(mapFind(g, cmap2, C(0)) == ArcIt(g), "Wrong mapFind()");
+ check(mapFind(g, cmap2, C(1)) == INVALID, "Wrong mapFind()");
+
+ check(mapFindIf(g, map1, Less<int>(7)) == n2,
+ "Wrong mapFindIf()");
+ check(mapFindIf(g, map1, Less<int>(5)) == INVALID,
+ "Wrong mapFindIf()");
+ check(mapFindIf(g, map2, Less<char>('d')) == ArcIt(g),
+ "Wrong mapFindIf()");
+ check(mapFindIf(g, map2, Less<char>('a')) == INVALID,
+ "Wrong mapFindIf()");
+
+ // mapCount(), mapCountIf()
+ check(mapCount(g, map1, 5) == 1, "Wrong mapCount()");
+ check(mapCount(g, map1, 6) == 0, "Wrong mapCount()");
+ check(mapCount(g, map2, 'a') == 1, "Wrong mapCount()");
+ check(mapCount(g, map2, 'b') == 2, "Wrong mapCount()");
+ check(mapCount(g, map2, 'e') == 0, "Wrong mapCount()");
+ check(mapCount(g, cmap2, C(0)) == 4, "Wrong mapCount()");
+ check(mapCount(g, cmap2, C(1)) == 0, "Wrong mapCount()");
+
+ check(mapCountIf(g, map1, Less<int>(11)) == 2,
+ "Wrong mapCountIf()");
+ check(mapCountIf(g, map1, Less<int>(13)) == 3,
+ "Wrong mapCountIf()");
+ check(mapCountIf(g, map1, Less<int>(5)) == 0,
+ "Wrong mapCountIf()");
+ check(mapCountIf(g, map2, Less<char>('d')) == 4,
+ "Wrong mapCountIf()");
+ check(mapCountIf(g, map2, Less<char>('c')) == 3,
+ "Wrong mapCountIf()");
+ check(mapCountIf(g, map2, Less<char>('a')) == 0,
+ "Wrong mapCountIf()");
+
+ // MapIt, ConstMapIt
+/*
+These tests can be used after applying bugfix #330
+ typedef SmartDigraph::NodeMap<int>::MapIt MapIt;
+ typedef SmartDigraph::NodeMap<int>::ConstMapIt ConstMapIt;
+ check(*std::min_element(MapIt(map1), MapIt(INVALID)) == 5,
+ "Wrong NodeMap<>::MapIt");
+ check(*std::max_element(ConstMapIt(map1), ConstMapIt(INVALID)) == 12,
+ "Wrong NodeMap<>::MapIt");
+
+ int sum = 0;
+ std::for_each(MapIt(map1), MapIt(INVALID), Sum<int>(sum));
+ check(sum == 27, "Wrong NodeMap<>::MapIt");
+ std::for_each(ConstMapIt(map1), ConstMapIt(INVALID), Sum<int>(sum));
+ check(sum == 54, "Wrong NodeMap<>::ConstMapIt");
+*/
+
+ // mapCopy(), mapCompare(), mapFill()
+ check(mapCompare(g, map1, map1), "Wrong mapCompare()");
+ check(mapCompare(g, cmap2, cmap2), "Wrong mapCompare()");
+ check(mapCompare(g, map1, shiftMap(map1, 0)), "Wrong mapCompare()");
+ check(mapCompare(g, map2, scaleMap(map2, 1)), "Wrong mapCompare()");
+ check(!mapCompare(g, map1, shiftMap(map1, 1)), "Wrong mapCompare()");
+
+ SmartDigraph::NodeMap<int> map3(g, 0);
+ SmartDigraph::ArcMap<char> map4(g, 'a');
+
+ check(!mapCompare(g, map1, map3), "Wrong mapCompare()");
+ check(!mapCompare(g, map2, map4), "Wrong mapCompare()");
+
+ mapCopy(g, map1, map3);
+ mapCopy(g, map2, map4);
+
+ check(mapCompare(g, map1, map3), "Wrong mapCompare() or mapCopy()");
+ check(mapCompare(g, map2, map4), "Wrong mapCompare() or mapCopy()");
+
+ Undirector<SmartDigraph> ug(g);
+ Undirector<SmartDigraph>::EdgeMap<char> umap1(ug, 'x');
+ Undirector<SmartDigraph>::ArcMap<double> umap2(ug, 3.14);
+
+ check(!mapCompare(g, map2, umap1), "Wrong mapCompare() or mapCopy()");
+ check(!mapCompare(g, umap1, map2), "Wrong mapCompare() or mapCopy()");
+ check(!mapCompare(ug, map2, umap1), "Wrong mapCompare() or mapCopy()");
+ check(!mapCompare(ug, umap1, map2), "Wrong mapCompare() or mapCopy()");
+
+ mapCopy(g, map2, umap1);
+
+ check(mapCompare(g, map2, umap1), "Wrong mapCompare() or mapCopy()");
+ check(mapCompare(g, umap1, map2), "Wrong mapCompare() or mapCopy()");
+ check(mapCompare(ug, map2, umap1), "Wrong mapCompare() or mapCopy()");
+ check(mapCompare(ug, umap1, map2), "Wrong mapCompare() or mapCopy()");
+
+ mapCopy(g, map2, umap1);
+ mapCopy(g, umap1, map2);
+ mapCopy(ug, map2, umap1);
+ mapCopy(ug, umap1, map2);
+
+ check(!mapCompare(ug, umap1, umap2), "Wrong mapCompare() or mapCopy()");
+ mapCopy(ug, umap1, umap2);
+ check(mapCompare(ug, umap1, umap2), "Wrong mapCompare() or mapCopy()");
+
+ check(!mapCompare(g, map1, constMap<Node>(2)), "Wrong mapCompare()");
+ mapFill(g, map1, 2);
+ check(mapCompare(g, constMap<Node>(2), map1), "Wrong mapFill()");
+
+ check(!mapCompare(g, map2, constMap<Arc>('z')), "Wrong mapCompare()");
+ mapCopy(g, constMap<Arc>('z'), map2);
+ check(mapCompare(g, constMap<Arc>('z'), map2), "Wrong mapCopy()");
+ }
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/matching_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/matching_test.cc
new file mode 100644
index 00000000000..dcb1d3b5752
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/matching_test.cc
@@ -0,0 +1,449 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <queue>
+#include <cstdlib>
+
+#include <lemon/matching.h>
+#include <lemon/smart_graph.h>
+#include <lemon/concepts/graph.h>
+#include <lemon/concepts/maps.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/math.h>
+
+#include "test_tools.h"
+
+using namespace std;
+using namespace lemon;
+
+GRAPH_TYPEDEFS(SmartGraph);
+
+
+const int lgfn = 3;
+const std::string lgf[lgfn] = {
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "6\n"
+ "7\n"
+ "@edges\n"
+ " label weight\n"
+ "7 4 0 984\n"
+ "0 7 1 73\n"
+ "7 1 2 204\n"
+ "2 3 3 583\n"
+ "2 7 4 565\n"
+ "2 1 5 582\n"
+ "0 4 6 551\n"
+ "2 5 7 385\n"
+ "1 5 8 561\n"
+ "5 3 9 484\n"
+ "7 5 10 904\n"
+ "3 6 11 47\n"
+ "7 6 12 888\n"
+ "3 0 13 747\n"
+ "6 1 14 310\n",
+
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "6\n"
+ "7\n"
+ "@edges\n"
+ " label weight\n"
+ "2 5 0 710\n"
+ "0 5 1 241\n"
+ "2 4 2 856\n"
+ "2 6 3 762\n"
+ "4 1 4 747\n"
+ "6 1 5 962\n"
+ "4 7 6 723\n"
+ "1 7 7 661\n"
+ "2 3 8 376\n"
+ "1 0 9 416\n"
+ "6 7 10 391\n",
+
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "6\n"
+ "7\n"
+ "@edges\n"
+ " label weight\n"
+ "6 2 0 553\n"
+ "0 7 1 653\n"
+ "6 3 2 22\n"
+ "4 7 3 846\n"
+ "7 2 4 981\n"
+ "7 6 5 250\n"
+ "5 2 6 539\n",
+};
+
+void checkMaxMatchingCompile()
+{
+ typedef concepts::Graph Graph;
+ typedef Graph::Node Node;
+ typedef Graph::Edge Edge;
+ typedef Graph::EdgeMap<bool> MatMap;
+
+ Graph g;
+ Node n;
+ Edge e;
+ MatMap mat(g);
+
+ MaxMatching<Graph> mat_test(g);
+ const MaxMatching<Graph>&
+ const_mat_test = mat_test;
+
+ mat_test.init();
+ mat_test.greedyInit();
+ mat_test.matchingInit(mat);
+ mat_test.startSparse();
+ mat_test.startDense();
+ mat_test.run();
+
+ const_mat_test.matchingSize();
+ const_mat_test.matching(e);
+ const_mat_test.matching(n);
+ const MaxMatching<Graph>::MatchingMap& mmap =
+ const_mat_test.matchingMap();
+ e = mmap[n];
+ const_mat_test.mate(n);
+
+ MaxMatching<Graph>::Status stat =
+ const_mat_test.status(n);
+ ::lemon::ignore_unused_variable_warning(stat);
+ const MaxMatching<Graph>::StatusMap& smap =
+ const_mat_test.statusMap();
+ stat = smap[n];
+ const_mat_test.barrier(n);
+}
+
+void checkMaxWeightedMatchingCompile()
+{
+ typedef concepts::Graph Graph;
+ typedef Graph::Node Node;
+ typedef Graph::Edge Edge;
+ typedef Graph::EdgeMap<int> WeightMap;
+
+ Graph g;
+ Node n;
+ Edge e;
+ WeightMap w(g);
+
+ MaxWeightedMatching<Graph> mat_test(g, w);
+ const MaxWeightedMatching<Graph>&
+ const_mat_test = mat_test;
+
+ mat_test.init();
+ mat_test.start();
+ mat_test.run();
+
+ const_mat_test.matchingWeight();
+ const_mat_test.matchingSize();
+ const_mat_test.matching(e);
+ const_mat_test.matching(n);
+ const MaxWeightedMatching<Graph>::MatchingMap& mmap =
+ const_mat_test.matchingMap();
+ e = mmap[n];
+ const_mat_test.mate(n);
+
+ int k = 0;
+ const_mat_test.dualValue();
+ const_mat_test.nodeValue(n);
+ const_mat_test.blossomNum();
+ const_mat_test.blossomSize(k);
+ const_mat_test.blossomValue(k);
+}
+
+void checkMaxWeightedPerfectMatchingCompile()
+{
+ typedef concepts::Graph Graph;
+ typedef Graph::Node Node;
+ typedef Graph::Edge Edge;
+ typedef Graph::EdgeMap<int> WeightMap;
+
+ Graph g;
+ Node n;
+ Edge e;
+ WeightMap w(g);
+
+ MaxWeightedPerfectMatching<Graph> mat_test(g, w);
+ const MaxWeightedPerfectMatching<Graph>&
+ const_mat_test = mat_test;
+
+ mat_test.init();
+ mat_test.start();
+ mat_test.run();
+
+ const_mat_test.matchingWeight();
+ const_mat_test.matching(e);
+ const_mat_test.matching(n);
+ const MaxWeightedPerfectMatching<Graph>::MatchingMap& mmap =
+ const_mat_test.matchingMap();
+ e = mmap[n];
+ const_mat_test.mate(n);
+
+ int k = 0;
+ const_mat_test.dualValue();
+ const_mat_test.nodeValue(n);
+ const_mat_test.blossomNum();
+ const_mat_test.blossomSize(k);
+ const_mat_test.blossomValue(k);
+}
+
+void checkMatching(const SmartGraph& graph,
+ const MaxMatching<SmartGraph>& mm) {
+ int num = 0;
+
+ IntNodeMap comp_index(graph);
+ UnionFind<IntNodeMap> comp(comp_index);
+
+ int barrier_num = 0;
+
+ for (NodeIt n(graph); n != INVALID; ++n) {
+ check(mm.status(n) == MaxMatching<SmartGraph>::EVEN ||
+ mm.matching(n) != INVALID, "Wrong Gallai-Edmonds decomposition");
+ if (mm.status(n) == MaxMatching<SmartGraph>::ODD) {
+ ++barrier_num;
+ } else {
+ comp.insert(n);
+ }
+ }
+
+ for (EdgeIt e(graph); e != INVALID; ++e) {
+ if (mm.matching(e)) {
+ check(e == mm.matching(graph.u(e)), "Wrong matching");
+ check(e == mm.matching(graph.v(e)), "Wrong matching");
+ ++num;
+ }
+ check(mm.status(graph.u(e)) != MaxMatching<SmartGraph>::EVEN ||
+ mm.status(graph.v(e)) != MaxMatching<SmartGraph>::MATCHED,
+ "Wrong Gallai-Edmonds decomposition");
+
+ check(mm.status(graph.v(e)) != MaxMatching<SmartGraph>::EVEN ||
+ mm.status(graph.u(e)) != MaxMatching<SmartGraph>::MATCHED,
+ "Wrong Gallai-Edmonds decomposition");
+
+ if (mm.status(graph.u(e)) != MaxMatching<SmartGraph>::ODD &&
+ mm.status(graph.v(e)) != MaxMatching<SmartGraph>::ODD) {
+ comp.join(graph.u(e), graph.v(e));
+ }
+ }
+
+ std::set<int> comp_root;
+ int odd_comp_num = 0;
+ for (NodeIt n(graph); n != INVALID; ++n) {
+ if (mm.status(n) != MaxMatching<SmartGraph>::ODD) {
+ int root = comp.find(n);
+ if (comp_root.find(root) == comp_root.end()) {
+ comp_root.insert(root);
+ if (comp.size(n) % 2 == 1) {
+ ++odd_comp_num;
+ }
+ }
+ }
+ }
+
+ check(mm.matchingSize() == num, "Wrong matching");
+ check(2 * num == countNodes(graph) - (odd_comp_num - barrier_num),
+ "Wrong matching");
+ return;
+}
+
+void checkWeightedMatching(const SmartGraph& graph,
+ const SmartGraph::EdgeMap<int>& weight,
+ const MaxWeightedMatching<SmartGraph>& mwm) {
+ for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
+ if (graph.u(e) == graph.v(e)) continue;
+ int rw = mwm.nodeValue(graph.u(e)) + mwm.nodeValue(graph.v(e));
+
+ for (int i = 0; i < mwm.blossomNum(); ++i) {
+ bool s = false, t = false;
+ for (MaxWeightedMatching<SmartGraph>::BlossomIt n(mwm, i);
+ n != INVALID; ++n) {
+ if (graph.u(e) == n) s = true;
+ if (graph.v(e) == n) t = true;
+ }
+ if (s == true && t == true) {
+ rw += mwm.blossomValue(i);
+ }
+ }
+ rw -= weight[e] * mwm.dualScale;
+
+ check(rw >= 0, "Negative reduced weight");
+ check(rw == 0 || !mwm.matching(e),
+ "Non-zero reduced weight on matching edge");
+ }
+
+ int pv = 0;
+ for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
+ if (mwm.matching(n) != INVALID) {
+ check(mwm.nodeValue(n) >= 0, "Invalid node value");
+ pv += weight[mwm.matching(n)];
+ SmartGraph::Node o = graph.target(mwm.matching(n));
+ check(mwm.mate(n) == o, "Invalid matching");
+ check(mwm.matching(n) == graph.oppositeArc(mwm.matching(o)),
+ "Invalid matching");
+ } else {
+ check(mwm.mate(n) == INVALID, "Invalid matching");
+ check(mwm.nodeValue(n) == 0, "Invalid matching");
+ }
+ }
+
+ int dv = 0;
+ for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
+ dv += mwm.nodeValue(n);
+ }
+
+ for (int i = 0; i < mwm.blossomNum(); ++i) {
+ check(mwm.blossomValue(i) >= 0, "Invalid blossom value");
+ check(mwm.blossomSize(i) % 2 == 1, "Even blossom size");
+ dv += mwm.blossomValue(i) * ((mwm.blossomSize(i) - 1) / 2);
+ }
+
+ check(pv * mwm.dualScale == dv * 2, "Wrong duality");
+
+ return;
+}
+
+void checkWeightedPerfectMatching(const SmartGraph& graph,
+ const SmartGraph::EdgeMap<int>& weight,
+ const MaxWeightedPerfectMatching<SmartGraph>& mwpm) {
+ for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
+ if (graph.u(e) == graph.v(e)) continue;
+ int rw = mwpm.nodeValue(graph.u(e)) + mwpm.nodeValue(graph.v(e));
+
+ for (int i = 0; i < mwpm.blossomNum(); ++i) {
+ bool s = false, t = false;
+ for (MaxWeightedPerfectMatching<SmartGraph>::BlossomIt n(mwpm, i);
+ n != INVALID; ++n) {
+ if (graph.u(e) == n) s = true;
+ if (graph.v(e) == n) t = true;
+ }
+ if (s == true && t == true) {
+ rw += mwpm.blossomValue(i);
+ }
+ }
+ rw -= weight[e] * mwpm.dualScale;
+
+ check(rw >= 0, "Negative reduced weight");
+ check(rw == 0 || !mwpm.matching(e),
+ "Non-zero reduced weight on matching edge");
+ }
+
+ int pv = 0;
+ for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
+ check(mwpm.matching(n) != INVALID, "Non perfect");
+ pv += weight[mwpm.matching(n)];
+ SmartGraph::Node o = graph.target(mwpm.matching(n));
+ check(mwpm.mate(n) == o, "Invalid matching");
+ check(mwpm.matching(n) == graph.oppositeArc(mwpm.matching(o)),
+ "Invalid matching");
+ }
+
+ int dv = 0;
+ for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
+ dv += mwpm.nodeValue(n);
+ }
+
+ for (int i = 0; i < mwpm.blossomNum(); ++i) {
+ check(mwpm.blossomValue(i) >= 0, "Invalid blossom value");
+ check(mwpm.blossomSize(i) % 2 == 1, "Even blossom size");
+ dv += mwpm.blossomValue(i) * ((mwpm.blossomSize(i) - 1) / 2);
+ }
+
+ check(pv * mwpm.dualScale == dv * 2, "Wrong duality");
+
+ return;
+}
+
+
+int main() {
+
+ for (int i = 0; i < lgfn; ++i) {
+ SmartGraph graph;
+ SmartGraph::EdgeMap<int> weight(graph);
+
+ istringstream lgfs(lgf[i]);
+ graphReader(graph, lgfs).
+ edgeMap("weight", weight).run();
+
+ bool perfect;
+ {
+ MaxMatching<SmartGraph> mm(graph);
+ mm.run();
+ checkMatching(graph, mm);
+ perfect = 2 * mm.matchingSize() == countNodes(graph);
+ }
+
+ {
+ MaxWeightedMatching<SmartGraph> mwm(graph, weight);
+ mwm.run();
+ checkWeightedMatching(graph, weight, mwm);
+ }
+
+ {
+ MaxWeightedMatching<SmartGraph> mwm(graph, weight);
+ mwm.init();
+ mwm.start();
+ checkWeightedMatching(graph, weight, mwm);
+ }
+
+ {
+ MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
+ bool result = mwpm.run();
+
+ check(result == perfect, "Perfect matching found");
+ if (perfect) {
+ checkWeightedPerfectMatching(graph, weight, mwpm);
+ }
+ }
+
+ {
+ MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
+ mwpm.init();
+ bool result = mwpm.start();
+
+ check(result == perfect, "Perfect matching found");
+ if (perfect) {
+ checkWeightedPerfectMatching(graph, weight, mwpm);
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/max_cardinality_search_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/max_cardinality_search_test.cc
new file mode 100644
index 00000000000..c01066f36e7
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/max_cardinality_search_test.cc
@@ -0,0 +1,162 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+
+#include "test_tools.h"
+#include <lemon/smart_graph.h>
+#include <lemon/max_cardinality_search.h>
+#include <lemon/concepts/digraph.h>
+#include <lemon/concepts/maps.h>
+#include <lemon/concepts/heap.h>
+#include <lemon/lgf_reader.h>
+
+using namespace lemon;
+using namespace std;
+
+char test_lgf[] =
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "@arcs\n"
+ " label capacity\n"
+ "0 1 0 2\n"
+ "1 0 1 2\n"
+ "2 1 2 1\n"
+ "2 3 3 3\n"
+ "3 2 4 3\n"
+ "3 1 5 5\n"
+ "@attributes\n"
+ "s 0\n"
+ "x 1\n"
+ "y 2\n"
+ "z 3\n";
+
+void checkMaxCardSearchCompile() {
+
+ typedef concepts::Digraph Digraph;
+ typedef int Value;
+ typedef Digraph::Node Node;
+ typedef Digraph::Arc Arc;
+ typedef concepts::ReadMap<Arc,Value> CapMap;
+ typedef concepts::ReadWriteMap<Node,Value> CardMap;
+ typedef concepts::ReadWriteMap<Node,bool> ProcMap;
+ typedef Digraph::NodeMap<int> HeapCrossRef;
+
+ Digraph g;
+ Node n,s;
+ CapMap cap;
+ CardMap card;
+ ProcMap proc;
+ HeapCrossRef crossref(g);
+
+ typedef MaxCardinalitySearch<Digraph,CapMap>
+ ::SetCapacityMap<CapMap>
+ ::SetCardinalityMap<CardMap>
+ ::SetProcessedMap<ProcMap>
+ ::SetStandardHeap<BinHeap<Value,HeapCrossRef> >
+ ::Create MaxCardType;
+
+ MaxCardType maxcard(g,cap);
+ const MaxCardType& const_maxcard = maxcard;
+
+ const MaxCardType::Heap& heap_const = const_maxcard.heap();
+ MaxCardType::Heap& heap = const_cast<MaxCardType::Heap&>(heap_const);
+ maxcard.heap(heap,crossref);
+
+ maxcard.capacityMap(cap).cardinalityMap(card).processedMap(proc);
+
+ maxcard.init();
+ maxcard.addSource(s);
+ n = maxcard.nextNode();
+ maxcard.processNextNode();
+ maxcard.start();
+ maxcard.run(s);
+ maxcard.run();
+ }
+
+ void checkWithIntMap( std::istringstream& input)
+ {
+ typedef SmartDigraph Digraph;
+ typedef Digraph::Node Node;
+ typedef Digraph::ArcMap<int> CapMap;
+
+ Digraph g;
+ Node s,x,y,z,a;
+ CapMap cap(g);
+
+ DigraphReader<Digraph>(g,input).
+ arcMap("capacity", cap).
+ node("s",s).
+ node("x",x).
+ node("y",y).
+ node("z",z).
+ run();
+
+ MaxCardinalitySearch<Digraph,CapMap> maxcard(g,cap);
+
+ maxcard.init();
+ maxcard.addSource(s);
+ maxcard.start(x);
+
+ check(maxcard.processed(s) && !maxcard.processed(x) &&
+ !maxcard.processed(y), "Wrong processed()!");
+
+ a=maxcard.nextNode();
+ check(maxcard.processNextNode()==a,
+ "Wrong nextNode() or processNextNode() return value!");
+
+ check(maxcard.processed(a), "Wrong processNextNode()!");
+
+ maxcard.start();
+ check(maxcard.cardinality(x)==2 && maxcard.cardinality(y)>=4,
+ "Wrong cardinalities!");
+ }
+
+ void checkWithConst1Map(std::istringstream &input) {
+ typedef SmartDigraph Digraph;
+ typedef Digraph::Node Node;
+
+ Digraph g;
+ Node s,x,y,z;
+
+ DigraphReader<Digraph>(g,input).
+ node("s",s).
+ node("x",x).
+ node("y",y).
+ node("z",z).
+ run();
+
+ MaxCardinalitySearch<Digraph> maxcard(g);
+ maxcard.run(s);
+ check(maxcard.cardinality(x)==1 &&
+ maxcard.cardinality(y)+maxcard.cardinality(z)==3,
+ "Wrong cardinalities!");
+}
+
+int main() {
+
+ std::istringstream input1(test_lgf);
+ checkWithIntMap(input1);
+
+ std::istringstream input2(test_lgf);
+ checkWithConst1Map(input2);
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/max_clique_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/max_clique_test.cc
new file mode 100644
index 00000000000..d16f0f99072
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/max_clique_test.cc
@@ -0,0 +1,188 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <sstream>
+#include <lemon/list_graph.h>
+#include <lemon/full_graph.h>
+#include <lemon/grid_graph.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/grosso_locatelli_pullan_mc.h>
+
+#include "test_tools.h"
+
+using namespace lemon;
+
+char test_lgf[] =
+ "@nodes\n"
+ "label max_clique\n"
+ "1 0\n"
+ "2 0\n"
+ "3 0\n"
+ "4 1\n"
+ "5 1\n"
+ "6 1\n"
+ "7 1\n"
+ "@edges\n"
+ " label\n"
+ "1 2 1\n"
+ "1 3 2\n"
+ "1 4 3\n"
+ "1 6 4\n"
+ "2 3 5\n"
+ "2 5 6\n"
+ "2 7 7\n"
+ "3 4 8\n"
+ "3 5 9\n"
+ "4 5 10\n"
+ "4 6 11\n"
+ "4 7 12\n"
+ "5 6 13\n"
+ "5 7 14\n"
+ "6 7 15\n";
+
+
+// Check with general graphs
+template <typename Param>
+void checkMaxCliqueGeneral(Param rule) {
+ typedef ListGraph GR;
+ typedef GrossoLocatelliPullanMc<GR> McAlg;
+ typedef McAlg::CliqueNodeIt CliqueIt;
+
+ // Basic tests
+ {
+ GR g;
+ GR::NodeMap<bool> map(g);
+ McAlg mc(g);
+ mc.iterationLimit(50);
+ check(mc.run(rule) == McAlg::SIZE_LIMIT, "Wrong termination cause");
+ check(mc.cliqueSize() == 0, "Wrong clique size");
+ check(CliqueIt(mc) == INVALID, "Wrong CliqueNodeIt");
+
+ GR::Node u = g.addNode();
+ check(mc.run(rule) == McAlg::SIZE_LIMIT, "Wrong termination cause");
+ check(mc.cliqueSize() == 1, "Wrong clique size");
+ mc.cliqueMap(map);
+ check(map[u], "Wrong clique map");
+ CliqueIt it1(mc);
+ check(static_cast<GR::Node>(it1) == u && ++it1 == INVALID,
+ "Wrong CliqueNodeIt");
+
+ GR::Node v = g.addNode();
+ check(mc.run(rule) == McAlg::ITERATION_LIMIT, "Wrong termination cause");
+ check(mc.cliqueSize() == 1, "Wrong clique size");
+ mc.cliqueMap(map);
+ check((map[u] && !map[v]) || (map[v] && !map[u]), "Wrong clique map");
+ CliqueIt it2(mc);
+ check(it2 != INVALID && ++it2 == INVALID, "Wrong CliqueNodeIt");
+
+ g.addEdge(u, v);
+ check(mc.run(rule) == McAlg::SIZE_LIMIT, "Wrong termination cause");
+ check(mc.cliqueSize() == 2, "Wrong clique size");
+ mc.cliqueMap(map);
+ check(map[u] && map[v], "Wrong clique map");
+ CliqueIt it3(mc);
+ check(it3 != INVALID && ++it3 != INVALID && ++it3 == INVALID,
+ "Wrong CliqueNodeIt");
+ }
+
+ // Test graph
+ {
+ GR g;
+ GR::NodeMap<bool> max_clique(g);
+ GR::NodeMap<bool> map(g);
+ std::istringstream input(test_lgf);
+ graphReader(g, input)
+ .nodeMap("max_clique", max_clique)
+ .run();
+
+ McAlg mc(g);
+ mc.iterationLimit(50);
+ check(mc.run(rule) == McAlg::ITERATION_LIMIT, "Wrong termination cause");
+ check(mc.cliqueSize() == 4, "Wrong clique size");
+ mc.cliqueMap(map);
+ for (GR::NodeIt n(g); n != INVALID; ++n) {
+ check(map[n] == max_clique[n], "Wrong clique map");
+ }
+ int cnt = 0;
+ for (CliqueIt n(mc); n != INVALID; ++n) {
+ cnt++;
+ check(map[n] && max_clique[n], "Wrong CliqueNodeIt");
+ }
+ check(cnt == 4, "Wrong CliqueNodeIt");
+ }
+}
+
+// Check with full graphs
+template <typename Param>
+void checkMaxCliqueFullGraph(Param rule) {
+ typedef FullGraph GR;
+ typedef GrossoLocatelliPullanMc<FullGraph> McAlg;
+ typedef McAlg::CliqueNodeIt CliqueIt;
+
+ for (int size = 0; size <= 40; size = size * 3 + 1) {
+ GR g(size);
+ GR::NodeMap<bool> map(g);
+ McAlg mc(g);
+ check(mc.run(rule) == McAlg::SIZE_LIMIT, "Wrong termination cause");
+ check(mc.cliqueSize() == size, "Wrong clique size");
+ mc.cliqueMap(map);
+ for (GR::NodeIt n(g); n != INVALID; ++n) {
+ check(map[n], "Wrong clique map");
+ }
+ int cnt = 0;
+ for (CliqueIt n(mc); n != INVALID; ++n) cnt++;
+ check(cnt == size, "Wrong CliqueNodeIt");
+ }
+}
+
+// Check with grid graphs
+template <typename Param>
+void checkMaxCliqueGridGraph(Param rule) {
+ GridGraph g(5, 7);
+ GridGraph::NodeMap<char> map(g);
+ GrossoLocatelliPullanMc<GridGraph> mc(g);
+
+ mc.iterationLimit(100);
+ check(mc.run(rule) == mc.ITERATION_LIMIT, "Wrong termination cause");
+ check(mc.cliqueSize() == 2, "Wrong clique size");
+
+ mc.stepLimit(100);
+ check(mc.run(rule) == mc.STEP_LIMIT, "Wrong termination cause");
+ check(mc.cliqueSize() == 2, "Wrong clique size");
+
+ mc.sizeLimit(2);
+ check(mc.run(rule) == mc.SIZE_LIMIT, "Wrong termination cause");
+ check(mc.cliqueSize() == 2, "Wrong clique size");
+}
+
+
+int main() {
+ checkMaxCliqueGeneral(GrossoLocatelliPullanMc<ListGraph>::RANDOM);
+ checkMaxCliqueGeneral(GrossoLocatelliPullanMc<ListGraph>::DEGREE_BASED);
+ checkMaxCliqueGeneral(GrossoLocatelliPullanMc<ListGraph>::PENALTY_BASED);
+
+ checkMaxCliqueFullGraph(GrossoLocatelliPullanMc<FullGraph>::RANDOM);
+ checkMaxCliqueFullGraph(GrossoLocatelliPullanMc<FullGraph>::DEGREE_BASED);
+ checkMaxCliqueFullGraph(GrossoLocatelliPullanMc<FullGraph>::PENALTY_BASED);
+
+ checkMaxCliqueGridGraph(GrossoLocatelliPullanMc<GridGraph>::RANDOM);
+ checkMaxCliqueGridGraph(GrossoLocatelliPullanMc<GridGraph>::DEGREE_BASED);
+ checkMaxCliqueGridGraph(GrossoLocatelliPullanMc<GridGraph>::PENALTY_BASED);
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/max_flow_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/max_flow_test.cc
new file mode 100644
index 00000000000..f63874a615a
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/max_flow_test.cc
@@ -0,0 +1,395 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+
+#include "test_tools.h"
+#include <lemon/smart_graph.h>
+#include <lemon/preflow.h>
+#include <lemon/edmonds_karp.h>
+#include <lemon/concepts/digraph.h>
+#include <lemon/concepts/maps.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/elevator.h>
+
+using namespace lemon;
+
+char test_lgf[] =
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "6\n"
+ "7\n"
+ "8\n"
+ "9\n"
+ "@arcs\n"
+ " label capacity\n"
+ "0 1 0 20\n"
+ "0 2 1 0\n"
+ "1 1 2 3\n"
+ "1 2 3 8\n"
+ "1 3 4 8\n"
+ "2 5 5 5\n"
+ "3 2 6 5\n"
+ "3 5 7 5\n"
+ "3 6 8 5\n"
+ "4 3 9 3\n"
+ "5 7 10 3\n"
+ "5 6 11 10\n"
+ "5 8 12 10\n"
+ "6 8 13 8\n"
+ "8 9 14 20\n"
+ "8 1 15 5\n"
+ "9 5 16 5\n"
+ "@attributes\n"
+ "source 1\n"
+ "target 8\n";
+
+
+// Checks the general interface of a max flow algorithm
+template <typename GR, typename CAP>
+struct MaxFlowClassConcept
+{
+
+ template <typename MF>
+ struct Constraints {
+
+ typedef typename GR::Node Node;
+ typedef typename GR::Arc Arc;
+ typedef typename CAP::Value Value;
+ typedef concepts::ReadWriteMap<Arc, Value> FlowMap;
+ typedef concepts::WriteMap<Node, bool> CutMap;
+
+ GR g;
+ Node n;
+ Arc e;
+ CAP cap;
+ FlowMap flow;
+ CutMap cut;
+ Value v;
+ bool b;
+
+ void constraints() {
+ checkConcept<concepts::Digraph, GR>();
+
+ const Constraints& me = *this;
+
+ typedef typename MF
+ ::template SetFlowMap<FlowMap>
+ ::Create MaxFlowType;
+ typedef typename MF::Create MaxFlowType2;
+ MaxFlowType max_flow(me.g, me.cap, me.n, me.n);
+ const MaxFlowType& const_max_flow = max_flow;
+
+ max_flow
+ .capacityMap(cap)
+ .flowMap(flow)
+ .source(n)
+ .target(n);
+
+ typename MaxFlowType::Tolerance tol = const_max_flow.tolerance();
+ max_flow.tolerance(tol);
+
+ max_flow.init();
+ max_flow.init(cap);
+ max_flow.run();
+
+ v = const_max_flow.flowValue();
+ v = const_max_flow.flow(e);
+ const FlowMap& fm = const_max_flow.flowMap();
+
+ b = const_max_flow.minCut(n);
+ const_max_flow.minCutMap(cut);
+
+ ::lemon::ignore_unused_variable_warning(fm);
+ }
+
+ };
+
+};
+
+// Checks the specific parts of Preflow's interface
+void checkPreflowCompile()
+{
+ typedef int Value;
+ typedef concepts::Digraph Digraph;
+ typedef concepts::ReadMap<Digraph::Arc, Value> CapMap;
+ typedef Elevator<Digraph, Digraph::Node> Elev;
+ typedef LinkedElevator<Digraph, Digraph::Node> LinkedElev;
+
+ Digraph g;
+ Digraph::Node n;
+ CapMap cap;
+
+ typedef Preflow<Digraph, CapMap>
+ ::SetElevator<Elev>
+ ::SetStandardElevator<LinkedElev>
+ ::Create PreflowType;
+ PreflowType preflow_test(g, cap, n, n);
+ const PreflowType& const_preflow_test = preflow_test;
+
+ const PreflowType::Elevator& elev = const_preflow_test.elevator();
+ preflow_test.elevator(const_cast<PreflowType::Elevator&>(elev));
+
+ bool b = preflow_test.init(cap);
+ preflow_test.startFirstPhase();
+ preflow_test.startSecondPhase();
+ preflow_test.runMinCut();
+
+ ::lemon::ignore_unused_variable_warning(b);
+}
+
+// Checks the specific parts of EdmondsKarp's interface
+void checkEdmondsKarpCompile()
+{
+ typedef int Value;
+ typedef concepts::Digraph Digraph;
+ typedef concepts::ReadMap<Digraph::Arc, Value> CapMap;
+ typedef Elevator<Digraph, Digraph::Node> Elev;
+ typedef LinkedElevator<Digraph, Digraph::Node> LinkedElev;
+
+ Digraph g;
+ Digraph::Node n;
+ CapMap cap;
+
+ EdmondsKarp<Digraph, CapMap> ek_test(g, cap, n, n);
+
+ ek_test.init(cap);
+ bool b = ek_test.checkedInit(cap);
+ b = ek_test.augment();
+ ek_test.start();
+
+ ::lemon::ignore_unused_variable_warning(b);
+}
+
+
+template <typename T>
+T cutValue (const SmartDigraph& g,
+ const SmartDigraph::NodeMap<bool>& cut,
+ const SmartDigraph::ArcMap<T>& cap) {
+
+ T c=0;
+ for(SmartDigraph::ArcIt e(g); e!=INVALID; ++e) {
+ if (cut[g.source(e)] && !cut[g.target(e)]) c+=cap[e];
+ }
+ return c;
+}
+
+template <typename T>
+bool checkFlow(const SmartDigraph& g,
+ const SmartDigraph::ArcMap<T>& flow,
+ const SmartDigraph::ArcMap<T>& cap,
+ SmartDigraph::Node s, SmartDigraph::Node t) {
+
+ for (SmartDigraph::ArcIt e(g); e != INVALID; ++e) {
+ if (flow[e] < 0 || flow[e] > cap[e]) return false;
+ }
+
+ for (SmartDigraph::NodeIt n(g); n != INVALID; ++n) {
+ if (n == s || n == t) continue;
+ T sum = 0;
+ for (SmartDigraph::OutArcIt e(g, n); e != INVALID; ++e) {
+ sum += flow[e];
+ }
+ for (SmartDigraph::InArcIt e(g, n); e != INVALID; ++e) {
+ sum -= flow[e];
+ }
+ if (sum != 0) return false;
+ }
+ return true;
+}
+
+void initFlowTest()
+{
+ DIGRAPH_TYPEDEFS(SmartDigraph);
+
+ SmartDigraph g;
+ SmartDigraph::ArcMap<int> cap(g),iflow(g);
+ Node s=g.addNode(); Node t=g.addNode();
+ Node n1=g.addNode(); Node n2=g.addNode();
+ Arc a;
+ a=g.addArc(s,n1); cap[a]=20; iflow[a]=20;
+ a=g.addArc(n1,n2); cap[a]=10; iflow[a]=0;
+ a=g.addArc(n2,t); cap[a]=20; iflow[a]=0;
+
+ Preflow<SmartDigraph> pre(g,cap,s,t);
+ pre.init(iflow);
+ pre.startFirstPhase();
+ check(pre.flowValue() == 10, "The incorrect max flow value.");
+ check(pre.minCut(s), "Wrong min cut (Node s).");
+ check(pre.minCut(n1), "Wrong min cut (Node n1).");
+ check(!pre.minCut(n2), "Wrong min cut (Node n2).");
+ check(!pre.minCut(t), "Wrong min cut (Node t).");
+}
+
+template <typename MF, typename SF>
+void checkMaxFlowAlg() {
+ typedef SmartDigraph Digraph;
+ DIGRAPH_TYPEDEFS(Digraph);
+
+ typedef typename MF::Value Value;
+ typedef Digraph::ArcMap<Value> CapMap;
+ typedef CapMap FlowMap;
+ typedef BoolNodeMap CutMap;
+
+ Digraph g;
+ Node s, t;
+ CapMap cap(g);
+ std::istringstream input(test_lgf);
+ DigraphReader<Digraph>(g,input)
+ .arcMap("capacity", cap)
+ .node("source",s)
+ .node("target",t)
+ .run();
+
+ MF max_flow(g, cap, s, t);
+ max_flow.run();
+
+ check(checkFlow(g, max_flow.flowMap(), cap, s, t),
+ "The flow is not feasible.");
+
+ CutMap min_cut(g);
+ max_flow.minCutMap(min_cut);
+ Value min_cut_value = cutValue(g, min_cut, cap);
+
+ check(max_flow.flowValue() == min_cut_value,
+ "The max flow value is not equal to the min cut value.");
+
+ FlowMap flow(g);
+ for (ArcIt e(g); e != INVALID; ++e) flow[e] = max_flow.flowMap()[e];
+
+ Value flow_value = max_flow.flowValue();
+
+ for (ArcIt e(g); e != INVALID; ++e) cap[e] = 2 * cap[e];
+ max_flow.init(flow);
+
+ SF::startFirstPhase(max_flow); // start first phase of the algorithm
+
+ CutMap min_cut1(g);
+ max_flow.minCutMap(min_cut1);
+ min_cut_value = cutValue(g, min_cut1, cap);
+
+ check(max_flow.flowValue() == min_cut_value &&
+ min_cut_value == 2 * flow_value,
+ "The max flow value or the min cut value is wrong.");
+
+ SF::startSecondPhase(max_flow); // start second phase of the algorithm
+
+ check(checkFlow(g, max_flow.flowMap(), cap, s, t),
+ "The flow is not feasible.");
+
+ CutMap min_cut2(g);
+ max_flow.minCutMap(min_cut2);
+ min_cut_value = cutValue(g, min_cut2, cap);
+
+ check(max_flow.flowValue() == min_cut_value &&
+ min_cut_value == 2 * flow_value,
+ "The max flow value or the min cut value was not doubled");
+
+
+ max_flow.flowMap(flow);
+
+ NodeIt tmp1(g, s);
+ ++tmp1;
+ if (tmp1 != INVALID) s = tmp1;
+
+ NodeIt tmp2(g, t);
+ ++tmp2;
+ if (tmp2 != INVALID) t = tmp2;
+
+ max_flow.source(s);
+ max_flow.target(t);
+
+ max_flow.run();
+
+ CutMap min_cut3(g);
+ max_flow.minCutMap(min_cut3);
+ min_cut_value=cutValue(g, min_cut3, cap);
+
+ check(max_flow.flowValue() == min_cut_value,
+ "The max flow value or the min cut value is wrong.");
+}
+
+// Struct for calling start functions of a general max flow algorithm
+template <typename MF>
+struct GeneralStartFunctions {
+
+ static void startFirstPhase(MF& mf) {
+ mf.start();
+ }
+
+ static void startSecondPhase(MF& mf) {
+ ::lemon::ignore_unused_variable_warning(mf);
+ }
+
+};
+
+// Struct for calling start functions of Preflow
+template <typename MF>
+struct PreflowStartFunctions {
+
+ static void startFirstPhase(MF& mf) {
+ mf.startFirstPhase();
+ }
+
+ static void startSecondPhase(MF& mf) {
+ mf.startSecondPhase();
+ }
+
+};
+
+int main() {
+
+ typedef concepts::Digraph GR;
+ typedef concepts::ReadMap<GR::Arc, int> CM1;
+ typedef concepts::ReadMap<GR::Arc, double> CM2;
+
+ // Check the interface of Preflow
+ checkConcept< MaxFlowClassConcept<GR, CM1>,
+ Preflow<GR, CM1> >();
+ checkConcept< MaxFlowClassConcept<GR, CM2>,
+ Preflow<GR, CM2> >();
+
+ // Check the interface of EdmondsKarp
+ checkConcept< MaxFlowClassConcept<GR, CM1>,
+ EdmondsKarp<GR, CM1> >();
+ checkConcept< MaxFlowClassConcept<GR, CM2>,
+ EdmondsKarp<GR, CM2> >();
+
+ // Check Preflow
+ typedef Preflow<SmartDigraph, SmartDigraph::ArcMap<int> > PType1;
+ typedef Preflow<SmartDigraph, SmartDigraph::ArcMap<float> > PType2;
+ checkMaxFlowAlg<PType1, PreflowStartFunctions<PType1> >();
+ checkMaxFlowAlg<PType2, PreflowStartFunctions<PType2> >();
+ initFlowTest();
+
+ // Check EdmondsKarp
+ typedef EdmondsKarp<SmartDigraph, SmartDigraph::ArcMap<int> > EKType1;
+ typedef EdmondsKarp<SmartDigraph, SmartDigraph::ArcMap<float> > EKType2;
+ checkMaxFlowAlg<EKType1, GeneralStartFunctions<EKType1> >();
+ checkMaxFlowAlg<EKType2, GeneralStartFunctions<EKType2> >();
+
+ initFlowTest();
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/min_cost_arborescence_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/min_cost_arborescence_test.cc
new file mode 100644
index 00000000000..3a5ea36f1ea
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/min_cost_arborescence_test.cc
@@ -0,0 +1,207 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+#include <set>
+#include <vector>
+#include <iterator>
+
+#include <lemon/smart_graph.h>
+#include <lemon/min_cost_arborescence.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/concepts/digraph.h>
+
+#include "test_tools.h"
+
+using namespace lemon;
+using namespace std;
+
+const char test_lgf[] =
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "6\n"
+ "7\n"
+ "8\n"
+ "9\n"
+ "@arcs\n"
+ " label cost\n"
+ "1 8 0 107\n"
+ "0 3 1 70\n"
+ "2 1 2 46\n"
+ "4 1 3 28\n"
+ "4 4 4 91\n"
+ "3 9 5 76\n"
+ "9 8 6 61\n"
+ "8 1 7 39\n"
+ "9 8 8 74\n"
+ "8 0 9 39\n"
+ "4 3 10 45\n"
+ "2 2 11 34\n"
+ "0 1 12 100\n"
+ "6 3 13 95\n"
+ "4 1 14 22\n"
+ "1 1 15 31\n"
+ "7 2 16 51\n"
+ "2 6 17 29\n"
+ "8 3 18 115\n"
+ "6 9 19 32\n"
+ "1 1 20 60\n"
+ "0 3 21 40\n"
+ "@attributes\n"
+ "source 0\n";
+
+
+void checkMinCostArborescenceCompile()
+{
+ typedef double VType;
+ typedef concepts::Digraph Digraph;
+ typedef concepts::ReadMap<Digraph::Arc, VType> CostMap;
+ typedef Digraph::Node Node;
+ typedef Digraph::Arc Arc;
+ typedef concepts::WriteMap<Digraph::Arc, bool> ArbMap;
+ typedef concepts::ReadWriteMap<Digraph::Node, Digraph::Arc> PredMap;
+
+ typedef MinCostArborescence<Digraph, CostMap>::
+ SetArborescenceMap<ArbMap>::
+ SetPredMap<PredMap>::Create MinCostArbType;
+
+ Digraph g;
+ Node s, n;
+ Arc e;
+ VType c;
+ bool b;
+ ::lemon::ignore_unused_variable_warning(c,b);
+ int i;
+ CostMap cost;
+ ArbMap arb;
+ PredMap pred;
+
+ MinCostArbType mcarb_test(g, cost);
+ const MinCostArbType& const_mcarb_test = mcarb_test;
+
+ mcarb_test
+ .arborescenceMap(arb)
+ .predMap(pred)
+ .run(s);
+
+ mcarb_test.init();
+ mcarb_test.addSource(s);
+ mcarb_test.start();
+ n = mcarb_test.processNextNode();
+ b = const_mcarb_test.emptyQueue();
+ i = const_mcarb_test.queueSize();
+
+ c = const_mcarb_test.arborescenceCost();
+ b = const_mcarb_test.arborescence(e);
+ e = const_mcarb_test.pred(n);
+ const MinCostArbType::ArborescenceMap &am =
+ const_mcarb_test.arborescenceMap();
+ const MinCostArbType::PredMap &pm =
+ const_mcarb_test.predMap();
+ b = const_mcarb_test.reached(n);
+ b = const_mcarb_test.processed(n);
+
+ i = const_mcarb_test.dualNum();
+ c = const_mcarb_test.dualValue();
+ i = const_mcarb_test.dualSize(i);
+ c = const_mcarb_test.dualValue(i);
+
+ ::lemon::ignore_unused_variable_warning(am);
+ ::lemon::ignore_unused_variable_warning(pm);
+}
+
+int main() {
+ typedef SmartDigraph Digraph;
+ DIGRAPH_TYPEDEFS(Digraph);
+
+ typedef Digraph::ArcMap<double> CostMap;
+
+ Digraph digraph;
+ CostMap cost(digraph);
+ Node source;
+
+ std::istringstream is(test_lgf);
+ digraphReader(digraph, is).
+ arcMap("cost", cost).
+ node("source", source).run();
+
+ MinCostArborescence<Digraph, CostMap> mca(digraph, cost);
+ mca.run(source);
+
+ vector<pair<double, set<Node> > > dualSolution(mca.dualNum());
+
+ for (int i = 0; i < mca.dualNum(); ++i) {
+ dualSolution[i].first = mca.dualValue(i);
+ for (MinCostArborescence<Digraph, CostMap>::DualIt it(mca, i);
+ it != INVALID; ++it) {
+ dualSolution[i].second.insert(it);
+ }
+ }
+
+ for (ArcIt it(digraph); it != INVALID; ++it) {
+ if (mca.reached(digraph.source(it))) {
+ double sum = 0.0;
+ for (int i = 0; i < int(dualSolution.size()); ++i) {
+ if (dualSolution[i].second.find(digraph.target(it))
+ != dualSolution[i].second.end() &&
+ dualSolution[i].second.find(digraph.source(it))
+ == dualSolution[i].second.end()) {
+ sum += dualSolution[i].first;
+ }
+ }
+ if (mca.arborescence(it)) {
+ check(sum == cost[it], "Invalid dual solution");
+ }
+ check(sum <= cost[it], "Invalid dual solution");
+ }
+ }
+
+
+ check(mca.dualValue() == mca.arborescenceCost(), "Invalid dual solution");
+
+ check(mca.reached(source), "Invalid arborescence");
+ for (ArcIt a(digraph); a != INVALID; ++a) {
+ check(!mca.reached(digraph.source(a)) ||
+ mca.reached(digraph.target(a)), "Invalid arborescence");
+ }
+
+ for (NodeIt n(digraph); n != INVALID; ++n) {
+ if (!mca.reached(n)) continue;
+ int cnt = 0;
+ for (InArcIt a(digraph, n); a != INVALID; ++a) {
+ if (mca.arborescence(a)) {
+ check(mca.pred(n) == a, "Invalid arborescence");
+ ++cnt;
+ }
+ }
+ check((n == source ? cnt == 0 : cnt == 1), "Invalid arborescence");
+ }
+
+ Digraph::ArcMap<bool> arborescence(digraph);
+ check(mca.arborescenceCost() ==
+ minCostArborescence(digraph, cost, source, arborescence),
+ "Wrong result of the function interface");
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/min_cost_flow_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/min_cost_flow_test.cc
new file mode 100644
index 00000000000..15dcf542d36
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/min_cost_flow_test.cc
@@ -0,0 +1,548 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+#include <fstream>
+#include <limits>
+
+#include <lemon/list_graph.h>
+#include <lemon/lgf_reader.h>
+
+#include <lemon/network_simplex.h>
+#include <lemon/capacity_scaling.h>
+#include <lemon/cost_scaling.h>
+#include <lemon/cycle_canceling.h>
+
+#include <lemon/concepts/digraph.h>
+#include <lemon/concepts/heap.h>
+#include <lemon/concept_check.h>
+
+#include "test_tools.h"
+
+using namespace lemon;
+
+// Test networks
+char test_lgf[] =
+ "@nodes\n"
+ "label sup1 sup2 sup3 sup4 sup5 sup6\n"
+ " 1 20 27 0 30 20 30\n"
+ " 2 -4 0 0 0 -8 -3\n"
+ " 3 0 0 0 0 0 0\n"
+ " 4 0 0 0 0 0 0\n"
+ " 5 9 0 0 0 6 11\n"
+ " 6 -6 0 0 0 -5 -6\n"
+ " 7 0 0 0 0 0 0\n"
+ " 8 0 0 0 0 0 3\n"
+ " 9 3 0 0 0 0 0\n"
+ " 10 -2 0 0 0 -7 -2\n"
+ " 11 0 0 0 0 -10 0\n"
+ " 12 -20 -27 0 -30 -30 -20\n"
+ "\n"
+ "@arcs\n"
+ " cost cap low1 low2 low3\n"
+ " 1 2 70 11 0 8 8\n"
+ " 1 3 150 3 0 1 0\n"
+ " 1 4 80 15 0 2 2\n"
+ " 2 8 80 12 0 0 0\n"
+ " 3 5 140 5 0 3 1\n"
+ " 4 6 60 10 0 1 0\n"
+ " 4 7 80 2 0 0 0\n"
+ " 4 8 110 3 0 0 0\n"
+ " 5 7 60 14 0 0 0\n"
+ " 5 11 120 12 0 0 0\n"
+ " 6 3 0 3 0 0 0\n"
+ " 6 9 140 4 0 0 0\n"
+ " 6 10 90 8 0 0 0\n"
+ " 7 1 30 5 0 0 -5\n"
+ " 8 12 60 16 0 4 3\n"
+ " 9 12 50 6 0 0 0\n"
+ "10 12 70 13 0 5 2\n"
+ "10 2 100 7 0 0 0\n"
+ "10 7 60 10 0 0 -3\n"
+ "11 10 20 14 0 6 -20\n"
+ "12 11 30 10 0 0 -10\n"
+ "\n"
+ "@attributes\n"
+ "source 1\n"
+ "target 12\n";
+
+char test_neg1_lgf[] =
+ "@nodes\n"
+ "label sup\n"
+ " 1 100\n"
+ " 2 0\n"
+ " 3 0\n"
+ " 4 -100\n"
+ " 5 0\n"
+ " 6 0\n"
+ " 7 0\n"
+ "@arcs\n"
+ " cost low1 low2\n"
+ "1 2 100 0 0\n"
+ "1 3 30 0 0\n"
+ "2 4 20 0 0\n"
+ "3 4 80 0 0\n"
+ "3 2 50 0 0\n"
+ "5 3 10 0 0\n"
+ "5 6 80 0 1000\n"
+ "6 7 30 0 -1000\n"
+ "7 5 -120 0 0\n";
+
+char test_neg2_lgf[] =
+ "@nodes\n"
+ "label sup\n"
+ " 1 100\n"
+ " 2 -300\n"
+ "@arcs\n"
+ " cost\n"
+ "1 2 -1\n";
+
+
+// Test data
+typedef ListDigraph Digraph;
+DIGRAPH_TYPEDEFS(ListDigraph);
+
+Digraph gr;
+Digraph::ArcMap<int> c(gr), l1(gr), l2(gr), l3(gr), u(gr);
+Digraph::NodeMap<int> s1(gr), s2(gr), s3(gr), s4(gr), s5(gr), s6(gr);
+ConstMap<Arc, int> cc(1), cu(std::numeric_limits<int>::max());
+Node v, w;
+
+Digraph neg1_gr;
+Digraph::ArcMap<int> neg1_c(neg1_gr), neg1_l1(neg1_gr), neg1_l2(neg1_gr);
+ConstMap<Arc, int> neg1_u1(std::numeric_limits<int>::max()), neg1_u2(5000);
+Digraph::NodeMap<int> neg1_s(neg1_gr);
+
+Digraph neg2_gr;
+Digraph::ArcMap<int> neg2_c(neg2_gr);
+ConstMap<Arc, int> neg2_l(0), neg2_u(1000);
+Digraph::NodeMap<int> neg2_s(neg2_gr);
+
+
+enum SupplyType {
+ EQ,
+ GEQ,
+ LEQ
+};
+
+
+// Check the interface of an MCF algorithm
+template <typename GR, typename Value, typename Cost>
+class McfClassConcept
+{
+public:
+
+ template <typename MCF>
+ struct Constraints {
+ void constraints() {
+ checkConcept<concepts::Digraph, GR>();
+
+ const Constraints& me = *this;
+
+ MCF mcf(me.g);
+ const MCF& const_mcf = mcf;
+
+ b = mcf.reset().resetParams()
+ .lowerMap(me.lower)
+ .upperMap(me.upper)
+ .costMap(me.cost)
+ .supplyMap(me.sup)
+ .stSupply(me.n, me.n, me.k)
+ .run();
+
+ c = const_mcf.totalCost();
+ x = const_mcf.template totalCost<double>();
+ v = const_mcf.flow(me.a);
+ c = const_mcf.potential(me.n);
+ const_mcf.flowMap(fm);
+ const_mcf.potentialMap(pm);
+ }
+
+ typedef typename GR::Node Node;
+ typedef typename GR::Arc Arc;
+ typedef concepts::ReadMap<Node, Value> NM;
+ typedef concepts::ReadMap<Arc, Value> VAM;
+ typedef concepts::ReadMap<Arc, Cost> CAM;
+ typedef concepts::WriteMap<Arc, Value> FlowMap;
+ typedef concepts::WriteMap<Node, Cost> PotMap;
+
+ GR g;
+ VAM lower;
+ VAM upper;
+ CAM cost;
+ NM sup;
+ Node n;
+ Arc a;
+ Value k;
+
+ FlowMap fm;
+ PotMap pm;
+ bool b;
+ double x;
+ typename MCF::Value v;
+ typename MCF::Cost c;
+ };
+
+};
+
+
+// Check the feasibility of the given flow (primal soluiton)
+template < typename GR, typename LM, typename UM,
+ typename SM, typename FM >
+bool checkFlow( const GR& gr, const LM& lower, const UM& upper,
+ const SM& supply, const FM& flow,
+ SupplyType type = EQ )
+{
+ TEMPLATE_DIGRAPH_TYPEDEFS(GR);
+
+ for (ArcIt e(gr); e != INVALID; ++e) {
+ if (flow[e] < lower[e] || flow[e] > upper[e]) return false;
+ }
+
+ for (NodeIt n(gr); n != INVALID; ++n) {
+ typename SM::Value sum = 0;
+ for (OutArcIt e(gr, n); e != INVALID; ++e)
+ sum += flow[e];
+ for (InArcIt e(gr, n); e != INVALID; ++e)
+ sum -= flow[e];
+ bool b = (type == EQ && sum == supply[n]) ||
+ (type == GEQ && sum >= supply[n]) ||
+ (type == LEQ && sum <= supply[n]);
+ if (!b) return false;
+ }
+
+ return true;
+}
+
+// Check the feasibility of the given potentials (dual soluiton)
+// using the "Complementary Slackness" optimality condition
+template < typename GR, typename LM, typename UM,
+ typename CM, typename SM, typename FM, typename PM >
+bool checkPotential( const GR& gr, const LM& lower, const UM& upper,
+ const CM& cost, const SM& supply, const FM& flow,
+ const PM& pi, SupplyType type )
+{
+ TEMPLATE_DIGRAPH_TYPEDEFS(GR);
+
+ bool opt = true;
+ for (ArcIt e(gr); opt && e != INVALID; ++e) {
+ typename CM::Value red_cost =
+ cost[e] + pi[gr.source(e)] - pi[gr.target(e)];
+ opt = red_cost == 0 ||
+ (red_cost > 0 && flow[e] == lower[e]) ||
+ (red_cost < 0 && flow[e] == upper[e]);
+ }
+
+ for (NodeIt n(gr); opt && n != INVALID; ++n) {
+ typename SM::Value sum = 0;
+ for (OutArcIt e(gr, n); e != INVALID; ++e)
+ sum += flow[e];
+ for (InArcIt e(gr, n); e != INVALID; ++e)
+ sum -= flow[e];
+ if (type != LEQ) {
+ opt = (pi[n] <= 0) && (sum == supply[n] || pi[n] == 0);
+ } else {
+ opt = (pi[n] >= 0) && (sum == supply[n] || pi[n] == 0);
+ }
+ }
+
+ return opt;
+}
+
+// Check whether the dual cost is equal to the primal cost
+template < typename GR, typename LM, typename UM,
+ typename CM, typename SM, typename PM >
+bool checkDualCost( const GR& gr, const LM& lower, const UM& upper,
+ const CM& cost, const SM& supply, const PM& pi,
+ typename CM::Value total )
+{
+ TEMPLATE_DIGRAPH_TYPEDEFS(GR);
+
+ typename CM::Value dual_cost = 0;
+ SM red_supply(gr);
+ for (NodeIt n(gr); n != INVALID; ++n) {
+ red_supply[n] = supply[n];
+ }
+ for (ArcIt a(gr); a != INVALID; ++a) {
+ if (lower[a] != 0) {
+ dual_cost += lower[a] * cost[a];
+ red_supply[gr.source(a)] -= lower[a];
+ red_supply[gr.target(a)] += lower[a];
+ }
+ }
+
+ for (NodeIt n(gr); n != INVALID; ++n) {
+ dual_cost -= red_supply[n] * pi[n];
+ }
+ for (ArcIt a(gr); a != INVALID; ++a) {
+ typename CM::Value red_cost =
+ cost[a] + pi[gr.source(a)] - pi[gr.target(a)];
+ dual_cost -= (upper[a] - lower[a]) * std::max(-red_cost, 0);
+ }
+
+ return dual_cost == total;
+}
+
+// Run a minimum cost flow algorithm and check the results
+template < typename MCF, typename GR,
+ typename LM, typename UM,
+ typename CM, typename SM,
+ typename PT >
+void checkMcf( const MCF& mcf, PT mcf_result,
+ const GR& gr, const LM& lower, const UM& upper,
+ const CM& cost, const SM& supply,
+ PT result, bool optimal, typename CM::Value total,
+ const std::string &test_id = "",
+ SupplyType type = EQ )
+{
+ check(mcf_result == result, "Wrong result " + test_id);
+ if (optimal) {
+ typename GR::template ArcMap<typename SM::Value> flow(gr);
+ typename GR::template NodeMap<typename CM::Value> pi(gr);
+ mcf.flowMap(flow);
+ mcf.potentialMap(pi);
+ check(checkFlow(gr, lower, upper, supply, flow, type),
+ "The flow is not feasible " + test_id);
+ check(mcf.totalCost() == total, "The flow is not optimal " + test_id);
+ check(checkPotential(gr, lower, upper, cost, supply, flow, pi, type),
+ "Wrong potentials " + test_id);
+ check(checkDualCost(gr, lower, upper, cost, supply, pi, total),
+ "Wrong dual cost " + test_id);
+ }
+}
+
+template < typename MCF, typename Param >
+void runMcfGeqTests( Param param,
+ const std::string &test_str = "",
+ bool full_neg_cost_support = false )
+{
+ MCF mcf1(gr), mcf2(neg1_gr), mcf3(neg2_gr);
+
+ // Basic tests
+ mcf1.upperMap(u).costMap(c).supplyMap(s1);
+ checkMcf(mcf1, mcf1.run(param), gr, l1, u, c, s1,
+ mcf1.OPTIMAL, true, 5240, test_str + "-1");
+ mcf1.stSupply(v, w, 27);
+ checkMcf(mcf1, mcf1.run(param), gr, l1, u, c, s2,
+ mcf1.OPTIMAL, true, 7620, test_str + "-2");
+ mcf1.lowerMap(l2).supplyMap(s1);
+ checkMcf(mcf1, mcf1.run(param), gr, l2, u, c, s1,
+ mcf1.OPTIMAL, true, 5970, test_str + "-3");
+ mcf1.stSupply(v, w, 27);
+ checkMcf(mcf1, mcf1.run(param), gr, l2, u, c, s2,
+ mcf1.OPTIMAL, true, 8010, test_str + "-4");
+ mcf1.resetParams().supplyMap(s1);
+ checkMcf(mcf1, mcf1.run(param), gr, l1, cu, cc, s1,
+ mcf1.OPTIMAL, true, 74, test_str + "-5");
+ mcf1.lowerMap(l2).stSupply(v, w, 27);
+ checkMcf(mcf1, mcf1.run(param), gr, l2, cu, cc, s2,
+ mcf1.OPTIMAL, true, 94, test_str + "-6");
+ mcf1.reset();
+ checkMcf(mcf1, mcf1.run(param), gr, l1, cu, cc, s3,
+ mcf1.OPTIMAL, true, 0, test_str + "-7");
+ mcf1.lowerMap(l2).upperMap(u);
+ checkMcf(mcf1, mcf1.run(param), gr, l2, u, cc, s3,
+ mcf1.INFEASIBLE, false, 0, test_str + "-8");
+ mcf1.lowerMap(l3).upperMap(u).costMap(c).supplyMap(s4);
+ checkMcf(mcf1, mcf1.run(param), gr, l3, u, c, s4,
+ mcf1.OPTIMAL, true, 6360, test_str + "-9");
+
+ // Tests for the GEQ form
+ mcf1.resetParams().upperMap(u).costMap(c).supplyMap(s5);
+ checkMcf(mcf1, mcf1.run(param), gr, l1, u, c, s5,
+ mcf1.OPTIMAL, true, 3530, test_str + "-10", GEQ);
+ mcf1.lowerMap(l2);
+ checkMcf(mcf1, mcf1.run(param), gr, l2, u, c, s5,
+ mcf1.OPTIMAL, true, 4540, test_str + "-11", GEQ);
+ mcf1.supplyMap(s6);
+ checkMcf(mcf1, mcf1.run(param), gr, l2, u, c, s6,
+ mcf1.INFEASIBLE, false, 0, test_str + "-12", GEQ);
+
+ // Tests with negative costs
+ mcf2.lowerMap(neg1_l1).costMap(neg1_c).supplyMap(neg1_s);
+ checkMcf(mcf2, mcf2.run(param), neg1_gr, neg1_l1, neg1_u1, neg1_c, neg1_s,
+ mcf2.UNBOUNDED, false, 0, test_str + "-13");
+ mcf2.upperMap(neg1_u2);
+ checkMcf(mcf2, mcf2.run(param), neg1_gr, neg1_l1, neg1_u2, neg1_c, neg1_s,
+ mcf2.OPTIMAL, true, -40000, test_str + "-14");
+ mcf2.resetParams().lowerMap(neg1_l2).costMap(neg1_c).supplyMap(neg1_s);
+ checkMcf(mcf2, mcf2.run(param), neg1_gr, neg1_l2, neg1_u1, neg1_c, neg1_s,
+ mcf2.UNBOUNDED, false, 0, test_str + "-15");
+
+ mcf3.costMap(neg2_c).supplyMap(neg2_s);
+ if (full_neg_cost_support) {
+ checkMcf(mcf3, mcf3.run(param), neg2_gr, neg2_l, neg2_u, neg2_c, neg2_s,
+ mcf3.OPTIMAL, true, -300, test_str + "-16", GEQ);
+ } else {
+ checkMcf(mcf3, mcf3.run(param), neg2_gr, neg2_l, neg2_u, neg2_c, neg2_s,
+ mcf3.UNBOUNDED, false, 0, test_str + "-17", GEQ);
+ }
+ mcf3.upperMap(neg2_u);
+ checkMcf(mcf3, mcf3.run(param), neg2_gr, neg2_l, neg2_u, neg2_c, neg2_s,
+ mcf3.OPTIMAL, true, -300, test_str + "-18", GEQ);
+
+ // Tests for empty graph
+ Digraph gr0;
+ MCF mcf0(gr0);
+ mcf0.run(param);
+ check(mcf0.totalCost() == 0, "Wrong total cost");
+}
+
+template < typename MCF, typename Param >
+void runMcfLeqTests( Param param,
+ const std::string &test_str = "" )
+{
+ // Tests for the LEQ form
+ MCF mcf1(gr);
+ mcf1.supplyType(mcf1.LEQ);
+ mcf1.upperMap(u).costMap(c).supplyMap(s6);
+ checkMcf(mcf1, mcf1.run(param), gr, l1, u, c, s6,
+ mcf1.OPTIMAL, true, 5080, test_str + "-19", LEQ);
+ mcf1.lowerMap(l2);
+ checkMcf(mcf1, mcf1.run(param), gr, l2, u, c, s6,
+ mcf1.OPTIMAL, true, 5930, test_str + "-20", LEQ);
+ mcf1.supplyMap(s5);
+ checkMcf(mcf1, mcf1.run(param), gr, l2, u, c, s5,
+ mcf1.INFEASIBLE, false, 0, test_str + "-21", LEQ);
+}
+
+
+int main()
+{
+ // Read the test networks
+ std::istringstream input(test_lgf);
+ DigraphReader<Digraph>(gr, input)
+ .arcMap("cost", c)
+ .arcMap("cap", u)
+ .arcMap("low1", l1)
+ .arcMap("low2", l2)
+ .arcMap("low3", l3)
+ .nodeMap("sup1", s1)
+ .nodeMap("sup2", s2)
+ .nodeMap("sup3", s3)
+ .nodeMap("sup4", s4)
+ .nodeMap("sup5", s5)
+ .nodeMap("sup6", s6)
+ .node("source", v)
+ .node("target", w)
+ .run();
+
+ std::istringstream neg_inp1(test_neg1_lgf);
+ DigraphReader<Digraph>(neg1_gr, neg_inp1)
+ .arcMap("cost", neg1_c)
+ .arcMap("low1", neg1_l1)
+ .arcMap("low2", neg1_l2)
+ .nodeMap("sup", neg1_s)
+ .run();
+
+ std::istringstream neg_inp2(test_neg2_lgf);
+ DigraphReader<Digraph>(neg2_gr, neg_inp2)
+ .arcMap("cost", neg2_c)
+ .nodeMap("sup", neg2_s)
+ .run();
+
+ // Check the interface of NetworkSimplex
+ {
+ typedef concepts::Digraph GR;
+ checkConcept< McfClassConcept<GR, int, int>,
+ NetworkSimplex<GR> >();
+ checkConcept< McfClassConcept<GR, double, double>,
+ NetworkSimplex<GR, double> >();
+ checkConcept< McfClassConcept<GR, int, double>,
+ NetworkSimplex<GR, int, double> >();
+ }
+
+ // Check the interface of CapacityScaling
+ {
+ typedef concepts::Digraph GR;
+ checkConcept< McfClassConcept<GR, int, int>,
+ CapacityScaling<GR> >();
+ checkConcept< McfClassConcept<GR, double, double>,
+ CapacityScaling<GR, double> >();
+ checkConcept< McfClassConcept<GR, int, double>,
+ CapacityScaling<GR, int, double> >();
+ typedef CapacityScaling<GR>::
+ SetHeap<concepts::Heap<int, RangeMap<int> > >::Create CAS;
+ checkConcept< McfClassConcept<GR, int, int>, CAS >();
+ }
+
+ // Check the interface of CostScaling
+ {
+ typedef concepts::Digraph GR;
+ checkConcept< McfClassConcept<GR, int, int>,
+ CostScaling<GR> >();
+ checkConcept< McfClassConcept<GR, double, double>,
+ CostScaling<GR, double> >();
+ checkConcept< McfClassConcept<GR, int, double>,
+ CostScaling<GR, int, double> >();
+ typedef CostScaling<GR>::
+ SetLargeCost<double>::Create COS;
+ checkConcept< McfClassConcept<GR, int, int>, COS >();
+ }
+
+ // Check the interface of CycleCanceling
+ {
+ typedef concepts::Digraph GR;
+ checkConcept< McfClassConcept<GR, int, int>,
+ CycleCanceling<GR> >();
+ checkConcept< McfClassConcept<GR, double, double>,
+ CycleCanceling<GR, double> >();
+ checkConcept< McfClassConcept<GR, int, double>,
+ CycleCanceling<GR, int, double> >();
+ }
+
+ // Test NetworkSimplex
+ {
+ typedef NetworkSimplex<Digraph> MCF;
+ runMcfGeqTests<MCF>(MCF::FIRST_ELIGIBLE, "NS-FE", true);
+ runMcfLeqTests<MCF>(MCF::FIRST_ELIGIBLE, "NS-FE");
+ runMcfGeqTests<MCF>(MCF::BEST_ELIGIBLE, "NS-BE", true);
+ runMcfLeqTests<MCF>(MCF::BEST_ELIGIBLE, "NS-BE");
+ runMcfGeqTests<MCF>(MCF::BLOCK_SEARCH, "NS-BS", true);
+ runMcfLeqTests<MCF>(MCF::BLOCK_SEARCH, "NS-BS");
+ runMcfGeqTests<MCF>(MCF::CANDIDATE_LIST, "NS-CL", true);
+ runMcfLeqTests<MCF>(MCF::CANDIDATE_LIST, "NS-CL");
+ runMcfGeqTests<MCF>(MCF::ALTERING_LIST, "NS-AL", true);
+ runMcfLeqTests<MCF>(MCF::ALTERING_LIST, "NS-AL");
+ }
+
+ // Test CapacityScaling
+ {
+ typedef CapacityScaling<Digraph> MCF;
+ runMcfGeqTests<MCF>(0, "SSP");
+ runMcfGeqTests<MCF>(2, "CAS");
+ }
+
+ // Test CostScaling
+ {
+ typedef CostScaling<Digraph> MCF;
+ runMcfGeqTests<MCF>(MCF::PUSH, "COS-PR");
+ runMcfGeqTests<MCF>(MCF::AUGMENT, "COS-AR");
+ runMcfGeqTests<MCF>(MCF::PARTIAL_AUGMENT, "COS-PAR");
+ }
+
+ // Test CycleCanceling
+ {
+ typedef CycleCanceling<Digraph> MCF;
+ runMcfGeqTests<MCF>(MCF::SIMPLE_CYCLE_CANCELING, "SCC");
+ runMcfGeqTests<MCF>(MCF::MINIMUM_MEAN_CYCLE_CANCELING, "MMCC");
+ runMcfGeqTests<MCF>(MCF::CANCEL_AND_TIGHTEN, "CAT");
+ }
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/min_mean_cycle_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/min_mean_cycle_test.cc
new file mode 100644
index 00000000000..e7524546e54
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/min_mean_cycle_test.cc
@@ -0,0 +1,223 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+#include <sstream>
+
+#include <lemon/smart_graph.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/path.h>
+#include <lemon/concepts/digraph.h>
+#include <lemon/concept_check.h>
+
+#include <lemon/karp_mmc.h>
+#include <lemon/hartmann_orlin_mmc.h>
+#include <lemon/howard_mmc.h>
+
+#include "test_tools.h"
+
+using namespace lemon;
+
+char test_lgf[] =
+ "@nodes\n"
+ "label\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "6\n"
+ "7\n"
+ "@arcs\n"
+ " len1 len2 len3 len4 c1 c2 c3 c4\n"
+ "1 2 1 1 1 1 0 0 0 0\n"
+ "2 4 5 5 5 5 1 0 0 0\n"
+ "2 3 8 8 8 8 0 0 0 0\n"
+ "3 2 -2 0 0 0 1 0 0 0\n"
+ "3 4 4 4 4 4 0 0 0 0\n"
+ "3 7 -4 -4 -4 -4 0 0 0 0\n"
+ "4 1 2 2 2 2 0 0 0 0\n"
+ "4 3 3 3 3 3 1 0 0 0\n"
+ "4 4 3 3 0 0 0 0 1 0\n"
+ "5 2 4 4 4 4 0 0 0 0\n"
+ "5 6 3 3 3 3 0 1 0 0\n"
+ "6 5 2 2 2 2 0 1 0 0\n"
+ "6 4 -1 -1 -1 -1 0 0 0 0\n"
+ "6 7 1 1 1 1 0 0 0 0\n"
+ "7 7 4 4 4 -1 0 0 0 1\n";
+
+
+// Check the interface of an MMC algorithm
+template <typename GR, typename Cost>
+struct MmcClassConcept
+{
+ template <typename MMC>
+ struct Constraints {
+ void constraints() {
+ const Constraints& me = *this;
+
+ typedef typename MMC
+ ::template SetPath<ListPath<GR> >
+ ::template SetLargeCost<Cost>
+ ::Create MmcAlg;
+ MmcAlg mmc(me.g, me.cost);
+ const MmcAlg& const_mmc = mmc;
+
+ typename MmcAlg::Tolerance tol = const_mmc.tolerance();
+ mmc.tolerance(tol);
+
+ b = mmc.cycle(p).run();
+ b = mmc.findCycleMean();
+ b = mmc.findCycle();
+
+ v = const_mmc.cycleCost();
+ i = const_mmc.cycleSize();
+ d = const_mmc.cycleMean();
+ p = const_mmc.cycle();
+ }
+
+ typedef concepts::ReadMap<typename GR::Arc, Cost> CM;
+
+ GR g;
+ CM cost;
+ ListPath<GR> p;
+ Cost v;
+ int i;
+ double d;
+ bool b;
+ };
+};
+
+// Perform a test with the given parameters
+template <typename MMC>
+void checkMmcAlg(const SmartDigraph& gr,
+ const SmartDigraph::ArcMap<int>& lm,
+ const SmartDigraph::ArcMap<int>& cm,
+ int cost, int size) {
+ MMC alg(gr, lm);
+ check(alg.findCycleMean(), "Wrong result");
+ check(alg.cycleMean() == static_cast<double>(cost) / size,
+ "Wrong cycle mean");
+ alg.findCycle();
+ check(alg.cycleCost() == cost && alg.cycleSize() == size,
+ "Wrong path");
+ SmartDigraph::ArcMap<int> cycle(gr, 0);
+ for (typename MMC::Path::ArcIt a(alg.cycle()); a != INVALID; ++a) {
+ ++cycle[a];
+ }
+ for (SmartDigraph::ArcIt a(gr); a != INVALID; ++a) {
+ check(cm[a] == cycle[a], "Wrong path");
+ }
+}
+
+// Class for comparing types
+template <typename T1, typename T2>
+struct IsSameType {
+ static const int result = 0;
+};
+
+template <typename T>
+struct IsSameType<T,T> {
+ static const int result = 1;
+};
+
+
+int main() {
+ #ifdef LEMON_HAVE_LONG_LONG
+ typedef long long long_int;
+ #else
+ typedef long long_int;
+ #endif
+
+ // Check the interface
+ {
+ typedef concepts::Digraph GR;
+
+ // KarpMmc
+ checkConcept< MmcClassConcept<GR, int>,
+ KarpMmc<GR, concepts::ReadMap<GR::Arc, int> > >();
+ checkConcept< MmcClassConcept<GR, float>,
+ KarpMmc<GR, concepts::ReadMap<GR::Arc, float> > >();
+
+ // HartmannOrlinMmc
+ checkConcept< MmcClassConcept<GR, int>,
+ HartmannOrlinMmc<GR, concepts::ReadMap<GR::Arc, int> > >();
+ checkConcept< MmcClassConcept<GR, float>,
+ HartmannOrlinMmc<GR, concepts::ReadMap<GR::Arc, float> > >();
+
+ // HowardMmc
+ checkConcept< MmcClassConcept<GR, int>,
+ HowardMmc<GR, concepts::ReadMap<GR::Arc, int> > >();
+ checkConcept< MmcClassConcept<GR, float>,
+ HowardMmc<GR, concepts::ReadMap<GR::Arc, float> > >();
+
+ check((IsSameType<HowardMmc<GR, concepts::ReadMap<GR::Arc, int> >
+ ::LargeCost, long_int>::result == 1), "Wrong LargeCost type");
+ check((IsSameType<HowardMmc<GR, concepts::ReadMap<GR::Arc, float> >
+ ::LargeCost, double>::result == 1), "Wrong LargeCost type");
+ }
+
+ // Run various tests
+ {
+ typedef SmartDigraph GR;
+ DIGRAPH_TYPEDEFS(GR);
+
+ GR gr;
+ IntArcMap l1(gr), l2(gr), l3(gr), l4(gr);
+ IntArcMap c1(gr), c2(gr), c3(gr), c4(gr);
+
+ std::istringstream input(test_lgf);
+ digraphReader(gr, input).
+ arcMap("len1", l1).
+ arcMap("len2", l2).
+ arcMap("len3", l3).
+ arcMap("len4", l4).
+ arcMap("c1", c1).
+ arcMap("c2", c2).
+ arcMap("c3", c3).
+ arcMap("c4", c4).
+ run();
+
+ // Karp
+ checkMmcAlg<KarpMmc<GR, IntArcMap> >(gr, l1, c1, 6, 3);
+ checkMmcAlg<KarpMmc<GR, IntArcMap> >(gr, l2, c2, 5, 2);
+ checkMmcAlg<KarpMmc<GR, IntArcMap> >(gr, l3, c3, 0, 1);
+ checkMmcAlg<KarpMmc<GR, IntArcMap> >(gr, l4, c4, -1, 1);
+
+ // HartmannOrlin
+ checkMmcAlg<HartmannOrlinMmc<GR, IntArcMap> >(gr, l1, c1, 6, 3);
+ checkMmcAlg<HartmannOrlinMmc<GR, IntArcMap> >(gr, l2, c2, 5, 2);
+ checkMmcAlg<HartmannOrlinMmc<GR, IntArcMap> >(gr, l3, c3, 0, 1);
+ checkMmcAlg<HartmannOrlinMmc<GR, IntArcMap> >(gr, l4, c4, -1, 1);
+
+ // Howard
+ checkMmcAlg<HowardMmc<GR, IntArcMap> >(gr, l1, c1, 6, 3);
+ checkMmcAlg<HowardMmc<GR, IntArcMap> >(gr, l2, c2, 5, 2);
+ checkMmcAlg<HowardMmc<GR, IntArcMap> >(gr, l3, c3, 0, 1);
+ checkMmcAlg<HowardMmc<GR, IntArcMap> >(gr, l4, c4, -1, 1);
+
+ // Howard with iteration limit
+ HowardMmc<GR, IntArcMap> mmc(gr, l1);
+ check((mmc.findCycleMean(2) == HowardMmc<GR, IntArcMap>::ITERATION_LIMIT),
+ "Wrong termination cause");
+ check((mmc.findCycleMean(4) == HowardMmc<GR, IntArcMap>::OPTIMAL),
+ "Wrong termination cause");
+ }
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/mip_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/mip_test.cc
new file mode 100644
index 00000000000..641ceb5fe77
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/mip_test.cc
@@ -0,0 +1,171 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include "test_tools.h"
+
+#include <lemon/config.h>
+
+#ifdef LEMON_HAVE_CPLEX
+#include <lemon/cplex.h>
+#endif
+
+#ifdef LEMON_HAVE_GLPK
+#include <lemon/glpk.h>
+#endif
+
+#ifdef LEMON_HAVE_CBC
+#include <lemon/cbc.h>
+#endif
+
+#ifdef LEMON_HAVE_MIP
+#include <lemon/lp.h>
+#endif
+
+
+using namespace lemon;
+
+void solveAndCheck(MipSolver& mip, MipSolver::ProblemType stat,
+ double exp_opt) {
+ using std::string;
+
+ mip.solve();
+ //int decimal,sign;
+ std::ostringstream buf;
+ buf << "Type should be: " << int(stat)<<" and it is "<<int(mip.type());
+
+
+ // itoa(stat,buf1, 10);
+ check(mip.type()==stat, buf.str());
+
+ if (stat == MipSolver::OPTIMAL) {
+ std::ostringstream sbuf;
+ sbuf << "Wrong optimal value ("<< mip.solValue()
+ <<" instead of " << exp_opt << ")";
+ check(std::abs(mip.solValue()-exp_opt) < 1e-3, sbuf.str());
+ //+ecvt(exp_opt,2)
+ }
+}
+
+void aTest(MipSolver& mip)
+{
+ //The following example is very simple
+
+
+ typedef MipSolver::Row Row;
+ typedef MipSolver::Col Col;
+
+
+ Col x1 = mip.addCol();
+ Col x2 = mip.addCol();
+
+
+ //Objective function
+ mip.obj(x1);
+
+ mip.max();
+
+ //Unconstrained optimization
+ mip.solve();
+ //Check it out!
+
+ //Constraints
+ mip.addRow(2 * x1 + x2 <= 2);
+ Row y2 = mip.addRow(x1 - 2 * x2 <= 0);
+
+ //Nonnegativity of the variable x1
+ mip.colLowerBound(x1, 0);
+
+
+ //Maximization of x1
+ //over the triangle with vertices (0,0),(4/5,2/5),(0,2)
+ double expected_opt=4.0/5.0;
+ solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
+
+
+ //Restrict x2 to integer
+ mip.colType(x2,MipSolver::INTEGER);
+ expected_opt=1.0/2.0;
+ solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
+
+
+ //Restrict both to integer
+ mip.colType(x1,MipSolver::INTEGER);
+ expected_opt=0;
+ solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
+
+ //Erase a variable
+ mip.erase(x2);
+ mip.rowUpperBound(y2, 8);
+ expected_opt=1;
+ solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
+
+}
+
+
+template<class MIP>
+void cloneTest()
+{
+
+ MIP* mip = new MIP();
+ MIP* mipnew = mip->newSolver();
+ MIP* mipclone = mip->cloneSolver();
+ delete mip;
+ delete mipnew;
+ delete mipclone;
+}
+
+int main()
+{
+
+#ifdef LEMON_HAVE_MIP
+ {
+ Mip mip1;
+ aTest(mip1);
+ cloneTest<Mip>();
+ }
+#endif
+
+#ifdef LEMON_HAVE_GLPK
+ {
+ GlpkMip mip1;
+ aTest(mip1);
+ cloneTest<GlpkMip>();
+ }
+#endif
+
+#ifdef LEMON_HAVE_CPLEX
+ try {
+ CplexMip mip2;
+ aTest(mip2);
+ cloneTest<CplexMip>();
+ } catch (CplexEnv::LicenseError& error) {
+ check(false, error.what());
+ }
+#endif
+
+#ifdef LEMON_HAVE_CBC
+ {
+ CbcMip mip1;
+ aTest(mip1);
+ cloneTest<CbcMip>();
+ }
+#endif
+
+ return 0;
+
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/nagamochi_ibaraki_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/nagamochi_ibaraki_test.cc
new file mode 100644
index 00000000000..94ec29d933b
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/nagamochi_ibaraki_test.cc
@@ -0,0 +1,142 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <sstream>
+
+#include <lemon/smart_graph.h>
+#include <lemon/adaptors.h>
+#include <lemon/concepts/graph.h>
+#include <lemon/concepts/maps.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/nagamochi_ibaraki.h>
+
+#include "test_tools.h"
+
+using namespace lemon;
+using namespace std;
+
+const std::string lgf =
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "@edges\n"
+ " cap1 cap2 cap3\n"
+ "0 1 1 1 1 \n"
+ "0 2 2 2 4 \n"
+ "1 2 4 4 4 \n"
+ "3 4 1 1 1 \n"
+ "3 5 2 2 4 \n"
+ "4 5 4 4 4 \n"
+ "2 3 1 6 6 \n";
+
+void checkNagamochiIbarakiCompile()
+{
+ typedef int Value;
+ typedef concepts::Graph Graph;
+
+ typedef Graph::Node Node;
+ typedef Graph::Edge Edge;
+ typedef concepts::ReadMap<Edge, Value> CapMap;
+ typedef concepts::WriteMap<Node, bool> CutMap;
+
+ Graph g;
+ Node n;
+ CapMap cap;
+ CutMap cut;
+ Value v;
+ bool b;
+ ::lemon::ignore_unused_variable_warning(v,b);
+
+ NagamochiIbaraki<Graph, CapMap> ni_test(g, cap);
+ const NagamochiIbaraki<Graph, CapMap>& const_ni_test = ni_test;
+
+ ni_test.init();
+ ni_test.start();
+ b = ni_test.processNextPhase();
+ ni_test.run();
+
+ v = const_ni_test.minCutValue();
+ v = const_ni_test.minCutMap(cut);
+}
+
+template <typename Graph, typename CapMap, typename CutMap>
+typename CapMap::Value
+ cutValue(const Graph& graph, const CapMap& cap, const CutMap& cut)
+{
+ typename CapMap::Value sum = 0;
+ for (typename Graph::EdgeIt e(graph); e != INVALID; ++e) {
+ if (cut[graph.u(e)] != cut[graph.v(e)]) {
+ sum += cap[e];
+ }
+ }
+ return sum;
+}
+
+int main() {
+ SmartGraph graph;
+ SmartGraph::EdgeMap<int> cap1(graph), cap2(graph), cap3(graph);
+ SmartGraph::NodeMap<bool> cut(graph);
+
+ istringstream input(lgf);
+ graphReader(graph, input)
+ .edgeMap("cap1", cap1)
+ .edgeMap("cap2", cap2)
+ .edgeMap("cap3", cap3)
+ .run();
+
+ {
+ NagamochiIbaraki<SmartGraph> ni(graph, cap1);
+ ni.run();
+ ni.minCutMap(cut);
+
+ check(ni.minCutValue() == 1, "Wrong cut value");
+ check(ni.minCutValue() == cutValue(graph, cap1, cut), "Wrong cut value");
+ }
+ {
+ NagamochiIbaraki<SmartGraph> ni(graph, cap2);
+ ni.run();
+ ni.minCutMap(cut);
+
+ check(ni.minCutValue() == 3, "Wrong cut value");
+ check(ni.minCutValue() == cutValue(graph, cap2, cut), "Wrong cut value");
+ }
+ {
+ NagamochiIbaraki<SmartGraph> ni(graph, cap3);
+ ni.run();
+ ni.minCutMap(cut);
+
+ check(ni.minCutValue() == 5, "Wrong cut value");
+ check(ni.minCutValue() == cutValue(graph, cap3, cut), "Wrong cut value");
+ }
+ {
+ NagamochiIbaraki<SmartGraph>::SetUnitCapacity::Create ni(graph);
+ ni.run();
+ ni.minCutMap(cut);
+
+ ConstMap<SmartGraph::Edge, int> cap4(1);
+ check(ni.minCutValue() == 1, "Wrong cut value");
+ check(ni.minCutValue() == cutValue(graph, cap4, cut), "Wrong cut value");
+ }
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/path_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/path_test.cc
new file mode 100644
index 00000000000..f2d96038135
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/path_test.cc
@@ -0,0 +1,339 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <string>
+#include <iostream>
+
+#include <lemon/concepts/path.h>
+#include <lemon/concepts/digraph.h>
+#include <lemon/concept_check.h>
+
+#include <lemon/path.h>
+#include <lemon/list_graph.h>
+
+#include "test_tools.h"
+
+using namespace std;
+using namespace lemon;
+
+template <typename GR>
+void checkConcepts() {
+ checkConcept<concepts::Path<GR>, concepts::Path<GR> >();
+ checkConcept<concepts::Path<GR>, Path<GR> >();
+ checkConcept<concepts::Path<GR>, SimplePath<GR> >();
+ checkConcept<concepts::Path<GR>, StaticPath<GR> >();
+ checkConcept<concepts::Path<GR>, ListPath<GR> >();
+}
+
+// Conecpt checking for path structures
+void checkPathConcepts() {
+ checkConcepts<concepts::Digraph>();
+ checkConcepts<ListDigraph>();
+}
+
+// Check if proper copy consructor is called (use valgrind for testing)
+template <typename GR, typename P1, typename P2>
+void checkCopy(typename GR::Arc a) {
+ P1 p;
+ p.addBack(a);
+ P1 q;
+ q = p;
+ P1 r(p);
+ P2 q2;
+ q2 = p;
+ P2 r2(p);
+}
+
+// Tests for copy constructors and assignment operators of paths
+void checkPathCopy() {
+ ListDigraph g;
+ ListDigraph::Arc a = g.addArc(g.addNode(), g.addNode());
+
+ typedef Path<ListDigraph> Path1;
+ typedef SimplePath<ListDigraph> Path2;
+ typedef ListPath<ListDigraph> Path3;
+ typedef StaticPath<ListDigraph> Path4;
+ checkCopy<ListDigraph, Path1, Path2>(a);
+ checkCopy<ListDigraph, Path1, Path3>(a);
+ checkCopy<ListDigraph, Path1, Path4>(a);
+ checkCopy<ListDigraph, Path2, Path1>(a);
+ checkCopy<ListDigraph, Path2, Path3>(a);
+ checkCopy<ListDigraph, Path2, Path4>(a);
+ checkCopy<ListDigraph, Path3, Path1>(a);
+ checkCopy<ListDigraph, Path3, Path2>(a);
+ checkCopy<ListDigraph, Path3, Path4>(a);
+}
+
+// Class for testing path functions
+class CheckPathFunctions {
+ typedef ListDigraph GR;
+ DIGRAPH_TYPEDEFS(GR);
+ GR gr;
+ const GR& cgr;
+ Node n1, n2, n3, n4;
+ Node tmp_n;
+ Arc a1, a2, a3, a4;
+ Arc tmp_a;
+
+public:
+
+ CheckPathFunctions() : cgr(gr) {
+ n1 = gr.addNode();
+ n2 = gr.addNode();
+ n3 = gr.addNode();
+ n4 = gr.addNode();
+ a1 = gr.addArc(n1, n2);
+ a2 = gr.addArc(n2, n3);
+ a3 = gr.addArc(n3, n4);
+ a4 = gr.addArc(n4, n1);
+ }
+
+ void run() {
+ checkBackAndFrontInsertablePath<Path<GR> >();
+ checkBackAndFrontInsertablePath<ListPath<GR> >();
+ checkBackInsertablePath<SimplePath<GR> >();
+
+ checkListPathSplitAndSplice();
+ }
+
+private:
+
+ template <typename P>
+ void checkBackInsertablePath() {
+
+ // Create and check empty path
+ P p;
+ const P& cp = p;
+ check(cp.empty(), "The path is not empty");
+ check(cp.length() == 0, "The path is not empty");
+// check(cp.front() == INVALID, "Wrong front()");
+// check(cp.back() == INVALID, "Wrong back()");
+ typename P::ArcIt ai(cp);
+ check(ai == INVALID, "Wrong ArcIt");
+ check(pathSource(cgr, cp) == INVALID, "Wrong pathSource()");
+ check(pathTarget(cgr, cp) == INVALID, "Wrong pathTarget()");
+ check(checkPath(cgr, cp), "Wrong checkPath()");
+ PathNodeIt<P> ni(cgr, cp);
+ check(ni == INVALID, "Wrong PathNodeIt");
+
+ // Check single-arc path
+ p.addBack(a1);
+ check(!cp.empty(), "Wrong empty()");
+ check(cp.length() == 1, "Wrong length");
+ check(cp.front() == a1, "Wrong front()");
+ check(cp.back() == a1, "Wrong back()");
+ check(cp.nth(0) == a1, "Wrong nth()");
+ ai = cp.nthIt(0);
+ check((tmp_a = ai) == a1, "Wrong nthIt()");
+ check(++ai == INVALID, "Wrong nthIt()");
+ typename P::ArcIt ai2(cp);
+ check((tmp_a = ai2) == a1, "Wrong ArcIt");
+ check(++ai2 == INVALID, "Wrong ArcIt");
+ check(pathSource(cgr, cp) == n1, "Wrong pathSource()");
+ check(pathTarget(cgr, cp) == n2, "Wrong pathTarget()");
+ check(checkPath(cgr, cp), "Wrong checkPath()");
+ PathNodeIt<P> ni2(cgr, cp);
+ check((tmp_n = ni2) == n1, "Wrong PathNodeIt");
+ check((tmp_n = ++ni2) == n2, "Wrong PathNodeIt");
+ check(++ni2 == INVALID, "Wrong PathNodeIt");
+
+ // Check adding more arcs
+ p.addBack(a2);
+ p.addBack(a3);
+ check(!cp.empty(), "Wrong empty()");
+ check(cp.length() == 3, "Wrong length");
+ check(cp.front() == a1, "Wrong front()");
+ check(cp.back() == a3, "Wrong back()");
+ check(cp.nth(0) == a1, "Wrong nth()");
+ check(cp.nth(1) == a2, "Wrong nth()");
+ check(cp.nth(2) == a3, "Wrong nth()");
+ typename P::ArcIt ai3(cp);
+ check((tmp_a = ai3) == a1, "Wrong ArcIt");
+ check((tmp_a = ++ai3) == a2, "Wrong nthIt()");
+ check((tmp_a = ++ai3) == a3, "Wrong nthIt()");
+ check(++ai3 == INVALID, "Wrong nthIt()");
+ ai = cp.nthIt(0);
+ check((tmp_a = ai) == a1, "Wrong nthIt()");
+ check((tmp_a = ++ai) == a2, "Wrong nthIt()");
+ ai = cp.nthIt(2);
+ check((tmp_a = ai) == a3, "Wrong nthIt()");
+ check(++ai == INVALID, "Wrong nthIt()");
+ check(pathSource(cgr, cp) == n1, "Wrong pathSource()");
+ check(pathTarget(cgr, cp) == n4, "Wrong pathTarget()");
+ check(checkPath(cgr, cp), "Wrong checkPath()");
+ PathNodeIt<P> ni3(cgr, cp);
+ check((tmp_n = ni3) == n1, "Wrong PathNodeIt");
+ check((tmp_n = ++ni3) == n2, "Wrong PathNodeIt");
+ check((tmp_n = ++ni3) == n3, "Wrong PathNodeIt");
+ check((tmp_n = ++ni3) == n4, "Wrong PathNodeIt");
+ check(++ni3 == INVALID, "Wrong PathNodeIt");
+
+ // Check arc removal and addition
+ p.eraseBack();
+ p.eraseBack();
+ p.addBack(a2);
+ check(!cp.empty(), "Wrong empty()");
+ check(cp.length() == 2, "Wrong length");
+ check(cp.front() == a1, "Wrong front()");
+ check(cp.back() == a2, "Wrong back()");
+ check(pathSource(cgr, cp) == n1, "Wrong pathSource()");
+ check(pathTarget(cgr, cp) == n3, "Wrong pathTarget()");
+ check(checkPath(cgr, cp), "Wrong checkPath()");
+
+ // Check clear()
+ p.clear();
+ check(cp.empty(), "The path is not empty");
+ check(cp.length() == 0, "The path is not empty");
+
+ // Check inconsistent path
+ p.addBack(a4);
+ p.addBack(a2);
+ p.addBack(a1);
+ check(!cp.empty(), "Wrong empty()");
+ check(cp.length() == 3, "Wrong length");
+ check(cp.front() == a4, "Wrong front()");
+ check(cp.back() == a1, "Wrong back()");
+ check(pathSource(cgr, cp) == n4, "Wrong pathSource()");
+ check(pathTarget(cgr, cp) == n2, "Wrong pathTarget()");
+ check(!checkPath(cgr, cp), "Wrong checkPath()");
+ }
+
+ template <typename P>
+ void checkBackAndFrontInsertablePath() {
+
+ // Include back insertable test cases
+ checkBackInsertablePath<P>();
+
+ // Check front and back insertion
+ P p;
+ const P& cp = p;
+ p.addFront(a4);
+ p.addBack(a1);
+ p.addFront(a3);
+ check(!cp.empty(), "Wrong empty()");
+ check(cp.length() == 3, "Wrong length");
+ check(cp.front() == a3, "Wrong front()");
+ check(cp.back() == a1, "Wrong back()");
+ check(cp.nth(0) == a3, "Wrong nth()");
+ check(cp.nth(1) == a4, "Wrong nth()");
+ check(cp.nth(2) == a1, "Wrong nth()");
+ typename P::ArcIt ai(cp);
+ check((tmp_a = ai) == a3, "Wrong ArcIt");
+ check((tmp_a = ++ai) == a4, "Wrong nthIt()");
+ check((tmp_a = ++ai) == a1, "Wrong nthIt()");
+ check(++ai == INVALID, "Wrong nthIt()");
+ ai = cp.nthIt(0);
+ check((tmp_a = ai) == a3, "Wrong nthIt()");
+ check((tmp_a = ++ai) == a4, "Wrong nthIt()");
+ ai = cp.nthIt(2);
+ check((tmp_a = ai) == a1, "Wrong nthIt()");
+ check(++ai == INVALID, "Wrong nthIt()");
+ check(pathSource(cgr, cp) == n3, "Wrong pathSource()");
+ check(pathTarget(cgr, cp) == n2, "Wrong pathTarget()");
+ check(checkPath(cgr, cp), "Wrong checkPath()");
+
+ // Check eraseFront()
+ p.eraseFront();
+ p.addBack(a2);
+ check(!cp.empty(), "Wrong empty()");
+ check(cp.length() == 3, "Wrong length");
+ check(cp.front() == a4, "Wrong front()");
+ check(cp.back() == a2, "Wrong back()");
+ check(cp.nth(0) == a4, "Wrong nth()");
+ check(cp.nth(1) == a1, "Wrong nth()");
+ check(cp.nth(2) == a2, "Wrong nth()");
+ typename P::ArcIt ai2(cp);
+ check((tmp_a = ai2) == a4, "Wrong ArcIt");
+ check((tmp_a = ++ai2) == a1, "Wrong nthIt()");
+ check((tmp_a = ++ai2) == a2, "Wrong nthIt()");
+ check(++ai2 == INVALID, "Wrong nthIt()");
+ ai = cp.nthIt(0);
+ check((tmp_a = ai) == a4, "Wrong nthIt()");
+ check((tmp_a = ++ai) == a1, "Wrong nthIt()");
+ ai = cp.nthIt(2);
+ check((tmp_a = ai) == a2, "Wrong nthIt()");
+ check(++ai == INVALID, "Wrong nthIt()");
+ check(pathSource(cgr, cp) == n4, "Wrong pathSource()");
+ check(pathTarget(cgr, cp) == n3, "Wrong pathTarget()");
+ check(checkPath(cgr, cp), "Wrong checkPath()");
+ }
+
+ void checkListPathSplitAndSplice() {
+
+ // Build a path with spliceFront() and spliceBack()
+ ListPath<GR> p1, p2, p3, p4;
+ p1.addBack(a3);
+ p1.addFront(a2);
+ p2.addBack(a1);
+ p1.spliceFront(p2);
+ p3.addFront(a4);
+ p1.spliceBack(p3);
+ check(p1.length() == 4, "Wrong length");
+ check(p1.front() == a1, "Wrong front()");
+ check(p1.back() == a4, "Wrong back()");
+ ListPath<GR>::ArcIt ai(p1);
+ check((tmp_a = ai) == a1, "Wrong ArcIt");
+ check((tmp_a = ++ai) == a2, "Wrong nthIt()");
+ check((tmp_a = ++ai) == a3, "Wrong nthIt()");
+ check((tmp_a = ++ai) == a4, "Wrong nthIt()");
+ check(++ai == INVALID, "Wrong nthIt()");
+ check(checkPath(cgr, p1), "Wrong checkPath()");
+
+ // Check split()
+ p1.split(p1.nthIt(2), p2);
+ check(p1.length() == 2, "Wrong length");
+ ai = p1.nthIt(0);
+ check((tmp_a = ai) == a1, "Wrong ArcIt");
+ check((tmp_a = ++ai) == a2, "Wrong nthIt()");
+ check(++ai == INVALID, "Wrong nthIt()");
+ check(checkPath(cgr, p1), "Wrong checkPath()");
+ check(p2.length() == 2, "Wrong length");
+ ai = p2.nthIt(0);
+ check((tmp_a = ai) == a3, "Wrong ArcIt");
+ check((tmp_a = ++ai) == a4, "Wrong nthIt()");
+ check(++ai == INVALID, "Wrong nthIt()");
+ check(checkPath(cgr, p2), "Wrong checkPath()");
+
+ // Check split() and splice()
+ p1.spliceFront(p2);
+ p1.split(p1.nthIt(2), p2);
+ p2.split(p2.nthIt(1), p3);
+ p2.spliceBack(p1);
+ p2.splice(p2.nthIt(1), p3);
+ check(p2.length() == 4, "Wrong length");
+ check(p2.front() == a1, "Wrong front()");
+ check(p2.back() == a4, "Wrong back()");
+ ai = p2.nthIt(0);
+ check((tmp_a = ai) == a1, "Wrong ArcIt");
+ check((tmp_a = ++ai) == a2, "Wrong nthIt()");
+ check((tmp_a = ++ai) == a3, "Wrong nthIt()");
+ check((tmp_a = ++ai) == a4, "Wrong nthIt()");
+ check(++ai == INVALID, "Wrong nthIt()");
+ check(checkPath(cgr, p2), "Wrong checkPath()");
+ }
+
+};
+
+int main() {
+ checkPathConcepts();
+ checkPathCopy();
+ CheckPathFunctions cpf;
+ cpf.run();
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/planarity_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/planarity_test.cc
new file mode 100644
index 00000000000..0ac11eebba1
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/planarity_test.cc
@@ -0,0 +1,262 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+
+#include <lemon/planarity.h>
+
+#include <lemon/smart_graph.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/connectivity.h>
+#include <lemon/dim2.h>
+
+#include "test_tools.h"
+
+using namespace lemon;
+using namespace lemon::dim2;
+
+const int lgfn = 4;
+const std::string lgf[lgfn] = {
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "@edges\n"
+ " label\n"
+ "0 1 0\n"
+ "0 2 0\n"
+ "0 3 0\n"
+ "0 4 0\n"
+ "1 2 0\n"
+ "1 3 0\n"
+ "1 4 0\n"
+ "2 3 0\n"
+ "2 4 0\n"
+ "3 4 0\n",
+
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "@edges\n"
+ " label\n"
+ "0 1 0\n"
+ "0 2 0\n"
+ "0 3 0\n"
+ "0 4 0\n"
+ "1 2 0\n"
+ "1 3 0\n"
+ "2 3 0\n"
+ "2 4 0\n"
+ "3 4 0\n",
+
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "@edges\n"
+ " label\n"
+ "0 3 0\n"
+ "0 4 0\n"
+ "0 5 0\n"
+ "1 3 0\n"
+ "1 4 0\n"
+ "1 5 0\n"
+ "2 3 0\n"
+ "2 4 0\n"
+ "2 5 0\n",
+
+ "@nodes\n"
+ "label\n"
+ "0\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "@edges\n"
+ " label\n"
+ "0 3 0\n"
+ "0 4 0\n"
+ "0 5 0\n"
+ "1 3 0\n"
+ "1 4 0\n"
+ "1 5 0\n"
+ "2 3 0\n"
+ "2 5 0\n"
+};
+
+
+
+typedef SmartGraph Graph;
+GRAPH_TYPEDEFS(Graph);
+
+typedef PlanarEmbedding<SmartGraph> PE;
+typedef PlanarDrawing<SmartGraph> PD;
+typedef PlanarColoring<SmartGraph> PC;
+
+void checkEmbedding(const Graph& graph, PE& pe) {
+ int face_num = 0;
+
+ Graph::ArcMap<int> face(graph, -1);
+
+ for (ArcIt a(graph); a != INVALID; ++a) {
+ if (face[a] == -1) {
+ Arc b = a;
+ while (face[b] == -1) {
+ face[b] = face_num;
+ b = pe.next(graph.oppositeArc(b));
+ }
+ check(face[b] == face_num, "Wrong face");
+ ++face_num;
+ }
+ }
+ check(face_num + countNodes(graph) - countConnectedComponents(graph) ==
+ countEdges(graph) + 1, "Euler test does not passed");
+}
+
+void checkKuratowski(const Graph& graph, PE& pe) {
+ std::map<int, int> degs;
+ for (NodeIt n(graph); n != INVALID; ++n) {
+ int deg = 0;
+ for (IncEdgeIt e(graph, n); e != INVALID; ++e) {
+ if (pe.kuratowski(e)) {
+ ++deg;
+ }
+ }
+ ++degs[deg];
+ }
+ for (std::map<int, int>::iterator it = degs.begin(); it != degs.end(); ++it) {
+ check(it->first == 0 || it->first == 2 ||
+ (it->first == 3 && it->second == 6) ||
+ (it->first == 4 && it->second == 5),
+ "Wrong degree in Kuratowski graph");
+ }
+
+ // Not full test
+ check((degs[3] == 0) != (degs[4] == 0), "Wrong Kuratowski graph");
+}
+
+bool intersect(Point<int> e1, Point<int> e2, Point<int> f1, Point<int> f2) {
+ int l, r;
+ if (std::min(e1.x, e2.x) > std::max(f1.x, f2.x)) return false;
+ if (std::max(e1.x, e2.x) < std::min(f1.x, f2.x)) return false;
+ if (std::min(e1.y, e2.y) > std::max(f1.y, f2.y)) return false;
+ if (std::max(e1.y, e2.y) < std::min(f1.y, f2.y)) return false;
+
+ l = (e2.x - e1.x) * (f1.y - e1.y) - (e2.y - e1.y) * (f1.x - e1.x);
+ r = (e2.x - e1.x) * (f2.y - e1.y) - (e2.y - e1.y) * (f2.x - e1.x);
+ if (!((l >= 0 && r <= 0) || (l <= 0 && r >= 0))) return false;
+ l = (f2.x - f1.x) * (e1.y - f1.y) - (f2.y - f1.y) * (e1.x - f1.x);
+ r = (f2.x - f1.x) * (e2.y - f1.y) - (f2.y - f1.y) * (e2.x - f1.x);
+ if (!((l >= 0 && r <= 0) || (l <= 0 && r >= 0))) return false;
+ return true;
+}
+
+bool collinear(Point<int> p, Point<int> q, Point<int> r) {
+ int v;
+ v = (q.x - p.x) * (r.y - p.y) - (q.y - p.y) * (r.x - p.x);
+ if (v != 0) return false;
+ v = (q.x - p.x) * (r.x - p.x) + (q.y - p.y) * (r.y - p.y);
+ if (v < 0) return false;
+ return true;
+}
+
+void checkDrawing(const Graph& graph, PD& pd) {
+ for (Graph::NodeIt n(graph); n != INVALID; ++n) {
+ Graph::NodeIt m(n);
+ for (++m; m != INVALID; ++m) {
+ check(pd[m] != pd[n], "Two nodes with identical coordinates");
+ }
+ }
+
+ for (Graph::EdgeIt e(graph); e != INVALID; ++e) {
+ for (Graph::EdgeIt f(e); f != e; ++f) {
+ Point<int> e1 = pd[graph.u(e)];
+ Point<int> e2 = pd[graph.v(e)];
+ Point<int> f1 = pd[graph.u(f)];
+ Point<int> f2 = pd[graph.v(f)];
+
+ if (graph.u(e) == graph.u(f)) {
+ check(!collinear(e1, e2, f2), "Wrong drawing");
+ } else if (graph.u(e) == graph.v(f)) {
+ check(!collinear(e1, e2, f1), "Wrong drawing");
+ } else if (graph.v(e) == graph.u(f)) {
+ check(!collinear(e2, e1, f2), "Wrong drawing");
+ } else if (graph.v(e) == graph.v(f)) {
+ check(!collinear(e2, e1, f1), "Wrong drawing");
+ } else {
+ check(!intersect(e1, e2, f1, f2), "Wrong drawing");
+ }
+ }
+ }
+}
+
+void checkColoring(const Graph& graph, PC& pc, int num) {
+ for (NodeIt n(graph); n != INVALID; ++n) {
+ check(pc.colorIndex(n) >= 0 && pc.colorIndex(n) < num,
+ "Wrong coloring");
+ }
+ for (EdgeIt e(graph); e != INVALID; ++e) {
+ check(pc.colorIndex(graph.u(e)) != pc.colorIndex(graph.v(e)),
+ "Wrong coloring");
+ }
+}
+
+int main() {
+
+ for (int i = 0; i < lgfn; ++i) {
+ std::istringstream lgfs(lgf[i]);
+
+ SmartGraph graph;
+ graphReader(graph, lgfs).run();
+
+ check(simpleGraph(graph), "Test graphs must be simple");
+
+ PE pe(graph);
+ bool planar = pe.run();
+ check(checkPlanarity(graph) == planar, "Planarity checking failed");
+
+ if (planar) {
+ checkEmbedding(graph, pe);
+
+ PlanarDrawing<Graph> pd(graph);
+ pd.run(pe.embeddingMap());
+ checkDrawing(graph, pd);
+
+ PlanarColoring<Graph> pc(graph);
+ pc.runFiveColoring(pe.embeddingMap());
+ checkColoring(graph, pc, 5);
+
+ } else {
+ checkKuratowski(graph, pe);
+ }
+ }
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/radix_sort_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/radix_sort_test.cc
new file mode 100644
index 00000000000..6ae2debfa84
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/radix_sort_test.cc
@@ -0,0 +1,266 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/time_measure.h>
+#include <lemon/smart_graph.h>
+#include <lemon/maps.h>
+#include <lemon/radix_sort.h>
+#include <lemon/math.h>
+
+#include "test_tools.h"
+
+#include <vector>
+#include <list>
+#include <algorithm>
+
+using namespace lemon;
+
+static const int n = 10000;
+
+struct Negate {
+ typedef int argument_type;
+ typedef int result_type;
+ int operator()(int a) { return - a; }
+};
+
+int negate(int a) { return - a; }
+
+template<class T>
+bool isTheSame(T &a, T&b)
+{
+ typename T::iterator ai=a.begin();
+ typename T::iterator bi=b.begin();
+ for(;ai!=a.end()||bi!=b.end();++ai,++bi)
+ if(*ai!=*bi) return false;
+ return ai==a.end()&&bi==b.end();
+}
+
+template<class T>
+T listsort(typename T::iterator b, typename T::iterator e)
+{
+ if(b==e) return T();
+ typename T::iterator bn=b;
+ if(++bn==e) {
+ T l;
+ l.push_back(*b);
+ return l;
+ }
+ typename T::iterator m=b;
+ bool x=false;
+ for(typename T::iterator i=b;i!=e;++i,x=!x)
+ if(x) ++m;
+ T l1(listsort<T>(b,m));
+ T l2(listsort<T>(m,e));
+ T l;
+ while((!l1.empty())&&(!l2.empty()))
+ if(l1.front()<=l2.front())
+ {
+ l.push_back(l1.front());
+ l1.pop_front();
+ }
+ else {
+ l.push_back(l2.front());
+ l2.pop_front();
+ }
+ while(!l1.empty())
+ {
+ l.push_back(l1.front());
+ l1.pop_front();
+ }
+ while(!l2.empty())
+ {
+ l.push_back(l2.front());
+ l2.pop_front();
+ }
+ return l;
+}
+
+template<class T>
+void generateIntSequence(int n, T & data) {
+ int prime = 9973;
+ int root = 136, value = 1;
+ for (int i = 0; i < n; ++i) {
+ data.push_back(value - prime / 2);
+ value = (value * root) % prime;
+ }
+}
+
+template<class T>
+void generateCharSequence(int n, T & data) {
+ int prime = 251;
+ int root = 3, value = root;
+ for (int i = 0; i < n; ++i) {
+ data.push_back(static_cast<unsigned char>(value));
+ value = (value * root) % prime;
+ }
+}
+
+void checkRadixSort() {
+ {
+ std::vector<int> data1;
+ generateIntSequence(n, data1);
+
+ std::vector<int> data2(data1);
+ std::sort(data1.begin(), data1.end());
+
+ radixSort(data2.begin(), data2.end());
+ for (int i = 0; i < n; ++i) {
+ check(data1[i] == data2[i], "Test failed");
+ }
+
+ // radixSort(data2.begin(), data2.end(), Negate());
+ // for (int i = 0; i < n; ++i) {
+ // check(data1[i] == data2[n - 1 - i], "Test failed");
+ // }
+
+ // radixSort(data2.begin(), data2.end(), negate);
+ // for (int i = 0; i < n; ++i) {
+ // check(data1[i] == data2[n - 1 - i], "Test failed");
+ // }
+
+ }
+
+ {
+ std::vector<unsigned char> data1(n);
+ generateCharSequence(n, data1);
+
+ std::vector<unsigned char> data2(data1);
+ std::sort(data1.begin(), data1.end());
+
+ radixSort(data2.begin(), data2.end());
+ for (int i = 0; i < n; ++i) {
+ check(data1[i] == data2[i], "Test failed");
+ }
+
+ }
+ {
+ std::list<int> data1;
+ generateIntSequence(n, data1);
+
+ std::list<int> data2(listsort<std::list<int> >(data1.begin(), data1.end()));
+
+ radixSort(data1.begin(), data1.end());
+
+ check(isTheSame(data1,data2), "Test failed");
+
+
+ // radixSort(data2.begin(), data2.end(), Negate());
+ // check(isTheSame(data1,data2), "Test failed");
+ // for (int i = 0; i < n; ++i) {
+ // check(data1[i] == data2[n - 1 - i], "Test failed");
+ // }
+
+ // radixSort(data2.begin(), data2.end(), negate);
+ // for (int i = 0; i < n; ++i) {
+ // check(data1[i] == data2[n - 1 - i], "Test failed");
+ // }
+
+ }
+
+ {
+ std::list<unsigned char> data1(n);
+ generateCharSequence(n, data1);
+
+ std::list<unsigned char> data2(listsort<std::list<unsigned char> >
+ (data1.begin(),
+ data1.end()));
+
+ radixSort(data1.begin(), data1.end());
+ check(isTheSame(data1,data2), "Test failed");
+
+ }
+}
+
+
+void checkStableRadixSort() {
+ {
+ std::vector<int> data1;
+ generateIntSequence(n, data1);
+
+ std::vector<int> data2(data1);
+ std::sort(data1.begin(), data1.end());
+
+ stableRadixSort(data2.begin(), data2.end());
+ for (int i = 0; i < n; ++i) {
+ check(data1[i] == data2[i], "Test failed");
+ }
+
+ stableRadixSort(data2.begin(), data2.end(), Negate());
+ for (int i = 0; i < n; ++i) {
+ check(data1[i] == data2[n - 1 - i], "Test failed");
+ }
+
+ stableRadixSort(data2.begin(), data2.end(), negate);
+ for (int i = 0; i < n; ++i) {
+ check(data1[i] == data2[n - 1 - i], "Test failed");
+ }
+ }
+
+ {
+ std::vector<unsigned char> data1(n);
+ generateCharSequence(n, data1);
+
+ std::vector<unsigned char> data2(data1);
+ std::sort(data1.begin(), data1.end());
+
+ radixSort(data2.begin(), data2.end());
+ for (int i = 0; i < n; ++i) {
+ check(data1[i] == data2[i], "Test failed");
+ }
+
+ }
+ {
+ std::list<int> data1;
+ generateIntSequence(n, data1);
+
+ std::list<int> data2(listsort<std::list<int> >(data1.begin(),
+ data1.end()));
+ stableRadixSort(data1.begin(), data1.end());
+ check(isTheSame(data1,data2), "Test failed");
+
+ // stableRadixSort(data2.begin(), data2.end(), Negate());
+ // for (int i = 0; i < n; ++i) {
+ // check(data1[i] == data2[n - 1 - i], "Test failed");
+ // }
+
+ // stableRadixSort(data2.begin(), data2.end(), negate);
+ // for (int i = 0; i < n; ++i) {
+ // check(data1[i] == data2[n - 1 - i], "Test failed");
+ // }
+ }
+
+ {
+ std::list<unsigned char> data1(n);
+ generateCharSequence(n, data1);
+
+ std::list<unsigned char> data2(listsort<std::list<unsigned char> >
+ (data1.begin(),
+ data1.end()));
+ radixSort(data1.begin(), data1.end());
+ check(isTheSame(data1,data2), "Test failed");
+
+ }
+}
+
+int main() {
+
+ checkRadixSort();
+ checkStableRadixSort();
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/random_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/random_test.cc
new file mode 100644
index 00000000000..49dd8b60398
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/random_test.cc
@@ -0,0 +1,40 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/random.h>
+#include "test_tools.h"
+
+int seed_array[] = {1, 2};
+
+int main()
+{
+ double a=lemon::rnd();
+ check(a<1.0&&a>0.0,"This should be in [0,1)");
+ a=lemon::rnd.gauss();
+ a=lemon::rnd.gamma(3.45,0);
+ a=lemon::rnd.gamma(4);
+ //Does gamma work with integer k?
+ a=lemon::rnd.gamma(4.0,0);
+ a=lemon::rnd.poisson(.5);
+
+ lemon::rnd.seed(100);
+ lemon::rnd.seed(seed_array, seed_array +
+ (sizeof(seed_array) / sizeof(seed_array[0])));
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/suurballe_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/suurballe_test.cc
new file mode 100644
index 00000000000..7c00f212ac0
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/suurballe_test.cc
@@ -0,0 +1,267 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+
+#include <lemon/list_graph.h>
+#include <lemon/lgf_reader.h>
+#include <lemon/path.h>
+#include <lemon/suurballe.h>
+#include <lemon/concepts/digraph.h>
+#include <lemon/concepts/heap.h>
+
+#include "test_tools.h"
+
+using namespace lemon;
+
+char test_lgf[] =
+ "@nodes\n"
+ "label\n"
+ "1\n"
+ "2\n"
+ "3\n"
+ "4\n"
+ "5\n"
+ "6\n"
+ "7\n"
+ "8\n"
+ "9\n"
+ "10\n"
+ "11\n"
+ "12\n"
+ "@arcs\n"
+ " length\n"
+ " 1 2 70\n"
+ " 1 3 150\n"
+ " 1 4 80\n"
+ " 2 8 80\n"
+ " 3 5 140\n"
+ " 4 6 60\n"
+ " 4 7 80\n"
+ " 4 8 110\n"
+ " 5 7 60\n"
+ " 5 11 120\n"
+ " 6 3 0\n"
+ " 6 9 140\n"
+ " 6 10 90\n"
+ " 7 1 30\n"
+ " 8 12 60\n"
+ " 9 12 50\n"
+ "10 12 70\n"
+ "10 2 100\n"
+ "10 7 60\n"
+ "11 10 20\n"
+ "12 11 30\n"
+ "@attributes\n"
+ "source 1\n"
+ "target 12\n"
+ "@end\n";
+
+// Check the interface of Suurballe
+void checkSuurballeCompile()
+{
+ typedef int VType;
+ typedef concepts::Digraph Digraph;
+
+ typedef Digraph::Node Node;
+ typedef Digraph::Arc Arc;
+ typedef concepts::ReadMap<Arc, VType> LengthMap;
+
+ typedef Suurballe<Digraph, LengthMap> ST;
+ typedef Suurballe<Digraph, LengthMap>
+ ::SetFlowMap<ST::FlowMap>
+ ::SetPotentialMap<ST::PotentialMap>
+ ::SetPath<SimplePath<Digraph> >
+ ::SetHeap<concepts::Heap<VType, Digraph::NodeMap<int> > >
+ ::Create SuurballeType;
+
+ Digraph g;
+ Node n;
+ Arc e;
+ LengthMap len;
+ SuurballeType::FlowMap flow(g);
+ SuurballeType::PotentialMap pi(g);
+
+ SuurballeType suurb_test(g, len);
+ const SuurballeType& const_suurb_test = suurb_test;
+
+ suurb_test
+ .flowMap(flow)
+ .potentialMap(pi);
+
+ int k;
+ k = suurb_test.run(n, n);
+ k = suurb_test.run(n, n, k);
+ suurb_test.init(n);
+ suurb_test.fullInit(n);
+ suurb_test.start(n);
+ suurb_test.start(n, k);
+ k = suurb_test.findFlow(n);
+ k = suurb_test.findFlow(n, k);
+ suurb_test.findPaths();
+
+ int f;
+ VType c;
+ ::lemon::ignore_unused_variable_warning(f,c);
+
+ c = const_suurb_test.totalLength();
+ f = const_suurb_test.flow(e);
+ const SuurballeType::FlowMap& fm =
+ const_suurb_test.flowMap();
+ c = const_suurb_test.potential(n);
+ const SuurballeType::PotentialMap& pm =
+ const_suurb_test.potentialMap();
+ k = const_suurb_test.pathNum();
+ Path<Digraph> p = const_suurb_test.path(k);
+
+ ::lemon::ignore_unused_variable_warning(fm);
+ ::lemon::ignore_unused_variable_warning(pm);
+}
+
+// Check the feasibility of the flow
+template <typename Digraph, typename FlowMap>
+bool checkFlow( const Digraph& gr, const FlowMap& flow,
+ typename Digraph::Node s, typename Digraph::Node t,
+ int value )
+{
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+ for (ArcIt e(gr); e != INVALID; ++e)
+ if (!(flow[e] == 0 || flow[e] == 1)) return false;
+
+ for (NodeIt n(gr); n != INVALID; ++n) {
+ int sum = 0;
+ for (OutArcIt e(gr, n); e != INVALID; ++e)
+ sum += flow[e];
+ for (InArcIt e(gr, n); e != INVALID; ++e)
+ sum -= flow[e];
+ if (n == s && sum != value) return false;
+ if (n == t && sum != -value) return false;
+ if (n != s && n != t && sum != 0) return false;
+ }
+
+ return true;
+}
+
+// Check the optimalitiy of the flow
+template < typename Digraph, typename CostMap,
+ typename FlowMap, typename PotentialMap >
+bool checkOptimality( const Digraph& gr, const CostMap& cost,
+ const FlowMap& flow, const PotentialMap& pi )
+{
+ // Check the "Complementary Slackness" optimality condition
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+ bool opt = true;
+ for (ArcIt e(gr); e != INVALID; ++e) {
+ typename CostMap::Value red_cost =
+ cost[e] + pi[gr.source(e)] - pi[gr.target(e)];
+ opt = (flow[e] == 0 && red_cost >= 0) ||
+ (flow[e] == 1 && red_cost <= 0);
+ if (!opt) break;
+ }
+ return opt;
+}
+
+// Check a path
+template <typename Digraph, typename Path>
+bool checkPath( const Digraph& gr, const Path& path,
+ typename Digraph::Node s, typename Digraph::Node t)
+{
+ TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+ Node n = s;
+ for (int i = 0; i < path.length(); ++i) {
+ if (gr.source(path.nth(i)) != n) return false;
+ n = gr.target(path.nth(i));
+ }
+ return n == t;
+}
+
+
+int main()
+{
+ DIGRAPH_TYPEDEFS(ListDigraph);
+
+ // Read the test digraph
+ ListDigraph digraph;
+ ListDigraph::ArcMap<int> length(digraph);
+ Node s, t;
+
+ std::istringstream input(test_lgf);
+ DigraphReader<ListDigraph>(digraph, input).
+ arcMap("length", length).
+ node("source", s).
+ node("target", t).
+ run();
+
+ // Check run()
+ {
+ Suurballe<ListDigraph> suurballe(digraph, length);
+
+ // Find 2 paths
+ check(suurballe.run(s, t) == 2, "Wrong number of paths");
+ check(checkFlow(digraph, suurballe.flowMap(), s, t, 2),
+ "The flow is not feasible");
+ check(suurballe.totalLength() == 510, "The flow is not optimal");
+ check(checkOptimality(digraph, length, suurballe.flowMap(),
+ suurballe.potentialMap()),
+ "Wrong potentials");
+ for (int i = 0; i < suurballe.pathNum(); ++i)
+ check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
+
+ // Find 3 paths
+ check(suurballe.run(s, t, 3) == 3, "Wrong number of paths");
+ check(checkFlow(digraph, suurballe.flowMap(), s, t, 3),
+ "The flow is not feasible");
+ check(suurballe.totalLength() == 1040, "The flow is not optimal");
+ check(checkOptimality(digraph, length, suurballe.flowMap(),
+ suurballe.potentialMap()),
+ "Wrong potentials");
+ for (int i = 0; i < suurballe.pathNum(); ++i)
+ check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
+
+ // Find 5 paths (only 3 can be found)
+ check(suurballe.run(s, t, 5) == 3, "Wrong number of paths");
+ check(checkFlow(digraph, suurballe.flowMap(), s, t, 3),
+ "The flow is not feasible");
+ check(suurballe.totalLength() == 1040, "The flow is not optimal");
+ check(checkOptimality(digraph, length, suurballe.flowMap(),
+ suurballe.potentialMap()),
+ "Wrong potentials");
+ for (int i = 0; i < suurballe.pathNum(); ++i)
+ check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
+ }
+
+ // Check fullInit() + start()
+ {
+ Suurballe<ListDigraph> suurballe(digraph, length);
+ suurballe.fullInit(s);
+
+ // Find 2 paths
+ check(suurballe.start(t) == 2, "Wrong number of paths");
+ check(suurballe.totalLength() == 510, "The flow is not optimal");
+
+ // Find 3 paths
+ check(suurballe.start(t, 3) == 3, "Wrong number of paths");
+ check(suurballe.totalLength() == 1040, "The flow is not optimal");
+
+ // Find 5 paths (only 3 can be found)
+ check(suurballe.start(t, 5) == 3, "Wrong number of paths");
+ check(suurballe.totalLength() == 1040, "The flow is not optimal");
+ }
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/test_tools.h b/extern/quadriflow/3rd/lemon-1.3.1/test/test_tools.h
new file mode 100644
index 00000000000..33003566791
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/test_tools.h
@@ -0,0 +1,50 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2010
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_TEST_TEST_TOOLS_H
+#define LEMON_TEST_TEST_TOOLS_H
+
+///\ingroup misc
+///\file
+///\brief Some utilities to write test programs.
+
+#include <iostream>
+#include <stdlib.h>
+
+///If \c rc is fail, writes an error message and exits.
+
+///If \c rc is fail, writes an error message and exits.
+///The error message contains the file name and the line number of the
+///source code in a standard from, which makes it possible to go there
+///using good source browsers like e.g. \c emacs.
+///
+///For example
+///\code check(0==1,"This is obviously false.");\endcode will
+///print something like this (and then exits).
+///\verbatim file_name.cc:123: error: This is obviously false. \endverbatim
+#define check(rc, msg) \
+ { \
+ if(!(rc)) { \
+ std::cerr << __FILE__ ":" << __LINE__ << ": error: " \
+ << msg << std::endl; \
+ abort(); \
+ } else { } \
+ } \
+
+
+#endif
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/test_tools_fail.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/test_tools_fail.cc
new file mode 100644
index 00000000000..6407cd15b04
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/test_tools_fail.cc
@@ -0,0 +1,25 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include "test_tools.h"
+
+int main()
+{
+ check(false, "Don't panic. Failing is the right behaviour here.");
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/test_tools_pass.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/test_tools_pass.cc
new file mode 100644
index 00000000000..b590c15a614
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/test_tools_pass.cc
@@ -0,0 +1,25 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include "test_tools.h"
+
+int main()
+{
+ check(true, "It should pass.");
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/time_measure_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/time_measure_test.cc
new file mode 100644
index 00000000000..4e7155a91ba
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/time_measure_test.cc
@@ -0,0 +1,60 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/time_measure.h>
+#include <lemon/concept_check.h>
+
+using namespace lemon;
+
+void f()
+{
+ double d=0;
+ for(int i=0;i<1000;i++)
+ d+=0.1;
+}
+
+void g()
+{
+ static Timer T;
+
+ for(int i=0;i<1000;i++)
+ {
+ TimeStamp x(T);
+ ::lemon::ignore_unused_variable_warning(x);
+ }
+}
+
+int main()
+{
+ Timer T;
+ unsigned int n;
+ for(n=0;T.realTime()<0.1;n++) ;
+ std::cout << T << " (" << n << " time queries)\n";
+
+ TimeStamp full;
+ TimeStamp t;
+ t=runningTimeTest(f,0.1,&n,&full);
+ std::cout << t << " (" << n << " tests)\n";
+ std::cout << "Total: " << full << "\n";
+
+ t=runningTimeTest(g,0.1,&n,&full);
+ std::cout << t << " (" << n << " tests)\n";
+ std::cout << "Total: " << full << "\n";
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/tsp_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/tsp_test.cc
new file mode 100644
index 00000000000..398a812e090
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/tsp_test.cc
@@ -0,0 +1,287 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <iostream>
+
+#include <lemon/full_graph.h>
+#include <lemon/math.h>
+#include <lemon/maps.h>
+#include <lemon/random.h>
+#include <lemon/dim2.h>
+
+#include <lemon/nearest_neighbor_tsp.h>
+#include <lemon/greedy_tsp.h>
+#include <lemon/insertion_tsp.h>
+#include <lemon/christofides_tsp.h>
+#include <lemon/opt2_tsp.h>
+
+#include "test_tools.h"
+
+using namespace lemon;
+
+// // Tests checkMetricCost() function
+// void metricCostTest() {
+// GRAPH_TYPEDEFS(FullGraph);
+// FullGraph g(10);
+// check(checkMetricCost(g, constMap<Edge>(0)), "Wrong checkMetricCost()");
+// check(checkMetricCost(g, constMap<Edge>(1)), "Wrong checkMetricCost()");
+// check(!checkMetricCost(g, constMap<Edge>(-1)), "Wrong checkMetricCost()");
+//
+// FullGraph::EdgeMap<float> cost(g);
+// for (NodeIt u(g); u != INVALID; ++u) {
+// for (NodeIt v(g); v != INVALID; ++v) {
+// if (u == v) continue;
+// float x1 = g.id(u), x2 = g.id(v);
+// float y1 = x1 * x1, y2 = x2 * x2;
+// cost[g.edge(u, v)] = std::sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
+// }
+// }
+// check(checkMetricCost(g, cost), "Wrong checkMetricCost()");
+// float eps = Tolerance<float>::defaultEpsilon();
+// cost[g.edge(g(0), g(9))] =
+// cost[g.edge(g(0), g(8))] + cost[g.edge(g(8), g(9))] + eps * 2;
+// check(!checkMetricCost(g, cost), "Wrong checkMetricCost()");
+// check(checkMetricCost(g, cost, Tolerance<float>(eps * 4)),
+// "Wrong checkMetricCost()");
+// }
+
+// Checks tour validity
+template <typename Container>
+bool checkTour(const FullGraph &gr, const Container &p) {
+ FullGraph::NodeMap<bool> used(gr, false);
+
+ int node_cnt = 0;
+ for (typename Container::const_iterator it = p.begin(); it != p.end(); ++it)
+ {
+ FullGraph::Node node = *it;
+ if (used[node]) return false;
+ used[node] = true;
+ ++node_cnt;
+ }
+
+ return (node_cnt == gr.nodeNum());
+}
+
+// Checks tour validity
+bool checkTourPath(const FullGraph &gr, const Path<FullGraph> &p) {
+ FullGraph::NodeMap<bool> used(gr, false);
+
+ if (!checkPath(gr, p)) return false;
+ if (gr.nodeNum() <= 1 && p.length() != 0) return false;
+ if (gr.nodeNum() > 1 && p.length() != gr.nodeNum()) return false;
+
+ for (int i = 0; i < p.length(); ++i) {
+ if (used[gr.target(p.nth(i))]) return false;
+ used[gr.target(p.nth(i))] = true;
+ }
+ return true;
+}
+
+// Checks tour cost
+template <typename CostMap>
+bool checkCost(const FullGraph &gr, const std::vector<FullGraph::Node> &p,
+ const CostMap &cost, typename CostMap::Value total)
+{
+ typedef typename CostMap::Value Cost;
+
+ Cost s = 0;
+ for (int i = 0; i < int(p.size()) - 1; ++i)
+ s += cost[gr.edge(p[i], p[i+1])];
+ if (int(p.size()) >= 2)
+ s += cost[gr.edge(p.back(), p.front())];
+
+ return !Tolerance<Cost>().different(s, total);
+}
+
+// Checks tour cost
+template <typename CostMap>
+bool checkCost(const FullGraph &, const Path<FullGraph> &p,
+ const CostMap &cost, typename CostMap::Value total)
+{
+ typedef typename CostMap::Value Cost;
+
+ Cost s = 0;
+ for (int i = 0; i < p.length(); ++i)
+ s += cost[p.nth(i)];
+
+ return !Tolerance<Cost>().different(s, total);
+}
+
+// Tests a TSP algorithm on small graphs
+template <typename TSP>
+void tspTestSmall(const std::string &alg_name) {
+ GRAPH_TYPEDEFS(FullGraph);
+
+ for (int n = 0; n <= 5; ++n) {
+ FullGraph g(n);
+ unsigned nsize = n;
+ int esize = n <= 1 ? 0 : n;
+
+ ConstMap<Edge, int> cost_map(1);
+ TSP alg(g, cost_map);
+
+ check(alg.run() == esize, alg_name + ": Wrong total cost");
+ check(alg.tourCost() == esize, alg_name + ": Wrong total cost");
+
+ std::list<Node> list1(nsize), list2;
+ std::vector<Node> vec1(nsize), vec2;
+ alg.tourNodes(list1.begin());
+ alg.tourNodes(vec1.begin());
+ alg.tourNodes(std::front_inserter(list2));
+ alg.tourNodes(std::back_inserter(vec2));
+ check(checkTour(g, alg.tourNodes()), alg_name + ": Wrong node sequence");
+ check(checkTour(g, list1), alg_name + ": Wrong node sequence");
+ check(checkTour(g, vec1), alg_name + ": Wrong node sequence");
+ check(checkTour(g, list2), alg_name + ": Wrong node sequence");
+ check(checkTour(g, vec2), alg_name + ": Wrong node sequence");
+ check(checkCost(g, vec1, constMap<Edge, int>(1), esize),
+ alg_name + ": Wrong tour cost");
+
+ SimplePath<FullGraph> path;
+ alg.tour(path);
+ check(path.length() == esize, alg_name + ": Wrong tour");
+ check(checkTourPath(g, path), alg_name + ": Wrong tour");
+ check(checkCost(g, path, constMap<Edge, int>(1), esize),
+ alg_name + ": Wrong tour cost");
+ }
+}
+
+// Tests a TSP algorithm on random graphs
+template <typename TSP>
+void tspTestRandom(const std::string &alg_name) {
+ GRAPH_TYPEDEFS(FullGraph);
+
+ FullGraph g(20);
+ FullGraph::NodeMap<dim2::Point<double> > pos(g);
+ DoubleEdgeMap cost(g);
+
+ TSP alg(g, cost);
+ Opt2Tsp<DoubleEdgeMap > opt2(g, cost);
+
+ for (int i = 1; i <= 3; i++) {
+ for (NodeIt u(g); u != INVALID; ++u) {
+ pos[u] = dim2::Point<double>(rnd(), rnd());
+ }
+ for (NodeIt u(g); u != INVALID; ++u) {
+ for (NodeIt v(g); v != INVALID; ++v) {
+ if (u == v) continue;
+ cost[g.edge(u, v)] = (pos[u] - pos[v]).normSquare();
+ }
+ }
+
+ check(alg.run() > 0, alg_name + ": Wrong total cost");
+
+ std::vector<Node> vec;
+ alg.tourNodes(std::back_inserter(vec));
+ check(checkTour(g, vec), alg_name + ": Wrong node sequence");
+ check(checkCost(g, vec, cost, alg.tourCost()),
+ alg_name + ": Wrong tour cost");
+
+ SimplePath<FullGraph> path;
+ alg.tour(path);
+ check(checkTourPath(g, path), alg_name + ": Wrong tour");
+ check(checkCost(g, path, cost, alg.tourCost()),
+ alg_name + ": Wrong tour cost");
+
+ check(!Tolerance<double>().less(alg.tourCost(), opt2.run(alg.tourNodes())),
+ "2-opt improvement: Wrong total cost");
+ check(checkTour(g, opt2.tourNodes()),
+ "2-opt improvement: Wrong node sequence");
+ check(checkCost(g, opt2.tourNodes(), cost, opt2.tourCost()),
+ "2-opt improvement: Wrong tour cost");
+
+ check(!Tolerance<double>().less(alg.tourCost(), opt2.run(path)),
+ "2-opt improvement: Wrong total cost");
+ check(checkTour(g, opt2.tourNodes()),
+ "2-opt improvement: Wrong node sequence");
+ check(checkCost(g, opt2.tourNodes(), cost, opt2.tourCost()),
+ "2-opt improvement: Wrong tour cost");
+ }
+}
+
+// Algorithm class for Nearest Insertion
+template <typename CM>
+class NearestInsertionTsp : public InsertionTsp<CM> {
+public:
+ NearestInsertionTsp(const FullGraph &gr, const CM &cost)
+ : InsertionTsp<CM>(gr, cost) {}
+ typename CM::Value run() {
+ return InsertionTsp<CM>::run(InsertionTsp<CM>::NEAREST);
+ }
+};
+
+// Algorithm class for Farthest Insertion
+template <typename CM>
+class FarthestInsertionTsp : public InsertionTsp<CM> {
+public:
+ FarthestInsertionTsp(const FullGraph &gr, const CM &cost)
+ : InsertionTsp<CM>(gr, cost) {}
+ typename CM::Value run() {
+ return InsertionTsp<CM>::run(InsertionTsp<CM>::FARTHEST);
+ }
+};
+
+// Algorithm class for Cheapest Insertion
+template <typename CM>
+class CheapestInsertionTsp : public InsertionTsp<CM> {
+public:
+ CheapestInsertionTsp(const FullGraph &gr, const CM &cost)
+ : InsertionTsp<CM>(gr, cost) {}
+ typename CM::Value run() {
+ return InsertionTsp<CM>::run(InsertionTsp<CM>::CHEAPEST);
+ }
+};
+
+// Algorithm class for Random Insertion
+template <typename CM>
+class RandomInsertionTsp : public InsertionTsp<CM> {
+public:
+ RandomInsertionTsp(const FullGraph &gr, const CM &cost)
+ : InsertionTsp<CM>(gr, cost) {}
+ typename CM::Value run() {
+ return InsertionTsp<CM>::run(InsertionTsp<CM>::RANDOM);
+ }
+};
+
+int main() {
+ GRAPH_TYPEDEFS(FullGraph);
+
+ // metricCostTest();
+
+ tspTestSmall<NearestNeighborTsp<ConstMap<Edge, int> > >("Nearest Neighbor");
+ tspTestSmall<GreedyTsp<ConstMap<Edge, int> > >("Greedy");
+ tspTestSmall<NearestInsertionTsp<ConstMap<Edge, int> > >("Nearest Insertion");
+ tspTestSmall<FarthestInsertionTsp<ConstMap<Edge, int> > >
+ ("Farthest Insertion");
+ tspTestSmall<CheapestInsertionTsp<ConstMap<Edge, int> > >
+ ("Cheapest Insertion");
+ tspTestSmall<RandomInsertionTsp<ConstMap<Edge, int> > >("Random Insertion");
+ tspTestSmall<ChristofidesTsp<ConstMap<Edge, int> > >("Christofides");
+ tspTestSmall<Opt2Tsp<ConstMap<Edge, int> > >("2-opt");
+
+ tspTestRandom<NearestNeighborTsp<DoubleEdgeMap > >("Nearest Neighbor");
+ tspTestRandom<GreedyTsp<DoubleEdgeMap > >("Greedy");
+ tspTestRandom<NearestInsertionTsp<DoubleEdgeMap > >("Nearest Insertion");
+ tspTestRandom<FarthestInsertionTsp<DoubleEdgeMap > >("Farthest Insertion");
+ tspTestRandom<CheapestInsertionTsp<DoubleEdgeMap > >("Cheapest Insertion");
+ tspTestRandom<RandomInsertionTsp<DoubleEdgeMap > >("Random Insertion");
+ tspTestRandom<ChristofidesTsp<DoubleEdgeMap > >("Christofides");
+ tspTestRandom<Opt2Tsp<DoubleEdgeMap > >("2-opt");
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/test/unionfind_test.cc b/extern/quadriflow/3rd/lemon-1.3.1/test/unionfind_test.cc
new file mode 100644
index 00000000000..e82d8e64ae7
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/test/unionfind_test.cc
@@ -0,0 +1,102 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <lemon/list_graph.h>
+#include <lemon/maps.h>
+#include <lemon/unionfind.h>
+#include "test_tools.h"
+
+using namespace lemon;
+using namespace std;
+
+typedef UnionFindEnum<ListGraph::NodeMap<int> > UFE;
+
+int main() {
+ ListGraph g;
+ ListGraph::NodeMap<int> base(g);
+ UFE U(base);
+ vector<ListGraph::Node> n;
+
+ for(int i=0;i<20;i++) n.push_back(g.addNode());
+
+ U.insert(n[1]);
+ U.insert(n[2]);
+
+ check(U.join(n[1],n[2]) != -1, "Something is wrong with UnionFindEnum");
+
+ U.insert(n[3]);
+ U.insert(n[4]);
+ U.insert(n[5]);
+ U.insert(n[6]);
+ U.insert(n[7]);
+
+
+ check(U.join(n[1],n[4]) != -1, "Something is wrong with UnionFindEnum");
+ check(U.join(n[2],n[4]) == -1, "Something is wrong with UnionFindEnum");
+ check(U.join(n[3],n[5]) != -1, "Something is wrong with UnionFindEnum");
+
+
+ U.insert(n[8],U.find(n[5]));
+
+
+ check(U.size(U.find(n[4])) == 3, "Something is wrong with UnionFindEnum");
+ check(U.size(U.find(n[5])) == 3, "Something is wrong with UnionFindEnum");
+ check(U.size(U.find(n[6])) == 1, "Something is wrong with UnionFindEnum");
+ check(U.size(U.find(n[2])) == 3, "Something is wrong with UnionFindEnum");
+
+
+ U.insert(n[9]);
+ U.insert(n[10],U.find(n[9]));
+
+
+ check(U.join(n[8],n[10]) != -1, "Something is wrong with UnionFindEnum");
+
+
+ check(U.size(U.find(n[4])) == 3, "Something is wrong with UnionFindEnum");
+ check(U.size(U.find(n[9])) == 5, "Something is wrong with UnionFindEnum");
+
+ check(U.size(U.find(n[8])) == 5, "Something is wrong with UnionFindEnum");
+
+ U.erase(n[9]);
+ U.erase(n[1]);
+
+ check(U.size(U.find(n[10])) == 4, "Something is wrong with UnionFindEnum");
+ check(U.size(U.find(n[2])) == 2, "Something is wrong with UnionFindEnum");
+
+ U.erase(n[6]);
+ U.split(U.find(n[8]));
+
+
+ check(U.size(U.find(n[4])) == 2, "Something is wrong with UnionFindEnum");
+ check(U.size(U.find(n[3])) == 1, "Something is wrong with UnionFindEnum");
+ check(U.size(U.find(n[2])) == 2, "Something is wrong with UnionFindEnum");
+
+
+ check(U.join(n[3],n[4]) != -1, "Something is wrong with UnionFindEnum");
+ check(U.join(n[2],n[4]) == -1, "Something is wrong with UnionFindEnum");
+
+
+ check(U.size(U.find(n[4])) == 3, "Something is wrong with UnionFindEnum");
+ check(U.size(U.find(n[3])) == 3, "Something is wrong with UnionFindEnum");
+ check(U.size(U.find(n[2])) == 3, "Something is wrong with UnionFindEnum");
+
+ U.eraseClass(U.find(n[4]));
+ U.eraseClass(U.find(n[7]));
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/tools/CMakeLists.txt b/extern/quadriflow/3rd/lemon-1.3.1/tools/CMakeLists.txt
new file mode 100644
index 00000000000..64b7df77f65
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/tools/CMakeLists.txt
@@ -0,0 +1,31 @@
+INCLUDE_DIRECTORIES(
+ ${PROJECT_SOURCE_DIR}
+ ${PROJECT_BINARY_DIR}
+)
+
+LINK_DIRECTORIES(
+ ${PROJECT_BINARY_DIR}/lemon
+)
+
+ADD_EXECUTABLE(lgf-gen lgf-gen.cc)
+TARGET_LINK_LIBRARIES(lgf-gen lemon)
+
+ADD_EXECUTABLE(dimacs-to-lgf dimacs-to-lgf.cc)
+TARGET_LINK_LIBRARIES(dimacs-to-lgf lemon)
+
+ADD_EXECUTABLE(dimacs-solver dimacs-solver.cc)
+TARGET_LINK_LIBRARIES(dimacs-solver lemon)
+
+INSTALL(
+ TARGETS lgf-gen dimacs-to-lgf dimacs-solver
+ RUNTIME DESTINATION bin
+ COMPONENT bin
+)
+
+IF(NOT WIN32)
+ INSTALL(
+ PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/lemon-0.x-to-1.x.sh
+ DESTINATION bin
+ COMPONENT bin
+ )
+ENDIF()
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/tools/dimacs-solver.cc b/extern/quadriflow/3rd/lemon-1.3.1/tools/dimacs-solver.cc
new file mode 100644
index 00000000000..60da2330e50
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/tools/dimacs-solver.cc
@@ -0,0 +1,279 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2013
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\ingroup tools
+///\file
+///\brief DIMACS problem solver.
+///
+/// This program solves various problems given in DIMACS format.
+///
+/// See
+/// \code
+/// dimacs-solver --help
+/// \endcode
+/// for more info on usage.
+
+#include <iostream>
+#include <fstream>
+#include <cstring>
+
+#include <lemon/smart_graph.h>
+#include <lemon/dimacs.h>
+#include <lemon/lgf_writer.h>
+#include <lemon/time_measure.h>
+
+#include <lemon/arg_parser.h>
+#include <lemon/error.h>
+
+#include <lemon/dijkstra.h>
+#include <lemon/preflow.h>
+#include <lemon/matching.h>
+#include <lemon/network_simplex.h>
+
+using namespace lemon;
+typedef SmartDigraph Digraph;
+DIGRAPH_TYPEDEFS(Digraph);
+typedef SmartGraph Graph;
+
+template<class Value>
+void solve_sp(ArgParser &ap, std::istream &is, std::ostream &,
+ DimacsDescriptor &desc)
+{
+ bool report = !ap.given("q");
+ Digraph g;
+ Node s;
+ Digraph::ArcMap<Value> len(g);
+ Timer t;
+ t.restart();
+ readDimacsSp(is, g, len, s, desc);
+ if(report) std::cerr << "Read the file: " << t << '\n';
+ t.restart();
+ Dijkstra<Digraph, Digraph::ArcMap<Value> > dij(g,len);
+ if(report) std::cerr << "Setup Dijkstra class: " << t << '\n';
+ t.restart();
+ dij.run(s);
+ if(report) std::cerr << "Run Dijkstra: " << t << '\n';
+}
+
+template<class Value>
+void solve_max(ArgParser &ap, std::istream &is, std::ostream &,
+ Value infty, DimacsDescriptor &desc)
+{
+ bool report = !ap.given("q");
+ Digraph g;
+ Node s,t;
+ Digraph::ArcMap<Value> cap(g);
+ Timer ti;
+ ti.restart();
+ readDimacsMax(is, g, cap, s, t, infty, desc);
+ if(report) std::cerr << "Read the file: " << ti << '\n';
+ ti.restart();
+ Preflow<Digraph, Digraph::ArcMap<Value> > pre(g,cap,s,t);
+ if(report) std::cerr << "Setup Preflow class: " << ti << '\n';
+ ti.restart();
+ pre.run();
+ if(report) std::cerr << "Run Preflow: " << ti << '\n';
+ if(report) std::cerr << "\nMax flow value: " << pre.flowValue() << '\n';
+}
+
+template<class Value, class LargeValue>
+void solve_min(ArgParser &ap, std::istream &is, std::ostream &,
+ Value infty, DimacsDescriptor &desc)
+{
+ bool report = !ap.given("q");
+ Digraph g;
+ Digraph::ArcMap<Value> lower(g), cap(g), cost(g);
+ Digraph::NodeMap<Value> sup(g);
+ Timer ti;
+
+ ti.restart();
+ readDimacsMin(is, g, lower, cap, cost, sup, infty, desc);
+ ti.stop();
+ Value sum_sup = 0;
+ for (Digraph::NodeIt n(g); n != INVALID; ++n) {
+ sum_sup += sup[n];
+ }
+ if (report) {
+ std::cerr << "Sum of supply values: " << sum_sup << "\n";
+ if (sum_sup <= 0)
+ std::cerr << "GEQ supply contraints are used for NetworkSimplex\n\n";
+ else
+ std::cerr << "LEQ supply contraints are used for NetworkSimplex\n\n";
+ }
+ if (report) std::cerr << "Read the file: " << ti << '\n';
+
+ typedef NetworkSimplex<Digraph, Value> MCF;
+ ti.restart();
+ MCF ns(g);
+ ns.lowerMap(lower).upperMap(cap).costMap(cost).supplyMap(sup);
+ if (sum_sup > 0) ns.supplyType(ns.LEQ);
+ if (report) std::cerr << "Setup NetworkSimplex class: " << ti << '\n';
+ ti.restart();
+ typename MCF::ProblemType res = ns.run();
+ if (report) {
+ std::cerr << "Run NetworkSimplex: " << ti << "\n\n";
+ std::cerr << "Feasible flow: " << (res == MCF::OPTIMAL ? "found" :
+ "not found") << '\n';
+ if (res) std::cerr << "Min flow cost: "
+ << ns.template totalCost<LargeValue>() << '\n';
+ }
+}
+
+void solve_mat(ArgParser &ap, std::istream &is, std::ostream &,
+ DimacsDescriptor &desc)
+{
+ bool report = !ap.given("q");
+ Graph g;
+ Timer ti;
+ ti.restart();
+ readDimacsMat(is, g, desc);
+ if(report) std::cerr << "Read the file: " << ti << '\n';
+ ti.restart();
+ MaxMatching<Graph> mat(g);
+ if(report) std::cerr << "Setup MaxMatching class: " << ti << '\n';
+ ti.restart();
+ mat.run();
+ if(report) std::cerr << "Run MaxMatching: " << ti << '\n';
+ if(report) std::cerr << "\nCardinality of max matching: "
+ << mat.matchingSize() << '\n';
+}
+
+
+template<class Value, class LargeValue>
+void solve(ArgParser &ap, std::istream &is, std::ostream &os,
+ DimacsDescriptor &desc)
+{
+ std::stringstream iss(static_cast<std::string>(ap["infcap"]));
+ Value infty;
+ iss >> infty;
+ if(iss.fail())
+ {
+ std::cerr << "Cannot interpret '"
+ << static_cast<std::string>(ap["infcap"]) << "' as infinite"
+ << std::endl;
+ exit(1);
+ }
+
+ switch(desc.type)
+ {
+ case DimacsDescriptor::MIN:
+ solve_min<Value, LargeValue>(ap,is,os,infty,desc);
+ break;
+ case DimacsDescriptor::MAX:
+ solve_max<Value>(ap,is,os,infty,desc);
+ break;
+ case DimacsDescriptor::SP:
+ solve_sp<Value>(ap,is,os,desc);
+ break;
+ case DimacsDescriptor::MAT:
+ solve_mat(ap,is,os,desc);
+ break;
+ default:
+ break;
+ }
+}
+
+int main(int argc, const char *argv[]) {
+
+ std::string inputName;
+ std::string outputName;
+
+ ArgParser ap(argc, argv);
+ ap.other("[INFILE [OUTFILE]]",
+ "If either the INFILE or OUTFILE file is missing the standard\n"
+ " input/output will be used instead.")
+ .boolOption("q", "Do not print any report")
+ .boolOption("int","Use 'int' for capacities, costs etc. (default)")
+ .optionGroup("datatype","int")
+#ifdef LEMON_HAVE_LONG_LONG
+ .boolOption("long","Use 'long long' for capacities, costs etc.")
+ .optionGroup("datatype","long")
+#endif
+ .boolOption("double","Use 'double' for capacities, costs etc.")
+ .optionGroup("datatype","double")
+ .boolOption("ldouble","Use 'long double' for capacities, costs etc.")
+ .optionGroup("datatype","ldouble")
+ .onlyOneGroup("datatype")
+ .stringOption("infcap","Value used for 'very high' capacities","0")
+ .run();
+
+ std::ifstream input;
+ std::ofstream output;
+
+ switch(ap.files().size())
+ {
+ case 2:
+ output.open(ap.files()[1].c_str());
+ if (!output) {
+ throw IoError("Cannot open the file for writing", ap.files()[1]);
+ }
+ case 1:
+ input.open(ap.files()[0].c_str());
+ if (!input) {
+ throw IoError("File cannot be found", ap.files()[0]);
+ }
+ case 0:
+ break;
+ default:
+ std::cerr << ap.commandName() << ": too many arguments\n";
+ return 1;
+ }
+ std::istream& is = (ap.files().size()<1 ? std::cin : input);
+ std::ostream& os = (ap.files().size()<2 ? std::cout : output);
+
+ DimacsDescriptor desc = dimacsType(is);
+
+ if(!ap.given("q"))
+ {
+ std::cout << "Problem type: ";
+ switch(desc.type)
+ {
+ case DimacsDescriptor::MIN:
+ std::cout << "min";
+ break;
+ case DimacsDescriptor::MAX:
+ std::cout << "max";
+ break;
+ case DimacsDescriptor::SP:
+ std::cout << "sp";
+ case DimacsDescriptor::MAT:
+ std::cout << "mat";
+ break;
+ default:
+ exit(1);
+ break;
+ }
+ std::cout << "\nNum of nodes: " << desc.nodeNum;
+ std::cout << "\nNum of arcs: " << desc.edgeNum;
+ std::cout << "\n\n";
+ }
+
+ if(ap.given("double"))
+ solve<double, double>(ap,is,os,desc);
+ else if(ap.given("ldouble"))
+ solve<long double, long double>(ap,is,os,desc);
+#ifdef LEMON_HAVE_LONG_LONG
+ else if(ap.given("long"))
+ solve<long long, long long>(ap,is,os,desc);
+ else solve<int, long long>(ap,is,os,desc);
+#else
+ else solve<int, long>(ap,is,os,desc);
+#endif
+
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/tools/dimacs-to-lgf.cc b/extern/quadriflow/3rd/lemon-1.3.1/tools/dimacs-to-lgf.cc
new file mode 100644
index 00000000000..3968645dd90
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/tools/dimacs-to-lgf.cc
@@ -0,0 +1,148 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\ingroup tools
+///\file
+///\brief DIMACS to LGF converter.
+///
+/// This program converts various DIMACS formats to the LEMON Digraph Format
+/// (LGF).
+///
+/// See
+/// \code
+/// dimacs-to-lgf --help
+/// \endcode
+/// for more info on the usage.
+
+#include <iostream>
+#include <fstream>
+#include <cstring>
+
+#include <lemon/smart_graph.h>
+#include <lemon/dimacs.h>
+#include <lemon/lgf_writer.h>
+
+#include <lemon/arg_parser.h>
+#include <lemon/error.h>
+
+using namespace std;
+using namespace lemon;
+
+
+int main(int argc, const char *argv[]) {
+ typedef SmartDigraph Digraph;
+
+ typedef Digraph::Arc Arc;
+ typedef Digraph::Node Node;
+ typedef Digraph::ArcIt ArcIt;
+ typedef Digraph::NodeIt NodeIt;
+ typedef Digraph::ArcMap<double> DoubleArcMap;
+ typedef Digraph::NodeMap<double> DoubleNodeMap;
+
+ std::string inputName;
+ std::string outputName;
+
+ ArgParser ap(argc, argv);
+ ap.other("[INFILE [OUTFILE]]",
+ "If either the INFILE or OUTFILE file is missing the standard\n"
+ " input/output will be used instead.")
+ .run();
+
+ ifstream input;
+ ofstream output;
+
+ switch(ap.files().size())
+ {
+ case 2:
+ output.open(ap.files()[1].c_str());
+ if (!output) {
+ throw IoError("Cannot open the file for writing", ap.files()[1]);
+ }
+ case 1:
+ input.open(ap.files()[0].c_str());
+ if (!input) {
+ throw IoError("File cannot be found", ap.files()[0]);
+ }
+ case 0:
+ break;
+ default:
+ cerr << ap.commandName() << ": too many arguments\n";
+ return 1;
+ }
+ istream& is = (ap.files().size()<1 ? cin : input);
+ ostream& os = (ap.files().size()<2 ? cout : output);
+
+ DimacsDescriptor desc = dimacsType(is);
+ switch(desc.type)
+ {
+ case DimacsDescriptor::MIN:
+ {
+ Digraph digraph;
+ DoubleArcMap lower(digraph), capacity(digraph), cost(digraph);
+ DoubleNodeMap supply(digraph);
+ readDimacsMin(is, digraph, lower, capacity, cost, supply, 0, desc);
+ DigraphWriter<Digraph>(digraph, os).
+ nodeMap("supply", supply).
+ arcMap("lower", lower).
+ arcMap("capacity", capacity).
+ arcMap("cost", cost).
+ attribute("problem","min").
+ run();
+ }
+ break;
+ case DimacsDescriptor::MAX:
+ {
+ Digraph digraph;
+ Node s, t;
+ DoubleArcMap capacity(digraph);
+ readDimacsMax(is, digraph, capacity, s, t, 0, desc);
+ DigraphWriter<Digraph>(digraph, os).
+ arcMap("capacity", capacity).
+ node("source", s).
+ node("target", t).
+ attribute("problem","max").
+ run();
+ }
+ break;
+ case DimacsDescriptor::SP:
+ {
+ Digraph digraph;
+ Node s;
+ DoubleArcMap capacity(digraph);
+ readDimacsSp(is, digraph, capacity, s, desc);
+ DigraphWriter<Digraph>(digraph, os).
+ arcMap("capacity", capacity).
+ node("source", s).
+ attribute("problem","sp").
+ run();
+ }
+ break;
+ case DimacsDescriptor::MAT:
+ {
+ Digraph digraph;
+ readDimacsMat(is, digraph,desc);
+ DigraphWriter<Digraph>(digraph, os).
+ attribute("problem","mat").
+ run();
+ }
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/tools/lemon-0.x-to-1.x.sh b/extern/quadriflow/3rd/lemon-1.3.1/tools/lemon-0.x-to-1.x.sh
new file mode 100755
index 00000000000..1dac1be653a
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/tools/lemon-0.x-to-1.x.sh
@@ -0,0 +1,134 @@
+#!/bin/bash
+
+set -e
+
+if [ $# -eq 0 -o x$1 = "x-h" -o x$1 = "x-help" -o x$1 = "x--help" ]; then
+ echo "Usage:"
+ echo " $0 source-file(s)"
+ exit
+fi
+
+for i in $@
+do
+ echo Update $i...
+ TMP=`mktemp`
+ sed -e "s/\<undirected graph\>/_gr_aph_label_/g"\
+ -e "s/\<undirected graphs\>/_gr_aph_label_s/g"\
+ -e "s/\<undirected edge\>/_ed_ge_label_/g"\
+ -e "s/\<undirected edges\>/_ed_ge_label_s/g"\
+ -e "s/\<directed graph\>/_digr_aph_label_/g"\
+ -e "s/\<directed graphs\>/_digr_aph_label_s/g"\
+ -e "s/\<directed edge\>/_ar_c_label_/g"\
+ -e "s/\<directed edges\>/_ar_c_label_s/g"\
+ -e "s/UGraph/_Gr_aph_label_/g"\
+ -e "s/u[Gg]raph/_gr_aph_label_/g"\
+ -e "s/Graph\>/_Digr_aph_label_/g"\
+ -e "s/\<graph\>/_digr_aph_label_/g"\
+ -e "s/Graphs\>/_Digr_aph_label_s/g"\
+ -e "s/\<graphs\>/_digr_aph_label_s/g"\
+ -e "s/\([Gg]\)raph\([a-z]\)/_\1r_aph_label_\2/g"\
+ -e "s/\([a-z_]\)graph/\1_gr_aph_label_/g"\
+ -e "s/Graph/_Digr_aph_label_/g"\
+ -e "s/graph/_digr_aph_label_/g"\
+ -e "s/UEdge/_Ed_ge_label_/g"\
+ -e "s/u[Ee]dge/_ed_ge_label_/g"\
+ -e "s/IncEdgeIt/_In_cEd_geIt_label_/g"\
+ -e "s/Edge\>/_Ar_c_label_/g"\
+ -e "s/\<edge\>/_ar_c_label_/g"\
+ -e "s/_edge\>/__ar_c_label_/g"\
+ -e "s/Edges\>/_Ar_c_label_s/g"\
+ -e "s/\<edges\>/_ar_c_label_s/g"\
+ -e "s/_edges\>/__ar_c_label_s/g"\
+ -e "s/\([Ee]\)dge\([a-z]\)/_\1d_ge_label_\2/g"\
+ -e "s/\([a-z]\)edge/\1_ed_ge_label_/g"\
+ -e "s/Edge/_Ar_c_label_/g"\
+ -e "s/edge/_ar_c_label_/g"\
+ -e "s/A[Nn]ode/_Re_d_label_/g"\
+ -e "s/B[Nn]ode/_Blu_e_label_/g"\
+ -e "s/A-[Nn]ode/_Re_d_label_/g"\
+ -e "s/B-[Nn]ode/_Blu_e_label_/g"\
+ -e "s/a[Nn]ode/_re_d_label_/g"\
+ -e "s/b[Nn]ode/_blu_e_label_/g"\
+ -e "s/\<UGRAPH_TYPEDEFS\([ \t]*([ \t]*\)typename[ \t]/TEMPLATE__GR_APH_TY_PEDE_FS_label_\1/g"\
+ -e "s/\<GRAPH_TYPEDEFS\([ \t]*([ \t]*\)typename[ \t]/TEMPLATE__DIGR_APH_TY_PEDE_FS_label_\1/g"\
+ -e "s/\<UGRAPH_TYPEDEFS\>/_GR_APH_TY_PEDE_FS_label_/g"\
+ -e "s/\<GRAPH_TYPEDEFS\>/_DIGR_APH_TY_PEDE_FS_label_/g"\
+ -e "s/_Digr_aph_label_/Digraph/g"\
+ -e "s/_digr_aph_label_/digraph/g"\
+ -e "s/_Gr_aph_label_/Graph/g"\
+ -e "s/_gr_aph_label_/graph/g"\
+ -e "s/_Ar_c_label_/Arc/g"\
+ -e "s/_ar_c_label_/arc/g"\
+ -e "s/_Ed_ge_label_/Edge/g"\
+ -e "s/_ed_ge_label_/edge/g"\
+ -e "s/_In_cEd_geIt_label_/IncEdgeIt/g"\
+ -e "s/_Re_d_label_/Red/g"\
+ -e "s/_Blu_e_label_/Blue/g"\
+ -e "s/_re_d_label_/red/g"\
+ -e "s/_blu_e_label_/blue/g"\
+ -e "s/_GR_APH_TY_PEDE_FS_label_/GRAPH_TYPEDEFS/g"\
+ -e "s/_DIGR_APH_TY_PEDE_FS_label_/DIGRAPH_TYPEDEFS/g"\
+ -e "s/\<digraph_adaptor\.h\>/adaptors.h/g"\
+ -e "s/\<digraph_utils\.h\>/core.h/g"\
+ -e "s/\<digraph_reader\.h\>/lgf_reader.h/g"\
+ -e "s/\<digraph_writer\.h\>/lgf_writer.h/g"\
+ -e "s/\<topology\.h\>/connectivity.h/g"\
+ -e "s/DigraphToEps/GraphToEps/g"\
+ -e "s/digraphToEps/graphToEps/g"\
+ -e "s/\<DefPredMap\>/SetPredMap/g"\
+ -e "s/\<DefDistMap\>/SetDistMap/g"\
+ -e "s/\<DefReachedMap\>/SetReachedMap/g"\
+ -e "s/\<DefProcessedMap\>/SetProcessedMap/g"\
+ -e "s/\<DefHeap\>/SetHeap/g"\
+ -e "s/\<DefStandardHeap\>/SetStandradHeap/g"\
+ -e "s/\<DefOperationTraits\>/SetOperationTraits/g"\
+ -e "s/\<DefProcessedMapToBeDefaultMap\>/SetStandardProcessedMap/g"\
+ -e "s/\<copyGraph\>/graphCopy/g"\
+ -e "s/\<copyDigraph\>/digraphCopy/g"\
+ -e "s/\<HyperCubeDigraph\>/HypercubeGraph/g"\
+ -e "s/\<IntegerMap\>/RangeMap/g"\
+ -e "s/\<integerMap\>/rangeMap/g"\
+ -e "s/\<\([sS]\)tdMap\>/\1parseMap/g"\
+ -e "s/\<\([Ff]\)unctorMap\>/\1unctorToMap/g"\
+ -e "s/\<\([Mm]\)apFunctor\>/\1apToFunctor/g"\
+ -e "s/\<\([Ff]\)orkWriteMap\>/\1orkMap/g"\
+ -e "s/\<StoreBoolMap\>/LoggerBoolMap/g"\
+ -e "s/\<storeBoolMap\>/loggerBoolMap/g"\
+ -e "s/\<InvertableMap\>/CrossRefMap/g"\
+ -e "s/\<invertableMap\>/crossRefMap/g"\
+ -e "s/\<DescriptorMap\>/RangeIdMap/g"\
+ -e "s/\<descriptorMap\>/rangeIdMap/g"\
+ -e "s/\<BoundingBox\>/Box/g"\
+ -e "s/\<readNauty\>/readNautyGraph/g"\
+ -e "s/\<RevDigraphAdaptor\>/ReverseDigraph/g"\
+ -e "s/\<revDigraphAdaptor\>/reverseDigraph/g"\
+ -e "s/\<SubDigraphAdaptor\>/SubDigraph/g"\
+ -e "s/\<subDigraphAdaptor\>/subDigraph/g"\
+ -e "s/\<SubGraphAdaptor\>/SubGraph/g"\
+ -e "s/\<subGraphAdaptor\>/subGraph/g"\
+ -e "s/\<NodeSubDigraphAdaptor\>/FilterNodes/g"\
+ -e "s/\<nodeSubDigraphAdaptor\>/filterNodes/g"\
+ -e "s/\<ArcSubDigraphAdaptor\>/FilterArcs/g"\
+ -e "s/\<arcSubDigraphAdaptor\>/filterArcs/g"\
+ -e "s/\<UndirDigraphAdaptor\>/Undirector/g"\
+ -e "s/\<undirDigraphAdaptor\>/undirector/g"\
+ -e "s/\<ResDigraphAdaptor\>/ResidualDigraph/g"\
+ -e "s/\<resDigraphAdaptor\>/residualDigraph/g"\
+ -e "s/\<SplitDigraphAdaptor\>/SplitNodes/g"\
+ -e "s/\<splitDigraphAdaptor\>/splitNodes/g"\
+ -e "s/\<SubGraphAdaptor\>/SubGraph/g"\
+ -e "s/\<subGraphAdaptor\>/subGraph/g"\
+ -e "s/\<NodeSubGraphAdaptor\>/FilterNodes/g"\
+ -e "s/\<nodeSubGraphAdaptor\>/filterNodes/g"\
+ -e "s/\<ArcSubGraphAdaptor\>/FilterEdges/g"\
+ -e "s/\<arcSubGraphAdaptor\>/filterEdges/g"\
+ -e "s/\<DirGraphAdaptor\>/Orienter/g"\
+ -e "s/\<dirGraphAdaptor\>/orienter/g"\
+ -e "s/\<LpCplex\>/CplexLp/g"\
+ -e "s/\<MipCplex\>/CplexMip/g"\
+ -e "s/\<LpGlpk\>/GlpkLp/g"\
+ -e "s/\<MipGlpk\>/GlpkMip/g"\
+ -e "s/\<LpSoplex\>/SoplexLp/g"\
+ <$i > $TMP
+ mv $TMP $i
+done
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/tools/lgf-gen.cc b/extern/quadriflow/3rd/lemon-1.3.1/tools/lgf-gen.cc
new file mode 100644
index 00000000000..390c8ae5972
--- /dev/null
+++ b/extern/quadriflow/3rd/lemon-1.3.1/tools/lgf-gen.cc
@@ -0,0 +1,847 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+/// \ingroup tools
+/// \file
+/// \brief Special plane graph generator.
+///
+/// Graph generator application for various types of plane graphs.
+///
+/// See
+/// \code
+/// lgf-gen --help
+/// \endcode
+/// for more information on the usage.
+
+#include <algorithm>
+#include <set>
+#include <ctime>
+#include <lemon/list_graph.h>
+#include <lemon/random.h>
+#include <lemon/dim2.h>
+#include <lemon/bfs.h>
+#include <lemon/counter.h>
+#include <lemon/suurballe.h>
+#include <lemon/graph_to_eps.h>
+#include <lemon/lgf_writer.h>
+#include <lemon/arg_parser.h>
+#include <lemon/euler.h>
+#include <lemon/math.h>
+#include <lemon/kruskal.h>
+#include <lemon/time_measure.h>
+
+using namespace lemon;
+
+typedef dim2::Point<double> Point;
+
+GRAPH_TYPEDEFS(ListGraph);
+
+bool progress=true;
+
+int N;
+// int girth;
+
+ListGraph g;
+
+std::vector<Node> nodes;
+ListGraph::NodeMap<Point> coords(g);
+
+
+double totalLen(){
+ double tlen=0;
+ for(EdgeIt e(g);e!=INVALID;++e)
+ tlen+=std::sqrt((coords[g.v(e)]-coords[g.u(e)]).normSquare());
+ return tlen;
+}
+
+int tsp_impr_num=0;
+
+const double EPSILON=1e-8;
+bool tsp_improve(Node u, Node v)
+{
+ double luv=std::sqrt((coords[v]-coords[u]).normSquare());
+ Node u2=u;
+ Node v2=v;
+ do {
+ Node n;
+ for(IncEdgeIt e(g,v2);(n=g.runningNode(e))==u2;++e) { }
+ u2=v2;
+ v2=n;
+ if(luv+std::sqrt((coords[v2]-coords[u2]).normSquare())-EPSILON>
+ std::sqrt((coords[u]-coords[u2]).normSquare())+
+ std::sqrt((coords[v]-coords[v2]).normSquare()))
+ {
+ g.erase(findEdge(g,u,v));
+ g.erase(findEdge(g,u2,v2));
+ g.addEdge(u2,u);
+ g.addEdge(v,v2);
+ tsp_impr_num++;
+ return true;
+ }
+ } while(v2!=u);
+ return false;
+}
+
+bool tsp_improve(Node u)
+{
+ for(IncEdgeIt e(g,u);e!=INVALID;++e)
+ if(tsp_improve(u,g.runningNode(e))) return true;
+ return false;
+}
+
+void tsp_improve()
+{
+ bool b;
+ do {
+ b=false;
+ for(NodeIt n(g);n!=INVALID;++n)
+ if(tsp_improve(n)) b=true;
+ } while(b);
+}
+
+void tsp()
+{
+ for(int i=0;i<N;i++) g.addEdge(nodes[i],nodes[(i+1)%N]);
+ tsp_improve();
+}
+
+class Line
+{
+public:
+ Point a;
+ Point b;
+ Line(Point _a,Point _b) :a(_a),b(_b) {}
+ Line(Node _a,Node _b) : a(coords[_a]),b(coords[_b]) {}
+ Line(const Arc &e) : a(coords[g.source(e)]),b(coords[g.target(e)]) {}
+ Line(const Edge &e) : a(coords[g.u(e)]),b(coords[g.v(e)]) {}
+};
+
+inline std::ostream& operator<<(std::ostream &os, const Line &l)
+{
+ os << l.a << "->" << l.b;
+ return os;
+}
+
+bool cross(Line a, Line b)
+{
+ Point ao=rot90(a.b-a.a);
+ Point bo=rot90(b.b-b.a);
+ return (ao*(b.a-a.a))*(ao*(b.b-a.a))<0 &&
+ (bo*(a.a-b.a))*(bo*(a.b-b.a))<0;
+}
+
+struct Parc
+{
+ Node a;
+ Node b;
+ double len;
+};
+
+bool pedgeLess(Parc a,Parc b)
+{
+ return a.len<b.len;
+}
+
+std::vector<Edge> arcs;
+
+namespace _delaunay_bits {
+
+ struct Part {
+ int prev, curr, next;
+
+ Part(int p, int c, int n) : prev(p), curr(c), next(n) {}
+ };
+
+ inline std::ostream& operator<<(std::ostream& os, const Part& part) {
+ os << '(' << part.prev << ',' << part.curr << ',' << part.next << ')';
+ return os;
+ }
+
+ inline double circle_point(const Point& p, const Point& q, const Point& r) {
+ double a = p.x * (q.y - r.y) + q.x * (r.y - p.y) + r.x * (p.y - q.y);
+ if (a == 0) return std::numeric_limits<double>::quiet_NaN();
+
+ double d = (p.x * p.x + p.y * p.y) * (q.y - r.y) +
+ (q.x * q.x + q.y * q.y) * (r.y - p.y) +
+ (r.x * r.x + r.y * r.y) * (p.y - q.y);
+
+ double e = (p.x * p.x + p.y * p.y) * (q.x - r.x) +
+ (q.x * q.x + q.y * q.y) * (r.x - p.x) +
+ (r.x * r.x + r.y * r.y) * (p.x - q.x);
+
+ double f = (p.x * p.x + p.y * p.y) * (q.x * r.y - r.x * q.y) +
+ (q.x * q.x + q.y * q.y) * (r.x * p.y - p.x * r.y) +
+ (r.x * r.x + r.y * r.y) * (p.x * q.y - q.x * p.y);
+
+ return d / (2 * a) + std::sqrt((d * d + e * e) / (4 * a * a) + f / a);
+ }
+
+ inline bool circle_form(const Point& p, const Point& q, const Point& r) {
+ return rot90(q - p) * (r - q) < 0.0;
+ }
+
+ inline double intersection(const Point& p, const Point& q, double sx) {
+ const double epsilon = 1e-8;
+
+ if (p.x == q.x) return (p.y + q.y) / 2.0;
+
+ if (sx < p.x + epsilon) return p.y;
+ if (sx < q.x + epsilon) return q.y;
+
+ double a = q.x - p.x;
+ double b = (q.x - sx) * p.y - (p.x - sx) * q.y;
+ double d = (q.x - sx) * (p.x - sx) * (p - q).normSquare();
+ return (b - std::sqrt(d)) / a;
+ }
+
+ struct YLess {
+
+
+ YLess(const std::vector<Point>& points, double& sweep)
+ : _points(points), _sweep(sweep) {}
+
+ bool operator()(const Part& l, const Part& r) const {
+ const double epsilon = 1e-8;
+
+ // std::cerr << l << " vs " << r << std::endl;
+ double lbx = l.prev != -1 ?
+ intersection(_points[l.prev], _points[l.curr], _sweep) :
+ - std::numeric_limits<double>::infinity();
+ double rbx = r.prev != -1 ?
+ intersection(_points[r.prev], _points[r.curr], _sweep) :
+ - std::numeric_limits<double>::infinity();
+ double lex = l.next != -1 ?
+ intersection(_points[l.curr], _points[l.next], _sweep) :
+ std::numeric_limits<double>::infinity();
+ double rex = r.next != -1 ?
+ intersection(_points[r.curr], _points[r.next], _sweep) :
+ std::numeric_limits<double>::infinity();
+
+ if (lbx > lex) std::swap(lbx, lex);
+ if (rbx > rex) std::swap(rbx, rex);
+
+ if (lex < epsilon + rex && lbx + epsilon < rex) return true;
+ if (rex < epsilon + lex && rbx + epsilon < lex) return false;
+ return lex < rex;
+ }
+
+ const std::vector<Point>& _points;
+ double& _sweep;
+ };
+
+ struct BeachIt;
+
+ typedef std::multimap<double, BeachIt*> SpikeHeap;
+
+ typedef std::multimap<Part, SpikeHeap::iterator, YLess> Beach;
+
+ struct BeachIt {
+ Beach::iterator it;
+
+ BeachIt(Beach::iterator iter) : it(iter) {}
+ };
+
+}
+
+inline void delaunay() {
+ Counter cnt("Number of arcs added: ");
+
+ using namespace _delaunay_bits;
+
+ typedef _delaunay_bits::Part Part;
+ typedef std::vector<std::pair<double, int> > SiteHeap;
+
+
+ std::vector<Point> points;
+ std::vector<Node> nodes;
+
+ for (NodeIt it(g); it != INVALID; ++it) {
+ nodes.push_back(it);
+ points.push_back(coords[it]);
+ }
+
+ SiteHeap siteheap(points.size());
+
+ double sweep;
+
+
+ for (int i = 0; i < int(siteheap.size()); ++i) {
+ siteheap[i] = std::make_pair(points[i].x, i);
+ }
+
+ std::sort(siteheap.begin(), siteheap.end());
+ sweep = siteheap.front().first;
+
+ YLess yless(points, sweep);
+ Beach beach(yless);
+
+ SpikeHeap spikeheap;
+
+ std::set<std::pair<int, int> > arcs;
+
+ int siteindex = 0;
+ {
+ SiteHeap front;
+
+ while (siteindex < int(siteheap.size()) &&
+ siteheap[0].first == siteheap[siteindex].first) {
+ front.push_back(std::make_pair(points[siteheap[siteindex].second].y,
+ siteheap[siteindex].second));
+ ++siteindex;
+ }
+
+ std::sort(front.begin(), front.end());
+
+ for (int i = 0; i < int(front.size()); ++i) {
+ int prev = (i == 0 ? -1 : front[i - 1].second);
+ int curr = front[i].second;
+ int next = (i + 1 == int(front.size()) ? -1 : front[i + 1].second);
+
+ beach.insert(std::make_pair(Part(prev, curr, next),
+ spikeheap.end()));
+ }
+ }
+
+ while (siteindex < int(points.size()) || !spikeheap.empty()) {
+
+ SpikeHeap::iterator spit = spikeheap.begin();
+
+ if (siteindex < int(points.size()) &&
+ (spit == spikeheap.end() || siteheap[siteindex].first < spit->first)) {
+ int site = siteheap[siteindex].second;
+ sweep = siteheap[siteindex].first;
+
+ Beach::iterator bit = beach.upper_bound(Part(site, site, site));
+
+ if (bit->second != spikeheap.end()) {
+ delete bit->second->second;
+ spikeheap.erase(bit->second);
+ }
+
+ int prev = bit->first.prev;
+ int curr = bit->first.curr;
+ int next = bit->first.next;
+
+ beach.erase(bit);
+
+ SpikeHeap::iterator pit = spikeheap.end();
+ if (prev != -1 &&
+ circle_form(points[prev], points[curr], points[site])) {
+ double x = circle_point(points[prev], points[curr], points[site]);
+ pit = spikeheap.insert(std::make_pair(x, new BeachIt(beach.end())));
+ pit->second->it =
+ beach.insert(std::make_pair(Part(prev, curr, site), pit));
+ } else {
+ beach.insert(std::make_pair(Part(prev, curr, site), pit));
+ }
+
+ beach.insert(std::make_pair(Part(curr, site, curr), spikeheap.end()));
+
+ SpikeHeap::iterator nit = spikeheap.end();
+ if (next != -1 &&
+ circle_form(points[site], points[curr],points[next])) {
+ double x = circle_point(points[site], points[curr], points[next]);
+ nit = spikeheap.insert(std::make_pair(x, new BeachIt(beach.end())));
+ nit->second->it =
+ beach.insert(std::make_pair(Part(site, curr, next), nit));
+ } else {
+ beach.insert(std::make_pair(Part(site, curr, next), nit));
+ }
+
+ ++siteindex;
+ } else {
+ sweep = spit->first;
+
+ Beach::iterator bit = spit->second->it;
+
+ int prev = bit->first.prev;
+ int curr = bit->first.curr;
+ int next = bit->first.next;
+
+ {
+ std::pair<int, int> arc;
+
+ arc = prev < curr ?
+ std::make_pair(prev, curr) : std::make_pair(curr, prev);
+
+ if (arcs.find(arc) == arcs.end()) {
+ arcs.insert(arc);
+ g.addEdge(nodes[prev], nodes[curr]);
+ ++cnt;
+ }
+
+ arc = curr < next ?
+ std::make_pair(curr, next) : std::make_pair(next, curr);
+
+ if (arcs.find(arc) == arcs.end()) {
+ arcs.insert(arc);
+ g.addEdge(nodes[curr], nodes[next]);
+ ++cnt;
+ }
+ }
+
+ Beach::iterator pbit = bit; --pbit;
+ int ppv = pbit->first.prev;
+ Beach::iterator nbit = bit; ++nbit;
+ int nnt = nbit->first.next;
+
+ if (bit->second != spikeheap.end())
+ {
+ delete bit->second->second;
+ spikeheap.erase(bit->second);
+ }
+ if (pbit->second != spikeheap.end())
+ {
+ delete pbit->second->second;
+ spikeheap.erase(pbit->second);
+ }
+ if (nbit->second != spikeheap.end())
+ {
+ delete nbit->second->second;
+ spikeheap.erase(nbit->second);
+ }
+
+ beach.erase(nbit);
+ beach.erase(bit);
+ beach.erase(pbit);
+
+ SpikeHeap::iterator pit = spikeheap.end();
+ if (ppv != -1 && ppv != next &&
+ circle_form(points[ppv], points[prev], points[next])) {
+ double x = circle_point(points[ppv], points[prev], points[next]);
+ if (x < sweep) x = sweep;
+ pit = spikeheap.insert(std::make_pair(x, new BeachIt(beach.end())));
+ pit->second->it =
+ beach.insert(std::make_pair(Part(ppv, prev, next), pit));
+ } else {
+ beach.insert(std::make_pair(Part(ppv, prev, next), pit));
+ }
+
+ SpikeHeap::iterator nit = spikeheap.end();
+ if (nnt != -1 && prev != nnt &&
+ circle_form(points[prev], points[next], points[nnt])) {
+ double x = circle_point(points[prev], points[next], points[nnt]);
+ if (x < sweep) x = sweep;
+ nit = spikeheap.insert(std::make_pair(x, new BeachIt(beach.end())));
+ nit->second->it =
+ beach.insert(std::make_pair(Part(prev, next, nnt), nit));
+ } else {
+ beach.insert(std::make_pair(Part(prev, next, nnt), nit));
+ }
+
+ }
+ }
+
+ for (Beach::iterator it = beach.begin(); it != beach.end(); ++it) {
+ int curr = it->first.curr;
+ int next = it->first.next;
+
+ if (next == -1) continue;
+
+ std::pair<int, int> arc;
+
+ arc = curr < next ?
+ std::make_pair(curr, next) : std::make_pair(next, curr);
+
+ if (arcs.find(arc) == arcs.end()) {
+ arcs.insert(arc);
+ g.addEdge(nodes[curr], nodes[next]);
+ ++cnt;
+ }
+ }
+}
+
+void sparse(int d)
+{
+ Counter cnt("Number of arcs removed: ");
+ Bfs<ListGraph> bfs(g);
+ for(std::vector<Edge>::reverse_iterator ei=arcs.rbegin();
+ ei!=arcs.rend();++ei)
+ {
+ Node a=g.u(*ei);
+ Node b=g.v(*ei);
+ g.erase(*ei);
+ bfs.run(a,b);
+ if(bfs.predArc(b)==INVALID || bfs.dist(b)>d)
+ g.addEdge(a,b);
+ else cnt++;
+ }
+}
+
+void sparse2(int d)
+{
+ Counter cnt("Number of arcs removed: ");
+ for(std::vector<Edge>::reverse_iterator ei=arcs.rbegin();
+ ei!=arcs.rend();++ei)
+ {
+ Node a=g.u(*ei);
+ Node b=g.v(*ei);
+ g.erase(*ei);
+ ConstMap<Arc,int> cegy(1);
+ Suurballe<ListGraph,ConstMap<Arc,int> > sur(g,cegy);
+ int k=sur.run(a,b,2);
+ if(k<2 || sur.totalLength()>d)
+ g.addEdge(a,b);
+ else cnt++;
+// else std::cout << "Remove arc " << g.id(a) << "-" << g.id(b) << '\n';
+ }
+}
+
+void sparseTriangle(int d)
+{
+ Counter cnt("Number of arcs added: ");
+ std::vector<Parc> pedges;
+ for(NodeIt n(g);n!=INVALID;++n)
+ for(NodeIt m=++(NodeIt(n));m!=INVALID;++m)
+ {
+ Parc p;
+ p.a=n;
+ p.b=m;
+ p.len=(coords[m]-coords[n]).normSquare();
+ pedges.push_back(p);
+ }
+ std::sort(pedges.begin(),pedges.end(),pedgeLess);
+ for(std::vector<Parc>::iterator pi=pedges.begin();pi!=pedges.end();++pi)
+ {
+ Line li(pi->a,pi->b);
+ EdgeIt e(g);
+ for(;e!=INVALID && !cross(e,li);++e) ;
+ Edge ne;
+ if(e==INVALID) {
+ ConstMap<Arc,int> cegy(1);
+ Suurballe<ListGraph,ConstMap<Arc,int> > sur(g,cegy);
+ int k=sur.run(pi->a,pi->b,2);
+ if(k<2 || sur.totalLength()>d)
+ {
+ ne=g.addEdge(pi->a,pi->b);
+ arcs.push_back(ne);
+ cnt++;
+ }
+ }
+ }
+}
+
+template <typename Graph, typename CoordMap>
+class LengthSquareMap {
+public:
+ typedef typename Graph::Edge Key;
+ typedef typename CoordMap::Value::Value Value;
+
+ LengthSquareMap(const Graph& graph, const CoordMap& coords)
+ : _graph(graph), _coords(coords) {}
+
+ Value operator[](const Key& key) const {
+ return (_coords[_graph.v(key)] -
+ _coords[_graph.u(key)]).normSquare();
+ }
+
+private:
+
+ const Graph& _graph;
+ const CoordMap& _coords;
+};
+
+void minTree() {
+ std::vector<Parc> pedges;
+ Timer T;
+ std::cout << T.realTime() << "s: Creating delaunay triangulation...\n";
+ delaunay();
+ std::cout << T.realTime() << "s: Calculating spanning tree...\n";
+ LengthSquareMap<ListGraph, ListGraph::NodeMap<Point> > ls(g, coords);
+ ListGraph::EdgeMap<bool> tree(g);
+ kruskal(g, ls, tree);
+ std::cout << T.realTime() << "s: Removing non tree arcs...\n";
+ std::vector<Edge> remove;
+ for (EdgeIt e(g); e != INVALID; ++e) {
+ if (!tree[e]) remove.push_back(e);
+ }
+ for(int i = 0; i < int(remove.size()); ++i) {
+ g.erase(remove[i]);
+ }
+ std::cout << T.realTime() << "s: Done\n";
+}
+
+void tsp2()
+{
+ std::cout << "Find a tree..." << std::endl;
+
+ minTree();
+
+ std::cout << "Total arc length (tree) : " << totalLen() << std::endl;
+
+ std::cout << "Make it Euler..." << std::endl;
+
+ {
+ std::vector<Node> leafs;
+ for(NodeIt n(g);n!=INVALID;++n)
+ if(countIncEdges(g,n)%2==1) leafs.push_back(n);
+
+// for(unsigned int i=0;i<leafs.size();i+=2)
+// g.addArc(leafs[i],leafs[i+1]);
+
+ std::vector<Parc> pedges;
+ for(unsigned int i=0;i<leafs.size()-1;i++)
+ for(unsigned int j=i+1;j<leafs.size();j++)
+ {
+ Node n=leafs[i];
+ Node m=leafs[j];
+ Parc p;
+ p.a=n;
+ p.b=m;
+ p.len=(coords[m]-coords[n]).normSquare();
+ pedges.push_back(p);
+ }
+ std::sort(pedges.begin(),pedges.end(),pedgeLess);
+ for(unsigned int i=0;i<pedges.size();i++)
+ if(countIncEdges(g,pedges[i].a)%2 &&
+ countIncEdges(g,pedges[i].b)%2)
+ g.addEdge(pedges[i].a,pedges[i].b);
+ }
+
+ for(NodeIt n(g);n!=INVALID;++n)
+ if(countIncEdges(g,n)%2 || countIncEdges(g,n)==0 )
+ std::cout << "GEBASZ!!!" << std::endl;
+
+ for(EdgeIt e(g);e!=INVALID;++e)
+ if(g.u(e)==g.v(e))
+ std::cout << "LOOP GEBASZ!!!" << std::endl;
+
+ std::cout << "Number of arcs : " << countEdges(g) << std::endl;
+
+ std::cout << "Total arc length (euler) : " << totalLen() << std::endl;
+
+ ListGraph::EdgeMap<Arc> enext(g);
+ {
+ EulerIt<ListGraph> e(g);
+ Arc eo=e;
+ Arc ef=e;
+// std::cout << "Tour arc: " << g.id(Edge(e)) << std::endl;
+ for(++e;e!=INVALID;++e)
+ {
+// std::cout << "Tour arc: " << g.id(Edge(e)) << std::endl;
+ enext[eo]=e;
+ eo=e;
+ }
+ enext[eo]=ef;
+ }
+
+ std::cout << "Creating a tour from that..." << std::endl;
+
+ int nnum = countNodes(g);
+ int ednum = countEdges(g);
+
+ for(Arc p=enext[EdgeIt(g)];ednum>nnum;p=enext[p])
+ {
+// std::cout << "Checking arc " << g.id(p) << std::endl;
+ Arc e=enext[p];
+ Arc f=enext[e];
+ Node n2=g.source(f);
+ Node n1=g.oppositeNode(n2,e);
+ Node n3=g.oppositeNode(n2,f);
+ if(countIncEdges(g,n2)>2)
+ {
+// std::cout << "Remove an Arc" << std::endl;
+ Arc ff=enext[f];
+ g.erase(e);
+ g.erase(f);
+ if(n1!=n3)
+ {
+ Arc ne=g.direct(g.addEdge(n1,n3),n1);
+ enext[p]=ne;
+ enext[ne]=ff;
+ ednum--;
+ }
+ else {
+ enext[p]=ff;
+ ednum-=2;
+ }
+ }
+ }
+
+ std::cout << "Total arc length (tour) : " << totalLen() << std::endl;
+
+ std::cout << "2-opt the tour..." << std::endl;
+
+ tsp_improve();
+
+ std::cout << "Total arc length (2-opt tour) : " << totalLen() << std::endl;
+}
+
+
+int main(int argc,const char **argv)
+{
+ ArgParser ap(argc,argv);
+
+// bool eps;
+ bool disc_d, square_d, gauss_d;
+// bool tsp_a,two_a,tree_a;
+ int num_of_cities=1;
+ double area=1;
+ N=100;
+// girth=10;
+ std::string ndist("disc");
+ ap.refOption("n", "Number of nodes (default is 100)", N)
+ .intOption("g", "Girth parameter (default is 10)", 10)
+ .refOption("cities", "Number of cities (default is 1)", num_of_cities)
+ .refOption("area", "Full relative area of the cities (default is 1)", area)
+ .refOption("disc", "Nodes are evenly distributed on a unit disc (default)",
+ disc_d)
+ .optionGroup("dist", "disc")
+ .refOption("square", "Nodes are evenly distributed on a unit square",
+ square_d)
+ .optionGroup("dist", "square")
+ .refOption("gauss", "Nodes are located according to a two-dim Gauss "
+ "distribution", gauss_d)
+ .optionGroup("dist", "gauss")
+ .onlyOneGroup("dist")
+ .boolOption("eps", "Also generate .eps output (<prefix>.eps)")
+ .boolOption("nonodes", "Draw only the edges in the generated .eps output")
+ .boolOption("dir", "Directed graph is generated (each edge is replaced by "
+ "two directed arcs)")
+ .boolOption("2con", "Create a two connected planar graph")
+ .optionGroup("alg","2con")
+ .boolOption("tree", "Create a min. cost spanning tree")
+ .optionGroup("alg","tree")
+ .boolOption("tsp", "Create a TSP tour")
+ .optionGroup("alg","tsp")
+ .boolOption("tsp2", "Create a TSP tour (tree based)")
+ .optionGroup("alg","tsp2")
+ .boolOption("dela", "Delaunay triangulation graph")
+ .optionGroup("alg","dela")
+ .onlyOneGroup("alg")
+ .boolOption("rand", "Use time seed for random number generator")
+ .optionGroup("rand", "rand")
+ .intOption("seed", "Random seed", -1)
+ .optionGroup("rand", "seed")
+ .onlyOneGroup("rand")
+ .other("[prefix]","Prefix of the output files. Default is 'lgf-gen-out'")
+ .run();
+
+ if (ap["rand"]) {
+ int seed = int(time(0));
+ std::cout << "Random number seed: " << seed << std::endl;
+ rnd = Random(seed);
+ }
+ if (ap.given("seed")) {
+ int seed = ap["seed"];
+ std::cout << "Random number seed: " << seed << std::endl;
+ rnd = Random(seed);
+ }
+
+ std::string prefix;
+ switch(ap.files().size())
+ {
+ case 0:
+ prefix="lgf-gen-out";
+ break;
+ case 1:
+ prefix=ap.files()[0];
+ break;
+ default:
+ std::cerr << "\nAt most one prefix can be given\n\n";
+ exit(1);
+ }
+
+ double sum_sizes=0;
+ std::vector<double> sizes;
+ std::vector<double> cum_sizes;
+ for(int s=0;s<num_of_cities;s++)
+ {
+ // sum_sizes+=rnd.exponential();
+ double d=rnd();
+ sum_sizes+=d;
+ sizes.push_back(d);
+ cum_sizes.push_back(sum_sizes);
+ }
+ int i=0;
+ for(int s=0;s<num_of_cities;s++)
+ {
+ Point center=(num_of_cities==1?Point(0,0):rnd.disc());
+ if(gauss_d)
+ for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
+ Node n=g.addNode();
+ nodes.push_back(n);
+ coords[n]=center+rnd.gauss2()*area*
+ std::sqrt(sizes[s]/sum_sizes);
+ }
+ else if(square_d)
+ for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
+ Node n=g.addNode();
+ nodes.push_back(n);
+ coords[n]=center+Point(rnd()*2-1,rnd()*2-1)*area*
+ std::sqrt(sizes[s]/sum_sizes);
+ }
+ else if(disc_d || true)
+ for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
+ Node n=g.addNode();
+ nodes.push_back(n);
+ coords[n]=center+rnd.disc()*area*
+ std::sqrt(sizes[s]/sum_sizes);
+ }
+ }
+
+// for (ListGraph::NodeIt n(g); n != INVALID; ++n) {
+// std::cerr << coords[n] << std::endl;
+// }
+
+ if(ap["tsp"]) {
+ tsp();
+ std::cout << "#2-opt improvements: " << tsp_impr_num << std::endl;
+ }
+ if(ap["tsp2"]) {
+ tsp2();
+ std::cout << "#2-opt improvements: " << tsp_impr_num << std::endl;
+ }
+ else if(ap["2con"]) {
+ std::cout << "Make triangles\n";
+ // triangle();
+ sparseTriangle(ap["g"]);
+ std::cout << "Make it sparser\n";
+ sparse2(ap["g"]);
+ }
+ else if(ap["tree"]) {
+ minTree();
+ }
+ else if(ap["dela"]) {
+ delaunay();
+ }
+
+
+ std::cout << "Number of nodes : " << countNodes(g) << std::endl;
+ std::cout << "Number of arcs : " << countEdges(g) << std::endl;
+ double tlen=0;
+ for(EdgeIt e(g);e!=INVALID;++e)
+ tlen+=std::sqrt((coords[g.v(e)]-coords[g.u(e)]).normSquare());
+ std::cout << "Total arc length : " << tlen << std::endl;
+
+ if(ap["eps"])
+ graphToEps(g,prefix+".eps").scaleToA4().
+ scale(600).nodeScale(.005).arcWidthScale(.001).preScale(false).
+ coords(coords).hideNodes(ap.given("nonodes")).run();
+
+ if(ap["dir"])
+ DigraphWriter<ListGraph>(g,prefix+".lgf").
+ nodeMap("coordinates_x",scaleMap(xMap(coords),600)).
+ nodeMap("coordinates_y",scaleMap(yMap(coords),600)).
+ run();
+ else GraphWriter<ListGraph>(g,prefix+".lgf").
+ nodeMap("coordinates_x",scaleMap(xMap(coords),600)).
+ nodeMap("coordinates_y",scaleMap(yMap(coords),600)).
+ run();
+}
+
diff --git a/extern/quadriflow/3rd/pcg32/pcg32/pcg32.h b/extern/quadriflow/3rd/pcg32/pcg32/pcg32.h
new file mode 100644
index 00000000000..aa06f28a845
--- /dev/null
+++ b/extern/quadriflow/3rd/pcg32/pcg32/pcg32.h
@@ -0,0 +1,209 @@
+/*
+ * Tiny self-contained version of the PCG Random Number Generation for C++
+ * put together from pieces of the much larger C/C++ codebase.
+ * Wenzel Jakob, February 2015
+ *
+ * The PCG random number generator was developed by Melissa O'Neill <oneill@pcg-random.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For additional information about the PCG random number generation scheme,
+ * including its license and other licensing options, visit
+ *
+ * http://www.pcg-random.org
+ */
+
+#ifndef __PCG32_H
+#define __PCG32_H 1
+
+#define PCG32_DEFAULT_STATE 0x853c49e6748fea9bULL
+#define PCG32_DEFAULT_STREAM 0xda3e39cb94b95bdbULL
+#define PCG32_MULT 0x5851f42d4c957f2dULL
+
+#include <inttypes.h>
+#include <cmath>
+#include <cassert>
+#include <algorithm>
+
+/// PCG32 Pseudorandom number generator
+struct pcg32 {
+ /// Initialize the pseudorandom number generator with default seed
+ pcg32() : state(PCG32_DEFAULT_STATE), inc(PCG32_DEFAULT_STREAM) {}
+
+ /// Initialize the pseudorandom number generator with the \ref seed() function
+ pcg32(uint64_t initstate, uint64_t initseq = 1u) { seed(initstate, initseq); }
+
+ /**
+ * \brief Seed the pseudorandom number generator
+ *
+ * Specified in two parts: a state initializer and a sequence selection
+ * constant (a.k.a. stream id)
+ */
+ void seed(uint64_t initstate, uint64_t initseq = 1) {
+ state = 0U;
+ inc = (initseq << 1u) | 1u;
+ nextUInt();
+ state += initstate;
+ nextUInt();
+ }
+
+ /// Generate a uniformly distributed unsigned 32-bit random number
+ uint32_t nextUInt() {
+ uint64_t oldstate = state;
+ state = oldstate * PCG32_MULT + inc;
+ uint32_t xorshifted = (uint32_t) (((oldstate >> 18u) ^ oldstate) >> 27u);
+ uint32_t rot = (uint32_t) (oldstate >> 59u);
+ return (xorshifted >> rot) | (xorshifted << ((~rot + 1u) & 31));
+ }
+
+ /// Generate a uniformly distributed number, r, where 0 <= r < bound
+ uint32_t nextUInt(uint32_t bound) {
+ // To avoid bias, we need to make the range of the RNG a multiple of
+ // bound, which we do by dropping output less than a threshold.
+ // A naive scheme to calculate the threshold would be to do
+ //
+ // uint32_t threshold = 0x100000000ull % bound;
+ //
+ // but 64-bit div/mod is slower than 32-bit div/mod (especially on
+ // 32-bit platforms). In essence, we do
+ //
+ // uint32_t threshold = (0x100000000ull-bound) % bound;
+ //
+ // because this version will calculate the same modulus, but the LHS
+ // value is less than 2^32.
+
+ uint32_t threshold = (~bound+1u) % bound;
+
+ // Uniformity guarantees that this loop will terminate. In practice, it
+ // should usually terminate quickly; on average (assuming all bounds are
+ // equally likely), 82.25% of the time, we can expect it to require just
+ // one iteration. In the worst case, someone passes a bound of 2^31 + 1
+ // (i.e., 2147483649), which invalidates almost 50% of the range. In
+ // practice, bounds are typically small and only a tiny amount of the range
+ // is eliminated.
+ for (;;) {
+ uint32_t r = nextUInt();
+ if (r >= threshold)
+ return r % bound;
+ }
+ }
+
+ /// Generate a single precision floating point value on the interval [0, 1)
+ float nextFloat() {
+ /* Trick from MTGP: generate an uniformly distributed
+ single precision number in [1,2) and subtract 1. */
+ union {
+ uint32_t u;
+ float f;
+ } x;
+ x.u = (nextUInt() >> 9) | 0x3f800000UL;
+ return x.f - 1.0f;
+ }
+
+ /**
+ * \brief Generate a double precision floating point value on the interval [0, 1)
+ *
+ * \remark Since the underlying random number generator produces 32 bit output,
+ * only the first 32 mantissa bits will be filled (however, the resolution is still
+ * finer than in \ref nextFloat(), which only uses 23 mantissa bits)
+ */
+ double nextDouble() {
+ /* Trick from MTGP: generate an uniformly distributed
+ double precision number in [1,2) and subtract 1. */
+ union {
+ uint64_t u;
+ double d;
+ } x;
+ x.u = ((uint64_t) nextUInt() << 20) | 0x3ff0000000000000ULL;
+ return x.d - 1.0;
+ }
+
+ /**
+ * \brief Multi-step advance function (jump-ahead, jump-back)
+ *
+ * The method used here is based on Brown, "Random Number Generation
+ * with Arbitrary Stride", Transactions of the American Nuclear
+ * Society (Nov. 1994). The algorithm is very similar to fast
+ * exponentiation.
+ */
+ void advance(int64_t delta_) {
+ uint64_t
+ cur_mult = PCG32_MULT,
+ cur_plus = inc,
+ acc_mult = 1u,
+ acc_plus = 0u;
+
+ /* Even though delta is an unsigned integer, we can pass a signed
+ integer to go backwards, it just goes "the long way round". */
+ uint64_t delta = (uint64_t) delta_;
+
+ while (delta > 0) {
+ if (delta & 1) {
+ acc_mult *= cur_mult;
+ acc_plus = acc_plus * cur_mult + cur_plus;
+ }
+ cur_plus = (cur_mult + 1) * cur_plus;
+ cur_mult *= cur_mult;
+ delta /= 2;
+ }
+ state = acc_mult * state + acc_plus;
+ }
+
+ /**
+ * \brief Draw uniformly distributed permutation and permute the
+ * given STL container
+ *
+ * From: Knuth, TAoCP Vol. 2 (3rd 3d), Section 3.4.2
+ */
+ template <typename Iterator> void shuffle(Iterator begin, Iterator end) {
+ if (begin <= end) return;
+ for (Iterator it = end - 1; it > begin; --it)
+ std::iter_swap(it, begin + nextUInt((uint32_t) (it - begin + 1)));
+ }
+
+ /// Compute the distance between two PCG32 pseudorandom number generators
+ int64_t operator-(const pcg32 &other) const {
+ assert(inc == other.inc);
+
+ uint64_t
+ cur_mult = PCG32_MULT,
+ cur_plus = inc,
+ cur_state = other.state,
+ the_bit = 1u,
+ distance = 0u;
+
+ while (state != cur_state) {
+ if ((state & the_bit) != (cur_state & the_bit)) {
+ cur_state = cur_state * cur_mult + cur_plus;
+ distance |= the_bit;
+ }
+ assert((state & the_bit) == (cur_state & the_bit));
+ the_bit <<= 1;
+ cur_plus = (cur_mult + 1ULL) * cur_plus;
+ cur_mult *= cur_mult;
+ }
+
+ return (int64_t) distance;
+ }
+
+ /// Equality operator
+ bool operator==(const pcg32 &other) const { return state == other.state && inc == other.inc; }
+
+ /// Inequality operator
+ bool operator!=(const pcg32 &other) const { return state != other.state || inc != other.inc; }
+
+ uint64_t state; // RNG state. All values are possible.
+ uint64_t inc; // Controls which RNG sequence (stream) is selected. Must *always* be odd.
+};
+
+#endif // __PCG32_H
diff --git a/extern/quadriflow/3rd/pss/pss/parallel_stable_sort.h b/extern/quadriflow/3rd/pss/pss/parallel_stable_sort.h
new file mode 100644
index 00000000000..3d8854f92ca
--- /dev/null
+++ b/extern/quadriflow/3rd/pss/pss/parallel_stable_sort.h
@@ -0,0 +1,140 @@
+/*
+ Copyright (C) 2014 Intel Corporation
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <iterator>
+#include <algorithm>
+#include <tbb/task.h>
+
+#include "pss_common.h"
+
+namespace pss {
+
+namespace internal {
+
+template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename RandomAccessIterator3, typename Compare>
+class merge_task: public tbb::task {
+ tbb::task* execute();
+ RandomAccessIterator1 xs, xe;
+ RandomAccessIterator2 ys, ye;
+ RandomAccessIterator3 zs;
+ Compare comp;
+ bool destroy;
+public:
+ merge_task( RandomAccessIterator1 xs_, RandomAccessIterator1 xe_, RandomAccessIterator2 ys_, RandomAccessIterator2 ye_, RandomAccessIterator3 zs_, bool destroy_, Compare comp_ ) :
+ xs(xs_), xe(xe_), ys(ys_), ye(ye_), zs(zs_), comp(comp_), destroy(destroy_)
+ {}
+};
+
+template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename RandomAccessIterator3, typename Compare>
+tbb::task* merge_task<RandomAccessIterator1,RandomAccessIterator2,RandomAccessIterator3,Compare>::execute() {
+ const size_t MERGE_CUT_OFF = 2000;
+ auto n = (xe-xs) + (ye-ys);
+ if( (size_t) n <= MERGE_CUT_OFF ) {
+ serial_move_merge( xs, xe, ys, ye, zs, comp );
+ if( destroy ) {
+ serial_destroy(xs,xe);
+ serial_destroy(ys,ye);
+ }
+ return NULL;
+ } else {
+ RandomAccessIterator1 xm;
+ RandomAccessIterator2 ym;
+ if( xe-xs < ye-ys ) {
+ ym = ys+(ye-ys)/2;
+ xm = std::upper_bound(xs,xe,*ym,comp);
+ } else {
+ xm = xs+(xe-xs)/2;
+ ym = std::lower_bound(ys,ye,*xm,comp);
+ }
+ RandomAccessIterator3 zm = zs + ((xm-xs) + (ym-ys));
+ tbb::task* right = new( allocate_additional_child_of(*parent()) ) merge_task( xm, xe, ym, ye, zm, destroy, comp );
+ spawn(*right);
+ recycle_as_continuation();
+ xe = xm;
+ ye = ym;
+ return this;
+ }
+}
+
+template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename Compare>
+class stable_sort_task: public tbb::task {
+ tbb::task* execute();
+ RandomAccessIterator1 xs, xe;
+ RandomAccessIterator2 zs;
+ Compare comp;
+ signed char inplace;
+public:
+ stable_sort_task(RandomAccessIterator1 xs_, RandomAccessIterator1 xe_, RandomAccessIterator2 zs_, int inplace_, Compare comp_ ) :
+ xs(xs_), xe(xe_), zs(zs_), comp(comp_), inplace(inplace_)
+ {}
+};
+
+template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename Compare>
+tbb::task* stable_sort_task<RandomAccessIterator1, RandomAccessIterator2, Compare>::execute() {
+ const size_t SORT_CUT_OFF = 500;
+ if ((size_t) (xe - xs) <= SORT_CUT_OFF) {
+ stable_sort_base_case(xs, xe, zs, inplace, comp);
+ return NULL;
+ } else {
+ RandomAccessIterator1 xm = xs + (xe - xs) / 2;
+ RandomAccessIterator2 zm = zs + (xm - xs);
+ RandomAccessIterator2 ze = zs + (xe - xs);
+ task* m;
+ if (inplace)
+ m = new (allocate_continuation()) merge_task<RandomAccessIterator2,RandomAccessIterator2,RandomAccessIterator1,Compare>(zs, zm, zm, ze, xs, inplace==2, comp);
+ else
+ m = new (allocate_continuation()) merge_task<RandomAccessIterator1,RandomAccessIterator1,RandomAccessIterator2,Compare>(xs, xm, xm, xe, zs, false, comp);
+ m->set_ref_count(2);
+ task* right = new(m->allocate_child()) stable_sort_task(xm,xe,zm,!inplace, comp);
+ spawn(*right);
+ recycle_as_child_of(*m);
+ xe=xm;
+ inplace=!inplace;
+ return this;
+ }
+}
+
+} // namespace internal
+
+template<typename RandomAccessIterator, typename Compare>
+void parallel_stable_sort( RandomAccessIterator xs, RandomAccessIterator xe, Compare comp ) {
+ typedef typename std::iterator_traits<RandomAccessIterator>::value_type T;
+ if( internal::raw_buffer z = internal::raw_buffer( sizeof(T)*(xe-xs) ) ) {
+ using tbb::task;
+ typedef typename std::iterator_traits<RandomAccessIterator>::value_type T;
+ internal::raw_buffer buf( sizeof(T)*(xe-xs) );
+ task::spawn_root_and_wait(*new( task::allocate_root() ) internal::stable_sort_task<RandomAccessIterator,T*,Compare>( xs, xe, (T*)buf.get(), 2, comp ));
+ } else
+ // Not enough memory available - fall back on serial sort
+ std::stable_sort( xs, xe, comp );
+}
+
+} // namespace pss
diff --git a/extern/quadriflow/3rd/pss/pss/pss_common.h b/extern/quadriflow/3rd/pss/pss/pss_common.h
new file mode 100644
index 00000000000..628c0f9830a
--- /dev/null
+++ b/extern/quadriflow/3rd/pss/pss/pss_common.h
@@ -0,0 +1,106 @@
+/*
+ Copyright (C) 2014 Intel Corporation
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <utility>
+#include <iterator>
+
+namespace pss {
+
+namespace internal {
+
+//! Destroy sequence [xs,xe)
+template<class RandomAccessIterator>
+void serial_destroy( RandomAccessIterator zs, RandomAccessIterator ze ) {
+ typedef typename std::iterator_traits<RandomAccessIterator>::value_type T;
+ while( zs!=ze ) {
+ --ze;
+ (*ze).~T();
+ }
+}
+
+//! Merge sequences [xs,xe) and [ys,ye) to output sequence [zs,(xe-xs)+(ye-ys)), using std::move
+template<class RandomAccessIterator1, class RandomAccessIterator2, class RandomAccessIterator3, class Compare>
+void serial_move_merge( RandomAccessIterator1 xs, RandomAccessIterator1 xe, RandomAccessIterator2 ys, RandomAccessIterator2 ye, RandomAccessIterator3 zs, Compare comp ) {
+ if( xs!=xe ) {
+ if( ys!=ye ) {
+ for(;;) {
+ if( comp(*ys,*xs) ) {
+ *zs = std::move(*ys);
+ ++zs;
+ if( ++ys==ye ) { break; }
+ } else {
+ *zs = std::move(*xs);
+ ++zs;
+ if( ++xs==xe ) { goto movey; }
+ }
+ }
+ }
+ ys = xs;
+ ye = xe;
+ }
+movey:
+ std::move( ys, ye, zs );
+}
+
+template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename Compare>
+void stable_sort_base_case( RandomAccessIterator1 xs, RandomAccessIterator1 xe, RandomAccessIterator2 zs, int inplace, Compare comp) {
+ std::stable_sort( xs, xe, comp );
+ if( inplace!=2 ) {
+ RandomAccessIterator2 ze = zs + (xe-xs);
+ typedef typename std::iterator_traits<RandomAccessIterator2>::value_type T;
+ if( inplace )
+ // Initialize the temporary buffer
+ for( ; zs<ze; ++zs )
+ new(&*zs) T;
+ else
+ // Initialize the temporary buffer and move keys to it.
+ for( ; zs<ze; ++xs, ++zs )
+ new(&*zs) T(std::move(*xs));
+ }
+}
+
+//! Raw memory buffer with automatic cleanup.
+class raw_buffer {
+ void* ptr;
+public:
+ //! Try to obtain buffer of given size.
+ raw_buffer( size_t bytes ) : ptr( operator new(bytes,std::nothrow) ) {}
+ //! True if buffer was successfully obtained, zero otherwise.
+ operator bool() const {return ptr;}
+ //! Return pointer to buffer, or NULL if buffer could not be obtained.
+ void* get() const {return ptr;}
+ //! Destroy buffer
+ ~raw_buffer() {operator delete(ptr);}
+};
+
+} // namespace internal
+
+} // namespace pss
diff --git a/extern/quadriflow/CMakeLists.txt b/extern/quadriflow/CMakeLists.txt
new file mode 100644
index 00000000000..488d95a48b9
--- /dev/null
+++ b/extern/quadriflow/CMakeLists.txt
@@ -0,0 +1,105 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2019, Blender Foundation
+# All rights reserved.
+# ***** END GPL LICENSE BLOCK *****
+
+# avoid noisy warnings
+if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
+ add_c_flag(
+ "-Wno-unused-result"
+ )
+endif()
+
+set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+if (WIN32)
+ add_definitions(-D_USE_MATH_DEFINES)
+endif()
+
+set(LEMON_3RD_PATH 3rd/lemon-1.3.1)
+
+set(LEMON_SOURCE_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${LEMON_3RD_PATH})
+
+set(LEMON_SRC ${LEMON_SOURCE_ROOT_DIR}/lemon)
+set(LEMON_INCLUDE_DIRS ${LEMON_SOURCE_ROOT_DIR})
+
+configure_file(
+ ${LEMON_SRC}/config.h.in
+ ${LEMON_SRC}/config.h
+ )
+set(LEMON_SOURCES
+ ${LEMON_SRC}/arg_parser.cc
+ ${LEMON_SRC}/base.cc
+ ${LEMON_SRC}/color.cc
+ ${LEMON_SRC}/lp_base.cc
+ ${LEMON_SRC}/lp_skeleton.cc
+ ${LEMON_SRC}/random.cc
+ ${LEMON_SRC}/bits/windows.cc
+ )
+
+set(INC
+ src
+ 3rd/pcg32
+ 3rd/pss
+ ${LEMON_INCLUDE_DIRS}
+)
+
+set(INC_SYS
+ ${BOOST_INCLUDE_DIR}
+ ${EIGEN3_INCLUDE_DIRS}
+)
+
+set(SRC
+ src/adjacent-matrix.cpp
+ src/adjacent-matrix.hpp
+ src/compare-key.hpp
+ src/config.hpp
+ src/dedge.cpp
+ src/dedge.hpp
+ src/disajoint-tree.hpp
+ src/dset.hpp
+ src/field-math.hpp
+ src/flow.hpp
+ src/hierarchy.cpp
+ src/hierarchy.hpp
+ src/loader.cpp
+ src/loader.hpp
+ src/localsat.cpp
+ src/localsat.hpp
+ src/merge-vertex.cpp
+ src/merge-vertex.hpp
+ src/optimizer.cpp
+ src/optimizer.hpp
+ src/parametrizer.cpp
+ src/parametrizer-flip.cpp
+ src/parametrizer-int.cpp
+ src/parametrizer-mesh.cpp
+ src/parametrizer-scale.cpp
+ src/parametrizer-sing.cpp
+ src/parametrizer.hpp
+ src/serialize.hpp
+ src/subdivide.cpp
+ src/subdivide.hpp
+ ${LEMON_SOURCES}
+)
+
+set(LIB
+)
+
+blender_add_lib(extern_quadriflow "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/extern/quadriflow/LICENSE.txt b/extern/quadriflow/LICENSE.txt
new file mode 100644
index 00000000000..5e963f42ca7
--- /dev/null
+++ b/extern/quadriflow/LICENSE.txt
@@ -0,0 +1,37 @@
+Copyright (c) 2018 Jingwei Huang, Yichao Zhou, Matthias Niessner,
+Jonathan Shewchuk and Leonidas Guibas. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+("Enhancements") to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to the authors of this software, without
+imposing a separate written license agreement for such Enhancements, then you
+hereby grant the following license: a non-exclusive, royalty-free perpetual
+license to install, use, modify, prepare derivative works, incorporate into
+other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form. \ No newline at end of file
diff --git a/extern/quadriflow/README.md b/extern/quadriflow/README.md
new file mode 100644
index 00000000000..dae22414184
--- /dev/null
+++ b/extern/quadriflow/README.md
@@ -0,0 +1,134 @@
+# QuadriFlow: A Scalable and Robust Method for Quadrangulation
+
+Source code for the paper:
+
+Jingwei Huang, Yichao Zhou, Matthias Niessner, Jonathan Shewchuk and Leonidas Guibas. [**QuadriFlow: A Scalable and Robust Method for Quadrangulation**](http://stanford.edu/~jingweih/papers/quadriflow/quadriflow.pdf), The Eurographics Symposium on Geometry Processing (SGP) 2018.
+
+<!-- ## Processing Result -->
+![QuadriFlow Results](https://github.com/hjwdzh/quadriflow/raw/master/img/result.jpg)
+
+## WebGL Application
+Our 3D WebGL Apps for QuadriFlow are online! Without any installation, you are able to
+* [**Compare**](https://yichaozhou.com/publication/1805quadriflow/#demo) QuadriFlow with previous methods;
+* [**Quadrangulate**](https://yichaozhou.com/publication/1805quadriflow/#tool) your own meshes and
+ download the result!
+
+## Desktop Software
+The software supports cmake build for Linux/Mac/Windows systems. For linux and mac users, run **`sh demo.sh`** to build and try the QuadriFlow example, which converts `examples/Gargoyle_input.obj` to `examples/Gargoyle_quadriflow.obj`.
+
+### Install
+
+```
+git clone git://github.com/hjwdzh/quadriflow
+cd quadriflow
+mkdir build
+cd build
+cmake .. -DCMAKE_BUILD_TYPE=release
+make -j
+```
+
+### QuadriFlow Software
+
+We take a manifold triangle mesh `input.obj` and generate a manifold quad mesh `output.obj`. The face number increases linearly with the resolution controled by the user.
+
+```
+./quadriflow -i input.obj -o output.obj -f [resolution]
+```
+
+Here, the resolution is the desired number of faces in the quad mesh.
+
+## Advanced Functions
+
+### Min-cost Flow
+By default, `quadriflow` uses the Boykov maximum flow solver from boost becuase it is faster. To
+enable the adaptive network simplex minimum-cost flow solver, you can enable the `-mcf` option:
+
+```
+./quadriflow -mcf -i input.obj -o output.obj -f [resolution]
+```
+
+### Sharp Preserving
+By default, `quadriflow` does not explicitly detect and perserve the sharp edges in the model. To
+enable this feature, uses
+
+```
+./quadriflow -sharp -i input.obj -o output.obj -f [resolution]
+```
+
+### SAT Flip Removal (Unix Only)
+By default, `quadriflow` does not use the SAT solver to remove the flips in the integer offsets
+map. To remove the flips and guarantee a watertight result mesh, you can enable the SAT solver.
+First, make sure that `minisat` and `timeout` is properly installed under your `${PATH}`. The
+former can be done by building `3rd/MapleCOMSPS_LRB/CMakeLists.txt` and copying `minisat` to `/usr/bin`.
+In addition, `timeout` is included in coreutils. If you are using Mac, you can install it using
+homebrew:
+```
+brew install coreutils
+export PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
+```
+
+You can verify if those binaries are properly installed by executing
+```
+which minisat
+which timeout
+```
+
+After that, you can enable SAT flip removal procedure by executing
+```
+./quadriflow -sat -i input.obj -o output.obj -f [resolution]
+```
+
+When using the SAT flip removal, we also suggest you enabling the verbose logging to understand
+what is going on. You can build quadriflow with the following options:
+```
+cmake .. -DCMAKE_BUILD_TYPE=release -DBUILD_LOG=ON
+```
+
+### GUROBI Support (For Benchmark Purpose)
+
+To use the Gurobi integer programming to solve the integer offset problem, you can build QuadriFlow with
+```
+cmake .. -DCMAKE_BUILD_TYPE=release -DBUILD_GUROBI=ON -DBUILD_LOG=ON
+```
+This override other solvers and should only be used for benchmark purpose.
+
+## External Dependencies
+* Boost
+* Eigen
+* OpenMP (optional in CMake)
+* TBB (optional in CMake)
+* GUROBI (for benchmark purpose only)
+
+## Licenses
+
+QuadriFlow is released under [MIT License](LICENSE.txt).
+For 3rd dependencies,
+* Boost and Lemon are released under [Boost Software License](https://lemon.cs.elte.hu/trac/lemon/wiki/License)
+* Most part of Eigen is released under [MPL2](https://www.mozilla.org/en-US/MPL/2.0/FAQ/)
+ * Sparse Cholesky Decomposition algorithms are released under LGPL
+ * To replace it using Sparse LU decomposition with a more permissive MPL2 license (a little slower), enable `BUILD_FREE_LICENSE` in CMake (e.g., `-DBUILD_FREE_LICENSE=ON`).
+* `pcg32.h` is released under the Apache License, Version 2.0
+* `parallel_stable_sort.h` is released under the MIT License
+
+## Authors
+- [Jingwei Huang](mailto:jingweih@stanford.edu)
+- [Yichao Zhou](mailto:zyc@berkeley.edu)
+
+&copy; 2018 Jingwei Huang and Yichao Zhou All Rights Reserved
+
+**IMPORTANT**: If you use this software please cite the following in any resulting publication:
+```
+@article {10.1111:cgf.13498,
+ journal = {Computer Graphics Forum},
+ title = {{QuadriFlow: A Scalable and Robust Method for Quadrangulation}},
+ author = {Huang, Jingwei and Zhou, Yichao and Niessner, Matthias and Shewchuk, Jonathan Richard and Guibas, Leonidas J.},
+ year = {2018},
+ publisher = {The Eurographics Association and John Wiley & Sons Ltd.},
+ ISSN = {1467-8659},
+ DOI = {10.1111/cgf.13498}
+}
+```
+
+## Triangle Manifold
+
+In case you are dealing with a triangle mesh that is not a manifold, we implemented the software that converts any triangle mesh to watertight manifold. Please visit https://github.com/hjwdzh/Manifold for details.
diff --git a/extern/quadriflow/src/Optimizer.cu b/extern/quadriflow/src/Optimizer.cu
new file mode 100644
index 00000000000..8520c3f90a8
--- /dev/null
+++ b/extern/quadriflow/src/Optimizer.cu
@@ -0,0 +1,281 @@
+#include <glm/glm.hpp>
+#include <cuda_runtime.h>
+#include "AdjacentMatrix.h"
+
+__device__ __host__ glm::dvec3
+middle_point(const glm::dvec3 &p0, const glm::dvec3 &n0, const glm::dvec3 &p1, const glm::dvec3 &n1) {
+ /* How was this derived?
+ *
+ * Minimize \|x-p0\|^2 + \|x-p1\|^2, where
+ * dot(n0, x) == dot(n0, p0)
+ * dot(n1, x) == dot(n1, p1)
+ *
+ * -> Lagrange multipliers, set derivative = 0
+ * Use first 3 equalities to write x in terms of
+ * lambda_1 and lambda_2. Substitute that into the last
+ * two equations and solve for the lambdas. Finally,
+ * add a small epsilon term to avoid issues when n1=n2.
+ */
+ double n0p0 = glm::dot(n0, p0), n0p1 = glm::dot(n0, p1),
+ n1p0 = glm::dot(n1, p0), n1p1 = glm::dot(n1, p1),
+ n0n1 = glm::dot(n0, n1),
+ denom = 1.0f / (1.0f - n0n1*n0n1 + 1e-4f),
+ lambda_0 = 2.0f*(n0p1 - n0p0 - n0n1*(n1p0 - n1p1))*denom,
+ lambda_1 = 2.0f*(n1p0 - n1p1 - n0n1*(n0p1 - n0p0))*denom;
+
+ return 0.5 * (p0 + p1) - 0.25 * (n0 * lambda_0 + n1 * lambda_1);
+}
+
+__device__ __host__ glm::dvec3
+position_round_4(const glm::dvec3 &o, const glm::dvec3 &q,
+const glm::dvec3 &n, const glm::dvec3 &p,
+double scale) {
+ double inv_scale = 1.0 / scale;
+ glm::dvec3 t = glm::cross(n, q);
+ glm::dvec3 d = p - o;
+ return o +
+ q * std::round(glm::dot(q, d) * inv_scale) * scale +
+ t * std::round(glm::dot(t, d) * inv_scale) * scale;
+}
+
+__device__ __host__ glm::dvec3
+position_floor_4(const glm::dvec3 &o, const glm::dvec3 &q,
+const glm::dvec3 &n, const glm::dvec3 &p,
+double scale) {
+ double inv_scale = 1.0 / scale;
+ glm::dvec3 t = glm::cross(n,q);
+ glm::dvec3 d = p - o;
+ return o +
+ q * std::floor(glm::dot(q, d) * inv_scale) * scale +
+ t * std::floor(glm::dot(t, d) * inv_scale) * scale;
+}
+
+
+__device__ __host__ double cudaSignum(double value) {
+ return std::copysign((double)1, value);
+}
+
+__device__ __host__ void
+compat_orientation_extrinsic_4(const glm::dvec3 &q0, const glm::dvec3 &n0,
+const glm::dvec3 &q1, const glm::dvec3 &n1, glm::dvec3& value1, glm::dvec3& value2) {
+ const glm::dvec3 A[2] = { q0, glm::cross(n0, q0) };
+ const glm::dvec3 B[2] = { q1, glm::cross(n1, q1) };
+
+ double best_score = -1e10;
+ int best_a = 0, best_b = 0;
+
+ for (int i = 0; i < 2; ++i) {
+ for (int j = 0; j < 2; ++j) {
+ double score = std::abs(glm::dot(A[i], B[j]));
+ if (score > best_score + 1e-6) {
+ best_a = i;
+ best_b = j;
+ best_score = score;
+ }
+ }
+ }
+ const double dp = glm::dot(A[best_a], B[best_b]);
+ value1 = A[best_a];
+ value2 = B[best_b] * cudaSignum(dp);
+}
+
+__device__ __host__ void
+compat_position_extrinsic_4(
+const glm::dvec3 &p0, const glm::dvec3 &n0, const glm::dvec3 &q0, const glm::dvec3 &o0,
+const glm::dvec3 &p1, const glm::dvec3 &n1, const glm::dvec3 &q1, const glm::dvec3 &o1,
+double scale, glm::dvec3& v1, glm::dvec3& v2) {
+
+ glm::dvec3 t0 = glm::cross(n0, q0), t1 = glm::cross(n1, q1);
+ glm::dvec3 middle = middle_point(p0, n0, p1, n1);
+ glm::dvec3 o0p = position_floor_4(o0, q0, n0, middle, scale);
+ glm::dvec3 o1p = position_floor_4(o1, q1, n1, middle, scale);
+
+ double best_cost = 1e10;
+ int best_i = -1, best_j = -1;
+
+ for (int i = 0; i<4; ++i) {
+ glm::dvec3 o0t = o0p + (q0 * ((i & 1) * scale) + t0 * (((i & 2) >> 1) * scale));
+ for (int j = 0; j<4; ++j) {
+ glm::dvec3 o1t = o1p + (q1 * ((j & 1) * scale) + t1 * (((j & 2) >> 1) * scale));
+ glm::dvec3 t = o0t - o1t;
+ double cost = glm::dot(t, t);
+
+ if (cost < best_cost) {
+ best_i = i;
+ best_j = j;
+ best_cost = cost;
+ }
+ }
+ }
+
+ v1 = o0p + (q0 * ((best_i & 1) * scale) + t0 * (((best_i & 2) >> 1) * scale)),
+ v2 = o1p + (q1 * ((best_j & 1) * scale) + t1 * (((best_j & 2) >> 1) * scale));
+}
+
+__global__
+void cudaUpdateOrientation(int* phase, int num_phases, glm::dvec3* N, glm::dvec3* Q, Link* adj, int* adjOffset, int num_adj) {
+ int pi = blockIdx.x * blockDim.x + threadIdx.x;
+
+// for (int pi = 0; pi < num_phases; ++pi) {
+ if (pi >= num_phases)
+ return;
+ int i = phase[pi];
+ glm::dvec3 n_i = N[i];
+ double weight_sum = 0.0f;
+ glm::dvec3 sum = Q[i];
+
+ for (int l = adjOffset[i]; l < adjOffset[i + 1]; ++l) {
+ Link link = adj[l];
+ const int j = link.id;
+ const double weight = link.weight;
+ if (weight == 0)
+ continue;
+ glm::dvec3 n_j = N[j];
+ glm::dvec3 q_j = Q[j];
+ glm::dvec3 value1, value2;
+ compat_orientation_extrinsic_4(sum, n_i, q_j, n_j, value1, value2);
+ sum = value1 * weight_sum + value2 * weight;
+ sum -= n_i*glm::dot(n_i, sum);
+ weight_sum += weight;
+
+ double norm = glm::length(sum);
+ if (norm > 2.93873587705571876e-39f)
+ sum /= norm;
+ }
+
+ if (weight_sum > 0) {
+ Q[i] = sum;
+ }
+// }
+}
+
+__global__
+void cudaPropagateOrientationUpper(glm::dvec3* srcField, glm::ivec2* toUpper, glm::dvec3* N, glm::dvec3* destField, int num_orientation) {
+ int i = blockIdx.x * blockDim.x + threadIdx.x;
+// for (int i = 0; i < num_orientation; ++i) {
+ if (i >= num_orientation)
+ return;
+ for (int k = 0; k < 2; ++k) {
+ int dest = toUpper[i][k];
+ if (dest == -1)
+ continue;
+ glm::dvec3 q = srcField[i];
+ glm::dvec3 n = N[dest];
+ destField[dest] = q - n * glm::dot(n, q);
+ }
+// }
+}
+
+__global__
+void cudaPropagateOrientationLower(glm::ivec2* toUpper, glm::dvec3* Q, glm::dvec3* N, glm::dvec3* Q_next, glm::dvec3* N_next, int num_toUpper) {
+ int i = blockIdx.x * blockDim.x + threadIdx.x;
+// for (int i = 0; i < num_toUpper; ++i) {
+ if (i >= num_toUpper)
+ return;
+ glm::ivec2 upper = toUpper[i];
+ glm::dvec3 q0 = Q[upper[0]];
+ glm::dvec3 n0 = N[upper[0]];
+
+ glm::dvec3 q, q1, n1, value1, value2;
+ if (upper[1] != -1) {
+ q1 = Q[upper[1]];
+ n1 = N[upper[1]];
+ compat_orientation_extrinsic_4(q0, n0, q1, n1, value1, value2);
+ q = value1 + value2;
+ }
+ else {
+ q = q0;
+ }
+ glm::dvec3 n = N_next[i];
+ q -= glm::dot(n, q) * n;
+
+ double len = q.x * q.x + q.y * q.y + q.z * q.z;
+ if (len > 2.93873587705571876e-39f)
+ q /= sqrt(len);
+ Q_next[i] = q;
+// }
+}
+
+
+__global__
+void cudaUpdatePosition(int* phase, int num_phases, glm::dvec3* N, glm::dvec3* Q, Link* adj, int* adjOffset, int num_adj, glm::dvec3* V, glm::dvec3* O, double scale) {
+ int pi = blockIdx.x * blockDim.x + threadIdx.x;
+
+// for (int pi = 0; pi < num_phases; ++pi) {
+ if (pi >= num_phases)
+ return;
+ int i = phase[pi];
+ glm::dvec3 n_i = N[i], v_i = V[i];
+ glm::dvec3 q_i = Q[i];
+ glm::dvec3 sum = O[i];
+ double weight_sum = 0.0f;
+
+ for (int l = adjOffset[i]; l < adjOffset[i + 1]; ++l) {
+ Link link = adj[l];
+ int j = link.id;
+ const double weight = link.weight;
+ if (weight == 0)
+ continue;
+
+ glm::dvec3 n_j = N[j], v_j = V[j];
+ glm::dvec3 q_j = Q[j], o_j = O[j];
+ glm::dvec3 v1, v2;
+ compat_position_extrinsic_4(
+ v_i, n_i, q_i, sum, v_j, n_j, q_j, o_j, scale, v1, v2);
+
+ sum = v1*weight_sum +v2*weight;
+ weight_sum += weight;
+ if (weight_sum > 2.93873587705571876e-39f)
+ sum /= weight_sum;
+ sum -= glm::dot(n_i, sum - v_i)*n_i;
+ }
+
+ if (weight_sum > 0) {
+ O[i] = position_round_4(sum, q_i, n_i, v_i, scale);
+ }
+// }
+}
+
+__global__
+void cudaPropagatePositionUpper(glm::dvec3* srcField, glm::ivec2* toUpper, glm::dvec3* N, glm::dvec3* V, glm::dvec3* destField, int num_position) {
+ int i = blockIdx.x * blockDim.x + threadIdx.x;
+// for (int i = 0; i < num_position; ++i) {
+ if (i >= num_position)
+ return;
+ for (int k = 0; k < 2; ++k) {
+ int dest = toUpper[i][k];
+ if (dest == -1)
+ continue;
+ glm::dvec3 o = srcField[i], n = N[dest], v = V[dest];
+ o -= n * glm::dot(n, o - v);
+ destField[dest] = o;
+ }
+// }
+}
+
+
+void UpdateOrientation(int* phase, int num_phases, glm::dvec3* N, glm::dvec3* Q, Link* adj, int* adjOffset, int num_adj) {
+ cudaUpdateOrientation << <(num_phases + 255) / 256, 256 >> >(phase, num_phases, N, Q, adj, adjOffset, num_adj);
+// cudaUpdateOrientation(phase, num_phases, N, Q, adj, adjOffset, num_adj);
+}
+
+void PropagateOrientationUpper(glm::dvec3* srcField, int num_orientation, glm::ivec2* toUpper, glm::dvec3* N, glm::dvec3* destField) {
+ cudaPropagateOrientationUpper << <(num_orientation + 255) / 256, 256 >> >(srcField, toUpper, N, destField, num_orientation);
+// cudaPropagateOrientationUpper(srcField, toUpper, N, destField, num_orientation);
+}
+
+void PropagateOrientationLower(glm::ivec2* toUpper, glm::dvec3* Q, glm::dvec3* N, glm::dvec3* Q_next, glm::dvec3* N_next, int num_toUpper) {
+ cudaPropagateOrientationLower << <(num_toUpper + 255) / 256, 256 >> >(toUpper, Q, N, Q_next, N_next, num_toUpper);
+// cudaPropagateOrientationLower(toUpper, Q, N, Q_next, N_next, num_toUpper);
+}
+
+
+void UpdatePosition(int* phase, int num_phases, glm::dvec3* N, glm::dvec3* Q, Link* adj, int* adjOffset, int num_adj, glm::dvec3* V, glm::dvec3* O, double scale) {
+ cudaUpdatePosition << <(num_phases + 255) / 256, 256 >> >(phase, num_phases, N, Q, adj, adjOffset, num_adj, V, O, scale);
+// cudaUpdatePosition(phase, num_phases, N, Q, adj, adjOffset, num_adj, V, O, scale);
+}
+
+void PropagatePositionUpper(glm::dvec3* srcField, int num_position, glm::ivec2* toUpper, glm::dvec3* N, glm::dvec3* V, glm::dvec3* destField) {
+ cudaPropagatePositionUpper << <(num_position + 255) / 256, 256 >> >(srcField, toUpper, N, V, destField, num_position);
+// cudaPropagatePositionUpper(srcField, toUpper, N, V, destField, num_position);
+}
diff --git a/extern/quadriflow/src/adjacent-matrix.cpp b/extern/quadriflow/src/adjacent-matrix.cpp
new file mode 100644
index 00000000000..e20ffb05f6d
--- /dev/null
+++ b/extern/quadriflow/src/adjacent-matrix.cpp
@@ -0,0 +1,35 @@
+#include "config.hpp"
+#include "adjacent-matrix.hpp"
+#include "dedge.hpp"
+#include <fstream>
+
+namespace qflow {
+
+void generate_adjacency_matrix_uniform(
+ const MatrixXi &F, const VectorXi &V2E, const VectorXi &E2E,
+ const VectorXi &nonManifold, AdjacentMatrix& adj) {
+ adj.resize(V2E.size());
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int i = 0; i < adj.size(); ++i) {
+ int start = V2E[i];
+ int edge = start;
+ if (start == -1)
+ continue;
+ do {
+ int base = edge % 3, f = edge / 3;
+ int opp = E2E[edge], next = dedge_next_3(opp);
+ if (adj[i].empty())
+ adj[i].push_back(Link(F((base + 2) % 3, f)));
+ if (opp == -1 || next != start) {
+ adj[i].push_back(Link(F((base + 1) % 3, f)));
+ if (opp == -1)
+ break;
+ }
+ edge = next;
+ } while (edge != start);
+ }
+}
+
+} // namespace qflow
diff --git a/extern/quadriflow/src/adjacent-matrix.hpp b/extern/quadriflow/src/adjacent-matrix.hpp
new file mode 100644
index 00000000000..e3eb2e12a47
--- /dev/null
+++ b/extern/quadriflow/src/adjacent-matrix.hpp
@@ -0,0 +1,37 @@
+#ifndef ADJACENT_MATRIX_H_
+#define ADJACENT_MATRIX_H_
+
+#include <vector>
+
+namespace qflow {
+
+struct Link
+{
+ Link(){}
+ Link(int _id, double _w = 1)
+ : id(_id), weight(_w)
+ {}
+ inline bool operator<(const Link &link) const { return id < link.id; }
+ int id;
+ double weight;
+};
+
+struct TaggedLink {
+ int id;
+ unsigned char flag;
+ TaggedLink(){}
+ TaggedLink(int id) : id(id), flag(0) { }
+ bool used() const { return flag & 1; }
+ void markUsed() { flag |= 1; }
+ TaggedLink& operator=(const Link& l) {
+ flag = 0;
+ id = l.id;
+ return *this;
+ }
+};
+
+typedef std::vector<std::vector<Link> > AdjacentMatrix;
+
+} // namespace qflow
+
+#endif \ No newline at end of file
diff --git a/extern/quadriflow/src/compare-key.hpp b/extern/quadriflow/src/compare-key.hpp
new file mode 100644
index 00000000000..df9109d62e0
--- /dev/null
+++ b/extern/quadriflow/src/compare-key.hpp
@@ -0,0 +1,102 @@
+#ifndef COMPARE_KEY_H_
+#define COMPARE_KEY_H_
+
+#include <iostream>
+#include <map>
+
+namespace qflow {
+
+struct Key2i
+{
+ Key2i(int x, int y)
+ : key(std::make_pair(x, y))
+ {}
+ bool operator==(const Key2i& other) const
+ {
+ return key == other.key;
+ }
+ bool operator<(const Key2i& other) const
+ {
+ return key < other.key;
+ }
+ std::pair<int, int> key;
+};
+
+struct Key3i
+{
+ Key3i(int x, int y, int z)
+ : key(std::make_pair(x, std::make_pair(y, z)))
+ {}
+ bool operator==(const Key3i& other) const
+ {
+ return key == other.key;
+ }
+ bool operator<(const Key3i& other) const
+ {
+ return key < other.key;
+ }
+ std::pair<int, std::pair<int, int> > key;
+};
+
+struct Key3f
+{
+ Key3f(double x, double y, double z, double threshold)
+ : key(std::make_pair(x / threshold, std::make_pair(y / threshold, z / threshold)))
+ {}
+ bool operator==(const Key3f& other) const
+ {
+ return key == other.key;
+ }
+ bool operator<(const Key3f& other) const
+ {
+ return key < other.key;
+ }
+ std::pair<int, std::pair<int, int> > key;
+};
+
+struct KeySorted2i
+{
+ KeySorted2i(int x, int y)
+ : key(std::make_pair(x, y))
+ {
+ if (x > y)
+ std::swap(key.first, key.second);
+ }
+ bool operator==(const KeySorted2i& other) const
+ {
+ return key == other.key;
+ }
+ bool operator<(const KeySorted2i& other) const
+ {
+ return key < other.key;
+ }
+ std::pair<int, int> key;
+};
+
+struct KeySorted3i
+{
+ KeySorted3i(int x, int y, int z)
+ : key(std::make_pair(x, std::make_pair(y, z)))
+ {
+ if (key.first > key.second.first)
+ std::swap(key.first, key.second.first);
+ if (key.first > key.second.second)
+ std::swap(key.first, key.second.second);
+ if (key.second.first > key.second.second)
+ std::swap(key.second.first, key.second.second);
+ }
+ bool operator==(const Key3i& other) const
+ {
+ return key == other.key;
+ }
+ bool operator<(const Key3i& other) const
+ {
+ return key < other.key;
+ }
+ std::pair<int, std::pair<int, int> > key;
+};
+
+
+} // namespace qflow
+
+#endif
diff --git a/extern/quadriflow/src/config.hpp b/extern/quadriflow/src/config.hpp
new file mode 100644
index 00000000000..842b885a209
--- /dev/null
+++ b/extern/quadriflow/src/config.hpp
@@ -0,0 +1,34 @@
+#ifndef CONFIG_H_
+#define CONFIG_H_
+
+// Move settings to cmake to make CMake happy :)
+
+// #define WITH_SCALE
+// #define WITH_CUDA
+
+const int GRAIN_SIZE = 1024;
+
+#ifdef LOG_OUTPUT
+
+#define lprintf(...) printf(__VA_ARGS__)
+#define lputs(...) puts(__VA_ARGS__)
+
+#else
+
+#define lprintf(...) void(0)
+#define lputs(...) void(0)
+
+#endif
+
+#include <chrono>
+
+namespace qflow {
+
+// simulation of Windows GetTickCount()
+unsigned long long inline GetCurrentTime64() {
+ using namespace std::chrono;
+ return duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
+}
+} // namespace qflow
+
+#endif
diff --git a/extern/quadriflow/src/dedge.cpp b/extern/quadriflow/src/dedge.cpp
new file mode 100644
index 00000000000..b030e20d6a1
--- /dev/null
+++ b/extern/quadriflow/src/dedge.cpp
@@ -0,0 +1,487 @@
+#include "dedge.hpp"
+#include "config.hpp"
+
+#include <atomic>
+#include <fstream>
+#include <iostream>
+#include <set>
+#include <vector>
+#include "compare-key.hpp"
+#ifdef WITH_TBB
+#include "tbb/tbb.h"
+#endif
+namespace qflow {
+
+inline int dedge_prev(int e, int deg) { return (e % deg == 0u) ? e + (deg - 1) : e - 1; }
+
+inline bool atomicCompareAndExchange(volatile int* v, uint32_t newValue, int oldValue) {
+#if defined(_WIN32)
+ return _InterlockedCompareExchange(reinterpret_cast<volatile long*>(v), (long)newValue,
+ (long)oldValue) == (long)oldValue;
+#else
+ return __sync_bool_compare_and_swap(v, oldValue, newValue);
+#endif
+}
+
+const int INVALID = -1;
+
+#undef max
+#undef min
+bool compute_direct_graph(MatrixXd& V, MatrixXi& F, VectorXi& V2E, VectorXi& E2E,
+ VectorXi& boundary, VectorXi& nonManifold) {
+ V2E.resize(V.cols());
+ V2E.setConstant(INVALID);
+
+ uint32_t deg = F.rows();
+ std::vector<std::pair<uint32_t, uint32_t>> tmp(F.size());
+
+#ifdef WITH_TBB
+ tbb::parallel_for(
+ tbb::blocked_range<uint32_t>(0u, (uint32_t)F.cols(), GRAIN_SIZE),
+ [&](const tbb::blocked_range<uint32_t>& range) {
+ for (uint32_t f = range.begin(); f != range.end(); ++f) {
+ for (uint32_t i = 0; i < deg; ++i) {
+ uint32_t idx_cur = F(i, f), idx_next = F((i + 1) % deg, f),
+ edge_id = deg * f + i;
+ if (idx_cur >= V.cols() || idx_next >= V.cols())
+ throw std::runtime_error(
+ "Mesh data contains an out-of-bounds vertex reference!");
+ if (idx_cur == idx_next) continue;
+
+ tmp[edge_id] = std::make_pair(idx_next, INVALID);
+ if (!atomicCompareAndExchange(&V2E[idx_cur], edge_id, INVALID)) {
+ uint32_t idx = V2E[idx_cur];
+ while (!atomicCompareAndExchange((int*)&tmp[idx].second, edge_id, INVALID))
+ idx = tmp[idx].second;
+ }
+ }
+ }
+ });
+#else
+ for (int f = 0; f < F.cols(); ++f) {
+ for (unsigned int i = 0; i < deg; ++i) {
+ unsigned int idx_cur = F(i, f), idx_next = F((i + 1) % deg, f), edge_id = deg * f + i;
+ if (idx_cur >= V.cols() || idx_next >= V.cols())
+ throw std::runtime_error("Mesh data contains an out-of-bounds vertex reference!");
+ if (idx_cur == idx_next) continue;
+
+ tmp[edge_id] = std::make_pair(idx_next, -1);
+ if (V2E[idx_cur] == -1)
+ V2E[idx_cur] = edge_id;
+ else {
+ unsigned int idx = V2E[idx_cur];
+ while (tmp[idx].second != -1) {
+ idx = tmp[idx].second;
+ }
+ tmp[idx].second = edge_id;
+ }
+ }
+ }
+#endif
+
+ nonManifold.resize(V.cols());
+ nonManifold.setConstant(false);
+
+ E2E.resize(F.cols() * deg);
+ E2E.setConstant(INVALID);
+
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int f = 0; f < F.cols(); ++f) {
+ for (uint32_t i = 0; i < deg; ++i) {
+ uint32_t idx_cur = F(i, f), idx_next = F((i + 1) % deg, f), edge_id_cur = deg * f + i;
+
+ if (idx_cur == idx_next) continue;
+
+ uint32_t it = V2E[idx_next], edge_id_opp = INVALID;
+ while (it != INVALID) {
+ if (tmp[it].first == idx_cur) {
+ if (edge_id_opp == INVALID) {
+ edge_id_opp = it;
+ } else {
+ nonManifold[idx_cur] = true;
+ nonManifold[idx_next] = true;
+ edge_id_opp = INVALID;
+ break;
+ }
+ }
+ it = tmp[it].second;
+ }
+
+ if (edge_id_opp != INVALID && edge_id_cur < edge_id_opp) {
+ E2E[edge_id_cur] = edge_id_opp;
+ E2E[edge_id_opp] = edge_id_cur;
+ }
+ }
+ }
+ std::atomic<uint32_t> nonManifoldCounter(0), boundaryCounter(0), isolatedCounter(0);
+
+ boundary.resize(V.cols());
+ boundary.setConstant(false);
+
+ /* Detect boundary regions of the mesh and adjust vertex->edge pointers*/
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int i = 0; i < V.cols(); ++i) {
+ uint32_t edge = V2E[i];
+ if (edge == INVALID) {
+ isolatedCounter++;
+ continue;
+ }
+ if (nonManifold[i]) {
+ nonManifoldCounter++;
+ V2E[i] = INVALID;
+ continue;
+ }
+
+ /* Walk backwards to the first boundary edge (if any) */
+ uint32_t start = edge, v2e = INVALID;
+ do {
+ v2e = std::min(v2e, edge);
+ uint32_t prevEdge = E2E[dedge_prev(edge, deg)];
+ if (prevEdge == INVALID) {
+ /* Reached boundary -- update the vertex->edge link */
+ v2e = edge;
+ boundary[i] = true;
+ boundaryCounter++;
+ break;
+ }
+ edge = prevEdge;
+ } while (edge != start);
+ V2E[i] = v2e;
+ }
+#ifdef LOG_OUTPUT
+ printf("counter triangle %d %d\n", (int)boundaryCounter, (int)nonManifoldCounter);
+#endif
+ return true;
+ std::vector<std::vector<int>> vert_to_edges(V2E.size());
+ for (int i = 0; i < F.cols(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ int v = F(j, i);
+ vert_to_edges[v].push_back(i * 3 + j);
+ }
+ }
+ std::vector<int> colors(F.cols() * 3, -1);
+ bool update = false;
+ int num_v = V.cols();
+ std::map<int, int> new_vertices;
+ for (int i = 0; i < vert_to_edges.size(); ++i) {
+ int num_color = 0;
+ for (int j = 0; j < vert_to_edges[i].size(); ++j) {
+ int deid0 = vert_to_edges[i][j];
+ if (colors[deid0] == -1) {
+ int deid = deid0;
+ do {
+ colors[deid] = num_color;
+ if (num_color != 0) F(deid % 3, deid / 3) = num_v;
+ deid = deid / 3 * 3 + (deid + 2) % 3;
+ deid = E2E[deid];
+ } while (deid != deid0);
+ num_color += 1;
+ if (num_color > 1) {
+ update = true;
+ new_vertices[num_v] = i;
+ num_v += 1;
+ }
+ }
+ }
+ }
+ if (update) {
+ V.conservativeResize(3, num_v);
+ for (auto& p : new_vertices) {
+ V.col(p.first) = V.col(p.second);
+ }
+ return false;
+ }
+ return true;
+}
+
+void compute_direct_graph_quad(std::vector<Vector3d>& V, std::vector<Vector4i>& F, std::vector<int>& V2E, std::vector<int>& E2E, VectorXi& boundary, VectorXi& nonManifold) {
+ V2E.clear();
+ E2E.clear();
+ boundary = VectorXi();
+ nonManifold = VectorXi();
+ V2E.resize(V.size(), INVALID);
+
+ uint32_t deg = 4;
+ std::vector<std::pair<uint32_t, uint32_t>> tmp(F.size() * deg);
+
+#ifdef WITH_TBB
+ tbb::parallel_for(
+ tbb::blocked_range<uint32_t>(0u, (uint32_t)F.size(), GRAIN_SIZE),
+ [&](const tbb::blocked_range<uint32_t>& range) {
+ for (uint32_t f = range.begin(); f != range.end(); ++f) {
+ for (uint32_t i = 0; i < deg; ++i) {
+ uint32_t idx_cur = F[f][i], idx_next = F[f][(i + 1) % deg],
+ edge_id = deg * f + i;
+ if (idx_cur >= V.size() || idx_next >= V.size())
+ throw std::runtime_error(
+ "Mesh data contains an out-of-bounds vertex reference!");
+ if (idx_cur == idx_next) continue;
+
+ tmp[edge_id] = std::make_pair(idx_next, INVALID);
+ if (!atomicCompareAndExchange(&V2E[idx_cur], edge_id, INVALID)) {
+ uint32_t idx = V2E[idx_cur];
+ while (!atomicCompareAndExchange((int*)&tmp[idx].second, edge_id, INVALID))
+ idx = tmp[idx].second;
+ }
+ }
+ }
+ });
+#else
+ for (int f = 0; f < F.size(); ++f) {
+ for (unsigned int i = 0; i < deg; ++i) {
+ unsigned int idx_cur = F[f][i], idx_next = F[f][(i + 1) % deg], edge_id = deg * f + i;
+ if (idx_cur >= V.size() || idx_next >= V.size())
+ throw std::runtime_error("Mesh data contains an out-of-bounds vertex reference!");
+ if (idx_cur == idx_next) continue;
+ tmp[edge_id] = std::make_pair(idx_next, -1);
+ if (V2E[idx_cur] == -1) {
+ V2E[idx_cur] = edge_id;
+ }
+ else {
+ unsigned int idx = V2E[idx_cur];
+ while (tmp[idx].second != -1) {
+ idx = tmp[idx].second;
+ }
+ tmp[idx].second = edge_id;
+ }
+ }
+ }
+#endif
+ nonManifold.resize(V.size());
+ nonManifold.setConstant(false);
+
+ E2E.resize(F.size() * deg, INVALID);
+
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int f = 0; f < F.size(); ++f) {
+ for (uint32_t i = 0; i < deg; ++i) {
+ uint32_t idx_cur = F[f][i], idx_next = F[f][(i + 1) % deg], edge_id_cur = deg * f + i;
+
+ if (idx_cur == idx_next) continue;
+
+ uint32_t it = V2E[idx_next], edge_id_opp = INVALID;
+ while (it != INVALID) {
+ if (tmp[it].first == idx_cur) {
+ if (edge_id_opp == INVALID) {
+ edge_id_opp = it;
+ } else {
+ nonManifold[idx_cur] = true;
+ nonManifold[idx_next] = true;
+ edge_id_opp = INVALID;
+ break;
+ }
+ }
+ it = tmp[it].second;
+ }
+
+ if (edge_id_opp != INVALID && edge_id_cur < edge_id_opp) {
+ E2E[edge_id_cur] = edge_id_opp;
+ E2E[edge_id_opp] = edge_id_cur;
+ }
+ }
+ }
+ std::atomic<uint32_t> nonManifoldCounter(0), boundaryCounter(0), isolatedCounter(0);
+
+ boundary.resize(V.size());
+ boundary.setConstant(false);
+
+ /* Detect boundary regions of the mesh and adjust vertex->edge pointers*/
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int i = 0; i < V.size(); ++i) {
+ uint32_t edge = V2E[i];
+ if (edge == INVALID) {
+ isolatedCounter++;
+ continue;
+ }
+ if (nonManifold[i]) {
+ nonManifoldCounter++;
+ V2E[i] = INVALID;
+ continue;
+ }
+
+ /* Walk backwards to the first boundary edge (if any) */
+ uint32_t start = edge, v2e = INVALID;
+ do {
+ v2e = std::min(v2e, edge);
+ uint32_t prevEdge = E2E[dedge_prev(edge, deg)];
+ if (prevEdge == INVALID) {
+ /* Reached boundary -- update the vertex->edge link */
+ v2e = edge;
+ boundary[i] = true;
+ boundaryCounter++;
+ break;
+ }
+ edge = prevEdge;
+ } while (edge != start);
+ V2E[i] = v2e;
+ }
+#ifdef LOG_OUTPUT
+ printf("counter %d %d\n", (int)boundaryCounter, (int)nonManifoldCounter);
+#endif
+}
+
+void remove_nonmanifold(std::vector<Vector4i>& F, std::vector<Vector3d>& V) {
+ typedef std::pair<uint32_t, uint32_t> Edge;
+
+ int degree = 4;
+ std::map<uint32_t, std::map<uint32_t, std::pair<uint32_t, uint32_t>>> irregular;
+ std::vector<std::set<int>> E(V.size());
+ std::vector<std::set<int>> VF(V.size());
+
+ auto kill_face_single = [&](uint32_t f) {
+ if (F[f][0] == INVALID) return;
+ for (int i = 0; i < degree; ++i) E[F[f][i]].erase(F[f][(i + 1) % degree]);
+ F[f].setConstant(INVALID);
+ };
+
+ auto kill_face = [&](uint32_t f) {
+ if (degree == 4 && F[f][2] == F[f][3]) {
+ auto it = irregular.find(F[f][2]);
+ if (it != irregular.end()) {
+ for (auto& item : it->second) {
+ kill_face_single(item.second.second);
+ }
+ }
+ }
+ kill_face_single(f);
+ };
+
+ uint32_t nm_edge = 0, nm_vert = 0;
+
+ for (uint32_t f = 0; f < (uint32_t)F.size(); ++f) {
+ if (F[f][0] == INVALID) continue;
+ if (degree == 4 && F[f][2] == F[f][3]) {
+ /* Special handling of irregular faces */
+ irregular[F[f][2]][F[f][0]] = std::make_pair(F[f][1], f);
+ continue;
+ }
+
+ bool nonmanifold = false;
+ for (uint32_t e = 0; e < degree; ++e) {
+ uint32_t v0 = F[f][e], v1 = F[f][(e + 1) % degree], v2 = F[f][(e + 2) % degree];
+ if (E[v0].find(v1) != E[v0].end() || (degree == 4 && E[v0].find(v2) != E[v0].end()))
+ nonmanifold = true;
+ }
+
+ if (nonmanifold) {
+ nm_edge++;
+ F[f].setConstant(INVALID);
+ continue;
+ }
+
+ for (uint32_t e = 0; e < degree; ++e) {
+ uint32_t v0 = F[f][e], v1 = F[f][(e + 1) % degree], v2 = F[f][(e + 2) % degree];
+
+ E[v0].insert(v1);
+ if (degree == 4) E[v0].insert(v2);
+ VF[v0].insert(f);
+ }
+ }
+
+ std::vector<Edge> edges;
+ for (auto item : irregular) {
+ bool nonmanifold = false;
+ auto face = item.second;
+ edges.clear();
+
+ uint32_t cur = face.begin()->first, stop = cur;
+ while (true) {
+ uint32_t pred = cur;
+ cur = face[cur].first;
+ uint32_t next = face[cur].first, it = 0;
+ while (true) {
+ ++it;
+ if (next == pred) break;
+ if (E[cur].find(next) != E[cur].end() && it == 1) nonmanifold = true;
+ edges.push_back(Edge(cur, next));
+ next = face[next].first;
+ }
+ if (cur == stop) break;
+ }
+
+ if (nonmanifold) {
+ nm_edge++;
+ for (auto& i : item.second) F[i.second.second].setConstant(INVALID);
+ continue;
+ } else {
+ for (auto e : edges) {
+ E[e.first].insert(e.second);
+
+ for (auto e2 : face) VF[e.first].insert(e2.second.second);
+ }
+ }
+ }
+
+ /* Check vertices */
+ std::set<uint32_t> v_marked, v_unmarked, f_adjacent;
+
+ std::function<void(uint32_t)> dfs = [&](uint32_t i) {
+ v_marked.insert(i);
+ v_unmarked.erase(i);
+
+ for (uint32_t f : VF[i]) {
+ if (f_adjacent.find(f) == f_adjacent.end()) /* if not part of adjacent face */
+ continue;
+ for (uint32_t j = 0; j < degree; ++j) {
+ uint32_t k = F[f][j];
+ if (v_unmarked.find(k) == v_unmarked.end() || /* if not unmarked OR */
+ v_marked.find(k) != v_marked.end()) /* if already marked */
+ continue;
+ dfs(k);
+ }
+ }
+ };
+
+ for (uint32_t i = 0; i < (uint32_t)V.size(); ++i) {
+ v_marked.clear();
+ v_unmarked.clear();
+ f_adjacent.clear();
+
+ for (uint32_t f : VF[i]) {
+ if (F[f][0] == INVALID) continue;
+
+ for (uint32_t k = 0; k < degree; ++k) v_unmarked.insert(F[f][k]);
+
+ f_adjacent.insert(f);
+ }
+
+ if (v_unmarked.empty()) continue;
+ v_marked.insert(i);
+ v_unmarked.erase(i);
+
+ dfs(*v_unmarked.begin());
+
+ if (v_unmarked.size() > 0) {
+ nm_vert++;
+ for (uint32_t f : f_adjacent) kill_face(f);
+ }
+ }
+
+ if (nm_vert > 0 || nm_edge > 0) {
+ std::cout << "Non-manifold elements: vertices=" << nm_vert << ", edges=" << nm_edge
+ << std::endl;
+ }
+ uint32_t nFaces = 0, nFacesOrig = F.size();
+ for (uint32_t f = 0; f < (uint32_t)F.size(); ++f) {
+ if (F[f][0] == INVALID) continue;
+ if (nFaces != f) {
+ F[nFaces] = F[f];
+ }
+ ++nFaces;
+ }
+
+ if (nFacesOrig != nFaces) {
+ F.resize(nFaces);
+ std::cout << "Faces reduced from " << nFacesOrig << " -> " << nFaces << std::endl;
+ }
+}
+
+} // namespace qflow
diff --git a/extern/quadriflow/src/dedge.hpp b/extern/quadriflow/src/dedge.hpp
new file mode 100644
index 00000000000..e8ee372f012
--- /dev/null
+++ b/extern/quadriflow/src/dedge.hpp
@@ -0,0 +1,25 @@
+#ifndef DEDGE_H_
+#define DEDGE_H_
+
+#include <Eigen/Core>
+#include <Eigen/Dense>
+#include <vector>
+
+namespace qflow {
+
+using namespace Eigen;
+
+inline int dedge_prev_3(int e) { return (e % 3 == 0) ? e + 2 : e - 1; }
+inline int dedge_next_3(int e) { return (e % 3 == 2) ? e - 2 : e + 1; }
+
+bool compute_direct_graph(MatrixXd& V, MatrixXi& F, VectorXi& V2E,
+ VectorXi& E2E, VectorXi& boundary, VectorXi& nonManifold);
+
+void compute_direct_graph_quad(std::vector<Vector3d>& V, std::vector<Vector4i>& F, std::vector<int>& V2E,
+ std::vector<int>& E2E, VectorXi& boundary, VectorXi& nonManifold);
+
+void remove_nonmanifold(std::vector<Vector4i> &F, std::vector<Vector3d> &V);
+
+} // namespace qflow
+
+#endif
diff --git a/extern/quadriflow/src/disajoint-tree.hpp b/extern/quadriflow/src/disajoint-tree.hpp
new file mode 100644
index 00000000000..1822b83a208
--- /dev/null
+++ b/extern/quadriflow/src/disajoint-tree.hpp
@@ -0,0 +1,151 @@
+#ifndef DISAJOINT_TREE_H_
+#define DISAJOINT_TREE_H_
+
+#include <vector>
+
+namespace qflow {
+
+class DisajointTree {
+ public:
+ DisajointTree() {}
+ DisajointTree(int n) {
+ parent.resize(n);
+ rank.resize(n, 1);
+ for (int i = 0; i < n; ++i) parent[i] = i;
+ }
+ int Parent(int x) {
+ if (x == parent[x]) return x;
+ int y = Parent(parent[x]);
+ parent[x] = y;
+ return y;
+ }
+ int Index(int x) { return indices[x]; }
+ int IndexToParent(int x) {return indices_to_parent[x]; };
+ void MergeFromTo(int x, int y) {
+ int px = Parent(x);
+ int py = Parent(y);
+ if (px == py) return;
+ rank[py] += rank[px];
+ parent[px] = py;
+ }
+ void Merge(int x, int y) {
+ int px = Parent(x);
+ int py = Parent(y);
+ if (px == py) return;
+ if (rank[px] < rank[py]) {
+ rank[py] += rank[px];
+ parent[px] = py;
+ } else {
+ rank[px] += rank[py];
+ parent[py] = px;
+ }
+ }
+
+ // renumber the root so that it is consecutive.
+ void BuildCompactParent() {
+ std::vector<int> compact_parent;
+ compact_parent.resize(parent.size());
+ compact_num = 0;
+ for (int i = 0; i < parent.size(); ++i) {
+ if (parent[i] == i) {
+ compact_parent[i] = compact_num++;
+ indices_to_parent.push_back(i);
+ }
+ }
+ indices.resize(parent.size());
+ for (int i = 0; i < parent.size(); ++i) {
+ indices[i] = compact_parent[Parent(i)];
+ }
+ }
+
+ int CompactNum() { return compact_num; }
+
+ int compact_num;
+ std::vector<int> parent;
+ std::vector<int> indices, indices_to_parent;
+ std::vector<int> rank;
+};
+
+class DisajointOrientTree {
+ public:
+ DisajointOrientTree() {}
+ DisajointOrientTree(int n) {
+ parent.resize(n);
+ rank.resize(n, 1);
+ for (int i = 0; i < n; ++i) parent[i] = std::make_pair(i, 0);
+ }
+ int Parent(int j) {
+ if (j == parent[j].first) return j;
+ int k = Parent(parent[j].first);
+ parent[j].second = (parent[j].second + parent[parent[j].first].second) % 4;
+ parent[j].first = k;
+ return k;
+ }
+ int Orient(int j) {
+ if (j == parent[j].first) return parent[j].second;
+ return (parent[j].second + Orient(parent[j].first)) % 4;
+ }
+ int Index(int x) { return indices[x]; }
+ void MergeFromTo(int v0, int v1, int orient0, int orient1) {
+ int p0 = Parent(v0);
+ int p1 = Parent(v1);
+ if (p0 == p1) return;
+ int orientp0 = Orient(v0);
+ int orientp1 = Orient(v1);
+
+ if (p0 == p1) {
+ return;
+ }
+ rank[p1] += rank[p0];
+ parent[p0].first = p1;
+ parent[p0].second = (orient0 - orient1 + orientp1 - orientp0 + 8) % 4;
+ }
+
+ void Merge(int v0, int v1, int orient0, int orient1) {
+ int p0 = Parent(v0);
+ int p1 = Parent(v1);
+ if (p0 == p1) {
+ return;
+ }
+ int orientp0 = Orient(v0);
+ int orientp1 = Orient(v1);
+
+ if (p0 == p1) {
+ return;
+ }
+ if (rank[p1] < rank[p0]) {
+ rank[p0] += rank[p1];
+ parent[p1].first = p0;
+ parent[p1].second = (orient1 - orient0 + orientp0 - orientp1 + 8) % 4;
+ } else {
+ rank[p1] += rank[p0];
+ parent[p0].first = p1;
+ parent[p0].second = (orient0 - orient1 + orientp1 - orientp0 + 8) % 4;
+ }
+ }
+ void BuildCompactParent() {
+ std::vector<int> compact_parent;
+ compact_parent.resize(parent.size());
+ compact_num = 0;
+ for (int i = 0; i < parent.size(); ++i) {
+ if (parent[i].first == i) {
+ compact_parent[i] = compact_num++;
+ }
+ }
+ indices.resize(parent.size());
+ for (int i = 0; i < parent.size(); ++i) {
+ indices[i] = compact_parent[Parent(i)];
+ }
+ }
+
+ int CompactNum() { return compact_num; }
+
+ int compact_num;
+ std::vector<std::pair<int, int>> parent;
+ std::vector<int> indices;
+ std::vector<int> rank;
+};
+
+} // namespace qflow
+
+#endif
diff --git a/extern/quadriflow/src/dset.hpp b/extern/quadriflow/src/dset.hpp
new file mode 100644
index 00000000000..f8e6f6da6b6
--- /dev/null
+++ b/extern/quadriflow/src/dset.hpp
@@ -0,0 +1,163 @@
+#if !defined(__UNIONFIND_H)
+#define __UNIONFIND_H
+
+#include <vector>
+#include <atomic>
+#include <iostream>
+
+namespace qflow {
+
+/**
+* Lock-free parallel disjoint set data structure (aka UNION-FIND)
+* with path compression and union by rank
+*
+* Supports concurrent find(), same() and unite() calls as described
+* in the paper
+*
+* "Wait-free Parallel Algorithms for the Union-Find Problem"
+* by Richard J. Anderson and Heather Woll
+*
+* In addition, this class supports optimistic locking (try_lock/unlock)
+* of disjoint sets and a combined unite+unlock operation.
+*
+* \author Wenzel Jakob
+*/
+class DisjointSets {
+public:
+ DisjointSets(uint32_t size) : mData(size) {
+ for (uint32_t i = 0; i<size; ++i)
+ mData[i] = (uint32_t)i;
+ }
+
+ uint32_t find(uint32_t id) const {
+ while (id != parent(id)) {
+ uint64_t value = mData[id];
+ uint32_t new_parent = parent((uint32_t)value);
+ uint64_t new_value =
+ (value & 0xFFFFFFFF00000000ULL) | new_parent;
+ /* Try to update parent (may fail, that's ok) */
+ if (value != new_value)
+ mData[id].compare_exchange_weak(value, new_value);
+ id = new_parent;
+ }
+ return id;
+ }
+
+ bool same(uint32_t id1, uint32_t id2) const {
+ for (;;) {
+ id1 = find(id1);
+ id2 = find(id2);
+ if (id1 == id2)
+ return true;
+ if (parent(id1) == id1)
+ return false;
+ }
+ }
+
+ uint32_t unite(uint32_t id1, uint32_t id2) {
+ for (;;) {
+ id1 = find(id1);
+ id2 = find(id2);
+
+ if (id1 == id2)
+ return id1;
+
+ uint32_t r1 = rank(id1), r2 = rank(id2);
+
+ if (r1 > r2 || (r1 == r2 && id1 < id2)) {
+ std::swap(r1, r2);
+ std::swap(id1, id2);
+ }
+
+ uint64_t oldEntry = ((uint64_t)r1 << 32) | id1;
+ uint64_t newEntry = ((uint64_t)r1 << 32) | id2;
+
+ if (!mData[id1].compare_exchange_strong(oldEntry, newEntry))
+ continue;
+
+ if (r1 == r2) {
+ oldEntry = ((uint64_t)r2 << 32) | id2;
+ newEntry = ((uint64_t)(r2 + 1) << 32) | id2;
+ /* Try to update the rank (may fail, that's ok) */
+ mData[id2].compare_exchange_weak(oldEntry, newEntry);
+ }
+
+ break;
+ }
+ return id2;
+ }
+
+ /**
+ * Try to lock the a disjoint union identified by one
+ * of its elements (this can occasionally fail when there
+ * are concurrent operations). The parameter 'id' will be
+ * updated to store the current representative ID of the
+ * union
+ */
+ bool try_lock(uint32_t &id) {
+ const uint64_t lock_flag = 1ULL << 63;
+ id = find(id);
+ uint64_t value = mData[id];
+ if ((value & lock_flag) || (uint32_t)value != id)
+ return false;
+ // On IA32/x64, a PAUSE instruction is recommended for CAS busy loops
+#if defined(__i386__) || defined(__amd64__)
+ __asm__ __volatile__("pause\n");
+#endif
+ return mData[id].compare_exchange_strong(value, value | lock_flag);
+ }
+
+ void unlock(uint32_t id) {
+ const uint64_t lock_flag = 1ULL << 63;
+ mData[id] &= ~lock_flag;
+ }
+
+ /**
+ * Return the representative index of the set that results from merging
+ * locked disjoint sets 'id1' and 'id2'
+ */
+ uint32_t unite_index_locked(uint32_t id1, uint32_t id2) const {
+ uint32_t r1 = rank(id1), r2 = rank(id2);
+ return (r1 > r2 || (r1 == r2 && id1 < id2)) ? id1 : id2;
+ }
+
+ /**
+ * Atomically unite two locked disjoint sets and unlock them. Assumes
+ * that here are no other concurrent unite() involving the same sets
+ */
+ uint32_t unite_unlock(uint32_t id1, uint32_t id2) {
+ uint32_t r1 = rank(id1), r2 = rank(id2);
+
+ if (r1 > r2 || (r1 == r2 && id1 < id2)) {
+ std::swap(r1, r2);
+ std::swap(id1, id2);
+ }
+
+ mData[id1] = ((uint64_t)r1 << 32) | id2;
+ mData[id2] = ((uint64_t)(r2 + ((r1 == r2) ? 1 : 0)) << 32) | id2;
+
+ return id2;
+ }
+
+ uint32_t size() const { return (uint32_t)mData.size(); }
+
+ uint32_t rank(uint32_t id) const {
+ return ((uint32_t)(mData[id] >> 32)) & 0x7FFFFFFFu;
+ }
+
+ uint32_t parent(uint32_t id) const {
+ return (uint32_t)mData[id];
+ }
+
+ friend std::ostream &operator<<(std::ostream &os, const DisjointSets &f) {
+ for (size_t i = 0; i<f.mData.size(); ++i)
+ os << i << ": parent=" << f.parent(i) << ", rank=" << f.rank(i) << std::endl;
+ return os;
+ }
+
+ mutable std::vector<std::atomic<uint64_t>> mData;
+};
+
+} // namespace qflow
+
+#endif /* __UNIONFIND_H */
diff --git a/extern/quadriflow/src/field-math.hpp b/extern/quadriflow/src/field-math.hpp
new file mode 100644
index 00000000000..86ed4b2b1f4
--- /dev/null
+++ b/extern/quadriflow/src/field-math.hpp
@@ -0,0 +1,483 @@
+#ifndef FIELD_MATH_H_
+#define FIELD_MATH_H_
+
+#ifdef WITH_CUDA
+# include <glm/glm.hpp>
+#endif
+#include <Eigen/Core>
+#include <Eigen/Dense>
+#include <algorithm>
+#include <vector>
+
+namespace qflow {
+
+using namespace Eigen;
+
+struct DEdge
+{
+ DEdge()
+ : x(0), y(0)
+ {}
+ DEdge(int _x, int _y) {
+ if (_x > _y)
+ x = _y, y = _x;
+ else
+ x = _x, y = _y;
+ }
+ bool operator<(const DEdge& e) const {
+ return (x < e.x) || (x == e.x && y < e.y);
+ }
+ bool operator==(const DEdge& e) const {
+ return x == e.x && y == e.y;
+ }
+ bool operator!=(const DEdge& e) const {
+ return x != e.x || y != e.y;
+ }
+ int x, y;
+};
+
+inline int get_parents(std::vector<std::pair<int, int>>& parents, int j) {
+ if (j == parents[j].first) return j;
+ int k = get_parents(parents, parents[j].first);
+ parents[j].second = (parents[j].second + parents[parents[j].first].second) % 4;
+ parents[j].first = k;
+ return k;
+}
+
+inline int get_parents_orient(std::vector<std::pair<int, int>>& parents, int j) {
+ if (j == parents[j].first) return parents[j].second;
+ return (parents[j].second + get_parents_orient(parents, parents[j].first)) % 4;
+}
+
+inline double fast_acos(double x) {
+ double negate = double(x < 0.0f);
+ x = std::abs(x);
+ double ret = -0.0187293f;
+ ret *= x;
+ ret = ret + 0.0742610f;
+ ret *= x;
+ ret = ret - 0.2121144f;
+ ret *= x;
+ ret = ret + 1.5707288f;
+ ret = ret * std::sqrt(1.0f - x);
+ ret = ret - 2.0f * negate * ret;
+ return negate * (double)M_PI + ret;
+}
+
+inline double signum(double value) { return std::copysign((double)1, value); }
+
+/// Always-positive modulo function (assumes b > 0)
+inline int modulo(int a, int b) {
+ int r = a % b;
+ return (r < 0) ? r + b : r;
+}
+
+inline Vector3d rotate90_by(const Vector3d &q, const Vector3d &n, int amount) {
+ return ((amount & 1) ? (n.cross(q)) : q) * (amount < 2 ? 1.0f : -1.0f);
+}
+
+inline Vector2i rshift90(Vector2i shift, int amount) {
+ if (amount & 1) shift = Vector2i(-shift.y(), shift.x());
+ if (amount >= 2) shift = -shift;
+ return shift;
+}
+
+inline std::pair<int, int> compat_orientation_extrinsic_index_4(const Vector3d &q0,
+ const Vector3d &n0,
+ const Vector3d &q1,
+ const Vector3d &n1) {
+ const Vector3d A[2] = {q0, n0.cross(q0)};
+ const Vector3d B[2] = {q1, n1.cross(q1)};
+
+ double best_score = -std::numeric_limits<double>::infinity();
+ int best_a = 0, best_b = 0;
+
+ for (int i = 0; i < 2; ++i) {
+ for (int j = 0; j < 2; ++j) {
+ double score = std::abs(A[i].dot(B[j]));
+ if (score > best_score) {
+ best_a = i;
+ best_b = j;
+ best_score = score;
+ }
+ }
+ }
+
+ if (A[best_a].dot(B[best_b]) < 0) best_b += 2;
+
+ return std::make_pair(best_a, best_b);
+}
+
+inline std::pair<Vector3d, Vector3d> compat_orientation_extrinsic_4(const Vector3d &q0,
+ const Vector3d &n0,
+ const Vector3d &q1,
+ const Vector3d &n1) {
+ const Vector3d A[2] = {q0, n0.cross(q0)};
+ const Vector3d B[2] = {q1, n1.cross(q1)};
+
+ double best_score = -std::numeric_limits<double>::infinity();
+ int best_a = 0, best_b = 0;
+
+ for (int i = 0; i < 2; ++i) {
+ for (int j = 0; j < 2; ++j) {
+ double score = std::abs(A[i].dot(B[j]));
+ if (score > best_score + 1e-6) {
+ best_a = i;
+ best_b = j;
+ best_score = score;
+ }
+ }
+ }
+
+ const double dp = A[best_a].dot(B[best_b]);
+ return std::make_pair(A[best_a], B[best_b] * signum(dp));
+}
+
+inline Vector3d middle_point(const Vector3d &p0, const Vector3d &n0, const Vector3d &p1,
+ const Vector3d &n1) {
+ /* How was this derived?
+ *
+ * Minimize \|x-p0\|^2 + \|x-p1\|^2, where
+ * dot(n0, x) == dot(n0, p0)
+ * dot(n1, x) == dot(n1, p1)
+ *
+ * -> Lagrange multipliers, set derivative = 0
+ * Use first 3 equalities to write x in terms of
+ * lambda_1 and lambda_2. Substitute that into the last
+ * two equations and solve for the lambdas. Finally,
+ * add a small epsilon term to avoid issues when n1=n2.
+ */
+ double n0p0 = n0.dot(p0), n0p1 = n0.dot(p1), n1p0 = n1.dot(p0), n1p1 = n1.dot(p1),
+ n0n1 = n0.dot(n1), denom = 1.0f / (1.0f - n0n1 * n0n1 + 1e-4f),
+ lambda_0 = 2.0f * (n0p1 - n0p0 - n0n1 * (n1p0 - n1p1)) * denom,
+ lambda_1 = 2.0f * (n1p0 - n1p1 - n0n1 * (n0p1 - n0p0)) * denom;
+
+ return 0.5f * (p0 + p1) - 0.25f * (n0 * lambda_0 + n1 * lambda_1);
+}
+
+inline Vector3d position_floor_4(const Vector3d &o, const Vector3d &q, const Vector3d &n,
+ const Vector3d &p, double scale_x, double scale_y,
+ double inv_scale_x, double inv_scale_y) {
+ Vector3d t = n.cross(q);
+ Vector3d d = p - o;
+ return o + q * std::floor(q.dot(d) * inv_scale_x) * scale_x +
+ t * std::floor(t.dot(d) * inv_scale_y) * scale_y;
+}
+
+inline std::pair<Vector3d, Vector3d> compat_position_extrinsic_4(
+ const Vector3d &p0, const Vector3d &n0, const Vector3d &q0, const Vector3d &o0,
+ const Vector3d &p1, const Vector3d &n1, const Vector3d &q1, const Vector3d &o1, double scale_x,
+ double scale_y, double inv_scale_x, double inv_scale_y, double scale_x_1, double scale_y_1,
+ double inv_scale_x_1, double inv_scale_y_1) {
+ Vector3d t0 = n0.cross(q0), t1 = n1.cross(q1);
+ Vector3d middle = middle_point(p0, n0, p1, n1);
+ Vector3d o0p =
+ position_floor_4(o0, q0, n0, middle, scale_x, scale_y, inv_scale_x, inv_scale_y);
+ Vector3d o1p =
+ position_floor_4(o1, q1, n1, middle, scale_x_1, scale_y_1, inv_scale_x_1, inv_scale_y_1);
+
+ double best_cost = std::numeric_limits<double>::infinity();
+ int best_i = -1, best_j = -1;
+
+ for (int i = 0; i < 4; ++i) {
+ Vector3d o0t = o0p + (q0 * (i & 1) * scale_x + t0 * ((i & 2) >> 1) * scale_y);
+ for (int j = 0; j < 4; ++j) {
+ Vector3d o1t = o1p + (q1 * (j & 1) * scale_x_1 + t1 * ((j & 2) >> 1) * scale_y_1);
+ double cost = (o0t - o1t).squaredNorm();
+
+ if (cost < best_cost) {
+ best_i = i;
+ best_j = j;
+ best_cost = cost;
+ }
+ }
+ }
+
+ return std::make_pair(
+ o0p + (q0 * (best_i & 1) * scale_x + t0 * ((best_i & 2) >> 1) * scale_y),
+ o1p + (q1 * (best_j & 1) * scale_x_1 + t1 * ((best_j & 2) >> 1) * scale_y_1));
+}
+
+inline Vector3d position_round_4(const Vector3d &o, const Vector3d &q, const Vector3d &n,
+ const Vector3d &p, double scale_x, double scale_y,
+ double inv_scale_x, double inv_scale_y) {
+ Vector3d t = n.cross(q);
+ Vector3d d = p - o;
+ return o + q * std::round(q.dot(d) * inv_scale_x) * scale_x +
+ t * std::round(t.dot(d) * inv_scale_y) * scale_y;
+}
+
+inline Vector2i position_floor_index_4(const Vector3d &o, const Vector3d &q, const Vector3d &n,
+ const Vector3d &p, double /* unused */, double /* unused */,
+ double inv_scale_x, double inv_scale_y) {
+ Vector3d t = n.cross(q);
+ Vector3d d = p - o;
+ return Vector2i((int)std::floor(q.dot(d) * inv_scale_x),
+ (int)std::floor(t.dot(d) * inv_scale_y));
+}
+
+inline std::pair<Vector2i, Vector2i> compat_position_extrinsic_index_4(
+ const Vector3d &p0, const Vector3d &n0, const Vector3d &q0, const Vector3d &o0,
+ const Vector3d &p1, const Vector3d &n1, const Vector3d &q1, const Vector3d &o1, double scale_x,
+ double scale_y, double inv_scale_x, double inv_scale_y, double scale_x_1, double scale_y_1,
+ double inv_scale_x_1, double inv_scale_y_1, double *error) {
+ Vector3d t0 = n0.cross(q0), t1 = n1.cross(q1);
+ Vector3d middle = middle_point(p0, n0, p1, n1);
+ Vector2i o0p =
+ position_floor_index_4(o0, q0, n0, middle, scale_x, scale_y, inv_scale_x, inv_scale_y);
+ Vector2i o1p = position_floor_index_4(o1, q1, n1, middle, scale_x_1, scale_y_1, inv_scale_x_1,
+ inv_scale_y_1);
+
+ double best_cost = std::numeric_limits<double>::infinity();
+ int best_i = -1, best_j = -1;
+
+ for (int i = 0; i < 4; ++i) {
+ Vector3d o0t =
+ o0 + (q0 * ((i & 1) + o0p[0]) * scale_x + t0 * (((i & 2) >> 1) + o0p[1]) * scale_y);
+ for (int j = 0; j < 4; ++j) {
+ Vector3d o1t = o1 + (q1 * ((j & 1) + o1p[0]) * scale_x_1 +
+ t1 * (((j & 2) >> 1) + o1p[1]) * scale_y_1);
+ double cost = (o0t - o1t).squaredNorm();
+
+ if (cost < best_cost) {
+ best_i = i;
+ best_j = j;
+ best_cost = cost;
+ }
+ }
+ }
+ if (error) *error = best_cost;
+
+ return std::make_pair(Vector2i((best_i & 1) + o0p[0], ((best_i & 2) >> 1) + o0p[1]),
+ Vector2i((best_j & 1) + o1p[0], ((best_j & 2) >> 1) + o1p[1]));
+}
+
+inline void coordinate_system(const Vector3d &a, Vector3d &b, Vector3d &c) {
+ if (std::abs(a.x()) > std::abs(a.y())) {
+ double invLen = 1.0f / std::sqrt(a.x() * a.x() + a.z() * a.z());
+ c = Vector3d(a.z() * invLen, 0.0f, -a.x() * invLen);
+ } else {
+ double invLen = 1.0f / std::sqrt(a.y() * a.y() + a.z() * a.z());
+ c = Vector3d(0.0f, a.z() * invLen, -a.y() * invLen);
+ }
+ b = c.cross(a);
+}
+
+inline Vector3d rotate_vector_into_plane(Vector3d q, const Vector3d &source_normal,
+ const Vector3d &target_normal) {
+ const double cosTheta = source_normal.dot(target_normal);
+ if (cosTheta < 0.9999f) {
+ if (cosTheta < -0.9999f) return -q;
+ Vector3d axis = source_normal.cross(target_normal);
+ q = q * cosTheta + axis.cross(q) +
+ axis * (axis.dot(q) * (1.0 - cosTheta) / axis.dot(axis));
+ }
+ return q;
+}
+
+inline Vector3d Travel(Vector3d p, const Vector3d &dir, double &len, int &f, VectorXi &E2E,
+ MatrixXd &V, MatrixXi &F, MatrixXd &NF,
+ std::vector<MatrixXd> &triangle_space, double *tx = 0, double *ty = 0) {
+ Vector3d N = NF.col(f);
+ Vector3d pt = (dir - dir.dot(N) * N).normalized();
+ int prev_id = -1;
+ int count = 0;
+ while (len > 0) {
+ count += 1;
+ Vector3d t1 = V.col(F(1, f)) - V.col(F(0, f));
+ Vector3d t2 = V.col(F(2, f)) - V.col(F(0, f));
+ Vector3d N = NF.col(f);
+ // printf("point dis: %f\n", (p - V.col(F(1, f))).dot(N));
+ int edge_id = f * 3;
+ double max_len = 1e30;
+ bool found = false;
+ int next_id, next_f;
+ Vector3d next_q;
+ Matrix3d m, n;
+ m.col(0) = t1;
+ m.col(1) = t2;
+ m.col(2) = N;
+ n = m.inverse();
+ MatrixXd &T = triangle_space[f];
+ VectorXd coord = T * Vector3d(p - V.col(F(0, f)));
+ VectorXd dirs = (T * pt);
+
+ double lens[3];
+ lens[0] = -coord.y() / dirs.y();
+ lens[1] = (1 - coord.x() - coord.y()) / (dirs.x() + dirs.y());
+ lens[2] = -coord.x() / dirs.x();
+ for (int fid = 0; fid < 3; ++fid) {
+ if (fid + edge_id == prev_id) continue;
+
+ if (lens[fid] >= 0 && lens[fid] < max_len) {
+ max_len = lens[fid];
+ next_id = E2E[edge_id + fid];
+ next_f = next_id;
+ if (next_f != -1) next_f /= 3;
+ found = true;
+ }
+ }
+ if (!found) {
+ printf("error...\n");
+ exit(0);
+ }
+ // printf("status: %f %f %d\n", len, max_len, f);
+ if (max_len >= len) {
+ if (tx && ty) {
+ *tx = coord.x() + dirs.x() * len;
+ *ty = coord.y() + dirs.y() * len;
+ }
+ p = p + len * pt;
+ len = 0;
+ return p;
+ }
+ p = V.col(F(0, f)) + t1 * (coord.x() + dirs.x() * max_len) +
+ t2 * (coord.y() + dirs.y() * max_len);
+ len -= max_len;
+ if (next_f == -1) {
+ if (tx && ty) {
+ *tx = coord.x() + dirs.x() * max_len;
+ *ty = coord.y() + dirs.y() * max_len;
+ }
+ return p;
+ }
+ pt = rotate_vector_into_plane(pt, NF.col(f), NF.col(next_f));
+ f = next_f;
+ prev_id = next_id;
+ }
+ return p;
+}
+inline Vector3d TravelField(Vector3d p, Vector3d &pt, double &len, int &f, VectorXi &E2E,
+ MatrixXd &V, MatrixXi &F, MatrixXd &NF, MatrixXd &QF, MatrixXd &QV,
+ MatrixXd &NV, std::vector<MatrixXd> &triangle_space, double *tx = 0,
+ double *ty = 0, Vector3d *dir_unfold = 0) {
+ Vector3d N = NF.col(f);
+ pt = (pt - pt.dot(N) * N).normalized();
+ int prev_id = -1;
+ int count = 0;
+ std::vector<Vector3d> Ns;
+
+ auto FaceQFromVertices = [&](int f, double tx, double ty) {
+ const Vector3d &n = NF.col(f);
+ const Vector3d &q_1 = QV.col(F(0, f)), &q_2 = QV.col(F(1, f)), &q_3 = QV.col(F(2, f));
+ const Vector3d &n_1 = NV.col(F(0, f)), &n_2 = NV.col(F(1, f)), &n_3 = NV.col(F(2, f));
+ Vector3d q_1n = rotate_vector_into_plane(q_1, n_1, n);
+ Vector3d q_2n = rotate_vector_into_plane(q_2, n_2, n);
+ Vector3d q_3n = rotate_vector_into_plane(q_3, n_3, n);
+ auto orient = compat_orientation_extrinsic_4(q_1n, n, q_2n, n);
+ Vector3d q = (orient.first * tx + orient.second * ty).normalized();
+ orient = compat_orientation_extrinsic_4(q, n, q_3n, n);
+ q = (orient.first * (tx + ty) + orient.second * (1 - tx - ty)).normalized();
+ return q;
+ };
+
+ auto BestQFromGivenQ = [&](const Vector3d &n, const Vector3d &q, const Vector3d &given_q) {
+ Vector3d q_1 = n.cross(q);
+ double t1 = q.dot(given_q);
+ double t2 = q_1.dot(given_q);
+ if (fabs(t1) > fabs(t2)) {
+ if (t1 > 0.0)
+ return Vector3d(q);
+ else
+ return Vector3d(-q);
+ } else {
+ if (t2 > 0.0)
+ return Vector3d(q_1);
+ else
+ return Vector3d(-q_1);
+ }
+ };
+
+ while (len > 0) {
+ count += 1;
+ Vector3d t1 = V.col(F(1, f)) - V.col(F(0, f));
+ Vector3d t2 = V.col(F(2, f)) - V.col(F(0, f));
+ Vector3d N = NF.col(f);
+ Ns.push_back(N);
+ // printf("point dis: %f\n", (p - V.col(F(1, f))).dot(N));
+ int edge_id = f * 3;
+ double max_len = 1e30;
+ bool found = false;
+ int next_id = -1, next_f = -1;
+ Vector3d next_q;
+ Matrix3d m, n;
+ m.col(0) = t1;
+ m.col(1) = t2;
+ m.col(2) = N;
+ n = m.inverse();
+ MatrixXd &T = triangle_space[f];
+ VectorXd coord = T * Vector3d(p - V.col(F(0, f)));
+ VectorXd dirs = (T * pt);
+ double lens[3];
+ lens[0] = -coord.y() / dirs.y();
+ lens[1] = (1 - coord.x() - coord.y()) / (dirs.x() + dirs.y());
+ lens[2] = -coord.x() / dirs.x();
+ for (int fid = 0; fid < 3; ++fid) {
+ if (fid + edge_id == prev_id) continue;
+
+ if (lens[fid] >= 0 && lens[fid] < max_len) {
+ max_len = lens[fid];
+ next_id = E2E[edge_id + fid];
+ next_f = next_id;
+ if (next_f != -1) next_f /= 3;
+ found = true;
+ }
+ }
+ double w1 = (coord.x() + dirs.x() * max_len);
+ double w2 = (coord.y() + dirs.y() * max_len);
+ if (w1 < 0) w1 = 0.0f;
+ if (w2 < 0) w2 = 0.0f;
+ if (w1 + w2 > 1) {
+ double w = w1 + w2;
+ w1 /= w;
+ w2 /= w;
+ }
+
+ if (!found) {
+ printf("error...\n");
+ exit(0);
+ }
+ // printf("status: %f %f %d\n", len, max_len, f);
+ if (max_len >= len) {
+ if (tx && ty) {
+ *tx = w1;
+ *ty = w2;
+ }
+ Vector3d ideal_q = FaceQFromVertices(f, *tx, *ty);
+ *dir_unfold = BestQFromGivenQ(NF.col(f), ideal_q, *dir_unfold);
+ for (int i = Ns.size() - 1; i > 0; --i) {
+ *dir_unfold = rotate_vector_into_plane(*dir_unfold, Ns[i], Ns[i - 1]);
+ }
+ p = p + len * pt;
+ len = 0;
+ return p;
+ }
+ p = V.col(F(0, f)) + t1 * w1 + t2 * w2;
+ len -= max_len;
+ if (next_f == -1) {
+ if (tx && ty) {
+ *tx = w1;
+ *ty = w2;
+ }
+ Vector3d ideal_q = FaceQFromVertices(f, *tx, *ty);
+ *dir_unfold = BestQFromGivenQ(NF.col(f), ideal_q, *dir_unfold);
+ for (int i = Ns.size() - 1; i > 0; --i) {
+ *dir_unfold = rotate_vector_into_plane(*dir_unfold, Ns[i], Ns[i - 1]);
+ }
+ return p;
+ }
+ pt = rotate_vector_into_plane(pt, NF.col(f), NF.col(next_f));
+ // pt = BestQFromGivenQ(NF.col(next_f), QF.col(next_f), pt);
+ if (dir_unfold) {
+ *dir_unfold = BestQFromGivenQ(NF.col(next_f), QF.col(next_f), *dir_unfold);
+ }
+ f = next_f;
+ prev_id = next_id;
+ }
+
+ return p;
+}
+
+} // namespace qflow
+
+#endif
diff --git a/extern/quadriflow/src/flow.hpp b/extern/quadriflow/src/flow.hpp
new file mode 100644
index 00000000000..ab4a01cb4ed
--- /dev/null
+++ b/extern/quadriflow/src/flow.hpp
@@ -0,0 +1,375 @@
+#ifndef FLOW_H_
+#define FLOW_H_
+
+#include <Eigen/Core>
+#include <list>
+#include <map>
+#include <vector>
+
+#include "config.hpp"
+
+#include <boost/graph/adjacency_list.hpp>
+#include <boost/graph/boykov_kolmogorov_max_flow.hpp>
+#include <boost/graph/edmonds_karp_max_flow.hpp>
+#include <boost/graph/push_relabel_max_flow.hpp>
+
+#include <lemon/network_simplex.h>
+#include <lemon/preflow.h>
+#include <lemon/smart_graph.h>
+
+using namespace boost;
+using namespace Eigen;
+
+namespace qflow {
+
+class MaxFlowHelper {
+ public:
+ MaxFlowHelper() {}
+ virtual ~MaxFlowHelper(){};
+ virtual void resize(int n, int m) = 0;
+ virtual void addEdge(int x, int y, int c, int rc, int v, int cost = 1) = 0;
+ virtual int compute() = 0;
+ virtual void applyTo(std::vector<Vector2i>& edge_diff) = 0;
+};
+
+class BoykovMaxFlowHelper : public MaxFlowHelper {
+ public:
+ typedef int EdgeWeightType;
+ typedef adjacency_list_traits<vecS, vecS, directedS> Traits;
+ // clang-format off
+ typedef adjacency_list < vecS, vecS, directedS,
+ property < vertex_name_t, std::string,
+ property < vertex_index_t, long,
+ property < vertex_color_t, boost::default_color_type,
+ property < vertex_distance_t, long,
+ property < vertex_predecessor_t, Traits::edge_descriptor > > > > >,
+
+ property < edge_capacity_t, EdgeWeightType,
+ property < edge_residual_capacity_t, EdgeWeightType,
+ property < edge_reverse_t, Traits::edge_descriptor > > > > Graph;
+ // clang-format on
+
+ public:
+ BoykovMaxFlowHelper() { rev = get(edge_reverse, g); }
+ void resize(int n, int m) {
+ vertex_descriptors.resize(n);
+ for (int i = 0; i < n; ++i) vertex_descriptors[i] = add_vertex(g);
+ }
+ int compute() {
+ EdgeWeightType flow =
+ boykov_kolmogorov_max_flow(g, vertex_descriptors.front(), vertex_descriptors.back());
+ return flow;
+ }
+ void addDirectEdge(Traits::vertex_descriptor& v1, Traits::vertex_descriptor& v2,
+ property_map<Graph, edge_reverse_t>::type& rev, const int capacity,
+ const int inv_capacity, Graph& g, Traits::edge_descriptor& e1,
+ Traits::edge_descriptor& e2) {
+ e1 = add_edge(v1, v2, g).first;
+ e2 = add_edge(v2, v1, g).first;
+ put(edge_capacity, g, e1, capacity);
+ put(edge_capacity, g, e2, inv_capacity);
+
+ rev[e1] = e2;
+ rev[e2] = e1;
+ }
+ void addEdge(int x, int y, int c, int rc, int v, int cost = 1) {
+ Traits::edge_descriptor e1, e2;
+ addDirectEdge(vertex_descriptors[x], vertex_descriptors[y], rev, c, rc, g, e1, e2);
+ if (v != -1) {
+ edge_to_variables[e1] = std::make_pair(v, -1);
+ edge_to_variables[e2] = std::make_pair(v, 1);
+ }
+ }
+ void applyTo(std::vector<Vector2i>& edge_diff) {
+ property_map<Graph, edge_capacity_t>::type capacity = get(edge_capacity, g);
+ property_map<Graph, edge_residual_capacity_t>::type residual_capacity =
+ get(edge_residual_capacity, g);
+
+ graph_traits<Graph>::vertex_iterator u_iter, u_end;
+ graph_traits<Graph>::out_edge_iterator ei, e_end;
+ for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter)
+ for (tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei)
+ if (capacity[*ei] > 0) {
+ int flow = (capacity[*ei] - residual_capacity[*ei]);
+ if (flow > 0) {
+ auto it = edge_to_variables.find(*ei);
+ if (it != edge_to_variables.end()) {
+ edge_diff[it->second.first / 2][it->second.first % 2] +=
+ it->second.second * flow;
+ }
+ }
+ }
+ }
+
+ private:
+ Graph g;
+ property_map<Graph, edge_reverse_t>::type rev;
+ std::vector<Traits::vertex_descriptor> vertex_descriptors;
+ std::map<Traits::edge_descriptor, std::pair<int, int>> edge_to_variables;
+};
+
+class NetworkSimplexFlowHelper : public MaxFlowHelper {
+ public:
+ using Weight = int;
+ using Capacity = int;
+ using Graph = lemon::SmartDigraph;
+ using Node = Graph::Node;
+ using Arc = Graph::Arc;
+ template <typename ValueType>
+ using ArcMap = lemon::SmartDigraph::ArcMap<ValueType>;
+ using Preflow = lemon::Preflow<lemon::SmartDigraph, ArcMap<Capacity>>;
+ using NetworkSimplex = lemon::NetworkSimplex<lemon::SmartDigraph, Capacity, Weight>;
+
+ public:
+ NetworkSimplexFlowHelper() : cost(graph), capacity(graph), flow(graph), variable(graph) {}
+ ~NetworkSimplexFlowHelper(){};
+ void resize(int n, int m) {
+ nodes.reserve(n);
+ for (int i = 0; i < n; ++i) nodes.push_back(graph.addNode());
+ }
+ void addEdge(int x, int y, int c, int rc, int v, int cst = 1) {
+ assert(x >= 0);
+ assert(v >= -1);
+ if (c) {
+ auto e1 = graph.addArc(nodes[x], nodes[y]);
+ cost[e1] = cst;
+ capacity[e1] = c;
+ variable[e1] = std::make_pair(v, 1);
+ }
+
+ if (rc) {
+ auto e2 = graph.addArc(nodes[y], nodes[x]);
+ cost[e2] = cst;
+ capacity[e2] = rc;
+ variable[e2] = std::make_pair(v, -1);
+ }
+ }
+ int compute() {
+ Preflow pf(graph, capacity, nodes.front(), nodes.back());
+ NetworkSimplex ns(graph);
+
+ // Run preflow to find maximum flow
+ lprintf("push-relabel flow... ");
+ pf.runMinCut();
+ int maxflow = pf.flowValue();
+
+ // Run network simplex to find minimum cost maximum flow
+ ns.costMap(cost).upperMap(capacity).stSupply(nodes.front(), nodes.back(), maxflow);
+ auto status = ns.run();
+ switch (status) {
+ case NetworkSimplex::OPTIMAL:
+ ns.flowMap(flow);
+ break;
+ case NetworkSimplex::INFEASIBLE:
+ lputs("NetworkSimplex::INFEASIBLE");
+ assert(0);
+ break;
+ default:
+ lputs("Unknown: NetworkSimplex::Default");
+ assert(0);
+ break;
+ }
+
+ return maxflow;
+ }
+ void applyTo(std::vector<Vector2i>& edge_diff) {
+ for (Graph::ArcIt e(graph); e != lemon::INVALID; ++e) {
+ int var = variable[e].first;
+ if (var == -1) continue;
+ int sgn = variable[e].second;
+ edge_diff[var / 2][var % 2] -= sgn * flow[e];
+ }
+ }
+
+ private:
+ Graph graph;
+ ArcMap<Weight> cost;
+ ArcMap<Capacity> capacity;
+ ArcMap<Capacity> flow;
+ ArcMap<std::pair<int, int>> variable;
+ std::vector<Node> nodes;
+ std::vector<Arc> edges;
+};
+
+#ifdef WITH_GUROBI
+
+#include <gurobi_c++.h>
+
+class GurobiFlowHelper : public MaxFlowHelper {
+ public:
+ GurobiFlowHelper() {}
+ virtual ~GurobiFlowHelper(){};
+ virtual void resize(int n, int m) {
+ nodes.resize(n * 2);
+ edges.resize(m);
+ }
+ virtual void addEdge(int x, int y, int c, int rc, int v, int cost = 1) {
+ nodes[x * 2 + 0].push_back(vars.size());
+ nodes[y * 2 + 1].push_back(vars.size());
+ vars.push_back(model.addVar(0, c, 0, GRB_INTEGER));
+ edges.push_back(std::make_pair(v, 1));
+
+ nodes[y * 2 + 0].push_back(vars.size());
+ nodes[x * 2 + 1].push_back(vars.size());
+ vars.push_back(model.addVar(0, rc, 0, GRB_INTEGER));
+ edges.push_back(std::make_pair(v, -1));
+ }
+ virtual int compute() {
+ std::cerr << "compute" << std::endl;
+ int ns = nodes.size() / 2;
+
+ int flow;
+ for (int i = 1; i < ns - 1; ++i) {
+ GRBLinExpr cons = 0;
+ for (auto n : nodes[2 * i + 0]) cons += vars[n];
+ for (auto n : nodes[2 * i + 1]) cons -= vars[n];
+ model.addConstr(cons == 0);
+ }
+
+ // first pass, maximum flow
+ GRBLinExpr outbound = 0;
+ {
+ lprintf("first pass\n");
+ for (auto& n : nodes[0]) outbound += vars[n];
+ for (auto& n : nodes[1]) outbound -= vars[n];
+ model.setObjective(outbound, GRB_MAXIMIZE);
+ model.optimize();
+
+ flow = (int)model.get(GRB_DoubleAttr_ObjVal);
+ lprintf("Gurobi result: %d\n", flow);
+ }
+
+ // second pass, minimum cost flow
+ {
+ lprintf("second pass\n");
+ model.addConstr(outbound == flow);
+ GRBLinExpr cost = 0;
+ for (auto& v : vars) cost += v;
+ model.setObjective(cost, GRB_MINIMIZE);
+ model.optimize();
+
+ double optimal_cost = (int)model.get(GRB_DoubleAttr_ObjVal);
+ lprintf("Gurobi result: %.3f\n", optimal_cost);
+ }
+ return flow;
+ }
+ virtual void applyTo(std::vector<Vector2i>& edge_diff) { assert(0); };
+
+ private:
+ GRBEnv env = GRBEnv();
+ GRBModel model = GRBModel(env);
+ std::vector<GRBVar> vars;
+ std::vector<std::pair<int, int>> edges;
+ std::vector<std::vector<int>> nodes;
+};
+
+#endif
+
+class ECMaxFlowHelper : public MaxFlowHelper {
+ public:
+ struct FlowInfo {
+ int id;
+ int capacity, flow;
+ int v, d;
+ FlowInfo* rev;
+ };
+ struct SearchInfo {
+ SearchInfo(int _id, int _prev_id, FlowInfo* _info)
+ : id(_id), prev_id(_prev_id), info(_info) {}
+ int id;
+ int prev_id;
+ FlowInfo* info;
+ };
+ ECMaxFlowHelper() { num = 0; }
+ int num;
+ std::vector<FlowInfo*> variable_to_edge;
+ void resize(int n, int m) {
+ graph.resize(n);
+ variable_to_edge.resize(m, 0);
+ num = n;
+ }
+ void addEdge(int x, int y, int c, int rc, int v, int cost = 0) {
+ FlowInfo flow;
+ flow.id = y;
+ flow.capacity = c;
+ flow.flow = 0;
+ flow.v = v;
+ flow.d = -1;
+ graph[x].push_back(flow);
+ auto& f1 = graph[x].back();
+ flow.id = x;
+ flow.capacity = rc;
+ flow.flow = 0;
+ flow.v = v;
+ flow.d = 1;
+ graph[y].push_back(flow);
+ auto& f2 = graph[y].back();
+ f2.rev = &f1;
+ f1.rev = &f2;
+ }
+ int compute() {
+ int total_flow = 0;
+ int count = 0;
+ while (true) {
+ count += 1;
+ std::vector<int> vhash(num, 0);
+ std::vector<SearchInfo> q;
+ q.push_back(SearchInfo(0, -1, 0));
+ vhash[0] = 1;
+ int q_front = 0;
+ bool found = false;
+ while (q_front < q.size()) {
+ int vert = q[q_front].id;
+ for (auto& l : graph[vert]) {
+ if (vhash[l.id] || l.capacity <= l.flow) continue;
+ q.push_back(SearchInfo(l.id, q_front, &l));
+ vhash[l.id] = 1;
+ if (l.id == num - 1) {
+ found = true;
+ break;
+ }
+ }
+ if (found) break;
+ q_front += 1;
+ }
+ if (q_front == q.size()) break;
+ int loc = q.size() - 1;
+ while (q[loc].prev_id != -1) {
+ q[loc].info->flow += 1;
+ q[loc].info->rev->flow -= 1;
+ loc = q[loc].prev_id;
+ // int prev_v = q[loc].id;
+ // applyFlow(prev_v, current_v, 1);
+ // applyFlow(current_v, prev_v, -1);
+ }
+ total_flow += 1;
+ }
+ return total_flow;
+ }
+ void applyTo(std::vector<Vector2i>& edge_diff) {
+ for (int i = 0; i < graph.size(); ++i) {
+ for (auto& flow : graph[i]) {
+ if (flow.flow > 0 && flow.v != -1) {
+ if (flow.flow > 0) {
+ edge_diff[flow.v / 2][flow.v % 2] += flow.d * flow.flow;
+ if (abs(edge_diff[flow.v / 2][flow.v % 2]) > 2) {
+ }
+ }
+ }
+ }
+ }
+ }
+ void applyFlow(int v1, int v2, int flow) {
+ for (auto& it : graph[v1]) {
+ if (it.id == v2) {
+ it.flow += flow;
+ break;
+ }
+ }
+ }
+ std::vector<std::list<FlowInfo>> graph;
+};
+
+} // namespace qflow
+
+#endif
diff --git a/extern/quadriflow/src/hierarchy.cpp b/extern/quadriflow/src/hierarchy.cpp
new file mode 100644
index 00000000000..c333256a139
--- /dev/null
+++ b/extern/quadriflow/src/hierarchy.cpp
@@ -0,0 +1,1343 @@
+#include "hierarchy.hpp"
+#include <fstream>
+#include <algorithm>
+#include <unordered_map>
+#include "config.hpp"
+#include "field-math.hpp"
+#include <queue>
+#include "localsat.hpp"
+#include "pcg32/pcg32.h"
+#ifdef WITH_TBB
+# include "tbb/tbb.h"
+# include "pss/parallel_stable_sort.h"
+#endif
+
+namespace qflow {
+
+Hierarchy::Hierarchy() {
+ mAdj.resize(MAX_DEPTH + 1);
+ mV.resize(MAX_DEPTH + 1);
+ mN.resize(MAX_DEPTH + 1);
+ mA.resize(MAX_DEPTH + 1);
+ mPhases.resize(MAX_DEPTH + 1);
+ mToLower.resize(MAX_DEPTH);
+ mToUpper.resize(MAX_DEPTH);
+ rng_seed = 0;
+
+ mCQ.reserve(MAX_DEPTH + 1);
+ mCQw.reserve(MAX_DEPTH + 1);
+ mCO.reserve(MAX_DEPTH + 1);
+ mCOw.reserve(MAX_DEPTH + 1);
+}
+
+#undef max
+
+void Hierarchy::Initialize(double scale, int with_scale) {
+ this->with_scale = with_scale;
+ generate_graph_coloring_deterministic(mAdj[0], mV[0].cols(), mPhases[0]);
+
+ for (int i = 0; i < MAX_DEPTH; ++i) {
+ DownsampleGraph(mAdj[i], mV[i], mN[i], mA[i], mV[i + 1], mN[i + 1], mA[i + 1], mToUpper[i],
+ mToLower[i], mAdj[i + 1]);
+ generate_graph_coloring_deterministic(mAdj[i + 1], mV[i + 1].cols(), mPhases[i + 1]);
+ if (mV[i + 1].cols() == 1) {
+ mAdj.resize(i + 2);
+ mV.resize(i + 2);
+ mN.resize(i + 2);
+ mA.resize(i + 2);
+ mToUpper.resize(i + 1);
+ mToLower.resize(i + 1);
+ break;
+ }
+ }
+ mQ.resize(mV.size());
+ mO.resize(mV.size());
+ mS.resize(mV.size());
+ mK.resize(mV.size());
+
+ mCO.resize(mV.size());
+ mCOw.resize(mV.size());
+ mCQ.resize(mV.size());
+ mCQw.resize(mV.size());
+
+ //Set random seed
+ srand(rng_seed);
+
+ mScale = scale;
+ for (int i = 0; i < mV.size(); ++i) {
+ mQ[i].resize(mN[i].rows(), mN[i].cols());
+ mO[i].resize(mN[i].rows(), mN[i].cols());
+ mS[i].resize(2, mN[i].cols());
+ mK[i].resize(2, mN[i].cols());
+ for (int j = 0; j < mN[i].cols(); ++j) {
+ Vector3d s, t;
+ coordinate_system(mN[i].col(j), s, t);
+ //rand() is not thread safe!
+ double angle = ((double)rand()) / RAND_MAX * 2 * M_PI;
+ double x = ((double)rand()) / RAND_MAX * 2 - 1.f;
+ double y = ((double)rand()) / RAND_MAX * 2 - 1.f;
+ mQ[i].col(j) = s * std::cos(angle) + t * std::sin(angle);
+ mO[i].col(j) = mV[i].col(j) + (s * x + t * y) * scale;
+ if (with_scale) {
+ mS[i].col(j) = Vector2d(1.0f, 1.0f);
+ mK[i].col(j) = Vector2d(0.0, 0.0);
+ }
+ }
+ }
+#ifdef WITH_CUDA
+ printf("copy to device...\n");
+ CopyToDevice();
+ printf("copy to device finish...\n");
+#endif
+}
+
+#ifdef WITH_TBB
+void Hierarchy::generate_graph_coloring_deterministic(const AdjacentMatrix& adj, int size,
+ std::vector<std::vector<int>>& phases) {
+ struct ColorData {
+ uint8_t nColors;
+ uint32_t nNodes[256];
+ ColorData() : nColors(0) {}
+ };
+
+ const uint8_t INVALID_COLOR = 0xFF;
+ phases.clear();
+
+ /* Generate a permutation */
+ std::vector<uint32_t> perm(size);
+ std::vector<tbb::spin_mutex> mutex(size);
+ for (uint32_t i = 0; i < size; ++i) perm[i] = i;
+
+ tbb::parallel_for(tbb::blocked_range<uint32_t>(0u, size, GRAIN_SIZE),
+ [&](const tbb::blocked_range<uint32_t>& range) {
+ pcg32 rng;
+ rng.advance(range.begin());
+ for (uint32_t i = range.begin(); i != range.end(); ++i) {
+ uint32_t j = i, k = rng.nextUInt(size - i) + i;
+ if (j == k) continue;
+ if (j > k) std::swap(j, k);
+ tbb::spin_mutex::scoped_lock l0(mutex[j]);
+ tbb::spin_mutex::scoped_lock l1(mutex[k]);
+ std::swap(perm[j], perm[k]);
+ }
+ });
+
+ std::vector<uint8_t> color(size, INVALID_COLOR);
+ ColorData colorData = tbb::parallel_reduce(
+ tbb::blocked_range<uint32_t>(0u, size, GRAIN_SIZE), ColorData(),
+ [&](const tbb::blocked_range<uint32_t>& range, ColorData colorData) -> ColorData {
+ std::vector<uint32_t> neighborhood;
+ bool possible_colors[256];
+
+ for (uint32_t pidx = range.begin(); pidx != range.end(); ++pidx) {
+ uint32_t i = perm[pidx];
+
+ neighborhood.clear();
+ neighborhood.push_back(i);
+ // for (const Link *link = adj[i]; link != adj[i + 1]; ++link)
+ for (auto& link : adj[i]) neighborhood.push_back(link.id);
+ std::sort(neighborhood.begin(), neighborhood.end());
+ for (uint32_t j : neighborhood) mutex[j].lock();
+
+ std::fill(possible_colors, possible_colors + colorData.nColors, true);
+
+ // for (const Link *link = adj[i]; link != adj[i + 1]; ++link) {
+ for (auto& link : adj[i]) {
+ uint8_t c = color[link.id];
+ if (c != INVALID_COLOR) {
+ while (c >= colorData.nColors) {
+ possible_colors[colorData.nColors] = true;
+ colorData.nNodes[colorData.nColors] = 0;
+ colorData.nColors++;
+ }
+ possible_colors[c] = false;
+ }
+ }
+
+ uint8_t chosen_color = INVALID_COLOR;
+ for (uint8_t j = 0; j < colorData.nColors; ++j) {
+ if (possible_colors[j]) {
+ chosen_color = j;
+ break;
+ }
+ }
+ if (chosen_color == INVALID_COLOR) {
+ if (colorData.nColors == INVALID_COLOR - 1)
+ throw std::runtime_error(
+ "Ran out of colors during graph coloring! "
+ "The input mesh is very likely corrupt.");
+ colorData.nNodes[colorData.nColors] = 1;
+ color[i] = colorData.nColors++;
+ } else {
+ colorData.nNodes[chosen_color]++;
+ color[i] = chosen_color;
+ }
+
+ for (uint32_t j : neighborhood) mutex[j].unlock();
+ }
+ return colorData;
+ },
+ [](ColorData c1, ColorData c2) -> ColorData {
+ ColorData result;
+ result.nColors = std::max(c1.nColors, c2.nColors);
+ memset(result.nNodes, 0, sizeof(uint32_t) * result.nColors);
+ for (uint8_t i = 0; i < c1.nColors; ++i) result.nNodes[i] += c1.nNodes[i];
+ for (uint8_t i = 0; i < c2.nColors; ++i) result.nNodes[i] += c2.nNodes[i];
+ return result;
+ });
+
+ phases.resize(colorData.nColors);
+ for (int i = 0; i < colorData.nColors; ++i) phases[i].reserve(colorData.nNodes[i]);
+
+ for (uint32_t i = 0; i < size; ++i) phases[color[i]].push_back(i);
+}
+#else
+void Hierarchy::generate_graph_coloring_deterministic(const AdjacentMatrix& adj, int size,
+ std::vector<std::vector<int>>& phases) {
+ phases.clear();
+
+ std::vector<uint32_t> perm(size);
+ for (uint32_t i = 0; i < size; ++i) perm[i] = i;
+ pcg32 rng;
+ rng.shuffle(perm.begin(), perm.end());
+
+ std::vector<int> color(size, -1);
+ std::vector<uint8_t> possible_colors;
+ std::vector<int> size_per_color;
+ int ncolors = 0;
+
+ for (uint32_t i = 0; i < size; ++i) {
+ uint32_t ip = perm[i];
+
+ std::fill(possible_colors.begin(), possible_colors.end(), 1);
+
+ for (auto& link : adj[ip]) {
+ int c = color[link.id];
+ if (c >= 0) possible_colors[c] = 0;
+ }
+
+ int chosen_color = -1;
+ for (uint32_t j = 0; j < possible_colors.size(); ++j) {
+ if (possible_colors[j]) {
+ chosen_color = j;
+ break;
+ }
+ }
+
+ if (chosen_color < 0) {
+ chosen_color = ncolors++;
+ possible_colors.resize(ncolors);
+ size_per_color.push_back(0);
+ }
+
+ color[ip] = chosen_color;
+ size_per_color[chosen_color]++;
+ }
+ phases.resize(ncolors);
+ for (int i = 0; i < ncolors; ++i) phases[i].reserve(size_per_color[i]);
+ for (uint32_t i = 0; i < size; ++i) phases[color[i]].push_back(i);
+}
+#endif
+
+void Hierarchy::DownsampleGraph(const AdjacentMatrix adj, const MatrixXd& V, const MatrixXd& N,
+ const VectorXd& A, MatrixXd& V_p, MatrixXd& N_p, VectorXd& A_p,
+ MatrixXi& to_upper, VectorXi& to_lower, AdjacentMatrix& adj_p) {
+ struct Entry {
+ int i, j;
+ double order;
+ inline Entry() { i = j = -1; };
+ inline Entry(int i, int j, double order) : i(i), j(j), order(order) {}
+ inline bool operator<(const Entry& e) const { return order > e.order; }
+ inline bool operator==(const Entry& e) const { return order == e.order; }
+ };
+
+ int nLinks = 0;
+ for (auto& adj_i : adj) nLinks += adj_i.size();
+ std::vector<Entry> entries(nLinks);
+ std::vector<int> bases(adj.size());
+ for (int i = 1; i < bases.size(); ++i) {
+ bases[i] = bases[i - 1] + adj[i - 1].size();
+ }
+
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int i = 0; i < V.cols(); ++i) {
+ int base = bases[i];
+ auto& ad = adj[i];
+ auto entry_it = entries.begin() + base;
+ for (auto it = ad.begin(); it != ad.end(); ++it, ++entry_it) {
+ int k = it->id;
+ double dp = N.col(i).dot(N.col(k));
+ double ratio = A[i] > A[k] ? (A[i] / A[k]) : (A[k] / A[i]);
+ *entry_it = Entry(i, k, dp * ratio);
+ }
+ }
+
+#ifdef WITH_TBB
+ pss::parallel_stable_sort(entries.begin(), entries.end(), std::less<Entry>());
+#else
+ std::stable_sort(entries.begin(), entries.end(), std::less<Entry>());
+#endif
+
+ std::vector<bool> mergeFlag(V.cols(), false);
+
+ int nCollapsed = 0;
+ for (int i = 0; i < nLinks; ++i) {
+ const Entry& e = entries[i];
+ if (mergeFlag[e.i] || mergeFlag[e.j]) continue;
+ mergeFlag[e.i] = mergeFlag[e.j] = true;
+ entries[nCollapsed++] = entries[i];
+ }
+ int vertexCount = V.cols() - nCollapsed;
+
+ // Allocate memory for coarsened graph
+ V_p.resize(3, vertexCount);
+ N_p.resize(3, vertexCount);
+ A_p.resize(vertexCount);
+ to_upper.resize(2, vertexCount);
+ to_lower.resize(V.cols());
+
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int i = 0; i < nCollapsed; ++i) {
+ const Entry& e = entries[i];
+ const double area1 = A[e.i], area2 = A[e.j], surfaceArea = area1 + area2;
+ if (surfaceArea > RCPOVERFLOW)
+ V_p.col(i) = (V.col(e.i) * area1 + V.col(e.j) * area2) / surfaceArea;
+ else
+ V_p.col(i) = (V.col(e.i) + V.col(e.j)) * 0.5f;
+ Vector3d normal = N.col(e.i) * area1 + N.col(e.j) * area2;
+ double norm = normal.norm();
+ N_p.col(i) = norm > RCPOVERFLOW ? Vector3d(normal / norm) : Vector3d::UnitX();
+ A_p[i] = surfaceArea;
+ to_upper.col(i) << e.i, e.j;
+ to_lower[e.i] = i;
+ to_lower[e.j] = i;
+ }
+
+ int offset = nCollapsed;
+
+ for (int i = 0; i < V.cols(); ++i) {
+ if (!mergeFlag[i]) {
+ int idx = offset++;
+ V_p.col(idx) = V.col(i);
+ N_p.col(idx) = N.col(i);
+ A_p[idx] = A[i];
+ to_upper.col(idx) << i, -1;
+ to_lower[i] = idx;
+ }
+ }
+
+ adj_p.resize(V_p.cols());
+ std::vector<int> capacity(V_p.cols());
+ std::vector<std::vector<Link>> scratches(V_p.cols());
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int i = 0; i < V_p.cols(); ++i) {
+ int t = 0;
+ for (int j = 0; j < 2; ++j) {
+ int upper = to_upper(j, i);
+ if (upper == -1) continue;
+ t += adj[upper].size();
+ }
+ scratches[i].reserve(t);
+ adj_p[i].reserve(t);
+ }
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int i = 0; i < V_p.cols(); ++i) {
+ auto& scratch = scratches[i];
+ for (int j = 0; j < 2; ++j) {
+ int upper = to_upper(j, i);
+ if (upper == -1) continue;
+ auto& ad = adj[upper];
+ for (auto& link : ad) scratch.push_back(Link(to_lower[link.id], link.weight));
+ }
+ std::sort(scratch.begin(), scratch.end());
+ int id = -1;
+ auto& ad = adj_p[i];
+ for (auto& link : scratch) {
+ if (link.id != i) {
+ if (id != link.id) {
+ ad.push_back(link);
+ id = link.id;
+ } else {
+ ad.back().weight += link.weight;
+ }
+ }
+ }
+ }
+}
+
+void Hierarchy::SaveToFile(FILE* fp) {
+ Save(fp, mScale);
+ Save(fp, mF);
+ Save(fp, mE2E);
+ Save(fp, mAdj);
+ Save(fp, mV);
+ Save(fp, mN);
+ Save(fp, mA);
+ Save(fp, mToLower);
+ Save(fp, mToUpper);
+ Save(fp, mQ);
+ Save(fp, mO);
+ Save(fp, mS);
+ Save(fp, mK);
+ Save(fp, this->mPhases);
+}
+
+void Hierarchy::LoadFromFile(FILE* fp) {
+ Read(fp, mScale);
+ Read(fp, mF);
+ Read(fp, mE2E);
+ Read(fp, mAdj);
+ Read(fp, mV);
+ Read(fp, mN);
+ Read(fp, mA);
+ Read(fp, mToLower);
+ Read(fp, mToUpper);
+ Read(fp, mQ);
+ Read(fp, mO);
+ Read(fp, mS);
+ Read(fp, mK);
+ Read(fp, this->mPhases);
+}
+
+void Hierarchy::UpdateGraphValue(std::vector<Vector3i>& FQ, std::vector<Vector3i>& F2E,
+ std::vector<Vector2i>& edge_diff) {
+ FQ = std::move(mFQ[0]);
+ F2E = std::move(mF2E[0]);
+ edge_diff = std::move(mEdgeDiff[0]);
+}
+
+void Hierarchy::DownsampleEdgeGraph(std::vector<Vector3i>& FQ, std::vector<Vector3i>& F2E,
+ std::vector<Vector2i>& edge_diff,
+ std::vector<int>& allow_changes, int level) {
+ std::vector<Vector2i> E2F(edge_diff.size(), Vector2i(-1, -1));
+ for (int i = 0; i < F2E.size(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ int e = F2E[i][j];
+ if (E2F[e][0] == -1)
+ E2F[e][0] = i;
+ else
+ E2F[e][1] = i;
+ }
+ }
+ int levels = (level == -1) ? 100 : level;
+ mFQ.resize(levels);
+ mF2E.resize(levels);
+ mE2F.resize(levels);
+ mEdgeDiff.resize(levels);
+ mAllowChanges.resize(levels);
+ mSing.resize(levels);
+ mToUpperEdges.resize(levels - 1);
+ mToUpperOrients.resize(levels - 1);
+ for (int i = 0; i < FQ.size(); ++i) {
+ Vector2i diff(0, 0);
+ for (int j = 0; j < 3; ++j) {
+ diff += rshift90(edge_diff[F2E[i][j]], FQ[i][j]);
+ }
+ if (diff != Vector2i::Zero()) {
+ mSing[0].push_back(i);
+ }
+ }
+ mAllowChanges[0] = allow_changes;
+ mFQ[0] = std::move(FQ);
+ mF2E[0] = std::move(F2E);
+ mE2F[0] = std::move(E2F);
+ mEdgeDiff[0] = std::move(edge_diff);
+ for (int l = 0; l < levels - 1; ++l) {
+ auto& FQ = mFQ[l];
+ auto& E2F = mE2F[l];
+ auto& F2E = mF2E[l];
+ auto& Allow = mAllowChanges[l];
+ auto& EdgeDiff = mEdgeDiff[l];
+ auto& Sing = mSing[l];
+ std::vector<int> fixed_faces(F2E.size(), 0);
+ for (auto& s : Sing) {
+ fixed_faces[s] = 1;
+ }
+
+ auto& toUpper = mToUpperEdges[l];
+ auto& toUpperOrients = mToUpperOrients[l];
+ toUpper.resize(E2F.size(), -1);
+ toUpperOrients.resize(E2F.size(), 0);
+
+ auto& nFQ = mFQ[l + 1];
+ auto& nE2F = mE2F[l + 1];
+ auto& nF2E = mF2E[l + 1];
+ auto& nAllow = mAllowChanges[l + 1];
+ auto& nEdgeDiff = mEdgeDiff[l + 1];
+ auto& nSing = mSing[l + 1];
+
+ for (int i = 0; i < E2F.size(); ++i) {
+ if (EdgeDiff[i] != Vector2i::Zero()) continue;
+ if ((E2F[i][0] >= 0 && fixed_faces[E2F[i][0]]) ||
+ (E2F[i][1] >= 0 && fixed_faces[E2F[i][1]])) {
+ continue;
+ }
+ for (int j = 0; j < 2; ++j) {
+ int f = E2F[i][j];
+ if (f < 0)
+ continue;
+ for (int k = 0; k < 3; ++k) {
+ int neighbor_e = F2E[f][k];
+ for (int m = 0; m < 2; ++m) {
+ int neighbor_f = E2F[neighbor_e][m];
+ if (neighbor_f < 0)
+ continue;
+ if (fixed_faces[neighbor_f] == 0) fixed_faces[neighbor_f] = 1;
+ }
+ }
+ }
+ if (E2F[i][0] >= 0)
+ fixed_faces[E2F[i][0]] = 2;
+ if (E2F[i][1] >= 0)
+ fixed_faces[E2F[i][1]] = 2;
+ toUpper[i] = -2;
+ }
+ for (int i = 0; i < E2F.size(); ++i) {
+ if (toUpper[i] == -2) continue;
+ if ((E2F[i][0] < 0 || fixed_faces[E2F[i][0]] == 2) && (E2F[i][1] < 0 || fixed_faces[E2F[i][1]] == 2)) {
+ toUpper[i] = -3;
+ continue;
+ }
+ }
+ int numE = 0;
+ for (int i = 0; i < toUpper.size(); ++i) {
+ if (toUpper[i] == -1) {
+ if ((E2F[i][0] < 0 || fixed_faces[E2F[i][0]] < 2) && (E2F[i][1] < 0 || fixed_faces[E2F[i][1]] < 2)) {
+ nE2F.push_back(E2F[i]);
+ toUpperOrients[i] = 0;
+ toUpper[i] = numE++;
+ continue;
+ }
+ int f0 = (E2F[i][1] < 0 || fixed_faces[E2F[i][0]] < 2) ? E2F[i][0] : E2F[i][1];
+ int e = i;
+ int f = f0;
+ std::vector<std::pair<int, int>> paths;
+ paths.push_back(std::make_pair(i, 0));
+ while (true) {
+ if (E2F[e][0] == f)
+ f = E2F[e][1];
+ else if (E2F[e][1] == f)
+ f = E2F[e][0];
+ if (f < 0 || fixed_faces[f] < 2) {
+ for (int j = 0; j < paths.size(); ++j) {
+ auto& p = paths[j];
+ toUpper[p.first] = numE;
+ int orient = p.second;
+ if (j > 0) orient = (orient + toUpperOrients[paths[j - 1].first]) % 4;
+ toUpperOrients[p.first] = orient;
+ }
+ nE2F.push_back(Vector2i(f0, f));
+ numE += 1;
+ break;
+ }
+ int ind0 = -1, ind1 = -1;
+ int e0 = e;
+ for (int j = 0; j < 3; ++j) {
+ if (F2E[f][j] == e) {
+ ind0 = j;
+ break;
+ }
+ }
+ for (int j = 0; j < 3; ++j) {
+ int e1 = F2E[f][j];
+ if (e1 != e && toUpper[e1] != -2) {
+ e = e1;
+ ind1 = j;
+ break;
+ }
+ }
+
+ if (ind1 != -1) {
+ paths.push_back(std::make_pair(e, (FQ[f][ind1] - FQ[f][ind0] + 6) % 4));
+ } else {
+ if (EdgeDiff[e] != Vector2i::Zero()) {
+ printf("Unsatisfied !!!...\n");
+ printf("%d %d %d: %d %d\n", F2E[f][0], F2E[f][1], F2E[f][2], e0, e);
+ exit(0);
+ }
+ for (auto& p : paths) {
+ toUpper[p.first] = numE;
+ toUpperOrients[p.first] = 0;
+ }
+ numE += 1;
+ nE2F.push_back(Vector2i(f0, f0));
+ break;
+ }
+ }
+ }
+ }
+ nEdgeDiff.resize(numE);
+ nAllow.resize(numE * 2, 1);
+ for (int i = 0; i < toUpper.size(); ++i) {
+ if (toUpper[i] >= 0 && toUpperOrients[i] == 0) {
+ nEdgeDiff[toUpper[i]] = EdgeDiff[i];
+ }
+ if (toUpper[i] >= 0) {
+ int dimension = toUpperOrients[i] % 2;
+ if (Allow[i * 2 + dimension] == 0)
+ nAllow[toUpper[i] * 2] = 0;
+ else if (Allow[i * 2 + dimension] == 2)
+ nAllow[toUpper[i] * 2] = 2;
+ if (Allow[i * 2 + 1 - dimension] == 0)
+ nAllow[toUpper[i] * 2 + 1] = 0;
+ else if (Allow[i * 2 + 1 - dimension] == 2)
+ nAllow[toUpper[i] * 2 + 1] = 2;
+ }
+ }
+ std::vector<int> upperface(F2E.size(), -1);
+
+ for (int i = 0; i < F2E.size(); ++i) {
+ Vector3i eid;
+ for (int j = 0; j < 3; ++j) {
+ eid[j] = toUpper[F2E[i][j]];
+ }
+ if (eid[0] >= 0 && eid[1] >= 0 && eid[2] >= 0) {
+ Vector3i eid_orient;
+ for (int j = 0; j < 3; ++j) {
+ eid_orient[j] = (FQ[i][j] + 4 - toUpperOrients[F2E[i][j]]) % 4;
+ }
+ upperface[i] = nF2E.size();
+ nF2E.push_back(eid);
+ nFQ.push_back(eid_orient);
+ }
+ }
+ for (int i = 0; i < nE2F.size(); ++i) {
+ for (int j = 0; j < 2; ++j) {
+ if (nE2F[i][j] >= 0)
+ nE2F[i][j] = upperface[nE2F[i][j]];
+ }
+ }
+
+ for (auto& s : Sing) {
+ if (upperface[s] >= 0) nSing.push_back(upperface[s]);
+ }
+ mToUpperFaces.push_back(std::move(upperface));
+
+ if (nEdgeDiff.size() == EdgeDiff.size()) {
+ levels = l + 1;
+ break;
+ }
+ }
+
+ mFQ.resize(levels);
+ mF2E.resize(levels);
+ mAllowChanges.resize(levels);
+ mE2F.resize(levels);
+ mEdgeDiff.resize(levels);
+ mSing.resize(levels);
+ mToUpperEdges.resize(levels - 1);
+ mToUpperOrients.resize(levels - 1);
+}
+
+int Hierarchy::FixFlipSat(int depth, int threshold) {
+ if (system("which minisat > /dev/null 2>&1")) {
+ printf("minisat not found, \"-sat\" will not be used!\n");
+ return 0;
+ }
+ if (system("which timeout > /dev/null 2>&1")) {
+ printf("timeout not found, \"-sat\" will not be used!\n");
+ return 0;
+ }
+
+ auto& F2E = mF2E[depth];
+ auto& E2F = mE2F[depth];
+ auto& FQ = mFQ[depth];
+ auto& EdgeDiff = mEdgeDiff[depth];
+ auto& AllowChanges = mAllowChanges[depth];
+
+ // build E2E
+ std::vector<int> E2E(F2E.size() * 3, -1);
+ for (int i = 0; i < E2F.size(); ++i) {
+ int f1 = E2F[i][0];
+ int f2 = E2F[i][1];
+ int t1 = 0;
+ int t2 = 2;
+ if (f1 != -1) while (F2E[f1][t1] != i) t1 += 1;
+ if (f2 != -1) while (F2E[f2][t2] != i) t2 -= 1;
+ t1 += f1 * 3;
+ t2 += f2 * 3;
+ if (f1 != -1) E2E[t1] = (f2 == -1) ? -1 : t2;
+ if (f2 != -1) E2E[t2] = (f1 == -1) ? -1 : t1;
+ }
+
+ auto IntegerArea = [&](int f) {
+ Vector2i diff1 = rshift90(EdgeDiff[F2E[f][0]], FQ[f][0]);
+ Vector2i diff2 = rshift90(EdgeDiff[F2E[f][1]], FQ[f][1]);
+ return diff1[0] * diff2[1] - diff1[1] * diff2[0];
+ };
+
+ std::deque<std::pair<int, int>> Q;
+ std::vector<bool> mark_dedges(F2E.size() * 3, false);
+ for (int f = 0; f < F2E.size(); ++f) {
+ if (IntegerArea(f) < 0) {
+ for (int j = 0; j < 3; ++j) {
+ if (mark_dedges[f * 3 + j]) continue;
+ Q.push_back(std::make_pair(f * 3 + j, 0));
+ mark_dedges[f * 3 + j] = true;
+ }
+ }
+ }
+
+ int mark_count = 0;
+ while (!Q.empty()) {
+ int e0 = Q.front().first;
+ int depth = Q.front().second;
+ Q.pop_front();
+ mark_count++;
+
+ int e = e0, e1;
+ do {
+ e1 = E2E[e];
+ if (e1 == -1) break;
+ int length = EdgeDiff[F2E[e1 / 3][e1 % 3]].array().abs().sum();
+ if (length == 0 && !mark_dedges[e1]) {
+ mark_dedges[e1] = true;
+ Q.push_front(std::make_pair(e1, depth));
+ }
+ e = (e1 / 3) * 3 + (e1 + 1) % 3;
+ mark_dedges[e] = true;
+ } while (e != e0);
+ if (e1 == -1) {
+ do {
+ e1 = E2E[e];
+ if (e1 == -1) break;
+ int length = EdgeDiff[F2E[e1 / 3][e1 % 3]].array().abs().sum();
+ if (length == 0 && !mark_dedges[e1]) {
+ mark_dedges[e1] = true;
+ Q.push_front(std::make_pair(e1, depth));
+ }
+ e = (e1 / 3) * 3 + (e1 + 2) % 3;
+ mark_dedges[e] = true;
+ } while (e != e0);
+ }
+
+ do {
+ e1 = E2E[e];
+ if (e1 == -1) break;
+ int length = EdgeDiff[F2E[e1 / 3][e1 % 3]].array().abs().sum();
+ if (length > 0 && depth + length <= threshold && !mark_dedges[e1]) {
+ mark_dedges[e1] = true;
+ Q.push_back(std::make_pair(e1, depth + length));
+ }
+ e = e1 / 3 * 3 + (e1 + 1) % 3;
+ mark_dedges[e] = true;
+ } while (e != e0);
+ if (e1 == -1) {
+ do {
+ e1 = E2E[e];
+ if (e1 == -1) break;
+ int length = EdgeDiff[F2E[e1 / 3][e1 % 3]].array().abs().sum();
+ if (length > 0 && depth + length <= threshold && !mark_dedges[e1]) {
+ mark_dedges[e1] = true;
+ Q.push_back(std::make_pair(e1, depth + length));
+ }
+ e = e1 / 3 * 3 + (e1 + 2) % 3;
+ mark_dedges[e] = true;
+ } while (e != e0);
+ }
+ }
+ lprintf("[FlipH] Depth %2d: marked = %d\n", depth, mark_count);
+
+ std::vector<bool> flexible(EdgeDiff.size(), false);
+ for (int i = 0; i < F2E.size(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ int dedge = i * 3 + j;
+ int edgeid = F2E[i][j];
+ if (mark_dedges[dedge]) {
+ flexible[edgeid] = true;
+ }
+ }
+ }
+ for (int i = 0; i < flexible.size(); ++i) {
+ if (E2F[i][0] == E2F[i][1]) flexible[i] = false;
+ if (AllowChanges[i] == 0) flexible[i] = false;
+ }
+
+ // Reindexing and solve
+ int num_group = 0;
+ std::vector<int> groups(EdgeDiff.size(), -1);
+ std::vector<int> indices(EdgeDiff.size(), -1);
+ for (int i = 0; i < EdgeDiff.size(); ++i) {
+ if (groups[i] == -1 && flexible[i]) {
+ // group it
+ std::queue<int> q;
+ q.push(i);
+ groups[i] = num_group;
+ while (!q.empty()) {
+ int e = q.front();
+ q.pop();
+ int f[] = {E2F[e][0], E2F[e][1]};
+ for (int j = 0; j < 2; ++j) {
+ if (f[j] == -1) continue;
+ for (int k = 0; k < 3; ++k) {
+ int e1 = F2E[f[j]][k];
+ if (flexible[e1] && groups[e1] == -1) {
+ groups[e1] = num_group;
+ q.push(e1);
+ }
+ }
+ }
+ }
+ num_group += 1;
+ }
+ }
+
+ std::vector<int> num_edges(num_group);
+ std::vector<int> num_flips(num_group);
+ std::vector<std::vector<int>> values(num_group);
+ std::vector<std::vector<Vector3i>> variable_eq(num_group);
+ std::vector<std::vector<Vector3i>> constant_eq(num_group);
+ std::vector<std::vector<Vector4i>> variable_ge(num_group);
+ std::vector<std::vector<Vector2i>> constant_ge(num_group);
+ for (int i = 0; i < groups.size(); ++i) {
+ if (groups[i] != -1) {
+ indices[i] = num_edges[groups[i]]++;
+ values[groups[i]].push_back(EdgeDiff[i][0]);
+ values[groups[i]].push_back(EdgeDiff[i][1]);
+ }
+ }
+ std::vector<int> num_edges_flexible = num_edges;
+ std::map<std::pair<int, int>, int> fixed_variables;
+ for (int i = 0; i < F2E.size(); ++i) {
+ Vector2i var[3];
+ Vector2i cst[3];
+ int gind = 0;
+ while (gind < 3 && groups[F2E[i][gind]] == -1) gind += 1;
+ if (gind == 3) continue;
+ int group = groups[F2E[i][gind]];
+ int ind[3] = {-1, -1, -1};
+ for (int j = 0; j < 3; ++j) {
+ int g = groups[F2E[i][j]];
+ if (g != group) {
+ if (g == -1) {
+ auto key = std::make_pair(F2E[i][j], group);
+ auto it = fixed_variables.find(key);
+ if (it == fixed_variables.end()) {
+ ind[j] = num_edges[group];
+ values[group].push_back(EdgeDiff[F2E[i][j]][0]);
+ values[group].push_back(EdgeDiff[F2E[i][j]][1]);
+ fixed_variables[key] = num_edges[group]++;
+ } else {
+ ind[j] = it->second;
+ }
+ }
+ } else {
+ ind[j] = indices[F2E[i][j]];
+ }
+ }
+ for (int j = 0; j < 3; ++j) assert(ind[j] != -1);
+ for (int j = 0; j < 3; ++j) {
+ var[j] = rshift90(Vector2i(ind[j] * 2 + 1, ind[j] * 2 + 2), FQ[i][j]);
+ cst[j] = var[j].array().sign();
+ var[j] = var[j].array().abs() - 1;
+ }
+
+ num_flips[group] += IntegerArea(i) < 0;
+ variable_eq[group].push_back(Vector3i(var[0][0], var[1][0], var[2][0]));
+ constant_eq[group].push_back(Vector3i(cst[0][0], cst[1][0], cst[2][0]));
+ variable_eq[group].push_back(Vector3i(var[0][1], var[1][1], var[2][1]));
+ constant_eq[group].push_back(Vector3i(cst[0][1], cst[1][1], cst[2][1]));
+
+ variable_ge[group].push_back(Vector4i(var[0][0], var[1][1], var[0][1], var[1][0]));
+ constant_ge[group].push_back(Vector2i(cst[0][0] * cst[1][1], cst[0][1] * cst[1][0]));
+ }
+ int flip_before = 0, flip_after = 0;
+ for (int i = 0; i < F2E.size(); ++i) {
+ int area = IntegerArea(i);
+ if (area < 0) flip_before++;
+ }
+
+ for (int i = 0; i < num_group; ++i) {
+ std::vector<bool> flexible(values[i].size(), true);
+ for (int j = num_edges_flexible[i] * 2; j < flexible.size(); ++j) {
+ flexible[j] = false;
+ }
+ SolveSatProblem(values[i].size(), values[i], flexible, variable_eq[i], constant_eq[i],
+ variable_ge[i], constant_ge[i]);
+ }
+
+ for (int i = 0; i < EdgeDiff.size(); ++i) {
+ int group = groups[i];
+ if (group == -1) continue;
+ EdgeDiff[i][0] = values[group][2 * indices[i] + 0];
+ EdgeDiff[i][1] = values[group][2 * indices[i] + 1];
+ }
+ for (int i = 0; i < F2E.size(); ++i) {
+ Vector2i diff(0, 0);
+ for (int j = 0; j < 3; ++j) {
+ diff += rshift90(EdgeDiff[F2E[i][j]], FQ[i][j]);
+ }
+ assert(diff == Vector2i::Zero());
+
+ int area = IntegerArea(i);
+ if (area < 0) flip_after++;
+ }
+
+ lprintf("[FlipH] FlipArea, Before: %d After %d\n", flip_before, flip_after);
+ return flip_after;
+}
+
+void Hierarchy::PushDownwardFlip(int depth) {
+ auto& EdgeDiff = mEdgeDiff[depth];
+ auto& nEdgeDiff = mEdgeDiff[depth - 1];
+ auto& toUpper = mToUpperEdges[depth - 1];
+ auto& toUpperOrients = mToUpperOrients[depth - 1];
+ auto& toUpperFaces = mToUpperFaces[depth - 1];
+ for (int i = 0; i < toUpper.size(); ++i) {
+ if (toUpper[i] >= 0) {
+ int orient = (4 - toUpperOrients[i]) % 4;
+ nEdgeDiff[i] = rshift90(EdgeDiff[toUpper[i]], orient);
+ } else {
+ nEdgeDiff[i] = Vector2i(0, 0);
+ }
+ }
+ auto& nF2E = mF2E[depth - 1];
+ auto& nFQ = mFQ[depth - 1];
+ for (int i = 0; i < nF2E.size(); ++i) {
+ Vector2i diff(0, 0);
+ for (int j = 0; j < 3; ++j) {
+ diff += rshift90(nEdgeDiff[nF2E[i][j]], nFQ[i][j]);
+ }
+ if (diff != Vector2i::Zero()) {
+ printf("Fail!!!!!!! %d\n", i);
+ for (int j = 0; j < 3; ++j) {
+ Vector2i d = rshift90(nEdgeDiff[nF2E[i][j]], nFQ[i][j]);
+ printf("<%d %d %d>\n", nF2E[i][j], nFQ[i][j], toUpperOrients[nF2E[i][j]]);
+ printf("%d %d\n", d[0], d[1]);
+ printf("%d -> %d\n", nF2E[i][j], toUpper[nF2E[i][j]]);
+ }
+ printf("%d -> %d\n", i, toUpperFaces[i]);
+ exit(1);
+ }
+ }
+}
+
+void Hierarchy::FixFlip() {
+ int l = mF2E.size() - 1;
+ auto& F2E = mF2E[l];
+ auto& E2F = mE2F[l];
+ auto& FQ = mFQ[l];
+ auto& EdgeDiff = mEdgeDiff[l];
+ auto& AllowChange = mAllowChanges[l];
+
+ // build E2E
+ std::vector<int> E2E(F2E.size() * 3, -1);
+ for (int i = 0; i < E2F.size(); ++i) {
+ int v1 = E2F[i][0];
+ int v2 = E2F[i][1];
+ int t1 = 0;
+ int t2 = 2;
+ if (v1 != -1)
+ while (F2E[v1][t1] != i) t1 += 1;
+ if (v2 != -1)
+ while (F2E[v2][t2] != i) t2 -= 1;
+ t1 += v1 * 3;
+ t2 += v2 * 3;
+ if (v1 != -1)
+ E2E[t1] = (v2 == -1) ? -1 : t2;
+ if (v2 != -1)
+ E2E[t2] = (v1 == -1) ? -1 : t1;
+ }
+
+ auto Area = [&](int f) {
+ Vector2i diff1 = rshift90(EdgeDiff[F2E[f][0]], FQ[f][0]);
+ Vector2i diff2 = rshift90(EdgeDiff[F2E[f][1]], FQ[f][1]);
+ return diff1[0] * diff2[1] - diff1[1] * diff2[0];
+ };
+ std::vector<int> valences(F2E.size() * 3, -10000); // comment this line
+ auto CheckShrink = [&](int deid, int allowed_edge_length) {
+ // Check if we want shrink direct edge deid so that all edge length is smaller than
+ // allowed_edge_length
+ if (deid == -1) {
+ return false;
+ }
+ std::vector<int> corresponding_faces;
+ std::vector<int> corresponding_edges;
+ std::vector<Vector2i> corresponding_diff;
+ int deid0 = deid;
+ while (deid != -1) {
+ deid = deid / 3 * 3 + (deid + 2) % 3;
+ if (E2E[deid] == -1)
+ break;
+ deid = E2E[deid];
+ if (deid == deid0)
+ break;
+ }
+ Vector2i diff = EdgeDiff[F2E[deid / 3][deid % 3]];
+ do {
+ corresponding_diff.push_back(diff);
+ corresponding_edges.push_back(deid);
+ corresponding_faces.push_back(deid / 3);
+
+ // transform to the next face
+ deid = E2E[deid];
+ if (deid == -1) {
+ return false;
+ }
+ // transform for the target incremental diff
+ diff = -rshift90(diff, FQ[deid / 3][deid % 3]);
+ deid = deid / 3 * 3 + (deid + 1) % 3;
+ // transform to local
+ diff = rshift90(diff, (4 - FQ[deid / 3][deid % 3]) % 4);
+ } while (deid != corresponding_edges.front());
+ // check diff
+ if (deid != -1 && diff != corresponding_diff.front()) {
+ return false;
+ }
+ std::unordered_map<int, Vector2i> new_values;
+ for (int i = 0; i < corresponding_diff.size(); ++i) {
+ int deid = corresponding_edges[i];
+ int eid = F2E[deid / 3][deid % 3];
+ new_values[eid] = EdgeDiff[eid];
+ }
+ for (int i = 0; i < corresponding_diff.size(); ++i) {
+ int deid = corresponding_edges[i];
+ int eid = F2E[deid / 3][deid % 3];
+ for (int j = 0; j < 2; ++j) {
+ if (corresponding_diff[i][j] != 0 && AllowChange[eid * 2 + j] == 0) return false;
+ }
+ auto& res = new_values[eid];
+ res -= corresponding_diff[i];
+ int edge_thres = allowed_edge_length;
+ if (abs(res[0]) > edge_thres || abs(res[1]) > edge_thres) {
+ return false;
+ }
+ if ((abs(res[0]) > 1 && abs(res[1]) != 0) || (abs(res[1]) > 1 && abs(res[0]) != 0))
+ return false;
+ }
+ int prev_area = 0, current_area = 0;
+ for (int f = 0; f < corresponding_faces.size(); ++f) {
+ int area = Area(corresponding_faces[f]);
+ if (area < 0) prev_area += 1;
+ }
+ for (auto& p : new_values) {
+ std::swap(EdgeDiff[p.first], p.second);
+ }
+ for (int f = 0; f < corresponding_faces.size(); ++f) {
+ int area = Area(corresponding_faces[f]);
+ if (area < 0) {
+ current_area += 1;
+ }
+ }
+ if (current_area < prev_area) {
+ return true;
+ }
+ for (auto& p : new_values) {
+ std::swap(EdgeDiff[p.first], p.second);
+ }
+ return false;
+ };
+
+ std::queue<int> flipped;
+ for (int i = 0; i < F2E.size(); ++i) {
+ int area = Area(i);
+ if (area < 0) {
+ flipped.push(i);
+ }
+ }
+
+ bool update = false;
+ int max_len = 1;
+ while (!update && max_len <= 2) {
+ while (!flipped.empty()) {
+ int f = flipped.front();
+ if (Area(f) >= 0) {
+ flipped.pop();
+ continue;
+ }
+ for (int i = 0; i < 3; ++i) {
+ if (CheckShrink(f * 3 + i, max_len) || CheckShrink(E2E[f * 3 + i], max_len)) {
+ update = true;
+ break;
+ }
+ }
+ flipped.pop();
+ }
+ max_len += 1;
+ }
+ if (update) {
+ Hierarchy flip_hierarchy;
+ flip_hierarchy.DownsampleEdgeGraph(mFQ.back(), mF2E.back(), mEdgeDiff.back(),
+ mAllowChanges.back(), -1);
+ flip_hierarchy.FixFlip();
+ flip_hierarchy.UpdateGraphValue(mFQ.back(), mF2E.back(), mEdgeDiff.back());
+ }
+ PropagateEdge();
+}
+
+void Hierarchy::PropagateEdge() {
+ for (int level = mToUpperEdges.size(); level > 0; --level) {
+ auto& EdgeDiff = mEdgeDiff[level];
+ auto& nEdgeDiff = mEdgeDiff[level - 1];
+ auto& FQ = mFQ[level];
+ auto& nFQ = mFQ[level - 1];
+ auto& F2E = mF2E[level - 1];
+ auto& toUpper = mToUpperEdges[level - 1];
+ auto& toUpperFace = mToUpperFaces[level - 1];
+ auto& toUpperOrients = mToUpperOrients[level - 1];
+ for (int i = 0; i < toUpper.size(); ++i) {
+ if (toUpper[i] >= 0) {
+ int orient = (4 - toUpperOrients[i]) % 4;
+ nEdgeDiff[i] = rshift90(EdgeDiff[toUpper[i]], orient);
+ } else {
+ nEdgeDiff[i] = Vector2i(0, 0);
+ }
+ }
+ for (int i = 0; i < toUpperFace.size(); ++i) {
+ if (toUpperFace[i] == -1) continue;
+ Vector3i eid_orient = FQ[toUpperFace[i]];
+ for (int j = 0; j < 3; ++j) {
+ nFQ[i][j] = (eid_orient[j] + toUpperOrients[F2E[i][j]]) % 4;
+ }
+ }
+ }
+}
+
+void Hierarchy::clearConstraints() {
+ int levels = mV.size();
+ if (levels == 0) return;
+ for (int i = 0; i < levels; ++i) {
+ int size = mV[i].cols();
+ mCQ[i].resize(3, size);
+ mCO[i].resize(3, size);
+ mCQw[i].resize(size);
+ mCOw[i].resize(size);
+ mCQw[i].setZero();
+ mCOw[i].setZero();
+ }
+}
+
+void Hierarchy::propagateConstraints() {
+ int levels = mV.size();
+ if (levels == 0) return;
+
+ for (int l = 0; l < levels - 1; ++l) {
+ auto& N = mN[l];
+ auto& N_next = mN[l + 1];
+ auto& V = mV[l];
+ auto& V_next = mV[l + 1];
+ auto& CQ = mCQ[l];
+ auto& CQ_next = mCQ[l + 1];
+ auto& CQw = mCQw[l];
+ auto& CQw_next = mCQw[l + 1];
+ auto& CO = mCO[l];
+ auto& CO_next = mCO[l + 1];
+ auto& COw = mCOw[l];
+ auto& COw_next = mCOw[l + 1];
+ auto& toUpper = mToUpper[l];
+ MatrixXd& S = mS[l];
+
+ for (uint32_t i = 0; i != mV[l + 1].cols(); ++i) {
+ Vector2i upper = toUpper.col(i);
+ Vector3d cq = Vector3d::Zero(), co = Vector3d::Zero();
+ float cqw = 0.0f, cow = 0.0f;
+
+ bool has_cq0 = CQw[upper[0]] != 0;
+ bool has_cq1 = upper[1] != -1 && CQw[upper[1]] != 0;
+ bool has_co0 = COw[upper[0]] != 0;
+ bool has_co1 = upper[1] != -1 && COw[upper[1]] != 0;
+
+ if (has_cq0 && !has_cq1) {
+ cq = CQ.col(upper[0]);
+ cqw = CQw[upper[0]];
+ } else if (has_cq1 && !has_cq0) {
+ cq = CQ.col(upper[1]);
+ cqw = CQw[upper[1]];
+ } else if (has_cq1 && has_cq0) {
+ Vector3d q_i = CQ.col(upper[0]);
+ Vector3d n_i = CQ.col(upper[0]);
+ Vector3d q_j = CQ.col(upper[1]);
+ Vector3d n_j = CQ.col(upper[1]);
+ auto result = compat_orientation_extrinsic_4(q_i, n_i, q_j, n_j);
+ cq = result.first * CQw[upper[0]] + result.second * CQw[upper[1]];
+ cqw = (CQw[upper[0]] + CQw[upper[1]]);
+ }
+ if (cq != Vector3d::Zero()) {
+ Vector3d n = N_next.col(i);
+ cq -= n.dot(cq) * n;
+ if (cq.squaredNorm() > RCPOVERFLOW) cq.normalize();
+ }
+
+ if (has_co0 && !has_co1) {
+ co = CO.col(upper[0]);
+ cow = COw[upper[0]];
+ } else if (has_co1 && !has_co0) {
+ co = CO.col(upper[1]);
+ cow = COw[upper[1]];
+ } else if (has_co1 && has_co0) {
+ double scale_x = mScale;
+ double scale_y = mScale;
+ if (with_scale) {
+ // FIXME
+ // scale_x *= S(0, i);
+ // scale_y *= S(1, i);
+ }
+ double inv_scale_x = 1.0f / scale_x;
+ double inv_scale_y = 1.0f / scale_y;
+
+ double scale_x_1 = mScale;
+ double scale_y_1 = mScale;
+ if (with_scale) {
+ // FIXME
+ // scale_x_1 *= S(0, j);
+ // scale_y_1 *= S(1, j);
+ }
+ double inv_scale_x_1 = 1.0f / scale_x_1;
+ double inv_scale_y_1 = 1.0f / scale_y_1;
+ auto result = compat_position_extrinsic_4(
+ V.col(upper[0]), N.col(upper[0]), CQ.col(upper[0]), CO.col(upper[0]),
+ V.col(upper[1]), N.col(upper[1]), CQ.col(upper[1]), CO.col(upper[1]), scale_x,
+ scale_y, inv_scale_x, inv_scale_y, scale_x_1, scale_y_1, inv_scale_x_1,
+ inv_scale_y_1);
+ cow = COw[upper[0]] + COw[upper[1]];
+ co = (result.first * COw[upper[0]] + result.second * COw[upper[1]]) / cow;
+ }
+ if (co != Vector3d::Zero()) {
+ Vector3d n = N_next.col(i), v = V_next.col(i);
+ co -= n.dot(cq - v) * n;
+ }
+#if 0
+ cqw *= 0.5f;
+ cow *= 0.5f;
+#else
+ if (cqw > 0) cqw = 1;
+ if (cow > 0) cow = 1;
+#endif
+
+ CQw_next[i] = cqw;
+ COw_next[i] = cow;
+ CQ_next.col(i) = cq;
+ CO_next.col(i) = co;
+ }
+ }
+}
+#ifdef WITH_CUDA
+#include <cuda_runtime.h>
+
+void Hierarchy::CopyToDevice() {
+ if (cudaAdj.empty()) {
+ cudaAdj.resize(mAdj.size());
+ cudaAdjOffset.resize(mAdj.size());
+ for (int i = 0; i < mAdj.size(); ++i) {
+ std::vector<int> offset(mAdj[i].size() + 1, 0);
+ for (int j = 0; j < mAdj[i].size(); ++j) {
+ offset[j + 1] = offset[j] + mAdj[i][j].size();
+ }
+ cudaMalloc(&cudaAdjOffset[i], sizeof(int) * (mAdj[i].size() + 1));
+ cudaMemcpy(cudaAdjOffset[i], offset.data(), sizeof(int) * (mAdj[i].size() + 1),
+ cudaMemcpyHostToDevice);
+ // cudaAdjOffset[i] = (int*)malloc(sizeof(int) * (mAdj[i].size() + 1));
+ // memcpy(cudaAdjOffset[i], offset.data(), sizeof(int) * (mAdj[i].size() +
+ // 1));
+
+ cudaMalloc(&cudaAdj[i], sizeof(Link) * offset.back());
+ // cudaAdj[i] = (Link*)malloc(sizeof(Link) * offset.back());
+ std::vector<Link> plainlink(offset.back());
+ for (int j = 0; j < mAdj[i].size(); ++j) {
+ memcpy(plainlink.data() + offset[j], mAdj[i][j].data(),
+ mAdj[i][j].size() * sizeof(Link));
+ }
+ cudaMemcpy(cudaAdj[i], plainlink.data(), plainlink.size() * sizeof(Link),
+ cudaMemcpyHostToDevice);
+ }
+ }
+
+ if (cudaN.empty()) {
+ cudaN.resize(mN.size());
+ for (int i = 0; i < mN.size(); ++i) {
+ cudaMalloc(&cudaN[i], sizeof(glm::dvec3) * mN[i].cols());
+ // cudaN[i] = (glm::dvec3*)malloc(sizeof(glm::dvec3) * mN[i].cols());
+ }
+ }
+ for (int i = 0; i < mN.size(); ++i) {
+ cudaMemcpy(cudaN[i], mN[i].data(), sizeof(glm::dvec3) * mN[i].cols(),
+ cudaMemcpyHostToDevice);
+ // memcpy(cudaN[i], mN[i].data(), sizeof(glm::dvec3) * mN[i].cols());
+ }
+
+ if (cudaV.empty()) {
+ cudaV.resize(mV.size());
+ for (int i = 0; i < mV.size(); ++i) {
+ cudaMalloc(&cudaV[i], sizeof(glm::dvec3) * mV[i].cols());
+ // cudaV[i] = (glm::dvec3*)malloc(sizeof(glm::dvec3) * mV[i].cols());
+ }
+ }
+ for (int i = 0; i < mV.size(); ++i) {
+ cudaMemcpy(cudaV[i], mV[i].data(), sizeof(glm::dvec3) * mV[i].cols(),
+ cudaMemcpyHostToDevice);
+ // memcpy(cudaV[i], mV[i].data(), sizeof(glm::dvec3) * mV[i].cols());
+ }
+
+ if (cudaQ.empty()) {
+ cudaQ.resize(mQ.size());
+ for (int i = 0; i < mQ.size(); ++i) {
+ cudaMalloc(&cudaQ[i], sizeof(glm::dvec3) * mQ[i].cols());
+ // cudaQ[i] = (glm::dvec3*)malloc(sizeof(glm::dvec3) * mQ[i].cols());
+ }
+ }
+ for (int i = 0; i < mQ.size(); ++i) {
+ cudaMemcpy(cudaQ[i], mQ[i].data(), sizeof(glm::dvec3) * mQ[i].cols(),
+ cudaMemcpyHostToDevice);
+ // memcpy(cudaQ[i], mQ[i].data(), sizeof(glm::dvec3) * mQ[i].cols());
+ }
+ if (cudaO.empty()) {
+ cudaO.resize(mO.size());
+ for (int i = 0; i < mO.size(); ++i) {
+ cudaMalloc(&cudaO[i], sizeof(glm::dvec3) * mO[i].cols());
+ // cudaO[i] = (glm::dvec3*)malloc(sizeof(glm::dvec3) * mO[i].cols());
+ }
+ }
+ for (int i = 0; i < mO.size(); ++i) {
+ cudaMemcpy(cudaO[i], mO[i].data(), sizeof(glm::dvec3) * mO[i].cols(),
+ cudaMemcpyHostToDevice);
+ // memcpy(cudaO[i], mO[i].data(), sizeof(glm::dvec3) * mO[i].cols());
+ }
+ if (cudaPhases.empty()) {
+ cudaPhases.resize(mPhases.size());
+ for (int i = 0; i < mPhases.size(); ++i) {
+ cudaPhases[i].resize(mPhases[i].size());
+ for (int j = 0; j < mPhases[i].size(); ++j) {
+ cudaMalloc(&cudaPhases[i][j], sizeof(int) * mPhases[i][j].size());
+ // cudaPhases[i][j] = (int*)malloc(sizeof(int) *
+ // mPhases[i][j].size());
+ }
+ }
+ }
+ for (int i = 0; i < mPhases.size(); ++i) {
+ for (int j = 0; j < mPhases[i].size(); ++j) {
+ cudaMemcpy(cudaPhases[i][j], mPhases[i][j].data(), sizeof(int) * mPhases[i][j].size(),
+ cudaMemcpyHostToDevice);
+ // memcpy(cudaPhases[i][j], mPhases[i][j].data(), sizeof(int) *
+ // mPhases[i][j].size());
+ }
+ }
+ if (cudaToUpper.empty()) {
+ cudaToUpper.resize(mToUpper.size());
+ for (int i = 0; i < mToUpper.size(); ++i) {
+ cudaMalloc(&cudaToUpper[i], mToUpper[i].cols() * sizeof(glm::ivec2));
+ // cudaToUpper[i] = (glm::ivec2*)malloc(mToUpper[i].cols() *
+ // sizeof(glm::ivec2));
+ }
+ }
+ for (int i = 0; i < mToUpper.size(); ++i) {
+ cudaMemcpy(cudaToUpper[i], mToUpper[i].data(), sizeof(glm::ivec2) * mToUpper[i].cols(),
+ cudaMemcpyHostToDevice);
+ // memcpy(cudaToUpper[i], mToUpper[i].data(), sizeof(glm::ivec2) *
+ // mToUpper[i].cols());
+ }
+ cudaDeviceSynchronize();
+}
+
+void Hierarchy::CopyToHost() {}
+
+#endif
+
+} // namespace qflow
diff --git a/extern/quadriflow/src/hierarchy.hpp b/extern/quadriflow/src/hierarchy.hpp
new file mode 100644
index 00000000000..8403038de4f
--- /dev/null
+++ b/extern/quadriflow/src/hierarchy.hpp
@@ -0,0 +1,99 @@
+#ifndef HIERARCHY_H_
+#define HIERARCHY_H_
+
+#ifdef WITH_CUDA
+# include <glm/glm.hpp>
+#endif
+
+#include <map>
+#include <vector>
+#include "adjacent-matrix.hpp"
+#include "config.hpp"
+#include "serialize.hpp"
+#define RCPOVERFLOW 2.93873587705571876e-39f
+
+using namespace Eigen;
+
+namespace qflow {
+
+class Hierarchy {
+ public:
+ Hierarchy();
+ void Initialize(double scale, int with_scale = 0);
+ void DownsampleGraph(const AdjacentMatrix adj, const MatrixXd& V, const MatrixXd& N,
+ const VectorXd& A, MatrixXd& V_p, MatrixXd& N_p, VectorXd& A_p,
+ MatrixXi& to_upper, VectorXi& to_lower, AdjacentMatrix& adj_p);
+ void generate_graph_coloring_deterministic(const AdjacentMatrix& adj, int size,
+ std::vector<std::vector<int>>& phases);
+ void FixFlip();
+ int FixFlipSat(int depth, int threshold = 0);
+ void PushDownwardFlip(int depth);
+ void PropagateEdge();
+ void DownsampleEdgeGraph(std::vector<Vector3i>& FQ, std::vector<Vector3i>& F2E,
+ std::vector<Vector2i>& edge_diff,
+ std::vector<int>& allow_changes, int level);
+ void UpdateGraphValue(std::vector<Vector3i>& FQ, std::vector<Vector3i>& F2E,
+ std::vector<Vector2i>& edge_diff);
+
+ enum { MAX_DEPTH = 25 };
+
+ void SaveToFile(FILE* fp);
+ void LoadFromFile(FILE* fp);
+
+ void clearConstraints();
+ void propagateConstraints();
+
+ double mScale;
+ int rng_seed;
+
+ MatrixXi mF; // mF(i, j) i \in [0, 3) ith index in face j
+ VectorXi mE2E; // inverse edge
+ std::vector<AdjacentMatrix> mAdj;
+ std::vector<MatrixXd> mV;
+ std::vector<MatrixXd> mN;
+ std::vector<VectorXd> mA;
+ std::vector<std::vector<std::vector<int>>> mPhases;
+ // parameters
+ std::vector<MatrixXd> mQ;
+ std::vector<MatrixXd> mO;
+ std::vector<VectorXi> mToLower;
+ std::vector<MatrixXi> mToUpper; // mToUpper[h](i, j) \in V; i \in [0, 2); j \in V
+ std::vector<MatrixXd> mS;
+ std::vector<MatrixXd> mK;
+
+ // constraints
+ std::vector<MatrixXd> mCQ;
+ std::vector<MatrixXd> mCO;
+ std::vector<VectorXd> mCQw;
+ std::vector<VectorXd> mCOw;
+
+ int with_scale;
+
+ // upper: fine to coarse
+ std::vector<std::vector<int>> mToUpperFaces; // face correspondance
+ std::vector<std::vector<int>> mSing;
+ std::vector<std::vector<int>> mToUpperEdges; // edge correspondance
+ std::vector<std::vector<int>> mToUpperOrients; // rotation of edges from fine to coarse
+ std::vector<std::vector<Vector3i>> mFQ; // face_edgeOrients
+ std::vector<std::vector<Vector3i>> mF2E; // face_edgeIds
+ std::vector<std::vector<Vector2i>> mE2F; // undirect edges to face ID
+ std::vector<std::vector<int> > mAllowChanges;
+ std::vector<std::vector<Vector2i>> mEdgeDiff; // face_edgeDiff
+
+#ifdef WITH_CUDA
+ std::vector<Link*> cudaAdj;
+ std::vector<int*> cudaAdjOffset;
+ std::vector<glm::dvec3*> cudaN;
+ std::vector<glm::dvec3*> cudaV;
+ std::vector<glm::dvec3*> cudaQ;
+ std::vector<glm::dvec3*> cudaO;
+ std::vector<std::vector<int*>> cudaPhases;
+ std::vector<glm::ivec2*> cudaToUpper;
+ void CopyToDevice();
+ void CopyToHost();
+#endif
+};
+
+} // namespace qflow
+
+#endif
diff --git a/extern/quadriflow/src/loader.cpp b/extern/quadriflow/src/loader.cpp
new file mode 100644
index 00000000000..aa27066e6e4
--- /dev/null
+++ b/extern/quadriflow/src/loader.cpp
@@ -0,0 +1,159 @@
+//
+// loader.cpp
+// Loop
+//
+// Created by Jingwei on 10/22/17.
+// Copyright © 2017 Jingwei. All rights reserved.
+//
+
+#include "loader.hpp"
+
+#include <fstream>
+#include <unordered_map>
+
+namespace qflow {
+
+inline std::vector<std::string> &str_tokenize(const std::string &s, char delim, std::vector<std::string> &elems, bool include_empty = false) {
+ std::stringstream ss(s);
+ std::string item;
+ while (std::getline(ss, item, delim))
+ if (!item.empty() || include_empty)
+ elems.push_back(item);
+ return elems;
+}
+
+inline std::vector<std::string> str_tokenize(const std::string &s, char delim, bool include_empty) {
+ std::vector<std::string> elems;
+ str_tokenize(s, delim, elems, include_empty);
+ return elems;
+}
+
+inline uint32_t str_to_uint32_t(const std::string &str) {
+ char *end_ptr = nullptr;
+ uint32_t result = (uint32_t)strtoul(str.c_str(), &end_ptr, 10);
+ if (*end_ptr != '\0')
+ throw std::runtime_error("Could not parse unsigned integer \"" + str + "\"");
+ return result;
+}
+
+void load(const char* filename, MatrixXd& V, MatrixXi& F)
+{
+ /// Vertex indices used by the OBJ format
+ struct obj_vertex {
+ uint32_t p = (uint32_t)-1;
+ uint32_t n = (uint32_t)-1;
+ uint32_t uv = (uint32_t)-1;
+
+ inline obj_vertex() { }
+
+ inline obj_vertex(const std::string &string) {
+ std::vector<std::string> tokens = str_tokenize(string, '/', true);
+
+ if (tokens.size() < 1 || tokens.size() > 3)
+ throw std::runtime_error("Invalid vertex data: \"" + string + "\"");
+
+ p = str_to_uint32_t(tokens[0]);
+
+#if 0
+ if (tokens.size() >= 2 && !tokens[1].empty())
+ uv = str_to_uint32_t(tokens[1]);
+
+ if (tokens.size() >= 3 && !tokens[2].empty())
+ n = str_to_uint32_t(tokens[2]);
+#endif
+ }
+
+ inline bool operator==(const obj_vertex &v) const {
+ return v.p == p && v.n == n && v.uv == uv;
+ }
+ };
+
+ /// Hash function for obj_vertex
+ struct obj_vertexHash : std::unary_function<obj_vertex, size_t> {
+ std::size_t operator()(const obj_vertex &v) const {
+ size_t hash = std::hash<uint32_t>()(v.p);
+ hash = hash * 37 + std::hash<uint32_t>()(v.uv);
+ hash = hash * 37 + std::hash<uint32_t>()(v.n);
+ return hash;
+ }
+ };
+
+ typedef std::unordered_map<obj_vertex, uint32_t, obj_vertexHash> VertexMap;
+
+ std::ifstream is(filename);
+
+ std::vector<Vector3d> positions;
+ //std::vector<Vector2d> texcoords;
+ //std::vector<Vector3d> normals;
+ std::vector<uint32_t> indices;
+ std::vector<obj_vertex> vertices;
+ VertexMap vertexMap;
+
+ std::string line_str;
+ while (std::getline(is, line_str)) {
+ std::istringstream line(line_str);
+
+ std::string prefix;
+ line >> prefix;
+
+ if (prefix == "v") {
+ Vector3d p;
+ line >> p.x() >> p.y() >> p.z();
+ positions.push_back(p);
+ }
+ else if (prefix == "vt") {
+ /*
+ Vector2d tc;
+ line >> tc.x() >> tc.y();
+ texcoords.push_back(tc);
+ */
+ }
+ else if (prefix == "vn") {
+ /*
+ Vector3d n;
+ line >> n.x() >> n.y() >> n.z();
+ normals.push_back(n);
+ */
+ }
+ else if (prefix == "f") {
+ std::string v1, v2, v3, v4;
+ line >> v1 >> v2 >> v3 >> v4;
+ obj_vertex tri[6];
+ int nVertices = 3;
+
+ tri[0] = obj_vertex(v1);
+ tri[1] = obj_vertex(v2);
+ tri[2] = obj_vertex(v3);
+
+ if (!v4.empty()) {
+ /* This is a quad, split into two triangles */
+ tri[3] = obj_vertex(v4);
+ tri[4] = tri[0];
+ tri[5] = tri[2];
+ nVertices = 6;
+ }
+ /* Convert to an indexed vertex list */
+ for (int i = 0; i<nVertices; ++i) {
+ const obj_vertex &v = tri[i];
+ VertexMap::const_iterator it = vertexMap.find(v);
+ if (it == vertexMap.end()) {
+ vertexMap[v] = (uint32_t)vertices.size();
+ indices.push_back((uint32_t)vertices.size());
+ vertices.push_back(v);
+ }
+ else {
+ indices.push_back(it->second);
+ }
+ }
+ }
+ }
+
+ F.resize(3, indices.size() / 3);
+ memcpy(F.data(), indices.data(), sizeof(uint32_t)*indices.size());
+
+ V.resize(3, vertices.size());
+ for (uint32_t i = 0; i<vertices.size(); ++i)
+ V.col(i) = positions.at(vertices[i].p - 1);
+}
+
+} // namespace qflow
diff --git a/extern/quadriflow/src/loader.hpp b/extern/quadriflow/src/loader.hpp
new file mode 100644
index 00000000000..33b5e55b5e5
--- /dev/null
+++ b/extern/quadriflow/src/loader.hpp
@@ -0,0 +1,15 @@
+#ifndef __LOADER_H
+#define __LOADER_H
+
+#include <Eigen/Core>
+#include <vector>
+
+namespace qflow {
+
+using namespace Eigen;
+
+void load(const char* filename, MatrixXd& V, MatrixXi& F);
+
+} // namespace qflow
+
+#endif
diff --git a/extern/quadriflow/src/localsat.cpp b/extern/quadriflow/src/localsat.cpp
new file mode 100644
index 00000000000..1ab665175da
--- /dev/null
+++ b/extern/quadriflow/src/localsat.cpp
@@ -0,0 +1,295 @@
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+#include "localsat.hpp"
+#include "config.hpp"
+#include "dedge.hpp"
+#include "field-math.hpp"
+
+#include <Eigen/Core>
+
+#include <deque>
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace qflow {
+
+const int max_depth = 0;
+
+using namespace Eigen;
+
+SolverStatus RunCNF(const std::string &fin_name, int n_variable, int timeout,
+ const std::vector<std::vector<int>> &sat_clause, std::vector<int> &value) {
+ int n_sat_variable = 3 * n_variable;
+ auto fout_name = fin_name + ".result.txt";
+
+ FILE *fout = fopen(fin_name.c_str(), "w");
+ fprintf(fout, "p cnf %d %d\n", n_sat_variable, (int)sat_clause.size());
+ for (auto &c : sat_clause) {
+ for (auto e : c) fprintf(fout, "%d ", e);
+ fputs("0\n", fout);
+ }
+ fclose(fout);
+
+ char cmd[100];
+ snprintf(cmd, 99, "rm %s > /dev/null 2>&1", fout_name.c_str());
+ system(cmd);
+ snprintf(cmd, 99, "timeout %d minisat %s %s > /dev/null 2>&1", timeout, fin_name.c_str(),
+ fout_name.c_str());
+ int exit_code = system(cmd);
+
+ FILE *fin = fopen(fout_name.c_str(), "r");
+ char buf[16] = {0};
+ fscanf(fin, "%15s", buf);
+ lprintf(" MiniSAT:");
+ if (strcmp(buf, "SAT") != 0) {
+ fclose(fin);
+
+ if (exit_code == 124) {
+ lprintf(" Timeout! ");
+ return SolverStatus::Timeout;
+ }
+ lprintf(" Unsatisfiable! ");
+ return SolverStatus::Unsat;
+ };
+
+ lprintf(" Satisfiable! ");
+ for (int i = 0; i < n_variable; ++i) {
+ int sign[3];
+ fscanf(fin, "%d %d %d", sign + 0, sign + 1, sign + 2);
+
+ int nvalue = -2;
+ for (int j = 0; j < 3; ++j) {
+ assert(abs(sign[j]) == 3 * i + j + 1);
+ if ((sign[j] > 0) == (value[i] != j - 1)) {
+ assert(nvalue == -2);
+ nvalue = j - 1;
+ }
+ }
+ value[i] = nvalue;
+ }
+ fclose(fin);
+
+ return SolverStatus::Sat;
+}
+
+SolverStatus SolveSatProblem(int n_variable, std::vector<int> &value,
+ const std::vector<bool> flexible, // NOQA
+ const std::vector<Vector3i> &variable_eq,
+ const std::vector<Vector3i> &constant_eq,
+ const std::vector<Vector4i> &variable_ge,
+ const std::vector<Vector2i> &constant_ge,
+ int timeout) {
+ for (int v : value) assert(-1 <= v && v <= +1);
+
+ auto VAR = [&](int i, int v) {
+ int index = 1 + 3 * i + v + 1;
+ // We initialize the SAT problem by setting all the variable to false.
+ // This is because minisat by default will try false first.
+ if (v == value[i]) index = -index;
+ return index;
+ };
+
+ int n_flexible = 0;
+ std::vector<std::vector<int>> sat_clause;
+ std::vector<bool> sat_ishard;
+
+ auto add_clause = [&](const std::vector<int> &clause, bool hard) {
+ sat_clause.push_back(clause);
+ sat_ishard.push_back(hard);
+ };
+
+ for (int i = 0; i < n_variable; ++i) {
+ add_clause({-VAR(i, -1), -VAR(i, 0)}, true);
+ add_clause({-VAR(i, +1), -VAR(i, 0)}, true);
+ add_clause({-VAR(i, -1), -VAR(i, +1)}, true);
+ add_clause({VAR(i, -1), VAR(i, 0), VAR(i, +1)}, true);
+ if (!flexible[i]) {
+ add_clause({VAR(i, value[i])}, true);
+ } else {
+ ++n_flexible;
+ }
+ }
+
+ for (int i = 0; i < (int)variable_eq.size(); ++i) {
+ auto &var = variable_eq[i];
+ auto &cst = constant_eq[i];
+ for (int v0 = -1; v0 <= 1; ++v0)
+ for (int v1 = -1; v1 <= 1; ++v1)
+ for (int v2 = -1; v2 <= 1; ++v2)
+ if (cst[0] * v0 + cst[1] * v1 + cst[2] * v2 != 0) {
+ add_clause({-VAR(var[0], v0), -VAR(var[1], v1), -VAR(var[2], v2)}, true);
+ }
+ }
+
+ for (int i = 0; i < (int)variable_ge.size(); ++i) {
+ auto &var = variable_ge[i];
+ auto &cst = constant_ge[i];
+ for (int v0 = -1; v0 <= 1; ++v0)
+ for (int v1 = -1; v1 <= 1; ++v1)
+ for (int v2 = -1; v2 <= 1; ++v2)
+ for (int v3 = -1; v3 <= 1; ++v3)
+ if (cst[0] * v0 * v1 - cst[1] * v2 * v3 < 0) {
+ add_clause({-VAR(var[0], v0), -VAR(var[1], v1), -VAR(var[2], v2),
+ -VAR(var[3], v3)},
+ false);
+ }
+ }
+
+ int nflip_before = 0, nflip_after = 0;
+ for (int i = 0; i < (int)variable_ge.size(); ++i) {
+ auto &var = variable_ge[i];
+ auto &cst = constant_ge[i];
+ if (value[var[0]] * value[var[1]] * cst[0] - value[var[2]] * value[var[3]] * cst[1] < 0)
+ nflip_before++;
+ }
+
+ lprintf(" [SAT] nvar: %6d nflip: %3d ", n_flexible * 2, nflip_before);
+ auto rcnf = RunCNF("test.out", n_variable, timeout, sat_clause, value);
+
+ for (int i = 0; i < (int)variable_eq.size(); ++i) {
+ auto &var = variable_eq[i];
+ auto &cst = constant_eq[i];
+ assert(cst[0] * value[var[0]] + cst[1] * value[var[1]] + cst[2] * value[var[2]] == 0);
+ }
+ for (int i = 0; i < (int)variable_ge.size(); ++i) {
+ auto &var = variable_ge[i];
+ auto &cst = constant_ge[i];
+ int area = value[var[0]] * value[var[1]] * cst[0] - value[var[2]] * value[var[3]] * cst[1];
+ if (area < 0) ++nflip_after;
+ }
+ lprintf("nflip: %3d\n", nflip_after);
+ return rcnf;
+}
+
+void ExportLocalSat(std::vector<Vector2i> &edge_diff, const std::vector<Vector3i> &face_edgeIds,
+ const std::vector<Vector3i> &face_edgeOrients, const MatrixXi &F,
+ const VectorXi &V2E, const VectorXi &E2E) {
+ int flip_count = 0;
+ int flip_count1 = 0;
+
+ std::vector<int> value(2 * edge_diff.size());
+ for (int i = 0; i < (int)edge_diff.size(); ++i) {
+ value[2 * i + 0] = edge_diff[i][0];
+ value[2 * i + 1] = edge_diff[i][1];
+ }
+
+ std::deque<std::pair<int, int>> Q;
+ std::vector<bool> mark_vertex(V2E.size(), false);
+
+ assert(F.cols() == (int)face_edgeIds.size());
+ std::vector<Vector3i> variable_eq(face_edgeIds.size() * 2);
+ std::vector<Vector3i> constant_eq(face_edgeIds.size() * 2);
+ std::vector<Vector4i> variable_ge(face_edgeIds.size());
+ std::vector<Vector2i> constant_ge(face_edgeIds.size());
+
+ VectorXd face_area(F.cols());
+
+ for (int i = 0; i < (int)face_edgeIds.size(); ++i) {
+ Vector2i diff[3];
+ Vector2i var[3];
+ Vector2i cst[3];
+ for (int j = 0; j < 3; ++j) {
+ int edgeid = face_edgeIds[i][j];
+ diff[j] = rshift90(edge_diff[edgeid], face_edgeOrients[i][j]);
+ var[j] = rshift90(Vector2i(edgeid * 2 + 1, edgeid * 2 + 2), face_edgeOrients[i][j]);
+ cst[j] = var[j].array().sign();
+ var[j] = var[j].array().abs() - 1;
+ }
+
+ assert(diff[0] + diff[1] + diff[2] == Vector2i::Zero());
+ variable_eq[2 * i + 0] = Vector3i(var[0][0], var[1][0], var[2][0]);
+ constant_eq[2 * i + 0] = Vector3i(cst[0][0], cst[1][0], cst[2][0]);
+ variable_eq[2 * i + 1] = Vector3i(var[0][1], var[1][1], var[2][1]);
+ constant_eq[2 * i + 1] = Vector3i(cst[0][1], cst[1][1], cst[2][1]);
+
+ face_area[i] = diff[0][0] * diff[1][1] - diff[0][1] * diff[1][0];
+ if (face_area[i] < 0) {
+ printf("[SAT] Face %d's area < 0\n", i);
+ for (int j = 0; j < 3; ++j) {
+ int v = F(j, i);
+ if (mark_vertex[v]) continue;
+ Q.push_back(std::make_pair(v, 0));
+ mark_vertex[v] = true;
+ }
+ flip_count += 1;
+ }
+ variable_ge[i] = Vector4i(var[0][0], var[1][1], var[0][1], var[1][0]);
+ constant_ge[i] = Vector2i(cst[0][0] * cst[1][1], cst[0][1] * cst[1][0]);
+ }
+ for (int i = 0; i < (int)variable_eq.size(); ++i) {
+ auto &var = variable_eq[i];
+ auto &cst = constant_eq[i];
+ assert((0 <= var.array()).all());
+ assert((var.array() < value.size()).all());
+ assert(cst[0] * value[var[0]] + cst[1] * value[var[1]] + cst[2] * value[var[2]] == 0);
+ }
+
+ for (int i = 0; i < (int)variable_ge.size(); ++i) {
+ auto &var = variable_ge[i];
+ auto &cst = constant_ge[i];
+ assert((0 <= variable_ge[i].array()).all());
+ assert((variable_ge[i].array() < value.size()).all());
+ if (value[var[0]] * value[var[1]] * cst[0] - value[var[2]] * value[var[3]] * cst[1] < 0) {
+ assert(face_area[i] < 0);
+ flip_count1++;
+ }
+ }
+ assert(flip_count == flip_count1);
+
+ // BFS
+ printf("[SAT] Start BFS: Q.size() = %d\n", (int)Q.size());
+
+ int mark_count = Q.size();
+ while (!Q.empty()) {
+ int vertex = Q.front().first;
+ int depth = Q.front().second;
+ Q.pop_front();
+ mark_count++;
+ int e0 = V2E(vertex);
+
+ for (int e = e0;;) {
+ int v = F((e + 1) % 3, e / 3);
+ if (!mark_vertex[v]) {
+ int undirected_edge_id = face_edgeIds[e / 3][e % 3];
+ int undirected_edge_length = edge_diff[undirected_edge_id].array().abs().sum() > 0;
+ int ndepth = depth + undirected_edge_length;
+ if (ndepth <= max_depth) {
+ if (undirected_edge_length == 0)
+ Q.push_front(std::make_pair(v, ndepth));
+ else
+ Q.push_back(std::make_pair(v, ndepth));
+ mark_vertex[v] = true;
+ }
+ }
+ e = dedge_next_3(E2E(e));
+ if (e == e0) break;
+ }
+ }
+ printf("[SAT] Mark %d vertices out of %d\n", mark_count, (int)V2E.size());
+
+ std::vector<bool> flexible(value.size(), false);
+ for (int i = 0; i < (int)face_edgeIds.size(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ int edgeid = face_edgeIds[i][j];
+ if (mark_vertex[F(j, i)] || mark_vertex[F((j + 1) % 3, i)]) {
+ flexible[edgeid * 2 + 0] = true;
+ flexible[edgeid * 2 + 1] = true;
+ } else {
+ assert(face_area[i] >= 0);
+ }
+ }
+ }
+
+ SolveSatProblem(value.size(), value, flexible, variable_eq, constant_eq, variable_ge,
+ constant_ge);
+
+ for (int i = 0; i < edge_diff.size(); ++i) {
+ edge_diff[i][0] = value[2 * i + 0];
+ edge_diff[i][1] = value[2 * i + 1];
+ }
+}
+
+} // namespace qflow
diff --git a/extern/quadriflow/src/localsat.hpp b/extern/quadriflow/src/localsat.hpp
new file mode 100644
index 00000000000..af952320ebb
--- /dev/null
+++ b/extern/quadriflow/src/localsat.hpp
@@ -0,0 +1,31 @@
+#ifndef __LOCAL_SAT_H
+#define __LOCAL_SAT_H
+
+#include <Eigen/Core>
+#include <vector>
+
+namespace qflow {
+
+using namespace Eigen;
+
+enum class SolverStatus {
+ Sat,
+ Unsat,
+ Timeout,
+};
+
+SolverStatus SolveSatProblem(int n_variable, std::vector<int> &value,
+ const std::vector<bool> flexible, // NOQA
+ const std::vector<Vector3i> &variable_eq,
+ const std::vector<Vector3i> &constant_eq,
+ const std::vector<Vector4i> &variable_ge,
+ const std::vector<Vector2i> &constant_ge,
+ int timeout = 8);
+
+void ExportLocalSat(std::vector<Vector2i> &edge_diff, const std::vector<Vector3i> &face_edgeIds,
+ const std::vector<Vector3i> &face_edgeOrients, const MatrixXi &F,
+ const VectorXi &V2E, const VectorXi &E2E);
+
+} // namespace qflow
+
+#endif
diff --git a/extern/quadriflow/src/main.cpp b/extern/quadriflow/src/main.cpp
new file mode 100644
index 00000000000..18bc4063c42
--- /dev/null
+++ b/extern/quadriflow/src/main.cpp
@@ -0,0 +1,127 @@
+#include "config.hpp"
+#include "field-math.hpp"
+#include "optimizer.hpp"
+#include "parametrizer.hpp"
+#include <stdlib.h>
+
+#ifdef WITH_CUDA
+#include <cuda_runtime.h>
+#endif
+
+using namespace qflow;
+
+Parametrizer field;
+
+int main(int argc, char** argv) {
+ setbuf(stdout, NULL);
+
+#ifdef WITH_CUDA
+ cudaFree(0);
+#endif
+ int t1, t2;
+ std::string input_obj, output_obj;
+ int faces = -1;
+ for (int i = 0; i < argc; ++i) {
+ if (strcmp(argv[i], "-f") == 0) {
+ sscanf(argv[i + 1], "%d", &faces);
+ } else if (strcmp(argv[i], "-i") == 0) {
+ input_obj = argv[i + 1];
+ } else if (strcmp(argv[i], "-o") == 0) {
+ output_obj = argv[i + 1];
+ } else if (strcmp(argv[i], "-sharp") == 0) {
+ field.flag_preserve_sharp = 1;
+ } else if (strcmp(argv[i], "-boundary") == 0) {
+ field.flag_preserve_boundary = 1;
+ } else if (strcmp(argv[i], "-adaptive") == 0) {
+ field.flag_adaptive_scale = 1;
+ } else if (strcmp(argv[i], "-mcf") == 0) {
+ field.flag_minimum_cost_flow = 1;
+ } else if (strcmp(argv[i], "-sat") == 0) {
+ field.flag_aggresive_sat = 1;
+ } else if (strcmp(argv[i], "-seed") == 0) {
+ field.hierarchy.rng_seed = atoi(argv[i + 1]);
+ }
+ }
+ printf("%d %s %s\n", faces, input_obj.c_str(), output_obj.c_str());
+ if (input_obj.size() >= 1) {
+ field.Load(input_obj.c_str());
+ } else {
+ assert(0);
+ // field.Load((std::string(DATA_PATH) + "/fertility.obj").c_str());
+ }
+
+ printf("Initialize...\n");
+ t1 = GetCurrentTime64();
+ field.Initialize(faces);
+ t2 = GetCurrentTime64();
+ printf("Use %lf seconds\n", (t2 - t1) * 1e-3);
+
+ if (field.flag_preserve_boundary) {
+ printf("Add boundary constrains...\n");
+ Hierarchy& mRes = field.hierarchy;
+ mRes.clearConstraints();
+ for (uint32_t i = 0; i < 3 * mRes.mF.cols(); ++i) {
+ if (mRes.mE2E[i] == -1) {
+ uint32_t i0 = mRes.mF(i % 3, i / 3);
+ uint32_t i1 = mRes.mF((i + 1) % 3, i / 3);
+ Vector3d p0 = mRes.mV[0].col(i0), p1 = mRes.mV[0].col(i1);
+ Vector3d edge = p1 - p0;
+ if (edge.squaredNorm() > 0) {
+ edge.normalize();
+ mRes.mCO[0].col(i0) = p0;
+ mRes.mCO[0].col(i1) = p1;
+ mRes.mCQ[0].col(i0) = mRes.mCQ[0].col(i1) = edge;
+ mRes.mCQw[0][i0] = mRes.mCQw[0][i1] = mRes.mCOw[0][i0] = mRes.mCOw[0][i1] =
+ 1.0;
+ }
+ }
+ }
+ mRes.propagateConstraints();
+ }
+
+ printf("Solve Orientation Field...\n");
+ t1 = GetCurrentTime64();
+
+ Optimizer::optimize_orientations(field.hierarchy);
+ field.ComputeOrientationSingularities();
+ t2 = GetCurrentTime64();
+ printf("Use %lf seconds\n", (t2 - t1) * 1e-3);
+
+ if (field.flag_adaptive_scale == 1) {
+ printf("Estimate Slop...\n");
+ t1 = GetCurrentTime64();
+ field.EstimateSlope();
+ t2 = GetCurrentTime64();
+ printf("Use %lf seconds\n", (t2 - t1) * 1e-3);
+ }
+ printf("Solve for scale...\n");
+ t1 = GetCurrentTime64();
+ Optimizer::optimize_scale(field.hierarchy, field.rho, field.flag_adaptive_scale);
+ field.flag_adaptive_scale = 1;
+ t2 = GetCurrentTime64();
+ printf("Use %lf seconds\n", (t2 - t1) * 1e-3);
+
+ printf("Solve for position field...\n");
+ t1 = GetCurrentTime64();
+ Optimizer::optimize_positions(field.hierarchy, field.flag_adaptive_scale);
+
+ field.ComputePositionSingularities();
+ t2 = GetCurrentTime64();
+ printf("Use %lf seconds\n", (t2 - t1) * 1e-3);
+ t1 = GetCurrentTime64();
+ printf("Solve index map...\n");
+ field.ComputeIndexMap();
+ t2 = GetCurrentTime64();
+ printf("Indexmap Use %lf seconds\n", (t2 - t1) * 1e-3);
+ printf("Writing the file...\n");
+
+ if (output_obj.size() < 1) {
+ assert(0);
+ // field.OutputMesh((std::string(DATA_PATH) + "/result.obj").c_str());
+ } else {
+ field.OutputMesh(output_obj.c_str());
+ }
+ printf("finish...\n");
+ // field.LoopFace(2);
+ return 0;
+}
diff --git a/extern/quadriflow/src/merge-vertex.cpp b/extern/quadriflow/src/merge-vertex.cpp
new file mode 100644
index 00000000000..4c7b0a2bb9b
--- /dev/null
+++ b/extern/quadriflow/src/merge-vertex.cpp
@@ -0,0 +1,44 @@
+#include "merge-vertex.hpp"
+
+#include "compare-key.hpp"
+
+#include <map>
+#include <vector>
+
+namespace qflow {
+
+void merge_close(MatrixXd& V, MatrixXi& F, double threshold)
+{
+ std::map<Key3f, int> vid_maps;
+ std::vector<int> vid_compress(V.cols());
+ for (int i = 0; i < V.cols(); ++i) {
+ Key3f key(V(0, i), V(1, i), V(2, i), threshold);
+ if (vid_maps.count(key)) {
+ vid_compress[i] = vid_maps[key];
+ }
+ else {
+ V.col(vid_maps.size()) = V.col(i);
+ vid_compress[i] = vid_maps.size();
+ vid_maps[key] = vid_compress[i];
+ }
+ }
+ printf("Compress Vertex from %d to %d...\n", (int)V.cols(), (int)vid_maps.size());
+ MatrixXd newV(3, vid_maps.size());
+ memcpy(newV.data(), V.data(), sizeof(double) * 3 * vid_maps.size());
+ V = std::move(newV);
+ int f_num = 0;
+ for (int i = 0; i < F.cols(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ F(j, f_num) = vid_compress[F(j, i)];
+ }
+ if (F(0, f_num) != F(1, f_num) && F(0, f_num) != F(2, f_num) && F(1, f_num) != F(2, f_num)) {
+ f_num++;
+ }
+ }
+ printf("Compress Face from %d to %d...\n", (int)F.cols(), f_num);
+ MatrixXi newF(3, f_num);
+ memcpy(newF.data(), F.data(), sizeof(int) * 3 * f_num);
+ F = std::move(newF);
+}
+
+} // namespace qflow
diff --git a/extern/quadriflow/src/merge-vertex.hpp b/extern/quadriflow/src/merge-vertex.hpp
new file mode 100644
index 00000000000..8bcea3d8e4d
--- /dev/null
+++ b/extern/quadriflow/src/merge-vertex.hpp
@@ -0,0 +1,14 @@
+#ifndef MERGE_VERTEX_H_
+#define MERGE_VERTEX_H_
+
+#include <Eigen/Core>
+
+namespace qflow {
+
+using namespace Eigen;
+
+void merge_close(MatrixXd& V, MatrixXi& F, double threshold);
+
+} // namespace qflow
+
+#endif \ No newline at end of file
diff --git a/extern/quadriflow/src/optimizer.cpp b/extern/quadriflow/src/optimizer.cpp
new file mode 100644
index 00000000000..1c59ad0f70c
--- /dev/null
+++ b/extern/quadriflow/src/optimizer.cpp
@@ -0,0 +1,1419 @@
+#include "optimizer.hpp"
+
+#include <Eigen/Sparse>
+#include <cmath>
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <queue>
+#include <unordered_map>
+
+#include "config.hpp"
+#include "field-math.hpp"
+#include "flow.hpp"
+#include "parametrizer.hpp"
+
+namespace qflow {
+
+#ifdef WITH_CUDA
+# include <cuda_runtime.h>
+#endif
+
+#ifndef EIGEN_MPL2_ONLY
+template<class T>
+using LinearSolver = Eigen::SimplicialLLT<T>;
+#else
+template<class T>
+using LinearSolver = Eigen::SparseLU<T>;
+#endif
+
+Optimizer::Optimizer() {}
+
+void Optimizer::optimize_orientations(Hierarchy& mRes) {
+#ifdef WITH_CUDA
+ optimize_orientations_cuda(mRes);
+ printf("%s\n", cudaGetErrorString(cudaDeviceSynchronize()));
+ cudaMemcpy(mRes.mQ[0].data(), mRes.cudaQ[0], sizeof(glm::dvec3) * mRes.mQ[0].cols(),
+ cudaMemcpyDeviceToHost);
+
+#else
+
+ int levelIterations = 6;
+ for (int level = mRes.mN.size() - 1; level >= 0; --level) {
+ AdjacentMatrix& adj = mRes.mAdj[level];
+ const MatrixXd& N = mRes.mN[level];
+ const MatrixXd& CQ = mRes.mCQ[level];
+ const VectorXd& CQw = mRes.mCQw[level];
+ MatrixXd& Q = mRes.mQ[level];
+ auto& phases = mRes.mPhases[level];
+ for (int iter = 0; iter < levelIterations; ++iter) {
+ for (int phase = 0; phase < phases.size(); ++phase) {
+ auto& p = phases[phase];
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int pi = 0; pi < p.size(); ++pi) {
+ int i = p[pi];
+ const Vector3d n_i = N.col(i);
+ double weight_sum = 0.0f;
+ Vector3d sum = Q.col(i);
+ for (auto& link : adj[i]) {
+ const int j = link.id;
+ const double weight = link.weight;
+ if (weight == 0) continue;
+ const Vector3d n_j = N.col(j);
+ Vector3d q_j = Q.col(j);
+ std::pair<Vector3d, Vector3d> value =
+ compat_orientation_extrinsic_4(sum, n_i, q_j, n_j);
+ sum = value.first * weight_sum + value.second * weight;
+ sum -= n_i * n_i.dot(sum);
+ weight_sum += weight;
+ double norm = sum.norm();
+ if (norm > RCPOVERFLOW) sum /= norm;
+ }
+
+ if (CQw.size() > 0) {
+ float cw = CQw[i];
+ if (cw != 0) {
+ std::pair<Vector3d, Vector3d> value =
+ compat_orientation_extrinsic_4(sum, n_i, CQ.col(i), n_i);
+ sum = value.first * (1 - cw) + value.second * cw;
+ sum -= n_i * n_i.dot(sum);
+
+ float norm = sum.norm();
+ if (norm > RCPOVERFLOW) sum /= norm;
+ }
+ }
+
+ if (weight_sum > 0) {
+ Q.col(i) = sum;
+ }
+ }
+ }
+ }
+ if (level > 0) {
+ const MatrixXd& srcField = mRes.mQ[level];
+ const MatrixXi& toUpper = mRes.mToUpper[level - 1];
+ MatrixXd& destField = mRes.mQ[level - 1];
+ const MatrixXd& N = mRes.mN[level - 1];
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int i = 0; i < srcField.cols(); ++i) {
+ for (int k = 0; k < 2; ++k) {
+ int dest = toUpper(k, i);
+ if (dest == -1) continue;
+ Vector3d q = srcField.col(i), n = N.col(dest);
+ destField.col(dest) = q - n * n.dot(q);
+ }
+ }
+ }
+ }
+
+ for (int l = 0; l < mRes.mN.size() - 1; ++l) {
+ const MatrixXd& N = mRes.mN[l];
+ const MatrixXd& N_next = mRes.mN[l + 1];
+ const MatrixXd& Q = mRes.mQ[l];
+ MatrixXd& Q_next = mRes.mQ[l + 1];
+ auto& toUpper = mRes.mToUpper[l];
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int i = 0; i < toUpper.cols(); ++i) {
+ Vector2i upper = toUpper.col(i);
+ Vector3d q0 = Q.col(upper[0]);
+ Vector3d n0 = N.col(upper[0]);
+ Vector3d q;
+
+ if (upper[1] != -1) {
+ Vector3d q1 = Q.col(upper[1]);
+ Vector3d n1 = N.col(upper[1]);
+ auto result = compat_orientation_extrinsic_4(q0, n0, q1, n1);
+ q = result.first + result.second;
+ } else {
+ q = q0;
+ }
+ Vector3d n = N_next.col(i);
+ q -= n.dot(q) * n;
+ if (q.squaredNorm() > RCPOVERFLOW) q.normalize();
+
+ Q_next.col(i) = q;
+ }
+ }
+
+#endif
+}
+
+void Optimizer::optimize_scale(Hierarchy& mRes, VectorXd& rho, int adaptive) {
+ const MatrixXd& N = mRes.mN[0];
+ MatrixXd& Q = mRes.mQ[0];
+ MatrixXd& V = mRes.mV[0];
+ MatrixXd& S = mRes.mS[0];
+ MatrixXd& K = mRes.mK[0];
+ MatrixXi& F = mRes.mF;
+
+ if (adaptive) {
+ std::vector<Eigen::Triplet<double>> lhsTriplets;
+
+ lhsTriplets.reserve(F.cols() * 6);
+ for (int i = 0; i < V.cols(); ++i) {
+ for (int j = 0; j < 2; ++j) {
+ S(j, i) = 1.0;
+ double sc1 = std::max(0.75 * S(j, i), rho[i] * 1.0 / mRes.mScale);
+ S(j, i) = std::min(S(j, i), sc1);
+ }
+ }
+
+ std::vector<std::map<int, double>> entries(V.cols() * 2);
+ double lambda = 1;
+ for (int i = 0; i < entries.size(); ++i) {
+ entries[i][i] = lambda;
+ }
+ for (int i = 0; i < F.cols(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ int v1 = F(j, i);
+ int v2 = F((j + 1) % 3, i);
+ Vector3d diff = V.col(v2) - V.col(v1);
+ Vector3d q_1 = Q.col(v1);
+ Vector3d q_2 = Q.col(v2);
+ Vector3d n_1 = N.col(v1);
+ Vector3d n_2 = N.col(v2);
+ Vector3d q_1_y = n_1.cross(q_1);
+ auto index = compat_orientation_extrinsic_index_4(q_1, n_1, q_2, n_2);
+ int v1_x = v1 * 2, v1_y = v1 * 2 + 1, v2_x = v2 * 2, v2_y = v2 * 2 + 1;
+
+ double dx = diff.dot(q_1);
+ double dy = diff.dot(q_1_y);
+
+ double kx_g = K(0, v1);
+ double ky_g = K(1, v1);
+
+ if (index.first % 2 != index.second % 2) {
+ std::swap(v2_x, v2_y);
+ }
+ double scale_x = (fmin(fmax(1 + kx_g * dy, 0.3), 3));
+ double scale_y = (fmin(fmax(1 + ky_g * dx, 0.3), 3));
+ // (v2_x - scale_x * v1_x)^2 = 0
+ // x^2 - 2s xy + s^2 y^2
+ entries[v2_x][v2_x] += 1;
+ entries[v1_x][v1_x] += scale_x * scale_x;
+ entries[v2_y][v2_y] += 1;
+ entries[v1_y][v1_y] += scale_y * scale_y;
+ auto it = entries[v1_x].find(v2_x);
+ if (it == entries[v1_x].end()) {
+ entries[v1_x][v2_x] = -scale_x;
+ entries[v2_x][v1_x] = -scale_x;
+ entries[v1_y][v2_y] = -scale_y;
+ entries[v2_y][v1_y] = -scale_y;
+ } else {
+ it->second -= scale_x;
+ entries[v2_x][v1_x] -= scale_x;
+ entries[v1_y][v2_y] -= scale_y;
+ entries[v2_y][v1_y] -= scale_y;
+ }
+ }
+ }
+
+ Eigen::SparseMatrix<double> A(V.cols() * 2, V.cols() * 2);
+ VectorXd rhs(V.cols() * 2);
+ rhs.setZero();
+ for (int i = 0; i < entries.size(); ++i) {
+ rhs(i) = lambda * S(i % 2, i / 2);
+ for (auto& rec : entries[i]) {
+ lhsTriplets.push_back(Eigen::Triplet<double>(i, rec.first, rec.second));
+ }
+ }
+ A.setFromTriplets(lhsTriplets.begin(), lhsTriplets.end());
+ LinearSolver<Eigen::SparseMatrix<double>> solver;
+ solver.analyzePattern(A);
+
+ solver.factorize(A);
+
+ VectorXd result = solver.solve(rhs);
+
+ double total_area = 0;
+ for (int i = 0; i < V.cols(); ++i) {
+ S(0, i) = (result(i * 2));
+ S(1, i) = (result(i * 2 + 1));
+ total_area += S(0, i) * S(1, i);
+ }
+ total_area = sqrt(V.cols() / total_area);
+ for (int i = 0; i < V.cols(); ++i) {
+ // S(0, i) *= total_area;
+ // S(1, i) *= total_area;
+ }
+ } else {
+ for (int i = 0; i < V.cols(); ++i) {
+ S(0, i) = 1;
+ S(1, i) = 1;
+ }
+ }
+
+ for (int l = 0; l < mRes.mS.size() - 1; ++l) {
+ const MatrixXd& S = mRes.mS[l];
+ MatrixXd& S_next = mRes.mS[l + 1];
+ auto& toUpper = mRes.mToUpper[l];
+ for (int i = 0; i < toUpper.cols(); ++i) {
+ Vector2i upper = toUpper.col(i);
+ Vector2d q0 = S.col(upper[0]);
+
+ if (upper[1] != -1) {
+ q0 = (q0 + S.col(upper[1])) * 0.5;
+ }
+ S_next.col(i) = q0;
+ }
+ }
+}
+
+void Optimizer::optimize_positions(Hierarchy& mRes, int with_scale) {
+ int levelIterations = 6;
+#ifdef WITH_CUDA
+ optimize_positions_cuda(mRes);
+ cudaMemcpy(mRes.mO[0].data(), mRes.cudaO[0], sizeof(glm::dvec3) * mRes.mO[0].cols(),
+ cudaMemcpyDeviceToHost);
+#else
+ for (int level = mRes.mAdj.size() - 1; level >= 0; --level) {
+ for (int iter = 0; iter < levelIterations; ++iter) {
+ AdjacentMatrix& adj = mRes.mAdj[level];
+ const MatrixXd &N = mRes.mN[level], &Q = mRes.mQ[level], &V = mRes.mV[level];
+ const MatrixXd& CQ = mRes.mCQ[level];
+ const MatrixXd& CO = mRes.mCO[level];
+ const VectorXd& COw = mRes.mCOw[level];
+ MatrixXd& O = mRes.mO[level];
+ MatrixXd& S = mRes.mS[level];
+ auto& phases = mRes.mPhases[level];
+ for (int phase = 0; phase < phases.size(); ++phase) {
+ auto& p = phases[phase];
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int pi = 0; pi < p.size(); ++pi) {
+ int i = p[pi];
+ double scale_x = mRes.mScale;
+ double scale_y = mRes.mScale;
+ if (with_scale) {
+ scale_x *= S(0, i);
+ scale_y *= S(1, i);
+ }
+ double inv_scale_x = 1.0f / scale_x;
+ double inv_scale_y = 1.0f / scale_y;
+ const Vector3d n_i = N.col(i), v_i = V.col(i);
+ Vector3d q_i = Q.col(i);
+
+ Vector3d sum = O.col(i);
+ double weight_sum = 0.0f;
+
+ q_i.normalize();
+ for (auto& link : adj[i]) {
+ const int j = link.id;
+ const double weight = link.weight;
+ if (weight == 0) continue;
+ double scale_x_1 = mRes.mScale;
+ double scale_y_1 = mRes.mScale;
+ if (with_scale) {
+ scale_x_1 *= S(0, j);
+ scale_y_1 *= S(1, j);
+ }
+ double inv_scale_x_1 = 1.0f / scale_x_1;
+ double inv_scale_y_1 = 1.0f / scale_y_1;
+
+ const Vector3d n_j = N.col(j), v_j = V.col(j);
+ Vector3d q_j = Q.col(j), o_j = O.col(j);
+
+ q_j.normalize();
+
+ std::pair<Vector3d, Vector3d> value = compat_position_extrinsic_4(
+ v_i, n_i, q_i, sum, v_j, n_j, q_j, o_j, scale_x, scale_y, inv_scale_x,
+ inv_scale_y, scale_x_1, scale_y_1, inv_scale_x_1, inv_scale_y_1);
+
+ sum = value.first * weight_sum + value.second * weight;
+ weight_sum += weight;
+ if (weight_sum > RCPOVERFLOW) sum /= weight_sum;
+ sum -= n_i.dot(sum - v_i) * n_i;
+ }
+
+ if (COw.size() > 0) {
+ float cw = COw[i];
+ if (cw != 0) {
+ Vector3d co = CO.col(i), cq = CQ.col(i);
+ Vector3d d = co - sum;
+ d -= cq.dot(d) * cq;
+ sum += cw * d;
+ sum -= n_i.dot(sum - v_i) * n_i;
+ }
+ }
+
+ if (weight_sum > 0) {
+ O.col(i) = position_round_4(sum, q_i, n_i, v_i, scale_x, scale_y,
+ inv_scale_x, inv_scale_y);
+ }
+ }
+ }
+ }
+ if (level > 0) {
+ const MatrixXd& srcField = mRes.mO[level];
+ const MatrixXi& toUpper = mRes.mToUpper[level - 1];
+ MatrixXd& destField = mRes.mO[level - 1];
+ const MatrixXd& N = mRes.mN[level - 1];
+ const MatrixXd& V = mRes.mV[level - 1];
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int i = 0; i < srcField.cols(); ++i) {
+ for (int k = 0; k < 2; ++k) {
+ int dest = toUpper(k, i);
+ if (dest == -1) continue;
+ Vector3d o = srcField.col(i), n = N.col(dest), v = V.col(dest);
+ o -= n * n.dot(o - v);
+ destField.col(dest) = o;
+ }
+ }
+ }
+ }
+#endif
+}
+
+void Optimizer::optimize_positions_dynamic(
+ MatrixXi& F, MatrixXd& V, MatrixXd& N, MatrixXd& Q, std::vector<std::vector<int>>& Vset,
+ std::vector<Vector3d>& O_compact, std::vector<Vector4i>& F_compact,
+ std::vector<int>& V2E_compact, std::vector<int>& E2E_compact, double mScale,
+ std::vector<Vector3d>& diffs, std::vector<int>& diff_count,
+ std::map<std::pair<int, int>, int>& o2e, std::vector<int>& sharp_o,
+ std::map<int, std::pair<Vector3d, Vector3d>>& compact_sharp_constraints, int with_scale) {
+ std::set<int> uncertain;
+ for (auto& info : o2e) {
+ if (diff_count[info.second] == 0) {
+ uncertain.insert(info.first.first);
+ uncertain.insert(info.first.second);
+ }
+ }
+ std::vector<int> Vind(O_compact.size(), -1);
+ std::vector<std::list<int>> links(O_compact.size());
+ std::vector<std::list<int>> dedges(O_compact.size());
+ std::vector<std::vector<int>> adj(V.cols());
+ for (int i = 0; i < F.cols(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ int v1 = F(j, i);
+ int v2 = F((j + 1) % 3, i);
+ adj[v1].push_back(v2);
+ }
+ }
+ auto FindNearest = [&]() {
+ for (int i = 0; i < O_compact.size(); ++i) {
+ if (Vind[i] == -1) {
+ double min_dis = 1e30;
+ int min_ind = -1;
+ for (auto v : Vset[i]) {
+ double dis = (V.col(v) - O_compact[i]).squaredNorm();
+ if (dis < min_dis) {
+ min_dis = dis;
+ min_ind = v;
+ }
+ }
+ if (min_ind > -1) {
+ Vind[i] = min_ind;
+ double x = (O_compact[i] - V.col(min_ind)).dot(N.col(min_ind));
+ O_compact[i] -= x * N.col(min_ind);
+ }
+ } else {
+ int current_v = Vind[i];
+ Vector3d n = N.col(current_v);
+ double current_dis = (O_compact[i] - V.col(current_v)).squaredNorm();
+ while (true) {
+ int next_v = -1;
+ for (auto& v : adj[current_v]) {
+ if (N.col(v).dot(n) < cos(10.0 / 180.0 * 3.141592654)) continue;
+ double dis = (O_compact[i] - V.col(v)).squaredNorm();
+ if (dis < current_dis) {
+ current_dis = dis;
+ next_v = v;
+ }
+ }
+ if (next_v == -1) break;
+ // rotate ideal distance
+ Vector3d n1 = N.col(current_v);
+ Vector3d n2 = N.col(next_v);
+ Vector3d axis = n1.cross(n2);
+ double len = axis.norm();
+ double angle = atan2(len, n1.dot(n2));
+ axis.normalized();
+ Matrix3d m = AngleAxisd(angle, axis).toRotationMatrix();
+ for (auto e : dedges[i]) {
+ Vector3d& d = diffs[e];
+ d = m * d;
+ }
+ current_v = next_v;
+ }
+ Vind[i] = current_v;
+ }
+ }
+ };
+
+ auto BuildConnection = [&]() {
+ for (int i = 0; i < links.size(); ++i) {
+ int deid0 = V2E_compact[i];
+ if (deid0 != -1) {
+ std::list<int>& connection = links[i];
+ std::list<int>& dedge = dedges[i];
+ int deid = deid0;
+ do {
+ connection.push_back(F_compact[deid / 4][(deid + 1) % 4]);
+ dedge.push_back(deid);
+ deid = E2E_compact[deid / 4 * 4 + (deid + 3) % 4];
+ } while (deid != -1 && deid != deid0);
+ if (deid == -1) {
+ deid = deid0;
+ do {
+ deid = E2E_compact[deid];
+ if (deid == -1) break;
+ deid = deid / 4 * 4 + (deid + 1) % 4;
+ connection.push_front(F_compact[deid / 4][(deid + 1) % 4]);
+ dedge.push_front(deid);
+ } while (true);
+ }
+ }
+ }
+ };
+
+ std::vector<Vector3d> lines;
+ auto ComputeDistance = [&]() {
+ std::set<int> unobserved;
+ for (auto& info : o2e) {
+ if (diff_count[info.second] == 0) {
+ unobserved.insert(info.first.first);
+ }
+ }
+ while (true) {
+ bool update = false;
+ std::set<int> observed;
+ for (auto& p : unobserved) {
+ std::vector<int> observations, edges;
+ int count = 0;
+ for (auto& e : dedges[p]) {
+ edges.push_back(e);
+ if (diff_count[e]) {
+ count += 1;
+ observations.push_back(1);
+ } else {
+ observations.push_back(0);
+ }
+ }
+ if (count <= 1) continue;
+ update = true;
+ observed.insert(p);
+ for (int i = 0; i < observations.size(); ++i) {
+ if (observations[i] == 1) continue;
+ int j = i;
+ std::list<int> interp;
+ while (observations[j] == 0) {
+ interp.push_front(j);
+ j -= 1;
+ if (j < 0) j = edges.size() - 1;
+ }
+ j = (i + 1) % edges.size();
+ while (observations[j] == 0) {
+ interp.push_back(j);
+ j += 1;
+ if (j == edges.size()) j = 0;
+ }
+ Vector3d dl = diffs[edges[(interp.front() + edges.size() - 1) % edges.size()]];
+ double lenl = dl.norm();
+ Vector3d dr = diffs[edges[(interp.back() + 1) % edges.size()]];
+ double lenr = dr.norm();
+ dl /= lenl;
+ dr /= lenr;
+ Vector3d n = dl.cross(dr).normalized();
+ double angle = atan2(dl.cross(dr).norm(), dl.dot(dr));
+ if (angle < 0) angle += 2 * 3.141592654;
+ Vector3d nc = N.col(Vind[p]);
+ if (n.dot(nc) < 0) {
+ n = -n;
+ angle = 2 * 3.141592654 - angle;
+ }
+ double step = (lenr - lenl) / (interp.size() + 1);
+ angle /= interp.size() + 1;
+ Vector3d dlp = nc.cross(dl).normalized();
+ int t = 0;
+ for (auto q : interp) {
+ t += 1;
+ observations[q] = 1;
+ double ad = angle * t;
+ int e = edges[q];
+ int re = E2E_compact[e];
+ diff_count[e] = 2;
+ diffs[e] = (cos(ad) * dl + sin(ad) * dlp) * (lenl + step * t);
+ if (re != -1) {
+ diff_count[re] = 2;
+ diffs[re] = -diffs[e];
+ }
+ }
+ for (int i = 0; i < edges.size(); ++i) {
+ lines.push_back(O_compact[p]);
+ lines.push_back(O_compact[p] + diffs[edges[i]]);
+ }
+ }
+ }
+ if (!update) break;
+ for (auto& p : observed) unobserved.erase(p);
+ }
+ };
+
+ BuildConnection();
+ int max_iter = 10;
+ for (int iter = 0; iter < max_iter; ++iter) {
+ FindNearest();
+ ComputeDistance();
+
+ std::vector<std::unordered_map<int, double>> entries(O_compact.size() * 2);
+ std::vector<int> fixed_dim(O_compact.size() * 2, 0);
+ for (auto& info : compact_sharp_constraints) {
+ fixed_dim[info.first * 2 + 1] = 1;
+ if (info.second.second.norm() < 0.5) fixed_dim[info.first * 2] = 1;
+ }
+ std::vector<double> b(O_compact.size() * 2);
+ std::vector<double> x(O_compact.size() * 2);
+ std::vector<Vector3d> Q_compact(O_compact.size());
+ std::vector<Vector3d> N_compact(O_compact.size());
+ std::vector<Vector3d> V_compact(O_compact.size());
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int i = 0; i < O_compact.size(); ++i) {
+ Q_compact[i] = Q.col(Vind[i]);
+ N_compact[i] = N.col(Vind[i]);
+ V_compact[i] = V.col(Vind[i]);
+ if (fixed_dim[i * 2 + 1] && !fixed_dim[i * 2]) {
+ Q_compact[i] = compact_sharp_constraints[i].second;
+ V_compact[i] = compact_sharp_constraints[i].first;
+ }
+ }
+ for (int i = 0; i < O_compact.size(); ++i) {
+ Vector3d q = Q_compact[i];
+ Vector3d n = N_compact[i];
+ Vector3d q_y = n.cross(q);
+ auto Vi = V_compact[i];
+ x[i * 2] = (O_compact[i] - Vi).dot(q);
+ x[i * 2 + 1] = (O_compact[i] - Vi).dot(q_y);
+ }
+ for (int i = 0; i < O_compact.size(); ++i) {
+ Vector3d qx = Q_compact[i];
+ Vector3d qy = N_compact[i];
+ qy = qy.cross(qx);
+ auto dedge_it = dedges[i].begin();
+ for (auto it = links[i].begin(); it != links[i].end(); ++it, ++dedge_it) {
+ int j = *it;
+ Vector3d qx2 = Q_compact[j];
+ Vector3d qy2 = N_compact[j];
+ qy2 = qy2.cross(qx2);
+
+ int de = o2e[std::make_pair(i, j)];
+ double lambda = (diff_count[de] == 1) ? 1 : 1;
+ Vector3d target_offset = diffs[de];
+
+ auto Vi = V_compact[i];
+ auto Vj = V_compact[j];
+
+ Vector3d offset = Vj - Vi;
+
+ // target_offset.normalize();
+ // target_offset *= mScale;
+ Vector3d C = target_offset - offset;
+ int vid[] = {j * 2, j * 2 + 1, i * 2, i * 2 + 1};
+ Vector3d weights[] = {qx2, qy2, -qx, -qy};
+ for (int ii = 0; ii < 4; ++ii) {
+ for (int jj = 0; jj < 4; ++jj) {
+ auto it = entries[vid[ii]].find(vid[jj]);
+ if (it == entries[vid[ii]].end()) {
+ entries[vid[ii]][vid[jj]] = lambda * weights[ii].dot(weights[jj]);
+ } else {
+ entries[vid[ii]][vid[jj]] += lambda * weights[ii].dot(weights[jj]);
+ }
+ }
+ b[vid[ii]] += lambda * weights[ii].dot(C);
+ }
+ }
+ }
+
+ // fix sharp edges
+ for (int i = 0; i < entries.size(); ++i) {
+ if (entries[i].size() == 0) {
+ entries[i][i] = 1;
+ b[i] = x[i];
+ }
+ if (fixed_dim[i]) {
+ b[i] = x[i];
+ entries[i].clear();
+ entries[i][i] = 1;
+ } else {
+ std::unordered_map<int, double> newmap;
+ for (auto& rec : entries[i]) {
+ if (fixed_dim[rec.first]) {
+ b[i] -= rec.second * x[rec.first];
+ } else {
+ newmap[rec.first] = rec.second;
+ }
+ }
+ std::swap(entries[i], newmap);
+ }
+ }
+ std::vector<Eigen::Triplet<double>> lhsTriplets;
+ lhsTriplets.reserve(F_compact.size() * 8);
+ Eigen::SparseMatrix<double> A(O_compact.size() * 2, O_compact.size() * 2);
+ VectorXd rhs(O_compact.size() * 2);
+ rhs.setZero();
+ for (int i = 0; i < entries.size(); ++i) {
+ rhs(i) = b[i];
+ for (auto& rec : entries[i]) {
+ lhsTriplets.push_back(Eigen::Triplet<double>(i, rec.first, rec.second));
+ }
+ }
+
+ A.setFromTriplets(lhsTriplets.begin(), lhsTriplets.end());
+
+#ifdef LOG_OUTPUT
+ int t1 = GetCurrentTime64();
+#endif
+
+ // FIXME: IncompleteCholesky Preconditioner will fail here so I fallback to Diagonal one.
+ // I suspected either there is a implementation bug in IncompleteCholesky Preconditioner
+ // or there is a memory corruption somewhere. However, g++'s address sanitizer does not
+ // report anything useful.
+ LinearSolver<Eigen::SparseMatrix<double>> solver;
+ solver.analyzePattern(A);
+ solver.factorize(A);
+ // Eigen::setNbThreads(1);
+ // ConjugateGradient<SparseMatrix<double>, Lower | Upper> solver;
+ // VectorXd x0 = VectorXd::Map(x.data(), x.size());
+ // solver.setMaxIterations(40);
+
+ // solver.compute(A);
+ VectorXd x_new = solver.solve(rhs); // solver.solveWithGuess(rhs, x0);
+
+#ifdef LOG_OUTPUT
+ // std::cout << "[LSQ] n_iteration:" << solver.iterations() << std::endl;
+ // std::cout << "[LSQ] estimated error:" << solver.error() << std::endl;
+ int t2 = GetCurrentTime64();
+ printf("[LSQ] Linear solver uses %lf seconds.\n", (t2 - t1) * 1e-3);
+#endif
+ for (int i = 0; i < O_compact.size(); ++i) {
+ // Vector3d q = Q.col(Vind[i]);
+ Vector3d q = Q_compact[i];
+ // Vector3d n = N.col(Vind[i]);
+ Vector3d n = N_compact[i];
+ Vector3d q_y = n.cross(q);
+ auto Vi = V_compact[i];
+ O_compact[i] = Vi + q * x_new[i * 2] + q_y * x_new[i * 2 + 1];
+ }
+
+ // forgive my hack...
+ if (iter + 1 == max_iter) {
+ for (int iter = 0; iter < 5; ++iter) {
+ for (int i = 0; i < O_compact.size(); ++i) {
+ if (sharp_o[i]) continue;
+ if (dedges[i].size() != 4 || uncertain.count(i)) {
+ Vector3d n(0, 0, 0), v(0, 0, 0);
+ Vector3d v0 = O_compact[i];
+ for (auto e : dedges[i]) {
+ Vector3d v1 = O_compact[F_compact[e / 4][(e + 1) % 4]];
+ Vector3d v2 = O_compact[F_compact[e / 4][(e + 3) % 4]];
+ n += (v1 - v0).cross(v2 - v0);
+ v += v1;
+ }
+ n.normalize();
+ Vector3d offset = v / dedges[i].size() - v0;
+ offset -= offset.dot(n) * n;
+ O_compact[i] += offset;
+ }
+ }
+ }
+ }
+ }
+}
+
+void Optimizer::optimize_positions_sharp(
+ Hierarchy& mRes, std::vector<DEdge>& edge_values, std::vector<Vector2i>& edge_diff,
+ std::vector<int>& sharp_edges, std::set<int>& sharp_vertices,
+ std::map<int, std::pair<Vector3d, Vector3d>>& sharp_constraints, int with_scale) {
+ auto& V = mRes.mV[0];
+ auto& F = mRes.mF;
+ auto& Q = mRes.mQ[0];
+ auto& N = mRes.mN[0];
+ auto& O = mRes.mO[0];
+ auto& S = mRes.mS[0];
+
+ DisajointTree tree(V.cols());
+ for (int i = 0; i < edge_diff.size(); ++i) {
+ if (edge_diff[i].array().abs().sum() == 0) {
+ tree.Merge(edge_values[i].x, edge_values[i].y);
+ }
+ }
+ tree.BuildCompactParent();
+ std::map<int, int> compact_sharp_indices;
+ std::set<DEdge> compact_sharp_edges;
+ for (int i = 0; i < sharp_edges.size(); ++i) {
+ if (sharp_edges[i] == 1) {
+ int v1 = tree.Index(F(i % 3, i / 3));
+ int v2 = tree.Index(F((i + 1) % 3, i / 3));
+ compact_sharp_edges.insert(DEdge(v1, v2));
+ }
+ }
+ for (auto& v : sharp_vertices) {
+ int p = tree.Index(v);
+ if (compact_sharp_indices.count(p) == 0) {
+ int s = compact_sharp_indices.size();
+ compact_sharp_indices[p] = s;
+ }
+ }
+ std::map<int, std::set<int>> sharp_vertices_links;
+ std::set<DEdge> sharp_dedges;
+ for (int i = 0; i < sharp_edges.size(); ++i) {
+ if (sharp_edges[i]) {
+ int v1 = F(i % 3, i / 3);
+ int v2 = F((i + 1) % 3, i / 3);
+ if (sharp_vertices_links.count(v1) == 0) sharp_vertices_links[v1] = std::set<int>();
+ sharp_vertices_links[v1].insert(v2);
+ sharp_dedges.insert(DEdge(v1, v2));
+ }
+ }
+ std::vector<std::vector<int>> sharp_to_original_indices(compact_sharp_indices.size());
+ for (auto& v : sharp_vertices_links) {
+ if (v.second.size() == 2) continue;
+ int p = tree.Index(v.first);
+ sharp_to_original_indices[compact_sharp_indices[p]].push_back(v.first);
+ }
+ for (auto& v : sharp_vertices_links) {
+ if (v.second.size() != 2) continue;
+ int p = tree.Index(v.first);
+ sharp_to_original_indices[compact_sharp_indices[p]].push_back(v.first);
+ }
+
+ for (int i = 0; i < V.cols(); ++i) {
+ if (sharp_vertices.count(i)) continue;
+ int p = tree.Index(i);
+ if (compact_sharp_indices.count(p))
+ sharp_to_original_indices[compact_sharp_indices[p]].push_back(i);
+ }
+
+ int num = sharp_to_original_indices.size();
+ std::vector<std::set<int>> links(sharp_to_original_indices.size());
+ for (int e = 0; e < edge_diff.size(); ++e) {
+ int v1 = edge_values[e].x;
+ int v2 = edge_values[e].y;
+ int p1 = tree.Index(v1);
+ int p2 = tree.Index(v2);
+ if (p1 == p2 || compact_sharp_edges.count(DEdge(p1, p2)) == 0) continue;
+ p1 = compact_sharp_indices[p1];
+ p2 = compact_sharp_indices[p2];
+
+ links[p1].insert(p2);
+ links[p2].insert(p1);
+ }
+
+ std::vector<int> hash(links.size(), 0);
+ std::vector<std::vector<Vector3d>> loops;
+ for (int i = 0; i < num; ++i) {
+ if (hash[i] == 1) continue;
+ if (links[i].size() == 2) {
+ std::vector<int> q;
+ q.push_back(i);
+ hash[i] = 1;
+ int v = i;
+ int prev_v = -1;
+ bool is_loop = false;
+ while (links[v].size() == 2) {
+ int next_v = -1;
+ for (auto nv : links[v])
+ if (nv != prev_v) next_v = nv;
+ if (hash[next_v]) {
+ is_loop = true;
+ break;
+ }
+ if (links[next_v].size() == 2) hash[next_v] = true;
+ q.push_back(next_v);
+ prev_v = v;
+ v = next_v;
+ }
+ if (!is_loop && q.size() >= 2) {
+ std::vector<int> q1;
+ int v = i;
+ int prev_v = q[1];
+ while (links[v].size() == 2) {
+ int next_v = -1;
+ for (auto nv : links[v])
+ if (nv != prev_v) next_v = nv;
+ if (hash[next_v]) {
+ is_loop = true;
+ break;
+ }
+ if (links[next_v].size() == 2) hash[next_v] = true;
+ q1.push_back(next_v);
+ prev_v = v;
+ v = next_v;
+ }
+ std::reverse(q1.begin(), q1.end());
+ q1.insert(q1.end(), q.begin(), q.end());
+ std::swap(q1, q);
+ }
+ if (q.size() < 3) continue;
+ if (is_loop) q.push_back(q.front());
+ double len = 0, scale = 0;
+ std::vector<Vector3d> o(q.size()), new_o(q.size());
+ std::vector<double> sc(q.size());
+
+ for (int i = 0; i < q.size() - 1; ++i) {
+ int v1 = q[i];
+ int v2 = q[i + 1];
+ auto it = links[v1].find(v2);
+ if (it == links[v1].end()) {
+ printf("Non exist!\n");
+ exit(0);
+ }
+ }
+
+ for (int i = 0; i < q.size(); ++i) {
+ if (sharp_to_original_indices[q[i]].size() == 0) {
+ continue;
+ }
+ o[i] = O.col(sharp_to_original_indices[q[i]][0]);
+ Vector3d qx = Q.col(sharp_to_original_indices[q[i]][0]);
+ Vector3d qy = Vector3d(N.col(sharp_to_original_indices[q[i]][0])).cross(qx);
+ int fst = sharp_to_original_indices[q[1]][0];
+ Vector3d dis = (i == 0) ? (Vector3d(O.col(fst)) - o[i]) : o[i] - o[i - 1];
+ if (with_scale)
+ sc[i] = (abs(qx.dot(dis)) > abs(qy.dot(dis)))
+ ? S(0, sharp_to_original_indices[q[i]][0])
+ : S(1, sharp_to_original_indices[q[i]][0]);
+ else
+ sc[i] = 1;
+ new_o[i] = o[i];
+ }
+
+ if (is_loop) {
+ for (int i = 0; i < q.size(); ++i) {
+ Vector3d dir =
+ (o[(i + 1) % q.size()] - o[(i + q.size() - 1) % q.size()]).normalized();
+ for (auto& ind : sharp_to_original_indices[q[i]]) {
+ sharp_constraints[ind] = std::make_pair(o[i], dir);
+ }
+ }
+ } else {
+ for (int i = 0; i < q.size(); ++i) {
+ Vector3d dir(0, 0, 0);
+ if (i != 0 && i + 1 != q.size())
+ dir = (o[i + 1] - o[i - 1]).normalized();
+ else if (links[q[i]].size() == 1) {
+ if (i == 0)
+ dir = (o[i + 1] - o[i]).normalized();
+ else
+ dir = (o[i] - o[i - 1]).normalized();
+ }
+ for (auto& ind : sharp_to_original_indices[q[i]]) {
+ sharp_constraints[ind] = std::make_pair(o[i], dir);
+ }
+ }
+ }
+
+ for (int i = 0; i < q.size() - 1; ++i) {
+ len += (o[i + 1] - o[i]).norm();
+ scale += sc[i];
+ }
+
+ int next_m = q.size() - 1;
+
+ double left_norm = len * sc[0] / scale;
+ int current_v = 0;
+ double current_norm = (o[1] - o[0]).norm();
+ for (int i = 1; i < next_m; ++i) {
+ while (left_norm >= current_norm) {
+ left_norm -= current_norm;
+ current_v += 1;
+ current_norm = (o[current_v + 1] - o[current_v]).norm();
+ }
+ new_o[i] =
+ (o[current_v + 1] * left_norm + o[current_v] * (current_norm - left_norm)) /
+ current_norm;
+ o[current_v] = new_o[i];
+ current_norm -= left_norm;
+ left_norm = len * sc[current_v] / scale;
+ }
+
+ for (int i = 0; i < q.size(); ++i) {
+ for (auto v : sharp_to_original_indices[q[i]]) {
+ O.col(v) = new_o[i];
+ }
+ }
+
+ loops.push_back(new_o);
+ }
+ }
+ return;
+ std::ofstream os("/Users/jingwei/Desktop/sharp.obj");
+ for (int i = 0; i < loops.size(); ++i) {
+ for (auto& v : loops[i]) {
+ os << "v " << v[0] << " " << v[1] << " " << v[2] << "\n";
+ }
+ }
+ int offset = 1;
+ for (int i = 0; i < loops.size(); ++i) {
+ for (int j = 0; j < loops[i].size() - 1; ++j) {
+ os << "l " << offset + j << " " << offset + j + 1 << "\n";
+ }
+ offset += loops[i].size();
+ }
+ os.close();
+ exit(0);
+}
+
+void Optimizer::optimize_positions_fixed(
+ Hierarchy& mRes, std::vector<DEdge>& edge_values, std::vector<Vector2i>& edge_diff,
+ std::set<int>& sharp_vertices, std::map<int, std::pair<Vector3d, Vector3d>>& sharp_constraints,
+ int with_scale) {
+ auto& V = mRes.mV[0];
+ auto& F = mRes.mF;
+ auto& Q = mRes.mQ[0];
+ auto& N = mRes.mN[0];
+ auto& O = mRes.mO[0];
+ auto& S = mRes.mS[0];
+
+ DisajointTree tree(V.cols());
+ for (int i = 0; i < edge_diff.size(); ++i) {
+ if (edge_diff[i].array().abs().sum() == 0) {
+ tree.Merge(edge_values[i].x, edge_values[i].y);
+ }
+ }
+ tree.BuildCompactParent();
+ int num = tree.CompactNum();
+
+ // Find the most descriptive vertex
+ std::vector<Vector3d> v_positions(num, Vector3d(0, 0, 0));
+ std::vector<int> v_count(num);
+ std::vector<double> v_distance(num, 1e30);
+ std::vector<int> v_index(num, -1);
+
+ for (int i = 0; i < V.cols(); ++i) {
+ v_positions[tree.Index(i)] += O.col(i);
+ v_count[tree.Index(i)] += 1;
+ }
+ for (int i = 0; i < num; ++i) {
+ if (v_count[i] > 0) v_positions[i] /= v_count[i];
+ }
+ for (int i = 0; i < V.cols(); ++i) {
+ int p = tree.Index(i);
+ double dis = (v_positions[p] - V.col(i)).squaredNorm();
+ if (dis < v_distance[p]) {
+ v_distance[p] = dis;
+ v_index[p] = i;
+ }
+ }
+
+ std::set<int> compact_sharp_vertices;
+ for (auto& v : sharp_vertices) {
+ v_positions[tree.Index(v)] = O.col(v);
+ v_index[tree.Index(v)] = v;
+ V.col(v) = O.col(v);
+ compact_sharp_vertices.insert(tree.Index(v));
+ }
+ std::vector<std::map<int, std::pair<int, Vector3d>>> ideal_distances(tree.CompactNum());
+ for (int e = 0; e < edge_diff.size(); ++e) {
+ int v1 = edge_values[e].x;
+ int v2 = edge_values[e].y;
+
+ int p1 = tree.Index(v1);
+ int p2 = tree.Index(v2);
+ int q1 = v_index[p1];
+ int q2 = v_index[p2];
+
+ Vector3d q_1 = Q.col(v1);
+ Vector3d q_2 = Q.col(v2);
+
+ Vector3d n_1 = N.col(v1);
+ Vector3d n_2 = N.col(v2);
+ Vector3d q_1_y = n_1.cross(q_1);
+ Vector3d q_2_y = n_2.cross(q_2);
+ auto index = compat_orientation_extrinsic_index_4(q_1, n_1, q_2, n_2);
+ double s_x1 = S(0, v1), s_y1 = S(1, v1);
+ double s_x2 = S(0, v2), s_y2 = S(1, v2);
+ int rank_diff = (index.second + 4 - index.first) % 4;
+ if (rank_diff % 2 == 1) std::swap(s_x2, s_y2);
+ Vector3d qd_x = 0.5 * (rotate90_by(q_2, n_2, rank_diff) + q_1);
+ Vector3d qd_y = 0.5 * (rotate90_by(q_2_y, n_2, rank_diff) + q_1_y);
+ double scale_x = (with_scale ? 0.5 * (s_x1 + s_x2) : 1) * mRes.mScale;
+ double scale_y = (with_scale ? 0.5 * (s_y1 + s_y2) : 1) * mRes.mScale;
+ Vector2i diff = edge_diff[e];
+
+ Vector3d origin1 =
+ /*(sharp_constraints.count(q1)) ? sharp_constraints[q1].first : */ V.col(q1);
+ Vector3d origin2 =
+ /*(sharp_constraints.count(q2)) ? sharp_constraints[q2].first : */ V.col(q2);
+ Vector3d C = diff[0] * scale_x * qd_x + diff[1] * scale_y * qd_y + origin1 - origin2;
+ auto it = ideal_distances[p1].find(p2);
+ if (it == ideal_distances[p1].end()) {
+ ideal_distances[p1][p2] = std::make_pair(1, C);
+ } else {
+ it->second.first += 1;
+ it->second.second += C;
+ }
+ }
+
+ std::vector<std::unordered_map<int, double>> entries(num * 2);
+ std::vector<double> b(num * 2);
+
+ for (int m = 0; m < num; ++m) {
+ int v1 = v_index[m];
+ for (auto& info : ideal_distances[m]) {
+ int v2 = v_index[info.first];
+ Vector3d q_1 = Q.col(v1);
+ Vector3d q_2 = Q.col(v2);
+ if (sharp_constraints.count(v1)) {
+ Vector3d d = sharp_constraints[v1].second;
+ if (d != Vector3d::Zero()) q_1 = d;
+ }
+ if (sharp_constraints.count(v2)) {
+ Vector3d d = sharp_constraints[v2].second;
+ if (d != Vector3d::Zero()) q_2 = d;
+ }
+
+ Vector3d n_1 = N.col(v1);
+ Vector3d n_2 = N.col(v2);
+ Vector3d q_1_y = n_1.cross(q_1);
+ Vector3d q_2_y = n_2.cross(q_2);
+ Vector3d weights[] = {q_2, q_2_y, -q_1, -q_1_y};
+ int vid[] = {info.first * 2, info.first * 2 + 1, m * 2, m * 2 + 1};
+ Vector3d dis = info.second.second / info.second.first;
+ double lambda = 1;
+ if (sharp_vertices.count(v1) && sharp_vertices.count(v2)) lambda = 1;
+ for (int i = 0; i < 4; ++i) {
+ for (int j = 0; j < 4; ++j) {
+ auto it = entries[vid[i]].find(vid[j]);
+ if (it == entries[vid[i]].end()) {
+ entries[vid[i]][vid[j]] = weights[i].dot(weights[j]) * lambda;
+ } else {
+ entries[vid[i]][vid[j]] += weights[i].dot(weights[j]) * lambda;
+ }
+ }
+ b[vid[i]] += weights[i].dot(dis) * lambda;
+ }
+ }
+ }
+
+ std::vector<int> fixed_dim(num * 2, 0);
+ std::vector<double> x(num * 2);
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int i = 0; i < num; ++i) {
+ int p = v_index[i];
+ Vector3d q = Q.col(p);
+
+ if (sharp_constraints.count(p)) {
+ Vector3d dir = sharp_constraints[p].second;
+ fixed_dim[i * 2 + 1] = 1;
+ if (dir != Vector3d::Zero()) {
+ q = dir;
+ } else
+ fixed_dim[i * 2] = 1;
+ }
+ Vector3d n = N.col(p);
+ Vector3d q_y = n.cross(q);
+ x[i * 2] = (v_positions[i] - V.col(p)).dot(q);
+ x[i * 2 + 1] = (v_positions[i] - V.col(p)).dot(q_y);
+ }
+
+ // fix sharp edges
+ for (int i = 0; i < entries.size(); ++i) {
+ if (fixed_dim[i]) {
+ b[i] = x[i];
+ entries[i].clear();
+ entries[i][i] = 1;
+ } else {
+ std::unordered_map<int, double> newmap;
+ for (auto& rec : entries[i]) {
+ if (fixed_dim[rec.first]) {
+ b[i] -= rec.second * x[rec.first];
+ } else {
+ newmap[rec.first] = rec.second;
+ }
+ }
+ std::swap(entries[i], newmap);
+ }
+ }
+ for (int i = 0; i < entries.size(); ++i) {
+ if (entries[i].size() == 0) {
+ entries[i][i] = 1;
+ }
+ }
+
+ std::vector<Eigen::Triplet<double>> lhsTriplets;
+ lhsTriplets.reserve(F.cols() * 6);
+ Eigen::SparseMatrix<double> A(num * 2, num * 2);
+ VectorXd rhs(num * 2);
+ rhs.setZero();
+ for (int i = 0; i < entries.size(); ++i) {
+ rhs(i) = b[i];
+ if (std::isnan(b[i])) {
+ printf("Equation has nan!\n");
+ exit(0);
+ }
+ for (auto& rec : entries[i]) {
+ lhsTriplets.push_back(Eigen::Triplet<double>(i, rec.first, rec.second));
+ if (std::isnan(rec.second)) {
+ printf("Equation has nan!\n");
+ exit(0);
+ }
+ }
+ }
+ A.setFromTriplets(lhsTriplets.begin(), lhsTriplets.end());
+
+#ifdef LOG_OUTPUT
+ int t1 = GetCurrentTime64();
+#endif
+ /*
+ Eigen::setNbThreads(1);
+ ConjugateGradient<SparseMatrix<double>, Lower | Upper> solver;
+ VectorXd x0 = VectorXd::Map(x.data(), x.size());
+ solver.setMaxIterations(40);
+
+ solver.compute(A);
+ */
+ LinearSolver<Eigen::SparseMatrix<double>> solver;
+ solver.analyzePattern(A);
+ solver.factorize(A);
+
+ VectorXd x_new = solver.solve(rhs);
+#ifdef LOG_OUTPUT
+ // std::cout << "[LSQ] n_iteration:" << solver.iterations() << std::endl;
+ // std::cout << "[LSQ] estimated error:" << solver.error() << std::endl;
+ int t2 = GetCurrentTime64();
+ printf("[LSQ] Linear solver uses %lf seconds.\n", (t2 - t1) * 1e-3);
+#endif
+
+ for (int i = 0; i < x.size(); ++i) {
+ if (!std::isnan(x_new[i])) {
+ if (!fixed_dim[i / 2 * 2 + 1]) {
+ double total = 0;
+ for (auto& res : entries[i]) {
+ double t = x_new[res.first];
+ if (std::isnan(t)) t = 0;
+ total += t * res.second;
+ }
+ }
+ x[i] = x_new[i];
+ }
+ }
+
+ for (int i = 0; i < O.cols(); ++i) {
+ int p = tree.Index(i);
+ int c = v_index[p];
+ Vector3d q = Q.col(c);
+ if (fixed_dim[p * 2 + 1]) {
+ Vector3d dir = sharp_constraints[c].second;
+ if (dir != Vector3d::Zero()) q = dir;
+ }
+ Vector3d n = N.col(c);
+ Vector3d q_y = n.cross(q);
+ O.col(i) = V.col(c) + q * x[p * 2] + q_y * x[p * 2 + 1];
+ }
+}
+
+void Optimizer::optimize_integer_constraints(Hierarchy& mRes, std::map<int, int>& singularities,
+ bool use_minimum_cost_flow) {
+ int edge_capacity = 2;
+ bool fullFlow = false;
+ std::vector<std::vector<int>>& AllowChange = mRes.mAllowChanges;
+ for (int level = mRes.mToUpperEdges.size(); level >= 0; --level) {
+ auto& EdgeDiff = mRes.mEdgeDiff[level];
+ auto& FQ = mRes.mFQ[level];
+ auto& F2E = mRes.mF2E[level];
+ auto& E2F = mRes.mE2F[level];
+
+ int iter = 0;
+ while (!fullFlow) {
+ std::vector<Vector4i> edge_to_constraints(E2F.size() * 2, Vector4i(-1, 0, -1, 0));
+ std::vector<int> initial(F2E.size() * 2, 0);
+ for (int i = 0; i < F2E.size(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ int e = F2E[i][j];
+ Vector2i index = rshift90(Vector2i(e * 2 + 1, e * 2 + 2), FQ[i][j]);
+ for (int k = 0; k < 2; ++k) {
+ int l = abs(index[k]);
+ int s = index[k] / l;
+ int ind = l - 1;
+ int equationID = i * 2 + k;
+ if (edge_to_constraints[ind][0] == -1) {
+ edge_to_constraints[ind][0] = equationID;
+ edge_to_constraints[ind][1] = s;
+ } else {
+ edge_to_constraints[ind][2] = equationID;
+ edge_to_constraints[ind][3] = s;
+ }
+ initial[equationID] += s * EdgeDiff[ind / 2][ind % 2];
+ }
+ }
+ }
+ std::vector<std::pair<Vector2i, int>> arcs;
+ std::vector<int> arc_ids;
+ for (int i = 0; i < edge_to_constraints.size(); ++i) {
+ if (AllowChange[level][i] == 0) continue;
+ if (edge_to_constraints[i][0] == -1 || edge_to_constraints[i][2] == -1) continue;
+ if (edge_to_constraints[i][1] == -edge_to_constraints[i][3]) {
+ int v1 = edge_to_constraints[i][0];
+ int v2 = edge_to_constraints[i][2];
+ if (edge_to_constraints[i][1] < 0) std::swap(v1, v2);
+ int current_v = EdgeDiff[i / 2][i % 2];
+ arcs.push_back(std::make_pair(Vector2i(v1, v2), current_v));
+ if (AllowChange[level][i] == 1)
+ arc_ids.push_back(i + 1);
+ else {
+ arc_ids.push_back(-(i + 1));
+ }
+ }
+ }
+ int supply = 0;
+ int demand = 0;
+ for (int i = 0; i < initial.size(); ++i) {
+ int init_val = initial[i];
+ if (init_val > 0) {
+ arcs.push_back(std::make_pair(Vector2i(-1, i), initial[i]));
+ supply += init_val;
+ } else if (init_val < 0) {
+ demand -= init_val;
+ arcs.push_back(std::make_pair(Vector2i(i, initial.size()), -init_val));
+ }
+ }
+
+ std::unique_ptr<MaxFlowHelper> solver = nullptr;
+ if (use_minimum_cost_flow && level == mRes.mToUpperEdges.size()) {
+ lprintf("network simplex MCF is used\n");
+ solver = std::make_unique<NetworkSimplexFlowHelper>();
+ } else if (supply < 20) {
+ solver = std::make_unique<ECMaxFlowHelper>();
+ } else {
+ solver = std::make_unique<BoykovMaxFlowHelper>();
+ }
+
+#ifdef WITH_GUROBI
+ if (use_minimum_cost_flow && level == mRes.mToUpperEdges.size()) {
+ solver = std::make_unique<GurobiFlowHelper>();
+ }
+#endif
+ solver->resize(initial.size() + 2, arc_ids.size());
+
+ std::set<int> ids;
+ for (int i = 0; i < arcs.size(); ++i) {
+ int v1 = arcs[i].first[0] + 1;
+ int v2 = arcs[i].first[1] + 1;
+ int c = arcs[i].second;
+ if (v1 == 0 || v2 == initial.size() + 1) {
+ solver->addEdge(v1, v2, c, 0, -1);
+ } else {
+ if (arc_ids[i] > 0)
+ solver->addEdge(v1, v2, std::max(0, c + edge_capacity),
+ std::max(0, -c + edge_capacity), arc_ids[i] - 1);
+ else {
+ if (c > 0)
+ solver->addEdge(v1, v2, std::max(0, c - 1),
+ std::max(0, -c + edge_capacity), -1 - arc_ids[i]);
+ else
+ solver->addEdge(v1, v2, std::max(0, c + edge_capacity),
+ std::max(0, -c - 1), -1 - arc_ids[i]);
+ }
+ }
+ }
+ int flow_count = solver->compute();
+
+ solver->applyTo(EdgeDiff);
+
+ lprintf("flow_count = %d, supply = %d\n", flow_count, supply);
+ if (flow_count == supply) fullFlow = true;
+ if (level != 0 || fullFlow) break;
+ edge_capacity += 1;
+ iter++;
+ if (iter == 10) {
+ /* Probably won't converge. */
+ break;
+ }
+ lprintf("Not full flow, edge_capacity += 1\n");
+ }
+
+ if (level != 0) {
+ auto& nEdgeDiff = mRes.mEdgeDiff[level - 1];
+ auto& toUpper = mRes.mToUpperEdges[level - 1];
+ auto& toUpperOrients = mRes.mToUpperOrients[level - 1];
+ for (int i = 0; i < toUpper.size(); ++i) {
+ if (toUpper[i] >= 0) {
+ int orient = (4 - toUpperOrients[i]) % 4;
+ nEdgeDiff[i] = rshift90(EdgeDiff[toUpper[i]], orient);
+ }
+ }
+ }
+ }
+}
+
+#ifdef WITH_CUDA
+
+void Optimizer::optimize_orientations_cuda(Hierarchy& mRes) {
+ int levelIterations = 6;
+ for (int level = mRes.mN.size() - 1; level >= 0; --level) {
+ Link* adj = mRes.cudaAdj[level];
+ int* adjOffset = mRes.cudaAdjOffset[level];
+ glm::dvec3* N = mRes.cudaN[level];
+ glm::dvec3* Q = mRes.cudaQ[level];
+ auto& phases = mRes.cudaPhases[level];
+ for (int iter = 0; iter < levelIterations; ++iter) {
+ for (int phase = 0; phase < phases.size(); ++phase) {
+ int* p = phases[phase];
+ UpdateOrientation(p, mRes.mPhases[level][phase].size(), N, Q, adj, adjOffset,
+ mRes.mAdj[level][phase].size());
+ }
+ }
+ if (level > 0) {
+ glm::dvec3* srcField = mRes.cudaQ[level];
+ glm::ivec2* toUpper = mRes.cudaToUpper[level - 1];
+ glm::dvec3* destField = mRes.cudaQ[level - 1];
+ glm::dvec3* N = mRes.cudaN[level - 1];
+ PropagateOrientationUpper(srcField, mRes.mQ[level].cols(), toUpper, N, destField);
+ }
+ }
+
+ for (int l = 0; l < mRes.mN.size() - 1; ++l) {
+ glm::dvec3* N = mRes.cudaN[l];
+ glm::dvec3* N_next = mRes.cudaN[l + 1];
+ glm::dvec3* Q = mRes.cudaQ[l];
+ glm::dvec3* Q_next = mRes.cudaQ[l + 1];
+ glm::ivec2* toUpper = mRes.cudaToUpper[l];
+
+ PropagateOrientationLower(toUpper, Q, N, Q_next, N_next, mRes.mToUpper[l].cols());
+ }
+}
+
+void Optimizer::optimize_positions_cuda(Hierarchy& mRes) {
+ int levelIterations = 6;
+ for (int level = mRes.mAdj.size() - 1; level >= 0; --level) {
+ Link* adj = mRes.cudaAdj[level];
+ int* adjOffset = mRes.cudaAdjOffset[level];
+ glm::dvec3* N = mRes.cudaN[level];
+ glm::dvec3* Q = mRes.cudaQ[level];
+ glm::dvec3* V = mRes.cudaV[level];
+ glm::dvec3* O = mRes.cudaO[level];
+ std::vector<int*> phases = mRes.cudaPhases[level];
+ for (int iter = 0; iter < levelIterations; ++iter) {
+ for (int phase = 0; phase < phases.size(); ++phase) {
+ int* p = phases[phase];
+ UpdatePosition(p, mRes.mPhases[level][phase].size(), N, Q, adj, adjOffset,
+ mRes.mAdj[level][phase].size(), V, O, mRes.mScale);
+ }
+ }
+ if (level > 0) {
+ glm::dvec3* srcField = mRes.cudaO[level];
+ glm::ivec2* toUpper = mRes.cudaToUpper[level - 1];
+ glm::dvec3* destField = mRes.cudaO[level - 1];
+ glm::dvec3* N = mRes.cudaN[level - 1];
+ glm::dvec3* V = mRes.cudaV[level - 1];
+ PropagatePositionUpper(srcField, mRes.mO[level].cols(), toUpper, N, V, destField);
+ }
+ }
+}
+
+#endif
+
+} // namespace qflow
diff --git a/extern/quadriflow/src/optimizer.hpp b/extern/quadriflow/src/optimizer.hpp
new file mode 100644
index 00000000000..ad6fa720a6e
--- /dev/null
+++ b/extern/quadriflow/src/optimizer.hpp
@@ -0,0 +1,56 @@
+#ifndef OPTIMIZER_H_
+#define OPTIMIZER_H_
+#include "config.hpp"
+#include "field-math.hpp"
+#include "hierarchy.hpp"
+
+namespace qflow {
+
+class Optimizer {
+ public:
+ Optimizer();
+ static void optimize_orientations(Hierarchy& mRes);
+ static void optimize_scale(Hierarchy& mRes, VectorXd& rho, int adaptive);
+ static void optimize_positions(Hierarchy& mRes, int with_scale = 0);
+ static void optimize_integer_constraints(Hierarchy& mRes, std::map<int, int>& singularities,
+ bool use_minimum_cost_flow);
+ static void optimize_positions_fixed(
+ Hierarchy& mRes, std::vector<DEdge>& edge_values, std::vector<Vector2i>& edge_diff,
+ std::set<int>& sharp_vertices,
+ std::map<int, std::pair<Vector3d, Vector3d>>& sharp_constraints, int with_scale = 0);
+ static void optimize_positions_sharp(
+ Hierarchy& mRes, std::vector<DEdge>& edge_values, std::vector<Vector2i>& edge_diff,
+ std::vector<int>& sharp_edges, std::set<int>& sharp_vertices,
+ std::map<int, std::pair<Vector3d, Vector3d>>& sharp_constraints, int with_scale = 0);
+ static void optimize_positions_dynamic(
+ MatrixXi& F, MatrixXd& V, MatrixXd& N, MatrixXd& Q, std::vector<std::vector<int>>& Vset,
+ std::vector<Vector3d>& O_compact, std::vector<Vector4i>& F_compact,
+ std::vector<int>& V2E_compact, std::vector<int>& E2E_compact, double mScale,
+ std::vector<Vector3d>& diffs, std::vector<int>& diff_count,
+ std::map<std::pair<int, int>, int>& o2e, std::vector<int>& sharp_o,
+ std::map<int, std::pair<Vector3d, Vector3d>>& compact_sharp_constraints, int with_scale);
+#ifdef WITH_CUDA
+ static void optimize_orientations_cuda(Hierarchy& mRes);
+ static void optimize_positions_cuda(Hierarchy& mRes);
+#endif
+};
+
+#ifdef WITH_CUDA
+extern void UpdateOrientation(int* phase, int num_phases, glm::dvec3* N, glm::dvec3* Q, Link* adj,
+ int* adjOffset, int num_adj);
+extern void PropagateOrientationUpper(glm::dvec3* srcField, int num_orientation,
+ glm::ivec2* toUpper, glm::dvec3* N, glm::dvec3* destField);
+extern void PropagateOrientationLower(glm::ivec2* toUpper, glm::dvec3* Q, glm::dvec3* N,
+ glm::dvec3* Q_next, glm::dvec3* N_next, int num_toUpper);
+
+extern void UpdatePosition(int* phase, int num_phases, glm::dvec3* N, glm::dvec3* Q, Link* adj,
+ int* adjOffset, int num_adj, glm::dvec3* V, glm::dvec3* O,
+ double scale);
+extern void PropagatePositionUpper(glm::dvec3* srcField, int num_position, glm::ivec2* toUpper,
+ glm::dvec3* N, glm::dvec3* V, glm::dvec3* destField);
+
+#endif
+
+} // namespace qflow
+
+#endif
diff --git a/extern/quadriflow/src/parametrizer-flip.cpp b/extern/quadriflow/src/parametrizer-flip.cpp
new file mode 100644
index 00000000000..67b6ebbb8e2
--- /dev/null
+++ b/extern/quadriflow/src/parametrizer-flip.cpp
@@ -0,0 +1,583 @@
+#include "dedge.hpp"
+#include "parametrizer.hpp"
+
+#include <algorithm>
+#include <queue>
+#include <unordered_map>
+#include <vector>
+
+namespace qflow {
+
+double Parametrizer::QuadEnergy(std::vector<int>& loop_vertices, std::vector<Vector4i>& res_quads,
+ int level) {
+ if (loop_vertices.size() < 4) return 0;
+ if (loop_vertices.size() == 4) {
+ double energy = 0;
+ for (int j = 0; j < 4; ++j) {
+ int v0 = loop_vertices[j];
+ int v2 = loop_vertices[(j + 1) % 4];
+ int v1 = loop_vertices[(j + 3) % 4];
+ Vector3d pt1 = (O_compact[v1] - O_compact[v0]).normalized();
+ Vector3d pt2 = (O_compact[v2] - O_compact[v0]).normalized();
+ Vector3d n = pt1.cross(pt2);
+ double sina = n.norm();
+ if (n.dot(N_compact[v0]) < 0) sina = -sina;
+ double cosa = pt1.dot(pt2);
+ double angle = atan2(sina, cosa) / 3.141592654 * 180.0;
+ if (angle < 0) angle = 360 + angle;
+ energy += angle * angle;
+ }
+ res_quads.push_back(
+ Vector4i(loop_vertices[0], loop_vertices[3], loop_vertices[2], loop_vertices[1]));
+ return energy;
+ }
+ double max_energy = 1e30;
+ for (int seg1 = 2; seg1 < loop_vertices.size(); seg1 += 2) {
+ for (int seg2 = seg1 + 1; seg2 < loop_vertices.size(); seg2 += 2) {
+ std::vector<Vector4i> quads[4];
+ std::vector<int> vertices = {loop_vertices[0], loop_vertices[1], loop_vertices[seg1],
+ loop_vertices[seg2]};
+ double energy = 0;
+ energy += QuadEnergy(vertices, quads[0], level + 1);
+ if (seg1 > 2) {
+ std::vector<int> vertices(loop_vertices.begin() + 1, loop_vertices.begin() + seg1);
+ vertices.push_back(loop_vertices[seg1]);
+ energy += QuadEnergy(vertices, quads[1], level + 1);
+ }
+ if (seg2 != seg1 + 1) {
+ std::vector<int> vertices(loop_vertices.begin() + seg1,
+ loop_vertices.begin() + seg2);
+ vertices.push_back(loop_vertices[seg2]);
+ energy += QuadEnergy(vertices, quads[2], level + 2);
+ }
+ if (seg2 + 1 != loop_vertices.size()) {
+ std::vector<int> vertices(loop_vertices.begin() + seg2, loop_vertices.end());
+ vertices.push_back(loop_vertices[0]);
+ energy += QuadEnergy(vertices, quads[3], level + 1);
+ }
+ if (max_energy > energy) {
+ max_energy = energy;
+ res_quads.clear();
+ for (int i = 0; i < 4; ++i) {
+ for (auto& v : quads[i]) {
+ res_quads.push_back(v);
+ }
+ }
+ }
+ }
+ }
+ return max_energy;
+}
+
+void Parametrizer::FixHoles(std::vector<int>& loop_vertices) {
+ std::vector<std::vector<int>> loop_vertices_array;
+ std::unordered_map<int, int> map_loops;
+ for (int i = 0; i < loop_vertices.size(); ++i) {
+ if (map_loops.count(loop_vertices[i])) {
+ int j = map_loops[loop_vertices[i]];
+ loop_vertices_array.push_back(std::vector<int>());
+ if (i - j > 3 && (i - j) % 2 == 0) {
+ for (int k = j; k < i; ++k) {
+ if (map_loops.count(loop_vertices[k])) {
+ loop_vertices_array.back().push_back(loop_vertices[k]);
+ map_loops.erase(loop_vertices[k]);
+ }
+ }
+ }
+ }
+ map_loops[loop_vertices[i]] = i;
+ }
+ if (map_loops.size() >= 3) {
+ loop_vertices_array.push_back(std::vector<int>());
+ for (int k = 0; k < loop_vertices.size(); ++k) {
+ if (map_loops.count(loop_vertices[k])) {
+ if (map_loops.count(loop_vertices[k])) {
+ loop_vertices_array.back().push_back(loop_vertices[k]);
+ map_loops.erase(loop_vertices[k]);
+ }
+ }
+ }
+ }
+ for (int i = 0; i < loop_vertices_array.size(); ++i) {
+ auto& loop_vertices = loop_vertices_array[i];
+ if (loop_vertices.size() == 0) return;
+ std::vector<Vector4i> quads;
+#ifdef LOG_OUTPUT
+// printf("Compute energy for loop: %d\n", (int)loop_vertices.size());
+#endif
+ QuadEnergy(loop_vertices, quads, 0);
+#ifdef LOG_OUTPUT
+// printf("quads: %d\n", quads.size());
+#endif
+ for (auto& p : quads) {
+ bool flag = false;
+ for (int j = 0; j < 4; ++j) {
+ int v1 = p[j];
+ int v2 = p[(j + 1) % 4];
+ auto key = std::make_pair(v1, v2);
+ if (Quad_edges.count(key)) {
+ flag = true;
+ break;
+ }
+ }
+ if (!flag) {
+ for (int j = 0; j < 4; ++j) {
+ int v1 = p[j];
+ int v2 = p[(j + 1) % 4];
+ auto key = std::make_pair(v1, v2);
+ Quad_edges.insert(key);
+ }
+ F_compact.push_back(p);
+ }
+ }
+ }
+}
+
+void Parametrizer::FixHoles() {
+ for (int i = 0; i < F_compact.size(); ++i) {
+ for (int j = 0; j < 4; ++j) {
+ int v1 = F_compact[i][j];
+ int v2 = F_compact[i][(j + 1) % 4];
+ auto key = std::make_pair(v1, v2);
+ Quad_edges.insert(key);
+ }
+ }
+ std::vector<int> detected_boundary(E2E_compact.size(), 0);
+ for (int i = 0; i < E2E_compact.size(); ++i) {
+ if (detected_boundary[i] != 0 || E2E_compact[i] != -1) continue;
+ std::vector<int> loop_edges;
+ int current_e = i;
+
+ while (detected_boundary[current_e] == 0) {
+ detected_boundary[current_e] = 1;
+ loop_edges.push_back(current_e);
+ current_e = current_e / 4 * 4 + (current_e + 1) % 4;
+ while (E2E_compact[current_e] != -1) {
+ current_e = E2E_compact[current_e];
+ current_e = current_e / 4 * 4 + (current_e + 1) % 4;
+ }
+ }
+ std::vector<int> loop_vertices(loop_edges.size());
+ for (int j = 0; j < loop_edges.size(); ++j) {
+ loop_vertices[j] = F_compact[loop_edges[j] / 4][loop_edges[j] % 4];
+ }
+ if (loop_vertices.size() < 25) FixHoles(loop_vertices);
+ }
+}
+
+void Parametrizer::FixFlipHierarchy() {
+ Hierarchy fh;
+ fh.DownsampleEdgeGraph(face_edgeOrients, face_edgeIds, edge_diff, allow_changes, -1);
+ fh.FixFlip();
+ fh.UpdateGraphValue(face_edgeOrients, face_edgeIds, edge_diff);
+}
+
+void Parametrizer::FixFlipSat() {
+#ifdef LOG_OUTPUT
+ printf("Solving SAT!\n");
+#endif
+
+ if (!this->flag_aggresive_sat) return;
+
+ for (int threshold = 1; threshold <= 4; ++threshold) {
+ lprintf("[FixFlipSat] threshold = %d\n", threshold);
+
+ Hierarchy fh;
+ fh.DownsampleEdgeGraph(face_edgeOrients, face_edgeIds, edge_diff, allow_changes, -1);
+ int nflip = 0;
+ for (int depth = std::min(5, (int)fh.mFQ.size() - 1); depth >= 0; --depth) {
+ nflip = fh.FixFlipSat(depth, threshold);
+ if (depth > 0) fh.PushDownwardFlip(depth);
+ if (nflip == 0) break;
+ }
+ fh.UpdateGraphValue(face_edgeOrients, face_edgeIds, edge_diff);
+ if (nflip == 0) break;
+ }
+}
+
+void Parametrizer::AdvancedExtractQuad() {
+ Hierarchy fh;
+ fh.DownsampleEdgeGraph(face_edgeOrients, face_edgeIds, edge_diff, allow_changes, -1);
+ auto& V = hierarchy.mV[0];
+ auto& F = hierarchy.mF;
+ disajoint_tree = DisajointTree(V.cols());
+ auto& diffs = fh.mEdgeDiff.front();
+ for (int i = 0; i < diffs.size(); ++i) {
+ if (diffs[i] == Vector2i::Zero()) {
+ disajoint_tree.Merge(edge_values[i].x, edge_values[i].y);
+ }
+ }
+ disajoint_tree.BuildCompactParent();
+ auto& F2E = fh.mF2E.back();
+ auto& E2F = fh.mE2F.back();
+ auto& EdgeDiff = fh.mEdgeDiff.back();
+ auto& FQ = fh.mFQ.back();
+
+ std::vector<int> edge(E2F.size());
+ std::vector<int> face(F2E.size());
+ for (int i = 0; i < diffs.size(); ++i) {
+ int t = i;
+ for (int j = 0; j < fh.mToUpperEdges.size(); ++j) {
+ t = fh.mToUpperEdges[j][t];
+ if (t < 0) break;
+ }
+ if (t >= 0) edge[t] = i;
+ }
+ for (int i = 0; i < F.cols(); ++i) {
+ int t = i;
+ for (int j = 0; j < fh.mToUpperFaces.size(); ++j) {
+ t = fh.mToUpperFaces[j][t];
+ if (t < 0) break;
+ }
+ if (t >= 0) face[t] = i;
+ }
+ fh.UpdateGraphValue(face_edgeOrients, face_edgeIds, edge_diff);
+
+ auto& O = hierarchy.mO[0];
+ auto& Q = hierarchy.mQ[0];
+ auto& N = hierarchy.mN[0];
+ int num_v = disajoint_tree.CompactNum();
+ Vset.resize(num_v);
+ O_compact.resize(num_v, Vector3d::Zero());
+ Q_compact.resize(num_v, Vector3d::Zero());
+ N_compact.resize(num_v, Vector3d::Zero());
+ counter.resize(num_v, 0);
+ for (int i = 0; i < O.cols(); ++i) {
+ int compact_v = disajoint_tree.Index(i);
+ Vset[compact_v].push_back(i);
+ O_compact[compact_v] += O.col(i);
+ N_compact[compact_v] = N_compact[compact_v] * counter[compact_v] + N.col(i);
+ N_compact[compact_v].normalize();
+ if (counter[compact_v] == 0)
+ Q_compact[compact_v] = Q.col(i);
+ else {
+ auto pairs = compat_orientation_extrinsic_4(Q_compact[compact_v], N_compact[compact_v],
+ Q.col(i), N.col(i));
+ Q_compact[compact_v] = (pairs.first * counter[compact_v] + pairs.second).normalized();
+ }
+ counter[compact_v] += 1;
+ }
+ for (int i = 0; i < O_compact.size(); ++i) {
+ O_compact[i] /= counter[i];
+ }
+
+ BuildTriangleManifold(disajoint_tree, edge, face, edge_values, F2E, E2F, EdgeDiff, FQ);
+}
+
+void Parametrizer::BuildTriangleManifold(DisajointTree& disajoint_tree, std::vector<int>& edge,
+ std::vector<int>& face, std::vector<DEdge>& edge_values,
+ std::vector<Vector3i>& F2E, std::vector<Vector2i>& E2F,
+ std::vector<Vector2i>& EdgeDiff,
+ std::vector<Vector3i>& FQ) {
+ auto& F = hierarchy.mF;
+ std::vector<int> E2E(F2E.size() * 3, -1);
+ for (int i = 0; i < E2F.size(); ++i) {
+ int v1 = E2F[i][0];
+ int v2 = E2F[i][1];
+ int t1 = 0;
+ int t2 = 2;
+ if (v1 != -1)
+ while (F2E[v1][t1] != i) t1 += 1;
+ if (v2 != -1)
+ while (F2E[v2][t2] != i) t2 -= 1;
+ t1 += v1 * 3;
+ t2 += v2 * 3;
+ if (v1 != -1)
+ E2E[t1] = (v2 == -1) ? -1 : t2;
+ if (v2 != -1)
+ E2E[t2] = (v1 == -1) ? -1 : t1;
+ }
+
+ std::vector<Vector3i> triangle_vertices(F2E.size(), Vector3i(-1, -1, -1));
+ int num_v = 0;
+ std::vector<Vector3d> N, Q, O;
+ std::vector<std::vector<int>> Vs;
+ for (int i = 0; i < F2E.size(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ if (triangle_vertices[i][j] != -1) continue;
+ int f = face[i];
+ int v = disajoint_tree.Index(F(j, f));
+ Vs.push_back(Vset[v]);
+ Q.push_back(Q_compact[v]);
+ N.push_back(N_compact[v]);
+ O.push_back(O_compact[v]);
+ int deid0 = i * 3 + j;
+ int deid = deid0;
+ do {
+ triangle_vertices[deid / 3][deid % 3] = num_v;
+ deid = E2E[deid / 3 * 3 + (deid + 2) % 3];
+ } while (deid != deid0 && deid != -1);
+ if (deid == -1) {
+ deid = deid0;
+ do {
+ deid = E2E[deid];
+ if (deid == -1)
+ break;
+ deid = deid / 3 * 3 + (deid + 1) % 3;
+ triangle_vertices[deid/3][deid%3] = num_v;
+ } while (deid != -1);
+ }
+ num_v += 1;
+ }
+ }
+
+ int num_v0 = num_v;
+ do {
+ num_v0 = num_v;
+ std::vector<std::vector<int>> vert_to_dedge(num_v);
+ for (int i = 0; i < triangle_vertices.size(); ++i) {
+ Vector3i pt = triangle_vertices[i];
+ if (pt[0] == pt[1] || pt[1] == pt[2] || pt[2] == pt[0]) {
+ for (int j = 0; j < 3; ++j) {
+ int t = E2E[i * 3 + j];
+ if (t != -1) E2E[t] = -1;
+ }
+ for (int j = 0; j < 3; ++j) {
+ E2E[i * 3 + j] = -1;
+ }
+ } else {
+ for (int j = 0; j < 3; ++j)
+ vert_to_dedge[triangle_vertices[i][j]].push_back(i * 3 + j);
+ }
+ }
+ std::vector<int> colors(triangle_vertices.size() * 3, -1),
+ reverse_colors(triangle_vertices.size() * 3, -1);
+ for (int i = 0; i < vert_to_dedge.size(); ++i) {
+ int num_color = 0;
+ for (int j = 0; j < vert_to_dedge[i].size(); ++j) {
+ int deid = vert_to_dedge[i][j];
+ if (colors[deid] != -1) continue;
+ std::list<int> l;
+ int deid0 = deid;
+ do {
+ l.push_back(deid);
+ deid = deid / 3 * 3 + (deid + 2) % 3;
+ deid = E2E[deid];
+ } while (deid != -1 && deid != deid0);
+ if (deid == -1) {
+ deid = deid0;
+ do {
+ deid = E2E[deid];
+ if (deid == -1) break;
+ deid = deid / 3 * 3 + (deid + 1) % 3;
+ if (deid == deid0) break;
+ l.push_front(deid);
+ } while (true);
+ }
+ std::vector<int> dedges;
+ for (auto& e : l) dedges.push_back(e);
+ std::map<std::pair<int, int>, int> loc;
+ std::vector<int> deid_colors(dedges.size(), num_color);
+ num_color += 1;
+ for (int jj = 0; jj < dedges.size(); ++jj) {
+ int deid = dedges[jj];
+ colors[deid] = 0;
+ int v1 = triangle_vertices[deid / 3][deid % 3];
+ int v2 = triangle_vertices[deid / 3][(deid + 1) % 3];
+ std::pair<int, int> pt(v1, v2);
+ if (loc.count(pt)) {
+ int s = loc[pt];
+ for (int k = s; k < jj; ++k) {
+ int deid1 = dedges[k];
+ int v11 = triangle_vertices[deid1 / 3][deid1 % 3];
+ int v12 = triangle_vertices[deid1 / 3][(deid1 + 1) % 3];
+ std::pair<int, int> pt1(v11, v12);
+ loc.erase(pt1);
+ deid_colors[k] = num_color;
+ }
+ num_color += 1;
+ }
+ loc[pt] = jj;
+ }
+ for (int j = 0; j < dedges.size(); ++j) {
+ int deid = dedges[j];
+ int color = deid_colors[j];
+ if (color > 0) {
+ triangle_vertices[deid / 3][deid % 3] = num_v + color - 1;
+ }
+ }
+ }
+ if (num_color > 1) {
+ for (int j = 0; j < num_color - 1; ++j) {
+ Vs.push_back(Vs[i]);
+ O.push_back(O[i]);
+ N.push_back(N[i]);
+ Q.push_back(Q[i]);
+ }
+ num_v += num_color - 1;
+ }
+ }
+ } while (num_v != num_v0);
+ int offset = 0;
+ std::vector<Vector3i> triangle_edges, triangle_orients;
+ for (int i = 0; i < triangle_vertices.size(); ++i) {
+ Vector3i pt = triangle_vertices[i];
+ if (pt[0] == pt[1] || pt[1] == pt[2] || pt[2] == pt[0]) continue;
+ triangle_vertices[offset++] = triangle_vertices[i];
+ triangle_edges.push_back(F2E[i]);
+ triangle_orients.push_back(FQ[i]);
+ }
+ triangle_vertices.resize(offset);
+ std::set<int> flip_vertices;
+ for (int i = 0; i < triangle_vertices.size(); ++i) {
+ Vector2i d1 = rshift90(EdgeDiff[triangle_edges[i][0]], triangle_orients[i][0]);
+ Vector2i d2 = rshift90(EdgeDiff[triangle_edges[i][1]], triangle_orients[i][1]);
+ int area = d1[0] * d2[1] - d1[1] * d2[0];
+ if (area < 0) {
+ for (int j = 0; j < 3; ++j) {
+ flip_vertices.insert(triangle_vertices[i][j]);
+ }
+ }
+ }
+ MatrixXd NV(3, num_v);
+ MatrixXi NF(3, triangle_vertices.size());
+ memcpy(NF.data(), triangle_vertices.data(), sizeof(int) * 3 * triangle_vertices.size());
+ VectorXi NV2E, NE2E, NB, NN;
+ compute_direct_graph(NV, NF, NV2E, NE2E, NB, NN);
+
+ std::map<DEdge, std::pair<Vector3i, Vector3i>> quads;
+ for (int i = 0; i < triangle_vertices.size(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ int e = triangle_edges[i][j];
+ int v1 = triangle_vertices[i][j];
+ int v2 = triangle_vertices[i][(j + 1) % 3];
+ int v3 = triangle_vertices[i][(j + 2) % 3];
+ if (abs(EdgeDiff[e][0]) == 1 && abs(EdgeDiff[e][1]) == 1) {
+ DEdge edge(v1, v2);
+ if (quads.count(edge))
+ quads[edge].second = Vector3i(v1, v2, v3);
+ else
+ quads[edge] = std::make_pair(Vector3i(v1, v2, v3), Vector3i(-1, -1, -1));
+ }
+ }
+ }
+
+ for (auto& p : quads) {
+ if (p.second.second[0] != -1 && p.second.first[2] != p.second.second[2]) {
+ F_compact.push_back(Vector4i(p.second.first[1], p.second.first[2], p.second.first[0],
+ p.second.second[2]));
+ }
+ }
+ std::swap(Vs, Vset);
+ std::swap(O_compact, O);
+ std::swap(N_compact, N);
+ std::swap(Q_compact, Q);
+ compute_direct_graph_quad(O_compact, F_compact, V2E_compact, E2E_compact, boundary_compact,
+ nonManifold_compact);
+
+ while (true) {
+ std::vector<int> erasedF(F_compact.size(), 0);
+ for (int i = 0; i < F_compact.size(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ for (int k = j + 1; k < 4; ++k) {
+ if (F_compact[i][j] == F_compact[i][k]) {
+ erasedF[i] = 1;
+ }
+ }
+ }
+ }
+ for (int i = 0; i < O_compact.size(); ++i) {
+ int v = 0;
+ int e0 = V2E_compact[i];
+ if (e0 == -1) continue;
+ std::vector<int> dedges;
+ int e = e0;
+ do {
+ dedges.push_back(e);
+ v += 1;
+ e = e / 4 * 4 + (e + 3) % 4;
+ e = E2E_compact[e];
+ } while (e != e0 && e != -1);
+ if (e == -1) {
+ int e = e0;
+ while (true) {
+ e = E2E_compact[e];
+ if (e == -1) break;
+ e = e / 4 * 4 + (e + 1) % 4;
+ v += 1;
+ dedges.push_back(e);
+ }
+ }
+ if (v == 2) {
+ // erasedF[dedges[1] / 4] = 1;
+ // F_compact[dedges[0]/4][dedges[0]%4] =
+ // F_compact[dedges[1]/4][(dedges[1]+2)%4];
+ }
+ }
+ offset = 0;
+ for (int i = 0; i < F_compact.size(); ++i) {
+ if (erasedF[i] == 0) F_compact[offset++] = F_compact[i];
+ }
+ if (offset == F_compact.size()) break;
+ F_compact.resize(offset);
+ compute_direct_graph_quad(O_compact, F_compact, V2E_compact, E2E_compact, boundary_compact,
+ nonManifold_compact);
+ }
+ FixHoles();
+ compute_direct_graph_quad(O_compact, F_compact, V2E_compact, E2E_compact, boundary_compact,
+ nonManifold_compact);
+
+ /*
+ for (auto& p : flip_vertices) {
+ int deid0 = V2E_compact[p];
+ int deid = deid0;
+ std::list<int> dedges;
+ if (deid0 != -1) {
+ do {
+ dedges.push_back(deid);
+ deid = E2E_compact[deid/4*4 + (deid+3) % 4];
+ } while (deid != -1 && deid != deid0);
+ if (deid == -1) {
+ deid = deid0;
+ do {
+ deid = E2E_compact[deid];
+ if (deid == -1)
+ break;
+ deid = deid/4*4 + (deid +1) % 4;
+ dedges.push_front(deid);
+ } while (deid != -1 && deid != deid0);
+ }
+ std::set<int> eraseF;
+ std::set<int> valid_dedges;
+ std::set<int> boundaries;
+ std::vector<int> loop_vertices;
+ for (auto& dedge : dedges) {
+ int f = dedge / 4;
+ eraseF.insert(f);
+ valid_dedges.insert(E2E_compact[f * 4 + (dedge+1)%4]);
+ valid_dedges.insert(E2E_compact[f * 4 + (dedge+2)%4]);
+ loop_vertices.push_back(F_compact[f][(dedge+1)%4]);
+ loop_vertices.push_back(F_compact[f][(dedge+2)%4]);
+ boundaries.insert(F_compact[f][(dedge+1)%4]);
+ boundaries.insert(F_compact[f][(dedge+2)%4]);
+ }
+ int offset = 0;
+ auto it = eraseF.begin();
+ for (int i = 0; i < F_compact.size(); ++i) {
+ if (it == eraseF.end() || i != *it) {
+ bool need_erase = false;
+ for (int j = 0; j < 4; ++j) {
+ if (valid_dedges.count(i * 4 + j) == 0 && boundaries.count(F_compact[i][j])
+ && boundaries.count(F_compact[i][(j + 1) % 4])) { need_erase = true;
+ }
+ }
+ if (!need_erase)
+ F_compact[offset++] = F_compact[i];
+ } else {
+ it++;
+ }
+ }
+ F_compact.resize(offset);
+ compute_direct_graph_quad(O_compact, F_compact, V2E_compact, E2E_compact,
+ boundary_compact, nonManifold_compact); std::reverse(loop_vertices.begin(),
+ loop_vertices.end()); FixHoles(loop_vertices); compute_direct_graph_quad(O_compact, F_compact,
+ V2E_compact, E2E_compact, boundary_compact, nonManifold_compact);
+ }
+ }
+ FixHoles();
+ compute_direct_graph_quad(O_compact, F_compact, V2E_compact, E2E_compact, boundary_compact,
+ nonManifold_compact);
+ */
+}
+
+} // namespace qflow
diff --git a/extern/quadriflow/src/parametrizer-int.cpp b/extern/quadriflow/src/parametrizer-int.cpp
new file mode 100644
index 00000000000..08fa36c1baa
--- /dev/null
+++ b/extern/quadriflow/src/parametrizer-int.cpp
@@ -0,0 +1,425 @@
+#include "parametrizer.hpp"
+
+#include <queue>
+#include <unordered_map>
+#include <vector>
+#include <random>
+#include "optimizer.hpp"
+
+namespace qflow {
+
+
+void Parametrizer::BuildEdgeInfo() {
+ auto& F = hierarchy.mF;
+ auto& E2E = hierarchy.mE2E;
+
+ edge_diff.clear();
+ edge_values.clear();
+ face_edgeIds.resize(F.cols(), Vector3i(-1, -1, -1));
+ for (int i = 0; i < F.cols(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ int k1 = j, k2 = (j + 1) % 3;
+ int v1 = F(k1, i);
+ int v2 = F(k2, i);
+ DEdge e2(v1, v2);
+ Vector2i diff2;
+ int rank2;
+ if (v1 > v2) {
+ rank2 = pos_rank(k2, i);
+ diff2 =
+ rshift90(Vector2i(-pos_index(k1 * 2, i), -pos_index(k1 * 2 + 1, i)), rank2);
+ } else {
+ rank2 = pos_rank(k1, i);
+ diff2 = rshift90(Vector2i(pos_index(k1 * 2, i), pos_index(k1 * 2 + 1, i)), rank2);
+ }
+ int current_eid = i * 3 + k1;
+ int eid = E2E[current_eid];
+ int eID1 = face_edgeIds[current_eid / 3][current_eid % 3];
+ int eID2 = -1;
+ if (eID1 == -1) {
+ eID2 = edge_values.size();
+ edge_values.push_back(e2);
+ edge_diff.push_back(diff2);
+ face_edgeIds[i][k1] = eID2;
+ if (eid != -1) face_edgeIds[eid / 3][eid % 3] = eID2;
+ } else if (!singularities.count(i)) {
+ eID2 = face_edgeIds[eid / 3][eid % 3];
+ edge_diff[eID2] = diff2;
+ }
+ }
+ }
+}
+
+void Parametrizer::BuildIntegerConstraints() {
+ auto& F = hierarchy.mF;
+ auto& Q = hierarchy.mQ[0];
+ auto& N = hierarchy.mN[0];
+ face_edgeOrients.resize(F.cols());
+
+ //Random number generator (for shuffling)
+ std::random_device rd;
+ std::mt19937 g(rd());
+ g.seed(hierarchy.rng_seed);
+
+ // undirected edge to direct edge
+ std::vector<std::pair<int, int>> E2D(edge_diff.size(), std::make_pair(-1, -1));
+ for (int i = 0; i < F.cols(); ++i) {
+ int v0 = F(0, i);
+ int v1 = F(1, i);
+ int v2 = F(2, i);
+ DEdge e0(v0, v1), e1(v1, v2), e2(v2, v0);
+ const Vector3i& eid = face_edgeIds[i];
+ Vector2i variable_id[3];
+ for (int i = 0; i < 3; ++i) {
+ variable_id[i] = Vector2i(eid[i] * 2 + 1, eid[i] * 2 + 2);
+ }
+ auto index1 =
+ compat_orientation_extrinsic_index_4(Q.col(v0), N.col(v0), Q.col(v1), N.col(v1));
+ auto index2 =
+ compat_orientation_extrinsic_index_4(Q.col(v0), N.col(v0), Q.col(v2), N.col(v2));
+
+ int rank1 = (index1.first - index1.second + 4) % 4; // v1 -> v0
+ int rank2 = (index2.first - index2.second + 4) % 4; // v2 -> v0
+ int orients[3] = {0}; // == {0, 0, 0}
+ if (v1 < v0) {
+ variable_id[0] = -rshift90(variable_id[0], rank1);
+ orients[0] = (rank1 + 2) % 4;
+ } else {
+ orients[0] = 0;
+ }
+ if (v2 < v1) {
+ variable_id[1] = -rshift90(variable_id[1], rank2);
+ orients[1] = (rank2 + 2) % 4;
+ } else {
+ variable_id[1] = rshift90(variable_id[1], rank1);
+ orients[1] = rank1;
+ }
+ if (v2 < v0) {
+ variable_id[2] = rshift90(variable_id[2], rank2);
+ orients[2] = rank2;
+ } else {
+ variable_id[2] = -variable_id[2];
+ orients[2] = 2;
+ }
+ face_edgeOrients[i] = Vector3i(orients[0], orients[1], orients[2]);
+ for (int j = 0; j < 3; ++j) {
+ int eid = face_edgeIds[i][j];
+ if (E2D[eid].first == -1)
+ E2D[eid].first = i * 3 + j;
+ else
+ E2D[eid].second = i * 3 + j;
+ }
+ }
+
+ // a face disajoint tree
+ DisajointOrientTree disajoint_orient_tree = DisajointOrientTree(F.cols());
+ // merge the whole face graph except for the singularity in which there exists a spanning tree
+ // which contains consistent orientation
+ std::vector<int> sharpUE(E2D.size());
+ for (int i = 0; i < sharp_edges.size(); ++i) {
+ if (sharp_edges[i]) {
+ sharpUE[face_edgeIds[i / 3][i % 3]] = 1;
+ }
+ }
+
+ for (int i = 0; i < E2D.size(); ++i) {
+ auto& edge_c = E2D[i];
+ int f0 = edge_c.first / 3;
+ int f1 = edge_c.second / 3;
+ if (edge_c.first == -1 || edge_c.second == -1) continue;
+ if (singularities.count(f0) || singularities.count(f1) || sharpUE[i]) continue;
+ int orient1 = face_edgeOrients[f0][edge_c.first % 3];
+ int orient0 = (face_edgeOrients[f1][edge_c.second % 3] + 2) % 4;
+ disajoint_orient_tree.Merge(f0, f1, orient0, orient1);
+ }
+
+ // merge singularity later
+ for (auto& f : singularities) {
+ for (int i = 0; i < 3; ++i) {
+ if (sharpUE[face_edgeIds[f.first][i]]) continue;
+ auto& edge_c = E2D[face_edgeIds[f.first][i]];
+ if (edge_c.first == -1 || edge_c.second == -1) continue;
+ int v0 = edge_c.first / 3;
+ int v1 = edge_c.second / 3;
+ int orient1 = face_edgeOrients[v0][edge_c.first % 3];
+ int orient0 = (face_edgeOrients[v1][edge_c.second % 3] + 2) % 4;
+ disajoint_orient_tree.Merge(v0, v1, orient0, orient1);
+ }
+ }
+
+ for (int i = 0; i < sharpUE.size(); ++i) {
+ if (sharpUE[i] == 0) continue;
+ auto& edge_c = E2D[i];
+ if (edge_c.first == -1 || edge_c.second == -1) continue;
+ int f0 = edge_c.first / 3;
+ int f1 = edge_c.second / 3;
+ int orient1 = face_edgeOrients[f0][edge_c.first % 3];
+ int orient0 = (face_edgeOrients[f1][edge_c.second % 3] + 2) % 4;
+ disajoint_orient_tree.Merge(f0, f1, orient0, orient1);
+ }
+
+ // all the face has the same parent. we rotate every face to the space of that parent.
+ for (int i = 0; i < face_edgeOrients.size(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ face_edgeOrients[i][j] =
+ (face_edgeOrients[i][j] + disajoint_orient_tree.Orient(i)) % 4;
+ }
+ }
+
+ std::vector<int> sharp_colors(face_edgeIds.size(), -1);
+ int num_sharp_component = 0;
+ // label the connected component connected by non-fixed edges
+ // we need this because we need sink flow (demand) == source flow (supply) for each component
+ // rather than global
+ for (int i = 0; i < sharp_colors.size(); ++i) {
+ if (sharp_colors[i] != -1) continue;
+ sharp_colors[i] = num_sharp_component;
+ std::queue<int> q;
+ q.push(i);
+ int counter = 0;
+ while (!q.empty()) {
+ int v = q.front();
+ q.pop();
+ for (int i = 0; i < 3; ++i) {
+ int e = face_edgeIds[v][i];
+ int deid1 = E2D[e].first;
+ int deid2 = E2D[e].second;
+ if (deid1 == -1 || deid2 == -1) continue;
+ if (abs(face_edgeOrients[deid1 / 3][deid1 % 3] -
+ face_edgeOrients[deid2 / 3][deid2 % 3] + 4) %
+ 4 !=
+ 2 ||
+ sharpUE[e]) {
+ continue;
+ }
+ for (int k = 0; k < 2; ++k) {
+ int f = (k == 0) ? E2D[e].first / 3 : E2D[e].second / 3;
+ if (sharp_colors[f] == -1) {
+ sharp_colors[f] = num_sharp_component;
+ q.push(f);
+ }
+ }
+ }
+ counter += 1;
+ }
+ num_sharp_component += 1;
+ }
+ {
+ std::vector<int> total_flows(num_sharp_component);
+ // check if each component is full-flow
+ for (int i = 0; i < face_edgeIds.size(); ++i) {
+ Vector2i diff(0, 0);
+ for (int j = 0; j < 3; ++j) {
+ int orient = face_edgeOrients[i][j];
+ diff += rshift90(edge_diff[face_edgeIds[i][j]], orient);
+ }
+ total_flows[sharp_colors[i]] += diff[0] + diff[1];
+ }
+
+ // build "variable"
+ variables.resize(edge_diff.size() * 2, std::make_pair(Vector2i(-1, -1), 0));
+ for (int i = 0; i < face_edgeIds.size(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ Vector2i sign = rshift90(Vector2i(1, 1), face_edgeOrients[i][j]);
+ int eid = face_edgeIds[i][j];
+ Vector2i index = rshift90(Vector2i(eid * 2, eid * 2 + 1), face_edgeOrients[i][j]);
+ for (int k = 0; k < 2; ++k) {
+ auto& p = variables[abs(index[k])];
+ if (p.first[0] == -1)
+ p.first[0] = i * 2 + k;
+ else
+ p.first[1] = i * 2 + k;
+ p.second += sign[k];
+ }
+ }
+ }
+
+ // fixed variable that might be manually modified.
+ // modified_variables[component_od][].first = fixed_variable_id
+ // modified_variables[component_od][].second = 1 if two positive signs -1 if two negative
+ // signs
+ std::vector<std::vector<std::pair<int, int>>> modified_variables[2];
+ for (int i = 0; i < 2; ++i) modified_variables[i].resize(total_flows.size());
+ for (int i = 0; i < variables.size(); ++i) {
+ if ((variables[i].first[1] == -1 || variables[i].second != 0) &&
+ allow_changes[i] == 1) {
+ int find = sharp_colors[variables[i].first[0] / 2];
+ int step = std::abs(variables[i].second) % 2;
+ if (total_flows[find] > 0) {
+ if (variables[i].second > 0 && edge_diff[i / 2][i % 2] > -1) {
+ modified_variables[step][find].push_back(std::make_pair(i, -1));
+ }
+ if (variables[i].second < 0 && edge_diff[i / 2][i % 2] < 1) {
+ modified_variables[step][find].push_back(std::make_pair(i, 1));
+ }
+ } else if (total_flows[find] < 0) {
+ if (variables[i].second < 0 && edge_diff[i / 2][i % 2] > -1) {
+ modified_variables[step][find].push_back(std::make_pair(i, -1));
+ }
+ if (variables[i].second > 0 && edge_diff[i / 2][i % 2] < 1) {
+ modified_variables[step][find].push_back(std::make_pair(i, 1));
+ }
+ }
+ }
+ }
+
+ // uniformly random manually modify variables so that the network has full flow.
+ for (int i = 0; i < 2; ++i)
+ for (auto& modified_var : modified_variables[i])
+ std::shuffle(modified_var.begin(), modified_var.end(), g);
+
+ for (int j = 0; j < total_flows.size(); ++j) {
+ for (int ii = 0; ii < 2; ++ii) {
+ if (total_flows[j] == 0) continue;
+ int max_num;
+ if (ii == 0)
+ max_num =
+ std::min(abs(total_flows[j]) / 2, (int)modified_variables[ii][j].size());
+ else
+ max_num = std::min(abs(total_flows[j]), (int)modified_variables[ii][j].size());
+ int dir = (total_flows[j] > 0) ? -1 : 1;
+ for (int i = 0; i < max_num; ++i) {
+ auto& info = modified_variables[ii][j][i];
+ edge_diff[info.first / 2][info.first % 2] += info.second;
+ if (ii == 0)
+ total_flows[j] += 2 * dir;
+ else
+ total_flows[j] += dir;
+ }
+ }
+ }
+ }
+
+ std::vector<Vector4i> edge_to_constraints(E2D.size() * 2, Vector4i(-1, 0, -1, 0));
+ for (int i = 0; i < face_edgeIds.size(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ int e = face_edgeIds[i][j];
+ Vector2i index = rshift90(Vector2i(e * 2 + 1, e * 2 + 2), face_edgeOrients[i][j]);
+ for (int k = 0; k < 2; ++k) {
+ int l = abs(index[k]);
+ int s = index[k] / l;
+ int ind = l - 1;
+ int equationID = i * 2 + k;
+ if (edge_to_constraints[ind][0] == -1) {
+ edge_to_constraints[ind][0] = equationID;
+ edge_to_constraints[ind][1] = s;
+ } else {
+ edge_to_constraints[ind][2] = equationID;
+ edge_to_constraints[ind][3] = s;
+ }
+ }
+ }
+ }
+ std::vector<std::pair<Vector2i, int>> arcs;
+ std::vector<int> arc_ids;
+ DisajointTree tree(face_edgeIds.size() * 2);
+ for (int i = 0; i < edge_to_constraints.size(); ++i) {
+ if (allow_changes[i] == 0) continue;
+ if (edge_to_constraints[i][0] == -1 || edge_to_constraints[i][2] == -1) continue;
+ if (edge_to_constraints[i][1] == -edge_to_constraints[i][3]) {
+ int v1 = edge_to_constraints[i][0];
+ int v2 = edge_to_constraints[i][2];
+ tree.Merge(v1, v2);
+ if (edge_to_constraints[i][1] < 0) std::swap(v1, v2);
+ int current_v = edge_diff[i / 2][i % 2];
+ arcs.push_back(std::make_pair(Vector2i(v1, v2), current_v));
+ }
+ }
+ tree.BuildCompactParent();
+ std::vector<int> total_flows(tree.CompactNum());
+ // check if each component is full-flow
+ for (int i = 0; i < face_edgeIds.size(); ++i) {
+ Vector2i diff(0, 0);
+ for (int j = 0; j < 3; ++j) {
+ int orient = face_edgeOrients[i][j];
+ diff += rshift90(edge_diff[face_edgeIds[i][j]], orient);
+ }
+ for (int j = 0; j < 2; ++j) {
+ total_flows[tree.Index(i * 2 + j)] += diff[j];
+ }
+ }
+
+ // build "variable"
+ variables.resize(edge_diff.size() * 2);
+ for (int i = 0; i < variables.size(); ++i) {
+ variables[i].first = Vector2i(-1, -1);
+ variables[i].second = 0;
+ }
+ for (int i = 0; i < face_edgeIds.size(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ Vector2i sign = rshift90(Vector2i(1, 1), face_edgeOrients[i][j]);
+ int eid = face_edgeIds[i][j];
+ Vector2i index = rshift90(Vector2i(eid * 2, eid * 2 + 1), face_edgeOrients[i][j]);
+ for (int k = 0; k < 2; ++k) {
+ auto& p = variables[abs(index[k])];
+ if (p.first[0] == -1)
+ p.first[0] = i * 2 + k;
+ else
+ p.first[1] = i * 2 + k;
+ p.second += sign[k];
+ }
+ }
+ }
+
+ // fixed variable that might be manually modified.
+ // modified_variables[component_od][].first = fixed_variable_id
+ // modified_variables[component_od][].second = 1 if two positive signs -1 if two negative signs
+ std::vector<std::vector<std::pair<int, int>>> modified_variables[2];
+ for (int i = 0; i < 2; ++i) {
+ modified_variables[i].resize(total_flows.size());
+ }
+ for (int i = 0; i < variables.size(); ++i) {
+ if ((variables[i].first[1] == -1 || variables[i].second != 0) && allow_changes[i] == 1) {
+ int find = tree.Index(variables[i].first[0]);
+ int step = abs(variables[i].second) % 2;
+ if (total_flows[find] > 0) {
+ if (variables[i].second > 0 && edge_diff[i / 2][i % 2] > -1) {
+ modified_variables[step][find].push_back(std::make_pair(i, -1));
+ }
+ if (variables[i].second < 0 && edge_diff[i / 2][i % 2] < 1) {
+ modified_variables[step][find].push_back(std::make_pair(i, 1));
+ }
+ } else if (total_flows[find] < 0) {
+ if (variables[i].second < 0 && edge_diff[i / 2][i % 2] > -1) {
+ modified_variables[step][find].push_back(std::make_pair(i, -1));
+ }
+ if (variables[i].second > 0 && edge_diff[i / 2][i % 2] < 1) {
+ modified_variables[step][find].push_back(std::make_pair(i, 1));
+ }
+ }
+ }
+ }
+
+ // uniformly random manually modify variables so that the network has full flow.
+ for (int j = 0; j < 2; ++j) {
+ for (auto& modified_var : modified_variables[j])
+ std::shuffle(modified_var.begin(), modified_var.end(), g);
+ }
+ for (int j = 0; j < total_flows.size(); ++j) {
+ for (int ii = 0; ii < 2; ++ii) {
+ if (total_flows[j] == 0) continue;
+ int max_num;
+ if (ii == 0)
+ max_num = std::min(abs(total_flows[j]) / 2, (int)modified_variables[ii][j].size());
+ else
+ max_num = std::min(abs(total_flows[j]), (int)modified_variables[ii][j].size());
+ int dir = (total_flows[j] > 0) ? -1 : 1;
+ for (int i = 0; i < max_num; ++i) {
+ auto& info = modified_variables[ii][j][i];
+ edge_diff[info.first / 2][info.first % 2] += info.second;
+ if (ii == 0)
+ total_flows[j] += 2 * dir;
+ else
+ total_flows[j] += dir;
+ }
+ }
+ }
+}
+
+void Parametrizer::ComputeMaxFlow() {
+ hierarchy.DownsampleEdgeGraph(face_edgeOrients, face_edgeIds, edge_diff, allow_changes, 1);
+ Optimizer::optimize_integer_constraints(hierarchy, singularities, flag_minimum_cost_flow);
+ hierarchy.UpdateGraphValue(face_edgeOrients, face_edgeIds, edge_diff);
+}
+
+} // namespace qflow
diff --git a/extern/quadriflow/src/parametrizer-mesh.cpp b/extern/quadriflow/src/parametrizer-mesh.cpp
new file mode 100644
index 00000000000..19effe92390
--- /dev/null
+++ b/extern/quadriflow/src/parametrizer-mesh.cpp
@@ -0,0 +1,615 @@
+#include "config.hpp"
+#include "dedge.hpp"
+#include "field-math.hpp"
+#include "loader.hpp"
+#include "merge-vertex.hpp"
+#include "parametrizer.hpp"
+#include "subdivide.hpp"
+#include "dedge.hpp"
+#include <queue>
+
+namespace qflow {
+
+void Parametrizer::NormalizeMesh() {
+ double maxV[3] = {-1e30, -1e30, -1e30};
+ double minV[3] = {1e30, 1e30, 1e30};
+
+ for (int i = 0; i < V.cols(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ maxV[j] = std::max(maxV[j], V(j, i));
+ minV[j] = std::min(minV[j], V(j, i));
+ }
+ }
+ double scale =
+ std::max(std::max(maxV[0] - minV[0], maxV[1] - minV[1]), maxV[2] - minV[2]) * 0.5;
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int i = 0; i < V.cols(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ V(j, i) = (V(j, i) - (maxV[j] + minV[j]) * 0.5) / scale;
+ }
+ }
+#ifdef LOG_OUTPUT
+ printf("vertices size: %d\n", (int)V.cols());
+ printf("faces size: %d\n", (int)F.cols());
+#endif
+ this->normalize_scale = scale;
+ this->normalize_offset = Vector3d(0.5 * (maxV[0] + minV[0]), 0.5 * (maxV[1] + minV[1]), 0.5 * (maxV[2] + minV[2]));
+ // merge_close(V, F, 1e-6);
+}
+
+void Parametrizer::Load(const char* filename) {
+ load(filename, V, F);
+ NormalizeMesh();
+}
+
+void Parametrizer::Initialize(int faces) {
+ ComputeMeshStatus();
+ //ComputeCurvature(V, F, rho);
+ rho.resize(V.cols(), 1);
+ for (int i = 0; i < V.cols(); ++i) {
+ rho[i] = 1;
+ }
+#ifdef PERFORMANCE_TEST
+ scale = sqrt(surface_area / (V.cols() * 10));
+#else
+ if (faces <= 0) {
+ scale = sqrt(surface_area / V.cols());
+ } else {
+ scale = std::sqrt(surface_area / faces);
+ }
+#endif
+ double target_len = std::min(scale / 2, average_edge_length * 2);
+#ifdef PERFORMANCE_TEST
+ scale = sqrt(surface_area / V.cols());
+#endif
+
+ if (target_len < max_edge_length) {
+ while (!compute_direct_graph(V, F, V2E, E2E, boundary, nonManifold))
+ ;
+ subdivide(F, V, rho, V2E, E2E, boundary, nonManifold, target_len);
+ }
+
+ while (!compute_direct_graph(V, F, V2E, E2E, boundary, nonManifold))
+ ;
+ generate_adjacency_matrix_uniform(F, V2E, E2E, nonManifold, adj);
+
+ for (int iter = 0; iter < 5; ++iter) {
+ VectorXd r(rho.size());
+ for (int i = 0; i < rho.size(); ++i) {
+ r[i] = rho[i];
+ for (auto& id : adj[i]) {
+ r[i] = std::min(r[i], rho[id.id]);
+ }
+ }
+ rho = r;
+ }
+ ComputeSharpEdges();
+ ComputeSmoothNormal();
+ ComputeVertexArea();
+
+ if (flag_adaptive_scale)
+ ComputeInverseAffine();
+
+#ifdef LOG_OUTPUT
+ printf("V: %d F: %d\n", (int)V.cols(), (int)F.cols());
+#endif
+ hierarchy.mA[0] = std::move(A);
+ hierarchy.mAdj[0] = std::move(adj);
+ hierarchy.mN[0] = std::move(N);
+ hierarchy.mV[0] = std::move(V);
+ hierarchy.mE2E = std::move(E2E);
+ hierarchy.mF = std::move(F);
+ hierarchy.Initialize(scale, flag_adaptive_scale);
+}
+
+void Parametrizer::ComputeMeshStatus() {
+ surface_area = 0;
+ average_edge_length = 0;
+ max_edge_length = 0;
+ for (int f = 0; f < F.cols(); ++f) {
+ Vector3d v[3] = {V.col(F(0, f)), V.col(F(1, f)), V.col(F(2, f))};
+ double area = 0.5f * (v[1] - v[0]).cross(v[2] - v[0]).norm();
+ surface_area += area;
+ for (int i = 0; i < 3; ++i) {
+ double len = (v[(i + 1) % 3] - v[i]).norm();
+ average_edge_length += len;
+ if (len > max_edge_length) max_edge_length = len;
+ }
+ }
+ average_edge_length /= (F.cols() * 3);
+}
+
+void Parametrizer::ComputeSharpEdges() {
+ sharp_edges.resize(F.cols() * 3, 0);
+
+ if (flag_preserve_boundary) {
+ for (int i = 0; i < sharp_edges.size(); ++i) {
+ int re = E2E[i];
+ if (re == -1) {
+ sharp_edges[i] = 1;
+ }
+ }
+ }
+
+ if (flag_preserve_sharp == 0)
+ return;
+
+ std::vector<Vector3d> face_normals(F.cols());
+ for (int i = 0; i < F.cols(); ++i) {
+ Vector3d p1 = V.col(F(0, i));
+ Vector3d p2 = V.col(F(1, i));
+ Vector3d p3 = V.col(F(2, i));
+ face_normals[i] = (p2 - p1).cross(p3 - p1).normalized();
+ }
+
+ double cos_thres = cos(60.0/180.0*3.141592654);
+ for (int i = 0; i < sharp_edges.size(); ++i) {
+ int e = i;
+ int re = E2E[e];
+ Vector3d& n1 = face_normals[e/3];
+ Vector3d& n2 = face_normals[re/3];
+ if (n1.dot(n2) < cos_thres) {
+ sharp_edges[i] = 1;
+ }
+ }
+}
+
+void Parametrizer::ComputeSharpO() {
+ auto& F = hierarchy.mF;
+ auto& V = hierarchy.mV[0];
+ auto& O = hierarchy.mO[0];
+ auto& E2E = hierarchy.mE2E;
+ DisajointTree tree(V.cols());
+ for (int i = 0; i < edge_diff.size(); ++i) {
+ if (edge_diff[i][0] == 0 && edge_diff[i][1] == 0) {
+ tree.Merge(edge_values[i].x, edge_values[i].y);
+ }
+ }
+ std::map<DEdge, std::vector<Vector3d> > edge_normals;
+ for (int i = 0; i < F.cols(); ++i) {
+ int pv[] = {tree.Parent(F(0, i)), tree.Parent(F(1, i)), tree.Parent(F(2, i))};
+ if (pv[0] == pv[1] || pv[1] == pv[2] || pv[2] == pv[0])
+ continue;
+ DEdge e[] = {DEdge(pv[0], pv[1]), DEdge(pv[1], pv[2]), DEdge(pv[2], pv[0])};
+ Vector3d d1 = O.col(F(1, i)) - O.col(F(0, i));
+ Vector3d d2 = O.col(F(2, i)) - O.col(F(0, i));
+ Vector3d n = d1.cross(d2).normalized();
+ for (int j = 0; j < 3; ++j) {
+ if (edge_normals.count(e[j]) == 0)
+ edge_normals[e[j]] = std::vector<Vector3d>();
+ edge_normals[e[j]].push_back(n);
+ }
+ }
+ std::map<DEdge, int> sharps;
+ for (auto& info : edge_normals) {
+ auto& normals = info.second;
+ bool sharp = false;
+ for (int i = 0; i < normals.size(); ++i) {
+ for (int j = i + 1; j < normals.size(); ++j) {
+ if (normals[i].dot(normals[j]) < cos(60.0 / 180.0 * 3.141592654)) {
+ sharp = true;
+ break;
+ }
+ }
+ if (sharp)
+ break;
+ }
+ if (sharp) {
+ int s = sharps.size();
+ sharps[info.first] = s;
+ }
+ }
+ for (auto& s : sharp_edges)
+ s = 0;
+ std::vector<int> sharp_hash(sharps.size(), 0);
+ for (int i = 0; i < F.cols(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ int v1 = tree.Parent(F(j, i));
+ int v2 = tree.Parent(F((j + 1) % 3, i));
+ DEdge e(v1, v2);
+ if (sharps.count(e) == 0)
+ continue;
+ int id = sharps[e];
+ if (sharp_hash[id])
+ continue;
+ sharp_hash[id] = 1;
+ sharp_edges[i * 3 + j] = 1;
+ sharp_edges[E2E[i * 3 + j]] = 1;
+ }
+ }
+
+}
+
+void Parametrizer::ComputeSmoothNormal() {
+ /* Compute face normals */
+ Nf.resize(3, F.cols());
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int f = 0; f < F.cols(); ++f) {
+ Vector3d v0 = V.col(F(0, f)), v1 = V.col(F(1, f)), v2 = V.col(F(2, f)),
+ n = (v1 - v0).cross(v2 - v0);
+ double norm = n.norm();
+ if (norm < RCPOVERFLOW) {
+ n = Vector3d::UnitX();
+ } else {
+ n /= norm;
+ }
+ Nf.col(f) = n;
+ }
+
+ N.resize(3, V.cols());
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int i = 0; i < V2E.rows(); ++i) {
+ int edge = V2E[i];
+ if (nonManifold[i] || edge == -1) {
+ N.col(i) = Vector3d::UnitX();
+ continue;
+ }
+
+
+ int stop = edge;
+ do {
+ if (sharp_edges[edge])
+ break;
+ edge = E2E[edge];
+ if (edge != -1)
+ edge = dedge_next_3(edge);
+ } while (edge != stop && edge != -1);
+ if (edge == -1)
+ edge = stop;
+ else
+ stop = edge;
+ Vector3d normal = Vector3d::Zero();
+ do {
+ int idx = edge % 3;
+
+ Vector3d d0 = V.col(F((idx + 1) % 3, edge / 3)) - V.col(i);
+ Vector3d d1 = V.col(F((idx + 2) % 3, edge / 3)) - V.col(i);
+ double angle = fast_acos(d0.dot(d1) / std::sqrt(d0.squaredNorm() * d1.squaredNorm()));
+
+ /* "Computing Vertex Normals from Polygonal Facets"
+ by Grit Thuermer and Charles A. Wuethrich, JGT 1998, Vol 3 */
+ if (std::isfinite(angle)) normal += Nf.col(edge / 3) * angle;
+
+ int opp = E2E[edge];
+ if (opp == -1) break;
+
+ edge = dedge_next_3(opp);
+ if (sharp_edges[edge])
+ break;
+ } while (edge != stop);
+ double norm = normal.norm();
+ N.col(i) = norm > RCPOVERFLOW ? Vector3d(normal / norm) : Vector3d::UnitX();
+ }
+}
+
+void Parametrizer::ComputeVertexArea() {
+ A.resize(V.cols());
+ A.setZero();
+
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int i = 0; i < V2E.size(); ++i) {
+ int edge = V2E[i], stop = edge;
+ if (nonManifold[i] || edge == -1) continue;
+ double vertex_area = 0;
+ do {
+ int ep = dedge_prev_3(edge), en = dedge_next_3(edge);
+
+ Vector3d v = V.col(F(edge % 3, edge / 3));
+ Vector3d vn = V.col(F(en % 3, en / 3));
+ Vector3d vp = V.col(F(ep % 3, ep / 3));
+
+ Vector3d face_center = (v + vp + vn) * (1.0f / 3.0f);
+ Vector3d prev = (v + vp) * 0.5f;
+ Vector3d next = (v + vn) * 0.5f;
+
+ vertex_area += 0.5f * ((v - prev).cross(v - face_center).norm() +
+ (v - next).cross(v - face_center).norm());
+
+ int opp = E2E[edge];
+ if (opp == -1) break;
+ edge = dedge_next_3(opp);
+ } while (edge != stop);
+
+ A[i] = vertex_area;
+ }
+}
+
+void Parametrizer::FixValence()
+{
+ // Remove Valence 2
+ while (true) {
+ bool update = false;
+ std::vector<int> marks(V2E_compact.size(), 0);
+ std::vector<int> erasedF(F_compact.size(), 0);
+ for (int i = 0; i < V2E_compact.size(); ++i) {
+ int deid0 = V2E_compact[i];
+ if (marks[i] || deid0 == -1)
+ continue;
+ int deid = deid0;
+ std::vector<int> dedges;
+ do {
+ dedges.push_back(deid);
+ int deid1 = deid / 4 * 4 + (deid + 3) % 4;
+ deid = E2E_compact[deid1];
+ } while (deid != deid0 && deid != -1);
+ if (dedges.size() == 2) {
+ int v1 = F_compact[dedges[0]/4][(dedges[0] + 1)%4];
+ int v2 = F_compact[dedges[0]/4][(dedges[0] + 2)%4];
+ int v3 = F_compact[dedges[1]/4][(dedges[1] + 1)%4];
+ int v4 = F_compact[dedges[1]/4][(dedges[1] + 2)%4];
+ if (marks[v1] || marks[v2] || marks[v3] || marks[v4])
+ continue;
+ marks[v1] = true;
+ marks[v2] = true;
+ marks[v3] = true;
+ marks[v4] = true;
+ if (v1 == v2 || v1 == v3 || v1 == v4 || v2 == v3 || v2 == v4 || v3 == v4) {
+ erasedF[dedges[0]/4] = 1;
+ } else {
+ F_compact[dedges[0]/4] = Vector4i(v1, v2, v3, v4);
+ }
+ erasedF[dedges[1]/4] = 1;
+ update = true;
+ }
+ }
+ if (update) {
+ int top = 0;
+ for (int i = 0; i < erasedF.size(); ++i) {
+ if (erasedF[i] == 0) {
+ F_compact[top++] = F_compact[i];
+ }
+ }
+ F_compact.resize(top);
+ compute_direct_graph_quad(O_compact, F_compact, V2E_compact, E2E_compact, boundary_compact,
+ nonManifold_compact);
+ } else {
+ break;
+ }
+ }
+ std::vector<std::vector<int> > v_dedges(V2E_compact.size());
+ for (int i = 0; i < F_compact.size(); ++i) {
+ for (int j = 0; j < 4; ++j) {
+ v_dedges[F_compact[i][j]].push_back(i * 4 + j);
+ }
+ }
+ int top = V2E_compact.size();
+ for (int i = 0; i < v_dedges.size(); ++i) {
+ std::map<int, int> groups;
+ int group_id = 0;
+ for (int j = 0; j < v_dedges[i].size(); ++j) {
+ int deid = v_dedges[i][j];
+ if (groups.count(deid))
+ continue;
+ int deid0 = deid;
+ do {
+ groups[deid] = group_id;
+ deid = deid / 4 * 4 + (deid + 3) % 4;
+ deid = E2E_compact[deid];
+ } while (deid != deid0 && deid != -1);
+ if (deid == -1) {
+ deid = deid0;
+ while (E2E_compact[deid] != -1) {
+ deid = E2E_compact[deid];
+ deid = deid / 4 * 4 + (deid + 1) % 4;
+ groups[deid] = group_id;
+ }
+ }
+ group_id += 1;
+ }
+ if (group_id > 1) {
+ for (auto& g : groups) {
+ if (g.second >= 1)
+ F_compact[g.first/4][g.first%4] = top - 1 + g.second;
+ }
+ for (int j = 1; j < group_id; ++j) {
+ Vset.push_back(Vset[i]);
+ N_compact.push_back(N_compact[i]);
+ Q_compact.push_back(Q_compact[i]);
+ O_compact.push_back(O_compact[i]);
+ }
+ top = O_compact.size();
+ }
+ }
+ compute_direct_graph_quad(O_compact, F_compact, V2E_compact, E2E_compact, boundary_compact,
+ nonManifold_compact);
+
+ // Decrease Valence
+ while (true) {
+ bool update = false;
+ std::vector<int> marks(V2E_compact.size(), 0);
+ std::vector<int> valences(V2E_compact.size(), 0);
+ for (int i = 0; i < V2E_compact.size(); ++i) {
+ int deid0 = V2E_compact[i];
+ if (deid0 == -1)
+ continue;
+ int deid = deid0;
+ int count = 0;
+ do {
+ count += 1;
+ int deid1 = E2E_compact[deid];
+ if (deid1 == -1) {
+ count += 1;
+ break;
+ }
+ deid = deid1 / 4 * 4 + (deid1 + 1) % 4;
+ } while (deid != deid0 && deid != -1);
+ if (deid == -1)
+ count += 1;
+ valences[i] = count;
+ }
+ std::priority_queue<std::pair<int, int> > prior_queue;
+ for (int i = 0; i < valences.size(); ++i) {
+ if (valences[i] > 5)
+ prior_queue.push(std::make_pair(valences[i], i));
+ }
+ while (!prior_queue.empty()) {
+ auto info = prior_queue.top();
+ prior_queue.pop();
+ if (marks[info.second])
+ continue;
+ int deid0 = V2E_compact[info.second];
+ if (deid0 == -1)
+ continue;
+ int deid = deid0;
+ std::vector<int> loop_vertices, loop_dedges;;
+ bool marked = false;
+ do {
+ int v = F_compact[deid/4][(deid+1)%4];
+ loop_dedges.push_back(deid);
+ loop_vertices.push_back(v);
+ if (marks[v])
+ marked = true;
+ int deid1 = E2E_compact[deid];
+ if (deid1 == -1)
+ break;
+ deid = deid1 / 4 * 4 + (deid1 + 1) % 4;
+ } while (deid != deid0 && deid != -1);
+ if (marked)
+ continue;
+
+ if (deid != -1) {
+ int step = (info.first + 1) / 2;
+ std::pair<int, int> min_val(0x7fffffff, 0x7fffffff);
+ int split_idx = -1;
+ for (int i = 0; i < loop_vertices.size(); ++i) {
+ if (i + step >= loop_vertices.size())
+ continue;
+ int v1 = valences[loop_vertices[i]];
+ int v2 = valences[loop_vertices[i + step]];
+ if (v1 < v2)
+ std::swap(v1, v2);
+ auto key = std::make_pair(v1, v2);
+ if (key < min_val) {
+ min_val = key;
+ split_idx = i + 1;
+ }
+ }
+ if (min_val.first >= info.first)
+ continue;
+ update = true;
+ for (int id = split_idx; id < split_idx + step; ++id) {
+ F_compact[loop_dedges[id]/4][loop_dedges[id]%4] = O_compact.size();
+ }
+ F_compact.push_back(Vector4i(O_compact.size(), loop_vertices[(split_idx+loop_vertices.size()-1)%loop_vertices.size()],info.second, loop_vertices[(split_idx + step - 1 + loop_vertices.size()) % loop_vertices.size()]));
+ } else {
+ for (int id = loop_vertices.size() / 2; id < loop_vertices.size(); ++id) {
+ F_compact[loop_dedges[id]/4][loop_dedges[id]%4] = O_compact.size();
+ }
+ update = true;
+ }
+ marks[info.second] = 1;
+ for (int i = 0; i < loop_vertices.size(); ++i) {
+ marks[loop_vertices[i]] = 1;
+ }
+ Vset.push_back(Vset[info.second]);
+ O_compact.push_back(O_compact[info.second]);
+ N_compact.push_back(N_compact[info.second]);
+ Q_compact.push_back(Q_compact[info.second]);
+ }
+ if (!update) {
+ break;
+ } else {
+ compute_direct_graph_quad(O_compact, F_compact, V2E_compact, E2E_compact, boundary_compact,
+ nonManifold_compact);
+ }
+ }
+ // Remove Zero Valence
+ std::vector<int> valences(V2E_compact.size(), 0);
+ for (int i = 0; i < F_compact.size(); ++i) {
+ for (int j = 0; j < 4; ++j) {
+ valences[F_compact[i][j]] = 1;
+ }
+ }
+ top = 0;
+ std::vector<int> compact_indices(valences.size());
+ for (int i = 0; i < valences.size(); ++i) {
+ if (valences[i] == 0)
+ continue;
+ N_compact[top] = N_compact[i];
+ O_compact[top] = O_compact[i];
+ Q_compact[top] = Q_compact[i];
+ Vset[top] = Vset[i];
+ compact_indices[i] = top;
+ top += 1;
+ }
+ for (int i = 0; i < F_compact.size(); ++i) {
+ for (int j = 0; j < 4; ++j) {
+ F_compact[i][j] = compact_indices[F_compact[i][j]];
+ }
+ }
+ N_compact.resize(top);
+ O_compact.resize(top);
+ Q_compact.resize(top);
+ Vset.resize(top);
+ compute_direct_graph_quad(O_compact, F_compact, V2E_compact, E2E_compact, boundary_compact,
+ nonManifold_compact);
+ {
+ compute_direct_graph_quad(O_compact, F_compact, V2E_compact, E2E_compact, boundary_compact,
+ nonManifold_compact);
+ std::vector<int> masks(F_compact.size() * 4, 0);
+ for (int i = 0; i < V2E_compact.size(); ++i) {
+ int deid0 = V2E_compact[i];
+ if (deid0 == -1)
+ continue;
+ int deid = deid0;
+ do {
+ masks[deid] = 1;
+ deid = E2E_compact[deid];
+ if (deid == -1) {
+ break;
+ }
+ deid = deid / 4 * 4 + (deid + 1) % 4;
+ } while (deid != deid0 && deid != -1);
+ }
+ std::vector<std::vector<int> > v_dedges(V2E_compact.size());
+ for (int i = 0; i < F_compact.size(); ++i) {
+ for (int j = 0; j < 4; ++j) {
+ v_dedges[F_compact[i][j]].push_back(i * 4 + j);
+ }
+ }
+ }
+ std::map<int, int> pts;
+ for (int i = 0; i < V2E_compact.size(); ++i) {
+ int deid0 = V2E_compact[i];
+ if (deid0 == -1)
+ continue;
+ int deid = deid0;
+ int count = 0;
+ do {
+ count += 1;
+ int deid1 = E2E_compact[deid];
+ if (deid1 == -1)
+ break;
+ deid = deid1 / 4 * 4 + (deid1 + 1) % 4;
+ } while (deid != deid0 && deid != -1);
+ if (pts.count(count) == 0)
+ pts[count] = 1;
+ else
+ pts[count] += 1;
+ }
+ return;
+}
+
+void Parametrizer::OutputMesh(const char* obj_name) {
+ std::ofstream os(obj_name);
+ for (int i = 0; i < O_compact.size(); ++i) {
+ auto t = O_compact[i] * this->normalize_scale + this->normalize_offset;
+ os << "v " << t[0] << " " << t[1] << " " << t[2] << "\n";
+ }
+ for (int i = 0; i < F_compact.size(); ++i) {
+ os << "f " << F_compact[i][0]+1 << " " << F_compact[i][1]+1
+ << " " << F_compact[i][2]+1 << " " << F_compact[i][3]+1
+ << "\n";
+ }
+ os.close();
+}
+
+} // namespace qflow
diff --git a/extern/quadriflow/src/parametrizer-scale.cpp b/extern/quadriflow/src/parametrizer-scale.cpp
new file mode 100644
index 00000000000..bbd901d08c9
--- /dev/null
+++ b/extern/quadriflow/src/parametrizer-scale.cpp
@@ -0,0 +1,119 @@
+#include "parametrizer.hpp"
+
+namespace qflow {
+
+void Parametrizer::ComputeInverseAffine()
+{
+ if (flag_adaptive_scale == 0)
+ return;
+ triangle_space.resize(F.cols());
+#ifdef WITH_OMP
+#pragma omp parallel for
+#endif
+ for (int i = 0; i < F.cols(); ++i) {
+ Matrix3d p, q;
+ p.col(0) = V.col(F(1, i)) - V.col(F(0, i));
+ p.col(1) = V.col(F(2, i)) - V.col(F(0, i));
+ p.col(2) = Nf.col(i);
+ q = p.inverse();
+ triangle_space[i].resize(2, 3);
+ for (int j = 0; j < 2; ++j) {
+ for (int k = 0; k < 3; ++k) {
+ triangle_space[i](j, k) = q(j, k);
+ }
+ }
+ }
+}
+
+void Parametrizer::EstimateSlope() {
+ auto& mF = hierarchy.mF;
+ auto& mQ = hierarchy.mQ[0];
+ auto& mN = hierarchy.mN[0];
+ auto& mV = hierarchy.mV[0];
+ FS.resize(2, mF.cols());
+ FQ.resize(3, mF.cols());
+ for (int i = 0; i < mF.cols(); ++i) {
+ const Vector3d& n = Nf.col(i);
+ const Vector3d &q_1 = mQ.col(mF(0, i)), &q_2 = mQ.col(mF(1, i)), &q_3 = mQ.col(mF(2, i));
+ const Vector3d &n_1 = mN.col(mF(0, i)), &n_2 = mN.col(mF(1, i)), &n_3 = mN.col(mF(2, i));
+ Vector3d q_1n = rotate_vector_into_plane(q_1, n_1, n);
+ Vector3d q_2n = rotate_vector_into_plane(q_2, n_2, n);
+ Vector3d q_3n = rotate_vector_into_plane(q_3, n_3, n);
+
+ auto p = compat_orientation_extrinsic_4(q_1n, n, q_2n, n);
+ Vector3d q = (p.first + p.second).normalized();
+ p = compat_orientation_extrinsic_4(q, n, q_3n, n);
+ q = (p.first * 2 + p.second);
+ q = q - n * q.dot(n);
+ FQ.col(i) = q.normalized();
+ }
+ for (int i = 0; i < mF.cols(); ++i) {
+ double step = hierarchy.mScale * 1.f;
+
+ const Vector3d &n = Nf.col(i);
+ Vector3d p = (mV.col(mF(0, i)) + mV.col(mF(1, i)) + mV.col(mF(2, i))) * (1.0 / 3.0);
+ Vector3d q_x = FQ.col(i), q_y = n.cross(q_x);
+ Vector3d q_xl = -q_x, q_xr = q_x;
+ Vector3d q_yl = -q_y, q_yr = q_y;
+ Vector3d q_yl_unfold = q_y, q_yr_unfold = q_y, q_xl_unfold = q_x, q_xr_unfold = q_x;
+ int f;
+ double tx, ty, len;
+
+ f = i; len = step;
+ TravelField(p, q_xl, len, f, hierarchy.mE2E, mV, mF, Nf, FQ, mQ, mN, triangle_space, &tx, &ty, &q_yl_unfold);
+
+ f = i; len = step;
+ TravelField(p, q_xr, len, f, hierarchy.mE2E, mV, mF, Nf, FQ, mQ, mN, triangle_space, &tx, &ty, &q_yr_unfold);
+
+ f = i; len = step;
+ TravelField(p, q_yl, len, f, hierarchy.mE2E, mV, mF, Nf, FQ, mQ, mN, triangle_space, &tx, &ty, &q_xl_unfold);
+
+ f = i; len = step;
+ TravelField(p, q_yr, len, f, hierarchy.mE2E, mV, mF, Nf, FQ, mQ, mN, triangle_space, &tx, &ty, &q_xr_unfold);
+ double dSx = (q_yr_unfold - q_yl_unfold).dot(q_x) / (2.0f * step);
+ double dSy = (q_xr_unfold - q_xl_unfold).dot(q_y) / (2.0f * step);
+ FS.col(i) = Vector2d(dSx, dSy);
+ }
+
+ std::vector<double> areas(mV.cols(), 0.0);
+ for (int i = 0; i < mF.cols(); ++i) {
+ Vector3d p1 = mV.col(mF(1, i)) - mV.col(mF(0, i));
+ Vector3d p2 = mV.col(mF(2, i)) - mV.col(mF(0, i));
+ double area = p1.cross(p2).norm();
+ for (int j = 0; j < 3; ++j) {
+ auto index = compat_orientation_extrinsic_index_4(FQ.col(i), Nf.col(i), mQ.col(mF(j, i)), mN.col(mF(j, i)));
+ double scaleX = FS.col(i).x(), scaleY = FS.col(i).y();
+ if (index.first != index.second % 2) {
+ std::swap(scaleX, scaleY);
+ }
+ if (index.second >= 2) {
+ scaleX = -scaleX;
+ scaleY = -scaleY;
+ }
+ hierarchy.mK[0].col(mF(j, i)) += area * Vector2d(scaleX, scaleY);
+ areas[mF(j, i)] += area;
+ }
+ }
+ for (int i = 0; i < mV.cols(); ++i) {
+ if (areas[i] != 0)
+ hierarchy.mK[0].col(i) /= areas[i];
+ }
+ for (int l = 0; l< hierarchy.mK.size() - 1; ++l) {
+ const MatrixXd &K = hierarchy.mK[l];
+ MatrixXd &K_next = hierarchy.mK[l + 1];
+ auto& toUpper = hierarchy.mToUpper[l];
+ for (int i = 0; i < toUpper.cols(); ++i) {
+ Vector2i upper = toUpper.col(i);
+ Vector2d k0 = K.col(upper[0]);
+
+ if (upper[1] != -1) {
+ Vector2d k1 = K.col(upper[1]);
+ k0 = 0.5 * (k0 + k1);
+ }
+
+ K_next.col(i) = k0;
+ }
+ }
+}
+
+} // namespace qflow
diff --git a/extern/quadriflow/src/parametrizer-sing.cpp b/extern/quadriflow/src/parametrizer-sing.cpp
new file mode 100644
index 00000000000..2d600e3cda4
--- /dev/null
+++ b/extern/quadriflow/src/parametrizer-sing.cpp
@@ -0,0 +1,142 @@
+#include "config.hpp"
+#include "field-math.hpp"
+#include "parametrizer.hpp"
+
+namespace qflow {
+
+void Parametrizer::ComputeOrientationSingularities() {
+ MatrixXd &N = hierarchy.mN[0], &Q = hierarchy.mQ[0];
+ const MatrixXi& F = hierarchy.mF;
+ singularities.clear();
+ for (int f = 0; f < F.cols(); ++f) {
+ int index = 0;
+ int abs_index = 0;
+ for (int k = 0; k < 3; ++k) {
+ int i = F(k, f), j = F(k == 2 ? 0 : (k + 1), f);
+ auto value =
+ compat_orientation_extrinsic_index_4(Q.col(i), N.col(i), Q.col(j), N.col(j));
+ index += value.second - value.first;
+ abs_index += std::abs(value.second - value.first);
+ }
+ int index_mod = modulo(index, 4);
+ if (index_mod == 1 || index_mod == 3) {
+ if (index >= 4 || index < 0) {
+ Q.col(F(0, f)) = -Q.col(F(0, f));
+ }
+ singularities[f] = index_mod;
+ }
+ }
+}
+
+void Parametrizer::ComputePositionSingularities() {
+ const MatrixXd &V = hierarchy.mV[0], &N = hierarchy.mN[0], &Q = hierarchy.mQ[0],
+ &O = hierarchy.mO[0];
+ const MatrixXi& F = hierarchy.mF;
+
+ pos_sing.clear();
+ pos_rank.resize(F.rows(), F.cols());
+ pos_index.resize(6, F.cols());
+ for (int f = 0; f < F.cols(); ++f) {
+ Vector2i index = Vector2i::Zero();
+ uint32_t i0 = F(0, f), i1 = F(1, f), i2 = F(2, f);
+
+ Vector3d q[3] = {Q.col(i0).normalized(), Q.col(i1).normalized(), Q.col(i2).normalized()};
+ Vector3d n[3] = {N.col(i0), N.col(i1), N.col(i2)};
+ Vector3d o[3] = {O.col(i0), O.col(i1), O.col(i2)};
+ Vector3d v[3] = {V.col(i0), V.col(i1), V.col(i2)};
+
+ int best[3];
+ double best_dp = -std::numeric_limits<double>::infinity();
+ for (int i = 0; i < 4; ++i) {
+ Vector3d v0 = rotate90_by(q[0], n[0], i);
+ for (int j = 0; j < 4; ++j) {
+ Vector3d v1 = rotate90_by(q[1], n[1], j);
+ for (int k = 0; k < 4; ++k) {
+ Vector3d v2 = rotate90_by(q[2], n[2], k);
+ double dp = std::min(std::min(v0.dot(v1), v1.dot(v2)), v2.dot(v0));
+ if (dp > best_dp) {
+ best_dp = dp;
+ best[0] = i;
+ best[1] = j;
+ best[2] = k;
+ }
+ }
+ }
+ }
+ pos_rank(0, f) = best[0];
+ pos_rank(1, f) = best[1];
+ pos_rank(2, f) = best[2];
+ for (int k = 0; k < 3; ++k) q[k] = rotate90_by(q[k], n[k], best[k]);
+
+ for (int k = 0; k < 3; ++k) {
+ int kn = k == 2 ? 0 : (k + 1);
+ double scale_x = hierarchy.mScale, scale_y = hierarchy.mScale,
+ scale_x_1 = hierarchy.mScale, scale_y_1 = hierarchy.mScale;
+ if (flag_adaptive_scale) {
+ scale_x *= hierarchy.mS[0](0, F(k, f));
+ scale_y *= hierarchy.mS[0](1, F(k, f));
+ scale_x_1 *= hierarchy.mS[0](0, F(kn, f));
+ scale_y_1 *= hierarchy.mS[0](1, F(kn, f));
+ if (best[k] % 2 != 0) std::swap(scale_x, scale_y);
+ if (best[kn] % 2 != 0) std::swap(scale_x_1, scale_y_1);
+ }
+ double inv_scale_x = 1.0 / scale_x, inv_scale_y = 1.0 / scale_y,
+ inv_scale_x_1 = 1.0 / scale_x_1, inv_scale_y_1 = 1.0 / scale_y_1;
+ std::pair<Vector2i, Vector2i> value = compat_position_extrinsic_index_4(
+ v[k], n[k], q[k], o[k], v[kn], n[kn], q[kn], o[kn], scale_x, scale_y, inv_scale_x,
+ inv_scale_y, scale_x_1, scale_y_1, inv_scale_x_1, inv_scale_y_1, nullptr);
+ auto diff = value.first - value.second;
+ index += diff;
+ pos_index(k * 2, f) = diff[0];
+ pos_index(k * 2 + 1, f) = diff[1];
+ }
+
+ if (index != Vector2i::Zero()) {
+ pos_sing[f] = rshift90(index, best[0]);
+ }
+ }
+}
+
+void Parametrizer::AnalyzeValence() {
+ auto& F = hierarchy.mF;
+ std::map<int, int> sing;
+ for (auto& f : singularities) {
+ for (int i = 0; i < 3; ++i) {
+ sing[F(i, f.first)] = f.second;
+ }
+ }
+ auto& F2E = face_edgeIds;
+ auto& E2E = hierarchy.mE2E;
+ auto& FQ = face_edgeOrients;
+ std::set<int> sing1, sing2;
+ for (int i = 0; i < F2E.size(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ int deid = i * 3 + j;
+ int sum_int = 0;
+ std::vector<int> edges;
+ std::vector<double> angles;
+ do {
+ int deid1 = deid / 3 * 3 + (deid + 2) % 3;
+ deid = E2E[deid1];
+ sum_int += (FQ[deid / 3][deid % 3] + 6 - FQ[deid1 / 3][deid1 % 3]) % 4;
+ } while (deid != i * 3 + j);
+ if (sum_int % 4 == 2) {
+ printf("OMG! valence = 2\n");
+ exit(0);
+ }
+ if (sum_int % 4 == 1) sing1.insert(F(j, i));
+ if (sum_int % 4 == 3) sing2.insert(F(j, i));
+ }
+ }
+ int count3 = 0, count4 = 0;
+ for (auto& s : singularities) {
+ if (s.second == 1)
+ count3 += 1;
+ else
+ count4 += 1;
+ }
+ printf("singularity: <%d %d> <%d %d>\n", (int)sing1.size(), (int)sing2.size(), count3, count4);
+}
+
+
+} // namespace qflow
diff --git a/extern/quadriflow/src/parametrizer.cpp b/extern/quadriflow/src/parametrizer.cpp
new file mode 100644
index 00000000000..b85383566c9
--- /dev/null
+++ b/extern/quadriflow/src/parametrizer.cpp
@@ -0,0 +1,247 @@
+#include "parametrizer.hpp"
+#include "config.hpp"
+#include "dedge.hpp"
+#include "field-math.hpp"
+#include "flow.hpp"
+#include "localsat.hpp"
+#include "optimizer.hpp"
+#include "subdivide.hpp"
+
+#include "dset.hpp"
+
+#include <Eigen/Sparse>
+#include <fstream>
+#include <list>
+#include <map>
+#include <queue>
+#include <set>
+
+namespace qflow {
+
+void Parametrizer::ComputeIndexMap(int with_scale) {
+ // build edge info
+ auto& V = hierarchy.mV[0];
+ auto& F = hierarchy.mF;
+ auto& Q = hierarchy.mQ[0];
+ auto& N = hierarchy.mN[0];
+ auto& O = hierarchy.mO[0];
+ auto& S = hierarchy.mS[0];
+ // ComputeOrientationSingularities();
+
+ BuildEdgeInfo();
+
+ if (flag_preserve_sharp) {
+ // ComputeSharpO();
+ }
+ for (int i = 0; i < sharp_edges.size(); ++i) {
+ if (sharp_edges[i]) {
+ int e = face_edgeIds[i / 3][i % 3];
+ if (edge_diff[e][0] * edge_diff[e][1] != 0) {
+ Vector3d d = O.col(edge_values[e].y) - O.col(edge_values[e].x);
+ Vector3d q = Q.col(edge_values[e].x);
+ Vector3d n = N.col(edge_values[e].x);
+ Vector3d qy = n.cross(q);
+ if (abs(q.dot(d)) > qy.dot(d))
+ edge_diff[e][1] = 0;
+ else
+ edge_diff[e][0] = 0;
+ }
+ }
+ }
+ std::map<int, std::pair<Vector3d, Vector3d>> sharp_constraints;
+ std::set<int> sharpvert;
+ for (int i = 0; i < sharp_edges.size(); ++i) {
+ if (sharp_edges[i]) {
+ sharpvert.insert(F(i % 3, i / 3));
+ sharpvert.insert(F((i + 1) % 3, i / 3));
+ }
+ }
+
+ allow_changes.resize(edge_diff.size() * 2, 1);
+ for (int i = 0; i < sharp_edges.size(); ++i) {
+ int e = face_edgeIds[i / 3][i % 3];
+ if (sharpvert.count(edge_values[e].x) && sharpvert.count(edge_values[e].y)) {
+ if (sharp_edges[i] != 0) {
+ for (int k = 0; k < 2; ++k) {
+ if (edge_diff[e][k] == 0) {
+ allow_changes[e * 2 + k] = 0;
+ }
+ }
+ }
+ }
+ }
+#ifdef LOG_OUTPUT
+ printf("Build Integer Constraints...\n");
+#endif
+ BuildIntegerConstraints();
+
+ ComputeMaxFlow();
+ // potential bug
+#ifdef LOG_OUTPUT
+ printf("subdivide...\n");
+#endif
+ subdivide_edgeDiff(F, V, N, Q, O, &hierarchy.mS[0], V2E, hierarchy.mE2E, boundary, nonManifold,
+ edge_diff, edge_values, face_edgeOrients, face_edgeIds, sharp_edges,
+ singularities, 1);
+
+ allow_changes.clear();
+ allow_changes.resize(edge_diff.size() * 2, 1);
+ for (int i = 0; i < sharp_edges.size(); ++i) {
+ if (sharp_edges[i] == 0) continue;
+ int e = face_edgeIds[i / 3][i % 3];
+ for (int k = 0; k < 2; ++k) {
+ if (edge_diff[e][k] == 0) allow_changes[e * 2 + k] = 0;
+ }
+ }
+
+#ifdef LOG_OUTPUT
+ printf("Fix flip advance...\n");
+ int t1 = GetCurrentTime64();
+#endif
+ FixFlipHierarchy();
+ subdivide_edgeDiff(F, V, N, Q, O, &hierarchy.mS[0], V2E, hierarchy.mE2E, boundary, nonManifold,
+ edge_diff, edge_values, face_edgeOrients, face_edgeIds, sharp_edges,
+ singularities, 1);
+ FixFlipSat();
+
+#ifdef LOG_OUTPUT
+ int t2 = GetCurrentTime64();
+ printf("Flip use %lf\n", (t2 - t1) * 1e-3);
+ printf("Post Linear Solver...\n");
+#endif
+ std::set<int> sharp_vertices;
+ for (int i = 0; i < sharp_edges.size(); ++i) {
+ if (sharp_edges[i] == 1) {
+ sharp_vertices.insert(F(i % 3, i / 3));
+ sharp_vertices.insert(F((i + 1) % 3, i / 3));
+ }
+ }
+
+ Optimizer::optimize_positions_sharp(hierarchy, edge_values, edge_diff, sharp_edges,
+ sharp_vertices, sharp_constraints, with_scale);
+
+ Optimizer::optimize_positions_fixed(hierarchy, edge_values, edge_diff, sharp_vertices,
+ sharp_constraints, flag_adaptive_scale);
+
+ AdvancedExtractQuad();
+
+ FixValence();
+
+ std::vector<int> sharp_o(O_compact.size(), 0);
+ std::map<int, std::pair<Vector3d, Vector3d>> compact_sharp_constraints;
+ for (int i = 0; i < Vset.size(); ++i) {
+ int sharpv = -1;
+ for (auto& p : Vset[i]) {
+ if (sharp_constraints.count(p)) {
+ sharpv = p;
+ sharp_o[i] = 1;
+ if (compact_sharp_constraints.count(i) == 0 ||
+ compact_sharp_constraints[i].second != Vector3d::Zero()) {
+ compact_sharp_constraints[i] = sharp_constraints[sharpv];
+ O_compact[i] = O.col(sharpv);
+ compact_sharp_constraints[i].first = O_compact[i];
+ }
+ }
+ }
+ }
+
+ std::map<std::pair<int, int>, int> o2e;
+ for (int i = 0; i < F_compact.size(); ++i) {
+ for (int j = 0; j < 4; ++j) {
+ int v1 = F_compact[i][j];
+ int v2 = F_compact[i][(j + 1) % 4];
+ o2e[std::make_pair(v1, v2)] = i * 4 + j;
+ }
+ }
+ std::vector<std::vector<int>> v2o(V.cols());
+ for (int i = 0; i < Vset.size(); ++i) {
+ for (auto v : Vset[i]) {
+ v2o[v].push_back(i);
+ }
+ }
+ std::vector<Vector3d> diffs(F_compact.size() * 4, Vector3d(0, 0, 0));
+ std::vector<int> diff_count(F_compact.size() * 4, 0);
+ for (int i = 0; i < F.cols(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ int v1 = F(j, i);
+ int v2 = F((j + 1) % 3, i);
+ if (v1 != edge_values[face_edgeIds[i][j]].x) continue;
+ if (edge_diff[face_edgeIds[i][j]].array().abs().sum() != 1) continue;
+ if (v2o[v1].size() > 1 || v2o[v2].size() > 1) continue;
+ for (auto o1 : v2o[v1]) {
+ for (auto o2 : v2o[v2]) {
+ auto key = std::make_pair(o1, o2);
+ if (o2e.count(key)) {
+ int dedge = o2e[key];
+ Vector3d q_1 = Q.col(v1);
+ Vector3d q_2 = Q.col(v2);
+ Vector3d n_1 = N.col(v1);
+ Vector3d n_2 = N.col(v2);
+ Vector3d q_1_y = n_1.cross(q_1);
+ Vector3d q_2_y = n_2.cross(q_2);
+ auto index = compat_orientation_extrinsic_index_4(q_1, n_1, q_2, n_2);
+ double s_x1 = S(0, v1), s_y1 = S(1, v1);
+ double s_x2 = S(0, v2), s_y2 = S(1, v2);
+ int rank_diff = (index.second + 4 - index.first) % 4;
+ if (rank_diff % 2 == 1) std::swap(s_x2, s_y2);
+ Vector3d qd_x = 0.5 * (rotate90_by(q_2, n_2, rank_diff) + q_1);
+ Vector3d qd_y = 0.5 * (rotate90_by(q_2_y, n_2, rank_diff) + q_1_y);
+ double scale_x = (with_scale ? 0.5 * (s_x1 + s_x2) : 1) * hierarchy.mScale;
+ double scale_y = (with_scale ? 0.5 * (s_y1 + s_y2) : 1) * hierarchy.mScale;
+ Vector2i diff = edge_diff[face_edgeIds[i][j]];
+ Vector3d C = diff[0] * scale_x * qd_x + diff[1] * scale_y * qd_y;
+
+ diff_count[dedge] += 1;
+ diffs[dedge] += C;
+ auto key = std::make_pair(o2, o1);
+ if (o2e.count(key)) {
+ int dedge = o2e[key];
+ diff_count[dedge] += 1;
+ diffs[dedge] -= C;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < F.cols(); ++i) {
+ Vector2i d1 = rshift90(edge_diff[face_edgeIds[i][0]], face_edgeOrients[i][0]);
+ Vector2i d2 = rshift90(edge_diff[face_edgeIds[i][1]], face_edgeOrients[i][1]);
+ if (d1[0] * d2[1] - d1[1] * d2[0] < 0) {
+ for (int j = 0; j < 3; ++j) {
+ int v1 = F(j, i);
+ int v2 = F((j + 1) % 3, i);
+ for (auto o1 : v2o[v1]) {
+ for (auto o2 : v2o[v2]) {
+ auto key = std::make_pair(o1, o2);
+ if (o2e.count(key)) {
+ int dedge = o2e[key];
+ diff_count[dedge] = 0;
+ diffs[dedge] = Vector3d(0, 0, 0);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < diff_count.size(); ++i) {
+ if (diff_count[i] != 0) {
+ diffs[i] /= diff_count[i];
+ diff_count[i] = 1;
+ }
+ }
+
+ Optimizer::optimize_positions_dynamic(F, V, N, Q, Vset, O_compact, F_compact, V2E_compact,
+ E2E_compact, sqrt(surface_area / F_compact.size()),
+ diffs, diff_count, o2e, sharp_o,
+ compact_sharp_constraints, flag_adaptive_scale);
+
+ // optimize_quad_positions(O_compact, N_compact, Q_compact, F_compact, V2E_compact,
+ // E2E_compact,
+ // V, N, Q, O, F, V2E, hierarchy.mE2E, disajoint_tree,
+ // hierarchy.mScale, false);
+}
+
+} // namespace qflow
diff --git a/extern/quadriflow/src/parametrizer.hpp b/extern/quadriflow/src/parametrizer.hpp
new file mode 100644
index 00000000000..1f4a02be6c2
--- /dev/null
+++ b/extern/quadriflow/src/parametrizer.hpp
@@ -0,0 +1,177 @@
+#ifndef PARAMETRIZER_H_
+#define PARAMETRIZER_H_
+#include <atomic>
+#include <condition_variable>
+#ifdef WITH_TBB
+#include <tbb/tbb.h>
+#endif
+
+#include <Eigen/Core>
+#include <Eigen/Dense>
+#include <list>
+#include <map>
+#include <set>
+#include <unordered_set>
+#include "adjacent-matrix.hpp"
+#include "disajoint-tree.hpp"
+#include "field-math.hpp"
+#include "hierarchy.hpp"
+#include "post-solver.hpp"
+#include "serialize.hpp"
+
+namespace qflow {
+
+using namespace Eigen;
+
+typedef std::pair<unsigned int, unsigned int> Edge;
+typedef std::map<int, std::pair<int, int>> SingDictionary;
+
+struct ExpandInfo {
+ ExpandInfo() {}
+ int current_v;
+ int singularity;
+ int step;
+ int edge_id;
+ int prev;
+};
+
+class Parametrizer {
+ public:
+ Parametrizer() {}
+ // Mesh Initialization
+ void Load(const char* filename);
+ void NormalizeMesh();
+ void ComputeMeshStatus();
+ void ComputeSmoothNormal();
+ void ComputeSharpEdges();
+ void ComputeSharpO();
+ void ComputeVertexArea();
+ void Initialize(int faces);
+
+ // Singularity and Mesh property
+ void AnalyzeValence();
+ void ComputeOrientationSingularities();
+ void ComputePositionSingularities();
+
+ // Integer Grid Map Pipeline
+ void ComputeIndexMap(int with_scale = 0);
+ void BuildEdgeInfo();
+ void ComputeMaxFlow();
+ void MarkInteger();
+ void BuildIntegerConstraints();
+
+ // Fix Flip
+ void FixFlipHierarchy();
+ void FixFlipSat();
+ void FixHoles();
+ void FixHoles(std::vector<int>& loop_vertices);
+ void FixValence();
+ double QuadEnergy(std::vector<int>& loop_vertices, std::vector<Vector4i>& res_quads,
+ int level);
+
+ // Quadmesh and IO
+ void AdvancedExtractQuad();
+ void BuildTriangleManifold(DisajointTree& disajoint_tree, std::vector<int>& edge,
+ std::vector<int>& face, std::vector<DEdge>& edge_values,
+ std::vector<Vector3i>& F2E, std::vector<Vector2i>& E2F,
+ std::vector<Vector2i>& EdgeDiff, std::vector<Vector3i>& FQ);
+ void OutputMesh(const char* obj_name);
+
+ std::map<int, int> singularities; // map faceid to valence (1 (valence=3) or 3(valence=5))
+ std::map<int, Vector2i> pos_sing;
+ MatrixXi pos_rank; // pos_rank(i, j) i \in [0, 3) jth face ith vertex rotate by its value so
+ // that all thress vertices are in the same orientation
+ MatrixXi pos_index; // pos_index(i x 2 + dim, j) i \in [0, 6) jth face ith vertex's
+ // (t_ij-t_ji)'s dim's dimenstion in the paper
+ // input mesh
+ MatrixXd V;
+ MatrixXd N;
+ MatrixXd Nf;
+ MatrixXd FS;
+ MatrixXd FQ;
+ MatrixXi F;
+
+ double normalize_scale;
+ Vector3d normalize_offset;
+
+ // data structures
+ VectorXd rho;
+ VectorXi V2E;
+ VectorXi E2E;
+ VectorXi boundary;
+ VectorXi nonManifold; // nonManifold vertices, in boolean
+ AdjacentMatrix adj;
+ Hierarchy hierarchy;
+
+ // Mesh Status;
+ double surface_area;
+ double scale;
+ double average_edge_length;
+ double max_edge_length;
+ VectorXd A;
+
+ // just for test
+ DisajointTree disajoint_tree;
+
+ int compact_num_v;
+ std::vector<std::vector<int>> Vset;
+ std::vector<Vector3d> O_compact;
+ std::vector<Vector3d> Q_compact;
+ std::vector<Vector3d> N_compact;
+ std::vector<Vector4i> F_compact;
+ std::set<std::pair<int, int>> Quad_edges;
+ std::vector<int> V2E_compact;
+ std::vector<int> E2E_compact;
+ VectorXi boundary_compact;
+ VectorXi nonManifold_compact;
+
+ std::vector<int> bad_vertices;
+ std::vector<double> counter;
+ std::vector<int>
+ sharp_edges; // sharp_edges[deid]: whether deid is a sharp edge that should be preserved
+ std::vector<int> allow_changes; // allow_changes[variable_id]: whether var can be changed
+ // based on sharp edges
+ std::vector<Vector2i> edge_diff; // edge_diff[edgeIds[i](j)]: t_ij+t_ji under
+ // edge_values[edgeIds[i](j)].x's Q value
+ std::vector<DEdge> edge_values; // see above
+ std::vector<Vector3i>
+ face_edgeIds; // face_edgeIds[i](j): ith face jth edge's "undirected edge ID"
+
+ // face_edgeOrients[i](j): Rotate from edge_diff space
+ // (a) initially, to F(0, i)'s Q space
+ // (b) later on, to a global Q space where some edges are fixed
+ std::vector<Vector3i> face_edgeOrients;
+
+ // variable[i].first: indices of the two equations corresponding to variable i
+ // variable[i].second: number of positive minus negative of variables' occurances
+ std::vector<std::pair<Vector2i, int>> variables;
+
+ struct QuadInfo {
+ QuadInfo() : patchId(-1), coordinate(0x10000000, 0x10000000), singular(0), edge(0) {}
+ int patchId;
+ Vector2i coordinate;
+ int singular;
+ int edge;
+ };
+ std::vector<QuadInfo> quad_info;
+
+ // scale
+ void ComputeInverseAffine();
+ void EstimateSlope();
+ std::vector<MatrixXd> triangle_space;
+
+ // flag
+ int flag_preserve_sharp = 0;
+ int flag_preserve_boundary = 0;
+ int flag_adaptive_scale = 0;
+ int flag_aggresive_sat = 0;
+ int flag_minimum_cost_flow = 0;
+};
+
+extern void generate_adjacency_matrix_uniform(const MatrixXi& F, const VectorXi& V2E,
+ const VectorXi& E2E, const VectorXi& nonManifold,
+ AdjacentMatrix& adj);
+
+} // namespace qflow
+
+#endif
diff --git a/extern/quadriflow/src/post-solver.cpp b/extern/quadriflow/src/post-solver.cpp
new file mode 100644
index 00000000000..6027ddd2eb7
--- /dev/null
+++ b/extern/quadriflow/src/post-solver.cpp
@@ -0,0 +1,427 @@
+//
+// post-solver.cpp
+// parametrize
+//
+// Created by Jingwei on 2/5/18.
+//
+#include <algorithm>
+#include <boost/program_options.hpp>
+#include <cmath>
+#include <cstdio>
+#include <string>
+
+#include "ceres/ceres.h"
+#include "ceres/rotation.h"
+
+#include "post-solver.hpp"
+#include "serialize.hpp"
+
+namespace qflow {
+
+/// Coefficient of area constraint. The magnitude is 1 if area is equal to 0.
+const double COEFF_AREA = 1;
+/// Coefficient of tangent constraint. The magnitude is 0.03 if the bais is reference_length.
+/// This is because current tangent constraint is not very accurate.
+/// This optimization conflicts with COEFF_AREA.
+const double COEFF_TANGENT = 0.02;
+/// Coefficient of normal constraint. The magnitude is the arc angle.
+const double COEFF_NORMAL = 1;
+/// Coefficient of normal constraint. The magnitude is the arc angle.
+const double COEFF_FLOW = 1;
+/// Coefficient of orthogonal edge. The magnitude is the arc angle.
+const double COEFF_ORTH = 1;
+/// Coefficient of edge length. The magnitude is the arc angle.
+const double COEFF_LENGTH = 1;
+/// Number of iterations of the CGNR solver
+const int N_ITER = 100;
+
+template <typename T, typename T2>
+T DotProduct(const T a[3], const T2 b[3]) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+}
+
+template <typename T>
+T Length2(const T a[3]) {
+ return DotProduct(a, a);
+}
+
+namespace ceres {
+inline double min(const double f, const double g) { return std::min(f, g); }
+
+template <typename T, int N>
+inline Jet<T, N> min(const Jet<T, N>& f, const Jet<T, N>& g) {
+ if (f.a < g.a)
+ return f;
+ else
+ return g;
+}
+} // namespace ceres
+
+bool DEBUG = 0;
+struct FaceConstraint {
+ FaceConstraint(double coeff_area, double coeff_normal, double coeff_flow, double coeff_orth,
+ double length, Vector3d normal[4], Vector3d Q0[4], Vector3d Q1[4])
+ : coeff_area(coeff_area),
+ coeff_normal(coeff_normal),
+ coeff_flow(coeff_flow),
+ coeff_orth(coeff_orth),
+ area0(length * length),
+ normal0{
+ normal[0],
+ normal[1],
+ normal[2],
+ normal[3],
+ },
+ Q0{Q0[0], Q0[1], Q0[2], Q0[3]},
+ Q1{Q1[0], Q1[1], Q1[2], Q1[3]} {}
+
+ template <typename T>
+ bool operator()(const T* p0, const T* p1, const T* p2, const T* p3, T* r) const {
+ const T* p[] = {p0, p1, p2, p3};
+ r[12] = T();
+ for (int k = 0; k < 4; ++k) {
+ auto pc = p[k];
+ auto pa = p[(k + 1) % 4];
+ auto pb = p[(k + 3) % 4];
+
+ T a[3]{pa[0] - pc[0], pa[1] - pc[1], pa[2] - pc[2]};
+ T b[3]{pb[0] - pc[0], pb[1] - pc[1], pb[2] - pc[2]};
+
+ T length_a = ceres::sqrt(Length2(a));
+ T length_b = ceres::sqrt(Length2(b));
+ T aa[3]{a[0] / length_a, a[1] / length_a, a[2] / length_a};
+ T bb[3]{b[0] / length_b, b[1] / length_b, b[2] / length_b};
+ r[3 * k + 0] = coeff_orth * DotProduct(aa, bb);
+
+ T degree_edge0 = ceres::abs(DotProduct(aa, &Q0[k][0]));
+ T degree_edge1 = ceres::abs(DotProduct(aa, &Q1[k][0]));
+ T degree_edge = ceres::min(degree_edge0, degree_edge1);
+ r[3 * k + 1] = coeff_flow * degree_edge;
+
+ T normal[3];
+ ceres::CrossProduct(a, b, normal);
+ T area = ceres::sqrt(Length2(normal));
+ r[12] += area;
+
+ assert(area != T());
+ for (int i = 0; i < 3; ++i) normal[i] /= area;
+ T degree_normal = DotProduct(normal, &normal0[k][0]) - T(1);
+ r[3 * k + 2] = coeff_normal * degree_normal * degree_normal;
+ }
+ r[12] = coeff_area * (r[12] / (4.0 * area0) - 1.0);
+ return true;
+ }
+
+ static ceres::CostFunction* create(double coeff_area, double coeff_normal, double coeff_flow,
+ double coeff_orth, double length, Vector3d normal[4],
+ Vector3d Q0[4], Vector3d Q1[4]) {
+ return new ceres::AutoDiffCostFunction<FaceConstraint, 13, 3, 3, 3, 3>(new FaceConstraint(
+ coeff_area, coeff_normal, coeff_flow, coeff_orth, length, normal, Q0, Q1));
+ }
+
+ double coeff_area;
+ double coeff_normal;
+ double coeff_flow;
+ double coeff_orth;
+
+ double area0;
+ Vector3d normal0[4];
+ Vector3d Q0[4], Q1[4];
+};
+
+struct VertexConstraint {
+ VertexConstraint(double coeff_tangent, Vector3d normal, double bias, double length)
+ : coeff{coeff_tangent / length * 10}, bias0{bias}, normal0{normal} {}
+
+ template <typename T>
+ bool operator()(const T* p, T* r) const {
+ r[0] = coeff * (DotProduct(p, &normal0[0]) - bias0);
+ return true;
+ }
+
+ static ceres::CostFunction* create(double coeff_tangent, Vector3d normal, double bias,
+ double length) {
+ return new ceres::AutoDiffCostFunction<VertexConstraint, 1, 3>(
+ new VertexConstraint(coeff_tangent, normal, bias, length));
+ }
+
+ double coeff;
+ double bias0;
+ Vector3d normal0;
+};
+
+void solve(std::vector<Vector3d>& O_quad, std::vector<Vector3d>& N_quad,
+ std::vector<Vector3d>& Q_quad, std::vector<Vector4i>& F_quad,
+ std::vector<double>& B_quad, MatrixXd& V, MatrixXd& N, MatrixXd& Q, MatrixXd& O,
+ MatrixXi& F, double reference_length, double coeff_area, double coeff_tangent,
+ double coeff_normal, double coeff_flow, double coeff_orth) {
+ printf("Parameter: \n");
+ printf(" coeff_area: %.4f\n", coeff_area);
+ printf(" coeff_tangent: %.4f\n", coeff_tangent);
+ printf(" coeff_normal: %.4f\n", coeff_normal);
+ printf(" coeff_flow: %.4f\n", coeff_flow);
+ printf(" coeff_orth: %.4f\n\n", coeff_orth);
+ int n_quad = Q_quad.size();
+
+ ceres::Problem problem;
+ std::vector<double> solution(n_quad * 3);
+ for (int vquad = 0; vquad < n_quad; ++vquad) {
+ solution[3 * vquad + 0] = O_quad[vquad][0];
+ solution[3 * vquad + 1] = O_quad[vquad][1];
+ solution[3 * vquad + 2] = O_quad[vquad][2];
+ }
+
+ // Face constraint (area and normal direction)
+ for (int fquad = 0; fquad < F_quad.size(); ++fquad) {
+ auto v = F_quad[fquad];
+ Vector3d normal[4], Q0[4], Q1[4];
+ for (int k = 0; k < 4; ++k) {
+ normal[k] = N_quad[v[k]];
+ Q0[k] = Q_quad[v[k]];
+ Q1[k] = Q0[k].cross(normal[k]).normalized();
+ }
+ ceres::CostFunction* cost_function = FaceConstraint::create(
+ coeff_area, coeff_normal, coeff_flow, coeff_orth, reference_length, normal, Q0, Q1);
+ problem.AddResidualBlock(cost_function, nullptr, &solution[3 * v[0]], &solution[3 * v[1]],
+ &solution[3 * v[2]], &solution[3 * v[3]]);
+ }
+
+ // Tangent constraint
+ for (int vquad = 0; vquad < O_quad.size(); ++vquad) {
+ ceres::CostFunction* cost_function = VertexConstraint::create(
+ coeff_tangent, N_quad[vquad], B_quad[vquad], reference_length);
+ problem.AddResidualBlock(cost_function, nullptr, &solution[3 * vquad]);
+ }
+
+ // Flow constraint
+
+ ceres::Solver::Options options;
+ options.num_threads = 1;
+ options.max_num_iterations = N_ITER;
+ options.initial_trust_region_radius = 1;
+ options.linear_solver_type = ceres::CGNR;
+ options.minimizer_progress_to_stdout = true;
+ ceres::Solver::Summary summary;
+ ceres::Solve(options, &problem, &summary);
+
+ std::cout << summary.BriefReport() << std::endl;
+
+ for (int vquad = 0; vquad < n_quad; ++vquad) {
+ O_quad[vquad][0] = solution[3 * vquad + 0];
+ O_quad[vquad][1] = solution[3 * vquad + 1];
+ O_quad[vquad][2] = solution[3 * vquad + 2];
+ }
+
+ return;
+}
+
+void optimize_quad_positions(std::vector<Vector3d>& O_quad, std::vector<Vector3d>& N_quad,
+ std::vector<Vector3d>& Q_quad, std::vector<Vector4i>& F_quad,
+ VectorXi& V2E_quad, std::vector<int>& E2E_quad, MatrixXd& V,
+ MatrixXd& N, MatrixXd& Q, MatrixXd& O, MatrixXi& F, VectorXi& V2E,
+ VectorXi& E2E, DisajointTree& disajoint_tree, double reference_length,
+ bool just_serialize) {
+ printf("Quad mesh info:\n");
+ printf("Number of vertices with normals and orientations: %d = %d = %d\n", (int)O_quad.size(),
+ (int)N_quad.size(), (int)Q_quad.size());
+ printf("Number of faces: %d\n", (int)F_quad.size());
+ printf("Number of directed edges: %d\n", (int)E2E_quad.size());
+ // Information for the original mesh
+ printf("Triangle mesh info:\n");
+ printf(
+ "Number of vertices with normals, "
+ "orientations and associated quad positions: "
+ "%d = %d = %d = %d\n",
+ (int)V.cols(), (int)N.cols(), (int)Q.cols(), (int)O.cols());
+ printf("Number of faces: %d\n", (int)F.cols());
+ printf("Number of directed edges: %d\n", (int)E2E.size());
+ printf("Reference length: %.2f\n", reference_length);
+
+ int flip_count = 0;
+ for (int i = 0; i < F_quad.size(); ++i) {
+ bool flipped = false;
+ for (int j = 0; j < 4; ++j) {
+ int v1 = F_quad[i][j];
+ int v2 = F_quad[i][(j + 1) % 4];
+ int v3 = F_quad[i][(j + 3) % 4];
+
+ Vector3d face_norm = (O_quad[v2] - O_quad[v1]).cross(O_quad[v3] - O_quad[v1]);
+ Vector3d vertex_norm = N_quad[v1];
+ if (face_norm.dot(vertex_norm) < 0) {
+ flipped = true;
+ }
+ }
+ if (flipped) {
+ flip_count++;
+ }
+ }
+ printf("Flipped Quads: %d\n", flip_count);
+
+ int n_quad = O_quad.size();
+ int n_trig = O.cols();
+ std::vector<double> B_quad(n_quad); // Average bias for quad vertex
+ std::vector<int> B_weight(n_quad);
+
+ printf("ntrig: %d, disjoint_tree.size: %d\n", n_trig, (int)disajoint_tree.indices.size());
+ for (int vtrig = 0; vtrig < n_trig; ++vtrig) {
+ int vquad = disajoint_tree.Index(vtrig);
+ double b = N_quad[vquad].dot(O.col(vtrig));
+ B_quad[vquad] += b;
+ B_weight[vquad] += 1;
+ }
+ for (int vquad = 0; vquad < n_quad; ++vquad) {
+ assert(B_weight[vquad]);
+ B_quad[vquad] /= B_weight[vquad];
+ }
+
+ puts("Save parameters to post.bin for optimization");
+ FILE* out = fopen("post.bin", "wb");
+ assert(out);
+ Save(out, O_quad);
+ Save(out, N_quad);
+ Save(out, Q_quad);
+ Save(out, F_quad);
+ Save(out, B_quad);
+ Save(out, V);
+ Save(out, N);
+ Save(out, Q);
+ Save(out, O);
+ Save(out, F);
+ Save(out, reference_length);
+ fclose(out);
+
+ if (!just_serialize) {
+ puts("Start post optimization");
+ solve(O_quad, N_quad, Q_quad, F_quad, B_quad, V, N, Q, O, F, reference_length, COEFF_AREA,
+ COEFF_TANGENT, COEFF_NORMAL, COEFF_FLOW, COEFF_ORTH);
+ }
+}
+
+#ifdef POST_SOLVER
+
+void SaveObj(const std::string& fname, std::vector<Vector3d> O_quad,
+ std::vector<Vector4i> F_quad) {
+ std::ofstream os(fname);
+ for (int i = 0; i < (int)O_quad.size(); ++i) {
+ os << "v " << O_quad[i][0] << " " << O_quad[i][1] << " " << O_quad[i][2] << "\n";
+ }
+ for (int i = 0; i < (int)F_quad.size(); ++i) {
+ os << "f " << F_quad[i][0] + 1 << " " << F_quad[i][1] + 1 << " " << F_quad[i][2] + 1 << " "
+ << F_quad[i][3] + 1 << "\n";
+ }
+ os.close();
+}
+
+int main(int argc, char* argv[]) {
+ double coeff_area;
+ double coeff_tangent;
+ double coeff_normal;
+ double coeff_flow;
+ double coeff_orth;
+
+ namespace po = boost::program_options;
+ po::options_description desc("Allowed options");
+ desc.add_options() // clang-format off
+ ("help,h", "produce help message")
+ ("area,a", po::value<double>(&coeff_area)->default_value(COEFF_AREA), "Set the coefficient of area constraint")
+ ("tangent,t", po::value<double>(&coeff_tangent)->default_value(COEFF_TANGENT), "Set the coefficient of tangent constraint")
+ ("normal,n", po::value<double>(&coeff_normal)->default_value(COEFF_NORMAL), "Set the coefficient of normal constraint")
+ ("flow,f", po::value<double>(&coeff_flow)->default_value(COEFF_FLOW), "Set the coefficient of flow (Q) constraint")
+ ("orth,o", po::value<double>(&coeff_orth)->default_value(COEFF_ORTH), "Set the coefficient of orthogonal constraint");
+
+ // clang-format on
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+ if (vm.count("help")) {
+ std::cout << desc << std::endl;
+ return 1;
+ }
+
+ std::vector<Vector3d> O_quad;
+ std::vector<Vector3d> N_quad;
+ std::vector<Vector3d> Q_quad;
+ std::vector<Vector4i> F_quad;
+ std::vector<double> B_quad;
+ MatrixXd V;
+ MatrixXd N;
+ MatrixXd Q;
+ MatrixXd O;
+ MatrixXi F;
+ double reference_length;
+
+ puts("Read parameters from post.bin");
+ FILE* in = fopen("post.bin", "rb");
+ assert(in);
+ Read(in, O_quad);
+ Read(in, N_quad);
+ Read(in, Q_quad);
+ Read(in, F_quad);
+ Read(in, B_quad);
+ Read(in, V);
+ Read(in, N);
+ Read(in, Q);
+ Read(in, O);
+ Read(in, F);
+ Read(in, reference_length);
+ fclose(in);
+ printf("reference_length: %.2f\n", reference_length);
+ SaveObj("presolver.obj", O_quad, F_quad);
+
+ int n_flip = 0;
+ double sum_degree = 0;
+ for (int i = 0; i < F_quad.size(); ++i) {
+ bool flipped = false;
+ for (int j = 0; j < 4; ++j) {
+ int v1 = F_quad[i][j];
+ int v2 = F_quad[i][(j + 1) % 4];
+ int v3 = F_quad[i][(j + 3) % 4];
+
+ Vector3d face_norm =
+ (O_quad[v2] - O_quad[v1]).cross(O_quad[v3] - O_quad[v1]).normalized();
+ Vector3d vertex_norm = N_quad[v1];
+ if (face_norm.dot(vertex_norm) < 0) {
+ flipped = true;
+ }
+ double degree = std::acos(face_norm.dot(vertex_norm));
+ assert(degree >= 0);
+ // printf("cos theta = %.2f\n", degree);
+ sum_degree += degree * degree;
+ }
+ n_flip += flipped;
+ }
+ printf("n_flip: %d\nsum_degree: %.3f\n", n_flip, sum_degree);
+
+ puts("Start post optimization");
+ solve(O_quad, N_quad, Q_quad, F_quad, B_quad, V, N, Q, O, F, reference_length, coeff_area,
+ coeff_tangent, coeff_normal, coeff_flow, coeff_orth);
+ SaveObj("postsolver.obj", O_quad, F_quad);
+
+ n_flip = 0;
+ sum_degree = 0;
+ for (int i = 0; i < F_quad.size(); ++i) {
+ bool flipped = false;
+ for (int j = 0; j < 4; ++j) {
+ int v1 = F_quad[i][j];
+ int v2 = F_quad[i][(j + 1) % 4];
+ int v3 = F_quad[i][(j + 3) % 4];
+
+ Vector3d face_norm =
+ (O_quad[v2] - O_quad[v1]).cross(O_quad[v3] - O_quad[v1]).normalized();
+ Vector3d vertex_norm = N_quad[v1];
+ if (face_norm.dot(vertex_norm) < 0) {
+ flipped = true;
+ }
+ double degree = std::acos(face_norm.dot(vertex_norm));
+ assert(degree >= 0);
+ sum_degree += degree * degree;
+ }
+ n_flip += flipped;
+ }
+ printf("n_flip: %d\nsum_degree: %.3f\n", n_flip, sum_degree);
+ return 0;
+}
+
+#endif
+
+} // namespace qflow
diff --git a/extern/quadriflow/src/post-solver.hpp b/extern/quadriflow/src/post-solver.hpp
new file mode 100644
index 00000000000..546245d801e
--- /dev/null
+++ b/extern/quadriflow/src/post-solver.hpp
@@ -0,0 +1,64 @@
+//
+// post-solver.hpp
+// Parametrize
+//
+// Created by Jingwei on 2/5/18.
+//
+
+#ifndef post_solver_h
+#define post_solver_h
+
+#include <Eigen/Core>
+#include <vector>
+#include "disajoint-tree.hpp"
+
+namespace qflow {
+
+using namespace Eigen;
+
+/*
+ * TODO: Optimize O_quad, and possibly N_quad
+ * Input:
+ * O_quad[i]: initialized i-th vertex position of the quad mesh
+ * N_quad[i]: initialized i-th vertex normal of the quad mesh
+ * Q_quad[i]: initialized i-th vertex orientation of the quad mesh, guaranteed to be orthogonal to
+ * N_quad[i]
+ * F_quad[i]: 4 vertex index of the i-th quad face
+ *
+ * Concept: i-th directed edge is the (i%4)-th edge of the (i/4)-th face of the quad mesh
+ * V2E_quad[i]: one directed edge from i-th vertex of the quad mesh
+ * E2E_quad[i]: the reverse directed edge's index of the i-th directed edge of the quad mesh
+ *
+ * V.col(i): i-th vertex position of the triangle mesh
+ * N.col(i): i-th vertex normal of the triangle mesh
+ * Q.col(i): i-th vertex orientation of the triangle mesh, guaranteed to be orthogonal to N.col(i)
+ * O.col(i): "quad position" associated with the i-th vertex in the triangle mesh (see InstantMesh
+ * position field)
+ * F.col(i): i-th triangle of the triangle mesh
+ *
+ * V2E[i]: one directed edge from the i-th vertex of the triangle mesh
+ * E2E[i]: the reverse directed edge's index of the i-th directed edge of the triangle mesh
+ *
+ * j = disajoint_tree.Index(i)
+ * the j-th vertex of the quad mesh is corresponding to the i-th vertex of the triangle mesh
+ * the relation is one-to-multiple
+ * O_quad can be viewed as an average of corresponding O
+ * N_quad can be viewed as an average of corresponding N
+ * Q_quad can be viewed as aggregation of corresponding Q
+ * Method that aggregates qi to qj with weights wi and wj:
+ * value = compat_orientation_extrinsic_4(qj, nj, qi, ni)
+ * result = (value.first * wj + value.second * wi).normalized()
+ *
+ * Output:
+ * Optimized O_quad, (possibly N_quad)
+ */
+void optimize_quad_positions(std::vector<Vector3d>& O_quad, std::vector<Vector3d>& N_quad,
+ std::vector<Vector3d>& Q_quad, std::vector<Vector4i>& F_quad,
+ VectorXi& V2E_quad, std::vector<int>& E2E_quad, MatrixXd& V, MatrixXd& N,
+ MatrixXd& Q, MatrixXd& O, MatrixXi& F, VectorXi& V2E, VectorXi& E2E,
+ DisajointTree& disajoint_tree, double reference_length,
+ bool just_serialize = true);
+
+} // namespace qflow
+
+#endif /* post_solver_h */
diff --git a/extern/quadriflow/src/serialize.hpp b/extern/quadriflow/src/serialize.hpp
new file mode 100644
index 00000000000..3e670e02fa5
--- /dev/null
+++ b/extern/quadriflow/src/serialize.hpp
@@ -0,0 +1,127 @@
+#ifndef SERIALIZE_H_
+#define SERIALIZE_H_
+
+#include <Eigen/Core>
+#include <fstream>
+#include <map>
+#include <set>
+#include <vector>
+#include "adjacent-matrix.hpp"
+
+namespace qflow {
+
+template <typename T, int A, int B>
+inline void Save(FILE* fp, const Eigen::Matrix<T, A, B>& m) {
+ int r = m.rows(), c = m.cols();
+ fwrite(&r, sizeof(int), 1, fp);
+ fwrite(&c, sizeof(int), 1, fp);
+ std::vector<T> buffer(r * c);
+ for (int i = 0; i < r; ++i) {
+ for (int j = 0; j < c; ++j) {
+ buffer[i * c + j] = m(i, j);
+ }
+ }
+ fwrite(buffer.data(), sizeof(T), r * c, fp);
+}
+
+template <typename T, int A, int B>
+inline void Read(FILE* fp, Eigen::Matrix<T, A, B>& m) {
+ int r, c;
+ fread(&r, sizeof(int), 1, fp);
+ fread(&c, sizeof(int), 1, fp);
+ std::vector<T> buffer(r * c);
+ fread(buffer.data(), sizeof(T), r * c, fp);
+ m.resize(r, c);
+ for (int i = 0; i < r; ++i) {
+ for (int j = 0; j < c; ++j) {
+ m(i, j) = buffer[i * c + j];
+ }
+ }
+}
+
+inline void Save(FILE* fp, const Link& p) { fwrite(&p, sizeof(Link), 1, fp); }
+
+inline void Read(FILE* fp, Link& p) { fread(&p, sizeof(Link), 1, fp); }
+
+inline void Save(FILE* fp, const TaggedLink& p) { fwrite(&p, sizeof(TaggedLink), 1, fp); }
+
+inline void Read(FILE* fp, TaggedLink& p) { fread(&p, sizeof(TaggedLink), 1, fp); }
+
+inline void Save(FILE* fp, double p) { fwrite(&p, sizeof(double), 1, fp); }
+
+inline void Read(FILE* fp, double& p) { fread(&p, sizeof(double), 1, fp); }
+
+inline void Save(FILE* fp, int p) { fwrite(&p, sizeof(int), 1, fp); }
+
+inline void Read(FILE* fp, int& p) { fread(&p, sizeof(int), 1, fp); }
+
+template <class T, class F>
+inline void Save(FILE* fp, const std::pair<T, F>& p) {
+ fwrite(&p.first, sizeof(T), 1, fp);
+ fwrite(&p.second, sizeof(F), 1, fp);
+}
+
+template <class T, class F>
+inline void Read(FILE* fp, std::pair<T, F>& p) {
+ fread(&p.first, sizeof(T), 1, fp);
+ fread(&p.second, sizeof(F), 1, fp);
+}
+
+template <class T, class F>
+inline void Save(FILE* fp, const std::map<T, F>& p) {
+ int num = p.size();
+ fwrite(&num, sizeof(int), 1, fp);
+ for (auto& s : p) {
+ fwrite(&s, sizeof(s), 1, fp);
+ }
+}
+
+template <class T, class F>
+inline void Read(FILE* fp, std::map<T, F>& p) {
+ int num;
+ p.clear();
+ fread(&num, sizeof(int), 1, fp);
+ for (int i = 0; i < num; ++i) {
+ std::pair<T, F> m;
+ fread(&m, sizeof(m), 1, fp);
+ p.insert(m);
+ }
+}
+
+template <class T>
+void Save(FILE* fp, const std::vector<T>& p) {
+ int num = p.size();
+ fwrite(&num, sizeof(int), 1, fp);
+ for (auto& q : p) {
+ Save(fp, q);
+ }
+}
+
+template <class T>
+void Read(FILE* fp, std::vector<T>& p) {
+ int num;
+ fread(&num, sizeof(int), 1, fp);
+ p.resize(num);
+ for (auto& q : p) {
+ Read(fp, q);
+ }
+}
+
+template <class T>
+void Save(FILE* fp, const std::set<T>& p) {
+ std::vector<T> buffer;
+ buffer.insert(buffer.end(), p.begin(), p.end());
+ Save(fp, buffer);
+}
+
+template <class T>
+void Read(FILE* fp, std::set<T>& p) {
+ std::vector<T> buffer;
+ Read(fp, buffer);
+ p.clear();
+ for (auto& q : buffer) p.insert(q);
+}
+
+} // namespace qflow
+
+#endif
diff --git a/extern/quadriflow/src/subdivide.cpp b/extern/quadriflow/src/subdivide.cpp
new file mode 100644
index 00000000000..c408bbc6394
--- /dev/null
+++ b/extern/quadriflow/src/subdivide.cpp
@@ -0,0 +1,516 @@
+#include "subdivide.hpp"
+
+#include <fstream>
+#include <queue>
+
+#include "dedge.hpp"
+#include "disajoint-tree.hpp"
+#include "field-math.hpp"
+#include "parametrizer.hpp"
+
+namespace qflow {
+
+void subdivide(MatrixXi &F, MatrixXd &V, VectorXd& rho, VectorXi &V2E, VectorXi &E2E, VectorXi &boundary,
+ VectorXi &nonmanifold, double maxLength) {
+ typedef std::pair<double, int> Edge;
+
+ std::priority_queue<Edge> queue;
+
+ maxLength *= maxLength;
+
+ for (int i = 0; i < E2E.size(); ++i) {
+ int v0 = F(i % 3, i / 3), v1 = F((i + 1) % 3, i / 3);
+ if (nonmanifold[v0] || nonmanifold[v1]) continue;
+ double length = (V.col(v0) - V.col(v1)).squaredNorm();
+ if (length > maxLength || length > std::max(maxLength * 0.75, std::min(rho[v0], rho[v1]) * 1.0)) {
+ int other = E2E[i];
+ if (other == -1 || other > i) queue.push(Edge(length, i));
+ }
+ }
+
+ int nV = V.cols(), nF = F.cols(), nSplit = 0;
+ /*
+ / v0 \
+ v1p 1 | 0 v0p
+ \ v1 /
+
+ / v0 \
+ / 1 | 0 \
+ v1p - vn - v0p
+ \ 2 | 3 /
+ \ v1 /
+
+ f0: vn, v0p, v0
+ f1: vn, v0, v1p
+ f2: vn, v1p, v1
+ f3: vn, v1, v0p
+ */
+ int counter = 0;
+ while (!queue.empty()) {
+ counter += 1;
+ Edge edge = queue.top();
+ queue.pop();
+ int e0 = edge.second, e1 = E2E[e0];
+ bool is_boundary = e1 == -1;
+ int f0 = e0 / 3, f1 = is_boundary ? -1 : (e1 / 3);
+ int v0 = F(e0 % 3, f0), v0p = F((e0 + 2) % 3, f0), v1 = F((e0 + 1) % 3, f0);
+ if ((V.col(v0) - V.col(v1)).squaredNorm() != edge.first) {
+ continue;
+ }
+ int v1p = is_boundary ? -1 : F((e1 + 2) % 3, f1);
+ int vn = nV++;
+ nSplit++;
+ /* Update V */
+ if (nV > V.cols()) {
+ V.conservativeResize(V.rows(), V.cols() * 2);
+ rho.conservativeResize(V.cols() * 2);
+ V2E.conservativeResize(V.cols());
+ boundary.conservativeResize(V.cols());
+ nonmanifold.conservativeResize(V.cols());
+ }
+
+ /* Update V */
+ V.col(vn) = (V.col(v0) + V.col(v1)) * 0.5f;
+ rho[vn] = 0.5f * (rho[v0], rho[v1]);
+ nonmanifold[vn] = false;
+ boundary[vn] = is_boundary;
+
+ /* Update F and E2E */
+ int f2 = is_boundary ? -1 : (nF++);
+ int f3 = nF++;
+ if (nF > F.cols()) {
+ F.conservativeResize(F.rows(), std::max(nF, (int)F.cols() * 2));
+ E2E.conservativeResize(F.cols() * 3);
+ }
+
+ /* Update F */
+ F.col(f0) << vn, v0p, v0;
+ if (!is_boundary) {
+ F.col(f1) << vn, v0, v1p;
+ F.col(f2) << vn, v1p, v1;
+ }
+ F.col(f3) << vn, v1, v0p;
+
+ /* Update E2E */
+ const int e0p = E2E[dedge_prev_3(e0)], e0n = E2E[dedge_next_3(e0)];
+
+#define sE2E(a, b) \
+ E2E[a] = b; \
+ if (b != -1) E2E[b] = a;
+ sE2E(3 * f0 + 0, 3 * f3 + 2);
+ sE2E(3 * f0 + 1, e0p);
+ sE2E(3 * f3 + 1, e0n);
+ if (is_boundary) {
+ sE2E(3 * f0 + 2, -1);
+ sE2E(3 * f3 + 0, -1);
+ } else {
+ const int e1p = E2E[dedge_prev_3(e1)], e1n = E2E[dedge_next_3(e1)];
+ sE2E(3 * f0 + 2, 3 * f1 + 0);
+ sE2E(3 * f1 + 1, e1n);
+ sE2E(3 * f1 + 2, 3 * f2 + 0);
+ sE2E(3 * f2 + 1, e1p);
+ sE2E(3 * f2 + 2, 3 * f3 + 0);
+ }
+#undef sE2E
+
+ /* Update V2E */
+ V2E[v0] = 3 * f0 + 2;
+ V2E[vn] = 3 * f0 + 0;
+ V2E[v1] = 3 * f3 + 1;
+ V2E[v0p] = 3 * f0 + 1;
+ if (!is_boundary) V2E[v1p] = 3 * f1 + 2;
+
+ auto schedule = [&](int f) {
+ for (int i = 0; i < 3; ++i) {
+ double length = (V.col(F(i, f)) - V.col(F((i + 1) % 3, f))).squaredNorm();
+ if (length > maxLength
+ || length > std::max(maxLength * 0.75, std::min(rho[F(i, f)], rho[F((i + 1) % 3, f)]) * 1.0))
+ queue.push(Edge(length, f * 3 + i));
+ }
+ };
+
+ schedule(f0);
+ if (!is_boundary) {
+ schedule(f2);
+ schedule(f1);
+ };
+ schedule(f3);
+ }
+ F.conservativeResize(F.rows(), nF);
+ V.conservativeResize(V.rows(), nV);
+ rho.conservativeResize(nV);
+ V2E.conservativeResize(nV);
+ boundary.conservativeResize(nV);
+ nonmanifold.conservativeResize(nV);
+ E2E.conservativeResize(nF * 3);
+}
+
+void subdivide_edgeDiff(MatrixXi &F, MatrixXd &V, MatrixXd &N, MatrixXd &Q, MatrixXd &O, MatrixXd* S,
+ VectorXi &V2E, VectorXi &E2E, VectorXi &boundary, VectorXi &nonmanifold,
+ std::vector<Vector2i> &edge_diff, std::vector<DEdge> &edge_values,
+ std::vector<Vector3i> &face_edgeOrients, std::vector<Vector3i> &face_edgeIds,
+ std::vector<int>& sharp_edges, std::map<int, int> &singularities, int max_len) {
+ struct EdgeLink {
+ int id;
+ double length;
+ Vector2i diff;
+ int maxlen() const { return std::max(abs(diff[0]), abs(diff[1])); }
+ bool operator<(const EdgeLink &link) const { return maxlen() < link.maxlen(); }
+ };
+
+ struct FaceOrient {
+ int orient;
+ Vector3i d;
+ Vector3d q;
+ Vector3d n;
+ };
+
+ std::vector<FaceOrient> face_spaces(F.cols());
+ std::priority_queue<EdgeLink> queue;
+ std::vector<Vector2i> diffs(E2E.size());
+ for (int i = 0; i < F.cols(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ int eid = i * 3 + j;
+ diffs[eid] = rshift90(edge_diff[face_edgeIds[i][j]], face_edgeOrients[i][j]);
+ }
+ }
+ for (int i = 0; i < F.cols(); ++i) {
+ FaceOrient orient{};
+ orient.q = Q.col(F(0, i));
+ orient.n = N.col(F(0, i));
+ int orient_diff[3];
+ for (int j = 0; j < 3; ++j) {
+ int final_orient = face_edgeOrients[i][j];
+ int eid = face_edgeIds[i][j];
+ auto value = compat_orientation_extrinsic_index_4(
+ Q.col(edge_values[eid].x), N.col(edge_values[eid].x), orient.q, orient.n);
+ int target_orient = (value.second - value.first + 4) % 4;
+ if (F(j, i) == edge_values[eid].y) target_orient = (target_orient + 2) % 4;
+ orient_diff[j] = (final_orient - target_orient + 4) % 4;
+ }
+ if (orient_diff[0] == orient_diff[1])
+ orient.orient = orient_diff[0];
+ else if (orient_diff[0] == orient_diff[2])
+ orient.orient = orient_diff[2];
+ else if (orient_diff[1] == orient_diff[2])
+ orient.orient = orient_diff[1];
+ orient.d = Vector3i((orient_diff[0] - orient.orient + 4) % 4,
+ (orient_diff[1] - orient.orient + 4) % 4,
+ (orient_diff[2] - orient.orient + 4) % 4);
+ face_spaces[i] = (orient);
+ }
+ for (int i = 0; i < E2E.size(); ++i) {
+ int v0 = F(i % 3, i / 3), v1 = F((i + 1) % 3, i / 3);
+ if (nonmanifold[v0] || nonmanifold[v1]) continue;
+ double length = (V.col(v0) - V.col(v1)).squaredNorm();
+ Vector2i diff = diffs[i];
+ if (abs(diff[0]) > max_len || abs(diff[1]) > max_len) {
+ int other = E2E[i];
+ if (other == -1 || other > i) {
+ EdgeLink e;
+ e.id = i;
+ e.length = length;
+ e.diff = diff;
+ queue.push(e);
+ }
+ }
+ }
+ auto AnalyzeOrient = [&](int f0, const Vector3i &d) {
+ for (int j = 0; j < 3; ++j) {
+ int orient = face_spaces[f0].orient + d[j];
+ int v = std::min(F(j, f0), F((j + 1) % 3, f0));
+ auto value = compat_orientation_extrinsic_index_4(
+ Q.col(v), N.col(v), face_spaces[f0].q, face_spaces[f0].n);
+ if (F(j, f0) != v) orient += 2;
+ face_edgeOrients[f0][j] = (orient + value.second - value.first + 4) % 4;
+ }
+ face_spaces[f0].d = d;
+ for (int j = 0; j < 3; ++j) {
+ int eid = face_edgeIds[f0][j];
+ int orient = face_edgeOrients[f0][j];
+ auto diff = rshift90(diffs[f0 * 3 + j], (4 - orient) % 4);
+ edge_diff[eid] = diff;
+ }
+ };
+ auto FixOrient = [&](int f0) {
+ for (int j = 0; j < 3; ++j) {
+ auto diff = edge_diff[face_edgeIds[f0][j]];
+ if (rshift90(diff, face_edgeOrients[f0][j]) != diffs[f0 * 3 + j]) {
+ int orient = 0;
+ while (orient < 4 && rshift90(diff, orient) != diffs[f0 * 3 + j]) orient += 1;
+ face_spaces[f0].d[j] =
+ (face_spaces[f0].d[j] + orient - face_edgeOrients[f0][j]) % 4;
+ face_edgeOrients[f0][j] = orient;
+ }
+ }
+ };
+ /*
+ auto Length = [&](int f0) {
+ int l = 0;
+ for (int j = 0; j < 3; ++j) {
+ for (int k = 0; k < 2; ++k) {
+ l += abs(diffs[f0*3+j][k]);
+ }
+ printf("<%d %d> ", diffs[f0*3+j][0], diffs[f0*3+j][1]);
+ }
+ printf("\n");
+ return l;
+ };
+ */
+ int nV = V.cols(), nF = F.cols(), nSplit = 0;
+ /*
+ / v0 \
+ v1p 1 | 0 v0p
+ \ v1 /
+
+ / v0 \
+ / 1 | 0 \
+ v1p - vn - v0p
+ \ 2 | 3 /
+ \ v1 /
+
+ f0: vn, v0p, v0
+ f1: vn, v0, v1p
+ f2: vn, v1p, v1
+ f3: vn, v1, v0p
+ */
+ int counter = 0;
+ while (!queue.empty()) {
+ counter += 1;
+ EdgeLink edge = queue.top();
+ queue.pop();
+
+ int e0 = edge.id, e1 = E2E[e0];
+ bool is_boundary = e1 == -1;
+ int f0 = e0 / 3, f1 = is_boundary ? -1 : (e1 / 3);
+ int v0 = F(e0 % 3, f0), v0p = F((e0 + 2) % 3, f0), v1 = F((e0 + 1) % 3, f0);
+ if ((V.col(v0) - V.col(v1)).squaredNorm() != edge.length) {
+ continue;
+ }
+ if (abs(diffs[e0][0]) < 2 && abs(diffs[e0][1]) < 2) continue;
+ if (f1 != -1) {
+ face_edgeOrients.push_back(Vector3i());
+ sharp_edges.push_back(0);
+ sharp_edges.push_back(0);
+ sharp_edges.push_back(0);
+ face_edgeIds.push_back(Vector3i());
+ }
+ int v1p = is_boundary ? -1 : F((e1 + 2) % 3, f1);
+ int vn = nV++;
+ nSplit++;
+ if (nV > V.cols()) {
+ V.conservativeResize(V.rows(), V.cols() * 2);
+ N.conservativeResize(N.rows(), N.cols() * 2);
+ Q.conservativeResize(Q.rows(), Q.cols() * 2);
+ O.conservativeResize(O.rows(), O.cols() * 2);
+ if (S)
+ S->conservativeResize(S->rows(), S->cols() * 2);
+ V2E.conservativeResize(V.cols());
+ boundary.conservativeResize(V.cols());
+ nonmanifold.conservativeResize(V.cols());
+ }
+
+ V.col(vn) = (V.col(v0) + V.col(v1)) * 0.5;
+ N.col(vn) = N.col(v0);
+ Q.col(vn) = Q.col(v0);
+ O.col(vn) = (O.col(v0) + O.col(v1)) * 0.5;
+ if (S)
+ S->col(vn) = S->col(v0);
+
+ nonmanifold[vn] = false;
+ boundary[vn] = is_boundary;
+
+ int eid = face_edgeIds[f0][e0 % 3];
+ int sharp_eid = sharp_edges[e0];
+ int eid01 = face_edgeIds[f0][(e0 + 1) % 3];
+ int sharp_eid01 = sharp_edges[f0 * 3 + (e0 + 1) % 3];
+ int eid02 = face_edgeIds[f0][(e0 + 2) % 3];
+ int sharp_eid02 = sharp_edges[f0 * 3 + (e0 + 2) % 3];
+
+ int eid0, eid1, eid0p, eid1p;
+ int sharp_eid0, sharp_eid1, sharp_eid0p, sharp_eid1p;
+
+ eid0 = eid;
+ sharp_eid0 = sharp_eid;
+ edge_values[eid0] = DEdge(v0, vn);
+
+ eid1 = edge_values.size();
+ sharp_eid1 = sharp_eid;
+ edge_values.push_back(DEdge(vn, v1));
+ edge_diff.push_back(Vector2i());
+
+ eid0p = edge_values.size();
+ sharp_eid0p = 0;
+ edge_values.push_back(DEdge(vn, v0p));
+ edge_diff.push_back(Vector2i());
+
+ int f2 = is_boundary ? -1 : (nF++);
+ int f3 = nF++;
+ sharp_edges.push_back(0);
+ sharp_edges.push_back(0);
+ sharp_edges.push_back(0);
+ face_edgeIds.push_back(Vector3i());
+ face_edgeOrients.push_back(Vector3i());
+
+ if (nF > F.cols()) {
+ F.conservativeResize(F.rows(), std::max(nF, (int)F.cols() * 2));
+ face_spaces.resize(F.cols());
+ E2E.conservativeResize(F.cols() * 3);
+ diffs.resize(F.cols() * 3);
+ }
+
+ auto D01 = diffs[e0];
+ auto D1p = diffs[e0 / 3 * 3 + (e0 + 1) % 3];
+ auto Dp0 = diffs[e0 / 3 * 3 + (e0 + 2) % 3];
+
+ Vector2i D0n = D01 / 2;
+
+ auto orients1 = face_spaces[f0];
+ F.col(f0) << vn, v0p, v0;
+ face_edgeIds[f0] = Vector3i(eid0p, eid02, eid0);
+ sharp_edges[f0 * 3] = sharp_eid0p;
+ sharp_edges[f0 * 3 + 1] = sharp_eid02;
+ sharp_edges[f0 * 3 + 2] = sharp_eid0;
+
+ diffs[f0 * 3] = D01 + D1p - D0n;
+ diffs[f0 * 3 + 1] = Dp0;
+ diffs[f0 * 3 + 2] = D0n;
+ int o1 = e0 % 3, o2 = e1 % 3;
+ AnalyzeOrient(f0, Vector3i(0, orients1.d[(o1 + 2) % 3], orients1.d[o1]));
+ if (!is_boundary) {
+ auto orients2 = face_spaces[f1];
+ int eid11 = face_edgeIds[f1][(e1 + 1) % 3];
+ int sharp_eid11 = sharp_edges[f1 * 3 + (e1 + 1) % 3];
+ int eid12 = face_edgeIds[f1][(e1 + 2) % 3];
+ int sharp_eid12 = sharp_edges[f1 * 3 + (e1 + 2) % 3];
+
+ auto Ds10 = diffs[e1];
+ auto Ds0p = diffs[e1 / 3 * 3 + (e1 + 1) % 3];
+
+ auto Dsp1 = diffs[e1 / 3 * 3 + (e1 + 2) % 3];
+ int orient = 0;
+ while (rshift90(D01, orient) != Ds10) orient += 1;
+ Vector2i Dsn0 = rshift90(D0n, orient);
+
+ F.col(f1) << vn, v0, v1p;
+ eid1p = edge_values.size();
+ sharp_eid1p = 0;
+ edge_values.push_back(DEdge(vn, v1p));
+ edge_diff.push_back(Vector2i());
+
+ sharp_edges[f1 * 3] = sharp_eid0;
+ sharp_edges[f1 * 3 + 1] = sharp_eid11;
+ sharp_edges[f1 * 3 + 2] = sharp_eid1p;
+ face_edgeIds[f1] = (Vector3i(eid0, eid11, eid1p));
+ diffs[f1 * 3] = Dsn0;
+ diffs[f1 * 3 + 1] = Ds0p;
+ diffs[f1 * 3 + 2] = Dsp1 + (Ds10 - Dsn0);
+
+ AnalyzeOrient(f1, Vector3i(orients2.d[o2], orients2.d[(o2 + 1) % 3], 0));
+
+ face_spaces[f2] = face_spaces[f1];
+ sharp_edges[f2 * 3] = sharp_eid1p;
+ sharp_edges[f2 * 3 + 1] = sharp_eid12;
+ sharp_edges[f2 * 3 + 2] = sharp_eid1;
+ face_edgeIds[f2] = (Vector3i(eid1p, eid12, eid1));
+ F.col(f2) << vn, v1p, v1;
+ diffs[f2 * 3] = -Dsp1 - (Ds10 - Dsn0);
+ diffs[f2 * 3 + 1] = Dsp1;
+ diffs[f2 * 3 + 2] = Ds10 - Dsn0;
+
+ AnalyzeOrient(f2, Vector3i(0, orients2.d[(o2 + 2) % 3], orients2.d[o2]));
+ }
+ face_spaces[f3] = face_spaces[f0];
+ sharp_edges[f3 * 3] = sharp_eid1;
+ sharp_edges[f3 * 3 + 1] = sharp_eid01;
+ sharp_edges[f3 * 3 + 2] = sharp_eid0p;
+ face_edgeIds[f3] = (Vector3i(eid1, eid01, eid0p));
+ F.col(f3) << vn, v1, v0p;
+ diffs[f3 * 3] = D01 - D0n;
+ diffs[f3 * 3 + 1] = D1p;
+ diffs[f3 * 3 + 2] = D0n - (D01 + D1p);
+
+ AnalyzeOrient(f3, Vector3i(orients1.d[o1], orients1.d[(o1 + 1) % 3], 0));
+
+ FixOrient(f0);
+ if (!is_boundary) {
+ FixOrient(f1);
+ FixOrient(f2);
+ }
+ FixOrient(f3);
+
+ const int e0p = E2E[dedge_prev_3(e0)], e0n = E2E[dedge_next_3(e0)];
+
+#define sE2E(a, b) \
+ E2E[a] = b; \
+ if (b != -1) E2E[b] = a;
+ sE2E(3 * f0 + 0, 3 * f3 + 2);
+ sE2E(3 * f0 + 1, e0p);
+ sE2E(3 * f3 + 1, e0n);
+ if (is_boundary) {
+ sE2E(3 * f0 + 2, -1);
+ sE2E(3 * f3 + 0, -1);
+ } else {
+ const int e1p = E2E[dedge_prev_3(e1)], e1n = E2E[dedge_next_3(e1)];
+ sE2E(3 * f0 + 2, 3 * f1 + 0);
+ sE2E(3 * f1 + 1, e1n);
+ sE2E(3 * f1 + 2, 3 * f2 + 0);
+ sE2E(3 * f2 + 1, e1p);
+ sE2E(3 * f2 + 2, 3 * f3 + 0);
+ }
+#undef sE2E
+
+ V2E[v0] = 3 * f0 + 2;
+ V2E[vn] = 3 * f0 + 0;
+ V2E[v1] = 3 * f3 + 1;
+ V2E[v0p] = 3 * f0 + 1;
+ if (!is_boundary) V2E[v1p] = 3 * f1 + 2;
+
+ auto schedule = [&](int f) {
+ for (int i = 0; i < 3; ++i) {
+ if (abs(diffs[f * 3 + i][0]) > max_len || abs(diffs[f * 3 + i][1]) > max_len) {
+ EdgeLink e;
+ e.id = f * 3 + i;
+ e.length = (V.col(F((i + 1) % 3, f)) - V.col(F(i, f))).squaredNorm();
+ e.diff = diffs[f * 3 + i];
+ queue.push(e);
+ }
+ }
+ };
+
+ schedule(f0);
+ if (!is_boundary) {
+ schedule(f2);
+ schedule(f1);
+ };
+ schedule(f3);
+ }
+ F.conservativeResize(F.rows(), nF);
+ V.conservativeResize(V.rows(), nV);
+ N.conservativeResize(V.rows(), nV);
+ Q.conservativeResize(V.rows(), nV);
+ O.conservativeResize(V.rows(), nV);
+ if (S)
+ S->conservativeResize(S->rows(), nV);
+ V2E.conservativeResize(nV);
+ boundary.conservativeResize(nV);
+ nonmanifold.conservativeResize(nV);
+ E2E.conservativeResize(nF * 3);
+ for (int i = 0; i < F.cols(); ++i) {
+ for (int j = 0; j < 3; ++j) {
+ auto diff = edge_diff[face_edgeIds[i][j]];
+ if (abs(diff[0]) > 1 || abs(diff[1]) > 1) {
+ printf("wrong init %d %d!\n", face_edgeIds[i][j], i * 3 + j);
+ exit(0);
+ }
+ }
+ }
+ for (int i = 0; i < edge_diff.size(); ++i) {
+ if (abs(edge_diff[i][0]) > 1 || abs(edge_diff[i][1]) > 1) {
+ printf("wrong...\n");
+ exit(0);
+ }
+ }
+}
+
+} // namespace qflow
diff --git a/extern/quadriflow/src/subdivide.hpp b/extern/quadriflow/src/subdivide.hpp
new file mode 100644
index 00000000000..a93c58ac2a7
--- /dev/null
+++ b/extern/quadriflow/src/subdivide.hpp
@@ -0,0 +1,17 @@
+#include <Eigen/Core>
+#include <Eigen/Dense>
+
+#include "parametrizer.hpp"
+using namespace Eigen;
+
+namespace qflow {
+
+void subdivide(MatrixXi &F, MatrixXd &V, VectorXd& rho, VectorXi &V2E, VectorXi &E2E, VectorXi &boundary,
+ VectorXi &nonmanifold, double maxLength);
+
+void subdivide_edgeDiff(MatrixXi &F, MatrixXd &V, MatrixXd &N, MatrixXd &Q, MatrixXd &O, MatrixXd* S,
+ VectorXi &V2E, VectorXi &E2E, VectorXi &boundary, VectorXi &nonmanifold,
+ std::vector<Vector2i> &edge_diff, std::vector<DEdge> &edge_values,
+ std::vector<Vector3i> &face_edgeOrients, std::vector<Vector3i> &face_edgeIds,
+ std::vector<int>& sharp_edges, std::map<int, int> &singularities, int max_len);
+} // namespace qflow
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index b93f2057b47..4493c68a88d 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -76,3 +76,8 @@ endif()
if(WITH_OPENVDB)
add_subdirectory(openvdb)
endif()
+
+if(WITH_QUADRIFLOW)
+ add_subdirectory(quadriflow)
+endif()
+
diff --git a/intern/quadriflow/CMakeLists.txt b/intern/quadriflow/CMakeLists.txt
new file mode 100644
index 00000000000..615d5a34ce6
--- /dev/null
+++ b/intern/quadriflow/CMakeLists.txt
@@ -0,0 +1,45 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2019, Blender Foundation
+# All rights reserved.
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ ../guardedalloc
+)
+
+set(INC_SYS
+ ../../extern/quadriflow/src
+ ${BOOST_INCLUDE_DIR}
+ ${EIGEN3_INCLUDE_DIRS}
+)
+
+set(SRC
+ quadriflow_capi.cpp
+ quadriflow_capi.hpp
+)
+
+set(LIB
+ extern_quadriflow
+)
+
+if (WIN32)
+ add_definitions(-D_USE_MATH_DEFINES)
+endif()
+
+blender_add_lib(bf_intern_quadriflow "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/intern/quadriflow/quadriflow_capi.cpp b/intern/quadriflow/quadriflow_capi.cpp
new file mode 100644
index 00000000000..302c7a0ae30
--- /dev/null
+++ b/intern/quadriflow/quadriflow_capi.cpp
@@ -0,0 +1,238 @@
+// Copyright 2019 Blender Foundation. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// Author: Sebastian Parborg, Pablo Dobarro
+
+#include <unordered_map>
+
+#include "MEM_guardedalloc.h"
+
+#include "quadriflow_capi.hpp"
+#include "config.hpp"
+#include "field-math.hpp"
+#include "optimizer.hpp"
+#include "parametrizer.hpp"
+#include "loader.hpp"
+
+using namespace qflow;
+
+struct ObjVertex {
+ uint32_t p = (uint32_t)-1;
+ uint32_t n = (uint32_t)-1;
+ uint32_t uv = (uint32_t)-1;
+
+ ObjVertex()
+ {
+ }
+
+ ObjVertex(uint32_t pi)
+ {
+ p = pi;
+ }
+
+ bool operator==(const ObjVertex &v) const
+ {
+ return v.p == p && v.n == n && v.uv == uv;
+ }
+};
+
+struct ObjVertexHash : std::unary_function<ObjVertex, size_t> {
+ std::size_t operator()(const ObjVertex &v) const
+ {
+ size_t hash = std::hash<uint32_t>()(v.p);
+ hash = hash * 37 + std::hash<uint32_t>()(v.uv);
+ hash = hash * 37 + std::hash<uint32_t>()(v.n);
+ return hash;
+ }
+};
+
+typedef std::unordered_map<ObjVertex, uint32_t, ObjVertexHash> VertexMap;
+
+static int check_if_canceled(float progress,
+ void (*update_cb)(void *, float progress, int *cancel),
+ void *update_cb_data)
+{
+ int cancel = 0;
+ update_cb(update_cb_data, progress, &cancel);
+ return cancel;
+}
+
+void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
+ void (*update_cb)(void *, float progress, int *cancel),
+ void *update_cb_data)
+{
+ Parametrizer field;
+ VertexMap vertexMap;
+
+ /* Get remeshing parameters. */
+ int faces = qrd->target_faces;
+
+ if (qrd->preserve_sharp) {
+ field.flag_preserve_sharp = 1;
+ }
+ if (qrd->preserve_boundary) {
+ field.flag_preserve_boundary = 1;
+ }
+ if (qrd->adaptive_scale) {
+ field.flag_adaptive_scale = 1;
+ }
+ if (qrd->minimum_cost_flow) {
+ field.flag_minimum_cost_flow = 1;
+ }
+ if (qrd->aggresive_sat) {
+ field.flag_aggresive_sat = 1;
+ }
+ if (qrd->rng_seed) {
+ field.hierarchy.rng_seed = qrd->rng_seed;
+ }
+
+ if (check_if_canceled(0.0f, update_cb, update_cb_data) != 0) {
+ return;
+ }
+
+ /* Copy mesh to quadriflow data structures. */
+ std::vector<Vector3d> positions;
+ std::vector<uint32_t> indices;
+ std::vector<ObjVertex> vertices;
+
+ for (int i = 0; i < qrd->totverts; i++) {
+ Vector3d v(qrd->verts[i * 3], qrd->verts[i * 3 + 1], qrd->verts[i * 3 + 2]);
+ positions.push_back(v);
+ }
+
+ for (int q = 0; q < qrd->totfaces; q++) {
+ Vector3i f(qrd->faces[q * 3], qrd->faces[q * 3 + 1], qrd->faces[q * 3 + 2]);
+
+ ObjVertex tri[6];
+ int nVertices = 3;
+
+ tri[0] = ObjVertex(f[0]);
+ tri[1] = ObjVertex(f[1]);
+ tri[2] = ObjVertex(f[2]);
+
+ for (int i = 0; i < nVertices; ++i) {
+ const ObjVertex &v = tri[i];
+ VertexMap::const_iterator it = vertexMap.find(v);
+ if (it == vertexMap.end()) {
+ vertexMap[v] = (uint32_t)vertices.size();
+ indices.push_back((uint32_t)vertices.size());
+ vertices.push_back(v);
+ }
+ else {
+ indices.push_back(it->second);
+ }
+ }
+ }
+
+ field.F.resize(3, indices.size() / 3);
+ memcpy(field.F.data(), indices.data(), sizeof(uint32_t) * indices.size());
+
+ field.V.resize(3, vertices.size());
+ for (uint32_t i = 0; i < vertices.size(); ++i) {
+ field.V.col(i) = positions.at(vertices[i].p);
+ }
+
+ if (check_if_canceled(0.1f, update_cb, update_cb_data)) {
+ return;
+ }
+
+ /* Start processing the input mesh data */
+ field.NormalizeMesh();
+ field.Initialize(faces);
+
+ if (check_if_canceled(0.2f, update_cb, update_cb_data)) {
+ return;
+ }
+
+ /* Setup mesh boundary constraints if needed */
+ if (field.flag_preserve_boundary) {
+ Hierarchy &mRes = field.hierarchy;
+ mRes.clearConstraints();
+ for (uint32_t i = 0; i < 3 * mRes.mF.cols(); ++i) {
+ if (mRes.mE2E[i] == -1) {
+ uint32_t i0 = mRes.mF(i % 3, i / 3);
+ uint32_t i1 = mRes.mF((i + 1) % 3, i / 3);
+ Vector3d p0 = mRes.mV[0].col(i0), p1 = mRes.mV[0].col(i1);
+ Vector3d edge = p1 - p0;
+ if (edge.squaredNorm() > 0) {
+ edge.normalize();
+ mRes.mCO[0].col(i0) = p0;
+ mRes.mCO[0].col(i1) = p1;
+ mRes.mCQ[0].col(i0) = mRes.mCQ[0].col(i1) = edge;
+ mRes.mCQw[0][i0] = mRes.mCQw[0][i1] = mRes.mCOw[0][i0] = mRes.mCOw[0][i1] = 1.0;
+ }
+ }
+ }
+ mRes.propagateConstraints();
+ }
+
+ /* Optimize the mesh field orientations (tangental field etc) */
+ Optimizer::optimize_orientations(field.hierarchy);
+ field.ComputeOrientationSingularities();
+
+ if (check_if_canceled(0.3f, update_cb, update_cb_data)) {
+ return;
+ }
+
+ if (field.flag_adaptive_scale == 1) {
+ field.EstimateSlope();
+ }
+
+ if (check_if_canceled(0.4f, update_cb, update_cb_data)) {
+ return;
+ }
+
+ Optimizer::optimize_scale(field.hierarchy, field.rho, field.flag_adaptive_scale);
+ field.flag_adaptive_scale = 1;
+
+ Optimizer::optimize_positions(field.hierarchy, field.flag_adaptive_scale);
+
+ field.ComputePositionSingularities();
+
+ if (check_if_canceled(0.5f, update_cb, update_cb_data)) {
+ return;
+ }
+
+ /* Compute the final quad geomtry using a maxflow solver */
+ field.ComputeIndexMap();
+
+ if (check_if_canceled(0.9f, update_cb, update_cb_data)) {
+ return;
+ }
+
+ /* Get the output mesh data */
+ qrd->out_totverts = field.O_compact.size();
+ qrd->out_totfaces = field.F_compact.size();
+
+ qrd->out_verts = (float *)MEM_malloc_arrayN(
+ qrd->out_totverts, 3 * sizeof(float), "quadriflow remesher out verts");
+ qrd->out_faces = (unsigned int *)MEM_malloc_arrayN(
+ qrd->out_totfaces, 4 * sizeof(unsigned int), "quadriflow remesh out quads");
+
+ for (int i = 0; i < qrd->out_totverts; i++) {
+ auto t = field.O_compact[i] * field.normalize_scale + field.normalize_offset;
+ qrd->out_verts[i * 3] = t[0];
+ qrd->out_verts[i * 3 + 1] = t[1];
+ qrd->out_verts[i * 3 + 2] = t[2];
+ }
+
+ for (int i = 0; i < qrd->out_totfaces; i++) {
+ qrd->out_faces[i * 4] = field.F_compact[i][0];
+ qrd->out_faces[i * 4 + 1] = field.F_compact[i][1];
+ qrd->out_faces[i * 4 + 2] = field.F_compact[i][2];
+ qrd->out_faces[i * 4 + 3] = field.F_compact[i][3];
+ }
+}
diff --git a/intern/quadriflow/quadriflow_capi.hpp b/intern/quadriflow/quadriflow_capi.hpp
new file mode 100644
index 00000000000..c31fd6eff95
--- /dev/null
+++ b/intern/quadriflow/quadriflow_capi.hpp
@@ -0,0 +1,54 @@
+// Copyright 2019 Blender Foundation. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// Author: Sebastian Parborg, Pablo Dobarro
+
+#ifndef QUADRIFLOW_CAPI_HPP
+#define QUADRIFLOW_CAPI_HPP
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct QuadriflowRemeshData {
+ float *verts;
+ unsigned int *faces;
+ int totfaces;
+ int totverts;
+
+ float *out_verts;
+ unsigned int *out_faces;
+ int out_totverts;
+ int out_totfaces;
+
+ int target_faces;
+ bool preserve_sharp;
+ bool preserve_boundary;
+ bool adaptive_scale;
+ bool minimum_cost_flow;
+ bool aggresive_sat;
+ int rng_seed;
+} QuadriflowRemeshData;
+
+void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
+ void (*update_cb)(void *, float progress, int *cancel),
+ void *update_cb_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // QUADRIFLOW_CAPI_HPP
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 975f968b1b3..4994fac0b7d 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -468,14 +468,18 @@ class DATA_PT_remesh(MeshButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
layout.use_property_split = True
- col = layout.column()
+ row = layout.row()
mesh = context.mesh
- col.prop(mesh, "remesh_voxel_size")
- col.prop(mesh, "remesh_smooth_normals")
- col.prop(mesh, "remesh_preserve_paint_mask")
- col.operator("object.voxel_remesh", text="Voxel Remesh")
-
+ row.prop(mesh, "remesh_mode", text="Mode", expand=True)
+ col = layout.column()
+ if (mesh.remesh_mode == 'VOXEL'):
+ col.prop(mesh, "remesh_voxel_size")
+ col.prop(mesh, "remesh_smooth_normals")
+ col.prop(mesh, "remesh_preserve_paint_mask")
+ col.operator("object.voxel_remesh", text="Voxel Remesh")
+ else:
+ col.operator("object.quadriflow_remesh", text="QuadriFlow Remesh")
class DATA_PT_customdata(MeshButtonsPanel, Panel):
bl_label = "Geometry Data"
diff --git a/source/blender/blenkernel/BKE_mesh_remesh_voxel.h b/source/blender/blenkernel/BKE_mesh_remesh_voxel.h
index 089e4de4709..6b275e11cf7 100644
--- a/source/blender/blenkernel/BKE_mesh_remesh_voxel.h
+++ b/source/blender/blenkernel/BKE_mesh_remesh_voxel.h
@@ -39,6 +39,14 @@ struct Mesh *BKE_mesh_remesh_voxel_ovdb_volume_to_mesh_nomain(struct OpenVDBLeve
bool relax_disoriented_triangles);
#endif
struct Mesh *BKE_mesh_remesh_voxel_to_mesh_nomain(struct Mesh *mesh, float voxel_size);
+struct Mesh *BKE_mesh_remesh_quadriflow_to_mesh_nomain(struct Mesh *mesh,
+ int target_faces,
+ int seed,
+ bool preserve_sharp,
+ bool preserve_boundary,
+ bool adaptive_scale,
+ void *update_cb,
+ void *update_cb_data);
/* Data reprojection functions */
void BKE_remesh_reproject_paint_mask(struct Mesh *target, struct Mesh *source);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 4bf2f53f8f7..053e5435925 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -620,6 +620,16 @@ if(WITH_OPENVDB)
endif()
endif()
+if(WITH_QUADRIFLOW)
+ list(APPEND INC
+ ../../../intern/quadriflow
+ )
+ list(APPEND LIB
+ bf_intern_quadriflow
+ )
+ add_definitions(-DWITH_QUADRIFLOW)
+endif()
+
## Warnings as errors, this is too strict!
#if(MSVC)
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.c b/source/blender/blenkernel/intern/mesh_remesh_voxel.c
index a5136311a22..ff7ff947e1d 100644
--- a/source/blender/blenkernel/intern/mesh_remesh_voxel.c
+++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.c
@@ -49,6 +49,10 @@
# include "openvdb_capi.h"
#endif
+#ifdef WITH_QUADRIFLOW
+# include "quadriflow_capi.hpp"
+#endif
+
#ifdef WITH_OPENVDB
struct OpenVDBLevelSet *BKE_mesh_remesh_voxel_ovdb_mesh_to_level_set_create(
Mesh *mesh, struct OpenVDBTransform *transform)
@@ -146,6 +150,148 @@ Mesh *BKE_mesh_remesh_voxel_ovdb_volume_to_mesh_nomain(struct OpenVDBLevelSet *l
}
#endif
+#ifdef WITH_QUADRIFLOW
+static Mesh *BKE_mesh_remesh_quadriflow(Mesh *input_mesh,
+ int target_faces,
+ int seed,
+ bool preserve_sharp,
+ bool preserve_boundary,
+ bool adaptive_scale,
+ void *update_cb,
+ void *update_cb_data)
+{
+ /* Ensure that the triangulated mesh data is up to data */
+ BKE_mesh_runtime_looptri_recalc(input_mesh);
+ const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(input_mesh);
+
+ /* Gather the required data for export to the internal quadiflow mesh format */
+ MVertTri *verttri = MEM_callocN(sizeof(*verttri) * BKE_mesh_runtime_looptri_len(input_mesh),
+ "remesh_looptri");
+ BKE_mesh_runtime_verttri_from_looptri(
+ verttri, input_mesh->mloop, looptri, BKE_mesh_runtime_looptri_len(input_mesh));
+
+ unsigned int totfaces = BKE_mesh_runtime_looptri_len(input_mesh);
+ unsigned int totverts = input_mesh->totvert;
+ float *verts = (float *)MEM_malloc_arrayN(totverts * 3, sizeof(float), "remesh_input_verts");
+ unsigned int *faces = (unsigned int *)MEM_malloc_arrayN(
+ totfaces * 3, sizeof(unsigned int), "remesh_intput_faces");
+
+ for (unsigned int i = 0; i < totverts; i++) {
+ MVert *mvert = &input_mesh->mvert[i];
+ verts[i * 3] = mvert->co[0];
+ verts[i * 3 + 1] = mvert->co[1];
+ verts[i * 3 + 2] = mvert->co[2];
+ }
+
+ for (unsigned int i = 0; i < totfaces; i++) {
+ MVertTri *vt = &verttri[i];
+ faces[i * 3] = vt->tri[0];
+ faces[i * 3 + 1] = vt->tri[1];
+ faces[i * 3 + 2] = vt->tri[2];
+ }
+
+ /* Fill out the required input data */
+ QuadriflowRemeshData qrd;
+
+ qrd.totfaces = totfaces;
+ qrd.totverts = totverts;
+ qrd.verts = verts;
+ qrd.faces = faces;
+ qrd.target_faces = target_faces;
+
+ qrd.preserve_sharp = preserve_sharp;
+ qrd.preserve_boundary = preserve_boundary;
+ qrd.adaptive_scale = adaptive_scale;
+ qrd.minimum_cost_flow = 0;
+ qrd.aggresive_sat = 0;
+ qrd.rng_seed = seed;
+
+ qrd.out_faces = NULL;
+
+ /* Run the remesher */
+ QFLOW_quadriflow_remesh(&qrd, update_cb, update_cb_data);
+
+ MEM_freeN(verts);
+ MEM_freeN(faces);
+ MEM_freeN(verttri);
+
+ if (qrd.out_faces == NULL) {
+ /* The remeshing was canceled */
+ return NULL;
+ }
+
+ if (qrd.out_totfaces == 0) {
+ /* Meshing failed */
+ MEM_freeN(qrd.out_faces);
+ MEM_freeN(qrd.out_verts);
+ return NULL;
+ }
+
+ /* Construct the new output mesh */
+ Mesh *mesh = BKE_mesh_new_nomain(
+ qrd.out_totverts, 0, 0, (qrd.out_totfaces * 4), qrd.out_totfaces);
+
+ for (int i = 0; i < qrd.out_totverts; i++) {
+ copy_v3_v3(mesh->mvert[i].co, &qrd.out_verts[i * 3]);
+ }
+
+ MPoly *mp = mesh->mpoly;
+ MLoop *ml = mesh->mloop;
+ for (int i = 0; i < qrd.out_totfaces; i++, mp++, ml += 4) {
+ mp->loopstart = (int)(ml - mesh->mloop);
+ mp->totloop = 4;
+
+ ml[0].v = qrd.out_faces[i * 4];
+ ml[1].v = qrd.out_faces[i * 4 + 1];
+ ml[2].v = qrd.out_faces[i * 4 + 2];
+ ml[3].v = qrd.out_faces[i * 4 + 3];
+ }
+
+ BKE_mesh_calc_edges(mesh, false, false);
+ BKE_mesh_calc_normals(mesh);
+
+ MEM_freeN(qrd.out_faces);
+ MEM_freeN(qrd.out_verts);
+
+ return mesh;
+}
+#endif
+
+Mesh *BKE_mesh_remesh_quadriflow_to_mesh_nomain(Mesh *mesh,
+ int target_faces,
+ int seed,
+ bool preserve_sharp,
+ bool preserve_boundary,
+ bool adaptive_scale,
+ void *update_cb,
+ void *update_cb_data)
+{
+ Mesh *new_mesh = NULL;
+#ifdef WITH_QUADRIFLOW
+ if (target_faces <= 0) {
+ target_faces = -1;
+ }
+ new_mesh = BKE_mesh_remesh_quadriflow(mesh,
+ target_faces,
+ seed,
+ preserve_sharp,
+ preserve_boundary,
+ adaptive_scale,
+ update_cb,
+ update_cb_data);
+#else
+ UNUSED_VARS(mesh,
+ target_faces,
+ seed,
+ preserve_sharp,
+ preserve_boundary,
+ adaptive_scale,
+ update_cb,
+ update_cb_data);
+#endif
+ return new_mesh;
+}
+
Mesh *BKE_mesh_remesh_voxel_to_mesh_nomain(Mesh *mesh, float voxel_size)
{
Mesh *new_mesh = NULL;
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 669f3c44644..41205bc8778 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -281,6 +281,7 @@ void TRANSFORM_OT_vertex_random(struct wmOperatorType *ot);
/* object_remesh.c */
void OBJECT_OT_voxel_remesh(struct wmOperatorType *ot);
+void OBJECT_OT_quadriflow_remesh(struct wmOperatorType *ot);
/* object_transfer_data.c */
void OBJECT_OT_data_transfer(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index a1937c40191..f6b08b953a4 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -259,6 +259,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_hide_collection);
WM_operatortype_append(OBJECT_OT_voxel_remesh);
+ WM_operatortype_append(OBJECT_OT_quadriflow_remesh);
}
void ED_operatormacros_object(void)
diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c
index 5f464084a9b..815cc618d4b 100644
--- a/source/blender/editors/object/object_remesh.c
+++ b/source/blender/editors/object/object_remesh.c
@@ -88,7 +88,6 @@ static bool object_remesh_poll(bContext *C)
static int voxel_remesh_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
- Main *bmain = CTX_data_main(C);
Mesh *mesh = ob->data;
Mesh *new_mesh;
@@ -134,7 +133,6 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op)
}
BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
- DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
@@ -156,3 +154,391 @@ void OBJECT_OT_voxel_remesh(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+enum {
+ QUADRIFLOW_REMESH_RATIO = 1,
+ QUADRIFLOW_REMESH_EDGE_LENGTH,
+ QUADRIFLOW_REMESH_FACES,
+};
+
+/****************** quadriflow remesh operator *********************/
+
+typedef struct QuadriFlowJob {
+ /* from wmJob */
+ struct Object *owner;
+ short *stop, *do_update;
+ float *progress;
+
+ int target_faces;
+ int seed;
+ bool use_preserve_sharp;
+ bool use_preserve_boundary;
+ bool use_mesh_curvature;
+
+ bool preserve_paint_mask;
+ bool smooth_normals;
+
+ int success;
+} QuadriFlowJob;
+
+static void quadriflow_free_job(void *customdata)
+{
+ QuadriFlowJob *qj = customdata;
+ MEM_freeN(qj);
+}
+
+/* called by quadriflowjob, only to check job 'stop' value */
+static int quadriflow_break_job(void *customdata)
+{
+ QuadriFlowJob *qj = (QuadriFlowJob *)customdata;
+ // return *(qj->stop);
+
+ /* this is not nice yet, need to make the jobs list template better
+ * for identifying/acting upon various different jobs */
+ /* but for now we'll reuse the render break... */
+ bool should_break = (G.is_break);
+
+ if (should_break) {
+ qj->success = -1;
+ }
+
+ return should_break;
+}
+
+/* called by oceanbake, wmJob sends notifier */
+static void quadriflow_update_job(void *customdata, float progress, int *cancel)
+{
+ QuadriFlowJob *qj = customdata;
+
+ if (quadriflow_break_job(qj)) {
+ *cancel = 1;
+ }
+ else {
+ *cancel = 0;
+ }
+
+ *(qj->do_update) = true;
+ *(qj->progress) = progress;
+}
+
+static void quadriflow_start_job(void *customdata, short *stop, short *do_update, float *progress)
+{
+ QuadriFlowJob *qj = customdata;
+
+ qj->stop = stop;
+ qj->do_update = do_update;
+ qj->progress = progress;
+ qj->success = 1;
+
+ G.is_break = false; /* XXX shared with render - replace with job 'stop' switch */
+
+ Object *ob = qj->owner;
+ Mesh *mesh = ob->data;
+ Mesh *new_mesh;
+
+ new_mesh = BKE_mesh_remesh_quadriflow_to_mesh_nomain(mesh,
+ qj->target_faces,
+ qj->seed,
+ qj->use_preserve_sharp,
+ qj->use_preserve_boundary,
+ qj->use_mesh_curvature,
+ quadriflow_update_job,
+ (void *)qj);
+
+ if (!new_mesh) {
+ *do_update = true;
+ *stop = 0;
+ if (qj->success == 1) {
+ /* This is not a user cancelation event */
+ qj->success = 0;
+ }
+ return;
+ }
+
+ if (ob->mode == OB_MODE_SCULPT) {
+ ED_sculpt_undo_geometry_begin(ob);
+ }
+
+ Mesh *obj_mesh_copy = NULL;
+ if (qj->preserve_paint_mask) {
+ obj_mesh_copy = BKE_mesh_new_nomain_from_template(mesh, mesh->totvert, 0, 0, 0, 0);
+ CustomData_copy(
+ &mesh->vdata, &obj_mesh_copy->vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, mesh->totvert);
+ for (int i = 0; i < mesh->totvert; i++) {
+ copy_v3_v3(obj_mesh_copy->mvert[i].co, mesh->mvert[i].co);
+ }
+ }
+
+ BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob, &CD_MASK_MESH, true);
+
+ if (qj->preserve_paint_mask) {
+ BKE_remesh_reproject_paint_mask(mesh, obj_mesh_copy);
+ BKE_mesh_free(obj_mesh_copy);
+ }
+
+ if (qj->smooth_normals) {
+ BKE_mesh_smooth_flag_set(ob->data, true);
+ }
+
+ if (ob->mode == OB_MODE_SCULPT) {
+ ED_sculpt_undo_geometry_end(ob);
+ }
+
+ BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+
+ *do_update = true;
+ *stop = 0;
+}
+
+static void quadriflow_end_job(void *customdata)
+{
+ QuadriFlowJob *qj = customdata;
+
+ Object *ob = qj->owner;
+
+ WM_set_locked_interface(G_MAIN->wm.first, false);
+
+ if (qj->success > 0) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_reportf(RPT_INFO, "QuadriFlow: Completed remeshing!");
+ }
+ else {
+ if (qj->success == 0) {
+ WM_reportf(RPT_ERROR, "QuadriFlow: remeshing failed!");
+ }
+ else {
+ WM_report(RPT_WARNING, "QuadriFlow: remeshing canceled!");
+ }
+ }
+}
+
+static int quadriflow_remesh_exec(bContext *C, wmOperator *op)
+{
+ QuadriFlowJob *job = MEM_mallocN(sizeof(QuadriFlowJob), "QuadriFlowJob");
+
+ job->owner = CTX_data_active_object(C);
+
+ job->target_faces = RNA_int_get(op->ptr, "target_faces");
+ job->seed = RNA_int_get(op->ptr, "seed");
+
+ job->use_preserve_sharp = RNA_boolean_get(op->ptr, "use_preserve_sharp");
+ job->use_preserve_boundary = RNA_boolean_get(op->ptr, "use_preserve_boundary");
+
+ job->use_mesh_curvature = RNA_boolean_get(op->ptr, "use_mesh_curvature");
+
+ job->preserve_paint_mask = RNA_boolean_get(op->ptr, "preserve_paint_mask");
+ job->smooth_normals = RNA_boolean_get(op->ptr, "smooth_normals");
+
+ wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ CTX_data_scene(C),
+ "QuadriFlow Remesh",
+ WM_JOB_PROGRESS,
+ WM_JOB_TYPE_QUADRIFLOW_REMESH);
+
+ WM_jobs_customdata_set(wm_job, job, quadriflow_free_job);
+ WM_jobs_timer(wm_job, 0.1, NC_GEOM | ND_DATA, NC_GEOM | ND_DATA);
+ WM_jobs_callbacks(wm_job, quadriflow_start_job, NULL, NULL, quadriflow_end_job);
+
+ WM_set_locked_interface(CTX_wm_manager(C), true);
+
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+
+ return OPERATOR_FINISHED;
+}
+
+static bool quadriflow_check(bContext *C, wmOperator *op)
+{
+ int mode = RNA_enum_get(op->ptr, "mode");
+
+ if (mode == QUADRIFLOW_REMESH_EDGE_LENGTH) {
+ float area = RNA_float_get(op->ptr, "mesh_area");
+ if (area < 0.0f) {
+ Object *ob = CTX_data_active_object(C);
+ area = BKE_mesh_calc_area(ob->data);
+ RNA_float_set(op->ptr, "mesh_area", area);
+ }
+ int num_faces;
+ float edge_len = RNA_float_get(op->ptr, "target_edge_length");
+
+ num_faces = area / (edge_len * edge_len);
+ RNA_int_set(op->ptr, "target_faces", num_faces);
+ }
+ else if (mode == QUADRIFLOW_REMESH_RATIO) {
+ Object *ob = CTX_data_active_object(C);
+ Mesh *mesh = ob->data;
+
+ int num_faces;
+ float ratio = RNA_float_get(op->ptr, "target_ratio");
+
+ num_faces = mesh->totpoly * ratio;
+
+ RNA_int_set(op->ptr, "target_faces", num_faces);
+ }
+
+ return true;
+}
+
+/* Hide the target variables if they are not active */
+static bool quadriflow_poll_property(const bContext *C, wmOperator *op, const PropertyRNA *prop)
+{
+ const char *prop_id = RNA_property_identifier(prop);
+
+ if (STRPREFIX(prop_id, "target")) {
+ int mode = RNA_enum_get(op->ptr, "mode");
+
+ if (STREQ(prop_id, "target_edge_length") && mode != QUADRIFLOW_REMESH_EDGE_LENGTH) {
+ return false;
+ }
+ else if (STREQ(prop_id, "target_faces")) {
+ if (mode != QUADRIFLOW_REMESH_FACES) {
+ /* Make sure we can edit the target_faces value even if it doesn't start as EDITABLE */
+ float area = RNA_float_get(op->ptr, "mesh_area");
+ if (area < -0.8f) {
+ area += 0.2f;
+ /* Make sure we have up to date values from the start */
+ RNA_def_property_flag((PropertyRNA *)prop, PROP_EDITABLE);
+ quadriflow_check((bContext *)C, op);
+ }
+
+ /* Only disable input */
+ RNA_def_property_clear_flag((PropertyRNA *)prop, PROP_EDITABLE);
+ }
+ else {
+ RNA_def_property_flag((PropertyRNA *)prop, PROP_EDITABLE);
+ }
+ }
+ else if (STREQ(prop_id, "target_ratio") && mode != QUADRIFLOW_REMESH_RATIO) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static const EnumPropertyItem mode_type_items[] = {
+ {QUADRIFLOW_REMESH_RATIO,
+ "RATIO",
+ 0,
+ "Ratio",
+ "Specify target number of faces relative to the current mesh"},
+ {QUADRIFLOW_REMESH_EDGE_LENGTH,
+ "EDGE",
+ 0,
+ "Edge Length",
+ "Input target edge length in the new mesh"},
+ {QUADRIFLOW_REMESH_FACES, "FACES", 0, "Faces", "Input target number of faces in the new mesh"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+void OBJECT_OT_quadriflow_remesh(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "QuadriFlow Remesh";
+ ot->description =
+ "Create a new quad based mesh using the surface data of the current mesh. All data "
+ "layers will be lost";
+ ot->idname = "OBJECT_OT_quadriflow_remesh";
+
+ /* api callbacks */
+ ot->poll = object_remesh_poll;
+ ot->poll_property = quadriflow_poll_property;
+ ot->check = quadriflow_check;
+ ot->invoke = WM_operator_props_popup_confirm;
+ ot->exec = quadriflow_remesh_exec;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ PropertyRNA *prop;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "use_preserve_sharp",
+ false,
+ "Preserve Sharp",
+ "Try to preserve sharp features on the mesh");
+
+ RNA_def_boolean(ot->srna,
+ "use_preserve_boundary",
+ false,
+ "Preserve Mesh Boundary",
+ "Try to preserve mesh boundary on the mesh");
+
+ RNA_def_boolean(ot->srna,
+ "use_mesh_curvature",
+ false,
+ "Use Mesh Curvature",
+ "Take the mesh curvature into account when remeshing");
+
+ RNA_def_boolean(ot->srna,
+ "preserve_paint_mask",
+ false,
+ "Preserve Paint Mask",
+ "Reproject the paint mask onto the new mesh");
+
+ RNA_def_boolean(ot->srna,
+ "smooth_normals",
+ false,
+ "Smooth Normals",
+ "Set the output mesh normals to smooth");
+
+ RNA_def_enum(ot->srna,
+ "mode",
+ mode_type_items,
+ 0,
+ "Mode",
+ "How to specify the amount of detail for the new mesh");
+
+ prop = RNA_def_float(ot->srna,
+ "target_ratio",
+ 1,
+ 0,
+ FLT_MAX,
+ "Ratio",
+ "Relative number of faces compared to the current mesh",
+ 0.0f,
+ 1.0f);
+
+ prop = RNA_def_float(ot->srna,
+ "target_edge_length",
+ 0.1f,
+ 0.0000001f,
+ FLT_MAX,
+ "Edge Length",
+ "Target edge length in the new mesh",
+ 0.00001f,
+ 1.0f);
+
+ prop = RNA_def_int(ot->srna,
+ "target_faces",
+ 1,
+ 1,
+ INT_MAX,
+ "Number of Faces",
+ "Approximate number of faces (quads) in the new mesh",
+ 1,
+ INT_MAX);
+
+ prop = RNA_def_float(
+ ot->srna,
+ "mesh_area",
+ -1.0f,
+ -FLT_MAX,
+ FLT_MAX,
+ "Old Object Face Area",
+ "This property is only used to cache the object area for later calculations",
+ 0.0f,
+ FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ RNA_def_int(ot->srna,
+ "seed",
+ 0,
+ 0,
+ INT_MAX,
+ "Seed",
+ "Random seed to use with the solver. Different seeds will cause the remesher to "
+ "come up with different quad layouts on the mesh",
+ 0,
+ 255);
+}
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index cb6991ce67a..070180d0a24 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -193,7 +193,8 @@ typedef struct Mesh {
short totcol;
float remesh_voxel_size;
- char _pad1[4];
+ char remesh_mode;
+ char _pad1[3];
/** Deprecated multiresolution modeling data, only keep for loading old files. */
struct Multires *mr DNA_DEPRECATED;
@@ -261,6 +262,12 @@ enum {
ME_CDFLAG_EDGE_CREASE = 1 << 2,
};
+/* me->remesh_mode */
+enum {
+ REMESH_VOXEL = 0,
+ REMESH_QUAD = 1,
+};
+
/* Subsurf Type */
enum {
ME_CC_SUBSURF = 0,
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 12cfe157de2..1edf6a6b780 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -55,6 +55,12 @@ const EnumPropertyItem rna_enum_mesh_delimit_mode_items[] = {
{0, NULL, 0, NULL, NULL},
};
+const EnumPropertyItem rna_enum_mesh_remesh_mode_items[] = {
+ {REMESH_VOXEL, "VOXEL", 0, "Voxel", "Use the voxel remesher"},
+ {REMESH_QUAD, "QUAD", 0, "Quad", "Use the quad remesher"},
+ {0, NULL, 0, NULL, NULL},
+};
+
#ifdef RNA_RUNTIME
# include "DNA_scene_types.h"
@@ -3012,6 +3018,13 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_boolean_default(prop, false);
RNA_def_property_ui_text(prop, "Preserve Paint Mask", "Keep the current mask on the new mesh");
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
+
+ prop = RNA_def_property(srna, "remesh_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "remesh_mode");
+ RNA_def_property_enum_items(prop, rna_enum_mesh_remesh_mode_items);
+ RNA_def_property_ui_text(prop, "Remesh Mode", "");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
+
/* End remesh */
prop = RNA_def_property(srna, "use_auto_smooth", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index b933448d0bd..455a30b6ff5 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -686,6 +686,7 @@ enum {
WM_JOB_TYPE_STUDIOLIGHT,
WM_JOB_TYPE_LIGHT_BAKE,
WM_JOB_TYPE_FSMENU_BOOKMARK_VALIDATE,
+ WM_JOB_TYPE_QUADRIFLOW_REMESH,
/* add as needed, bake, seq proxy build
* if having hard coded values is a problem */
};