28 Aralık 2017 Perşembe

graph write_graphviz_dp metodu

Giriş
write_graphviz metodu ile kardeştir. Birinci parametre stream, ikinci graph, üçüncü parametre boost::dynamic_properties nesnesidir.

boost::dynamic_properties nesnesini doldurmak için Vertex'in üye alanına, üye metoduna erişmek gerekebilir.

Örnek - lambda
Property değerini dönmek için şöyle yaparız.
void visualize(Graph const& g, BranchMap const& branch_map) {
  // display helpers
  std::vector<std::string> const colors { "gray", "red", "green", "blue" };

  auto name = [](Vertex v) -> char { return 'A'+v; };
  auto color = [&](Vertex v) -> std::string { 
    return colors[branch_map.at(v) % colors.size()];
  };

  // write graphviz:
  boost::dynamic_properties dp;
  dp.property("node_id", transform(name));
  dp.property("color", transform(color));

  write_graphviz_dp(std::cout, g, dp);
}
Çıktı olarak şunu alırız.
digraph G {
A [color=gray];
B [color=red];
C [color=green];
D [color=green];
A->B ;
A->C ;
C->D ;
}
Örnek - boost::make_function_property_map
Property değerini dönmek için bir metod oluşturur.
Örnek
Elimizde şöyle bir graph olsun
struct VertexP { std::string tag; };
struct EdgeP { std::string symbol; };
struct GraphP { std::string orientation; };

typedef adjacency_list<vecS, vecS, directedS, VertexP, EdgeP, GraphP> Graph;
Graph'ı doldurmak için şöyle yaparız.
Graph g(GraphP{"LR"});
// Then fill the graph
add_edge(
  add_vertex(VertexP{ "tag1" }, g),
  add_vertex(VertexP{ "tag2" }, g),
  EdgeP{ "symbol" }, g
);
Şöyle yaparız
std::ofstream dot_file("automaton.dot");
dynamic_properties dp;
dp.property("node_id", get(&VertexP::tag, g));
dp.property("label", get(&VertexP::tag, g));
dp.property("label", get(&EdgeP::symbol, g));
dp.property("rankdir", boost::make_constant_property<Graph*>(std::string("LR")));
dp.property("dummy", boost::make_function_property_map<Graph*>
  ([](Graph const* g) { return g->m_property->orientation; }));

write_graphviz_dp(dot_file, g, dp);
Çıktı olarak şunu alırız.
digraph G {
dummy=LR;
rankdir=LR;
tag2 [label=tag2];
tag1 [label=tag1];
tag1->tag2  [label=symbol];
}
Örnek - boost::make_transform_value_property_map
Şu satırı dahil ederiz
#include <boost/property_map/transform_value_property_map.hpp>
Property değerini dönmek için bir üye alana erişir.

Elimizde variant'lardan oluşan bir grap olsun
namespace Nodes {
  struct Building { std::string id; };
  struct Contract { std::string id; };
  ...
}

using Nodes::Building;
using Nodes::Contract;
using Vertex = boost::variant<Building, Contract>;


typedef adjacency_list<vecS, vecS, directedS, Vertex> Graph;
Şöyle yaparız.
std::ofstream dot_file("graph.dot");
dynamic_properties dp;

dp.property("node_id", boost::make_transform_value_property_map(&::id_of,
  boost::get(boost::vertex_bundle, g)));
dp.property("shape", boost::make_transform_value_property_map(&::shape_of,
  boost::get(boost::vertex_bundle, g)));
dp.property("label", boost::make_transform_value_property_map(
  [](Vertex const& v) { return boost::lexical_cast<std::string>(v); },
boost::get(boost::vertex_bundle, g)));

write_graphviz_dp(dot_file, g, dp);
Örnek
Elimzide kendi sınıfımız olsun
struct MyVertex {
  MyVertex(std::string label, int id) :
    _label(std::move(label)), _id(id) {}

  std::string label() const { return _label; }
  int         id()    const { return _id;    }

  bool operator<(const MyVertex &rhs) const {
    return std::tie(_id, _label) < std::tie(rhs._id, rhs._label);
  }
private:
  std::string _label;
  int _id;
};

using graph_t = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
  std::shared_ptr<MyVertex>>;


graph_t graph;

auto v1 = add_vertex(std::make_shared<MyVertex>("Lorem", 123), graph);
auto v2 = add_vertex(std::make_shared<MyVertex>("ipsum", 456), graph);
auto v3 = add_vertex(std::make_shared<MyVertex>("Lorem", 123), graph);
shared_ptr'nin sarmaladığı nesneye erişmek için şöyle yaparız.
boost::dynamic_properties dp;
auto bundle = get(boost::vertex_bundle, graph);
dp.property("node_id", make_transform_value_property_map(std::mem_fn(&MyVertex::id),
  bundle));
dp.property("label", make_transform_value_property_map(std::mem_fn(&MyVertex::label),
  bundle));

write_graphviz_dp(std::cout, graph, dp);
Eğer shared_ptr kullanmasaydık şöyle yapardık.
boost::dynamic_properties dp;
dp.property("node_id", boost::get(&MyVertex::id, graph));
dp.property("label", boost::get(&MyVertex::label, graph));

write_graphviz_dp(std::cout, graph, dp);
Çıktı olarak şunu alırız.
digraph G {
123 [label=Lorem];
456 [label=ipsum];
123 [label=Lorem];
123->456 ;
123->123 ;
}



Hiç yorum yok:

Yorum Gönder