c++ Boost Graph Library图形生成函数问题

pgccezyw  于 2023-07-01  发布在  其他
关注(0)|答案(1)|浏览(94)

我一直在为一个个人项目学习一些图论。我还尝试使用Boost Graph Library来执行这些任务。下面的函数试图使用提供的random_spanning_tree函数生成树图,然后随机连接其中的一部分,但我无法让提供的函数以工作方式返回前驱Map。
目前我声明了precedentaryMap并将其传递给random_spanning_tree函数。输出不是我所期望的。使用gdb,我可以确定数据结构只是make_connected函数构建的简单连接线图的数据结构,以及我假设所有数据都保存在第0个单元格中的大数。为了清楚起见,我已经包括了调试输出的图像。很明显,我要么没有初始化,要么没有正确地传入前置Map,因为我的所有数据都保存到了第一个单元格中。有没有人知道我错在哪里?任何帮助都是非常感谢的,因为我一直在努力弄清楚这一点,为更好的一天。
运行random_spanning_tree函数后的前驱Map数据的图像:gdb watched variable

来源:

struct VertexData
{
    int num;
    int pred;
    int dist;
};

struct EdgeData
{
    double dist;
};

typedef adjacency_matrix<undirectedS, VertexData, EdgeData > Graph;
typedef graph_traits<Graph>::vertex_descriptor Vertex;

Graph generateConnectedGraph2(int numVertices, double connectionProbability) {
    Graph graph(numVertices);
    std::random_device rand;
    random::minstd_rand gen(rand()); //Seeded Random number generator

    make_connected(graph);

    //build a minimally connected graph for the random spanning tree

    std::vector<double> xPos(num_vertices(graph));
    std::vector<double> yPos(num_vertices(graph));

    bool isPlanar = false;

    std::vector<Vertex> predecessor(numVertices);  // Predecessor map
    predecessor[0] = 0;  // Set the root vertex to 0
    // Generate random edges to create a connected graph
    random_spanning_tree(graph, gen, predecessor_map(make_iterator_property_map(predecessor.begin(), get(vertex_index, graph) )));
    
    printAdjMatrix(graph, numVertices);
    
    applyPredecessorMap(graph, predecessor);
    printAdjMatrix(graph, numVertices);
    
    // Iterate over each pair of vertices and potentially add an edge
    for (Vertex u = 0; u < numVertices; ++u) {
        for (Vertex v = u + 1; v < numVertices; ++v) {
            if (u != v && u != numVertices && !edge(u, v, graph).second && random::bernoulli_distribution<>(connectionProbability)(gen)) {
                add_edge(u, v, graph);
            }
        }
    }
    
    return graph;
}

void applyPredecessorMap(Graph& graph, const std::vector<Vertex>& predecessor) {
    int numVertices = num_vertices(graph);

    for (Vertex v = 1; v < numVertices; ++v) {
        Vertex u = predecessor[v];
        add_edge(u, v, graph);
    }
}
fxnxkyjh

fxnxkyjh1#

您的代码完全按预期工作。“大数字”不是随机的。它是指示第一个顶点没有前趋顶点的特殊值:

assert(predecessor.at(vertex(0, graph)) == graph.null_vertex());

同时,您找到了一棵生成树,但根据定义,它只能由图中已有的边组成,因此applyPredecessor不应该有影响,除非您选择另一个允许重复边的图模型。
下面是扩展后的代码,其中有一些输出,显示了它是如何工作的:

Live On Coliru

#include <boost/graph/adjacency_matrix.hpp>
#include <boost/graph/make_connected.hpp>
#include <boost/graph/random_spanning_tree.hpp>
#include <boost/graph/graph_utility.hpp>
#include <random>
#include <fmt/ranges.h>
struct VertexData {
    int num;
    int pred;
    int dist;
};

struct EdgeData {
    double dist;
};

using Graph  = boost::adjacency_matrix<boost::undirectedS, VertexData, EdgeData>;
using Vertex = Graph::vertex_descriptor;

void applyPredecessorMap(Graph& graph, std::vector<Vertex> const& predecessor) {
    size_t numVertices = num_vertices(graph);

    for (Vertex v = 1; v < numVertices; ++v) {
        Vertex u = predecessor[v];
        add_edge(u, v, graph);
    }
}

Graph generateConnectedGraph2(size_t numVertices, double connectionProbability) {
    Graph graph(numVertices);
    std::random_device rand;
    std::minstd_rand gen(rand()); //Seeded Random number generator

    make_connected(graph);
    auto const original = graph;

    //build a minimally connected graph for the random spanning tree
    std::vector<double> xPos(num_vertices(graph));
    std::vector<double> yPos(num_vertices(graph));

    // bool isPlanar = false;

    std::vector<Vertex> predecessor(numVertices); // Predecessor map
    fmt::print("predecessor constructed: {}\n", predecessor);
    predecessor[0] = 0;                           // Set the root vertex to 0
    fmt::print("predecessor initialized: {}\n", predecessor);

    // Generate random edges to create a connected graph
    random_spanning_tree(
        std::as_const(graph), gen,
        predecessor_map(make_iterator_property_map(predecessor.begin(), get(boost::vertex_index, graph))));

    fmt::print("predecessor spanning: {}\n", predecessor);
    // v 0 doesn't have a predecessor
    assert(predecessor.at(vertex(0, graph)) == graph.null_vertex());

    print_graph(graph, std::cout << "Graph:\n");
    
    applyPredecessorMap(graph, predecessor);
    print_graph(graph, std::cout << "Graph with predecessors applied:\n");
    
    // Iterate over each pair of vertices and potentially add an edge
    std::bernoulli_distribution dist(connectionProbability);

    for (Vertex u = 0; u < numVertices; ++u) {
        for (Vertex v = u + 1; v < numVertices; ++v) {
            if (u != v && u != numVertices && !edge(u, v, graph).second && dist(gen)) {
                add_edge(u, v, graph);
            }
        }
    }

    print_graph(graph, std::cout << "Graph with random edges added:\n");

    return graph;
}

int main() {
    generateConnectedGraph2(10, 0.2);
}

印刷,例如

predecessor constructed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
predecessor initialized: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
predecessor spanning: [18446744073709551615, 0, 1, 2, 3, 4, 5, 6, 7, 8]
Graph:
0 <--> 1 
1 <--> 0 2 
2 <--> 1 3 
3 <--> 2 4 
4 <--> 3 5 
5 <--> 4 6 
6 <--> 5 7 
7 <--> 6 8 
8 <--> 7 9 
9 <--> 8 
Graph with predecessors applied:
0 <--> 1 
1 <--> 0 2 
2 <--> 1 3 
3 <--> 2 4 
4 <--> 3 5 
5 <--> 4 6 
6 <--> 5 7 
7 <--> 6 8 
8 <--> 7 9 
9 <--> 8 
Graph with random edges added:
0 <--> 1 6 9 
1 <--> 0 2 
2 <--> 1 3 6 
3 <--> 2 4 6 7 
4 <--> 3 5 8 
5 <--> 4 6 9 
6 <--> 0 2 3 5 7 
7 <--> 3 6 8 
8 <--> 4 7 9 
9 <--> 0 5 8

或重复运行:

相关问题