├── COPYING
├── LICENSE
├── README.md
├── data.tar.gz
├── makefile
├── src
├── Algorithm.cpp
├── Algorithm.h
├── ArraySet.h
├── CliqueColoringStrategy.cpp
├── CliqueColoringStrategy.h
├── CliqueTools.cpp
├── CliqueTools.h
├── ColoringStrategy.h
├── DegeneracyTools.cpp
├── DegeneracyTools.h
├── GraphTools.cpp
├── GraphTools.h
├── IndependentSetColoringStrategy.cpp
├── IndependentSetColoringStrategy.h
├── MCQ.cpp
├── MCQ.h
├── MCR.cpp
├── MCR.h
├── MCS.cpp
├── MCS.h
├── MISQ.cpp
├── MISQ.h
├── MISR.cpp
├── MISR.h
├── MISS.cpp
├── MISS.h
├── MaxSubgraphAlgorithm.cpp
├── MaxSubgraphAlgorithm.h
├── MemoryManager.cpp
├── MemoryManager.h
├── OrderingTools.cpp
├── OrderingTools.h
├── Set.h
├── SparseArraySet.h
├── SparseCliqueColoringStrategy.cpp
├── SparseCliqueColoringStrategy.h
├── SparseIndependentSetColoringStrategy.cpp
├── SparseIndependentSetColoringStrategy.h
├── StaticOrderMCS.cpp
├── StaticOrderMCS.h
├── StaticOrderMISS.cpp
├── StaticOrderMISS.h
├── Tools.cpp
├── Tools.h
└── main.cpp
├── test_all.sh
└── test_fast.sh
/README.md:
--------------------------------------------------------------------------------
1 | # **Open MCS**: An open implementation of the MC family of clique solvers
2 |
3 | [](http://www.gnu.org/licenses/)
4 |
5 | The intent of this software is to provide an open, faithful, and competetive implementation of the
6 | MC family of maximum clique algorithms, as described in the following papers.
7 |
8 | ###MCQ
9 |
10 | *An efficient branch-and-bound algorithm for finding a maximum clique*,
11 | **Etsuji Tomita and Tomokazu Seki**,
12 | Proceedings of Discrete Mathematics and Theoretical Computer Science. LNCS 2731, pp. 278–289, 2003.
13 | [doi:10.1007/3-540-45066-1_22](https://doi.org/10.1007/3-540-45066-1_22)
14 |
15 | ###MCR
16 |
17 | *An efficient branch-and-bound algorithm for finding a maximum clique with computational experiments*,
18 | **Etsuji Tomita and Toshikatsu Kameda**,
19 | Journal of Global Optimization, **37**:95--111, 2007.
20 | [doi:10.1007/s10898-006-9039-7](https://doi.org/10.1007/s10898-006-9039-7)
21 |
22 | and
23 |
24 | ###MCS (including version with static vertex ordering)
25 |
26 | *A simple and faster branch-and-bound algorithm for finding a maximum clique*,
27 | **Etsuji Tomita, Yoichi Sutani, Takanori Higashi, Shinya Takahashi, and Mitsuo Wakatsuki**,
28 | Proceedings of WALCOM 2010, LNCS 5942, pp. 191–203, 2010.
29 | [doi:10.1007/978-3-642-20662-7_31](https://doi.org/10.1007/978-3-642-20662-7_31)
30 |
31 | ##This package includes:
32 |
33 | - C++ code for implementations of MCQ, MCR, and MCS clique algorithms, and their independent set equivalents.
34 | - The 2nd DIMACS Challenge instances used in the original experiments for these algorithms. (in ./data/)
35 | - Test scripts to build and run MCS on all data sets (./test_all.sh and ./test_fast.sh)
36 |
37 | Please feel free to contact me with any questions!
38 |
39 | ### Version
40 | 1.0
41 |
42 | ### Building
43 |
44 | ```sh
45 | $ git clone https://github.com/darrenstrash/open-mcs.git
46 | $ cd open-mcs
47 | $ make
48 | ```
49 |
50 | ### Running
51 | ```sh
52 | $ ./bin/open-mcs --input-file= [--compute-independent-set] --algorithm=
53 | ```
54 |
55 | or
56 |
57 | ```sh
58 | $ ./test_all.sh
59 | ```
60 |
61 | to run MCS on all (2nd DIMACS Challenge) data sets.
62 |
63 | Should you not want to wait the day or so it takes to run all graphs, consider running
64 | on a smaller subset, such as with the command
65 |
66 | ```sh
67 | $ ./test_fast.sh
68 | ```
69 |
70 | , which takes about 30 seconds.
71 |
72 | ### Graph Format
73 |
74 | Currently, the unweighted METIS format is expected:
75 |
76 | <# vertices> <# edges> 1
77 |
78 | followed by <#vertices> lines, where the i-th line contains
79 | a list of space-separated neighbors of i. All vertices range from 1 to <# vertices>
80 |
81 |
82 | ### Data
83 |
84 | data.tar.gz contains the data sets from the 2nd DIMACS Challenge.
85 |
86 | Copyright
87 | ----
88 |
89 | Copyright (c) 2016 Darren Strash.
90 |
91 | License
92 | ----
93 |
94 | This code is released under the GNU Public License (GPL) 3.0.
95 |
96 | To read the GPL 3.0, read the file COPYING in this directory.
97 |
98 | This program is free software: you can redistribute it and/or modify
99 | it under the terms of the GNU General Public License as published by
100 | the Free Software Foundation, either version 3 of the License, or
101 | (at your option) any later version.
102 |
103 | This program is distributed in the hope that it will be useful,
104 | but WITHOUT ANY WARRANTY; without even the implied warranty of
105 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
106 | GNU General Public License for more details.
107 |
108 | You should have received a copy of the GNU General Public License
109 | along with this program. If not, see
110 |
111 | Contact
112 | ----
113 |
114 | **Darren Strash** (first name DOT last name AT gmail DOT com)
115 |
--------------------------------------------------------------------------------
/data.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darrenstrash/open-mcs/735788af066fc8589f577036af521f22f45c2731/data.tar.gz
--------------------------------------------------------------------------------
/makefile:
--------------------------------------------------------------------------------
1 |
2 | BUILD_DIR = build
3 | SRC_DIR = src
4 | BIN_DIR = bin
5 |
6 | CFLAGS = -Winline -O2 -std=c++0x -g
7 | #CFLAGS = -Winline -DDEBUG_MESSAGE -O0 -std=c++0x -g
8 |
9 | SOURCES_TMP += MaxSubgraphAlgorithm.cpp
10 | SOURCES_TMP += SparseIndependentSetColoringStrategy.cpp
11 | SOURCES_TMP += MISS.cpp
12 | SOURCES_TMP += StaticOrderMISS.cpp
13 | SOURCES_TMP += MISR.cpp
14 | SOURCES_TMP += MISQ.cpp
15 | SOURCES_TMP += OrderingTools.cpp
16 | SOURCES_TMP += MCS.cpp
17 | SOURCES_TMP += StaticOrderMCS.cpp
18 | SOURCES_TMP += MCR.cpp
19 | SOURCES_TMP += MCQ.cpp
20 | SOURCES_TMP += SparseCliqueColoringStrategy.cpp
21 | SOURCES_TMP += IndependentSetColoringStrategy.cpp
22 | SOURCES_TMP += CliqueColoringStrategy.cpp
23 | SOURCES_TMP += CliqueTools.cpp
24 | SOURCES_TMP += GraphTools.cpp
25 | SOURCES_TMP += MemoryManager.cpp
26 | SOURCES_TMP += Algorithm.cpp
27 | SOURCES_TMP += DegeneracyTools.cpp
28 | SOURCES_TMP += Tools.cpp
29 |
30 | SOURCES=$(addprefix $(SOURCES_DIR)/, $(SOURCES_TMP))
31 |
32 | OBJECTS_TMP=$(SOURCES_TMP:.cpp=.o)
33 | OBJECTS=$(addprefix $(BUILD_DIR)/, $(OBJECTS_TMP))
34 |
35 | DEPFILES_TMP:=$(SOURCES_TMP:.cpp=.d)
36 | DEPFILES=$(addprefix $(BUILD_DIR)/, $(DEPFILES_TMP))
37 |
38 | EXEC_NAMES = open-mcs
39 |
40 | EXECS = $(addprefix $(BIN_DIR)/, $(EXEC_NAMES))
41 |
42 | #DEFINE += -DDEBUG #for debugging
43 | #DEFINE += -DMEMORY_DEBUG #for memory debugging.
44 |
45 | #some systems handle malloc and calloc with 0 bytes strangely.
46 | DEFINE += -DALLOW_ALLOC_ZERO_BYTES# used by Eppstein and Strash (2011)
47 |
48 | VPATH = src
49 |
50 | .PHONY : all
51 |
52 | all: $(EXECS)
53 |
54 | .PHONY : clean
55 |
56 | clean:
57 | rm -rf $(EXECS) $(BUILD_DIR) $(BIN_DIR)
58 |
59 | $(BIN_DIR)/open-mcs: main.cpp ${OBJECTS} | ${BIN_DIR}
60 | g++ $(CFLAGS) ${DEFINE} ${OBJECTS} $(SRC_DIR)/main.cpp -o $@
61 |
62 | $(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h $(BUILD_DIR)/%.d | $(BUILD_DIR)
63 | g++ $(CFLAGS) ${DEFINE} -c $< -o $@
64 |
65 | $(BUILD_DIR)/%.d: $(SRC_DIR)/%.cpp | $(BUILD_DIR)
66 | g++ $(CFLAGS) -MM -MT '$(patsubst $(SRC_DIR)/%.cpp,$(BUILD_DIR)/%.o,$<)' $< -MF $@
67 |
68 | $(BUILD_DIR):
69 | mkdir -p $(BUILD_DIR)
70 |
71 | $(BIN_DIR):
72 | mkdir -p $(BIN_DIR)
73 |
74 |
--------------------------------------------------------------------------------
/src/Algorithm.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License as published by
4 | the Free Software Foundation, either version 3 of the License, or
5 | (at your option) any later version.
6 |
7 | This program is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 |
12 | You should have received a copy of the GNU General Public License
13 | along with this program. If not, see
14 | */
15 |
16 | #include "Algorithm.h"
17 |
18 | // system includes
19 | #include
20 |
21 | using namespace std;
22 |
23 | Algorithm::Algorithm(std::string const &name)
24 | : m_sName(name)
25 | , m_bQuiet(false)
26 | , m_vCallBacks()
27 | {
28 | }
29 |
30 | Algorithm::~Algorithm()
31 | {
32 | }
33 |
34 | void Algorithm::AddCallBack(std::function const&)> callback)
35 | {
36 | m_vCallBacks.push_back(callback);
37 | }
38 |
39 | void Algorithm::ExecuteCallBacks(std::list const &vertexSet) const
40 | {
41 | for (auto &function : m_vCallBacks) {
42 | function(vertexSet);
43 | }
44 | }
45 |
46 | void Algorithm::SetName(string const &name)
47 | {
48 | m_sName = name;
49 | }
50 |
51 | string Algorithm::GetName() const
52 | {
53 | return m_sName;
54 | }
55 |
56 | void Algorithm::SetQuiet(bool const quiet)
57 | {
58 | m_bQuiet = quiet;
59 | }
60 |
61 | bool Algorithm::GetQuiet() const
62 | {
63 | return m_bQuiet;
64 | }
65 |
--------------------------------------------------------------------------------
/src/Algorithm.h:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License as published by
4 | the Free Software Foundation, either version 3 of the License, or
5 | (at your option) any later version.
6 |
7 | This program is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 |
12 | You should have received a copy of the GNU General Public License
13 | along with this program. If not, see
14 | */
15 |
16 | #ifndef ALGORITHM_H
17 | #define ALGORITHM_H
18 |
19 | // system includes
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | class Algorithm
26 | {
27 | public:
28 | Algorithm(std::string const &name);
29 | virtual ~Algorithm();
30 |
31 | virtual long Run(std::list> &cliques) = 0;
32 | virtual void Run() {}
33 |
34 | void SetName(std::string const &name);
35 | std::string GetName() const;
36 |
37 | void AddCallBack(std::function const&)> callback);
38 |
39 | void ExecuteCallBacks(std::list const &vertexSet) const;
40 |
41 | void SetQuiet(bool const quiet);
42 | bool GetQuiet() const;
43 |
44 | private:
45 | std::string m_sName;
46 | bool m_bQuiet;
47 | std::vector const&)>> m_vCallBacks;
48 | };
49 |
50 | #endif //ALGORITHM_H
51 |
--------------------------------------------------------------------------------
/src/ArraySet.h:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License as published by
4 | the Free Software Foundation, either version 3 of the License, or
5 | (at your option) any later version.
6 |
7 | This program is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 |
12 | You should have received a copy of the GNU General Public License
13 | along with this program. If not, see
14 | */
15 |
16 | #ifndef ARRAY_SET_H
17 | #define ARRAY_SET_H
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | class ArraySet
26 | {
27 | public:
28 | ArraySet(size_t const size) : m_Lookup(size, -1), m_Elements(size, -1), m_iBegin(0), m_iEnd(-1), m_States(0), m_bInserted(false), m_bRemoved(false)
29 | {
30 | }
31 |
32 | ArraySet() : m_Lookup(), m_Elements(), m_iBegin(0), m_iEnd(-1), m_States(0), m_bInserted(false), m_bRemoved(false)
33 | {
34 | }
35 |
36 | ~ArraySet() {}
37 |
38 | void Resize(size_t const size)
39 | {
40 | m_Lookup.resize(size, -1);
41 | m_Elements.resize(size, -1);
42 | }
43 |
44 | void InitializeFromAdjacencyArray(std::vector> const &adjacencyArray, int const vertex)
45 | {
46 | Resize(adjacencyArray.size());
47 | for (int const neighbor : adjacencyArray[vertex]) {
48 | Insert(neighbor);
49 | }
50 | }
51 |
52 | void PrintSummary() const
53 | {
54 | std::cout << "Array[" << m_iBegin << ":" << m_iEnd << "] : ";
55 | for (int const p : *this) {
56 | std::cout << p << (Contains(p)? "":"<-inconsistency") << " ";
57 | }
58 | std::cout << std::endl;
59 | }
60 |
61 | bool Contains(int const x) const {
62 | if (x < 0 || x >= m_Lookup.size()) return false;
63 | int const locationX(m_Lookup[x]);
64 | return locationX >= m_iBegin && locationX <= m_iEnd;
65 | }
66 |
67 | // Inserts are not allowed after saving state, as it is currently not supported.
68 | void Insert(int const x) {
69 | //// if (x==107) std::cout << "Inserting vertex " << x << " into graph." << std::endl << std::flush;
70 | if (Contains(x)) return;
71 | assert(!m_bRemoved); // not allowed to insert and remove when saving states
72 | if (!m_States.empty()) m_bInserted = true;
73 | if (m_Elements[m_iEnd+1] != -1 && !Contains(m_Elements[m_iEnd+1])) // if not a reinserted element, overwrite its lookup.
74 | m_Lookup[m_Elements[m_iEnd+1]] = -1;
75 | m_iEnd++;
76 | m_Lookup[x] = m_iEnd;
77 | m_Elements[m_iEnd] = x;
78 | }
79 |
80 | void Remove(int const x) {
81 | //// if (x==107) std::cout << "Removing vertex " << x << " from graph." << std::endl << std::flush;
82 | if (!Contains(x)) return;
83 | assert(!m_bInserted); // not allowed to insert and remove when saving states
84 | if (!m_States.empty()) m_bRemoved = true;
85 | int const locationX(m_Lookup[x]);
86 | m_Elements[locationX] = m_Elements[m_iEnd];
87 | m_Lookup[m_Elements[locationX]] = locationX;
88 | m_Lookup[x] = m_iEnd;
89 | m_Elements[m_iEnd] = x;
90 | m_iEnd--;
91 | }
92 |
93 | void MoveTo(int const x, ArraySet &other) {
94 | Remove(x);
95 | other.Insert(x);
96 | }
97 |
98 | size_t Size() const { return m_iEnd - m_iBegin + 1; }
99 | bool Empty() const { return m_iEnd < m_iBegin; }
100 |
101 | std::vector::iterator begin() { return m_Elements.begin() + m_iBegin; }
102 | std::vector::iterator end() { return m_Elements.begin() + m_iEnd + 1; }
103 |
104 | std::vector::const_iterator begin() const { return m_Elements.begin() + m_iBegin; }
105 | std::vector::const_iterator end() const { return m_Elements.begin() + m_iEnd + 1; }
106 |
107 | int At(size_t const index) const
108 | {
109 | return m_Elements[index];
110 | }
111 |
112 | int operator[](size_t const index) const { return At(index); }
113 |
114 | void SaveState()
115 | {
116 | //// std::cout << "Saving State" << std::endl << std::flush;
117 | m_States.push_back(std::make_pair(m_iBegin, m_iEnd));
118 | }
119 |
120 | void RestoreState()
121 | {
122 | //// std::cout << "Restoring State" << std::endl << std::flush;
123 | std::pair const &range(m_States.back());
124 | m_iBegin = range.first;
125 | m_iEnd = range.second;
126 | m_States.pop_back();
127 | //// std::cout << "#States = " << m_States.size() << std::endl << std::flush;
128 | if (m_States.empty()) {
129 | m_bRemoved = false;
130 | m_bInserted = false;
131 | }
132 | }
133 |
134 | void Clear()
135 | {
136 | m_iBegin = 0;
137 | m_iEnd = -1;
138 | }
139 |
140 | bool operator==(ArraySet const &that) const
141 | {
142 | if (Size() != that.Size()) return false;
143 | for (int const value : *this) {
144 | if (!that.Contains(value)) return false;
145 | }
146 | return true;
147 | }
148 |
149 | bool operator!=(ArraySet const &that) const
150 | {
151 | return !(*this == that);
152 | }
153 |
154 | static bool Test() {
155 | std::cout << "ArraySet: ";
156 | ArraySet testSet(3);
157 | testSet.Insert(0);
158 | testSet.Insert(1);
159 | testSet.Insert(2);
160 |
161 | if (!testSet.Contains(0) || !testSet.Contains(1) || !testSet.Contains(2) || testSet.Size() != 3) {
162 | std::cout << "FAILED: ArraySet failed ContainsTest" << std::endl;
163 | return false;
164 | }
165 |
166 | testSet.Remove(0);
167 | if (testSet.Contains(0) || testSet.Size() != 2) {
168 | std::cout << "FAILED: ArraySet failed RemoveFirst Test" << std::endl;
169 | return false;
170 | }
171 |
172 | testSet.Insert(0);
173 | if (!testSet.Contains(0) || !testSet.Contains(1) || !testSet.Contains(2) || testSet.Size() != 3) {
174 | std::cout << "FAILED: ArraySet failed RemoveAdd Test" << std::endl;
175 | return false;
176 | }
177 |
178 | testSet.Remove(0);
179 | if (testSet.Contains(0) || testSet.Size() != 2) {
180 | std::cout << "FAILED: ArraySet failed RemoveLast Test" << std::endl;
181 | return false;
182 | }
183 |
184 | testSet.Insert(0);
185 | testSet.Remove(1);
186 | if (testSet.Contains(1) || testSet.Size() != 2) {
187 | std::cout << "FAILED: ArraySet failed RemoveMiddle Test" << std::endl;
188 | return false;
189 | }
190 |
191 | testSet.Insert(1);
192 | testSet.Remove(1);
193 | testSet.Remove(2);
194 | testSet.Remove(0);
195 | if (testSet.Contains(0) || testSet.Contains(1) || testSet.Contains(2) || testSet.Size() != 0 || !testSet.Empty()) {
196 | std::cout << "FAILED: ArraySet failed RemoveAll Test" << std::endl;
197 | return false;
198 | }
199 |
200 | testSet.Insert(0);
201 | testSet.Insert(1);
202 | testSet.Insert(2);
203 | if (!testSet.Contains(0) || !testSet.Contains(1) || !testSet.Contains(2) || testSet.Size() != 3) {
204 | std::cout << "FAILED: ArraySet failed InsertAll Test" << std::endl;
205 | return false;
206 | }
207 |
208 | testSet.SaveState();
209 | if (!testSet.Contains(0) || !testSet.Contains(1) || !testSet.Contains(2) || testSet.Size() != 3) {
210 | std::cout << "FAILED: ArraySet failed SaveState Test" << std::endl;
211 | return false;
212 | }
213 |
214 | testSet.Remove(0);
215 | if (testSet.Contains(0) || !testSet.Contains(1) || !testSet.Contains(2) || testSet.Size() != 2) {
216 | std::cout << "FAILED: ArraySet failed RemoveAfterSave Test" << std::endl;
217 | return false;
218 | }
219 |
220 | testSet.RestoreState();
221 | if (!testSet.Contains(0) || !testSet.Contains(1) || !testSet.Contains(2) || testSet.Size() != 3) {
222 | std::cout << "FAILED: ArraySet failed RestoreState Test" << std::endl;
223 | return false;
224 | }
225 |
226 | std::cout << "PASSED!" << std::endl << std::flush;
227 | return true;
228 | }
229 |
230 | private:
231 | std::vector m_Lookup;
232 | std::vector m_Elements;
233 | int m_iBegin;
234 | int m_iEnd;
235 | std::vector> m_States;
236 | bool m_bInserted;
237 | bool m_bRemoved;
238 | };
239 |
240 | #endif // ARRAY_SET_H
241 |
--------------------------------------------------------------------------------
/src/CliqueColoringStrategy.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License as published by
4 | the Free Software Foundation, either version 3 of the License, or
5 | (at your option) any later version.
6 |
7 | This program is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 |
12 | You should have received a copy of the GNU General Public License
13 | along with this program. If not, see
14 | */
15 |
16 | #include "CliqueColoringStrategy.h"
17 | #include "DegeneracyTools.h"
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | using namespace std;
25 |
26 | CliqueColoringStrategy::CliqueColoringStrategy(vector> const &adjacencyMatrix) : ColoringStrategy(), m_AdjacencyMatrix(adjacencyMatrix), m_vvVerticesWithColor()////, m_Colors(adjacencyList.size(), -1) , m_VertexOrder()
27 | {
28 | m_vvVerticesWithColor.resize(adjacencyMatrix.size());
29 | for (vector vVertices : m_vvVerticesWithColor) {
30 | vVertices.reserve(adjacencyMatrix.size());
31 | }
32 | //// m_VertexOrder = std::move(GetVerticesInDegeneracyOrder(adjacencyList));
33 | }
34 |
35 | void CliqueColoringStrategy::Color(vector> const &adjacencyMatrix, vector const &vVertexOrder, vector &vVerticesToReorder, vector &vColors)
36 | {
37 | if (vVertexOrder.empty()) return;
38 |
39 | #if 0
40 | cout << "Coloring (in ): ";
41 | //// for (int const vertex : vVerticesToReorder) {
42 | for (int index = 0; index < vVerticesToReorder.size(); index++) {
43 | int const vertex(vVerticesToReorder[index]);
44 | cout << vertex << "(" << vColors[index] << ") ";
45 | }
46 | cout << endl;
47 | #endif // 0
48 |
49 | size_t maxColor(0);
50 |
51 | size_t const numVerticesToReorder(vVertexOrder.size());
52 |
53 | for (int const vertex : vVertexOrder) {
54 | size_t color = 0;
55 | for (vector const &verticesWithColor : m_vvVerticesWithColor) {
56 | bool hasNeighborWithColor(false);
57 | if (verticesWithColor.empty()) break;
58 | for (int const coloredVertex : verticesWithColor) {
59 | // can be made more efficient?
60 | hasNeighborWithColor = adjacencyMatrix[vertex][coloredVertex];
61 | if (hasNeighborWithColor) {
62 | color++;
63 | break;
64 | }
65 | }
66 |
67 | if (!hasNeighborWithColor) {
68 | break;
69 | }
70 | }
71 |
72 | m_vvVerticesWithColor[color].push_back(vertex);
73 | maxColor = max(maxColor, color);
74 | }
75 |
76 | //// cout << "maxColor=" << maxColor << ", numVertices=" << vVerticesToReorder.size() << endl;
77 |
78 | //// vColors.resize(vVertexOrder.size());
79 | //// vVerticesToReorder.resize(vVertexOrder.size());
80 |
81 | int currentIndex(0);
82 | int currentColor(0);
83 | for (int currentColor = 0; currentColor <= maxColor; ++currentColor) {
84 | for (int const vertex : m_vvVerticesWithColor[currentColor]) {
85 | vVerticesToReorder[currentIndex] = vertex;
86 | vColors[currentIndex] = currentColor+1;
87 | currentIndex++;
88 | }
89 | m_vvVerticesWithColor[currentColor].clear();
90 | }
91 |
92 |
93 | #if 0
94 | cout << "Coloring (out): ";
95 | for (int index = 0; index < vVerticesToReorder.size(); index++) {
96 | int const vertex(vVerticesToReorder[index]);
97 | cout << vertex << "(" << vColors[index] << ") ";
98 | }
99 | cout << endl;
100 | #endif // 0
101 |
102 | // verify that it is a valid coloring.
103 | #ifdef DEBUG
104 | vector vColor(adjacencyList.size(), -1);
105 | for (size_t index = 0; index < vVerticesToReorder.size(); ++index) {
106 | vColor[vVerticesToReorder[index]] = vColors[index];
107 | }
108 | for (int const vertex : vVerticesToReorder) {
109 | for (int const neighbor : adjacencyList[vertex]) {
110 | if (vColor[vertex] == vColor[neighbor]) {
111 | cout << "Consistency Error: vertex " << vertex << " has the same color as neighbor " << neighbor << ", color=" << vColor[vertex] << endl << flush;
112 | }
113 | }
114 | }
115 | #endif // DEBUG
116 | }
117 |
118 | void CliqueColoringStrategy::Recolor(vector> const &adjacencyMatrix, vector const &vVertexOrder, vector &vVerticesToReorder, vector &vColors, int const currentBestCliqueSize, int const currentCliqueSize)
119 | {
120 | if (vVerticesToReorder.empty()) return;
121 |
122 | #if 0
123 | cout << "Coloring (in ): ";
124 | //// for (int const vertex : vVerticesToReorder) {
125 | for (int index = 0; index < vVerticesToReorder.size(); index++) {
126 | int const vertex(vVerticesToReorder[index]);
127 | cout << vertex << "(" << vColors[index] << ") ";
128 | }
129 | cout << endl;
130 | #endif // 0
131 |
132 | size_t maxColor(0);
133 |
134 | int iBestCliqueDelta(currentBestCliqueSize - currentCliqueSize);
135 |
136 | size_t const numVerticesToReorder(vVerticesToReorder.size());
137 |
138 | for (int const vertex : vVertexOrder) {
139 | size_t color = 0;
140 | for (vector const &verticesWithColor : m_vvVerticesWithColor) {
141 | bool hasNeighborWithColor(false);
142 | if (verticesWithColor.empty()) break;
143 | for (int const coloredVertex : verticesWithColor) {
144 | // can be made more efficient?
145 | hasNeighborWithColor = adjacencyMatrix[vertex][coloredVertex];
146 | if (hasNeighborWithColor) {
147 | color++;
148 | break;
149 | }
150 | }
151 |
152 | if (!hasNeighborWithColor) {
153 | break;
154 | }
155 | }
156 |
157 | m_vvVerticesWithColor[color].push_back(vertex);
158 | maxColor = max(maxColor, color);
159 | #ifdef PROSSER
160 | if (color+1 > iBestCliqueDelta && m_vvVerticesWithColor[color].size() == 1 && Repair(vertex,color, iBestCliqueDelta)) {
161 | maxColor--;
162 | }
163 | #else
164 | if (color+1 > iBestCliqueDelta && /*m_vvVerticesWithColor[color].size() == 1*/ color == maxColor) {
165 | Repair(vertex, color, iBestCliqueDelta);
166 | if (m_vvVerticesWithColor[maxColor].empty())
167 | maxColor--;
168 | }
169 | #endif // PROSSER
170 | }
171 |
172 | //// cout << "maxColor=" << maxColor << ", numVertices=" << vVerticesToReorder.size() << endl;
173 |
174 | int currentIndex(0);
175 | int currentColor(0);
176 | for (int currentColor = 0; currentColor <= maxColor; ++currentColor) {
177 | for (int const vertex : m_vvVerticesWithColor[currentColor]) {
178 | vVerticesToReorder[currentIndex] = vertex;
179 | vColors[currentIndex] = currentColor+1;
180 | currentIndex++;
181 | }
182 | m_vvVerticesWithColor[currentColor].clear();
183 | }
184 |
185 | #if 0
186 | cout << "Coloring (out): ";
187 | for (int index = 0; index < vVerticesToReorder.size(); index++) {
188 | int const vertex(vVerticesToReorder[index]);
189 | cout << vertex << "(" << vColors[index] << ") ";
190 | }
191 | cout << endl;
192 | #endif // 0
193 |
194 | // verify that it is a valid coloring.
195 | #ifdef DEBUG
196 | vector vColor(adjacencyList.size(), -1);
197 | for (size_t index = 0; index < vVerticesToReorder.size(); ++index) {
198 | vColor[vVerticesToReorder[index]] = vColors[index];
199 | }
200 | for (int const vertex : vVerticesToReorder) {
201 | for (int const neighbor : adjacencyList[vertex]) {
202 | if (vColor[vertex] == vColor[neighbor]) {
203 | cout << "Consistency Error: vertex " << vertex << " has the same color as neighbor " << neighbor << ", color=" << vColor[vertex] << endl << flush;
204 | }
205 | }
206 | }
207 | #endif // DEBUG
208 | }
209 |
210 | bool CliqueColoringStrategy::HasConflict(int const vertex, vector const &vVerticesWithColor)
211 | {
212 | if (vVerticesWithColor.empty()) return false;
213 | for (int const coloredVertex : vVerticesWithColor) {
214 | // can be made more efficient?
215 | if (m_AdjacencyMatrix[vertex][coloredVertex]) {
216 | return true;
217 | }
218 | }
219 |
220 | return false;
221 | }
222 |
223 | int CliqueColoringStrategy::GetConflictingVertex(int const vertex, vector const &vVerticesWithColor)
224 | {
225 | int conflictingVertex(-1);
226 | int count(0);
227 | for (int const candidateVertex : vVerticesWithColor) {
228 | if (m_AdjacencyMatrix[vertex][candidateVertex]) {
229 | conflictingVertex = candidateVertex;
230 | count++;
231 | if (count > 1) return -1;
232 | }
233 | }
234 | return conflictingVertex;
235 | }
236 |
237 | bool CliqueColoringStrategy::Repair(int const vertex, int const color, int const iBestCliqueDelta)
238 | {
239 | for (int newColor = 0; newColor <= iBestCliqueDelta-1; newColor++) {
240 | int const conflictingVertex(GetConflictingVertex(vertex, m_vvVerticesWithColor[newColor]));
241 | if (conflictingVertex < 0) continue;
242 | for (int nextColor = newColor+1; nextColor <= iBestCliqueDelta; nextColor++) {
243 | if (HasConflict(conflictingVertex, m_vvVerticesWithColor[nextColor])) continue;
244 | m_vvVerticesWithColor[color].erase(find(m_vvVerticesWithColor[color].begin(), m_vvVerticesWithColor[color].end(), vertex));
245 | m_vvVerticesWithColor[newColor].erase(find(m_vvVerticesWithColor[newColor].begin(), m_vvVerticesWithColor[newColor].end(), conflictingVertex));
246 | m_vvVerticesWithColor[newColor].push_back(vertex);
247 | m_vvVerticesWithColor[nextColor].push_back(conflictingVertex);
248 | //// cout << "Repairing vertices " << vertex << " and " << conflictingVertex << endl;
249 | return true;
250 | }
251 | }
252 | return false;
253 | }
254 |
--------------------------------------------------------------------------------
/src/CliqueColoringStrategy.h:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License as published by
4 | the Free Software Foundation, either version 3 of the License, or
5 | (at your option) any later version.
6 |
7 | This program is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 |
12 | You should have received a copy of the GNU General Public License
13 | along with this program. If not, see
14 | */
15 |
16 | #ifndef CLIQUE_COLORING_STRATEGY
17 | #define CLIQUE_COLORING_STRATEGY
18 |
19 | #include "ColoringStrategy.h"
20 |
21 | class CliqueColoringStrategy : public ColoringStrategy
22 | {
23 | public:
24 | CliqueColoringStrategy(std::vector> const &adjacencyMatrix);
25 | virtual void Color(std::vector> const &adjacencyMatrix, std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors);
26 | virtual void Recolor(std::vector> const &adjacencyMatrix, std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors, int const currentBestCliqueSize, int const currentCliqueSize);
27 | bool HasConflict(int const vertex, std::vector const &vVerticesWithColor);
28 | int GetConflictingVertex(int const vertex, std::vector const &vVerticesWithColor);
29 | bool Repair(int const vertex, int const color, int const iBestCliqueDelta);
30 | //// virtual void Recolor();
31 | //// virtual void RemoveVertex(int const vertex);
32 | //// virtual void PeekAtNextVertexAndColor(int &vertex, int &color);
33 | protected:
34 | std::vector> const &m_AdjacencyMatrix;
35 | std::vector> m_vvVerticesWithColor;
36 | //// std::vector m_Colors;
37 | //// std::vector m_VertexOrder;
38 | };
39 |
40 | #endif //CLIQUE_COLORING_STRATEGY
41 |
--------------------------------------------------------------------------------
/src/CliqueTools.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License as published by
4 | the Free Software Foundation, either version 3 of the License, or
5 | (at your option) any later version.
6 |
7 | This program is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 |
12 | You should have received a copy of the GNU General Public License
13 | along with this program. If not, see
14 | */
15 |
16 |
17 | // local includes
18 | #include "CliqueTools.h"
19 | #include "GraphTools.h"
20 |
21 | // system includes
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | using namespace std;
28 |
29 | bool CliqueTools::IsMaximalClique(vector> &adjacencyArray, list const&clique, bool const verbose)
30 | {
31 | size_t const cliqueSize(clique.size());
32 | vector vMarkedVertices(adjacencyArray.size(), false);
33 |
34 | for (int const vertex : clique) {
35 | vMarkedVertices[vertex] = true;
36 | }
37 |
38 | // first check that it is a clique
39 | #if 0
40 | for (int const vertex : clique) {
41 | size_t neighborsInClique(0)
42 | for (int const neighbor : adjacencyArray[vertex]) {
43 | if (vMarkedVertices[neighbor]) neighborsInClique++;
44 | }
45 | if (neighborsInClique != cliqueSize - 1) {
46 | if (verbose) {
47 | cout << "Maximal clique test failed: " << vertex << " is not in the clique!" << endl;
48 | }
49 | return false;
50 | }
51 | #else
52 | for (size_t vertex = 0; vertex < adjacencyArray.size(); ++vertex) {
53 | bool const inClique(vMarkedVertices[vertex]);
54 | size_t neighborsInClique(0);
55 | for (int const neighbor : adjacencyArray[vertex]) {
56 | if (vMarkedVertices[neighbor]) neighborsInClique++;
57 | }
58 |
59 | if (inClique && neighborsInClique != cliqueSize - 1) {
60 | if (verbose) {
61 | cout << "Maximal clique test failed: " << vertex << " should not be in clique!" << endl;
62 | }
63 | return false;
64 | }
65 |
66 | if (!inClique && neighborsInClique == cliqueSize) {
67 | if (verbose) {
68 | cout << "Maximal clique test failed: " << vertex << " can be added to clique!" << endl;
69 | }
70 | return false;
71 | }
72 | }
73 | #endif
74 | return true;
75 | }
76 |
77 | bool CliqueTools::IsClique(vector> &adjacencyMatrix, list const&clique, bool const verbose)
78 | {
79 | for (int const vertex : clique) {
80 | for (int const otherVertex : clique) {
81 | if (vertex == otherVertex) continue;
82 | if (!adjacencyMatrix[vertex][otherVertex]) {
83 | cout << "clique test failed: " << vertex << " should not be in the same set with " << otherVertex << endl << flush;
84 | return false;
85 | }
86 | }
87 | }
88 |
89 | return true;
90 | }
91 |
92 | bool CliqueTools::IsIndependentSet(vector> &adjacencyMatrix, list const&clique, bool const verbose)
93 | {
94 | for (int const vertex : clique) {
95 | for (int const otherVertex : clique) {
96 | if (vertex == otherVertex) continue;
97 | if (adjacencyMatrix[vertex][otherVertex]) {
98 | cout << "Independent set test failed: " << vertex << " should not be in the same set with " << otherVertex << endl << flush;
99 | return false;
100 | }
101 | }
102 | }
103 |
104 | return true;
105 | }
106 |
107 |
108 | bool CliqueTools::IsMaximalIndependentSet(vector> &adjacencyArray, list const &vertexSet, bool const verbose)
109 | {
110 | size_t const setSize(vertexSet.size());
111 | vector vMarkedVertices(adjacencyArray.size(), false);
112 |
113 | for (size_t const vertex : vertexSet) {
114 | vMarkedVertices[vertex] = true;
115 | }
116 |
117 | // first check that it is a clique
118 | #if 0
119 | for (int const vertex : clique) {
120 | size_t neighborsInClique(0)
121 | for (int const neighbor : adjacencyArray[vertex]) {
122 | if (vMarkedVertices[neighbor]) neighborsInClique++;
123 | }
124 | if (neighborsInClique != cliqueSize - 1) {
125 | if (verbose) {
126 | cout << "Maximal clique test failed: " << vertex << " is not in the clique!" << endl;
127 | }
128 | return false;
129 | }
130 | #else
131 | for (size_t vertex = 0; vertex < adjacencyArray.size(); ++vertex) {
132 | bool const inSet(vMarkedVertices[vertex]);
133 | size_t neighborsInSet(0);
134 | for (int const neighbor : adjacencyArray[vertex]) {
135 | if (vMarkedVertices[neighbor]) {
136 | neighborsInSet++;
137 | if (inSet) {
138 | cout << "Maximal independent set test failed: " << vertex << " should not be in set with neighbor " << neighbor << "!" << endl;
139 | }
140 | }
141 | }
142 |
143 | if (inSet && neighborsInSet != 0) {
144 | //// if (verbose) {
145 | //// cout << "Maximal independent set test failed: " << vertex << " should not be in set!" << endl;
146 | //// }
147 | return false;
148 | }
149 |
150 | if (!inSet && neighborsInSet == 0) {
151 | if (verbose) {
152 | cout << "Maximal independent set test failed: " << vertex << " can be added to set!" << endl;
153 | }
154 | return false;
155 | }
156 | }
157 | #endif
158 | return true;
159 | }
160 |
161 | bool CliqueTools::IsIndependentSet(vector> &adjacencyArray, list const &vertexSet, bool const verbose)
162 | {
163 | size_t const setSize(vertexSet.size());
164 | vector vMarkedVertices(adjacencyArray.size(), false);
165 |
166 | for (size_t const vertex : vertexSet) {
167 | vMarkedVertices[vertex] = true;
168 | }
169 |
170 | // first check that it is a clique
171 | #if 0
172 | for (int const vertex : clique) {
173 | size_t neighborsInClique(0)
174 | for (int const neighbor : adjacencyArray[vertex]) {
175 | if (vMarkedVertices[neighbor]) neighborsInClique++;
176 | }
177 | if (neighborsInClique != cliqueSize - 1) {
178 | if (verbose) {
179 | cout << "Maximal clique test failed: " << vertex << " is not in the clique!" << endl;
180 | }
181 | return false;
182 | }
183 | #else
184 | for (size_t vertex = 0; vertex < adjacencyArray.size(); ++vertex) {
185 | bool const inSet(vMarkedVertices[vertex]);
186 | size_t neighborsInSet(0);
187 | for (int const neighbor : adjacencyArray[vertex]) {
188 | if (vMarkedVertices[neighbor]) {
189 | neighborsInSet++;
190 | if (inSet) {
191 | cout << "Maximal independent set test failed: " << vertex << " should not be in set with neighbor " << neighbor << "!" << endl;
192 | }
193 | }
194 | }
195 |
196 | if (inSet && neighborsInSet != 0) {
197 | //// if (verbose) {
198 | //// cout << "Maximal independent set test failed: " << vertex << " should not be in set!" << endl;
199 | //// }
200 | return false;
201 | }
202 |
203 | //// if (!inSet && neighborsInSet == 0) {
204 | //// if (verbose) {
205 | //// cout << "Maximal independent set test failed: " << vertex << " can be added to set!" << endl;
206 | //// }
207 | //// return false;
208 | //// }
209 | }
210 | #endif
211 | return true;
212 | }
213 |
--------------------------------------------------------------------------------
/src/CliqueTools.h:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License as published by
4 | the Free Software Foundation, either version 3 of the License, or
5 | (at your option) any later version.
6 |
7 | This program is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 |
12 | You should have received a copy of the GNU General Public License
13 | along with this program. If not, see
14 | */
15 |
16 | #ifndef CLIQUE_TOOLS_H
17 | #define CLIQUE_TOOLS_H
18 |
19 | #include
20 | #include
21 | #include
22 |
23 | namespace CliqueTools
24 | {
25 | bool IsMaximalClique(std::vector> &adjacencyArray, std::list const&clique, bool const verbose);
26 | bool IsClique(std::vector> &adjacencyMatrix, std::list const &clique, bool const verbose);
27 | bool IsIndependentSet(std::vector> &adjacencyMatrix, std::list const &clique, bool const verbose);
28 | bool IsMaximalIndependentSet(std::vector> &adjacencyArray, std::list const &vertexSet, bool const verbose);
29 | bool IsIndependentSet(std::vector> &adjacencyArray, std::list const &vertexSet, bool const verbose);
30 | };
31 |
32 | #endif //CLIQUE_TOOLS_H
33 |
--------------------------------------------------------------------------------
/src/ColoringStrategy.h:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License as published by
4 | the Free Software Foundation, either version 3 of the License, or
5 | (at your option) any later version.
6 |
7 | This program is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 |
12 | You should have received a copy of the GNU General Public License
13 | along with this program. If not, see
14 | */
15 |
16 | #ifndef COLORING_STRATEGY_H
17 | #define COLORING_STRATEGY_H
18 |
19 | #include
20 |
21 | class ColoringStrategy
22 | {
23 | public:
24 | ColoringStrategy() {}
25 | virtual void Color(std::vector> const &adjacencyList, std::vector &vVerticesToReorder, std::vector &vColors) {};
26 | virtual void Color(std::vector> const &adjacencyMatrix, std::vector &vVerticesToReorder, std::vector &vColors) {};
27 |
28 | virtual void Color(std::vector> const &adjacencyMatrix, std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors) {};
29 | virtual int ColorWithoutReorder(std::vector> const &adjacencyMatrix, std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors) { return 0; }
30 | virtual void Recolor(std::vector> const &adjacencyMatrix, std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors) {};
31 | virtual void Recolor(std::vector> const &adjacencyArray, std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors) {};
32 | //// virtual void Recolor() = 0;
33 | //// virtual void RemoveVertex(int const vertex) = 0;
34 | //// virtual void PeekAtNextVertexAndColor(int &vertex, int &color) = 0;
35 | };
36 |
37 | #endif //COLORING_STRATEGY_H
38 |
--------------------------------------------------------------------------------
/src/DegeneracyTools.h:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License as published by
4 | the Free Software Foundation, either version 3 of the License, or
5 | (at your option) any later version.
6 |
7 | This program is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 |
12 | You should have received a copy of the GNU General Public License
13 | along with this program. If not, see
14 | */
15 |
16 | #ifndef _DJS_DEGENERACY_HELPER_H_
17 | #define _DJS_DEGENERACY_HELPER_H_
18 |
19 | #include
20 | #include
21 | #include
22 |
23 | #include "Tools.h"
24 | #include
25 | #include "MemoryManager.h"
26 |
27 | /*! \file DegeneracyTools.h
28 |
29 | \brief A collection of structures and functions to compute degeneracy and degeneracy order.
30 |
31 | \author Darren Strash (first name DOT last name AT gmail DOT com)
32 |
33 | \copyright Copyright (c) 2011 Darren Strash. This code is released under the GNU Public License (GPL) 3.0.
34 |
35 | \image html gplv3-127x51.png
36 |
37 | \htmlonly
38 |
39 | See GPL 3.0 here
40 |
41 | \endhtmlonly
42 | */
43 |
44 |
45 | /*! \struct NeighborList
46 |
47 | \brief For a given ordering, this stores later neighbors and earlier neighbors
48 | for a given vertex in linked lists.
49 | */
50 |
51 | struct NeighborList
52 | {
53 | NeighborList()
54 | : vertex(-1)
55 | , earlier()
56 | , later()
57 | , orderNumber(-1) {}
58 |
59 | int vertex; //!< the vertex that owns this neighbor list
60 | std::list earlier; //!< a linked list of neighbors that come before this vertex in the ordering
61 | std::list later; //!< a linked list of neighbors that come after this vertex in the ordering
62 | int orderNumber; //!< the position of this vertex in the ordering
63 | };
64 |
65 | typedef struct NeighborList NeighborList;
66 |
67 | /*! \struct NeighborListArray
68 |
69 | \brief For a given ordering, this stores later neighbors and earlier neighbors
70 | for a given vertex in arrays.
71 |
72 | This version of the NeighborList structure is more cache efficient.
73 | */
74 |
75 | class NeighborListArray
76 | {
77 | public:
78 | NeighborListArray()
79 | : vertex(-1)
80 | , earlier()
81 | , earlierDegree(-1)
82 | , later()
83 | , laterDegree(-1)
84 | , orderNumber(-1) {}
85 |
86 | int vertex; //!< the vertex that owns this neighbor list
87 | std::vector earlier; //!< an array of neighbors that come before this vertex in an ordering
88 | int earlierDegree; //!< the number of neighbors in earlier
89 | std::vector later; //!< an array of neighbors that come after this vertex in an ordering
90 | int laterDegree; //!< an array of neighbors that come after this vertex in an ordering
91 | int orderNumber; //!< the position of this verex in the ordering
92 | };
93 |
94 | typedef struct NeighborListArray NeighborListArray;
95 |
96 | int computeDegeneracy(std::vector> const &adjList, int size);
97 | int computeDegeneracy(std::vector> const &adjList, int size);
98 |
99 | NeighborList** computeDegeneracyOrderList(std::vector> const &adjList, int size);
100 |
101 | NeighborListArray** computeDegeneracyOrderArray(std::vector> const &adjList, int size);
102 |
103 | std::vector computeDegeneracyOrderArray(std::vector> &adjArray, int size);
104 | std::vector computeDegeneracyOrderArrayWithArrays(std::vector> &adjArray, int size);
105 |
106 | std::vector computeDegeneracyOrderArrayForReverse(std::vector> &adjArray, int size);
107 |
108 | int neighborListComparator(void* nl1, void* nl2);
109 |
110 | std::vector computeMaximumLaterOrderArray(std::vector> &adjArray, int size);
111 |
112 | std::vector GetVerticesInDegeneracyOrder(std::vector> &adjArray);
113 |
114 | #endif
115 |
--------------------------------------------------------------------------------
/src/GraphTools.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License as published by
4 | the Free Software Foundation, either version 3 of the License, or
5 | (at your option) any later version.
6 |
7 | This program is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 |
12 | You should have received a copy of the GNU General Public License
13 | along with this program. If not, see
14 | */
15 |
16 | #include "GraphTools.h"
17 | #include "SparseArraySet.h"
18 | #include "ArraySet.h"
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | using namespace std;
28 |
29 | void GraphTools::ComputeInducedSubgraph(vector> const &graph, set const &vertices, vector> &subgraph, map &remapping)
30 | {
31 | subgraph.clear();
32 | remapping.clear();
33 |
34 | //// cout << "Forming induced subgraph on " << vertices.size() << " vertices." << endl;
35 |
36 | map forwardMapping;
37 |
38 | int vertexIndex(0);
39 | auto mappedVertex = [&vertexIndex, &remapping, &forwardMapping](int const vertex)
40 | {
41 | if (forwardMapping.find(vertex) == forwardMapping.end()) {
42 | forwardMapping[vertex] = vertexIndex;
43 | remapping[vertexIndex] = vertex;
44 | vertexIndex++;
45 | }
46 | return forwardMapping[vertex];
47 | };
48 |
49 | for (int const vertex : vertices) {
50 | mappedVertex(vertex);
51 | }
52 |
53 | subgraph.resize(vertices.size());
54 |
55 | for (int vertex = 0; vertex < graph.size(); ++vertex) {
56 | if (vertices.find(vertex) == vertices.end()) continue;
57 |
58 | vector const &neighbors(graph[vertex]);
59 | int const newVertex = mappedVertex(vertex);
60 | //// cout << newVertex << " : ";
61 | for (int const neighbor : neighbors) {
62 | if (vertices.find(neighbor) == vertices.end()) continue;
63 | int const newNeighbor = mappedVertex(neighbor);
64 | subgraph[newVertex].push_back(newNeighbor);
65 | //// subgraph[newNeighbor].push_back(newVertex);
66 | //// cout << newNeighbor << " ";
67 | }
68 | //// cout << endl;
69 | }
70 | }
71 |
72 | vector GraphTools::OrderVerticesByDegree(vector> const &adjacencyList, bool const ascending)
73 | {
74 | vector vOrderedVertices(adjacencyList.size(), -1);
75 |
76 | size_t maxDegree(0);
77 | for (vector const &neighbors : adjacencyList) {
78 | maxDegree = max(maxDegree, neighbors.size());
79 | }
80 |
81 | vector> vlVerticesByDegree(maxDegree + 1, list());
82 |
83 | for (size_t vertex = 0; vertex < adjacencyList.size(); ++vertex) {
84 | //// std::cout << "maxDegree=" << maxDegree << ", degree=" << adjacencyList[vertex].size() << endl << flush;
85 | vlVerticesByDegree[adjacencyList[vertex].size()].push_back(vertex);
86 | }
87 |
88 | if (ascending) {
89 | size_t index(0);
90 | for (size_t degree = 0; degree <= maxDegree; ++degree) {
91 | for (int const vertex : vlVerticesByDegree[degree]) {
92 | vOrderedVertices[index++] = vertex;
93 | }
94 | }
95 | } else {
96 | size_t index(0);
97 | for (size_t degree = 0; degree <= maxDegree; ++degree) {
98 | for (int const vertex : vlVerticesByDegree[maxDegree - degree]) {
99 | vOrderedVertices[index++] = vertex;
100 | }
101 | }
102 | }
103 |
104 | return vOrderedVertices;
105 | }
106 |
107 | vector GraphTools::OrderVerticesByDegree(vector> const &adjacencyMatrix, vector const &vDegree, bool const ascending)
108 | {
109 | vector vOrderedVertices(adjacencyMatrix.size(), -1);
110 |
111 | size_t maxDegree(0);
112 | for (int const degree : vDegree) {
113 | maxDegree = max(maxDegree, static_cast(degree));
114 | }
115 |
116 | vector> vlVerticesByDegree(maxDegree + 1, list());
117 |
118 | for (size_t vertex = 0; vertex < adjacencyMatrix.size(); ++vertex) {
119 | //// std::cout << "maxDegree=" << maxDegree << ", degree=" << adjacencyList[vertex].size() << endl << flush;
120 | vlVerticesByDegree[vDegree[vertex]].push_back(vertex);
121 | }
122 |
123 | if (ascending) {
124 | size_t index(0);
125 | for (size_t degree = 0; degree <= maxDegree; ++degree) {
126 | for (int const vertex : vlVerticesByDegree[degree]) {
127 | vOrderedVertices[index++] = vertex;
128 | }
129 | }
130 | } else {
131 | size_t index(0);
132 | for (size_t degree = 0; degree <= maxDegree; ++degree) {
133 | for (int const vertex : vlVerticesByDegree[maxDegree - degree]) {
134 | vOrderedVertices[index++] = vertex;
135 | }
136 | }
137 | }
138 |
139 | return vOrderedVertices;
140 | }
141 |
142 | vector GraphTools::OrderVerticesByDegree(vector> const &adjacencyMatrix, bool const ascending)
143 | {
144 | vector vDegree(adjacencyMatrix.size(), 0);
145 | for (size_t u = 0; u < adjacencyMatrix.size(); ++u) {
146 | for (size_t v = 0; v < adjacencyMatrix.size(); ++v) {
147 | if (adjacencyMatrix[u][v]) vDegree[u]++;
148 | }
149 | }
150 | return std::move(OrderVerticesByDegree(adjacencyMatrix, vDegree, ascending));
151 | }
152 |
153 | vector GraphTools::OrderVerticesByDegree(ArraySet const &inGraph, vector const &neighborSets, bool const ascending)
154 | {
155 | vector vOrderedVertices(inGraph.Size(), -1);
156 |
157 | size_t maxDegree(0);
158 | for (ArraySet const &neighborSet : neighborSets) {
159 | maxDegree = max(maxDegree, neighborSet.Size());
160 | }
161 |
162 | vector> vlVerticesByDegree(maxDegree + 1, list());
163 |
164 | for (size_t vertex = 0; vertex < neighborSets.size(); ++vertex) {
165 | if (!inGraph.Contains(vertex)) continue;
166 | //// std::cout << "maxDegree=" << maxDegree << ", degree=" << adjacencyList[vertex].size() << endl << flush;
167 | vlVerticesByDegree[neighborSets[vertex].Size()].push_back(vertex);
168 | }
169 |
170 | if (ascending) {
171 | size_t index(0);
172 | for (size_t degree = 0; degree <= maxDegree; ++degree) {
173 | for (int const vertex : vlVerticesByDegree[degree]) {
174 | vOrderedVertices[index++] = vertex;
175 | }
176 | }
177 | } else {
178 | size_t index(0);
179 | for (size_t degree = 0; degree <= maxDegree; ++degree) {
180 | for (int const vertex : vlVerticesByDegree[maxDegree - degree]) {
181 | vOrderedVertices[index++] = vertex;
182 | }
183 | }
184 | }
185 |
186 | return vOrderedVertices;
187 | }
188 |
189 | vector GraphTools::OrderVerticesByDegree(ArraySet const &inGraph, vector const &neighborSets, bool const ascending)
190 | {
191 | vector vOrderedVertices(inGraph.Size(), -1);
192 |
193 | size_t maxDegree(0);
194 | for (SparseArraySet const &neighborSet : neighborSets) {
195 | maxDegree = max(maxDegree, neighborSet.Size());
196 | }
197 |
198 | vector> vlVerticesByDegree(maxDegree + 1, list());
199 |
200 | for (size_t vertex = 0; vertex < neighborSets.size(); ++vertex) {
201 | if (!inGraph.Contains(vertex)) continue;
202 | //// std::cout << "maxDegree=" << maxDegree << ", degree=" << adjacencyList[vertex].size() << endl << flush;
203 | vlVerticesByDegree[neighborSets[vertex].Size()].push_back(vertex);
204 | }
205 |
206 | if (ascending) {
207 | size_t index(0);
208 | for (size_t degree = 0; degree <= maxDegree; ++degree) {
209 | for (int const vertex : vlVerticesByDegree[degree]) {
210 | vOrderedVertices[index++] = vertex;
211 | }
212 | }
213 | } else {
214 | size_t index(0);
215 | for (size_t degree = 0; degree <= maxDegree; ++degree) {
216 | for (int const vertex : vlVerticesByDegree[maxDegree - degree]) {
217 | vOrderedVertices[index++] = vertex;
218 | }
219 | }
220 | }
221 |
222 | return vOrderedVertices;
223 | }
224 |
225 | void GraphTools::ComputeConnectedComponents(vector> const &adjacencyList, vector> &vComponents) {
226 |
227 | vComponents.clear();
228 | if (adjacencyList.empty()) return;
229 |
230 |
231 | size_t componentCount(0);
232 | size_t uNumVertices(adjacencyList.size());
233 |
234 | vector evaluated (uNumVertices, false);
235 | ArraySet currentSearch(uNumVertices);
236 | ArraySet remaining (uNumVertices);
237 |
238 | for (int vertex = 0; vertex < uNumVertices; ++vertex) {
239 | remaining.Insert(vertex);
240 | }
241 |
242 | // add first vertex, from where we start search
243 | int const startVertex(0);
244 | currentSearch.Insert(startVertex);
245 | remaining.Remove(startVertex);
246 | componentCount++;
247 | vComponents.resize(componentCount);
248 |
249 | while (!remaining.Empty() && !currentSearch.Empty()) {
250 | int const nextVertex(*currentSearch.begin());
251 | evaluated[nextVertex] = true;
252 | vComponents[componentCount - 1].push_back(nextVertex);
253 | currentSearch.Remove(nextVertex);
254 | remaining.Remove(nextVertex);
255 | for (int const neighbor : adjacencyList[nextVertex]) {
256 | if (!evaluated[neighbor]) {
257 | currentSearch.Insert(neighbor);
258 | }
259 | }
260 |
261 | if (currentSearch.Empty() && !remaining.Empty()) {
262 | int const startVertex = *remaining.begin();
263 | currentSearch.Insert(startVertex);
264 | remaining.Remove(startVertex);
265 | componentCount++;
266 | vComponents.resize(componentCount);
267 | }
268 | }
269 | }
270 |
271 | void GraphTools::PrintGraphInEdgesFormat(vector> const &adjacencyArray)
272 | {
273 | cout << adjacencyArray.size() << endl;
274 | size_t edges(0);
275 | for (vector const &neighborList : adjacencyArray) {
276 | edges+= neighborList.size();
277 | }
278 | cout << edges << endl;
279 |
280 | for (size_t index = 0; index < adjacencyArray.size(); ++index) {
281 | for (int const neighbor : adjacencyArray[index]) {
282 | cout << index << "," << neighbor << endl;
283 | }
284 | }
285 | }
286 |
287 | void GraphTools::PrintGraphInSNAPFormat(vector> const &adjacencyArray)
288 | {
289 | for (size_t index = 0; index < adjacencyArray.size(); ++index) {
290 | for (int const neighbor : adjacencyArray[index]) {
291 | cout << (index+1) << " " << (neighbor+1) << endl << flush;
292 | }
293 | }
294 | }
295 |
--------------------------------------------------------------------------------
/src/GraphTools.h:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License as published by
4 | the Free Software Foundation, either version 3 of the License, or
5 | (at your option) any later version.
6 |
7 | This program is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 |
12 | You should have received a copy of the GNU General Public License
13 | along with this program. If not, see
14 | */
15 |
16 | #ifndef GRAPH_TOOLS_H
17 | #define GRAPH_TOOLS_H
18 |
19 | #include "SparseArraySet.h"
20 | #include "ArraySet.h"
21 |
22 | #include
23 | #include
24 | #include
25 |
26 | namespace GraphTools
27 | {
28 | void ComputeInducedSubgraph(std::vector> const &adjacencyList, std::set const &vertices, std::vector> &subraph, std::map &remapping);
29 | std::vector OrderVerticesByDegree(std::vector> const &adjacencyList, bool const ascending);
30 | std::vector OrderVerticesByDegree(ArraySet const &inGraph, std::vector const &neighborSets, bool const ascending);
31 | std::vector OrderVerticesByDegree(ArraySet const &inGraph, std::vector const &neighborSets, bool const ascending);
32 | std::vector OrderVerticesByDegree(std::vector> const &adjacencyMatrix, std::vector const &vDegree, bool const ascending);
33 | std::vector OrderVerticesByDegree(std::vector> const &adjacencyMatrix, bool const ascending);
34 |
35 | void PrintGraphInEdgesFormat(std::vector> const &adjacencyArray);
36 | void PrintGraphInSNAPFormat(std::vector> const &adjacencyArray);
37 |
38 | void ComputeConnectedComponents(std::vector> const &adjacencyList, std::vector> &vComponents);
39 | };
40 |
41 | #endif //GRAPH_TOOLS_H
42 |
--------------------------------------------------------------------------------
/src/IndependentSetColoringStrategy.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License as published by
4 | the Free Software Foundation, either version 3 of the License, or
5 | (at your option) any later version.
6 |
7 | This program is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 |
12 | You should have received a copy of the GNU General Public License
13 | along with this program. If not, see
14 | */
15 |
16 | #include "IndependentSetColoringStrategy.h"
17 | #include "DegeneracyTools.h"
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | using namespace std;
25 |
26 | IndependentSetColoringStrategy::IndependentSetColoringStrategy(vector> const &adjacencyMatrix) : ColoringStrategy(), m_AdjacencyMatrix(adjacencyMatrix), m_vvVerticesWithColor()////, m_Colors(adjacencyList.size(), -1) , m_VertexOrder()
27 | {
28 | m_vvVerticesWithColor.resize(adjacencyMatrix.size());
29 | for (vector vVertices : m_vvVerticesWithColor) {
30 | vVertices.reserve(adjacencyMatrix.size());
31 | }
32 | //// m_VertexOrder = std::move(GetVerticesInDegeneracyOrder(adjacencyList));
33 | }
34 |
35 | int IndependentSetColoringStrategy::ColorWithoutReorder(vector> const &adjacencyMatrix, vector const &vVertexOrder, vector &vVerticesToReorder, vector &vColors)
36 | {
37 | if (vVerticesToReorder.empty()) return 0;
38 |
39 | #if 0
40 | cout << "Coloring (in ): ";
41 | //// for (int const vertex : vVerticesToReorder) {
42 | for (int index = 0; index < vVerticesToReorder.size(); index++) {
43 | int const vertex(vVerticesToReorder[index]);
44 | cout << vertex << "(" << vColors[index] << ") ";
45 | }
46 | cout << endl;
47 | #endif // 0
48 |
49 | size_t maxColor(0);
50 |
51 | vVerticesToReorder = vVertexOrder;
52 | vColors.clear();
53 | vColors.reserve(vVerticesToReorder.size());
54 |
55 | size_t const numVerticesToReorder(vVerticesToReorder.size());
56 |
57 | for (int const vertex : vVertexOrder) {
58 | size_t color = 0;
59 | for (vector const &verticesWithColor : m_vvVerticesWithColor) {
60 | bool hasNeighborWithColor(false);
61 | if (verticesWithColor.empty()) break;
62 | for (int const coloredVertex : verticesWithColor) {
63 | // can be made more efficient?
64 | hasNeighborWithColor = !adjacencyMatrix[vertex][coloredVertex];
65 | if (hasNeighborWithColor) {
66 | color++;
67 | break;
68 | }
69 | }
70 |
71 | if (!hasNeighborWithColor) {
72 | break;
73 | }
74 | }
75 |
76 | vColors.push_back(color+1);
77 | m_vvVerticesWithColor[color].push_back(vertex);
78 | maxColor = max(maxColor, color);
79 | }
80 |
81 |
82 | //// cout << "maxColor=" << maxColor << ", numVertices=" << vVerticesToReorder.size() << endl;
83 |
84 | for (int currentColor = 0; currentColor <= maxColor; ++currentColor) {
85 | m_vvVerticesWithColor[currentColor].clear();
86 | }
87 |
88 | return maxColor + 1;
89 |
90 | #if 0
91 | cout << "Coloring (out): ";
92 | for (int index = 0; index < vVerticesToReorder.size(); index++) {
93 | int const vertex(vVerticesToReorder[index]);
94 | cout << vertex << "(" << vColors[index] << ") ";
95 | }
96 | cout << endl;
97 | #endif // 0
98 |
99 | // verify that it is a valid coloring.
100 | #ifdef DEBUG
101 | vector vColor(adjacencyList.size(), -1);
102 | for (size_t index = 0; index < vVerticesToReorder.size(); ++index) {
103 | vColor[vVerticesToReorder[index]] = vColors[index];
104 | }
105 | for (int const vertex : vVerticesToReorder) {
106 | for (int const neighbor : adjacencyList[vertex]) {
107 | if (vColor[vertex] == vColor[neighbor]) {
108 | cout << "Consistency Error: vertex " << vertex << " has the same color as neighbor " << neighbor << ", color=" << vColor[vertex] << endl << flush;
109 | }
110 | }
111 | }
112 | #endif // DEBUG
113 | }
114 |
115 |
116 | void IndependentSetColoringStrategy::Color(vector> const &adjacencyMatrix, vector const &vVertexOrder, vector &vVerticesToReorder, vector &vColors)
117 | {
118 | if (vVertexOrder.empty()) return;
119 |
120 | #if 0
121 | cout << "Coloring (in ): ";
122 | //// for (int const vertex : vVerticesToReorder) {
123 | for (int index = 0; index < vVerticesToReorder.size(); index++) {
124 | int const vertex(vVerticesToReorder[index]);
125 | cout << vertex << "(" << vColors[index] << ") ";
126 | }
127 | cout << endl;
128 | #endif // 0
129 |
130 | size_t maxColor(0);
131 |
132 | size_t const numVerticesToReorder(vVertexOrder.size());
133 | vVerticesToReorder.resize(vVertexOrder.size());
134 | vColors.resize(vVertexOrder.size());
135 |
136 | for (int const vertex : vVertexOrder) {
137 | size_t color = 0;
138 | for (vector const &verticesWithColor : m_vvVerticesWithColor) {
139 | bool hasNeighborWithColor(false);
140 | if (verticesWithColor.empty()) break;
141 | for (int const coloredVertex : verticesWithColor) {
142 | // can be made more efficient?
143 | hasNeighborWithColor = !adjacencyMatrix[vertex][coloredVertex];
144 | if (hasNeighborWithColor) {
145 | color++;
146 | break;
147 | }
148 | }
149 |
150 | if (!hasNeighborWithColor) {
151 | break;
152 | }
153 | }
154 |
155 | m_vvVerticesWithColor[color].push_back(vertex);
156 | maxColor = max(maxColor, color);
157 | }
158 |
159 | //// cout << "maxColor=" << maxColor << ", numVertices=" << vVerticesToReorder.size() << endl;
160 |
161 | int currentIndex(0);
162 | int currentColor(0);
163 | for (int currentColor = 0; currentColor <= maxColor; ++currentColor) {
164 | for (int const vertex : m_vvVerticesWithColor[currentColor]) {
165 | vVerticesToReorder[currentIndex] = vertex;
166 | vColors[currentIndex] = currentColor+1;
167 | currentIndex++;
168 | }
169 | m_vvVerticesWithColor[currentColor].clear();
170 | }
171 |
172 | #if 0
173 | cout << "Coloring (out): ";
174 | for (int index = 0; index < vVerticesToReorder.size(); index++) {
175 | int const vertex(vVerticesToReorder[index]);
176 | cout << vertex << "(" << vColors[index] << ") ";
177 | }
178 | cout << endl;
179 | #endif // 0
180 |
181 | // verify that it is a valid coloring.
182 | #ifdef DEBUG
183 | vector vColor(adjacencyList.size(), -1);
184 | for (size_t index = 0; index < vVerticesToReorder.size(); ++index) {
185 | vColor[vVerticesToReorder[index]] = vColors[index];
186 | }
187 | for (int const vertex : vVerticesToReorder) {
188 | for (int const neighbor : adjacencyList[vertex]) {
189 | if (vColor[vertex] == vColor[neighbor]) {
190 | cout << "Consistency Error: vertex " << vertex << " has the same color as neighbor " << neighbor << ", color=" << vColor[vertex] << endl << flush;
191 | }
192 | }
193 | }
194 | #endif // DEBUG
195 | }
196 |
197 | void IndependentSetColoringStrategy::Recolor(vector> const &adjacencyMatrix, vector const &vVertexOrder, vector &vVerticesToReorder, vector &vColors, int const currentBestCliqueSize, int const currentCliqueSize)
198 | {
199 | if (vVerticesToReorder.empty()) return;
200 |
201 | #if 0
202 | cout << "Coloring (in ): ";
203 | //// for (int const vertex : vVerticesToReorder) {
204 | for (int index = 0; index < vVerticesToReorder.size(); index++) {
205 | int const vertex(vVerticesToReorder[index]);
206 | cout << vertex << "(" << vColors[index] << ") ";
207 | }
208 | cout << endl;
209 | #endif // 0
210 |
211 | size_t maxColor(0);
212 |
213 | int iBestCliqueDelta(currentBestCliqueSize - currentCliqueSize);
214 |
215 | size_t const numVerticesToReorder(vVerticesToReorder.size());
216 |
217 | for (int const vertex : vVertexOrder) {
218 | size_t color = 0;
219 | for (vector const &verticesWithColor : m_vvVerticesWithColor) {
220 | bool hasNeighborWithColor(false);
221 | if (verticesWithColor.empty()) break;
222 | for (int const coloredVertex : verticesWithColor) {
223 | // can be made more efficient?
224 | hasNeighborWithColor = !adjacencyMatrix[vertex][coloredVertex];
225 | if (hasNeighborWithColor) {
226 | color++;
227 | break;
228 | }
229 | }
230 |
231 | if (!hasNeighborWithColor) {
232 | break;
233 | }
234 | }
235 |
236 | m_vvVerticesWithColor[color].push_back(vertex);
237 | maxColor = max(maxColor, color);
238 | if (color+1 > iBestCliqueDelta && /*m_vvVerticesWithColor[color].size() == 1*/ color == maxColor) {
239 | Repair(vertex, color, iBestCliqueDelta);
240 | if (m_vvVerticesWithColor[maxColor].empty())
241 | maxColor--;
242 | }
243 | }
244 |
245 | //// vVerticesToReorder.resize(vVertexOrder.size());
246 | //// vColors.resize(vVertexOrder.size());
247 |
248 | //// cout << "maxColor=" << maxColor << ", numVertices=" << vVerticesToReorder.size() << endl;
249 |
250 | int currentIndex(0);
251 | int currentColor(0);
252 | for (int currentColor = 0; currentColor <= maxColor; ++currentColor) {
253 | for (int const vertex : m_vvVerticesWithColor[currentColor]) {
254 | vVerticesToReorder[currentIndex] = vertex;
255 | vColors[currentIndex] = currentColor+1;
256 | currentIndex++;
257 | }
258 | m_vvVerticesWithColor[currentColor].clear();
259 | }
260 |
261 | #if 0
262 | cout << "Coloring (out): ";
263 | for (int index = 0; index < vVerticesToReorder.size(); index++) {
264 | int const vertex(vVerticesToReorder[index]);
265 | cout << vertex << "(" << vColors[index] << ") ";
266 | }
267 | cout << endl;
268 | #endif // 0
269 |
270 | // verify that it is a valid coloring.
271 | #ifdef DEBUG
272 | vector vColor(adjacencyList.size(), -1);
273 | for (size_t index = 0; index < vVerticesToReorder.size(); ++index) {
274 | vColor[vVerticesToReorder[index]] = vColors[index];
275 | }
276 | for (int const vertex : vVerticesToReorder) {
277 | for (int const neighbor : adjacencyList[vertex]) {
278 | if (vColor[vertex] == vColor[neighbor]) {
279 | cout << "Consistency Error: vertex " << vertex << " has the same color as neighbor " << neighbor << ", color=" << vColor[vertex] << endl << flush;
280 | }
281 | }
282 | }
283 | #endif // DEBUG
284 | }
285 |
286 | bool IndependentSetColoringStrategy::HasConflict(int const vertex, vector const &vVerticesWithColor)
287 | {
288 | if (vVerticesWithColor.empty()) return false;
289 | for (int const coloredVertex : vVerticesWithColor) {
290 | // can be made more efficient?
291 | if (!m_AdjacencyMatrix[vertex][coloredVertex]) {
292 | return true;
293 | }
294 | }
295 |
296 | return false;
297 | }
298 |
299 | int IndependentSetColoringStrategy::GetConflictingVertex(int const vertex, vector const &vVerticesWithColor)
300 | {
301 | int conflictingVertex(-1);
302 | int count(0);
303 | for (int const candidateVertex : vVerticesWithColor) {
304 | if (!m_AdjacencyMatrix[vertex][candidateVertex]) {
305 | conflictingVertex = candidateVertex;
306 | count++;
307 | if (count > 1) return -1;
308 | }
309 | }
310 | return conflictingVertex;
311 | }
312 |
313 | bool IndependentSetColoringStrategy::Repair(int const vertex, int const color, int const iBestCliqueDelta)
314 | {
315 | for (int newColor = 0; newColor <= iBestCliqueDelta-1; newColor++) {
316 | int const conflictingVertex(GetConflictingVertex(vertex, m_vvVerticesWithColor[newColor]));
317 | if (conflictingVertex < 0) continue;
318 | for (int nextColor = newColor+1; nextColor <= iBestCliqueDelta; nextColor++) {
319 | if (HasConflict(conflictingVertex, m_vvVerticesWithColor[nextColor])) continue;
320 | m_vvVerticesWithColor[color].erase(find(m_vvVerticesWithColor[color].begin(), m_vvVerticesWithColor[color].end(), vertex));
321 | m_vvVerticesWithColor[newColor].erase(find(m_vvVerticesWithColor[newColor].begin(), m_vvVerticesWithColor[newColor].end(), conflictingVertex));
322 | m_vvVerticesWithColor[newColor].push_back(vertex);
323 | m_vvVerticesWithColor[nextColor].push_back(conflictingVertex);
324 | //// cout << "Repairing vertices " << vertex << " and " << conflictingVertex << endl;
325 | return true;
326 | }
327 | }
328 | return false;
329 | }
330 |
--------------------------------------------------------------------------------
/src/IndependentSetColoringStrategy.h:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License as published by
4 | the Free Software Foundation, either version 3 of the License, or
5 | (at your option) any later version.
6 |
7 | This program is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 |
12 | You should have received a copy of the GNU General Public License
13 | along with this program. If not, see
14 | */
15 |
16 | #ifndef IS_COLORING_STRATEGY
17 | #define IS_COLORING_STRATEGY
18 |
19 | #include "ColoringStrategy.h"
20 |
21 | class IndependentSetColoringStrategy : public ColoringStrategy
22 | {
23 | public:
24 | IndependentSetColoringStrategy(std::vector> const &adjacencyMatrix);
25 | virtual int ColorWithoutReorder(std::vector> const &adjacencyMatrix, std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors);
26 | virtual void Color(std::vector> const &adjacencyMatrix, std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors);
27 | virtual void Recolor(std::vector> const &adjacencyMatrix, std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors, int const currentBestCliqueSize, int const currentCliqueSize);
28 | bool HasConflict(int const vertex, std::vector const &vVerticesWithColor);
29 | int GetConflictingVertex(int const vertex, std::vector const &vVerticesWithColor);
30 | bool Repair(int const vertex, int const color, int const iBestCliqueDelta);
31 | //// virtual void Recolor();
32 | //// virtual void RemoveVertex(int const vertex);
33 | //// virtual void PeekAtNextVertexAndColor(int &vertex, int &color);
34 | protected:
35 | std::vector> const &m_AdjacencyMatrix;
36 | std::vector> m_vvVerticesWithColor;
37 | //// std::vector m_Colors;
38 | //// std::vector m_VertexOrder;
39 | };
40 |
41 | #endif //IS_COLORING_STRATEGY
42 |
--------------------------------------------------------------------------------
/src/MCQ.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License as published by
4 | the Free Software Foundation, either version 3 of the License, or
5 | (at your option) any later version.
6 |
7 | This program is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 |
12 | You should have received a copy of the GNU General Public License
13 | along with this program. If not, see
14 | */
15 |
16 | #include "MCQ.h"
17 | #include "OrderingTools.h"
18 |
19 | #include
20 | #include
21 |
22 | using namespace std;
23 |
24 | MCQ::MCQ(vector> const &vAdjacencyMatrix)
25 | : MaxSubgraphAlgorithm("mcq")
26 | , m_AdjacencyMatrix(vAdjacencyMatrix)
27 | , coloringStrategy(m_AdjacencyMatrix)
28 | ////, m_bInvert(0)
29 | {
30 | R.reserve(m_AdjacencyMatrix.size());
31 |
32 | stackP.resize(m_AdjacencyMatrix.size() + 1);
33 | stackColors.resize(m_AdjacencyMatrix.size() + 1);
34 | stackOrder.resize(m_AdjacencyMatrix.size() + 1);
35 | stackEvaluatedHalfVertices.resize(m_AdjacencyMatrix.size() + 1);
36 |
37 | // don't reserve for 0-th vectors, they get std::move'd by InitialOrdering
38 | for (int index = 0; index < stackP.size(); ++index) {
39 | stackP[index].reserve(m_AdjacencyMatrix.size());
40 | stackColors[index].reserve(m_AdjacencyMatrix.size());
41 | stackOrder[index].reserve(m_AdjacencyMatrix.size());
42 | }
43 | }
44 |
45 | ////void MCQ::SetInvert(bool const invert)
46 | ////{
47 | //// m_bInvert = invert;
48 | ////}
49 |
50 | void MCQ::InitializeOrder(std::vector &P, std::vector &vVertexOrder, std::vector &vColors)
51 | {
52 | OrderingTools::InitialOrderingMCQ(m_AdjacencyMatrix, P, vColors);
53 | vVertexOrder = P;
54 | }
55 |
56 | void MCQ::Color(std::vector const &vVertexOrder, std::vector