41 #include <gsl/gsl_errno.h>
54 nodes = vector<int>(0);
56 adj_matrix_sparse = gsl_spmatrix_alloc(1,1);
57 working_adj_matrix = NULL;
61 GraphGCG::GraphGCG(
int _n_nodes,
bool _undirected)
63 undirected = _undirected;
66 assert(_n_nodes >= 0);
67 nodes = vector<int>(_n_nodes, 0);
69 adj_matrix_sparse = gsl_spmatrix_alloc(_n_nodes, _n_nodes);
70 working_adj_matrix = NULL;
72 adj_matrix = vector<vector<double>>(_n_nodes, vector<double>(_n_nodes, 0.0));
78 vector<int>().swap(this->nodes);
80 vector<vector<double>>().swap(adj_matrix);
81 assert((
int)adj_matrix.size() == 0);
83 gsl_spmatrix_free(adj_matrix_sparse);
95 SCIP_RETCODE GraphGCG::addNNodes(
int _n_nodes)
97 if(locked || initialized)
102 if(adj_matrix_sparse == NULL)
103 adj_matrix_sparse = gsl_spmatrix_alloc(_n_nodes, _n_nodes);
105 for(
auto i = 0; i < _n_nodes; i++)
107 gsl_spmatrix_set(adj_matrix_sparse, i, i, 1.0);
110 assert(adj_matrix.size() == 0);
111 adj_matrix = vector<vector<double>>(_n_nodes, vector<double>(_n_nodes, 0.0));
114 nodes = vector<int>(_n_nodes, 0);
119 SCIP_RETCODE GraphGCG::addNNodes(
int _n_nodes, std::vector<int> weights)
121 auto res = addNNodes(_n_nodes);
122 nodes = vector<int>(weights);
127 int GraphGCG::getNNodes()
129 if(!initialized)
return 0;
131 assert(nodes.size() == adj_matrix_sparse->size1);
132 assert(adj_matrix_sparse->size1 == adj_matrix_sparse->size2);
133 return adj_matrix_sparse->size1;
135 assert(nodes.size() == adj_matrix.size());
136 return (
int)adj_matrix.size();
142 gsl_spmatrix* GraphGCG::getAdjMatrix()
144 cout <<
"Return adj_matrix_sparse..." << endl;
145 return adj_matrix_sparse;
149 void GraphGCG::expand(
int factor)
151 assert(working_adj_matrix->sptype == (
size_t)1);
152 const double alpha = 1.0;
154 for(
int i = 1; i < factor; i++)
156 tmp = gsl_spmatrix_alloc_nzmax(working_adj_matrix->size1, working_adj_matrix->size2, working_adj_matrix->nz, GSL_SPMATRIX_CCS);
157 gsl_spblas_dgemm(alpha, working_adj_matrix, working_adj_matrix, tmp);
158 gsl_spmatrix_free(working_adj_matrix);
159 working_adj_matrix = gsl_spmatrix_alloc_nzmax(tmp->size1, tmp->size2, tmp->nz, GSL_SPMATRIX_CCS);
160 gsl_spmatrix_memcpy(working_adj_matrix, tmp);
161 gsl_spmatrix_free(tmp);
167 void GraphGCG::inflate(
double factor)
169 assert(working_adj_matrix->sptype == (
size_t)1);
171 while(i < working_adj_matrix->nz)
173 working_adj_matrix->data[i] = pow(working_adj_matrix->data[i], factor);
181 void GraphGCG::colL1Norm()
183 assert(working_adj_matrix->sptype == (
size_t)1);
185 for(
int col = 0; col < (int)working_adj_matrix->size2; col++)
187 double col_sum = 0.0;
188 size_t begin_ = working_adj_matrix->p[col];
189 const size_t end_ = working_adj_matrix->p[col+1];
192 col_sum += working_adj_matrix->data[begin_++];
194 begin_ = working_adj_matrix->p[col];
197 working_adj_matrix->data[begin_] /= col_sum;
203 double threshold = 1e-8;
204 gsl_spmatrix *tmp = gsl_spmatrix_alloc(working_adj_matrix->size1, working_adj_matrix->size2);
206 for (
int col = 0; col < (int)working_adj_matrix->size1; col++)
208 size_t begin_ = working_adj_matrix->p[col];
209 const size_t end_ = working_adj_matrix->p[col+1];
212 if(working_adj_matrix->data[begin_] > threshold)
214 gsl_spmatrix_set(tmp, working_adj_matrix->i[begin_], col, working_adj_matrix->data[begin_]);
220 gsl_spmatrix *tmp_comp = gsl_spmatrix_compcol(tmp);
221 gsl_spmatrix_free(working_adj_matrix);
222 working_adj_matrix = gsl_spmatrix_alloc_nzmax(tmp_comp->size1, tmp_comp->size2, tmp_comp->nz, GSL_SPMATRIX_CCS);
223 gsl_spmatrix_memcpy(working_adj_matrix, tmp_comp);
224 gsl_spmatrix_free(tmp);
225 gsl_spmatrix_free(tmp_comp);
230 void GraphGCG::prune()
232 double threshold_start = 1e-3;
233 gsl_spmatrix *tmp = gsl_spmatrix_alloc(working_adj_matrix->size1, working_adj_matrix->size2);
235 double ave_col_sum = 0.0;
236 for (
int col = 0; col < (int)working_adj_matrix->size1; col++)
238 size_t begin_ = working_adj_matrix->p[col];
239 const size_t end_ = working_adj_matrix->p[col+1];
242 if(working_adj_matrix->data[begin_] > threshold_start)
244 gsl_spmatrix_set(tmp, working_adj_matrix->i[begin_], col, working_adj_matrix->data[begin_]);
245 ave_col_sum += working_adj_matrix->data[begin_];
250 ave_col_sum /= (double)(tmp->size1);
252 double thresholds[2] = {5*1e-4, 1e-4};
253 for(
int i = 0; i < 2; i++)
255 if(ave_col_sum > 0.85)
260 gsl_spmatrix_set_zero(tmp);
262 for (
int col = 0; col < (int)working_adj_matrix->size1; col++)
264 size_t begin_ = working_adj_matrix->p[col];
265 const size_t end_ = working_adj_matrix->p[col+1];
268 if(working_adj_matrix->data[begin_] > thresholds[i])
270 gsl_spmatrix_set(tmp, working_adj_matrix->i[begin_], col, working_adj_matrix->data[begin_]);
271 ave_col_sum += working_adj_matrix->data[begin_];
276 ave_col_sum /= (double)(tmp->size1);
279 gsl_spmatrix *tmp_comp = gsl_spmatrix_compcol(tmp);
280 gsl_spmatrix_free(working_adj_matrix);
281 working_adj_matrix = gsl_spmatrix_alloc_nzmax(tmp_comp->size1, tmp_comp->size2, tmp_comp->nz, GSL_SPMATRIX_CCS);
282 gsl_spmatrix_memcpy(working_adj_matrix, tmp_comp);
284 gsl_spmatrix_free(tmp);
285 gsl_spmatrix_free(tmp_comp);
292 bool GraphGCG::stopMCL(
int iter)
296 gsl_spmatrix *tmpSquare = gsl_spmatrix_alloc_nzmax(working_adj_matrix->size1, working_adj_matrix->size2, working_adj_matrix->nz, GSL_SPMATRIX_CCS);
297 gsl_spmatrix *tmpMinus = gsl_spmatrix_alloc_nzmax(working_adj_matrix->size1, working_adj_matrix->size2, working_adj_matrix->nz, GSL_SPMATRIX_CCS);
298 gsl_spmatrix *res = gsl_spmatrix_alloc_nzmax(working_adj_matrix->size1, working_adj_matrix->size2, working_adj_matrix->nz, GSL_SPMATRIX_CCS);
299 gsl_spmatrix_memcpy(tmpMinus, working_adj_matrix);
300 gsl_spmatrix_scale(tmpMinus, -1.0);
302 gsl_spblas_dgemm(alpha, working_adj_matrix, working_adj_matrix, tmpSquare);
303 gsl_spmatrix_add(res, tmpSquare, tmpMinus);
305 gsl_set_error_handler_off();
306 int status = gsl_spmatrix_minmax(res, &min, &max);
307 if(status == GSL_EINVAL)
313 gsl_spmatrix_free(res);
314 gsl_spmatrix_free(tmpSquare);
315 gsl_spmatrix_free(tmpMinus);
316 if(abs(max - min) < 1e-8)
324 vector<int> GraphGCG::getClustersMCL()
326 assert(working_adj_matrix->size1 == working_adj_matrix->size2);
327 vector<int> res(working_adj_matrix->size1, 0);
328 map<int, int> row_to_label;
330 vector<int> labels(working_adj_matrix->size1);
332 for(
int i = 0; i < (int)working_adj_matrix->nz; i++)
334 nzrows.insert(working_adj_matrix->i[i]);
337 for(
auto nzrow: nzrows)
339 row_to_label[nzrow] = c;
343 map<int, vector<int> > clust_map;
345 for (
int col = 0; col < (int)working_adj_matrix->size2; col++)
347 size_t begin_ = working_adj_matrix->p[col];
348 const size_t end_ = working_adj_matrix->p[col+1];
351 labels[col] = row_to_label[working_adj_matrix->i[begin_]];
352 clust_map[row_to_label[working_adj_matrix->i[begin_]]].push_back(col);
357 for(
auto item : clust_map)
359 for(
auto val : item.second)
361 labels[val] = item.first;
365 set<int> existinglabels;
366 map<int, int> fixlabels;
367 for(
int i = 0; i < (int)labels.size(); i++)
369 existinglabels.insert(labels[i]);
373 for(
auto existinglabel: existinglabels)
375 fixlabels[existinglabel] = c;
378 for(
int i = 0; i < (int)labels.size(); i++)
380 labels[i] = fixlabels[labels[i]];
386 void GraphGCG::initMCL()
388 working_adj_matrix = gsl_spmatrix_alloc_nzmax(adj_matrix_sparse->size1, adj_matrix_sparse->size2, adj_matrix_sparse->nz, GSL_SPMATRIX_CCS);
389 gsl_spmatrix_memcpy(working_adj_matrix, adj_matrix_sparse);
393 void GraphGCG::clearMCL()
395 gsl_spmatrix_free(working_adj_matrix);
399 vector<vector<double>> GraphGCG::getAdjMatrix()
407 int GraphGCG::getNEdges()
412 n_edges = adj_matrix_sparse->nz - adj_matrix_sparse->size1;
416 for(
int i = 0; i < (int)adj_matrix.size(); i++)
418 n_edges += getNNeighbors(i);
423 assert(n_edges % 2 == 0);
424 n_edges = (int) ( n_edges / 2.0);
426 assert(n_edges == (
int)edges.size());
430 SCIP_Bool GraphGCG::isEdge(
int node_i,
int node_j)
435 if(gsl_spmatrix_get(adj_matrix_sparse, node_i, node_j) != 0.0)
440 if(adj_matrix[node_i][node_j] != 0.0)
448 int GraphGCG::getNNeighbors(
int node)
453 if(!initialized)
return 0;
454 assert(adj_matrix_sparse->sptype == (
size_t)1);
455 assert(node < (
int)adj_matrix_sparse->size2);
456 const size_t begin_ = adj_matrix_sparse->p[node];
457 const size_t end_ = adj_matrix_sparse->p[node+1];
458 n_neighbors = (int)(end_ - begin_);
459 if(gsl_spmatrix_get(adj_matrix_sparse, node, node) != 0.0)
464 assert(node < (
int)adj_matrix.size());
465 n_neighbors = count_if(adj_matrix[node].begin(), adj_matrix[node].end(), [](
double i) {
return i != 0.0;});
467 if(adj_matrix[node][node] != 0.0)
475 vector<int> GraphGCG::getNeighbors(
int node)
479 if(!initialized || !locked)
return res;
480 assert(adj_matrix_sparse->sptype == (
size_t)1);
481 assert(node < (
int)adj_matrix_sparse->size2);
482 size_t begin_ = adj_matrix_sparse->p[node];
483 size_t end_ = adj_matrix_sparse->p[node+1];
484 res.resize(end_ - begin_);
486 bool self_found =
false;
487 while(begin_ < end_){
488 if((
int)adj_matrix_sparse->i[begin_] == node) self_found =
true;
489 res[curr++] = adj_matrix_sparse->i[begin_++];
491 assert(curr == res.size());
493 res.erase(remove(res.begin(), res.end(), node), res.end());
495 for(
int i = 0; i < (int)adj_matrix[node].size(); i++)
497 if(adj_matrix[node][i] != 0.0 && node != i)
506 vector<pair<int, double> > GraphGCG::getNeighborWeights(
int node)
508 vector<pair<int, double> > res;
510 if(!initialized || !locked)
return res;
511 assert(adj_matrix_sparse->sptype == (
size_t)1);
512 assert(node < (
int)adj_matrix_sparse->size2);
513 size_t begin_ = adj_matrix_sparse->p[node];
514 size_t end_ = adj_matrix_sparse->p[node+1];
515 res.resize(end_ - begin_);
517 bool self_found =
false;
519 while(begin_ < end_){
520 if((
int)adj_matrix_sparse->i[begin_] == node)
525 double value = adj_matrix_sparse->data[begin_];
526 int row = (int)adj_matrix_sparse->i[begin_];
527 res[curr++] = pair<int, double>(row, value);
530 assert(curr == res.size());
533 res.erase(res.begin() + found_pos);
536 for(
int i = 0; i < (int)adj_matrix[node].size(); i++)
538 if(adj_matrix[node][i] != 0.0 && node != i)
540 res.push_back(make_pair(i, adj_matrix[node][i]));
550 SCIP_RETCODE GraphGCG::addNode(
int node,
int weight)
557 int next_id = (int)nodes.size();
558 assert(node == next_id);
561 if(adj_matrix_sparse == NULL)
562 adj_matrix_sparse = gsl_spmatrix_alloc(1, 1);
564 gsl_spmatrix_set(adj_matrix_sparse, next_id, next_id, 1.0);
570 for(
size_t i = 0; i < adj_matrix.size(); i++)
572 adj_matrix[i].push_back(0.0);
575 adj_matrix.push_back(vector<double>(next_id+1));
578 adj_matrix[next_id][next_id] = 1.0;
579 assert(adj_matrix.size() == adj_matrix[0].size());
582 nodes.push_back(weight);
586 SCIP_RETCODE GraphGCG::addNode()
589 return addNode((
int)adj_matrix_sparse->size2, 0);
591 return addNode((
int)adj_matrix.size(), 0);
595 SCIP_RETCODE GraphGCG::deleteNode(
int node)
602 return SCIP_INVALIDCALL;
605 SCIP_RETCODE GraphGCG::addEdge(
int node_i,
int node_j)
607 return addEdge(node_i, node_j, 1);
610 SCIP_RETCODE GraphGCG::addEdge(
int node_i,
int node_j,
double weight)
612 if(locked || !initialized || node_i == node_j)
616 bool new_edge =
true;
617 assert(weight >= 0.0);
621 assert(node_i < (
int)adj_matrix_sparse->size2);
622 assert(node_j < (
int)adj_matrix_sparse->size2);
623 if (gsl_spmatrix_get(adj_matrix_sparse, node_i, node_j) != 0.0)
629 gsl_spmatrix_set(adj_matrix_sparse, node_i, node_j, weight);
632 gsl_spmatrix_set(adj_matrix_sparse, node_j, node_i, weight);
636 assert(node_i < (
int)adj_matrix.size());
637 assert(node_j < (
int)adj_matrix.size());
638 (adj_matrix[node_i][node_j] == 0.0) ? new_edge = true : new_edge =
false;
639 adj_matrix[node_i][node_j] = weight;
642 adj_matrix[node_j][node_i] = weight;
645 if(new_edge && node_i != node_j)
648 first = node_i < node_j ? node_i : node_j;
649 second = node_i == first ? node_j : node_i;
651 edges.push_back(edge1);
657 SCIP_RETCODE GraphGCG::setEdge(
int node_i,
int node_j,
double weight)
659 if(locked || !initialized)
663 assert(weight >= 0.0);
667 assert(node_i < (
int)adj_matrix_sparse->size2);
668 assert(node_j < (
int)adj_matrix_sparse->size2);
669 gsl_spmatrix_set(adj_matrix_sparse, node_i, node_j, weight);
672 gsl_spmatrix_set(adj_matrix_sparse, node_j, node_i, weight);
675 assert(node_i < (
int)adj_matrix.size());
676 assert(node_j < (
int)adj_matrix.size());
677 adj_matrix[node_i][node_j] = weight;
680 adj_matrix[node_j][node_i] = weight;
684 for(
auto edge: edges)
686 if((edge->src == node_i && edge->dest == node_j) || (edge->src == node_j && edge->dest == node_i))
688 edge->weight = weight;
694 SCIP_RETCODE GraphGCG::deleteEdge(
int node_i,
int node_j)
696 return setEdge(node_i, node_j, 0);
699 int GraphGCG::graphGetWeights(
int node)
704 double GraphGCG::getEdgeWeight(
int node_i,
int node_j)
710 assert(node_i < (
int)adj_matrix_sparse->size1);
711 assert(node_j < (
int)adj_matrix_sparse->size1);
712 weight = gsl_spmatrix_get(adj_matrix_sparse, node_i, node_j);
714 assert(node_i < (
int)adj_matrix.size());
715 assert(node_j < (
int)adj_matrix.size());
716 weight = adj_matrix[node_i][node_j];
721 SCIP_RETCODE GraphGCG::flush()
725 gsl_spmatrix *adj_matrix_sparse_tmp = gsl_spmatrix_compcol(adj_matrix_sparse);
726 gsl_spmatrix_free(adj_matrix_sparse);
727 adj_matrix_sparse = adj_matrix_sparse_tmp;
732 SCIP_RETCODE GraphGCG::normalize()
737 gsl_spmatrix_minmax(adj_matrix_sparse, &min, &max);
739 gsl_spmatrix_scale(adj_matrix_sparse,
double(1.0/scaler));
742 for(
int i = 0; i < (int)adj_matrix.size(); i++)
744 vector<double>::iterator tmp = max_element(adj_matrix[i].begin(), adj_matrix[i].end());
745 double curr_max = *tmp;
746 if( curr_max > scaler )
752 for(
int i = 0; i < (int)adj_matrix.size(); i++)
754 for(
int j = 0; j < (int)adj_matrix[i].size(); j++)
756 adj_matrix[i][j] /= scaler;
757 assert(adj_matrix[i][j] <= 1);
758 assert(adj_matrix[i][j] >= 0);
765 double GraphGCG::getEdgeWeightPercentile(
double q)
768 vector<double> all_weights;
770 all_weights = vector<double>(adj_matrix_sparse->data, adj_matrix_sparse->data + adj_matrix_sparse->nz);
772 for(
int i = 0; i < (int)adj_matrix.size(); i++)
774 for(
int j = 0; j < (int)adj_matrix[i].size(); j++)
776 if(adj_matrix[i][j] != 0.0)
778 all_weights.push_back(adj_matrix[i][j]);
783 sort(all_weights.begin(), all_weights.end());
785 int upper_pos = (int) floor((q/100.0)*all_weights.size());
786 int lower_pos = (int) ceil((q/100.0)*all_weights.size());
787 if(upper_pos != lower_pos)
789 res = (all_weights[upper_pos] + all_weights[lower_pos]) / 2.0;
793 res = all_weights[lower_pos];
799 SCIP_RETCODE GraphGCG::getEdges(vector<void *>& _edges)
801 _edges.resize(edges.size());
802 for(
int i = 0; i < (int)edges.size(); i++)
804 assert(edges[i]->src < (
int)nodes.size());
805 assert(edges[i]->dest < (
int)nodes.size());
806 assert(edges[i]->src != edges[i]->dest);
808 (_edges[i]) = (
void *)(edges[i]);