Read@CVL
mcqd.h
Go to the documentation of this file.
1 /*
2  Copyright 2007-2012 Janez Konc
3 
4  If you use this program, please cite:
5  Janez Konc and Dusanka Janezic. An improved branch and bound algorithm for the
6  maximum clique problem. MATCH Commun. Math. Comput. Chem., 2007, 58, 569-590.
7 
8  More information at: http://www.sicmm.org/~konc
9 
10  This program is free software: you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23 
24 #ifndef MCQD
25 #define MCQD
26 
27 #include <iostream>
28 #include <algorithm>
29 #include <assert.h>
30 
31 #pragma warning(push, 0) // no warnings from includes
32 #include <QDebug>
33 #pragma warning(pop)
34 
35 #ifdef DBG
36 using namespace std;
37 #endif
38 
39 class Maxclique {
40  const bool* const* e;
41  int pk, level;
42  const float Tlimit;
43  class Vertices {
44  class Vertex {
45  int i, d;
46  public:
47  void set_i(const int ii) { i = ii; }
48  int get_i() const { return i; }
49  void set_degree(int dd) { d = dd; }
50  int get_degree() const { return d; }
51  };
52  Vertex *v;
53  int sz;
54  static bool desc_degree(const Vertex vi, const Vertex vj) { return (vi.get_degree() > vj.get_degree()); }
55  public:
56 #ifdef DBG
57  void dbg_v(const string msg="") const {
58  std::cout << msg << " Vertices: [";
59  for (int i=0; i < sz; i++)
60  std::cout << "(" << v[i].get_i() << "," << v[i].get_degree() << ") ";
61  std::cout << "]" << std::endl;
62  }
63 #endif
64  Vertices(int size) : sz(0) { v = new Vertex[size]; }
65  ~Vertices () {}
66  void dispose() { if (v) delete [] v; }
67  void sort() { std::sort(v, v+sz, desc_degree); }
68  void init_colors();
69  void set_degrees(Maxclique&);
70  int size() const { return sz; }
71  void push(const int ii) { v[sz++].set_i(ii); };
72  void pop() { sz--; };
73  Vertex& at(const int ii) const { return v[ii]; };
74  Vertex& end() const { return v[sz - 1]; };
75  };
76  class ColorClass {
77  int *i;
78  int sz;
79  public:
80 #ifdef DBG
81  void dbg_i(const string msg="") const {
82  std::cout << msg << " Class: [";
83  for (int ii=0; ii < sz; ii++)
84  std::cout << i[ii] << " ";
85  std::cout << "]" << std::endl;
86  }
87 #endif
88  ColorClass() : sz(0), i(0) {}
89  ColorClass(const int sz) : sz(sz), i(0) { init(sz); }
90  ~ColorClass() { if (i) delete [] i;
91  }
92  void init(const int sz2) { i = new int[sz2]; rewind(); }
93  void push(const int ii) { i[sz++] = ii; };
94  void pop() { sz--; };
95  void rewind() { sz = 0; };
96  int size() const { return sz; }
97  int& at(const int ii) const { return i[ii]; }
98  ColorClass& operator=(const ColorClass& dh) {
99  for (int j = 0; j < dh.sz; j++) i[j] = dh.i[j];
100  sz = dh.sz;
101  return *this;
102  }
103  };
104  Vertices V;
105  ColorClass *C, QMAX, Q;
106  class StepCount {
107  int i1, i2;
108  public:
109  StepCount() : i1(0), i2(0) {}
110  void set_i1(const int ii) { i1 = ii; }
111  int get_i1() const { return i1; }
112  void set_i2(const int ii) { i2 = ii; }
113  int get_i2() const { return i2; }
114  void inc_i1() { i1++; }
115  };
116  StepCount *S;
117  bool connection(const int i, const int j) const { return e[i][j]; }
118  bool cut1(const int, const ColorClass&);
119  void cut2(const Vertices&, Vertices&);
120  void color_sort(Vertices&);
121  void expand(Vertices);
122  void expand_dyn(Vertices);
123  void _mcq(int*&, int&, bool);
124  void degree_sort(Vertices &R) { R.set_degrees(*this); R.sort(); }
125 public:
126 #ifdef DBG
127  void dbg_C() const {
128  for (int i=0; i < V.size(); i++) {
129  std::cout << "C["<< i << "] : ";
130  C[i].dbg_i();
131  }
132  }
133  void dbg_conn() const {
134  for (int i=0; i < V.size(); i++) {
135  for (int j=0; j < V.size(); j++) {
136  std::cout <<e[i][j];
137  }
138  std::cout<< std::endl;
139  }
140  }
141 #endif
142  Maxclique(const bool* const*, const int, const float=0.025);
143  int steps() const { return pk; }
144  void mcq(int* &maxclique, int &sz) { _mcq(maxclique, sz, false); }
145  void mcqdyn(int* &maxclique, int &sz) { _mcq(maxclique, sz, true); }
147  if (C) delete [] C;
148  if (S) delete [] S;
149  V.dispose();
150  };
151 };
152 
153 Maxclique::Maxclique (const bool* const* conn, const int sz, const float tt) : pk(0), level(1), Tlimit(tt), V(sz), Q(sz), QMAX(sz) {
154  assert(conn!=0 && sz>0);
155  for (int i=0; i < sz; i++) V.push(i);
156  e = conn;
157  C = new ColorClass[sz + 1];
158  for (int i=0; i < sz + 1; i++) C[i].init(sz + 1);
159  S = new StepCount[sz + 1];
160 }
161 
162 void Maxclique::_mcq(int* &maxclique, int &sz, bool dyn) {
163  V.set_degrees(*this);
164  V.sort();
165  V.init_colors();
166  if (dyn) {
167  for (int i=0; i < V.size() + 1; i++) {
168  S[i].set_i1(0);
169  S[i].set_i2(0);
170  }
171  expand_dyn(V);
172  }
173  else
174  expand(V);
175  maxclique = new int[QMAX.size()];
176  for (int i=0; i<QMAX.size(); i++) {
177  maxclique[i] = QMAX.at(i);
178  }
179  sz = QMAX.size();
180 }
181 
182 void Maxclique::Vertices::init_colors() {
183  const int max_degree = v[0].get_degree();
184  for (int i = 0; i < max_degree; i++)
185  v[i].set_degree(i + 1);
186  for (int i = max_degree; i < sz; i++)
187  v[i].set_degree(max_degree + 1);
188 }
189 
190 void Maxclique::Vertices::set_degrees(Maxclique &m) {
191  for (int i=0; i < sz; i++) {
192  int d = 0;
193  for (int j=0; j < sz; j++)
194  if (m.connection(v[i].get_i(), v[j].get_i())) d++;
195  v[i].set_degree(d);
196  }
197 }
198 
199 bool Maxclique::cut1(const int pi, const ColorClass &A) {
200  for (int i = 0; i < A.size(); i++)
201  if (connection(pi, A.at(i)))
202  return true;
203  return false;
204 }
205 
206 void Maxclique::cut2(const Vertices &A, Vertices &B) {
207  for (int i = 0; i < A.size() - 1; i++) {
208  if (connection(A.end().get_i(), A.at(i).get_i()))
209  B.push(A.at(i).get_i());
210  }
211 }
212 
213 void Maxclique::color_sort(Vertices &R) {
214  int j = 0;
215  int maxno = 1;
216  int min_k = QMAX.size() - Q.size() + 1;
217  C[1].rewind();
218  C[2].rewind();
219  int k = 1;
220  for (int i=0; i < R.size(); i++) {
221  int pi = R.at(i).get_i();
222  k = 1;
223  while (cut1(pi, C[k]))
224  k++;
225  if (k > maxno) {
226  maxno = k;
227  C[maxno + 1].rewind();
228  }
229  C[k].push(pi);
230  if (k < min_k) {
231  R.at(j++).set_i(pi);
232  }
233  }
234  if (j > 0) R.at(j-1).set_degree(0);
235  if (min_k <= 0) min_k = 1;
236  for (k = min_k; k <= maxno; k++)
237  for (int i = 0; i < C[k].size(); i++) {
238  R.at(j).set_i(C[k].at(i));
239  R.at(j++).set_degree(k);
240  }
241 }
242 
243 void Maxclique::expand(Vertices R) {
244  while (R.size()) {
245  if (Q.size() + R.end().get_degree() > QMAX.size()) {
246  Q.push(R.end().get_i());
247  Vertices Rp(R.size());
248  cut2(R, Rp);
249  if (Rp.size()) {
250  color_sort(Rp);
251  pk++;
252  expand(Rp);
253  }
254  else if (Q.size() > QMAX.size()) {
255  qDebug() << "step = " << pk << " current max. clique size = " << Q.size();
256  QMAX = Q;
257  }
258  Rp.dispose();
259  Q.pop();
260  }
261  else {
262  return;
263  }
264  R.pop();
265  }
266 }
267 
268 void Maxclique::expand_dyn(Vertices R) {
269  S[level].set_i1(S[level].get_i1() + S[level - 1].get_i1() - S[level].get_i2());
270  S[level].set_i2(S[level - 1].get_i1());
271  while (R.size()) {
272  if (Q.size() + R.end().get_degree() > QMAX.size()) {
273  Q.push(R.end().get_i());
274  Vertices Rp(R.size());
275  cut2(R, Rp);
276  if (Rp.size()) {
277  if ((float)S[level].get_i1()/++pk < Tlimit) {
278  degree_sort(Rp);
279  }
280  color_sort(Rp);
281  S[level].inc_i1();
282  level++;
283  expand_dyn(Rp);
284  level--;
285  }
286  else if (Q.size() > QMAX.size()) {
287  std::cout << "step = " << pk << " current max. clique size = " << Q.size() << std::endl;
288  QMAX = Q;
289  }
290  Rp.dispose();
291  Q.pop();
292  }
293  else {
294  return;
295  }
296  R.pop();
297  }
298 }
299 
300 #endif
~Maxclique()
Definition: mcqd.h:146
level
Definition: DependencyCollector.py:25
Maxclique(const bool *const *, const int, const float=0.025)
Definition: mcqd.h:153
int steps() const
Definition: mcqd.h:143
void mcq(int *&maxclique, int &sz)
Definition: mcqd.h:144
Definition: mcqd.h:39
void mcqdyn(int *&maxclique, int &sz)
Definition: mcqd.h:145