使用自定义顶点属性增强图形的支配树

时间:2016-04-03 16:03:54

标签: c++ boost boost-graph

我尝试将boost::lengauer_tarjan_dominator_treecustom vertex properties的图表一起使用,但无法编译一个简单的示例:

#include <vector>
#include <iterator>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dominator_tree.hpp>
#include <boost/property_map/property_map.hpp> 

struct GraphNode
{
    explicit GraphNode(unsigned i) : index {i} {}
    unsigned index;
};

using Graph = boost::adjacency_list<boost::listS, boost::listS, 
                            boost::bidirectionalS, GraphNode, boost::no_property>;

using Vertex = boost::graph_traits<Graph>::vertex_descriptor;

int main()
{
    Graph g {};

    const auto u = boost::add_vertex(GraphNode {0}, g);
    const auto v = boost::add_vertex(GraphNode {1}, g);
    const auto x = boost::add_vertex(GraphNode {2}, g);
    const auto y = boost::add_vertex(GraphNode {3}, g);
    const auto z = boost::add_vertex(GraphNode {4}, g);

    boost::add_edge(u, v, g);
    boost::add_edge(u, x, g);
    boost::add_edge(v, y, g);
    boost::add_edge(x, y, g);
    boost::add_edge(y, z, g);

    const auto index_map = boost::get(&GraphNode::index, g);

    std::vector<Vertex> dom_tree_pred_vector(boost::num_vertices(g),
                                             boost::graph_traits<Graph>::null_vertex());

    auto dom_tree_pred_map = boost::make_iterator_property_map(std::begin(dom_tree_pred_vector),
                                index_map);

    boost::lengauer_tarjan_dominator_tree(g, u, dom_tree_pred_map);
}

我试图从文档中给出的example进行调整。

以下是错误消息的一部分:

/usr/local/include/boost/graph/detail/adjacency_list.hpp:2544:33: error: cannot form a reference to 'void'
        typedef const value_type& const_reference;
                                ^
/usr/local/include/boost/graph/dominator_tree.hpp:355:31: error: no matching function for call to 'get'
    const IndexMap indexMap = get(vertex_index, g);

我还尝试使用方法的第二种形式明确传递索引映射,但没有成功。我注意到这个方法界面似乎与其他图形方法略有不同,例如depth_first_search,其中vertex_index_map是一个命名参数。

是否可以将此方法用于自定义顶点属性?

1 个答案:

答案 0 :(得分:2)

问题 - 一如既往 - 是使用<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/value_text" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"/> <Button android:id="@+id/delete_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Delete"/> </LinearLayout> 以外的东西作为顶点容器。您丢失了内置import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class MainActivity extends AppCompatActivity { private List<String> items = new ArrayList<>( Arrays.asList("first", "second", "third")); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); RecyclerView myRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); myRecyclerView.setAdapter(new MyAdapter()); } private class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new MyViewHolder(LayoutInflater.from(MainActivity.this) .inflate(R.layout.my_item, parent, false)); } @Override public void onBindViewHolder(MyViewHolder holder, int position) { holder.bind(position); } @Override public int getItemCount() { return items.size(); } public class MyViewHolder extends RecyclerView.ViewHolder { private TextView valueTextView; private Button deleteButton; public MyViewHolder(View itemView) { super(itemView); valueTextView = (TextView) itemView.findViewById(R.id.value_text); deleteButton = (Button) itemView.findViewById(R.id.delete_button); deleteButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position = (int) v.getTag(); items.remove(position); notifyItemRemoved(position); notifyItemRangeChanged(position, items.size()); } }); } public void bind(int position) { valueTextView.setText(items.get(position)); deleteButton.setTag(position); } } } } 属性,因此必须将其提供给API。

遗憾的是,这个算法并不能很好地支持自定义顶点索引图。您尝试使用vecS正确地尝试了,但在内部算法仍然会查找vertex_index标记属性。

我能看到这项工作的唯一两种方式是,

  1. 手动执行DFS阶段(因为即使index_map的全参数重载也无法将正确的索引映射转发到DFS中)。然后,您可以调用vertex_index_t实现并获得结果。

  2. 或者您可以告诉图书馆您的图表的索引图。

  3. (最后,你可以接受命运并使用lengauer_tarjan*作为顶点容器选择器。我怀疑这显然不是你想要的。)

    样本

    使用第二种方法,这可能是最优雅的。以下是要添加的特化/重载:

    lengauer_tarjan_dominator_tree_without_dfs

    <强> Live On Coliru

    vecS

    打印

    namespace boost {
        template <>
            struct property_map<Graph, vertex_index_t> {
                typedef typename property_map<Graph, size_t GraphNode::*>::type type;
                typedef typename property_map<Graph, size_t GraphNode::*>::const_type const_type;
            };
    
        static auto get(vertex_index_t, Graph& g)       { return get(&GraphNode::index, g); }
        static auto get(vertex_index_t, Graph const& g) { return get(&GraphNode::index, g); }
    }