#c #boost #graph
#c #повышение #График
Вопрос:
В документации:http://www.boost.org/doc/libs/1_46_1/libs/graph/doc/random.html#randomize_property
Существует только прототип функции, я не могу найти рабочий пример. Я пробовал несколько вещей, но он просто не может скомпилироваться. Вот простой исходный код:
#include <ctime>
#include <iostream>
#include <boost/graph/random.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/random/linear_congruential.hpp>
#include <boost/graph/erdos_renyi_generator.hpp>
#include <boost/graph/graphviz.hpp>
using namespace std;
using namespace boost;
struct EdgeProperty {
int cost;
};
typedef adjacency_list<
setS, // disallow parallel edge
vecS,
undirectedS,
no_property,
EdgeProperty
> Graph;
typedef erdos_renyi_iterator<minstd_rand, Graph> ERGen;
int main(int argc, const char *argv[])
{
minstd_rand gen(time(0));
assert(argc >= 3);
int n = atoi(argv[1]);
double p = atof(argv[2]);
Graph g(ERGen(gen, n, p), ERGen(), n);
// randomize_property< [unknown class] >(g, gen);
return 0;
}
Обновление: код, предоставленный @phooji, работает. Я добавил конструктор по умолчанию для EdgeProperty
, и мой код тоже компилируется:
struct EdgeProperty {
EdgeProperty(int x = 0) : cost(x) { }
int cost;
};
Здесь указана исходная ошибка компиляции, суть которой я не могу понять. Надеюсь, кто-нибудь подскажет мне, как это работает.
Комментарии:
1. Кажется, повторяющийся вопрос у boost-пользователей: lists.boost.org/boost-users/2005/09/14033.php и lists.boost.org/boost-users/2009/08/50755.php — не похоже, что это было решено в любой момент.
2. @Cubbi Да, я тоже это нашел. Он отказался от этого, используя объединенные свойства.
3. Это не имеет отношения к вашему вопросу, но я пытался выяснить, как запретить параллельные ребра, и ваш пример кода дал мне ответ. Премного благодарен!
Ответ №1:
Это компилируется для меня:
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/random.hpp>
#include <boost/random/linear_congruential.hpp>
struct myedge {
myedge(int x) : testme(x) {
}
int testme;
};
typedef boost::adjacency_list<boost::setS, // disallow parallel edge
boost::vecS,
boost::undirectedS,
boost::no_property,
myedge
> mygraph;
int main(int argc, char**argv) {
mygraph g;
// auto pmap = boost::get(amp;myedge::testme, g);
boost::minstd_rand gen(0);
boost::randomize_property<boost::edge_bundle_t>(g, gen);
return EXIT_SUCCESS; // :)
}
Надеюсь, это поможет — у меня нет времени на самом деле протестировать это, поэтому прошу прощения, если это не то, что вам нужно.
Комментарии:
1. Спасибо. Ваш код компилируется. Это так странно, единственное различие между вашим кодом и моим заключается в том, что ваш объединенный класс свойств edge
myedge
имеет конструктор. Я добавил конструктор, и код компилируется. Не могу понять, почему. Надеюсь на объяснение 🙂2. @Ivan Z. Сяо: Обратите внимание, что это конструктор с одним аргументом, не помеченный как «явный», что означает следующую компиляцию:
myedge m = 5;
Или, что более важно,m = gen();
компилируется.3. @Cubbi Arrr… Спасибо, что указали на это. Если я правильно это интерпретирую, компилятор должен выполнить неявное приведение, вызвав конструктор по умолчанию для
myedge m = 5;
Ответ №2:
Я вижу по крайней мере одну проблему, которая заключается в недопустимом определении свойства edge. Для определения свойств графика следует использовать property<>
тип. Существует несколько предопределенных типов свойств, таких как индекс, вес, цвет и т.д. Для определения стоимости ребра используется edge_weight_t
тип свойства. Следовательно, определение типа графика должно быть следующим:
typedef adjacency_list<
setS, // disallow parallel edge
vecS,
undirectedS,
no_property,
property<edge_weight_t, int>
> Graph;
Для доступа к типу свойства property_map<>
используется: property_map<Graph, edge_weight_t>::type
.
Отредактируйте мою ошибку относительно объединенных свойств, по-прежнему сложно указать правильный тип для параметра шаблона randomize_property<Property>
, который должен быть вида свойства. Если вы определите график, как в моем примере, использование будет randomize_property<edge_weight_t>(g, gen);
Комментарии:
1. его свойство не является недействительным, оно включено, как в boost.org/doc/libs/1_46_1/libs/graph/doc/bundles.html
2. @Cubbi Вы правы, это была моя ошибка относительно пакетов. Однако пакеты в качестве отображения свойств усложняют использование
randomize_property<>
, посколькуProperty
параметр templete ожидает свойства типаedge_weight_t
илиvertex_index_t
, которые трудно вывести из пакета.3. Объединенное свойство более интуитивно понятно, поэтому я использую его. В своем документе они сказали, что в будущем они будут отказываться от внутреннего свойства.
Ответ №3:
Вы можете использовать следующий обходной путь, пока он не будет правильно отсортирован boost:
boost::detail::randomize_property<int EdgeProperty::*>
(g, gen, amp;EdgeProperty::cost, boost::edge_bundle_t);