简体   繁体   中英

Directed Acyclic Graph : Updating the vertex property of a parent node by comparing the property of the child nodes.

I have the connections between nodes in a DAG like this.

1 --> 7
2 -->
3 --> 4 5
4 --> 6
5 --> 
6 --> 
7 -->

I have to perform some tasks on this graph. 1) Find all the vertices without successors. 2) Assign a value to the vertices without successors. (I can do this with Vertex properties). 3) Back trace the graph and update all the parent node (Even the intermediate parent node) at each level with the minimum value of the children.

For example,

As per the above DAG, Vertices {2,5,6,7} are without any successors or out edges. Assume I will assign values {3,2,4,6} to vertices {2,5,6,7} respectively.

Since Vertex 4 is the parent node to 5 and 6, I have to add the value min{2,4} = 2 to Vertex 4. Similarly, 1 is the parent node to 7. So I have to add the value 6 to node 1.

May I know which functions I can use for each step so that the "Search" time is minimal.

I also wanted to know, is something above mentioned possible in a DAG using boost.

For fun:

I have the connections between nodes in a DAG like this.

using G = boost::adjacency_list<>;
G g(8);
add_edge(1, 7, g);
add_edge(3, 4, g);
add_edge(3, 5, g);
add_edge(4, 6, g);

Assume I will assign values {3,2,4,6} to vertices {2,5,6,7} respectively.

auto p = boost::make_vector_property_map<int>(id);
p[2] = 3; p[5] = 2; p[6] = 4; p[7] = 6;

3) Back trace the graph [...]

std::vector<V> order;
topological_sort(g, back_inserter(order));

[...] and update all the parent node (Even the intermediate parent node) at each level with the minimum value of the children.

auto getter = [&p](V vd) { return p[vd]; };
for (V vd : order) {
    auto child = make_iterator_range(adjacent_vertices(vd, g));
    if (child.size())
        p[vd] += *min_element(child | transformed(std::cref(getter)));
}

You didn't specify it but you will probably want to see the result:

print_graph(g, boost::make_transform_value_property_map(
                [&](V vd) { return "vertex #" + std::to_string(vd) + " (" + std::to_string(p[vd]) + ")"; }, id
            ));

DEMO

Live On Coliru

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_utility.hpp>
#include <boost/graph/topological_sort.hpp>
#include <boost/property_map/transform_value_property_map.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm/min_element.hpp>

using boost::adaptors::transformed;

int main() {
    using G = boost::adjacency_list<>;
    using V = G::vertex_descriptor;
    /*
     *1 --> 7
     *2 -->
     *3 --> 4 5
     *4 --> 6
     *5 --> 
     *6 --> 
     *7 -->
     */
    G g(8);
    add_edge(1, 7, g);
    add_edge(3, 4, g);
    add_edge(3, 5, g);
    add_edge(4, 6, g);

    // {3,2,4,6} to vertices {2,5,6,7}
    auto id = get(boost::vertex_index, g);
    auto p = boost::make_vector_property_map<int>(id);
    p[2] = 3; p[5] = 2; p[6] = 4; p[7] = 6;

    std::vector<V> order;
    boost::topological_sort(g, back_inserter(order));

    auto getter = [&p](V vd) { return p[vd]; };
    for (V vd : order) {
        auto child = make_iterator_range(adjacent_vertices(vd, g));
        if (child.size())
            p[vd] += *min_element(child | transformed(std::cref(getter)));
    }

    print_graph(g, boost::make_transform_value_property_map(
                    [&](V vd) { return "vertex #" + std::to_string(vd) + " (" + std::to_string(p[vd]) + ")"; },
                    id));
}

Output:

vertex #0 (0) --> 
vertex #1 (6) --> vertex #7 (6) 
vertex #2 (3) --> 
vertex #3 (2) --> vertex #4 (4) vertex #5 (2) 
vertex #4 (4) --> vertex #6 (4) 
vertex #5 (2) --> 
vertex #6 (4) --> 
vertex #7 (6) --> 

CAUTION

Consider this an answer to the question "I also wanted to know, is something above mentioned possible in a DAG using boost." . Don't turn this in as your solution.

I deliberately wrote this solution with some flair and brevity. It will help you get something started, but please make sure you understand every step of the way. In fact, rewrite it using proper bundled properties , proper vertex id mapping, proper output etc.

Caveat emptor. Your education is your own responsibility. Learning is the greatest skill of them all.

BONUS: Visualize

Using graphviz and filtering the zero vertex:

struct NotZero { bool operator()(V vd) const { return 0 != vd; } };
using F = boost::filtered_graph<G, boost::keep_all, NotZero>;

boost::dynamic_properties dp;
dp.property("node_id", id);
dp.property("shape", boost::make_constant_property<V>(std::string("Mrecord")));
dp.property("label", label);

write_graphviz_dp(std::cout, F(g, {}, {}), dp);

Live On Coliru

在此输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM