5#ifndef SASSY_GRAPH_BUILDER_H
6#define SASSY_GRAPH_BUILDER_H
20 struct vertexComparator {
21 explicit vertexComparator(
const sgraph &g) : graph(g) {}
25 bool operator()(
const int &v1,
const int &v2)
const {
26 return graph.
d[v1] < graph.
d[v2];
30 struct vertexComparatorColor {
31 vertexComparatorColor(
const sgraph &g,
const int *vtocol) : graph(g), vertex_to_col(vtocol) {}
34 const int *vertex_to_col;
36 bool operator()(
const int &v1,
const int &v2)
const {
38 return (vertex_to_col[v1] < vertex_to_col[v2]);
63 std::memset(c->
ptn, 1,
sizeof(
int) *
v_size);
65 if (this->v_size < c->domain_size) {
73 int last_new_cell = 0;
75 if (vertex_to_col ==
nullptr) {
76 for (
int i = 0; i <
v_size; i++) {
85 c->
ptn[last_new_cell] = i - last_new_cell;
90 if (this->d[c->
lab[i]] != this->d[c->
lab[i + 1]]) {
93 c->
ptn[last_new_cell] = i - last_new_cell;
94 last_new_cell = i + 1;
101 int min_col = INT32_MAX;
102 int max_col = INT32_MIN;
103 for (
int i = 0; i <
v_size; i++) {
104 if (vertex_to_col[i] < min_col)
105 min_col = vertex_to_col[i];
106 if (vertex_to_col[i] > max_col)
107 max_col = vertex_to_col[i];
110 std::vector<int> colsize;
111 colsize.reserve(std::min(this->v_size, (max_col - min_col) + 1));
113 if (min_col < 0 || max_col > 4 * this->v_size) {
114 std::unordered_map<int, int> colors;
115 colors.reserve(this->v_size);
116 for (
int i = 0; i <
v_size; i++) {
117 auto it = colors.find(vertex_to_col[i]);
118 if (it == colors.end()) {
119 colors.insert(std::pair<int, int>(vertex_to_col[i], col));
120 colsize.push_back(1);
122 vertex_to_col[i] = col;
125 const int found_col = it->second;
127 vertex_to_col[i] = found_col;
128 ++colsize[found_col];
132 std::vector<int> colors;
133 colors.reserve(max_col + 1);
134 for (
int i = 0; i < max_col + 1; ++i)
135 colors.push_back(-1);
136 for (
int i = 0; i <
v_size; i++) {
137 if (colors[vertex_to_col[i]] == -1) {
138 colors[vertex_to_col[i]] = col;
139 colsize.push_back(1);
141 vertex_to_col[i] = col;
144 const int found_col = colors[vertex_to_col[i]];
146 vertex_to_col[i] = found_col;
147 ++colsize[found_col];
153 for (
int &i: colsize) {
154 const int col_sz = i;
160 for (
int i = 0; i <
v_size; i++) {
161 const int v_col = vertex_to_col[i];
163 const int v_lab_pos = colsize[v_col];
164 c->
lab[v_lab_pos] = i;
176 c->
ptn[last_new_cell] = i - last_new_cell;
183 if (vertex_to_col[c->
lab[i]] != vertex_to_col[c->
lab[i + 1]]) {
186 c->
ptn[last_new_cell] = i - last_new_cell;
187 last_new_cell = i + 1;
197#if defined(DEJDEBUG) && !defined(NDEBUG)
198 for(
int i = 0; i <
v_size; ++i) {
204 for(
int i = 0; i <
e_size; ++i) {
212 for(
int i = 0; i <
v_size; ++i) {
213 multiedge_test.
reset();
214 for(
int j = 0; j <
d[i]; ++j) {
215 const int neigh =
e[
v[i] + j];
217 multiedge_test.
set(neigh);
223 for(
int i = 0; i <
v_size; ++i) {
224 multiedge_test.
reset();
225 for(
int j = 0; j <
d[i]; ++j) {
226 const int neigh =
e[
v[i] + j];
230 for(
int k = 0; k <
d[neigh]; ++k) {
231 const int neigh_neigh =
e[
v[neigh] + k];
232 if(neigh_neigh == i) {
251 memcpy(
v, g->
v, g->
v_size *
sizeof(
int));
252 memcpy(
d, g->
d, g->
v_size *
sizeof(
int));
253 memcpy(
e, g->
e, g->
e_size *
sizeof(
int));
259 for (
int i = 0; i <
v_size; ++i) {
260 const int estart =
v[i];
261 const int eend = estart +
d[i];
262 std::sort(
e + estart,
e + eend);
296 int* edge_cnt =
nullptr;
297 unsigned int num_vertices_defined = 0;
298 unsigned int num_edges_defined = 0;
299 unsigned int num_deg_edges_defined = 0;
301 bool finalized =
false;
307 throw std::logic_error(
"uninitialized graph");
308 if (num_vertices_defined != (
unsigned int) g.
v_size)
309 throw std::logic_error(
"did not add the number of vertices requested by constructor");
310 if (num_edges_defined != (
unsigned int) g.
e_size) {
311 std::cout << num_edges_defined <<
" vs. " << g.
e_size << std::endl;
312 throw std::logic_error(
"did not add the number of edges requested by constructor");
320 if(nv <= 0)
throw std::out_of_range(
"number of vertices must be positive");
321 if(ne <= 0)
throw std::out_of_range(
"number of edges must be positive");
326 edge_cnt =
new int[nv];
327 for(
int i = 0; i < nv; ++i) edge_cnt[i] = 0;
336 if(initialized && c !=
nullptr)
338 if(initialized && edge_cnt !=
nullptr)
343 if(initialized || finalized)
344 throw std::logic_error(
"can not initialize a graph that is already initialized");
350 edge_cnt =
new int[nv];
351 for(
unsigned int i = 0; i < nv; ++i)
357 throw std::logic_error(
"uninitialized graph");
359 throw std::logic_error(
"can not change finalized graph");
360 const unsigned int vertex = num_vertices_defined;
361 ++num_vertices_defined;
362 if(num_vertices_defined > (
unsigned int) g.
v_size)
363 throw std::out_of_range(
"vertices out-of-range, define more vertices initially");
366 g.
v[vertex] = (int) num_deg_edges_defined;
367 num_deg_edges_defined += deg;
371 void add_edge(
const unsigned int v1,
const unsigned int v2) {
373 throw std::logic_error(
"uninitialized graph");
375 throw std::logic_error(
"can not change finalized graph");
376 if(v1 > v2 || v1 == v2)
377 throw std::invalid_argument(
"invalid edge: v1 < v2 must hold");
378 if(v1 >= num_vertices_defined)
379 throw std::out_of_range(
"v1 is not a defined vertex, use add_vertex to add vertices");
380 if(v2 >= num_vertices_defined)
381 throw std::out_of_range(
"v2 is not a defined vertex, use add_vertex to add vertices");
382 if(
static_cast<int>(num_edges_defined + 2) > g.
e_size)
383 throw std::out_of_range(
"too many edges");
385 throw std::out_of_range(
"v1 too large, must be < INT32_MAX");
387 throw std::out_of_range(
"v2 too large, must be < INT32_MAX");
389 const int edg_cnt1 = edge_cnt[v1];
390 if(edg_cnt1 > g.
d[v1])
391 throw std::out_of_range(
"too many edges incident to v1");
392 g.
e[g.
v[v1] + edg_cnt1 - 1] =
static_cast<int>(v2);
395 const int edg_cnt2 = edge_cnt[v2];
396 if(edg_cnt2 > g.
d[v2])
397 throw std::out_of_range(
"too many edges incident to v2");
398 g.
e[g.
v[v2] + edg_cnt2 - 1] =
static_cast<int>(v1);
400 num_edges_defined += 2;
409 std::ofstream dumpfile;
410 dumpfile.open (filename, std::ios::out);
412 dumpfile <<
"p edge " << g.
v_size <<
" " << g.
e_size/2 << std::endl;
414 for(
int i = 0; i < g.
v_size; ++i) {
415 dumpfile <<
"n " << i+1 <<
" " << c[i] << std::endl;
418 for(
int i = 0; i < g.
v_size; ++i) {
419 for(
int j = g.
v[i]; j < g.
v[i]+g.
d[i]; ++j) {
420 const int neighbour = g.
e[j];
422 dumpfile <<
"e " << neighbour+1 <<
" " << i+1 << std::endl;
440static inline void parse_dimacs(
const std::string& filename,
dejavu::sgraph* g,
int** colmap,
bool silent=
true,
441 int seed_permute=0) {
442 std::chrono::high_resolution_clock::time_point timer = std::chrono::high_resolution_clock::now();
443 std::ifstream infile(filename);
445 std::vector<int> reshuffle;
447 std::vector<std::vector<int>> incidence_list;
448 std::set<int> degrees;
449 std::set<int> colors;
451 std::string nv_str, ne_str;
452 std::string nv1_string, nv2_string;
457 while (std::getline(infile, line)) {
462 for(i = 7; i < line.size() && line[i] !=
' '; ++i) {
467 for(; i < line.size() && line[i] !=
' '; ++i) {
470 nv = std::stoi(nv_str);
471 ne = std::stoi(ne_str);
472 average_d = (ne / nv) + 3;
475 reshuffle.reserve(nv);
476 for(
int j = 0; j < nv; ++j) reshuffle.push_back(j + 1);
477 if(seed_permute != 0) {
478 std::mt19937 eng(seed_permute);
479 std::shuffle(std::begin(reshuffle), std::end(reshuffle), eng);
482 incidence_list.reserve(nv);
483 for(
int j = 0; j < nv; ++j) {
484 incidence_list.emplace_back();
485 incidence_list[incidence_list.size() - 1].reserve(average_d);
491 for(i = 2; i < line.size() && line[i] !=
' '; ++i) {
492 nv1_string += line[i];
495 for(; i < line.size() && line[i] !=
' '; ++i) {
496 nv2_string += line[i];
499 nv1 = reshuffle[std::stoi(nv1_string)-1];
500 nv2 = reshuffle[std::stoi(nv2_string)-1];
502 incidence_list[nv1 - 1].push_back(nv2 - 1);
503 incidence_list[nv2 - 1].push_back(nv1 - 1);
506 if(*colmap ==
nullptr)
507 *colmap = (
int *) calloc(nv,
sizeof(
int));
510 for(i = 2; i < line.size() && line[i] !=
' '; ++i) {
511 nv1_string += line[i];
514 for(; i < line.size() && line[i] !=
' '; ++i) {
515 nv2_string += line[i];
518 nv1 = reshuffle[std::stoi(nv1_string)-1];
519 nv2 = std::stoi(nv2_string);
520 (*colmap)[nv1 - 1] = nv2;
532 for(
auto & incident : incidence_list) {
534 g->
d[vpos] = (int) incident.size();
536 if(g->
d[vpos] > maxd)
539 for(
int j : incident) {
550 const double parse_time = (double) (std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - timer).count());
551 if(!silent) std::cout << std::setprecision(2) <<
"parse_time=" << parse_time / 1000000.0 <<
"ms";
Vertex coloring for a graph.
void initialize(int new_domain_size)
Set specialized for quick resets.
void initialize(int size)
Internal graph data structure.
void initialize(int nv, int ne)
void sort_edgelist() const
void copy_graph(sgraph *g)
void initialize_coloring(ds::coloring *c, int *vertex_to_col)
Graph with static number of vertices and edges.
void add_edge(const unsigned int v1, const unsigned int v2)
unsigned int add_vertex(const int color, const int deg)
void initialize_graph(const unsigned int nv, const unsigned int ne)
void dump_dimacs(const std::string &filename)
static_graph(const int nv, const int ne)
dejavu::sgraph * get_sgraph()