ggen.cpp
3.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <cctype>
#include <random>
#include <chrono>
#include <vector>
#include <fstream>
#include <iostream>
static unsigned int vertexNumber;
static unsigned int edgeNumber;
static unsigned int weightNumber;
std::vector<std::pair<unsigned int, std::vector<unsigned int>>> possibleEdges;
void genWeights(std::ofstream& stream, const unsigned int vertexID)
{
std::random_device device;
std::uniform_int_distribution<unsigned int> distr (vertexID%100, 300);
for (size_t i = 0; i < weightNumber; ++i)
{
stream << distr(device);
if (i != weightNumber - 1)
stream << " ";
}
}
void genVertices (std::ofstream& stream)
{
for (size_t i = 0; i < vertexNumber; ++i)
{
genWeights(stream, i+1);
stream << std::endl;
}
}
void genEdges (std::ofstream& stream)
{
std::random_device device;
for (size_t i = 0; i < edgeNumber; ++i)
{
std::uniform_int_distribution<unsigned int> distr1 (0, possibleEdges.size()-1);
const unsigned int firstVertex = distr1(device);
std::uniform_int_distribution<unsigned int> distr2 (0, possibleEdges[firstVertex].second.size()-1);
const unsigned int secondVertex = distr2(device);
stream << (possibleEdges[firstVertex].first + 1) << " " << (possibleEdges[firstVertex].second[secondVertex] + 1) << std::endl;
std::swap(possibleEdges[firstVertex].second[secondVertex],possibleEdges[firstVertex].second.back());
possibleEdges[firstVertex].second.pop_back();
if (possibleEdges[firstVertex].second.empty())
{
std::swap(possibleEdges[firstVertex], possibleEdges.back());
possibleEdges.pop_back();
}
}
}
float computeGraphDensity(void)
{
const float floatVertexNumber = vertexNumber;
const float floatEdgeNumber = edgeNumber;
//Simply applying the formula
return (2.f*floatEdgeNumber) / (floatVertexNumber * floatVertexNumber - floatVertexNumber);
}
void genFile (std::ofstream& stream)
{
stream << "%edges: " << edgeNumber << " density: " << computeGraphDensity() << "\n";
stream << "i " << vertexNumber << " w " << weightNumber << "\n";
genVertices(stream);
genEdges(stream);
}
unsigned int getUInt (const char* str)
{
unsigned int result = 0;
while (std::isdigit(*str))
{
result *= 10;
result += *str - '0';
++str;
}
if (*str != '\0')
std::cerr << "WARNING: '" << *str << "' is not a digit, the rest of the line is not parsed" << std::endl;
return result;
}
//Format: ggen <file path> <weight per vertex> <n vertices> <n edges>
int main (int argc, const char** argv)
{
if (argc != 5)
{
std::cerr << "ERROR: arguments are <file parth> <weight per vertex> <n vertices> <n edges>" << std::endl;
return EXIT_FAILURE;
}
std::ofstream file (argv[1], std::ios::out);
weightNumber = getUInt(argv[2]);
vertexNumber = getUInt(argv[3]);
edgeNumber = getUInt(argv[4]);
const unsigned int maximumNumberOfEdges = (vertexNumber * (vertexNumber-1)) >> 1;
if (weightNumber >= 5)
std::cout << "WARNING: too many weights leads to the program taking more time to find the best cliques" << std::endl;
if (edgeNumber > maximumNumberOfEdges)
{
std::cout << "INFO: edge number too high, set back to " << maximumNumberOfEdges << std::endl;
edgeNumber = maximumNumberOfEdges;
}
std::cout << "INFO: w=" << weightNumber << " |V|=" << vertexNumber << " |E|=" << edgeNumber << " d=" << computeGraphDensity() << std::endl;
std::cout << "Begin generation... took: ";
possibleEdges.resize(vertexNumber-1);
const auto start = std::chrono::steady_clock::now();
for (size_t i = 0; i < vertexNumber-1; ++i)
{
possibleEdges[i].first = i;
possibleEdges[i].second.resize(vertexNumber - (i + 1));
for (size_t j = 0; j < possibleEdges[i].second.size(); ++j)
possibleEdges[i].second[j] = j+i+1;
}
genFile(file);
const auto end = std::chrono::steady_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::seconds>(end - start).count() << "s" << std::endl;
return EXIT_SUCCESS;
}