From 497c121e55a22cc27f5ee71af63a1e6472517cac Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 23 Jul 2019 08:39:16 +0200 Subject: [PATCH] Finalize API of alpha expansion + doc --- BGL/doc/BGL/BGL.txt | 41 +++ BGL/doc/BGL/Doxyfile.in | 3 +- BGL/doc/BGL/PackageDescription.txt | 1 + BGL/doc/BGL/fig/alpha_expansion.png | Bin 0 -> 15775 bytes .../boost/graph/alpha_expansion_graphcut.h | 335 +++++++++--------- .../alpha_expansion_graphcut_maxflow_gpl.h | 97 +++++ 6 files changed, 305 insertions(+), 172 deletions(-) create mode 100644 BGL/doc/BGL/fig/alpha_expansion.png rename Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Alpha_expansion_graph_cut.h => BGL/include/CGAL/boost/graph/alpha_expansion_graphcut.h (72%) create mode 100644 BGL/include/CGAL/boost/graph/alpha_expansion_graphcut_maxflow_gpl.h diff --git a/BGL/doc/BGL/BGL.txt b/BGL/doc/BGL/BGL.txt index 23c63b9f37d..8e90fb6bda3 100644 --- a/BGL/doc/BGL/BGL.txt +++ b/BGL/doc/BGL/BGL.txt @@ -653,6 +653,47 @@ can be done directly using `Face_filtered_graph`. Using \ref BGLNamedParameters some of the many options of METIS can be customized, as shown in \ref BGL_polyhedron_3/polyhedron_partition.cpp "this example". + +\section BGLGraphcut Graphcut + +Optimal partition from a set of labels can be computed through a +graphcut approach called Alpha Expansion +\cgalCite{boykov2001fastapproximate}. \cgal provides +`CGAL::alpha_expansion_graphcut()` which, or a graph \f$(V,E)\f$, this +function seeks for the partioning `f` that minimizes the following +energy: + +\f[ + \mathrm{E}(f) = \sum_{\{v0,v1\} \in E} W(v0,v1) + \sum_{v \in V} C(f_v) + \f] + +where \f$W(v0,v1)\f$ is the weight associated to the edge +\f$\{v0,v1\}\f$ and \f$C(f_v)\f$ is the cost of assigning the vertex +\f$v\f$ to the labeling \f$f\f$. + +Three different implementations are provided and can be selected by +using one of the following tags: + +- `CGAL::Alpha_expansion_boost_adjacency_list_tag` (default) +- `CGAL::Alpha_expansion_boost_compressed_sparse_raw_tag` +- `CGAL::Alpha_expansion_boost_MaxFlow_tag` + +All these implementation produce the exact same result but behave +differently in terms of timing and memory (see +\cgalFigureRef{alpha_exp}). The _MaxFlow_ implementation is the +fastest, but it grows rapidly in memory when increasing the complexity +of the input graph and labeling; the _compressed sparse raw_ (CSR) is very +efficient from a memory point of view but becomes very slow as the +complexity of the input graph and labeling increases; the _adjacency +list_ version provides a good compromise and is therefore the default +implementation. + +\cgalFigureBegin{alpha_exp, alpha_expansion.png} +Comparison of time and memory consumed by the different Alpha +Expansion implementation. +\cgalFigureEnd + + */ } /* namespace CGAL */ diff --git a/BGL/doc/BGL/Doxyfile.in b/BGL/doc/BGL/Doxyfile.in index c676a95fc13..8984e5b8082 100644 --- a/BGL/doc/BGL/Doxyfile.in +++ b/BGL/doc/BGL/Doxyfile.in @@ -15,7 +15,8 @@ INPUT += ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/Euler_operations.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/io.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/partition.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_graph.h \ - ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_dual_graph.h + ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_dual_graph.h \ + ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/alpha_expansion_graphcut.h EXAMPLE_PATH = ${CGAL_Surface_mesh_skeletonization_EXAMPLE_DIR} \ diff --git a/BGL/doc/BGL/PackageDescription.txt b/BGL/doc/BGL/PackageDescription.txt index 287b2662399..2b93f5cc4b9 100644 --- a/BGL/doc/BGL/PackageDescription.txt +++ b/BGL/doc/BGL/PackageDescription.txt @@ -710,6 +710,7 @@ user might encounter. \cgalCRPSection{Partitioning Methods} - `CGAL::METIS::partition_graph()` - `CGAL::METIS::partition_dual_graph()` +- `CGAL::alpha_expansion_graphcut()` \cgalCRPSection{I/O Functions} - \link PkgBGLIOFct CGAL::read_off() \endlink diff --git a/BGL/doc/BGL/fig/alpha_expansion.png b/BGL/doc/BGL/fig/alpha_expansion.png new file mode 100644 index 0000000000000000000000000000000000000000..afa8e5f457ff526654a58350acfe1c5c1b3cf7e0 GIT binary patch literal 15775 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 S9MF4sF_h%h<;rB<1pZ&}*=!8} literal 0 HcmV?d00001 diff --git a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Alpha_expansion_graph_cut.h b/BGL/include/CGAL/boost/graph/alpha_expansion_graphcut.h similarity index 72% rename from Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Alpha_expansion_graph_cut.h rename to BGL/include/CGAL/boost/graph/alpha_expansion_graphcut.h index 14bec111050..35930c748ac 100644 --- a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Alpha_expansion_graph_cut.h +++ b/BGL/include/CGAL/boost/graph/alpha_expansion_graphcut.h @@ -1,4 +1,4 @@ -#ifndef CGAL_SURFACE_MESH_SEGMENTATION_ALPHA_EXPANSION_GRAPH_CUT_H +#ifndef CGAL_BOOST_GRAPH_ALPHA_EXPANSION_GRAPHCUT_H // Copyright (c) 2014 GeometryFactory Sarl (France). // All rights reserved. // @@ -15,32 +15,13 @@ // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: LGPL-3.0+ // -// Author(s) : Ilker O. Yaz +// Author(s) : Ilker O. Yaz, Simon Giraudot -#define CGAL_SURFACE_MESH_SEGMENTATION_ALPHA_EXPANSION_GRAPH_CUT_H +#define CGAL_BOOST_GRAPH_ALPHA_EXPANSION_GRAPHCUT_H -#include - - -/// @cond CGAL_DOCUMENT_INTERNAL - -/** - * @file Alpha_expansion_graph_cut.h - * @brief This file contains 3 graph-cut algorithms, which can be used as a template parameter for CGAL::internal::Surface_mesh_segmentation. - * - * Main differences between implementations are underlying max-flow algorithm and graph type (i.e. results are the same, performance differs). - * - * By default, we use MAXFLOW and the class Alpha_expansion_graph_cut_boykov_kolmogorov. - * For deactivating MAXFLOW software and using boost implementation instead, define CGAL_DO_NOT_USE_BOYKOV_KOLMOGOROV_MAXFLOW_SOFTWARE. - * It deactivates Alpha_expansion_graph_cut_boykov_kolmogorov, activate boost versions - * and makes CGAL::internal::Surface_mesh_segmentation using Alpha_expansion_graph_cut_boost - * as default implementation for the graph-cut. - * - * Also algorithms can be used by their-own for applying alpha-expansion graph-cut on any graph. - * - */ +#include #include #ifdef CGAL_SEGMENTATION_BENCH_GRAPHCUT #include @@ -51,13 +32,6 @@ #include -#ifndef CGAL_DO_NOT_USE_BOYKOV_KOLMOGOROV_MAXFLOW_SOFTWARE -namespace MaxFlow -{ -#include -} -#endif - #include #include @@ -74,6 +48,8 @@ namespace MaxFlow namespace CGAL { + +/// \cond SKIP_IN_MANUAL namespace internal { @@ -91,25 +67,25 @@ struct Alpha_expansion_old_API_wrapper_graph typedef CGAL::Identity_property_map Vertex_index_map; typedef CGAL::Pointer_property_map::type Vertex_label_map; - struct Vertex_label_probability_map + struct Vertex_label_cost_map { typedef std::size_t key_type; typedef std::vector value_type; typedef value_type reference; typedef boost::readable_property_map_tag category; - const std::vector >* probability_matrix; + const std::vector >* cost_matrix; - Vertex_label_probability_map (const std::vector >* probability_matrix) - : probability_matrix (probability_matrix) + Vertex_label_cost_map (const std::vector >* cost_matrix) + : cost_matrix (cost_matrix) { } - friend reference get (const Vertex_label_probability_map& pmap, key_type idx) + friend reference get (const Vertex_label_cost_map& pmap, key_type idx) { std::vector out; - out.reserve (pmap.probability_matrix->size()); - for (std::size_t i = 0; i < pmap.probability_matrix->size(); ++ i) - out.push_back ((*pmap.probability_matrix)[i][idx]); + out.reserve (pmap.cost_matrix->size()); + for (std::size_t i = 0; i < pmap.cost_matrix->size(); ++ i) + out.push_back ((*pmap.cost_matrix)[i][idx]); return out; } @@ -119,14 +95,14 @@ struct Alpha_expansion_old_API_wrapper_graph const std::vector >& edges; const std::vector& edge_weights; - const std::vector >& probability_matrix; + const std::vector >& cost_matrix; std::vector& labels; Alpha_expansion_old_API_wrapper_graph (const std::vector >& edges, const std::vector& edge_weights, - const std::vector >& probability_matrix, + const std::vector >& cost_matrix, std::vector& labels) - : edges (edges), edge_weights (edge_weights), probability_matrix (probability_matrix), labels (labels) + : edges (edges), edge_weights (edge_weights), cost_matrix (cost_matrix), labels (labels) { } friend counting_range vertices (const Alpha_expansion_old_API_wrapper_graph& graph) @@ -150,8 +126,8 @@ struct Alpha_expansion_old_API_wrapper_graph Vertex_index_map vertex_index_map() const { return Vertex_index_map(); } Vertex_label_map vertex_label_map() { return CGAL::make_property_map(labels); } - Vertex_label_probability_map vertex_label_probability_map() const - { return Vertex_label_probability_map(&probability_matrix); } + Vertex_label_cost_map vertex_label_cost_map() const + { return Vertex_label_cost_map(&cost_matrix); } Edge_weight_map edge_weight_map() const { return CGAL::make_property_map(edge_weights); } }; @@ -206,7 +182,7 @@ struct Alpha_expansion_old_API_wrapper_graph * For representing graph, it uses adjacency_list with OutEdgeList = vecS, VertexList = listS. * Also no pre-allocation is made for vertex-list. */ -class Alpha_expansion_boost_adjacency_list +class Alpha_expansion_boost_adjacency_list_tag { private: typedef boost::adjacency_list_traits @@ -295,15 +271,6 @@ public: put (vertex_label_map, vd, alpha); } - /** - * Adds two directional edges between @a v1 and @a v2 - * @param v1 first vertex - * @param v2 second vertex - * @param w1 weight for edge from v1 to v2 (v1->v2) - * @param w2 weight for edge from v2 to v1 (v2->v1) - * @param graph to be added - * @return pair of added edges, first: v1->v2 and second: v2->v1 - */ void add_edge (Vertex_descriptor& v1, Vertex_descriptor& v2, double w1, double w2) { Edge_descriptor v1_v2, v2_v1; @@ -327,7 +294,7 @@ public: // another implementation using compressed_sparse_row_graph // for now there is a performance problem while setting reverse edges // if that can be solved, it is faster than Alpha_expansion_graph_cut_boost -class Alpha_expansion_boost_compressed_sparse_row +class Alpha_expansion_boost_compressed_sparse_row_tag { private: // CSR only accepts bundled props @@ -475,98 +442,123 @@ public: }; -#ifndef CGAL_DO_NOT_USE_BOYKOV_KOLMOGOROV_MAXFLOW_SOFTWARE -/** - * @brief Implements alpha-expansion graph cut algorithm. - * - * For underlying max-flow algorithm, it uses the MAXFLOW software implemented by Boykov & Kolmogorov. - * Also no pre-allocation is made. - */ -class Alpha_expansion_MaxFlow -{ -public: - - typedef MaxFlow::Graph::node_id Vertex_descriptor; - -private: - - MaxFlow::Graph graph; - -public: - - void clear_graph() - { - graph = MaxFlow::Graph(); - } - - Vertex_descriptor add_vertex() - { - return graph.add_node(); - } - - void add_tweight (Vertex_descriptor& v, double w1, double w2) - { - graph.add_tweights(v, w1, w2); - } - - void init_vertices() - { - } - - double max_flow() - { - return graph.maxflow(); - } - - template - void update(VertexLabelMap vertex_label_map, - const std::vector& inserted_vertices, - InputVertexDescriptor vd, - std::size_t vertex_i, - std::size_t alpha) - { - if(get(vertex_label_map, vd) != alpha - && graph.what_segment(inserted_vertices[vertex_i]) == MaxFlow::Graph::SINK) - put(vertex_label_map, vd, alpha); - } - - /** - * Adds two directional edges between @a v1 and @a v2 - * @param v1 first vertex - * @param v2 second vertex - * @param w1 weight for edge from v1 to v2 (v1->v2) - * @param w2 weight for edge from v2 to v1 (v2->v1) - * @param graph to be added - * @return pair of added edges, first: v1->v2 and second: v2->v1 - */ - void add_edge (Vertex_descriptor& v1, Vertex_descriptor& v2, double w1, double w2) - { - graph.add_edge(v1, v2, w1, w2); - } -}; -#endif //CGAL_DO_NOT_USE_BOYKOV_KOLMOGOROV_MAXFLOW_SOFTWARE -/// @endcond - +// Default version using boost adjacency list template -double alpha_expansion_graph_cut (const InputGraph& input_graph, - Edge_weight_map edge_weight_map, - Vertex_index_map vertex_index_map, - Vertex_label_map vertex_label_map, - Vertex_label_probability_map vertex_label_probability_map, - AlphaExpansionImplementation alpha_expansion = AlphaExpansionImplementation()) + typename EdgeWeightMap, + typename VertexIndexMap, + typename VertexLabelCostMap, + typename VertexLabelMap> +double alpha_expansion_graphcut (const InputGraph& input_graph, + EdgeWeightMap edge_weight_map, + VertexIndexMap vertex_index_map, + VertexLabelCostMap vertex_label_cost_map, + VertexLabelMap vertex_label_map) +{ + return alpha_expansion_graphcut + (input_graph, edge_weight_map, vertex_index_map, vertex_label_cost_map, vertex_label_map, + Alpha_expansion_boost_adjacency_list_tag()); +} + +/// \endcond + +// NOTE: latest performances check (2019-07-22) +// +// Using a random graph with 50000 vertices, 100000 edges and 30 labels: +// +// METHOD TIMING MEMORY +// Boost Adjacency list 49s 122MiB +// Boost CSR 187s 77MiB +// MaxFlow 12s 717MiB + +/** + \ingroup PkgBGLPartition + + Regularizes a partition of a graph into `n` labels using the Alpha + Expansion algorithm \cgalCite{Boykov2001FastApproximate}. + + For a graph \f$(V,E)\f$, this function seeks for the partioning `f` + that minimizes the following energy: + + \f[ + \mathrm{E}(f) = \sum_{\{v0,v1\} \in E} W(v0,v1) + \sum_{v \in V} C(f_v) + \f] + + where \f$W(v0,v1)\f$ is the weight associated to the edge + \f$\{v0,v1\}\f$ and \f$C(f_v)\f$ is the cost of assigning the + vertex \f$v\f$ to the labeling \f$f\f$. + + \tparam InputGraph a model of `Graph` + + \tparam EdgeWeightMap a model of `ReadablePropertyMap` with + `boost::graph_traits::%edge_descriptor` as key and `double` + as value. + + \tparam VertexIndexMap a model of `ReadablePropertyMap` with + `boost::graph_traits::%vertex_descriptor` as key and + `std::size_t` as value. + + \tparam VertexLabelCostMap a model of `ReadablePropertyMap` + with `boost::graph_traits::%vertex_descriptor` as key and + `std::vector` as value. + + \tparam VertexLabelMap a model of `ReadWritePropertyMap` with + `boost::graph_traits::%vertex_descriptor` as key and + `std::size_t` as value. + + \tparam AlphaExpansionImplementationTag optional tag used to select + which implementation of the Alpha Expansion should be + used. Available implementation tags are: + + - `CGAL::Alpha_expansion_boost_adjacency_list` (default) + - `CGAL::Alpha_expansion_boost_compressed_sparse_row_tag` + - `CGAL::Alpha_expansion_MaxFlow_tag` + + \note The `MaxFlow` implementation is provided separately under a + GPL license (whereas the rest of the package including this + function is under LGPL). The header + `` should be + included if users want to use this implementation. + + \param input_graph the input graph. + + \param edge_weight_map a property map providing the weight of each + edge. + + \param vertex_index_map a property map providing the index of each + vertex. + + \param vertex_label_map a property map providing the label of each + vertex. This map will be updated by the algorithm with the + regularized version of the partitioning. + + \param vertex_label_cost_map a property_map providing, for each + vertex, an `std::vector` containing the cost of this vertex to + belong to each label. For example, + `get(vertex_label_cost_map, vd)[label_idx]` returns the cost + of vertex `vd` to belong to the label `label_idx`. +*/ +template +double alpha_expansion_graphcut (const InputGraph& input_graph, + EdgeWeightMap edge_weight_map, + VertexIndexMap vertex_index_map, + VertexLabelCostMap vertex_label_cost_map, + VertexLabelMap vertex_label_map, + const AlphaExpansionImplementationTag&) { typedef boost::graph_traits GT; typedef typename GT::edge_descriptor input_edge_descriptor; typedef typename GT::vertex_descriptor input_vertex_descriptor; - typedef AlphaExpansionImplementation Alpha_expansion; + typedef AlphaExpansionImplementationTag Alpha_expansion; typedef typename Alpha_expansion::Vertex_descriptor Vertex_descriptor; + Alpha_expansion alpha_expansion; + // TODO: check this hardcoded parameter const double tolerance = 1e-10; @@ -580,7 +572,7 @@ double alpha_expansion_graph_cut (const InputGraph& input_graph, std::vector inserted_vertices; inserted_vertices.resize(num_vertices (input_graph)); - std::size_t number_of_labels = get(vertex_label_probability_map, *std::begin(vertices(input_graph))).size(); + std::size_t number_of_labels = get(vertex_label_cost_map, *std::begin(vertices(input_graph))).size(); bool success; do { @@ -602,12 +594,12 @@ double alpha_expansion_graph_cut (const InputGraph& input_graph, std::size_t vertex_i = get(vertex_index_map, vd); Vertex_descriptor new_vertex = alpha_expansion.add_vertex(); inserted_vertices[vertex_i] = new_vertex; - double source_weight = get(vertex_label_probability_map, vd)[alpha]; + double source_weight = get(vertex_label_cost_map, vd)[alpha]; // since it is expansion move, current alpha labeled vertices will be assigned to alpha again, // making sink_weight 'infinity' guarantee this. double sink_weight = (get(vertex_label_map, vd) == alpha ? (std::numeric_limits::max)() - : get(vertex_label_probability_map, vd)[get(vertex_label_map, vd)]); + : get(vertex_label_cost_map, vd)[get(vertex_label_map, vd)]); alpha_expansion.add_tweight(new_vertex, source_weight, sink_weight); } @@ -686,40 +678,41 @@ double alpha_expansion_graph_cut (const InputGraph& input_graph, return min_cut; } -template -double alpha_expansion_graph_cut (const InputGraph& input_graph, - Edge_weight_map edge_weight_map, - Vertex_index_map vertex_index_map, - Vertex_label_map vertex_label_map, - Vertex_label_probability_map vertex_label_probability_map) + +/// \cond SKIP_IN_MANUAL +// Old API +inline double alpha_expansion_graphcut (const std::vector >& edges, + const std::vector& edge_weights, + const std::vector >& cost_matrix, + std::vector& labels) { - return alpha_expansion_graph_cut - (input_graph, edge_weight_map, vertex_index_map, vertex_label_map, vertex_label_probability_map); + internal::Alpha_expansion_old_API_wrapper_graph graph (edges, edge_weights, cost_matrix, labels); + + return alpha_expansion_graphcut(graph, + graph.edge_weight_map(), + graph.vertex_index_map(), + graph.vertex_label_cost_map(), + graph.vertex_label_map()); } -// Old API -inline double alpha_expansion_graph_cut (const std::vector >& edges, - const std::vector& edge_weights, - const std::vector >& probability_matrix, - std::vector& labels) +template +double alpha_expansion_graphcut (const std::vector >& edges, + const std::vector& edge_weights, + const std::vector >& cost_matrix, + std::vector& labels, + const AlphaExpansionImplementationTag&) { - internal::Alpha_expansion_old_API_wrapper_graph graph (edges, edge_weights, probability_matrix, labels); + internal::Alpha_expansion_old_API_wrapper_graph graph (edges, edge_weights, cost_matrix, labels); - return alpha_expansion_graph_cut(graph, - graph.edge_weight_map(), - graph.vertex_index_map(), - graph.vertex_label_map(), - graph.vertex_label_probability_map()); + return alpha_expansion_graphcut(graph, + graph.edge_weight_map(), + graph.vertex_index_map(), + graph.vertex_label_cost_map(), + graph.vertex_label_map(), + AlphaExpansionImplementationTag()); } +/// \endcond + }//namespace CGAL -#endif //CGAL_SURFACE_MESH_SEGMENTATION_ALPHA_EXPANSION_GRAPH_CUT_H +#endif //CGAL_BOOST_GRAPH_ALPHA_EXPANSION_GRAPHCUT_H diff --git a/BGL/include/CGAL/boost/graph/alpha_expansion_graphcut_maxflow_gpl.h b/BGL/include/CGAL/boost/graph/alpha_expansion_graphcut_maxflow_gpl.h new file mode 100644 index 00000000000..c9457e816cf --- /dev/null +++ b/BGL/include/CGAL/boost/graph/alpha_expansion_graphcut_maxflow_gpl.h @@ -0,0 +1,97 @@ +#ifndef CGAL_BOOST_GRAPH_ALPHA_EXPANSION_GRAPHCUT_MAXFLOW_GPL_H +// Copyright (c) 2014 GeometryFactory Sarl (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// Author(s) : Ilker O. Yaz, Simon Giraudot + +#define CGAL_BOOST_GRAPH_ALPHA_EXPANSION_GRAPHCUT_MAXFLOW_GPL_H + +#include + +namespace MaxFlow +{ +#include +} + + +namespace CGAL +{ + +/** + * @brief Implements alpha-expansion graph cut algorithm. + * + * For underlying max-flow algorithm, it uses the MAXFLOW software implemented by Boykov & Kolmogorov. + * Also no pre-allocation is made. + */ +class Alpha_expansion_MaxFlow_tag +{ +public: + + typedef MaxFlow::Graph::node_id Vertex_descriptor; + +private: + + MaxFlow::Graph graph; + +public: + + void clear_graph() + { + graph = MaxFlow::Graph(); + } + + Vertex_descriptor add_vertex() + { + return graph.add_node(); + } + + void add_tweight (Vertex_descriptor& v, double w1, double w2) + { + graph.add_tweights(v, w1, w2); + } + + void init_vertices() + { + } + + double max_flow() + { + return graph.maxflow(); + } + + template + void update(VertexLabelMap vertex_label_map, + const std::vector& inserted_vertices, + InputVertexDescriptor vd, + std::size_t vertex_i, + std::size_t alpha) + { + if(get(vertex_label_map, vd) != alpha + && graph.what_segment(inserted_vertices[vertex_i]) == MaxFlow::Graph::SINK) + put(vertex_label_map, vd, alpha); + } + + void add_edge (Vertex_descriptor& v1, Vertex_descriptor& v2, double w1, double w2) + { + graph.add_edge(v1, v2, w1, w2); + } +}; + +}//namespace CGAL + +#endif //CGAL_BOOST_GRAPH_ALPHA_EXPANSION_GRAPHCUT_MAXFLOW_GPL_H