20 #include "ui_GenerateGraphWidget.h"
23 #include "DataStructure.h"
24 #include "DocumentManager.h"
25 #include "PointerType.h"
26 #include "Modifiers/Topology.h"
36 #include <QtCore/QList>
37 #include <QtCore/QMap>
38 #include <QtCore/QPair>
40 #include <boost/graph/adjacency_list.hpp>
41 #include <boost/graph/iteration_macros.hpp>
42 #include <boost/graph/random.hpp>
43 #include <boost/graph/random_layout.hpp>
44 #include <boost/graph/topology.hpp>
45 #include <boost/graph/fruchterman_reingold.hpp>
46 #include <boost/random/mersenne_twister.hpp>
47 #include <boost/graph/erdos_renyi_generator.hpp>
48 #include <boost/math/constants/constants.hpp>
51 typedef boost::adjacency_list < boost::listS, boost::vecS, boost::undirectedS,
52 boost::property<boost::vertex_name_t, std::string> >
61 typedef boost::iterator_property_map < PositionVec::iterator,
62 boost::property_map<Graph, boost::vertex_index_t>::type >
70 defaultIdentifiers.
insert(MeshGraph,
"MeshGraph");
71 defaultIdentifiers.
insert(StarGraph,
"StarGraph");
72 defaultIdentifiers.
insert(CircleGraph,
"CircleGraph");
73 defaultIdentifiers.
insert(ErdosRenyiRandomGraph,
"RandomGraph");
74 defaultIdentifiers.
insert(RandomTree,
"RandomTree");
75 defaultIdentifiers.
insert(MeshGraph,
"MeshGraph");
77 graphGenerator_ = MeshGraph;
80 ui =
new Ui::GenerateGraphWidget;
82 setMainWidget(widget);
85 setCaption(i18nc(
"@title:window",
"Generate Graph"));
86 setButtons(KDialog::Cancel | KDialog::Ok);
87 ui->buttonShowAdvanced->setIcon(KIcon(
"rocsadvancedsetup"));
88 KDialog::centerOnScreen(widget, -3);
90 connect(
this, SIGNAL(okClicked()),
this, SLOT(
generateGraph()));
91 connect(ui->comboGraphGenerator, SIGNAL(currentIndexChanged(
int)),
this, SLOT(
setGraphGenerator(
int)));
92 connect(ui->dataTypeSelector, SIGNAL(currentIndexChanged(
int)),
this, SLOT(
setDataType(
int)));
93 connect(ui->pointerTypeSelector, SIGNAL(currentIndexChanged(
int)),
this, SLOT(
setPointerType(
int)));
97 uint badRandomSeed = qHash(currentTime) % 99999;
98 badRandomSeed = (badRandomSeed == 0) ? 1 : badRandomSeed;
99 ui->randomGeneratorSeed->setValue(badRandomSeed);
100 ui->GNPGeneratorSeed->setValue(badRandomSeed);
101 ui->randomTreeGeneratorSeed->setValue(badRandomSeed);
105 ui->label_randomGeneratorSeed->setVisible(
false);
106 ui->randomGeneratorSeed->setVisible(
false);
107 ui->label_GNPGeneratorSeed->setVisible(
false);
108 ui->GNPGeneratorSeed->setVisible(
false);
109 ui->label_randomTreeGeneratorSeed->setVisible(
false);
110 ui->randomTreeGeneratorSeed->setVisible(
false);
112 foreach (
int pointerTypeID, document->pointerTypeList()) {
113 PointerTypePtr pointerType = document->pointerType(pointerTypeID);
118 pointerType->identifier());
119 ui->pointerTypeSelector->addItem(item,
QVariant(pointerTypeID));
121 ui->pointerTypeSelector->setCurrentIndex(0);
123 foreach (
int dataTypeID, document->dataTypeList()) {
124 DataTypePtr dataType = document->dataType(dataTypeID);
129 dataType->identifier());
130 ui->dataTypeSelector->addItem(item,
QVariant(dataTypeID));
132 ui->dataTypeSelector->setCurrentIndex(0);
138 graphGenerator_ = GraphGenerator(index);
139 if (defaultIdentifiers.
contains(graphGenerator_)) {
140 ui->identifier->setText(defaultIdentifiers[graphGenerator_]);
142 ui->identifier->setText(
"Graph");
148 identifier_ = identifier;
153 if (!DocumentManager::self().activeDocument()->dataTypeList().contains(type)) {
154 kWarning() <<
"Data type " << type <<
" does not exist: aborting";
162 if (!DocumentManager::self().activeDocument()->pointerTypeList().contains(type)) {
163 kWarning() <<
"Pointer type " << type <<
" does not exist: aborting";
178 switch (graphGenerator_) {
180 generateMesh(ui->meshRows->value(), ui->meshColumns->value());
183 generateCircle(ui->circleNodes->value());
186 generateStar(ui->starSatelliteNodes->value());
188 case RandomEdgeGraph:
189 setSeed(ui->randomGeneratorSeed->value());
191 ui->randomNodes->value(),
192 ui->randomEdges->value(),
193 ui->randomAllowSelfedges->isTristate()
196 case ErdosRenyiRandomGraph:
197 setSeed(ui->randomGeneratorSeed->value());
198 generateErdosRenyiRandomGraph(
199 ui->GNPNodes->value(),
200 ui->GNPEdgeProbability->value(),
201 ui->GNPAllowSelfedges->isTristate()
205 setSeed(ui->randomTreeGeneratorSeed->value());
206 generateRandomTreeGraph(
207 ui->randomTreeNodes->value()
222 void GenerateGraphWidget::generateMesh(
int rows,
int columns)
224 QPointF center = DocumentManager::self().activeDocument()->sceneRect().center();
234 DataStructurePtr graph = DocumentManager::self().activeDocument()->activeDataStructure();
235 if (graph->dataListAll().size() > 0) {
236 graph = DocumentManager::self().activeDocument()->addDataStructure(identifier_);
243 for (
int i = 0; i < columns; i++) {
244 for (
int j = 0; j < rows; j++) {
245 meshNodes[qMakePair(i, j)] = graph->createData(
QString(
"%1-%2").arg(i).arg(j),
246 QPointF(i * 50, j * 50) -
QPoint((
int)25 * columns, (
int)25 * rows) + center,
253 for (
int i = 0; i < columns; i++) {
254 for (
int j = 0; j < rows; j++) {
255 graph->createPointer(meshNodes[qMakePair(i, j)], meshNodes[qMakePair(i, j + 1)], pointerType_);
256 graph->createPointer(meshNodes[qMakePair(i, j)], meshNodes[qMakePair(i + 1, j)], pointerType_);
261 void GenerateGraphWidget::generateStar(
int satelliteNodes)
263 QPointF center = DocumentManager::self().activeDocument()->sceneRect().center();
267 int radius = 50 * satelliteNodes / (2 * boost::math::constants::pi<double>());
270 DataStructurePtr graph = DocumentManager::self().activeDocument()->activeDataStructure();
271 if (graph->dataListAll().size() > 0) {
272 graph = DocumentManager::self().activeDocument()->addDataStructure(identifier_);
276 for (
int i = 1; i <= satelliteNodes; i++) {
277 QPointF position =
QPointF(sin(i * 2 * boost::math::constants::pi<double>() / satelliteNodes)*radius,
278 cos(i * 2 * boost::math::constants::pi<double>() / satelliteNodes)*radius)
280 starNodes << qMakePair(
288 nodeList.
prepend(graph->createData(
QString(
"center"), center, dataType_));
291 for (
int i = 1; i <= satelliteNodes; i++) {
292 graph->createPointer(nodeList.
at(0), nodeList.
at(i), pointerType_);
296 void GenerateGraphWidget::generateCircle(
int nodes)
298 QPointF center = DocumentManager::self().activeDocument()->sceneRect().center();
302 int radius = 50 * nodes / (2 * boost::math::constants::pi<double>());
305 DataStructurePtr graph = DocumentManager::self().activeDocument()->activeDataStructure();
306 if (graph->dataListAll().size() > 0) {
307 graph = DocumentManager::self().activeDocument()->addDataStructure(identifier_);
313 for (
int i = 1; i <= nodes; i++) {
314 QPointF position =
QPointF( sin(i * 2 * boost::math::constants::pi<double>() / nodes)*radius,
315 cos(i * 2 * boost::math::constants::pi<double>() / nodes)*radius)
317 circleNodes << qMakePair(
325 for (
int i = 0; i < nodes - 1; i++) {
326 graph->createPointer(nodeList.
at(i), nodeList.
at(i + 1), pointerType_);
328 graph->createPointer(nodeList.
at(nodes - 1), nodeList.
at(0), pointerType_);
331 void GenerateGraphWidget::generateRandomGraph(
int nodes,
int edges,
bool selfEdges)
333 QPointF center = DocumentManager::self().activeDocument()->sceneRect().center();
337 gen.seed(static_cast<unsigned int>(seed_));
340 boost::generate_random_graph<Graph, boost::mt19937>(
349 boost::rectangle_topology< boost::mt19937 > topology(gen, center.
x() - 20 * nodes, center.
y() - 20 * nodes, center.
x() + 20 * nodes, center.
y() + 20 * nodes);
350 PositionVec position_vec(boost::num_vertices(randomGraph));
351 PositionMap positionMap(position_vec.begin(),
get(boost::vertex_index, randomGraph));
353 boost::random_graph_layout(randomGraph, positionMap, topology);
356 boost::fruchterman_reingold_force_directed_layout< boost::rectangle_topology< boost::mt19937 >,
Graph,
PositionMap >
360 boost::cooling(boost::linear_cooling<double>(100))
365 DataStructurePtr graph = DocumentManager::self().activeDocument()->activeDataStructure();
366 if (graph->dataListAll().size() > 0) {
367 graph = DocumentManager::self().activeDocument()->addDataStructure(identifier_);
373 boost::graph_traits<Graph>::vertex_iterator vi, vi_end;
374 for (boost::tie(vi, vi_end) = boost::vertices(randomGraph); vi != vi_end; ++vi) {
375 mapNodes[*vi] = graph->createData(
377 QPointF(positionMap[*vi][0], positionMap[*vi][1]),
382 boost::graph_traits<Graph>::edge_iterator ei, ei_end;
383 for (boost::tie(ei, ei_end) = boost::edges(randomGraph); ei != ei_end; ++ei) {
384 graph->createPointer(mapNodes[boost::source(*ei, randomGraph)],
385 mapNodes[boost::target(*ei, randomGraph)],
391 void GenerateGraphWidget::generateErdosRenyiRandomGraph(
int nodes,
double edgeProbability,
bool selfEdges)
393 QPointF center = DocumentManager::self().activeDocument()->sceneRect().center();
396 gen.seed(static_cast<unsigned int>(seed_));
399 typedef boost::erdos_renyi_iterator<boost::mt19937, Graph> ergen;
400 Graph randomGraph(ergen(gen, nodes, edgeProbability, selfEdges), ergen(), nodes);
403 boost::rectangle_topology< boost::mt19937 > topology(gen, center.
x() - 20 * nodes, center.
y() - 20 * nodes, center.
x() + 20 * nodes, center.
y() + 20 * nodes);
404 PositionVec position_vec(boost::num_vertices(randomGraph));
405 PositionMap positionMap(position_vec.begin(),
get(boost::vertex_index, randomGraph));
406 boost::random_graph_layout(randomGraph, positionMap, topology);
410 DataStructurePtr graph = DocumentManager::self().activeDocument()->activeDataStructure();
411 if (graph->dataListAll().size() > 0) {
412 graph = DocumentManager::self().activeDocument()->addDataStructure(identifier_);
416 boost::fruchterman_reingold_force_directed_layout< boost::rectangle_topology< boost::mt19937 >,
Graph,
PositionMap >
420 boost::cooling(boost::linear_cooling<double>(100))
426 boost::graph_traits<Graph>::vertex_iterator vi, vi_end;
427 for (boost::tie(vi, vi_end) = boost::vertices(randomGraph); vi != vi_end; ++vi) {
428 mapNodes[*vi] = graph->createData(
430 QPointF(positionMap[*vi][0], positionMap[*vi][1]),
435 boost::graph_traits<Graph>::edge_iterator ei, ei_end;
436 for (boost::tie(ei, ei_end) = boost::edges(randomGraph); ei != ei_end; ++ei) {
437 graph->createPointer(mapNodes[boost::source(*ei, randomGraph)],
438 mapNodes[boost::target(*ei, randomGraph)],
444 void GenerateGraphWidget::generateRandomTreeGraph(
int nodes)
446 Document *activeDocument = DocumentManager::self().activeDocument();
447 QPointF center = DocumentManager::self().activeDocument()->sceneRect().center();
449 DataStructurePtr graph = activeDocument->activeDataStructure();
450 if (graph->dataListAll().size() > 0) {
451 graph = DocumentManager::self().activeDocument()->addDataStructure(identifier_);
455 gen.seed(static_cast<unsigned int>(seed_));
459 PointerTypePtr ptrType = activeDocument->pointerType(0);
460 for (
int i = 1; i < nodes; i++) {
461 DataPtr thisNode = graph->createData(
QString::number(i + 1), center, dataType_);
463 boost::random::uniform_int_distribution<> randomEarlierNodeGen(0, i-1);
464 int randomEarlierNode = randomEarlierNodeGen(gen);
465 graph->createPointer(thisNode, addedNodes.at(randomEarlierNode), pointerType_);
466 if (ptrType->direction() == PointerType::Unidirectional) {
467 graph->createPointer(addedNodes.at(randomEarlierNode), thisNode, pointerType_);
469 addedNodes.append(thisNode);
472 Topology topology = Topology();
473 topology.directedGraphDefaultTopology(graph);
iterator insert(const Key &key, const T &value)
const T & at(int i) const
qint64 currentMSecsSinceEpoch()
QString number(int n, int base)
void prepend(const T &value)
bool contains(const Key &key) const