Scippy

GCG

Branch-and-Price & Column Generation for Everyone

graph_gcg.cpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program */
4 /* GCG --- Generic Column Generation */
5 /* a Dantzig-Wolfe decomposition based extension */
6 /* of the branch-cut-and-price framework */
7 /* SCIP --- Solving Constraint Integer Programs */
8 /* */
9 /* Copyright (C) 2010-2021 Operations Research, RWTH Aachen University */
10 /* Zuse Institute Berlin (ZIB) */
11 /* */
12 /* This program is free software; you can redistribute it and/or */
13 /* modify it under the terms of the GNU Lesser General Public License */
14 /* as published by the Free Software Foundation; either version 3 */
15 /* of the License, or (at your option) any later version. */
16 /* */
17 /* This program is distributed in the hope that it will be useful, */
18 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
19 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
20 /* GNU Lesser General Public License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with this program; if not, write to the Free Software */
24 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.*/
25 /* */
26 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
27 
28 /**@file graph_gcg.h
29  * @brief Implementation of the graph which supports both node and edge weights.
30  * @author Igor Pesic
31  */
32 
33 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
34 #include <algorithm>
35 #include <iostream>
36 #include <cmath>
37 #include <set>
38 #include "graph_gcg.h"
39 
40 #ifdef WITH_GSL
41 #include <gsl/gsl_errno.h>
42 #endif
43 
44 using namespace std;
45 
46 namespace gcg {
47 
48 
49 GraphGCG::GraphGCG()
50 {
51  undirected = true;
52  locked = false;
53  initialized = false;
54  nodes = vector<int>(0);
55 #ifdef WITH_GSL
56  adj_matrix_sparse = gsl_spmatrix_alloc(1,1);
57  working_adj_matrix = NULL;
58 #endif
59 }
60 
61 GraphGCG::GraphGCG(int _n_nodes, bool _undirected)
62 {
63  undirected = _undirected;
64  locked = false;
65  initialized = true;
66  assert(_n_nodes >= 0);
67  nodes = vector<int>(_n_nodes, 0);
68 #ifdef WITH_GSL
69  adj_matrix_sparse = gsl_spmatrix_alloc(_n_nodes, _n_nodes);
70  working_adj_matrix = NULL;
71 #else
72  adj_matrix = vector<vector<double>>(_n_nodes, vector<double>(_n_nodes, 0.0));
73 #endif
74 }
75 
76 GraphGCG::~GraphGCG()
77 {
78  vector<int>().swap(this->nodes);
79 #ifndef WITH_GSL
80  vector<vector<double>>().swap(adj_matrix);
81  assert((int)adj_matrix.size() == 0);
82 #else
83  gsl_spmatrix_free(adj_matrix_sparse);
84  /*if(working_adj_matrix != NULL)
85  gsl_spmatrix_free(working_adj_matrix);*/
86 #endif
87  for(auto edge: edges)
88  {
89  if (edge != NULL)
90  delete edge;
91  }
92  initialized = false;
93 }
94 
95 SCIP_RETCODE GraphGCG::addNNodes(int _n_nodes)
96 {
97  if(locked || initialized)
98  {
99  return SCIP_ERROR;
100  }
101 #ifdef WITH_GSL
102  if(adj_matrix_sparse == NULL)
103  adj_matrix_sparse = gsl_spmatrix_alloc(_n_nodes, _n_nodes);
104  // add diagonal because of MCL algorithm
105  for(auto i = 0; i < _n_nodes; i++)
106  {
107  gsl_spmatrix_set(adj_matrix_sparse, i, i, 1.0);
108  }
109 #else
110  assert(adj_matrix.size() == 0);
111  adj_matrix = vector<vector<double>>(_n_nodes, vector<double>(_n_nodes, 0.0));
112 
113 #endif
114  nodes = vector<int>(_n_nodes, 0);
115  initialized = true;
116  return SCIP_OKAY;
117 }
118 
119 SCIP_RETCODE GraphGCG::addNNodes(int _n_nodes, std::vector<int> weights)
120 {
121  auto res = addNNodes(_n_nodes);
122  nodes = vector<int>(weights);
123  return res;
124 }
125 
126 
127 int GraphGCG::getNNodes()
128 {
129  if(!initialized) return 0;
130 #ifdef WITH_GSL
131  assert(nodes.size() == adj_matrix_sparse->size1);
132  assert(adj_matrix_sparse->size1 == adj_matrix_sparse->size2);
133  return adj_matrix_sparse->size1;
134 #else
135  assert(nodes.size() == adj_matrix.size());
136  return (int)adj_matrix.size();
137 #endif
138 }
139 
140 
141 #ifdef WITH_GSL
142 gsl_spmatrix* GraphGCG::getAdjMatrix()
143 {
144  cout << "Return adj_matrix_sparse..." << endl;
145  return adj_matrix_sparse;
146 }
147 
148 
149 void GraphGCG::expand(int factor)
150 {
151  assert(working_adj_matrix->sptype == (size_t)1);
152  const double alpha = 1.0;
153  gsl_spmatrix *tmp;
154  for(int i = 1; i < factor; i++)
155  {
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);
162  }
163 }
164 
165 
166 // inflate columns and normalize them
167 void GraphGCG::inflate(double factor)
168 {
169  assert(working_adj_matrix->sptype == (size_t)1);
170  size_t i = 0;
171  while(i < working_adj_matrix->nz)
172  {
173  working_adj_matrix->data[i] = pow(working_adj_matrix->data[i], factor);
174  i++;
175  }
176  colL1Norm();
177 }
178 
179 
180 // normalize columns, but remove values below 1e-6
181 void GraphGCG::colL1Norm()
182 {
183  assert(working_adj_matrix->sptype == (size_t)1);
184  // normalize the columns to sum up to 1
185  for(int col = 0; col < (int)working_adj_matrix->size2; col++)
186  {
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];
190  while(begin_ < end_)
191  {
192  col_sum += working_adj_matrix->data[begin_++];
193  }
194  begin_ = working_adj_matrix->p[col];
195  while(begin_ < end_)
196  {
197  working_adj_matrix->data[begin_] /= col_sum;
198  begin_++;
199  }
200  }
201 
202  // We need this part to remove very very small values, otherwise GSL behaves strangely
203  double threshold = 1e-8;
204  gsl_spmatrix *tmp = gsl_spmatrix_alloc(working_adj_matrix->size1, working_adj_matrix->size2);
205 
206  for (int col = 0; col < (int)working_adj_matrix->size1; col++)
207  {
208  size_t begin_ = working_adj_matrix->p[col];
209  const size_t end_ = working_adj_matrix->p[col+1];
210  while(begin_ < end_)
211  {
212  if(working_adj_matrix->data[begin_] > threshold)
213  {
214  gsl_spmatrix_set(tmp, working_adj_matrix->i[begin_], col, working_adj_matrix->data[begin_]);
215  }
216  begin_++;
217  }
218  }
219 
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);
226 }
227 
228 
229 // remove values below 1e-3 or 5*1e-4 or 1e-4 and then normalize
230 void GraphGCG::prune()
231 {
232  double threshold_start = 1e-3;
233  gsl_spmatrix *tmp = gsl_spmatrix_alloc(working_adj_matrix->size1, working_adj_matrix->size2);
234 
235  double ave_col_sum = 0.0;
236  for (int col = 0; col < (int)working_adj_matrix->size1; col++)
237  {
238  size_t begin_ = working_adj_matrix->p[col];
239  const size_t end_ = working_adj_matrix->p[col+1];
240  while(begin_ < end_)
241  {
242  if(working_adj_matrix->data[begin_] > threshold_start)
243  {
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_];
246  }
247  begin_++;
248  }
249  }
250  ave_col_sum /= (double)(tmp->size1);
251 
252  double thresholds[2] = {5*1e-4, 1e-4};
253  for(int i = 0; i < 2; i++)
254  {
255  if(ave_col_sum > 0.85)
256  {
257  break;
258  }
259 
260  gsl_spmatrix_set_zero(tmp);
261  ave_col_sum = 0.0;
262  for (int col = 0; col < (int)working_adj_matrix->size1; col++)
263  {
264  size_t begin_ = working_adj_matrix->p[col];
265  const size_t end_ = working_adj_matrix->p[col+1];
266  while(begin_ < end_)
267  {
268  if(working_adj_matrix->data[begin_] > thresholds[i])
269  {
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_];
272  }
273  begin_++;
274  }
275  }
276  ave_col_sum /= (double)(tmp->size1);
277  }
278 
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);
283 
284  gsl_spmatrix_free(tmp);
285  gsl_spmatrix_free(tmp_comp);
286 
287  colL1Norm();
288 }
289 
290 
291 // checks if A*A - A stays unchanged
292 bool GraphGCG::stopMCL(int iter)
293 {
294  if(iter > 6)
295  {
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);
301  double alpha = 1.0;
302  gsl_spblas_dgemm(alpha, working_adj_matrix, working_adj_matrix, tmpSquare);
303  gsl_spmatrix_add(res, tmpSquare, tmpMinus);
304  double min, max;
305  gsl_set_error_handler_off();
306  int status = gsl_spmatrix_minmax(res, &min, &max);
307  if(status == GSL_EINVAL)
308  {
309  min = 0.0;
310  max = 0.0;
311  }
312 
313  gsl_spmatrix_free(res);
314  gsl_spmatrix_free(tmpSquare);
315  gsl_spmatrix_free(tmpMinus);
316  if(abs(max - min) < 1e-8)
317  {
318  return true;
319  }
320  }
321  return false;
322 }
323 
324 vector<int> GraphGCG::getClustersMCL()
325 {
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;
329  set<int> nzrows;
330  vector<int> labels(working_adj_matrix->size1);
331 
332  for(int i = 0; i < (int)working_adj_matrix->nz; i++)
333  {
334  nzrows.insert(working_adj_matrix->i[i]);
335  }
336  int c = 0;
337  for(auto nzrow: nzrows)
338  {
339  row_to_label[nzrow] = c;
340  c++;
341  }
342 
343  map<int, vector<int> > clust_map;
344  // all data that belongs to that row belongs to its cluster
345  for (int col = 0; col < (int)working_adj_matrix->size2; col++)
346  {
347  size_t begin_ = working_adj_matrix->p[col];
348  const size_t end_ = working_adj_matrix->p[col+1];
349  while(begin_ < end_)
350  {
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); // python version
353  begin_++;
354  }
355  }
356 
357  for(auto item : clust_map)
358  {
359  for(auto val : item.second)
360  {
361  labels[val] = item.first;
362  }
363  }
364  // enumerations of labels may be broken (e.g. we can have labels 0,1,4,5), so we have to fix it to 0,1,2,3
365  set<int> existinglabels;
366  map<int, int> fixlabels;
367  for(int i = 0; i < (int)labels.size(); i++)
368  {
369  existinglabels.insert(labels[i]);
370  }
371 
372  c = 0;
373  for(auto existinglabel: existinglabels)
374  {
375  fixlabels[existinglabel] = c;
376  c++;
377  }
378  for(int i = 0; i < (int)labels.size(); i++)
379  {
380  labels[i] = fixlabels[labels[i]];
381  }
382  return labels;
383 }
384 
385 
386 void GraphGCG::initMCL()
387 {
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);
390 }
391 
392 
393 void GraphGCG::clearMCL()
394 {
395  gsl_spmatrix_free(working_adj_matrix);
396 }
397 
398 #else
399 vector<vector<double>> GraphGCG::getAdjMatrix()
400 {
401  return adj_matrix;
402 }
403 #endif
404 
405 
406 // TODO: we can use edges.size() here
407 int GraphGCG::getNEdges()
408 {
409  int n_edges = 0;
410 #ifdef WITH_GSL
411  if(initialized)
412  n_edges = adj_matrix_sparse->nz - adj_matrix_sparse->size1;
413  else
414  n_edges = 0;
415 #else
416  for(int i = 0; i < (int)adj_matrix.size(); i++)
417  {
418  n_edges += getNNeighbors(i);
419  }
420 #endif
421  if(undirected)
422  {
423  assert(n_edges % 2 == 0);
424  n_edges = (int) ( n_edges / 2.0);
425  }
426  assert(n_edges == (int)edges.size());
427  return n_edges;
428 }
429 
430 SCIP_Bool GraphGCG::isEdge(int node_i, int node_j)
431 {
432  assert(node_i >= 0);
433  assert(node_j >= 0);
434 #ifdef WITH_GSL
435  if(gsl_spmatrix_get(adj_matrix_sparse, node_i, node_j) != 0.0)
436  {
437  return 1;
438  }
439 #else
440  if(adj_matrix[node_i][node_j] != 0.0)
441  {
442  return 1;
443  }
444 #endif
445  return 0;
446 }
447 
448 int GraphGCG::getNNeighbors(int node)
449 {
450  assert(node >= 0);
451  int n_neighbors;
452 #ifdef WITH_GSL
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)
460  {
461  n_neighbors -=1 ;
462  }
463 #else
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;});
466  // remove itself as a neighbor
467  if(adj_matrix[node][node] != 0.0)
468  {
469  n_neighbors -= 1;
470  }
471 #endif
472  return n_neighbors;
473 }
474 
475 vector<int> GraphGCG::getNeighbors(int node)
476 {
477  vector<int> res;
478 #ifdef WITH_GSL
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_);
485  size_t curr = 0;
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_++];
490  }
491  assert(curr == res.size());
492  if(self_found)
493  res.erase(remove(res.begin(), res.end(), node), res.end());
494 #else
495  for(int i = 0; i < (int)adj_matrix[node].size(); i++)
496  {
497  if(adj_matrix[node][i] != 0.0 && node != i)
498  {
499  res.push_back(i);
500  }
501  }
502 #endif
503  return res;
504 }
505 
506 vector<pair<int, double> > GraphGCG::getNeighborWeights(int node)
507 {
508  vector<pair<int, double> > res;
509 #ifdef WITH_GSL
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_);
516  size_t curr = 0;
517  bool self_found = false;
518  int found_pos = 0;
519  while(begin_ < end_){
520  if((int)adj_matrix_sparse->i[begin_] == node)
521  {
522  self_found = true;
523  found_pos = curr;
524  }
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);
528  begin_++;
529  }
530  assert(curr == res.size());
531  if(self_found)
532  {
533  res.erase(res.begin() + found_pos);
534  }
535 #else
536  for(int i = 0; i < (int)adj_matrix[node].size(); i++)
537  {
538  if(adj_matrix[node][i] != 0.0 && node != i)
539  {
540  res.push_back(make_pair(i, adj_matrix[node][i]));
541  }
542  }
543 #endif
544 
545 
546  return res;
547 }
548 
549 /** int node is obsolete, it must be the next available id */
550 SCIP_RETCODE GraphGCG::addNode(int node, int weight)
551 {
552 
553  if(locked)
554  {
555  return SCIP_ERROR;
556  }
557  int next_id = (int)nodes.size();
558  assert(node == next_id);
559 
560 #ifdef WITH_GSL
561  if(adj_matrix_sparse == NULL)
562  adj_matrix_sparse = gsl_spmatrix_alloc(1, 1);
563  // add diagonal because of MCL algorithm
564  gsl_spmatrix_set(adj_matrix_sparse, next_id, next_id, 1.0);
565 
566  //return SCIP_NOTIMPL;
567 #else
568 
569  // add new column
570  for(size_t i = 0; i < adj_matrix.size(); i++)
571  {
572  adj_matrix[i].push_back(0.0);
573  }
574  // add new row
575  adj_matrix.push_back(vector<double>(next_id+1));
576 
577  // add self loop
578  adj_matrix[next_id][next_id] = 1.0;
579  assert(adj_matrix.size() == adj_matrix[0].size());
580 #endif
581  initialized = true;
582  nodes.push_back(weight);
583  return SCIP_OKAY;
584 }
585 
586 SCIP_RETCODE GraphGCG::addNode()
587 {
588 #ifdef WITH_GSL
589  return addNode((int)adj_matrix_sparse->size2, 0);
590 #else
591  return addNode((int)adj_matrix.size(), 0);
592 #endif
593 }
594 
595 SCIP_RETCODE GraphGCG::deleteNode(int node)
596 {
597  if(locked)
598  {
599  return SCIP_ERROR;
600  }
601  // Would be very inefficient and is not necessary
602  return SCIP_INVALIDCALL;
603 }
604 
605 SCIP_RETCODE GraphGCG::addEdge(int node_i, int node_j)
606 {
607  return addEdge(node_i, node_j, 1);
608 }
609 
610 SCIP_RETCODE GraphGCG::addEdge(int node_i, int node_j, double weight)
611 {
612  if(locked || !initialized || node_i == node_j)
613  {
614  return SCIP_ERROR;
615  }
616  bool new_edge = true;
617  assert(weight >= 0.0);
618  assert(node_i >= 0);
619  assert(node_j >= 0);
620 #ifdef WITH_GSL
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)
624  {
625  new_edge = false;
626  }
627  if(new_edge)
628  {
629  gsl_spmatrix_set(adj_matrix_sparse, node_i, node_j, weight);
630  if(undirected)
631  {
632  gsl_spmatrix_set(adj_matrix_sparse, node_j, node_i, weight);
633  }
634  }
635 #else
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;
640  if(undirected)
641  {
642  adj_matrix[node_j][node_i] = weight;
643  }
644 #endif
645  if(new_edge && node_i != node_j)
646  {
647  int first, second;
648  first = node_i < node_j ? node_i : node_j;
649  second = node_i == first ? node_j : node_i;
650  EdgeGCG* edge1 = new EdgeGCG(first, second, weight);
651  edges.push_back(edge1);
652  }
653 
654  return SCIP_OKAY;
655 }
656 
657 SCIP_RETCODE GraphGCG::setEdge(int node_i, int node_j, double weight)
658 {
659  if(locked || !initialized)
660  {
661  return SCIP_ERROR;
662  }
663  assert(weight >= 0.0);
664  assert(node_i >= 0);
665  assert(node_j >= 0);
666 #ifdef WITH_GSL
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);
670  if(undirected)
671  {
672  gsl_spmatrix_set(adj_matrix_sparse, node_j, node_i, weight);
673  }
674 #else
675  assert(node_i < (int)adj_matrix.size());
676  assert(node_j < (int)adj_matrix.size());
677  adj_matrix[node_i][node_j] = weight;
678  if(undirected)
679  {
680  adj_matrix[node_j][node_i] = weight;
681  }
682 #endif
683  if(node_i != node_j)
684  for(auto edge: edges)
685  {
686  if((edge->src == node_i && edge->dest == node_j) || (edge->src == node_j && edge->dest == node_i))
687  {
688  edge->weight = weight;
689  }
690  }
691  return SCIP_OKAY;
692 }
693 
694 SCIP_RETCODE GraphGCG::deleteEdge(int node_i, int node_j)
695 {
696  return setEdge(node_i, node_j, 0);
697 }
698 
699 int GraphGCG::graphGetWeights(int node)
700 {
701  return nodes[node];
702 }
703 
704 double GraphGCG::getEdgeWeight(int node_i, int node_j)
705 {
706  assert(node_i >= 0);
707  assert(node_j >= 0);
708  double weight;
709 #ifdef WITH_GSL
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);
713 #else
714  assert(node_i < (int)adj_matrix.size());
715  assert(node_j < (int)adj_matrix.size());
716  weight = adj_matrix[node_i][node_j];
717 #endif
718  return weight;
719 }
720 
721 SCIP_RETCODE GraphGCG::flush()
722 {
723  locked = true;
724 #ifdef WITH_GSL
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;
728 #endif
729  return SCIP_OKAY;
730 }
731 
732 SCIP_RETCODE GraphGCG::normalize()
733 {
734  double scaler = 0.0;
735 #ifdef WITH_GSL
736  double min, max;
737  gsl_spmatrix_minmax(adj_matrix_sparse, &min, &max);
738  scaler = max;
739  gsl_spmatrix_scale(adj_matrix_sparse, double(1.0/scaler));
740 
741 #else
742  for(int i = 0; i < (int)adj_matrix.size(); i++)
743  {
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 )
747  {
748  scaler = curr_max;
749  }
750  }
751 
752  for(int i = 0; i < (int)adj_matrix.size(); i++)
753  {
754  for(int j = 0; j < (int)adj_matrix[i].size(); j++)
755  {
756  adj_matrix[i][j] /= scaler;
757  assert(adj_matrix[i][j] <= 1);
758  assert(adj_matrix[i][j] >= 0);
759  }
760  }
761 #endif
762  return SCIP_OKAY;
763 }
764 
765 double GraphGCG::getEdgeWeightPercentile(double q)
766 {
767  double res = -1;
768  vector<double> all_weights;
769 #ifdef WITH_GSL
770  all_weights = vector<double>(adj_matrix_sparse->data, adj_matrix_sparse->data + adj_matrix_sparse->nz);
771 #else
772  for(int i = 0; i < (int)adj_matrix.size(); i++)
773  {
774  for(int j = 0; j < (int)adj_matrix[i].size(); j++)
775  {
776  if(adj_matrix[i][j] != 0.0)
777  {
778  all_weights.push_back(adj_matrix[i][j]);
779  }
780  }
781  }
782 #endif
783  sort(all_weights.begin(), all_weights.end());
784 
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)
788  {
789  res = (all_weights[upper_pos] + all_weights[lower_pos]) / 2.0;
790  }
791  else
792  {
793  res = all_weights[lower_pos];
794  }
795  return res;
796 }
797 
798 
799 SCIP_RETCODE GraphGCG::getEdges(vector<void *>& _edges)
800 {
801  _edges.resize(edges.size());
802  for(int i = 0; i < (int)edges.size(); i++)
803  {
804  assert(edges[i]->src < (int)nodes.size());
805  assert(edges[i]->dest < (int)nodes.size());
806  assert(edges[i]->src != edges[i]->dest);
807 
808  (_edges[i]) = (void *)(edges[i]);
809  }
810  return SCIP_OKAY;
811 }
812 
813 
814 // Compare two edges according to their weights.
815 // Used in sort() for sorting an array of edges
816 int GraphGCG::edgeComp(const EdgeGCG* a, const EdgeGCG* b)
817 {
818  return (a->src < b->src) || (a->src == b->src && a->weight < b->weight);
819 }
820 
821 
822 
823 
824 }
double weight
Definition: graph_gcg.h:52
Implementation of the graph which supports both node and edge weights.