Граф с двумя типами узлов
Я пишу программу с использованием C++ и Boost Graph Library (BGL). У меня есть два класса под названием Здания и Контракты. Мне нужно сделать график, который представляет отношения связи между ними всеми. Таким образом, граф должен иметь два типа вершин (B и C), быть ориентированными и включать ребра B->B, C->C и B->C.
- Является ли это возможным?
- Если да, как это реализовать?
РЕДАКТИРОВАТЬ
На самом деле я старался избегать соединений между узлами разных типов, поэтому у меня было два отдельных графика. Но это сделало мою модель намного более сложной из-за реализации фактически существующей связи между B и C. Edge B1->B2 показывает, что для сборки B2 уже необходимо построить B1. C1->C2 на самом деле то же самое, но с точки зрения контрактов. B->C показывает, что контракт C может быть завершен в здании B.
1 ответ
Я уже оставил комментарий с просьбой о цели:
Я был бы рад показать (несколько) подходов, если бы вы смогли описать проблему, которую пытаетесь решить. Потому что на данный момент не совсем понятно, для чего вам нужна интегрированная структура данных (я не могу придумать алгоритмы, которые выиграли бы от наличия ребер BB, CC, BC). На мой взгляд, 2 отдельных графика, неявный граф, который соединяет их, или один граф с необязательно отфильтрованными представлениями. Фильтрация может быть выполнена с помощью какого-то (динамического) переключателя типа ИЛИ это может быть сделано с использованием какого-либо внешнего / навязчивого индекса. - Сехе 31 минут назад
Независимо от этого, вы можете использовать boost::variant
чтобы сделать именно то, что задает вопрос (то есть, вероятно, вопрос о проблеме X/Y):
демонстрация
#include <boost/graph/adj_list_serialize.hpp>
#include <boost/property_map/function_property_map.hpp>
#include <boost/property_map/transform_value_property_map.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/graph_utility.hpp>
#include <boost/variant.hpp>
#include <fstream>
using namespace boost;
namespace Nodes {
struct Building { std::string id; };
struct Contract { std::string id; };
static inline std::ostream& operator<<(std::ostream& os, Building const& b) { return os << "Building " << b.id; }
static inline std::ostream& operator<<(std::ostream& os, Contract const& b) { return os << "Contract " << b.id; }
std::string id_of(Building const& b) { return b.id; }
std::string id_of(Contract const& c) { return c.id; }
std::string shape_of(Building const& b) { return "circle"; }
std::string shape_of(Contract const& c) { return "diamond"; }
}
using Nodes::Building;
using Nodes::Contract;
using Vertex = boost::variant<Building, Contract>;
std::string id_of(Vertex const& v) {
return boost::apply_visitor([](auto const& node) { return id_of(node); }, v);
}
std::string shape_of(Vertex const& v) {
return boost::apply_visitor([](auto const& node) { return shape_of(node); }, v);
}
typedef adjacency_list<vecS, vecS, directedS, Vertex> Graph;
int main() {
Graph g;
auto office1 = add_vertex(Building{ "office1" }, g);
auto office2 = add_vertex(Building{ "office2" }, g);
auto warehouse1 = add_vertex(Building{ "warehouse1" }, g);
auto contract1 = add_vertex(Contract{ "contract1" }, g);
auto contract2 = add_vertex(Contract{ "contract2" }, g);
add_edge(office1, office2, g);
add_edge(warehouse1, contract1, g);
add_edge(contract2, contract1, g);
{
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);
}
print_graph(g);
}
Печать
0 --> 1
1 -->
2 --> 3
3 -->
4 --> 3
А также генерация graph.dot
для следующего графика:
Исходный код.dot выглядит так:
digraph G {
office1 [label="Building office1", shape=circle];
office2 [label="Building office2", shape=circle];
warehouse1 [label="Building warehouse1", shape=circle];
contract1 [label="Contract contract1", shape=diamond];
contract2 [label="Contract contract2", shape=diamond];
office1->office2 ;
warehouse1->contract1 ;
contract2->contract1 ;
}
И я сделал это онлайн, используя https://dreampuf.github.io/GraphvizOnline/