【问题标题】:(BOOST) Filter out the edges of a graph iteratively(BOOST) 迭代过滤出图的边
【发布时间】:2021-01-07 18:38:16
【问题描述】:

我有一个连通图 A(第 0 级),我想用图 B、C、D... 填充下一个级别,方法是在 A 中一次删除一条边。这是我的代码开始的方式:

struct VertexData
{
    long ID;
};

typedef boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS,VertexData, property< edge_index_t, int > >> SimpleGraph; 
typedef boost::graph_traits<SimpleGraph>::vertex_descriptor vertex_t;
typedef boost::graph_traits<SimpleGraph>::edge_descriptor edge_t;

int main(){
    
    SimpleGraph A;   
}

我曾尝试在 A 的边上循环并在复制图 A 后一次删除一条边:

        
SimpleGraph tempStructure;
vector<SimpleGraph> newStructures;
vector<long> parentList;

// loop over the edges
auto es = boost::edges(A);
pred = A.ID;

for (auto eit = es.first; eit != es.second; ++eit){
            
      // 1. copy structure
      cout << "Copy structure." <<endl;
      boost::copy_graph(A, tempStructure);
            
      // 2. remove a particular edge 
      cout << "Remove edge." << endl;
      boost::remove_edge(*eit, tempStructure);
            
      // 3. save structure
      cout << "Saving structure." << endl;
      newStructures.push_back(tempStructure);
            
      // 4. save parent of old structure]
      cout << "Saving parent." << endl;
      parentList.push_back(pred);

}

但正如我所阅读的here, 我理解这是一个非常幼稚的尝试。我找到了以下解决方案 (Boost filtered graph with blacklisted edges) 并看到过滤图似乎是要走的路。但是,我在实现它时遇到了麻烦......

是否可以一次过滤掉父图中的一条边,以便子图是 A 的过滤版本,在 A 中缺少一条边?

【问题讨论】:

    标签: c++ boost graph boost-graph filtered


    【解决方案1】:

    感谢对这个问题的讨论 (here),我能够想出解决问题的方法。我采用了与线程中相同的方法,并决定将每个边缘单独“列入黑名单”:

    typedef std::pair <int, int> Edge;
    typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, boost::no_property, boost::no_property> SimpleGraph;
    
    struct BlackListEdgeConstraint{
        
    private:
        Edge blackList;
        SimpleGraph* g;
        
    public:
        BlackListEdgeConstraint() : blackList(), g(NULL) {}; // constructor with initialization
        BlackListEdgeConstraint(Edge& list, SimpleGraph* gM) : blackList(list), g(gM){}
        
        // the actual predicate function
        bool operator()(const boost::graph_traits<SimpleGraph>::edge_descriptor& e) const {
            
            Edge edge(source(e, *g), target(e, *g));
            
            if (edge == blackList){
                return false;
            }
            else{
                return true;
            }
        }
    };
    

    然后,我使用这个谓词如下:

    auto es = boost::edges(parentStructure);
            
    for (auto eit = es.first; eit != es.second; ++eit){
                            
        // we filter the current edge -- blacklist it
        Edge edge(source(*eit, parentStructure), target(*eit, parentStructure));
        BlackListEdgeConstraint filter(edge, &parentStructure);
                
        // get filtered graph where this connection is missing
        boost::filtered_graph<SimpleGraph, BlackListEdgeConstraint> tempStructureFILT(parentStructure, filter);
    }
    

    我确信这可以以一种更优雅、更省时的方式完成,但目前,这个解决方案符合我的目的。我很高兴听到有关如何改进它的任何反馈:)

    【讨论】:

    • 使用(源,目标)而不是使用edge_descriptor(* eit)来识别边缘的原因是什么?边缘描述符被设计成低成本可复制和直接相等可比。
    • 你是完全正确的——没有实际的原因。我刚刚开始使用 boost,对我来说这更容易理解。我将仔细修改代码以删除这种冗余。非常感谢您的意见!
    猜你喜欢
    • 2019-09-11
    • 2011-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-12
    • 2011-12-08
    • 2016-03-23
    • 1970-01-01
    相关资源
    最近更新 更多