├── 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 | [![license](https://img.shields.io/badge/license-GPL%20v3.0-blue.svg)](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 &vVerticesToReorder, std::vector &vColors) 57 | { 58 | coloringStrategy.Color(m_AdjacencyMatrix, vVertexOrder/* evaluation order */, vVerticesToReorder /* color order */, vColors); 59 | //// cout << "Colors:"; 60 | //// for (int const color : vColors) { 61 | //// cout << color << " "; 62 | //// } 63 | //// cout << endl; 64 | } 65 | 66 | void MCQ::GetNewOrder(vector &vNewVertexOrder, vector &vVertexOrder, vector const &P, int const chosenVertex) 67 | { 68 | //// cout << "OldP :"; 69 | //// for (int const vertex : P) { 70 | //// cout << vertex << " "; 71 | //// } 72 | //// cout << endl; 73 | 74 | vNewVertexOrder.resize(P.size()); 75 | { 76 | size_t uNewIndex(0); 77 | for (int const candidate : P) { 78 | //// if (!m_bInvert && m_AdjacencyMatrix[chosenVertex][candidate]) vNewVertexOrder[uNewIndex++] = candidate; 79 | if (m_AdjacencyMatrix[chosenVertex][candidate]) vNewVertexOrder[uNewIndex++] = candidate; 80 | } 81 | vNewVertexOrder.resize(uNewIndex); 82 | } 83 | 84 | //// cout << "NewOrder:"; 85 | //// for (int const vertex : vNewVertexOrder) { 86 | //// cout << vertex << " "; 87 | //// } 88 | //// cout << endl; 89 | 90 | R.push_back(chosenVertex); 91 | } 92 | 93 | void MCQ::ProcessOrderAfterRecursion(std::vector &vVertexOrder, std::vector &P, std::vector &vColors, int const chosenVertex) 94 | { 95 | if (chosenVertex != -1) R.pop_back(); 96 | } 97 | -------------------------------------------------------------------------------- /src/MCQ.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 LIGHTWEIGHT_MCQ_H 17 | #define LIGHTWEIGHT_MCQ_H 18 | 19 | #include "MaxSubgraphAlgorithm.h" 20 | #include "CliqueColoringStrategy.h" 21 | 22 | #include 23 | #include 24 | 25 | class MCQ : public MaxSubgraphAlgorithm 26 | { 27 | public: 28 | MCQ(std::vector> const &vAdjacencyMatrix); 29 | //// virtual ~MCQ(); 30 | 31 | virtual void Color(std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors); 32 | 33 | virtual void InitializeOrder(std::vector &P, std::vector &vVertexOrder, std::vector &vColors); 34 | virtual void GetNewOrder(std::vector &vNewVertexOrder, std::vector &vVertexOrder, std::vector const &P, int const chosenVertex); 35 | virtual void ProcessOrderAfterRecursion(std::vector &vVertexOrder, std::vector &P, std::vector &vColors, int const chosenVertex); 36 | virtual void ProcessOrderBeforeReturn(std::vector &vVertexOrder, std::vector &P, std::vector &vColors) {} 37 | 38 | //// void SetInvert(bool const invert); 39 | 40 | protected: 41 | std::vector> const &m_AdjacencyMatrix; 42 | CliqueColoringStrategy coloringStrategy; 43 | //// bool m_bInvert; 44 | }; 45 | #endif 46 | -------------------------------------------------------------------------------- /src/MCR.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 "MCR.h" 17 | #include "OrderingTools.h" 18 | 19 | #include 20 | #include 21 | 22 | using namespace std; 23 | 24 | MCR::MCR(vector> const &vAdjacencyMatrix) 25 | : MCQ(vAdjacencyMatrix) 26 | { 27 | SetName("mcr"); 28 | } 29 | 30 | void MCR::InitializeOrder(std::vector &P, std::vector &vVertexOrder, std::vector &vColors) 31 | { 32 | OrderingTools::InitialOrderingMCR(m_AdjacencyMatrix, P, vColors, m_uMaximumCliqueSize); 33 | vVertexOrder = P; 34 | } 35 | -------------------------------------------------------------------------------- /src/MCR.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 LIGHTWEIGHT_MCR_H 17 | #define LIGHTWEIGHT_MCR_H 18 | 19 | #include "MCQ.h" 20 | #include "CliqueColoringStrategy.h" 21 | 22 | #include 23 | #include 24 | 25 | class MCR : public MCQ 26 | { 27 | public: 28 | MCR(std::vector> const &vAdjacencyMatrix); 29 | 30 | virtual void InitializeOrder(std::vector &P, std::vector &vVertexOrder, std::vector &vColors); 31 | }; 32 | #endif //LIGHTWEIGHT_MCR_H 33 | -------------------------------------------------------------------------------- /src/MCS.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 "MCS.h" 17 | #include "OrderingTools.h" 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | using namespace std; 24 | 25 | MCS::MCS(vector> const &vAdjacencyMatrix) 26 | : StaticOrderMCS(vAdjacencyMatrix) 27 | { 28 | SetName("mcs"); 29 | } 30 | 31 | void MCS::Color(std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors) 32 | { 33 | coloringStrategy.Recolor(m_AdjacencyMatrix, vVertexOrder/* evaluation order */, vVerticesToReorder /* color order */, vColors, static_cast(m_uMaximumCliqueSize), static_cast(R.size())); 34 | } 35 | -------------------------------------------------------------------------------- /src/MCS.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 LIGHTWEIGHT_FULL_MCS_H 17 | #define LIGHTWEIGHT_FULL_MCS_H 18 | 19 | #include "StaticOrderMCS.h" 20 | #include "CliqueColoringStrategy.h" 21 | 22 | #include 23 | #include 24 | 25 | class MCS : public StaticOrderMCS 26 | { 27 | public: 28 | MCS(std::vector> const &vAdjacencyMatrix); 29 | 30 | virtual void Color(std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors); 31 | }; 32 | 33 | #endif //LIGHTWEIGHT_FULL_MCS_H 34 | -------------------------------------------------------------------------------- /src/MISQ.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 "MISQ.h" 17 | #include "OrderingTools.h" 18 | #include "Tools.h" 19 | 20 | #include 21 | #include 22 | 23 | using namespace std; 24 | 25 | MISQ::MISQ(vector> const &vAdjacencyMatrix) 26 | : MaxSubgraphAlgorithm("misq") 27 | , m_AdjacencyMatrix(vAdjacencyMatrix) 28 | , coloringStrategy(m_AdjacencyMatrix) 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 MISQ::InitializeOrder(std::vector &P, std::vector &vVertexOrder, std::vector &vColors) 46 | { 47 | OrderingTools::InitialOrderingMISQ(m_AdjacencyMatrix, P, vColors); 48 | vVertexOrder = P; 49 | } 50 | 51 | void MISQ::Color(std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors) 52 | { 53 | coloringStrategy.Color(m_AdjacencyMatrix, vVertexOrder/* evaluation order */, vVerticesToReorder /* color order */, vColors); 54 | } 55 | 56 | void MISQ::GetNewOrder(vector &vNewVertexOrder, vector &vVertexOrder, vector const &P, int const chosenVertex) 57 | { 58 | vNewVertexOrder.resize(P.size()); 59 | { 60 | size_t uNewIndex(0); 61 | for (int const candidate : P) { 62 | if (chosenVertex == candidate) continue; 63 | if (!m_AdjacencyMatrix[chosenVertex][candidate]) vNewVertexOrder[uNewIndex++] = candidate; 64 | } 65 | vNewVertexOrder.resize(uNewIndex); 66 | } 67 | 68 | R.push_back(chosenVertex); 69 | } 70 | 71 | void MISQ::ProcessOrderAfterRecursion(std::vector &vVertexOrder, std::vector &P, std::vector &vColors, int const chosenVertex) 72 | { 73 | //// cout << "MISQ::ProcessOrderAfterRecursion" << endl; 74 | //// Color(vVertexOrder, P, vColors); 75 | if (chosenVertex != -1) R.pop_back(); 76 | } 77 | 78 | -------------------------------------------------------------------------------- /src/MISQ.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 LIGHTWEIGHT_MISQ_H 17 | #define LIGHTWEIGHT_MISQ_H 18 | 19 | #include "MaxSubgraphAlgorithm.h" 20 | #include "IndependentSetColoringStrategy.h" 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | class MISQ : public MaxSubgraphAlgorithm 27 | { 28 | public: 29 | MISQ(std::vector> const &vAdjacencyMatrix); 30 | //// virtual ~MISQ(); 31 | 32 | //// virtual long Run(std::list> &cliques); 33 | 34 | virtual void Color(std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors); 35 | 36 | virtual void InitializeOrder(std::vector &P, std::vector &vVertexOrder, std::vector &vColors); 37 | virtual void GetNewOrder(std::vector &vNewVertexOrder, std::vector &vVertexOrder, std::vector const &P, int const chosenVertex); 38 | virtual void ProcessOrderAfterRecursion(std::vector &vVertexOrder, std::vector &P, std::vector &vColors, int const chosenVertex); 39 | virtual void ProcessOrderBeforeReturn(std::vector &vVertexOrder, std::vector &P, std::vector &vColors) {} 40 | 41 | //// void SetInvert(bool const invert); 42 | 43 | protected: 44 | std::vector> const &m_AdjacencyMatrix; 45 | IndependentSetColoringStrategy coloringStrategy; 46 | //// bool m_bInvert; 47 | }; 48 | #endif 49 | -------------------------------------------------------------------------------- /src/MISR.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 "MISR.h" 17 | #include "OrderingTools.h" 18 | 19 | #include 20 | #include 21 | 22 | using namespace std; 23 | 24 | MISR::MISR(vector> const &vAdjacencyMatrix) 25 | : MISQ(vAdjacencyMatrix) 26 | { 27 | SetName("misr"); 28 | } 29 | 30 | void MISR::InitializeOrder(std::vector &P, std::vector &vVertexOrder, std::vector &vColors) 31 | { 32 | OrderingTools::InitialOrderingMISR(m_AdjacencyMatrix, P, vColors, m_uMaximumCliqueSize); 33 | vVertexOrder = P; 34 | } 35 | -------------------------------------------------------------------------------- /src/MISR.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 LIGHTWEIGHT_MISR_H 17 | #define LIGHTWEIGHT_MISR_H 18 | 19 | #include "MISQ.h" 20 | #include "CliqueColoringStrategy.h" 21 | 22 | #include 23 | #include 24 | 25 | class MISR : public MISQ 26 | { 27 | public: 28 | MISR(std::vector> const &vAdjacencyMatrix); 29 | 30 | virtual void InitializeOrder(std::vector &P, std::vector &vVertexOrder, std::vector &vColors); 31 | }; 32 | #endif //LIGHTWEIGHT_MISR_H 33 | -------------------------------------------------------------------------------- /src/MISS.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 "MISS.h" 17 | #include "OrderingTools.h" 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | using namespace std; 24 | 25 | MISS::MISS(vector> const &vAdjacencyMatrix) 26 | : StaticOrderMISS(vAdjacencyMatrix) 27 | { 28 | SetName("miss"); 29 | } 30 | 31 | void MISS::Color(std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors) 32 | { 33 | coloringStrategy.Recolor(m_AdjacencyMatrix, vVertexOrder/* evaluation order */, vVerticesToReorder /* color order */, vColors, static_cast(m_uMaximumCliqueSize), static_cast(R.size())); 34 | } 35 | -------------------------------------------------------------------------------- /src/MISS.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 LIGHTWEIGHT_FULL_MISS_H 17 | #define LIGHTWEIGHT_FULL_MISS_H 18 | 19 | #include "StaticOrderMISS.h" 20 | #include "CliqueColoringStrategy.h" 21 | 22 | #include 23 | #include 24 | 25 | class MISS : public StaticOrderMISS 26 | { 27 | public: 28 | MISS(std::vector> const &vAdjacencyMatrix); 29 | 30 | virtual void Color(std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors); 31 | }; 32 | 33 | #endif //LIGHTWEIGHT_FULL_MISS_H 34 | -------------------------------------------------------------------------------- /src/MaxSubgraphAlgorithm.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 "MaxSubgraphAlgorithm.h" 17 | #include "Tools.h" 18 | 19 | #include 20 | 21 | using namespace std; 22 | 23 | MaxSubgraphAlgorithm::MaxSubgraphAlgorithm(string const &name) 24 | : Algorithm(name) 25 | , m_uMaximumCliqueSize(0) 26 | , stackP() 27 | , stackColors() 28 | , stackOrder() 29 | , nodeCount(0) 30 | , depth(-1) 31 | , startTime(clock()) 32 | , timeToLargestClique(0) 33 | , m_bQuiet(true) 34 | , stackEvaluatedHalfVertices() 35 | ////, m_bInvert(0) 36 | , m_iOnlyVertex(-1) 37 | , m_TimeOut(0) 38 | , m_StartTime(clock()) 39 | , m_bTimedOut(false) 40 | { 41 | } 42 | 43 | ////void MaxSubgraphAlgorithm::SetInvert(bool const invert) 44 | ////{ 45 | //// m_bInvert = invert; 46 | ////} 47 | 48 | long MaxSubgraphAlgorithm::Run(list> &cliques) 49 | { 50 | vector &P(stackP[0]); 51 | vector &vColors(stackColors[0]); 52 | vector &vVertexOrder(stackOrder[0]); 53 | 54 | bool bMaximumCliqueSizeIsSet(m_uMaximumCliqueSize != 0); 55 | 56 | InitializeOrder(P, vVertexOrder, vColors); 57 | 58 | cliques.push_back(list()); 59 | 60 | if (!bMaximumCliqueSizeIsSet && R.size() < m_uMaximumCliqueSize) { 61 | cliques.back().clear(); 62 | cliques.back().insert(cliques.back().end(), P.begin(), P.begin() + m_uMaximumCliqueSize); 63 | ExecuteCallBacks(cliques.back()); 64 | } 65 | 66 | ProcessOrderAfterRecursion(vVertexOrder, P, vColors, -1 /* no vertex chosen for removal */); 67 | 68 | if (R.size() > m_uMaximumCliqueSize) { 69 | cliques.back().clear(); 70 | cliques.back().insert(cliques.back().end(), R.begin(), R.end()); 71 | ExecuteCallBacks(cliques.back()); 72 | m_uMaximumCliqueSize = R.size(); 73 | timeToLargestClique = clock() - startTime; 74 | } 75 | 76 | depth++; 77 | if (!P.empty()) { 78 | RunRecursive(P, vVertexOrder, cliques, vColors); 79 | } 80 | return cliques.size(); 81 | } 82 | 83 | void MaxSubgraphAlgorithm::RunRecursive(vector &P, vector &vVertexOrder, list> &cliques, vector &vColors) 84 | { 85 | nodeCount++; 86 | vector &vNewP(stackP[R.size()+1]); 87 | vector &vNewColors(stackColors[R.size()+1]); 88 | vector &vNewVertexOrder(stackOrder[R.size()+1]); 89 | 90 | //// bool &bEvaluatedHalfVertices = stackEvaluatedHalfVertices[R.size() + 1]; 91 | //// stackEvaluatedHalfVertices[depth + 1] = (rand()%(depth+1) == depth); 92 | //// stackEvaluatedHalfVertices[depth + 1] = true; 93 | //// stackEvaluatedHalfVertices[depth + 1] = false; 94 | //// stackEvaluatedHalfVertices[depth + 1] = (depth<=2); 95 | 96 | //// size_t halfVertices(0); 97 | //// size_t index = P.size()+1; 98 | //// for (; index > 0; --index) { 99 | //// if (vColors[index-1] + R.size() <= m_uMaximumCliqueSize) { 100 | //// halfVertices = (index - 1) + 0.9*(P.size() - (index - 1)); 101 | //// break; 102 | //// } 103 | //// } 104 | 105 | //// stackEvaluatedHalfVertices[depth + 1] = ((P.size() - index) > 50); //(depth<=2); 106 | stackEvaluatedHalfVertices[depth + 1] = true; 107 | 108 | size_t const uOriginalPSize(P.size()); 109 | 110 | if (nodeCount%10000 == 0) { 111 | if (!m_bQuiet) { 112 | cout << "Evaluated " << nodeCount << " nodes. " << Tools::GetTimeInSeconds(clock() - startTime) << endl; 113 | PrintState(); 114 | } 115 | if (m_TimeOut > 0 && (clock() - m_StartTime > m_TimeOut)) { 116 | m_bTimedOut = true; 117 | return; 118 | } 119 | } 120 | 121 | while (!P.empty()) { 122 | //// if (!stackEvaluatedHalfVertices[depth + 1]) { 123 | //// stackEvaluatedHalfVertices[depth + 1] = (rand()%(depth+1) == depth); 124 | //// stackEvaluatedHalfVertices[depth + 1] = (rand()%2 == 1); 125 | 126 | //// stackEvaluatedHalfVertices[depth+1] = (rand() % 20 == 1); ////!stackEvaluatedHalfVertices[depth+1]; 127 | 128 | //// if (!stackEvaluatedHalfVertices[depth + 1]) { 129 | //// if (uOriginalPSize >= 100 && P.size() > 1 && vColors[P.size()-5] + R.size() <= m_uMaximumCliqueSize) { 130 | //// stackEvaluatedHalfVertices[depth + 1] = true; 131 | //// } 132 | //// size_t index = P.size(); 133 | //// for (; index > 0; --index) { 134 | //// if (vColors[index-1] + R.size() <= m_uMaximumCliqueSize) { 135 | //// halfVertices = (index - 1 + uOriginalPSize)/2; 136 | //// break; 137 | //// } 138 | //// } 139 | //// 140 | //// if (P.size() - index == 1) { 141 | //// stackEvaluatedHalfVertices[depth + 1] = true; 142 | //// } 143 | 144 | //// if (P.size() <= halfVertices) { 145 | //// stackEvaluatedHalfVertices[depth + 1] = true; 146 | //// } 147 | //////// else if (rand() % 2 == 1) { ////(P.size() - halfVertices) == 1) { 148 | //////// stackEvaluatedHalfVertices[R.size() + 1] = true; 149 | //////// } 150 | //// else if (rand() % P.size() <= index) { 151 | //// stackEvaluatedHalfVertices[depth + 1] = true; 152 | //// } 153 | //// else if (rand() % 2 == 1) { 154 | //// stackEvaluatedHalfVertices[depth+1] = stackEvaluatedHalfVertices[depth]; 155 | //// } 156 | //// } 157 | 158 | //// cout << depth << ": P: "; 159 | //// for (int const p : P) { 160 | //// cout << p << " "; 161 | //// } 162 | //// cout << endl; 163 | 164 | if (depth == 0) { 165 | if (!m_bQuiet) { 166 | cout << "Only " << P.size() << " more vertices to go! " << Tools::GetTimeInSeconds(clock() - startTime) << endl; 167 | } 168 | } 169 | 170 | int const largestColor(vColors.back()); 171 | if (R.size() + largestColor <= m_uMaximumCliqueSize) { 172 | ProcessOrderBeforeReturn(vVertexOrder, P, vColors); 173 | P.clear(); 174 | return; 175 | } 176 | 177 | vColors.pop_back(); 178 | int const nextVertex(P.back()); P.pop_back(); 179 | 180 | //// cout << depth << ": Choosing next vertex: " << nextVertex << endl; 181 | 182 | GetNewOrder(vNewVertexOrder, vVertexOrder, P, nextVertex); 183 | 184 | if (!vNewVertexOrder.empty()) { 185 | vNewP.resize(vNewVertexOrder.size()); 186 | vNewColors.resize(vNewVertexOrder.size()); 187 | Color(vNewVertexOrder/* evaluation order */, vNewP /* color order */, vNewColors); 188 | #ifdef PREPRUNE 189 | if (R.size() + vNewColors.back() > m_uMaximumCliqueSize) { 190 | depth++; 191 | RunRecursive(vNewP, vNewVertexOrder, cliques, vNewColors); 192 | depth--; 193 | } 194 | #else 195 | depth++; 196 | RunRecursive(vNewP, vNewVertexOrder, cliques, vNewColors); 197 | depth--; 198 | #endif // PREPRUNE 199 | } else if (R.size() > m_uMaximumCliqueSize) { 200 | cliques.back().clear(); 201 | cliques.back().insert(cliques.back().end(), R.begin(), R.end()); 202 | ExecuteCallBacks(cliques.back()); 203 | m_uMaximumCliqueSize = R.size(); 204 | timeToLargestClique = clock() - startTime; 205 | } 206 | 207 | bool bPIsEmpty(P.empty()); 208 | ProcessOrderAfterRecursion(vVertexOrder, P, vColors, nextVertex); 209 | 210 | //// if (R.size() > m_uMaximumCliqueSize && bPIsEmpty && P.empty()) { 211 | //// cout << "ERROR!" << endl << flush; 212 | //// } 213 | 214 | if (!bPIsEmpty && P.empty()) { 215 | if (R.size() > m_uMaximumCliqueSize) { 216 | cliques.back().clear(); 217 | cliques.back().insert(cliques.back().end(), R.begin(), R.end()); 218 | ExecuteCallBacks(cliques.back()); 219 | m_uMaximumCliqueSize = R.size(); 220 | timeToLargestClique = clock() - startTime; 221 | } 222 | } 223 | } 224 | 225 | ProcessOrderBeforeReturn(vVertexOrder, P, vColors); 226 | P.clear(); 227 | 228 | vNewColors.clear(); 229 | vNewP.clear(); 230 | } 231 | 232 | 233 | MaxSubgraphAlgorithm::~MaxSubgraphAlgorithm() 234 | { 235 | if (!m_bQuiet) { 236 | cerr << "Largest Clique : " << m_uMaximumCliqueSize << endl; 237 | cerr << "Time to Clique : " << Tools::GetTimeInSeconds(timeToLargestClique) << endl; 238 | cerr << "Search Nodes : " << nodeCount << endl; 239 | } 240 | } 241 | 242 | void MaxSubgraphAlgorithm::PrintState() const 243 | { 244 | cout << "("; 245 | for (size_t index = 0; index <= R.size(); ++index) { 246 | cout << stackP[index].size(); 247 | if (index != R.size()) cout << ", "; 248 | } 249 | cout << ")" << endl << flush; 250 | } 251 | -------------------------------------------------------------------------------- /src/MaxSubgraphAlgorithm.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 MAX_SUBGRAPH_ALGORITHM_H 17 | #define MAX_SUBGRAPH_ALGORITHM_H 18 | 19 | #include "Algorithm.h" 20 | #include "IndependentSetColoringStrategy.h" 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | ////#define PREPRUNE 27 | ////#define REMOVE_ISOLATES_BEFORE_ONLY 28 | ////#define ALWAYS_REMOVE_ISOLATES_AFTER 29 | ////#define NO_ISOLATES_P_LEFT_10 30 | 31 | class MaxSubgraphAlgorithm : public Algorithm 32 | { 33 | public: 34 | MaxSubgraphAlgorithm(std::string const &name); 35 | virtual ~MaxSubgraphAlgorithm(); 36 | 37 | virtual long Run(std::list> &cliques); 38 | //// virtual long Run(vector const &startingVertices, std::list> &cliques); 39 | 40 | virtual void Color(std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors) = 0; 41 | 42 | virtual void InitializeOrder(std::vector &P, std::vector &vVertexOrder, std::vector &vColors) = 0; 43 | virtual void GetNewOrder(std::vector &vNewVertexOrder, std::vector &vVertexOrder, std::vector const &P, int const chosenVertex) = 0; 44 | virtual void ProcessOrderAfterRecursion(std::vector &vVertexOrder, std::vector &P, std::vector &vColors, int const chosenVertex) = 0; 45 | 46 | virtual void ProcessOrderBeforeReturn(std::vector &vVertexOrder, std::vector &P, std::vector &vColors) = 0; 47 | 48 | virtual void RunRecursive(std::vector &P, std::vector &vVertexOrder, std::list> &cliques, std::vector &vColors); 49 | 50 | virtual void SetQuiet(bool const quiet) { m_bQuiet = quiet; } 51 | 52 | virtual void PrintState() const; 53 | 54 | virtual void SetNodeCount(size_t const count) { nodeCount = count; } 55 | virtual size_t GetNodeCount() { return nodeCount; } 56 | 57 | void SetR(std::vector const &newR) { R = newR; } 58 | void SetMaximumCliqueSize(size_t const newCliqueSize) { m_uMaximumCliqueSize = newCliqueSize; } 59 | 60 | void SetOnlyVertex(int const vertex) { m_iOnlyVertex = vertex; } 61 | 62 | void SetTimeOutInSeconds(double const timeout) { m_TimeOut = timeout*CLOCKS_PER_SEC; } 63 | 64 | bool GetTimedOut() const { return m_bTimedOut; } 65 | 66 | protected: 67 | size_t m_uMaximumCliqueSize; 68 | std::vector R; 69 | std::vector> stackP; 70 | std::vector> stackColors; 71 | std::vector> stackOrder; 72 | size_t nodeCount; 73 | int depth; 74 | clock_t startTime; 75 | clock_t timeToLargestClique; 76 | bool m_bQuiet; 77 | std::vector stackEvaluatedHalfVertices; 78 | //// bool m_bInvert; 79 | int m_iOnlyVertex; 80 | clock_t m_TimeOut; 81 | clock_t m_StartTime; 82 | bool m_bTimedOut; 83 | }; 84 | #endif // MAX_SUBGRAPH_ALGORITHM_H 85 | -------------------------------------------------------------------------------- /src/MemoryManager.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 "MemoryManager.h" 17 | 18 | /*! \file MemoryManager.cpp 19 | 20 | \brief defines malloc and calloc wrapper functions so that we don't 21 | segfault if they return NULL 22 | 23 | \author Darren Strash (first name DOT last name AT gmail DOT com) 24 | 25 | \copyright Copyright (c) 2011 Darren Strash. This code is released under the GNU Public License (GPL) 3.0. 26 | 27 | \image html gplv3-127x51.png 28 | 29 | \htmlonly 30 |
31 | See GPL 3.0 here 32 |
33 | \endhtmlonly 34 | 35 | This functionality is only active if MEMORY_DEBUG is defined, to 36 | make things a little faster. 37 | 38 | */ 39 | 40 | #ifdef MEMORY_DEBUG 41 | 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/MemoryManager.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_MEMORYMANAGER_H_ 17 | #define _DJS_MEMORYMANAGER_H_ 18 | 19 | #include 20 | 21 | /*! \file MemoryManager.h 22 | 23 | \brief see MemoryManager.cpp 24 | 25 | \author Darren Strash (first name DOT last name AT gmail DOT com) 26 | 27 | \copyright Copyright (c) 2011 Darren Strash. This code is released under the GNU Public License (GPL) 3.0. 28 | 29 | \image html gplv3-127x51.png 30 | 31 | \htmlonly 32 |
33 | See GPL 3.0 here 34 |
35 | \endhtmlonly 36 | */ 37 | 38 | #ifdef MEMORY_DEBUG 39 | #include 40 | 41 | /*! \brief Call malloc and ensure that it returns non-NULL. 42 | 43 | \param x, the number of bytes to allocate 44 | 45 | \return a pointer to the allocated memory. If it is null, exit the program with error. 46 | 47 | */ 48 | 49 | static void* MallocWithCheck(size_t x) 50 | { 51 | #ifdef ALLOW_ALLOC_ZERO_BYTES 52 | void* retvalue = malloc(x); 53 | #else 54 | void* retvalue = malloc(max(x,1)); 55 | #endif 56 | 57 | if(retvalue==NULL) 58 | { 59 | fprintf(stderr, "ERROR, malloc returned null pointer, that means we probably ran out of memory...\n"); 60 | exit(1); 61 | } 62 | 63 | return retvalue; 64 | }; 65 | 66 | /*! \brief Call calloc, and ensure that it returns non-NULL. 67 | 68 | \param x, the number of array slots to allocate 69 | 70 | \param x, the number of bytes to allocate in each slot 71 | 72 | \return a pointer to the allocated memory. If it is null, exit the program with error. 73 | 74 | */ 75 | 76 | static void* CallocWithCheck(size_t x, size_t y) 77 | { 78 | #ifdef ALLOW_ALLOC_ZERO_BYTES 79 | void* retvalue = calloc(x,y); 80 | #else 81 | void* retvalue = calloc(max(x,1),max(y,1)); 82 | #endif 83 | 84 | if(retvalue==NULL) 85 | { 86 | fprintf(stderr, "ERROR, calloc returned null pointer, that means we probably ran out of memory...\n"); 87 | exit(1); 88 | } 89 | 90 | return retvalue; 91 | }; 92 | 93 | #define Malloc(x) MallocWithCheck(x) 94 | #define Calloc(x,y) CallocWithCheck(x,y) 95 | #define Free(x) free(x) 96 | 97 | #else 98 | 99 | #ifdef ALLOW_ALLOC_ZERO_BYTES 100 | #define Malloc(x) malloc(x) 101 | #define Calloc(x,y) calloc(x,y) 102 | #define Free(x) free(x) 103 | 104 | #else 105 | 106 | #define Malloc(x) malloc(max(x,1)) 107 | #define Calloc(x,y) calloc(max(x,1),max(y,1)) 108 | #define Free(x) free(x) 109 | 110 | #endif // ALLOW_ALLOC_ZERO_BYTES 111 | #endif // MEMORY_DEBUG 112 | 113 | #endif 114 | 115 | -------------------------------------------------------------------------------- /src/OrderingTools.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 ORDERING_TOOLS_H 17 | #define ORDERING_TOOLS_H 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | namespace OrderingTools 24 | { 25 | void InitialOrderingMCQ(std::vector> const &adjacencyMatrix, std::vector &vOrderedVertices, std::vector &vColoring); 26 | void InitialOrderingMCR(std::vector> const &adjacencyMatrix, std::vector &vOrderedVertices, std::vector &vColoring, size_t &cliqueSize); 27 | void InitialOrderingMCR(std::vector> const &adjacencyArray, std::vector &vOrderedVertices, std::vector &vColoring, size_t &cliqueSize); 28 | 29 | void InitialOrderingMCQ(std::vector> const &adjacencyArray, std::vector &vOrderedVertices, std::vector &vColoring); 30 | 31 | void InitialOrderingMISQ(std::vector> const &adjacencyMatrix, std::vector &vOrderedVertices, std::vector &vColoring); 32 | 33 | void InitialOrderingMISR(std::vector> const &adjacencyArray, std::vector &vOrderedVertices, std::vector &vColoring, size_t &cliqueSize); 34 | 35 | void InitialOrderingMISR(std::vector> const &adjacencyMatrix, std::vector &vOrderedVertices, std::vector &vColoring, size_t &cliqueSize); 36 | 37 | }; 38 | 39 | #endif //ORDERING_TOOLS_H 40 | -------------------------------------------------------------------------------- /src/Set.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 SET_H 17 | #define SET_H 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | class Set 24 | { 25 | public: 26 | Set() : m_State(1) 27 | { 28 | } 29 | 30 | ~Set() {} 31 | 32 | Set(Set const &that) : m_State(that.m_State) 33 | { 34 | } 35 | 36 | Set &operator=(Set const &that) 37 | { 38 | if (this != &that) { 39 | this->m_State = that.m_State; 40 | } 41 | return *this; 42 | } 43 | 44 | void PrintSummary() const 45 | { 46 | std::cout << "P(States): {"; 47 | for (std::set const &P: m_State) { 48 | std::cout << "["; 49 | for (int const p : P) { 50 | std::cout << p << " "; 51 | } 52 | std::cout << "] "; 53 | } 54 | std::cout << "}" << std::endl; 55 | } 56 | 57 | bool Contains(int const x) const { 58 | return m_State.back().find(x) != m_State.back().end(); 59 | } 60 | 61 | void Insert(int const x) { 62 | m_State.back().insert(x); 63 | } 64 | 65 | void Remove(int const x) { 66 | m_State.back().erase(x); 67 | } 68 | 69 | void MoveTo(int const x, Set &other) { 70 | Remove(x); 71 | other.Insert(x); 72 | } 73 | 74 | size_t Size() const { return m_State.back().size(); } 75 | 76 | bool Empty() const { return m_State.back().empty(); } 77 | 78 | void Clear() {m_State.back().clear(); } 79 | 80 | // make copy of current set, and make it the working copy 81 | void SaveState() { 82 | std::set temp(m_State.back()); 83 | m_State.emplace_back(std::move(temp)); 84 | //PrintSummary(); 85 | } 86 | 87 | // you have to make sure that you don't pop_back too many times... 88 | void RestoreState() { 89 | m_State.pop_back(); 90 | //PrintSummary(); 91 | } 92 | 93 | std::set::iterator begin() { return m_State.back().begin(); } 94 | std::set::iterator end() { return m_State.back().end(); } 95 | 96 | std::set::const_iterator begin() const { return m_State.back().begin(); } 97 | std::set::const_iterator end() const { return m_State.back().end(); } 98 | 99 | std::set const &GetStdSet() const { return m_State.back(); } 100 | std::set &GetStdSet() { return m_State.back(); } 101 | 102 | private: 103 | std::vector> m_State; 104 | }; 105 | 106 | #endif // SET_H 107 | -------------------------------------------------------------------------------- /src/SparseArraySet.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 SPARSE_ARRAY_SET_H 17 | #define SPARSE_ARRAY_SET_H 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | class SparseArraySet 26 | { 27 | public: 28 | SparseArraySet(size_t const size) : m_Elements(size, -1), m_iBegin(0), m_iEnd(-1), m_States(0), m_bInserted(false), m_bRemoved(false) 29 | { 30 | } 31 | 32 | SparseArraySet() : m_Elements(), m_iBegin(0), m_iEnd(-1), m_States(0), m_bInserted(false), m_bRemoved(false) 33 | { 34 | } 35 | 36 | ~SparseArraySet() {} 37 | 38 | void Resize(size_t const size) 39 | { 40 | m_Elements.resize(size, -1); 41 | } 42 | 43 | void InitializeFromAdjacencyArray(std::vector> const &adjacencyArray, int const vertex) 44 | { 45 | Resize(adjacencyArray[vertex].size()); 46 | for (int const neighbor : adjacencyArray[vertex]) { 47 | Insert(neighbor); 48 | } 49 | } 50 | 51 | void PrintSummary() const 52 | { 53 | std::cout << "Array[" << m_iBegin << ":" << m_iEnd << "] : "; 54 | for (int const p : *this) { 55 | std::cout << p << (Contains(p)? "":"<-inconsistency") << " "; 56 | } 57 | std::cout << std::endl; 58 | } 59 | 60 | bool Contains(int const x) const { 61 | for (int const value : *this) { 62 | if (value == x) return true; 63 | } 64 | return false; 65 | } 66 | 67 | // Inserts are not allowed after saving state, as it is currently not supported. 68 | void Insert(int const x) { 69 | if (Contains(x)) return; 70 | assert(!m_bRemoved); // not allowed to insert and remove when saving states 71 | if (!m_States.empty()) m_bInserted = true; 72 | m_iEnd++; 73 | m_Elements[m_iEnd] = x; 74 | } 75 | 76 | void Remove(int const x) { 77 | for (int index = m_iBegin; index <= m_iEnd; index++) { 78 | if (m_Elements[index] == x) { 79 | if (!m_States.empty()) m_bRemoved = true; 80 | assert(!m_bInserted); // not allowed to insert and remove when saving states 81 | m_Elements[index] = m_Elements[m_iEnd]; 82 | m_Elements[m_iEnd] = x; 83 | m_iEnd--; 84 | return; 85 | } 86 | } 87 | return; 88 | } 89 | 90 | void MoveTo(int const x, SparseArraySet &other) { 91 | Remove(x); 92 | other.Insert(x); 93 | } 94 | 95 | size_t Size() const { return m_iEnd - m_iBegin + 1; } 96 | bool Empty() const { return m_iEnd < m_iBegin; } 97 | 98 | std::vector::iterator begin() { return m_Elements.begin() + m_iBegin; } 99 | std::vector::iterator end() { return m_Elements.begin() + m_iEnd + 1; } 100 | 101 | std::vector::const_iterator begin() const { return m_Elements.begin() + m_iBegin; } 102 | std::vector::const_iterator end() const { return m_Elements.begin() + m_iEnd + 1; } 103 | 104 | int At(size_t const index) const 105 | { 106 | return m_Elements[index]; 107 | } 108 | 109 | int operator[](size_t const index) const { return At(index); } 110 | 111 | 112 | void SaveState() 113 | { 114 | //// std::cout << "Saving State" << std::endl << std::flush; 115 | m_States.push_back(std::make_pair(m_iBegin, m_iEnd)); 116 | } 117 | 118 | void RestoreState() 119 | { 120 | //// std::cout << "Restoring State" << std::endl << std::flush; 121 | std::pair const &range(m_States.back()); 122 | m_iBegin = range.first; 123 | m_iEnd = range.second; 124 | m_States.pop_back(); 125 | //// std::cout << "#States = " << m_States.size() << std::endl << std::flush; 126 | if (m_States.empty()) { 127 | m_bRemoved = false; 128 | m_bInserted = false; 129 | } 130 | } 131 | 132 | void Clear() 133 | { 134 | m_iBegin = 0; 135 | m_iEnd = -1; 136 | } 137 | 138 | static bool Test() { 139 | std::cout << "SparseArraySet: "; 140 | SparseArraySet testSet(3); 141 | testSet.Insert(0); 142 | testSet.Insert(1); 143 | testSet.Insert(2); 144 | 145 | if (!testSet.Contains(0) || !testSet.Contains(1) || !testSet.Contains(2) || testSet.Size() != 3) { 146 | std::cout << "FAILED: SparseArraySet failed ContainsTest" << std::endl; 147 | return false; 148 | } 149 | 150 | testSet.Remove(0); 151 | if (testSet.Contains(0) || testSet.Size() != 2) { 152 | std::cout << "FAILED: SparseArraySet failed RemoveFirst Test" << std::endl; 153 | return false; 154 | } 155 | 156 | testSet.Insert(0); 157 | if (!testSet.Contains(0) || !testSet.Contains(1) || !testSet.Contains(2) || testSet.Size() != 3) { 158 | std::cout << "FAILED: SparseArraySet failed RemoveAdd Test" << std::endl; 159 | return false; 160 | } 161 | 162 | testSet.Remove(0); 163 | if (testSet.Contains(0) || testSet.Size() != 2) { 164 | std::cout << "FAILED: SparseArraySet failed RemoveLast Test" << std::endl; 165 | return false; 166 | } 167 | 168 | testSet.Insert(0); 169 | testSet.Remove(1); 170 | if (testSet.Contains(1) || testSet.Size() != 2) { 171 | std::cout << "FAILED: SparseArraySet failed RemoveMiddle Test" << std::endl; 172 | return false; 173 | } 174 | 175 | testSet.Insert(1); 176 | testSet.Remove(1); 177 | testSet.Remove(2); 178 | testSet.Remove(0); 179 | if (testSet.Contains(0) || testSet.Contains(1) || testSet.Contains(2) || testSet.Size() != 0 || !testSet.Empty()) { 180 | std::cout << "FAILED: SparseArraySet failed RemoveAll Test" << std::endl; 181 | return false; 182 | } 183 | 184 | testSet.Insert(0); 185 | testSet.Insert(1); 186 | testSet.Insert(2); 187 | if (!testSet.Contains(0) || !testSet.Contains(1) || !testSet.Contains(2) || testSet.Size() != 3) { 188 | std::cout << "FAILED: SparseArraySet failed InsertAll Test" << std::endl; 189 | return false; 190 | } 191 | 192 | testSet.SaveState(); 193 | if (!testSet.Contains(0) || !testSet.Contains(1) || !testSet.Contains(2) || testSet.Size() != 3) { 194 | std::cout << "FAILED: SparseArraySet failed SaveState Test" << std::endl; 195 | return false; 196 | } 197 | 198 | testSet.Remove(0); 199 | if (testSet.Contains(0) || !testSet.Contains(1) || !testSet.Contains(2) || testSet.Size() != 2) { 200 | std::cout << "FAILED: SparseArraySet failed RemoveAfterSave Test" << std::endl; 201 | return false; 202 | } 203 | 204 | testSet.RestoreState(); 205 | if (!testSet.Contains(0) || !testSet.Contains(1) || !testSet.Contains(2) || testSet.Size() != 3) { 206 | std::cout << "FAILED: SparseArraySet failed RestoreState Test" << std::endl; 207 | return false; 208 | } 209 | 210 | std::cout << "PASSED!" << std::endl << std::flush; 211 | return true; 212 | } 213 | 214 | private: 215 | std::vector m_Elements; 216 | int m_iBegin; 217 | int m_iEnd; 218 | std::vector> m_States; 219 | bool m_bInserted; 220 | bool m_bRemoved; 221 | }; 222 | 223 | #endif // SPARSE_ARRAY_SET_H 224 | -------------------------------------------------------------------------------- /src/SparseCliqueColoringStrategy.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 "SparseCliqueColoringStrategy.h" 17 | #include "DegeneracyTools.h" 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | using namespace std; 25 | 26 | SparseCliqueColoringStrategy::SparseCliqueColoringStrategy(vector> const &adjacencyArray) 27 | : ColoringStrategy() 28 | , m_AdjacencyArray(adjacencyArray) 29 | , m_vlColorToVertices() 30 | , m_vVertexToColor(adjacencyArray.size(), -1) 31 | , m_vNeighborHasColor() 32 | , m_vvVerticesWithColor(adjacencyArray.size()) 33 | , m_vNeighborColorCount(adjacencyArray.size(), 0) 34 | , m_vbNeighbors(adjacencyArray.size(), false) 35 | , m_vbConflictNeighbors(adjacencyArray.size(), false) 36 | { 37 | //// m_VertexOrder = std::move(GetVerticesInDegeneracyOrder(adjacencyArray)); 38 | } 39 | 40 | // TODO/DS (17.03.2016): Is the sparse independent set version better? 41 | // Using lists isn't very efficient. Use m_vvVerticesWithColor instead 42 | void SparseCliqueColoringStrategy::Color(vector> const &adjacencyArray, vector const &vVertexOrder, vector &vVerticesToReorder, vector &vColors) 43 | { 44 | if (vVerticesToReorder.empty()) return; 45 | 46 | #if 0 47 | cout << "Coloring (in ): "; 48 | //// for (int const vertex : vVerticesToReorder) { 49 | for (int index = 0; index < vVerticesToReorder.size(); index++) { 50 | int const vertex(vVerticesToReorder[index]); 51 | cout << vertex << "(" << vColors[index] << ") "; 52 | } 53 | cout << endl; 54 | #endif // 0 55 | 56 | size_t maxColor(0); 57 | 58 | m_vlColorToVertices.resize(vVerticesToReorder.size()); 59 | m_vNeighborHasColor.resize(vVerticesToReorder.size(), false); 60 | 61 | size_t const numVerticesToReorder(vVerticesToReorder.size()); 62 | 63 | for (int const vertex : vVertexOrder) { 64 | size_t color = 0; 65 | for (int const neighbor : adjacencyArray[vertex]) { 66 | if (m_vVertexToColor[neighbor] != -1) { 67 | m_vNeighborHasColor[m_vVertexToColor[neighbor]] = true; 68 | } 69 | } 70 | 71 | for (size_t color = 0; color < m_vNeighborHasColor.size(); ++color) { 72 | if (!m_vNeighborHasColor[color]) { 73 | m_vlColorToVertices[color].push_back(vertex); 74 | m_vVertexToColor[vertex] = color; 75 | maxColor = max(maxColor, color); 76 | break; 77 | } 78 | } 79 | 80 | for (int const neighbor : adjacencyArray[vertex]) { 81 | if (m_vVertexToColor[neighbor] != -1) { 82 | m_vNeighborHasColor[m_vVertexToColor[neighbor]] = false; 83 | } 84 | } 85 | } 86 | 87 | //// cout << "maxColor=" << maxColor << ", numVertices=" << vVerticesToReorder.size() << endl; 88 | 89 | int currentIndex(0); 90 | int currentColor(0); 91 | for (int currentColor = 0; currentColor <= maxColor; ++currentColor) { 92 | for (int const vertex : m_vlColorToVertices[currentColor]) { 93 | vVerticesToReorder[currentIndex] = vertex; 94 | vColors[currentIndex] = currentColor + 1; 95 | currentIndex++; 96 | 97 | m_vVertexToColor[vertex] = -1; // reset all vertex colorings to be invalid 98 | } 99 | m_vlColorToVertices[currentColor].clear(); 100 | } 101 | 102 | #if 0 103 | cout << "Coloring (out): "; 104 | for (int index = 0; index < vVerticesToReorder.size(); index++) { 105 | int const vertex(vVerticesToReorder[index]); 106 | cout << vertex << "(" << vColors[index] << ") "; 107 | } 108 | cout << endl; 109 | #endif // 0 110 | 111 | // verify that it is a valid coloring. 112 | #if DEBUG ////def DEBUG 113 | vector vColor(adjacencyArray.size(), -1); 114 | for (size_t index = 0; index < vVerticesToReorder.size(); ++index) { 115 | vColor[vVerticesToReorder[index]] = vColors[index]; 116 | } 117 | for (int const vertex : vVerticesToReorder) { 118 | for (int const neighbor : adjacencyArray[vertex]) { 119 | if (vColor[vertex] == vColor[neighbor]) { 120 | cout << "Consistency Error: vertex " << vertex << " has the same color as neighbor " << neighbor << ", color=" << vColor[vertex] << endl << flush; 121 | } 122 | } 123 | } 124 | #endif // DEBUG 125 | } 126 | 127 | void SparseCliqueColoringStrategy::Color(vector> const &adjacencyArray, vector &vVerticesToReorder, vector &vColors) 128 | { 129 | Color(adjacencyArray, vVerticesToReorder, vVerticesToReorder, vColors); 130 | } 131 | 132 | 133 | // TODO/DS: Convert to Sparse 134 | void SparseCliqueColoringStrategy::Recolor(vector> const &adjacencyArray, vector const &vVertexOrder, vector &vVerticesToReorder, vector &vColors, int const currentBestCliqueSize, int const currentCliqueSize) 135 | { 136 | if (vVerticesToReorder.empty()) return; 137 | 138 | #if 0 139 | cout << "Coloring (in ): "; 140 | //// for (int const vertex : vVerticesToReorder) { 141 | for (int index = 0; index < vVerticesToReorder.size(); index++) { 142 | int const vertex(vVerticesToReorder[index]); 143 | cout << vertex << "(" << vColors[index] << ") "; 144 | } 145 | cout << endl; 146 | #endif // 0 147 | 148 | int maxColor(-1); 149 | 150 | int iBestCliqueDelta(currentBestCliqueSize - currentCliqueSize); 151 | 152 | size_t const numVerticesToReorder(vVerticesToReorder.size()); 153 | 154 | for (int const vertex : vVertexOrder) { 155 | #if 1 156 | int uSmallestFreeColor = maxColor + 1; 157 | // first count the number of neighbors with a given color 158 | for (int const neighbor : m_AdjacencyArray[vertex]) { 159 | m_vbNeighbors[neighbor] = true; 160 | if (m_vVertexToColor[neighbor] != -1) { 161 | m_vNeighborColorCount[m_vVertexToColor[neighbor]]++; 162 | } 163 | } 164 | 165 | // compare color counts to total number of vertices with the color 166 | // if there is a difference, then there exists a non-neighbor with 167 | // that color; otherwise the color is free. Pick the smallest such 168 | // free color 169 | for (int const neighbor : m_AdjacencyArray[vertex]) { 170 | int const currentColor(m_vVertexToColor[neighbor]); 171 | //// if (debug && neighbor==28) { 172 | //// cout << " neighbor 28 has color " << currentColor << ", there are " << m_vvVerticesWithColor[currentColor].size() << " vertices with that color, and " << m_vNeighborColorCount[currentColor] << " neighbors with that color" << endl; 173 | //// } 174 | if (currentColor != -1 && static_cast(m_vvVerticesWithColor[currentColor].size()) == m_vNeighborColorCount[currentColor]) { 175 | uSmallestFreeColor = min(currentColor, static_cast(uSmallestFreeColor)); 176 | } 177 | } 178 | 179 | //// // put color counts back to 0. 180 | //// for (int const neighbor : m_AdjacencyArray[vertex]) { 181 | //// if (m_vVertexToColor[neighbor] != -1) { 182 | //// m_vNeighborColorCount[m_vVertexToColor[neighbor]] = 0; 183 | //// } 184 | //// } 185 | 186 | #else 187 | int uSmallestFreeColor = 0; 188 | for (vector const &verticesWithColor : m_vvVerticesWithColor) { 189 | bool hasNeighborWithColor(false); 190 | if (verticesWithColor.empty()) break; 191 | for (int const coloredVertex : verticesWithColor) { 192 | // can be made more efficient? 193 | hasNeighborWithColor = (find(adjacencyArray[vertex].begin(), adjacencyArray[vertex].end(), coloredVertex) == adjacencyArray[vertex].end()); 194 | if (hasNeighborWithColor) { 195 | uSmallestFreeColor++; 196 | break; 197 | } 198 | } 199 | 200 | if (!hasNeighborWithColor) { 201 | break; 202 | } 203 | } 204 | #endif // 1 205 | //// cout << "vertex " << vertex << " gets initial color " << uSmallestFreeColor << endl; 206 | 207 | m_vvVerticesWithColor[uSmallestFreeColor].push_back(vertex); 208 | m_vVertexToColor[vertex] = uSmallestFreeColor; 209 | maxColor = max(maxColor, uSmallestFreeColor); 210 | if (uSmallestFreeColor +1 > iBestCliqueDelta && /*m_vvVerticesWithColor[color].size() == 1*/ uSmallestFreeColor == maxColor) { 211 | Repair(vertex, uSmallestFreeColor, iBestCliqueDelta); 212 | if (m_vvVerticesWithColor[maxColor].empty()) 213 | maxColor--; 214 | } 215 | 216 | // put color counts back to 0. Needs to come after repair, repair uses the counts. 217 | for (int const neighbor : m_AdjacencyArray[vertex]) { 218 | m_vbNeighbors[neighbor] = false; 219 | if (m_vVertexToColor[neighbor] != -1) { 220 | m_vNeighborColorCount[m_vVertexToColor[neighbor]] = 0; 221 | } 222 | } 223 | } 224 | 225 | //// cout << "maxColor=" << maxColor << ", numVertices=" << vVerticesToReorder.size() << endl; 226 | 227 | int currentIndex(0); 228 | int currentColor(0); 229 | for (int currentColor = 0; currentColor <= maxColor; ++currentColor) { 230 | for (int const vertex : m_vvVerticesWithColor[currentColor]) { 231 | vVerticesToReorder[currentIndex] = vertex; 232 | vColors[currentIndex] = currentColor+1; 233 | currentIndex++; 234 | 235 | m_vVertexToColor[vertex] = -1; 236 | } 237 | m_vvVerticesWithColor[currentColor].clear(); 238 | } 239 | 240 | #if 0 241 | cout << "Coloring (out): "; 242 | for (int index = 0; index < vVerticesToReorder.size(); index++) { 243 | int const vertex(vVerticesToReorder[index]); 244 | cout << vertex << "(" << vColors[index] << ") "; 245 | } 246 | cout << endl; 247 | #endif // 0 248 | 249 | // verify that it is a valid coloring. 250 | #ifdef DEBUG 251 | vector vColor(adjacencyArray.size(), -1); 252 | for (size_t index = 0; index < vVerticesToReorder.size(); ++index) { 253 | vColor[vVerticesToReorder[index]] = vColors[index]; 254 | } 255 | for (int const vertex : vVerticesToReorder) { 256 | for (int const neighbor : adjacencyArray[vertex]) { 257 | if (vColor[vertex] == vColor[neighbor]) { 258 | cout << "Consistency Error: vertex " << vertex << " has the same color as neighbor " << neighbor << ", color=" << vColor[vertex] << endl << flush; 259 | } 260 | } 261 | } 262 | #endif // DEBUG 263 | } 264 | 265 | bool SparseCliqueColoringStrategy::HasConflict(int const vertex, vector const &vVerticesWithColor) 266 | { 267 | if (vVerticesWithColor.empty()) return false; 268 | for (int const coloredVertex : vVerticesWithColor) { 269 | // can be made more efficient? 270 | if (m_vbConflictNeighbors[coloredVertex]) { 271 | return true; 272 | } 273 | } 274 | 275 | return false; 276 | } 277 | 278 | int SparseCliqueColoringStrategy::GetConflictingVertex(int const vertex, vector const &vVerticesWithColor) 279 | { 280 | int conflictingVertex(-1); 281 | int count(0); 282 | for (int const candidateVertex : vVerticesWithColor) { 283 | if (m_vbNeighbors[candidateVertex]) { ////find(m_AdjacencyArray[vertex].begin(), m_AdjacencyArray[vertex].end(), candidateVertex) == m_AdjacencyArray[vertex].end()) { 284 | conflictingVertex = candidateVertex; 285 | count++; 286 | if (count > 1) return -1; 287 | } 288 | } 289 | return conflictingVertex; 290 | } 291 | 292 | bool SparseCliqueColoringStrategy::Repair(int const vertex, int const color, int const iBestCliqueDelta) 293 | { 294 | for (int newColor = 0; newColor <= iBestCliqueDelta-1; newColor++) { 295 | int const conflictingVertex(GetConflictingVertex(vertex, m_vvVerticesWithColor[newColor])); 296 | if (conflictingVertex < 0) continue; 297 | 298 | for (int const neighbor : m_AdjacencyArray[conflictingVertex]) { 299 | m_vbConflictNeighbors[neighbor] = true; 300 | } 301 | 302 | // TODO/DS: put conflicting neighbors into array for quick testing. 303 | for (int nextColor = newColor+1; nextColor <= iBestCliqueDelta; nextColor++) { 304 | if (HasConflict(conflictingVertex, m_vvVerticesWithColor[nextColor])) continue; 305 | m_vvVerticesWithColor[color].erase(find(m_vvVerticesWithColor[color].begin(), m_vvVerticesWithColor[color].end(), vertex)); 306 | m_vvVerticesWithColor[newColor].erase(find(m_vvVerticesWithColor[newColor].begin(), m_vvVerticesWithColor[newColor].end(), conflictingVertex)); 307 | m_vvVerticesWithColor[newColor].push_back(vertex); 308 | m_vvVerticesWithColor[nextColor].push_back(conflictingVertex); 309 | 310 | m_vVertexToColor[vertex] = newColor; 311 | m_vVertexToColor[conflictingVertex] = nextColor; 312 | //// cout << "Repairing vertices " << vertex << " and " << conflictingVertex << endl; 313 | 314 | for (int const neighbor : m_AdjacencyArray[conflictingVertex]) { 315 | m_vbConflictNeighbors[neighbor] = false; 316 | } 317 | return true; 318 | } 319 | 320 | for (int const neighbor : m_AdjacencyArray[conflictingVertex]) { 321 | m_vbConflictNeighbors[neighbor] = false; 322 | } 323 | } 324 | return false; 325 | } 326 | -------------------------------------------------------------------------------- /src/SparseCliqueColoringStrategy.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 SPARSE_CLIQUE_COLORING_STRATEGY 17 | #define SPARSE_CLIQUE_COLORING_STRATEGY 18 | 19 | #include "ColoringStrategy.h" 20 | 21 | #include 22 | #include 23 | 24 | class SparseCliqueColoringStrategy : public ColoringStrategy 25 | { 26 | public: 27 | SparseCliqueColoringStrategy(std::vector> const &adjacencyList); 28 | virtual void Color(std::vector> const &adjacencyList, std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors); 29 | virtual void Color(std::vector> const &adjacencyList, std::vector &vVerticesToReorder, std::vector &vColors); 30 | 31 | virtual void Recolor(std::vector> const &adjacencyArray, std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors, int const currentBestCliqueSize, int const currentCliqueSize); 32 | bool HasConflict(int const vertex, std::vector const &vVerticesWithColor); 33 | int GetConflictingVertex(int const vertex, std::vector const &vVerticesWithColor); 34 | bool Repair(int const vertex, int const color, int const iBestCliqueDelta); 35 | 36 | protected: 37 | std::vector> const &m_AdjacencyArray; 38 | std::vector> m_vlColorToVertices; 39 | std::vector m_vVertexToColor; 40 | std::vector m_vNeighborHasColor; 41 | // From SparseIndependentSetColoringStrategy 42 | std::vector> m_vvVerticesWithColor; 43 | std::vector m_vNeighborColorCount; 44 | std::vector m_vbNeighbors; 45 | std::vector m_vbConflictNeighbors; 46 | }; 47 | 48 | #endif //SPARSE_CLIQUE_COLORING_STRATEGY 49 | -------------------------------------------------------------------------------- /src/SparseIndependentSetColoringStrategy.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 "SparseIndependentSetColoringStrategy.h" 17 | #include "DegeneracyTools.h" 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | using namespace std; 25 | 26 | SparseIndependentSetColoringStrategy::SparseIndependentSetColoringStrategy(vector> const &adjacencyArray) 27 | : ColoringStrategy() 28 | , m_AdjacencyArray(adjacencyArray) 29 | , m_vVertexToColor(adjacencyArray.size(), -1) 30 | , m_vvVerticesWithColor(adjacencyArray.size()) 31 | , m_vNeighborColorCount(adjacencyArray.size(), 0) 32 | , m_vbNeighbors(adjacencyArray.size(), false) 33 | , m_vbConflictNeighbors(adjacencyArray.size(), false) 34 | { 35 | } 36 | 37 | void SparseIndependentSetColoringStrategy::Color(vector> const &adjacencyArray, vector const &vVertexOrder, vector &vVerticesToReorder, vector &vColors) 38 | { 39 | if (vVerticesToReorder.empty()) return; 40 | 41 | #if 0 42 | cout << "Coloring (in ): "; 43 | //// for (int const vertex : vVerticesToReorder) { 44 | for (int index = 0; index < vVerticesToReorder.size(); index++) { 45 | int const vertex(vVerticesToReorder[index]); 46 | cout << vertex << "(" << vColors[index] << ") "; 47 | } 48 | cout << endl; 49 | #endif // 0 50 | 51 | int maxColor(-1); 52 | 53 | size_t const numVerticesToReorder(vVerticesToReorder.size()); 54 | 55 | for (int const vertex : vVertexOrder) { 56 | 57 | // choose the smallest color of any non-neighbor vertex. 58 | #if 1 59 | int uSmallestFreeColor = maxColor + 1; 60 | // first count the number of neighbors with a given color 61 | for (int const neighbor : m_AdjacencyArray[vertex]) { 62 | if (m_vVertexToColor[neighbor] != -1) { 63 | m_vNeighborColorCount[m_vVertexToColor[neighbor]]++; 64 | } 65 | } 66 | 67 | // compare color counts to total number of vertices with the color 68 | // if there is a difference, then there exists a non-neighbor with 69 | // that color; otherwise the color is free. Pick the smallest such 70 | // free color 71 | for (int const neighbor : m_AdjacencyArray[vertex]) { 72 | int const currentColor(m_vVertexToColor[neighbor]); 73 | if (currentColor != -1 && static_cast(m_vvVerticesWithColor[currentColor].size()) == m_vNeighborColorCount[currentColor]) { 74 | uSmallestFreeColor = min(currentColor, uSmallestFreeColor); 75 | } 76 | } 77 | 78 | // put color counts back to 0. 79 | for (int const neighbor : m_AdjacencyArray[vertex]) { 80 | if (m_vVertexToColor[neighbor] != -1) { 81 | m_vNeighborColorCount[m_vVertexToColor[neighbor]] = 0; 82 | } 83 | } 84 | #else 85 | int uSmallestFreeColor(0); 86 | for (vector const &verticesWithColor : m_vvVerticesWithColor) { 87 | bool hasNeighborWithColor(false); 88 | if (verticesWithColor.empty()) break; 89 | for (int const coloredVertex : verticesWithColor) { 90 | // can be made more efficient? 91 | hasNeighborWithColor = (find(adjacencyArray[vertex].begin(), adjacencyArray[vertex].end(), coloredVertex) == adjacencyArray[vertex].end()); 92 | if (hasNeighborWithColor) { 93 | uSmallestFreeColor++; 94 | break; 95 | } 96 | } 97 | 98 | if (!hasNeighborWithColor) { 99 | break; 100 | } 101 | } 102 | #endif // 1 103 | 104 | m_vvVerticesWithColor[uSmallestFreeColor].push_back(vertex); 105 | m_vVertexToColor[vertex] = uSmallestFreeColor; 106 | maxColor = max(maxColor, uSmallestFreeColor); 107 | } 108 | 109 | //// cout << "maxColor=" << maxColor << ", numVertices=" << vVerticesToReorder.size() << endl; 110 | 111 | int currentIndex(0); 112 | int currentColor(0); 113 | for (int currentColor = 0; currentColor <= maxColor; ++currentColor) { 114 | for (int const vertex : m_vvVerticesWithColor[currentColor]) { 115 | vVerticesToReorder[currentIndex] = vertex; 116 | vColors[currentIndex] = currentColor+1; 117 | currentIndex++; 118 | m_vVertexToColor[vertex] = -1; 119 | } 120 | m_vvVerticesWithColor[currentColor].clear(); 121 | } 122 | 123 | #if 0 124 | cout << "Coloring (out): "; 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 | // verify that it is a valid coloring. 133 | #ifdef DEBUG 134 | vector vColor(adjacencyList.size(), -1); 135 | for (size_t index = 0; index < vVerticesToReorder.size(); ++index) { 136 | vColor[vVerticesToReorder[index]] = vColors[index]; 137 | } 138 | for (int const vertex : vVerticesToReorder) { 139 | for (int const neighbor : adjacencyList[vertex]) { 140 | if (vColor[vertex] == vColor[neighbor]) { 141 | cout << "Consistency Error: vertex " << vertex << " has the same color as neighbor " << neighbor << ", color=" << vColor[vertex] << endl << flush; 142 | } 143 | } 144 | } 145 | #endif // DEBUG 146 | } 147 | 148 | 149 | // TODO/DS: Speedup recolor in sparse framework 150 | void SparseIndependentSetColoringStrategy::Recolor(vector> const &adjacencyArray, vector const &vVertexOrder, vector &vVerticesToReorder, vector &vColors, int const currentBestCliqueSize, int const currentCliqueSize) 151 | { 152 | if (vVerticesToReorder.empty()) return; 153 | 154 | #if 0 155 | cout << "Coloring (in ): "; 156 | //// for (int const vertex : vVerticesToReorder) { 157 | for (int index = 0; index < vVerticesToReorder.size(); index++) { 158 | int const vertex(vVerticesToReorder[index]); 159 | cout << vertex << "(" << vColors[index] << ") "; 160 | } 161 | cout << endl; 162 | #endif // 0 163 | 164 | int maxColor(-1); 165 | 166 | int iBestCliqueDelta(currentBestCliqueSize - currentCliqueSize); 167 | 168 | size_t const numVerticesToReorder(vVerticesToReorder.size()); 169 | 170 | for (int const vertex : vVertexOrder) { 171 | //// bool debug(vertex==29); 172 | //// 173 | //// if (debug) { 174 | //// cout << "State: " << endl; 175 | //// for (size_t colorIndex=0; colorIndex < m_vvVerticesWithColor.size(); colorIndex++) { 176 | //// cout << " Color " << colorIndex << ": "; 177 | //// if (m_vvVerticesWithColor[colorIndex].empty()) break; 178 | //// for (int const vertex : m_vvVerticesWithColor[colorIndex]) { 179 | //// cout << vertex << " "; 180 | //// } 181 | //// cout << endl; 182 | //// } 183 | //// cout << endl; 184 | //// cout << "Neighbors: " << endl; 185 | //// for (int const neighbor : m_AdjacencyArray[vertex]) { 186 | //// cout << neighbor << " "; 187 | //// } 188 | //// cout << endl; 189 | //// } 190 | 191 | #if 1 192 | int uSmallestFreeColor = maxColor + 1; 193 | // first count the number of neighbors with a given color 194 | for (int const neighbor : m_AdjacencyArray[vertex]) { 195 | m_vbNeighbors[neighbor] = true; 196 | if (m_vVertexToColor[neighbor] != -1) { 197 | m_vNeighborColorCount[m_vVertexToColor[neighbor]]++; 198 | } 199 | } 200 | 201 | // compare color counts to total number of vertices with the color 202 | // if there is a difference, then there exists a non-neighbor with 203 | // that color; otherwise the color is free. Pick the smallest such 204 | // free color 205 | for (int const neighbor : m_AdjacencyArray[vertex]) { 206 | int const currentColor(m_vVertexToColor[neighbor]); 207 | //// if (debug && neighbor==28) { 208 | //// cout << " neighbor 28 has color " << currentColor << ", there are " << m_vvVerticesWithColor[currentColor].size() << " vertices with that color, and " << m_vNeighborColorCount[currentColor] << " neighbors with that color" << endl; 209 | //// } 210 | if (currentColor != -1 && static_cast(m_vvVerticesWithColor[currentColor].size()) == m_vNeighborColorCount[currentColor]) { 211 | uSmallestFreeColor = min(currentColor, static_cast(uSmallestFreeColor)); 212 | } 213 | } 214 | 215 | //// // put color counts back to 0. 216 | //// for (int const neighbor : m_AdjacencyArray[vertex]) { 217 | //// if (m_vVertexToColor[neighbor] != -1) { 218 | //// m_vNeighborColorCount[m_vVertexToColor[neighbor]] = 0; 219 | //// } 220 | //// } 221 | 222 | #else 223 | int uSmallestFreeColor = 0; 224 | for (vector const &verticesWithColor : m_vvVerticesWithColor) { 225 | bool hasNeighborWithColor(false); 226 | if (verticesWithColor.empty()) break; 227 | for (int const coloredVertex : verticesWithColor) { 228 | // can be made more efficient? 229 | hasNeighborWithColor = (find(adjacencyArray[vertex].begin(), adjacencyArray[vertex].end(), coloredVertex) == adjacencyArray[vertex].end()); 230 | if (hasNeighborWithColor) { 231 | uSmallestFreeColor++; 232 | break; 233 | } 234 | } 235 | 236 | if (!hasNeighborWithColor) { 237 | break; 238 | } 239 | } 240 | #endif // 1 241 | //// cout << "vertex " << vertex << " gets initial color " << uSmallestFreeColor << endl; 242 | 243 | m_vvVerticesWithColor[uSmallestFreeColor].push_back(vertex); 244 | m_vVertexToColor[vertex] = uSmallestFreeColor; 245 | maxColor = max(maxColor, uSmallestFreeColor); 246 | if (uSmallestFreeColor +1 > iBestCliqueDelta && /*m_vvVerticesWithColor[color].size() == 1*/ uSmallestFreeColor == maxColor) { 247 | Repair(vertex, uSmallestFreeColor, iBestCliqueDelta); 248 | if (m_vvVerticesWithColor[maxColor].empty()) 249 | maxColor--; 250 | } 251 | 252 | // put color counts back to 0. Needs to come after repair, repair uses the counts. 253 | for (int const neighbor : m_AdjacencyArray[vertex]) { 254 | m_vbNeighbors[neighbor] = false; 255 | if (m_vVertexToColor[neighbor] != -1) { 256 | m_vNeighborColorCount[m_vVertexToColor[neighbor]] = 0; 257 | } 258 | } 259 | } 260 | 261 | //// cout << "maxColor=" << maxColor << ", numVertices=" << vVerticesToReorder.size() << endl; 262 | 263 | int currentIndex(0); 264 | int currentColor(0); 265 | for (int currentColor = 0; currentColor <= maxColor; ++currentColor) { 266 | for (int const vertex : m_vvVerticesWithColor[currentColor]) { 267 | vVerticesToReorder[currentIndex] = vertex; 268 | vColors[currentIndex] = currentColor+1; 269 | currentIndex++; 270 | 271 | m_vVertexToColor[vertex] = -1; 272 | } 273 | m_vvVerticesWithColor[currentColor].clear(); 274 | } 275 | 276 | #if 0 277 | cout << "Coloring (out): "; 278 | for (int index = 0; index < vVerticesToReorder.size(); index++) { 279 | int const vertex(vVerticesToReorder[index]); 280 | cout << vertex << "(" << vColors[index] << ") "; 281 | } 282 | cout << endl; 283 | #endif // 0 284 | 285 | // verify that it is a valid coloring. 286 | #ifdef DEBUG 287 | vector vColor(adjacencyList.size(), -1); 288 | for (size_t index = 0; index < vVerticesToReorder.size(); ++index) { 289 | vColor[vVerticesToReorder[index]] = vColors[index]; 290 | } 291 | for (int const vertex : vVerticesToReorder) { 292 | for (int const neighbor : adjacencyList[vertex]) { 293 | if (vColor[vertex] == vColor[neighbor]) { 294 | cout << "Consistency Error: vertex " << vertex << " has the same color as neighbor " << neighbor << ", color=" << vColor[vertex] << endl << flush; 295 | } 296 | } 297 | } 298 | #endif // DEBUG 299 | } 300 | 301 | bool SparseIndependentSetColoringStrategy::HasConflict(int const vertex, vector const &vVerticesWithColor) 302 | { 303 | if (vVerticesWithColor.empty()) return false; 304 | for (int const coloredVertex : vVerticesWithColor) { 305 | // can be made more efficient? 306 | if (!m_vbConflictNeighbors[coloredVertex]) { 307 | return true; 308 | } 309 | } 310 | 311 | return false; 312 | } 313 | 314 | int SparseIndependentSetColoringStrategy::GetConflictingVertex(int const vertex, vector const &vVerticesWithColor) 315 | { 316 | int conflictingVertex(-1); 317 | int count(0); 318 | for (int const candidateVertex : vVerticesWithColor) { 319 | if (!m_vbNeighbors[candidateVertex]) { ////find(m_AdjacencyArray[vertex].begin(), m_AdjacencyArray[vertex].end(), candidateVertex) == m_AdjacencyArray[vertex].end()) { 320 | conflictingVertex = candidateVertex; 321 | count++; 322 | if (count > 1) return -1; 323 | } 324 | } 325 | return conflictingVertex; 326 | } 327 | 328 | bool SparseIndependentSetColoringStrategy::Repair(int const vertex, int const color, int const iBestCliqueDelta) 329 | { 330 | for (int newColor = 0; newColor <= iBestCliqueDelta-1; newColor++) { 331 | int const conflictingVertex(GetConflictingVertex(vertex, m_vvVerticesWithColor[newColor])); 332 | if (conflictingVertex < 0) continue; 333 | 334 | for (int const neighbor : m_AdjacencyArray[conflictingVertex]) { 335 | m_vbConflictNeighbors[neighbor] = true; 336 | } 337 | 338 | // TODO/DS: put conflicting neighbors into array for quick testing. 339 | for (int nextColor = newColor+1; nextColor <= iBestCliqueDelta; nextColor++) { 340 | if (HasConflict(conflictingVertex, m_vvVerticesWithColor[nextColor])) continue; 341 | m_vvVerticesWithColor[color].erase(find(m_vvVerticesWithColor[color].begin(), m_vvVerticesWithColor[color].end(), vertex)); 342 | m_vvVerticesWithColor[newColor].erase(find(m_vvVerticesWithColor[newColor].begin(), m_vvVerticesWithColor[newColor].end(), conflictingVertex)); 343 | m_vvVerticesWithColor[newColor].push_back(vertex); 344 | m_vvVerticesWithColor[nextColor].push_back(conflictingVertex); 345 | 346 | m_vVertexToColor[vertex] = newColor; 347 | m_vVertexToColor[conflictingVertex] = nextColor; 348 | //// cout << "Repairing vertices " << vertex << " and " << conflictingVertex << endl; 349 | 350 | for (int const neighbor : m_AdjacencyArray[conflictingVertex]) { 351 | m_vbConflictNeighbors[neighbor] = false; 352 | } 353 | return true; 354 | } 355 | 356 | for (int const neighbor : m_AdjacencyArray[conflictingVertex]) { 357 | m_vbConflictNeighbors[neighbor] = false; 358 | } 359 | } 360 | return false; 361 | } 362 | -------------------------------------------------------------------------------- /src/SparseIndependentSetColoringStrategy.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 SPARSE_IS_COLORING_STRATEGY 17 | #define SPARSE_IS_COLORING_STRATEGY 18 | 19 | #include "ColoringStrategy.h" 20 | 21 | class SparseIndependentSetColoringStrategy : public ColoringStrategy 22 | { 23 | public: 24 | SparseIndependentSetColoringStrategy(std::vector> const &adjacencyArray); 25 | virtual void Color(std::vector> const &adjacencyArray, std::vector const &vVertexOrder, std::vector &vVerticesToReorder, std::vector &vColors); 26 | virtual void Recolor(std::vector> const &adjacencyArray, 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_AdjacencyArray; 35 | std::vector> m_vvVerticesWithColor; 36 | std::vector m_vVertexToColor; 37 | std::vector m_vNeighborColorCount; 38 | std::vector m_vbNeighbors; 39 | std::vector m_vbConflictNeighbors; 40 | //// std::vector m_Colors; 41 | //// std::vector m_VertexOrder; 42 | }; 43 | 44 | #endif //SPARSE_IS_COLORING_STRATEGY 45 | -------------------------------------------------------------------------------- /src/StaticOrderMCS.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 "StaticOrderMCS.h" 17 | #include "OrderingTools.h" 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | using namespace std; 24 | 25 | StaticOrderMCS::StaticOrderMCS(vector> const &vAdjacencyMatrix) 26 | : MCQ(vAdjacencyMatrix) 27 | { 28 | SetName("static-order-mcs"); 29 | } 30 | 31 | void StaticOrderMCS::InitializeOrder(std::vector &P, std::vector &vVertexOrder, std::vector &vColors) 32 | { 33 | OrderingTools::InitialOrderingMCR(m_AdjacencyMatrix, P, vColors, m_uMaximumCliqueSize); 34 | vVertexOrder = P; 35 | } 36 | 37 | void StaticOrderMCS::GetNewOrder(vector &vNewVertexOrder, vector &vVertexOrder, vector const &P, int const chosenVertex) 38 | { 39 | vNewVertexOrder.resize(P.size()); 40 | { 41 | size_t uNewIndex(0); 42 | for (int const candidate : vVertexOrder) { 43 | if (m_AdjacencyMatrix[chosenVertex][candidate]) vNewVertexOrder[uNewIndex++] = candidate; 44 | } 45 | vNewVertexOrder.resize(uNewIndex); 46 | } 47 | 48 | R.push_back(chosenVertex); 49 | } 50 | 51 | void StaticOrderMCS::ProcessOrderAfterRecursion(std::vector &vVertexOrder, std::vector &P, std::vector &vColors, int const chosenVertex) 52 | { 53 | if (chosenVertex == -1) return; 54 | #if 1 55 | vVertexOrder.erase(find(vVertexOrder.begin(), vVertexOrder.end(), chosenVertex)); 56 | #else 57 | // try searching from end, might be faster in general... 58 | size_t indexAfterVertex(0); 59 | for (indexAfterVertex = vVertexOrder.size(); indexAfterVertex >= 1; indexAfterVertex--) { 60 | if (vVertexOrder[indexAfterVertex-1] == chosenVertex) { 61 | break; 62 | } 63 | } 64 | 65 | for (; indexAfterVertex < vVertexOrder.size(); indexAfterVertex++) { 66 | vVertexOrder[indexAfterVertex-1] = vVertexOrder[indexAfterVertex]; 67 | } 68 | vVertexOrder.pop_back(); 69 | #endif // 0 70 | R.pop_back(); 71 | } 72 | -------------------------------------------------------------------------------- /src/StaticOrderMCS.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 LIGHTWEIGHT_STATIC_ORDER_MCS_H 17 | #define LIGHTWEIGHT_STATIC_ORDER_MCS_H 18 | 19 | #include "MCQ.h" 20 | #include "CliqueColoringStrategy.h" 21 | 22 | #include 23 | #include 24 | 25 | class StaticOrderMCS : public MCQ 26 | { 27 | public: 28 | StaticOrderMCS(std::vector> const &vAdjacencyMatrix); 29 | 30 | virtual void InitializeOrder(std::vector &P, std::vector &vVertexOrder, std::vector &vColors); 31 | 32 | virtual void GetNewOrder(std::vector &vNewVertexOrder, std::vector &vVertexOrder, std::vector const &P, int const chosenVertex); 33 | 34 | virtual void ProcessOrderAfterRecursion(std::vector &vVertexOrder, std::vector &P, std::vector &vColors, int const chosenVertex); 35 | 36 | protected: 37 | std::vector> stackOrder; 38 | }; 39 | 40 | #endif //LIGHTWEIGHT_STATIC_ORDER_MCS_H 41 | -------------------------------------------------------------------------------- /src/StaticOrderMISS.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 "StaticOrderMISS.h" 17 | #include "OrderingTools.h" 18 | #include "GraphTools.h" 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | using namespace std; 25 | 26 | StaticOrderMISS::StaticOrderMISS(vector> const &vAdjacencyMatrix) 27 | : MISQ(vAdjacencyMatrix) 28 | { 29 | SetName("static-order-miss"); 30 | } 31 | 32 | void StaticOrderMISS::InitializeOrder(std::vector &P, std::vector &vVertexOrder, std::vector &vColors) 33 | { 34 | OrderingTools::InitialOrderingMISR(m_AdjacencyMatrix, P, vColors, m_uMaximumCliqueSize); 35 | vVertexOrder = P; //std::move(GraphTools::OrderVerticesByDegree(m_AdjacencyMatrix, true /* non-decreasing */)); //// = P; //? 36 | } 37 | 38 | void StaticOrderMISS::GetNewOrder(vector &vNewVertexOrder, vector &vVertexOrder, vector const &P, int const chosenVertex) 39 | { 40 | //// cout << "Old order: "; 41 | //// for (int const vertex : vVertexOrder) { 42 | //// cout << vertex << " "; 43 | //// } 44 | //// cout << endl; 45 | vNewVertexOrder.resize(vVertexOrder.size()); 46 | { 47 | size_t uNewIndex(0); 48 | for (int const candidate : vVertexOrder) { 49 | //// cout << depth << ": accessing " << chosenVertex << "," << candidate << " in " << m_AdjacencyMatrix.size() << "," << m_AdjacencyMatrix[chosenVertex].size() << endl << flush; 50 | //// cout << depth << ": put in index " << uNewIndex << "/" << vNewVertexOrder.size() << endl << flush; 51 | //// cout << depth << ": size of stackP : " << stackP.size() << endl; 52 | //// cout << depth << ": size of stackOrder: " << stackOrder.size() << endl; 53 | if (chosenVertex == candidate) continue; 54 | if (!m_AdjacencyMatrix[chosenVertex][candidate]) vNewVertexOrder[uNewIndex++] = candidate; 55 | } 56 | vNewVertexOrder.resize(uNewIndex); 57 | } 58 | 59 | R.push_back(chosenVertex); 60 | 61 | //// cout << "New order: "; 62 | //// for (int const vertex : vNewVertexOrder) { 63 | //// cout << vertex << " "; 64 | //// } 65 | //// cout << endl; 66 | } 67 | 68 | void StaticOrderMISS::ProcessOrderAfterRecursion(std::vector &vVertexOrder, std::vector &P, std::vector &vColors, int const chosenVertex) 69 | { 70 | //// cout << "StaticOrderMISS::ProcessOrderAfterRecursion" << endl; 71 | if (chosenVertex == -1) return; 72 | //// cout << " order: "; 73 | //// for (int const vertex : vVertexOrder) { 74 | //// cout << vertex << " "; 75 | //// } 76 | //// cout << endl; 77 | //// cout << "# vertices=" << vVertexOrder.size() << endl << flush; 78 | //// vVertexOrder.erase(find(vVertexOrder.begin(), vVertexOrder.end(), chosenVertex)); 79 | // try searching from end, might be faster in general... 80 | //// if (find(vVertexOrder.begin(), vVertexOrder.end(), chosenVertex) != vVertexOrder.end()) { 81 | //// cout << "vertex " << chosenVertex << " is in ordering..." << endl << flush; 82 | //// } else { 83 | //// cout << "vertex " << chosenVertex << " is not in ordering..." << endl << flush; 84 | //// } 85 | size_t indexAfterVertex(0); 86 | for (indexAfterVertex = vVertexOrder.size(); indexAfterVertex >= 1; indexAfterVertex--) { 87 | if (vVertexOrder[indexAfterVertex-1] == chosenVertex) { 88 | break; 89 | } 90 | } 91 | 92 | for (; indexAfterVertex < vVertexOrder.size(); indexAfterVertex++) { 93 | vVertexOrder[indexAfterVertex-1] = vVertexOrder[indexAfterVertex]; 94 | } 95 | 96 | vVertexOrder.pop_back(); 97 | R.pop_back(); 98 | } 99 | -------------------------------------------------------------------------------- /src/StaticOrderMISS.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 LIGHTWEIGHT_STATIC_ORDER_MISS_H 17 | #define LIGHTWEIGHT_STATIC_ORDER_MISS_H 18 | 19 | #include "MISQ.h" 20 | 21 | #include 22 | #include 23 | 24 | class StaticOrderMISS : public MISQ 25 | { 26 | public: 27 | StaticOrderMISS(std::vector> const &vAdjacencyMatrix); 28 | 29 | virtual void InitializeOrder(std::vector &P, std::vector &vVertexOrder, std::vector &vColors); 30 | 31 | virtual void GetNewOrder(std::vector &vNewVertexOrder, std::vector &vVertexOrder, std::vector const &P, int const chosenVertex); 32 | 33 | virtual void ProcessOrderAfterRecursion(std::vector &vVertexOrder, std::vector &P, std::vector &vColors, int const chosenVertex); 34 | }; 35 | 36 | #endif //LIGHTWEIGHT_STATIC_ORDER_MISS_H 37 | -------------------------------------------------------------------------------- /src/Tools.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 17 | #include 18 | #include 19 | #include // ifstream 20 | //#include 21 | 22 | #include "Tools.h" 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "MemoryManager.h" 30 | #include "Algorithm.h" 31 | 32 | using namespace std; 33 | 34 | /*! \file Tools.cpp 35 | 36 | \brief A collection of useful comparators and print functions 37 | 38 | \author Darren Strash (first name DOT last name AT gmail DOT com) 39 | 40 | \copyright Copyright (c) 2011 Darren Strash. This code is released under the GNU Public License (GPL) 3.0. 41 | 42 | \image html gplv3-127x51.png 43 | 44 | \htmlonly 45 |
46 | See GPL 3.0 here 47 |
48 | \endhtmlonly 49 | */ 50 | 51 | /*! \brief compare integers return -1,0,1 for <,=,> 52 | 53 | \param node1 an integer 54 | 55 | \param node2 an integer 56 | 57 | \return -1 if <, 0 if =, and 1 if >. 58 | */ 59 | 60 | int nodeComparator(int node1, int node2) 61 | { 62 | if (node1 < node2) 63 | return -1; 64 | if(node1 > node2) 65 | return 1; 66 | 67 | return 0; 68 | } 69 | 70 | /*! \brief compare integer pointers; return -1,0,1 for <,=,>; 71 | used for calling sort(). 72 | 73 | \param node1 a pointer to an integer 74 | 75 | \param node2 a pointer to an integer 76 | 77 | \return -1 if <, 0 if =, and 1 if >. 78 | */ 79 | 80 | int sortComparator(int node1, int node2) 81 | { 82 | if (node1 < node2) 83 | return -1; 84 | if(node1 > node2) 85 | return 1; 86 | 87 | return 0; 88 | } 89 | 90 | /*! \brief print an array of integers to standard out. 91 | 92 | \param array the array to print 93 | 94 | \param size the length of the array 95 | */ 96 | 97 | void printArray(int* array, int size) 98 | { 99 | int i = 0; 100 | while(i> const &arrayOfLists, int size) 132 | { 133 | // list graph contents 134 | 135 | int i = 0; 136 | while (i < arrayOfLists.size()) 137 | { 138 | if (!arrayOfLists[i].empty()) 139 | { 140 | printf("%d:", i); 141 | printListAbbv(arrayOfLists[i], &Tools::printInt); 142 | } 143 | i++; 144 | } 145 | } 146 | 147 | /*! \brief print a clique, that is formatted as an integer 148 | array ending with -1. 149 | 150 | \param clique the clique. 151 | */ 152 | 153 | void printClique(int* clique) 154 | { 155 | int i = 0; 156 | while(clique[i]!=-1) 157 | { 158 | printf("%d", clique[i]); 159 | if(clique[i+1]!=-1) 160 | printf(" "); 161 | i++; 162 | } 163 | printf("\n"); 164 | } 165 | 166 | /*! \brief print an integer 167 | 168 | \param integer an integer cast to a void* 169 | */ 170 | 171 | void Tools::printInt(int integer) 172 | { 173 | printf("%d", integer); 174 | } 175 | 176 | /*! \brief destroy a linked list of integer arrays that have 177 | -1 in the last cell, have have been allocated by 178 | the user. 179 | 180 | \param cliques the linked list of integer arrays 181 | */ 182 | 183 | void destroyCliqueResults(list> &cliques) 184 | { 185 | cliques.clear(); 186 | } 187 | 188 | /*! \brief read in a graph from stdin and return an 189 | adjacency list, as an array of linked lists 190 | of integers. 191 | 192 | \param n this will be the number of vertices in the 193 | graph when this function returns. 194 | 195 | \param m this will be 2x the number of edges in the 196 | graph when this function returns. 197 | 198 | \return an array of linked lists of integers (adjacency list) 199 | representation of the graph 200 | */ 201 | 202 | vector> readInGraphAdjList(int* n, int* m) 203 | { 204 | int u, v; // endvertices, to read edges. 205 | 206 | if(scanf("%d", n)!=1) 207 | { 208 | fprintf(stderr, "problem with line 1 in input file\n"); 209 | exit(1); 210 | } 211 | 212 | if(scanf("%d", m)!=1) 213 | { 214 | fprintf(stderr, "problem with line 2 in input file\n"); 215 | exit(1); 216 | } 217 | 218 | #ifdef DEBUG 219 | printf("Number of vertices: %d\n", *n); 220 | printf("Number of edges: %d\n", *m); 221 | #endif 222 | 223 | vector> adjList(*n); 224 | 225 | int i = 0; 226 | while(i < *m) 227 | { 228 | if(scanf("%d,%d", &u, &v)!=2) 229 | { 230 | printf("problem with line %d in input file\n", i+2); 231 | exit(1); 232 | } 233 | assert(u < *n && u > -1); 234 | assert(v < *n && v > -1); 235 | if(u==v) 236 | printf("%d=%d\n", u, v); 237 | assert(u != v); 238 | 239 | adjList[u].push_back(v); 240 | 241 | i++; 242 | } 243 | 244 | #ifdef DEBUG 245 | printArrayOfLinkedLists(adjList, *n); 246 | #endif 247 | 248 | return adjList; 249 | } 250 | 251 | vector> readInGraphAdjListEdgesPerLine(int &n, int &m, string const &fileName) 252 | { 253 | ifstream instream(fileName.c_str()); 254 | 255 | if (instream.good() && !instream.eof()) { 256 | string line; 257 | std::getline(instream, line); 258 | //// cout << "Read Line: " << line << endl << flush; 259 | while((line.empty() || line[0] == '%') && instream.good() && !instream.eof()) { 260 | std::getline(instream, line); 261 | } 262 | stringstream strm(line); 263 | strm >> n >> m; 264 | } else { 265 | fprintf(stderr, "ERROR: Problem reading number of vertices and edges in file %s\n", fileName.c_str()); 266 | exit(1); 267 | } 268 | 269 | #ifdef DEBUG 270 | printf("Number of vertices: %d\n", n); 271 | printf("Number of edges: %d\n", m); 272 | #endif 273 | 274 | vector> adjList(n); 275 | 276 | int u, v; // endvertices, to read edges. 277 | int i = 0; 278 | while (i < n) { 279 | if (!instream.good() || instream.eof()) { 280 | fprintf(stderr, "ERROR: Problem reading line %d in file %s\n", i+1, fileName.c_str()); 281 | exit(1); 282 | } 283 | 284 | string line; 285 | std::getline(instream, line); 286 | u = i; // TODO/DS: remove. 287 | stringstream strm(line); 288 | //// bool debug(true); ////u == 40656 || u == 40653); 289 | ////if (debug) cout << (u+1) << " : " << endl << flush; 290 | ////if (debug) cout << "Read Line: " << line << endl << flush; 291 | ////if (debug) cout << "Actually Read: "; 292 | while (!line.empty() && strm.good() && !strm.eof()) { 293 | strm >> v; 294 | ////if (!strm.good()) break; 295 | ////if (debug) cout << v << " "; 296 | v--; 297 | 298 | assert(u < n && u > -1); 299 | assert(v < n && v > -1); 300 | if (u==v) { 301 | fprintf(stderr, "ERROR: Detected loop %d->%d\n", u + 1, v + 1); 302 | exit(1); 303 | } 304 | 305 | adjList[u].push_back(v); 306 | } 307 | ////if (debug) cout << endl << flush; 308 | 309 | i++; 310 | } 311 | 312 | #ifdef DEBUG 313 | printArrayOfLinkedLists(adjList, n); 314 | #endif 315 | 316 | return adjList; 317 | } 318 | 319 | 320 | vector> readInGraphAdjList(int &n, int &m, string const &fileName) 321 | { 322 | 323 | ifstream instream(fileName.c_str()); 324 | 325 | if (instream.good() && !instream.eof()) 326 | instream >> n; 327 | else { 328 | fprintf(stderr, "problem with line 1 in input file\n"); 329 | exit(1); 330 | } 331 | 332 | 333 | if (instream.good() && !instream.eof()) 334 | instream >> m; 335 | else { 336 | 337 | fprintf(stderr, "problem with line 2 in input file\n"); 338 | exit(1); 339 | } 340 | 341 | #ifdef DEBUG 342 | printf("Number of vertices: %d\n", n); 343 | printf("Number of edges: %d\n", m); 344 | #endif 345 | 346 | vector> adjList(n); 347 | 348 | int u, v; // endvertices, to read edges. 349 | int i = 0; 350 | while(i < m) 351 | { 352 | char comma; 353 | if (instream.good() && !instream.eof()) { 354 | instream >> u >> comma >> v; 355 | } else { 356 | fprintf(stderr, "problem with line %d in input file\n", i+2); 357 | exit(1); 358 | } 359 | assert(u < n && u > -1); 360 | assert(v < n && v > -1); 361 | if(u==v) 362 | fprintf(stderr, "Detected loop %d->%d\n", u, v); 363 | assert(u != v); 364 | 365 | adjList[u].push_back(v); 366 | 367 | i++; 368 | } 369 | 370 | #ifdef DEBUG 371 | printArrayOfLinkedLists(adjList, n); 372 | #endif 373 | 374 | return adjList; 375 | } 376 | 377 | #if 0 378 | vector> readInGraphAdjListDimacs(int &n, int &m, string const &fileName) 379 | { 380 | 381 | std::getline(instream, line); 382 | ifstream instream(fileName.c_str()); 383 | 384 | if (instream.good() && !instream.eof()) 385 | instream >> m; 386 | else { 387 | 388 | fprintf(stderr, "problem with line 2 in input file\n"); 389 | exit(1); 390 | } 391 | 392 | #ifdef DEBUG 393 | printf("Number of vertices: %d\n", n); 394 | printf("Number of edges: %d\n", m); 395 | #endif 396 | 397 | vector> adjList(n); 398 | 399 | int u, v; // endvertices, to read edges. 400 | int i = 0; 401 | while(i < m) 402 | { 403 | char comma; 404 | if (instream.good() && !instream.eof()) { 405 | instream >> u >> comma >> v; 406 | } else { 407 | fprintf(stderr, "problem with line %d in input file\n", i+2); 408 | exit(1); 409 | } 410 | assert(u < n && u > -1); 411 | assert(v < n && v > -1); 412 | if(u==v) 413 | fprintf(stderr, "Detected loop %d->%d\n", u, v); 414 | assert(u != v); 415 | 416 | adjList[u].push_back(v); 417 | 418 | i++; 419 | } 420 | 421 | #ifdef DEBUG 422 | printArrayOfLinkedLists(adjList, n); 423 | #endif 424 | 425 | return adjList; 426 | } 427 | #endif 428 | 429 | /*! \brief execute an clique algorithm, time it, 430 | and print the size of the maximum clique 431 | along with time information. 432 | 433 | \param pAlgorithm a pointer to a maximum clique algorithm object 434 | 435 | \param cliques a list of lists, storing the largest clique found so far 436 | 437 | \param outputLatex flag to indicate if latex formatting should be used for output 438 | 439 | */ 440 | 441 | void RunAndPrintStats(Algorithm *pAlgorithm, list> &cliques, bool const outputLatex) 442 | { 443 | fprintf(stderr, "%s: ", pAlgorithm->GetName().c_str()); 444 | fflush(stderr); 445 | 446 | clock_t const start = clock(); 447 | 448 | long const cliqueCount = pAlgorithm->Run(cliques); 449 | 450 | clock_t const end = clock(); 451 | 452 | int const cliqueNumber(cliques.empty()? -1: cliques.back().size()); 453 | 454 | if (!outputLatex) { 455 | fprintf(stderr, "Found maximum clique of size %d ", cliqueNumber); 456 | fprintf(stderr, "in %f seconds\n", (double)(end-start)/(double)(CLOCKS_PER_SEC)); 457 | } else { 458 | printf("%.2f", (double)(end-start)/(double)(CLOCKS_PER_SEC)); 459 | } 460 | fflush(stderr); 461 | } 462 | 463 | /*! \brief Print the items in the linked list. 464 | 465 | \param linkedList A linked list. 466 | 467 | \param printFunc A function to print the data elements in 468 | the linked list. 469 | */ 470 | 471 | void Tools::printList(list const &linkedList, void (*printFunc)(int)) 472 | { 473 | #ifdef DEBUG 474 | printf("printList...\n"); 475 | #endif 476 | int count = 0; 477 | for (int const value : linkedList) { 478 | printFunc(value); 479 | if (count != linkedList.size()) { 480 | printf(" "); 481 | } 482 | } 483 | 484 | printf("\n"); 485 | 486 | } 487 | 488 | /*! \brief Print the first 10 items in the linked list 489 | 490 | \param linkedList A linked list. 491 | 492 | \param printFunc A function to print the data elements in 493 | the linked list. 494 | */ 495 | 496 | void printListAbbv(list const &linkedList, void (*printFunc)(int)) 497 | { 498 | #ifdef DEBUG 499 | printf("printListAbbv...\n"); 500 | #endif 501 | int count = 0; 502 | 503 | for (list::const_iterator cit = linkedList.begin(); 504 | cit != linkedList.end() && count != 10; ++cit) 505 | { 506 | count++; 507 | printFunc(*cit); 508 | if(count != linkedList.size()) 509 | { 510 | printf(" "); 511 | } 512 | } 513 | 514 | if(count != linkedList.size()) 515 | { 516 | printf("... plus %lu more", linkedList.size()-10); 517 | } 518 | 519 | printf("\n"); 520 | } 521 | 522 | void DescribeVertex(int const lineNumber, int *vertexSets, int *vertexLookup, int const size, int const vertex, int const beginX, int const beginD, int const beginP, int const beginR) 523 | { 524 | int const vertexLocation(vertexLookup[vertex]); 525 | 526 | cout << lineNumber << ": vertex " << vertex << " is in position " << vertexLocation << (vertexSets[vertexLocation] == vertex ? "(consistent)" : "(inconsistent: " + to_string(vertexSets[vertexLocation]) + " is there)" ) << " in set "; 527 | 528 | if (vertexLocation < beginX) { 529 | cout << "(before X)" << endl; 530 | } 531 | if (vertexLocation >= beginX && vertexLocation < beginD) { 532 | cout << "X" << endl; 533 | } 534 | if (vertexLocation >= beginD && vertexLocation < beginP) { 535 | cout << "D" << endl; 536 | } 537 | if (vertexLocation >= beginP && vertexLocation < beginR) { 538 | cout << "P" << endl; 539 | } 540 | if (vertexLocation >= beginR) { 541 | cout << "R" << endl; 542 | } 543 | } 544 | 545 | void DescribeSet(string const &setName, int const begin, int const end) 546 | { 547 | cout << " " << setName << "=[" << begin << "->" << end << "]"; 548 | } 549 | 550 | void DescribeState(int const lineNumber, int *vertexSets, int *vertexLookup, int const size, int const beginX, int const beginD, int const beginP, int const beginR) 551 | { 552 | cout << lineNumber << ": Size " << size; 553 | DescribeSet("X", beginX, beginD-1); 554 | DescribeSet("D", beginD, beginP-1); 555 | DescribeSet("P", beginP, beginR-1); 556 | DescribeSet("R", beginR, size-1); 557 | cout << endl << flush; 558 | } 559 | 560 | void CheckConsistency(int const lineNumber, size_t const recursionNumber, int *vertexSets, int *vertexLookup, int const size) 561 | { 562 | //if (recursionNumber > 2) return; 563 | //cout << recursionNumber << "1 is in position " << ver 564 | for (int i=0; i < size; ++i) { 565 | if (vertexSets[vertexLookup[i]] != i) { 566 | cout << recursionNumber << "(line " << lineNumber << ") : inconsistency -- vertex " << i << " is supposed to be in position " << vertexLookup[i] << " but vertex " << vertexSets[vertexLookup[i]] << " is there." << endl; 567 | } 568 | } 569 | } 570 | 571 | void CheckReverseConsistency(int const lineNumber, size_t const recursionNumber, int *vertexSets, int *vertexLookup, int const size) 572 | { 573 | //if (recursionNumber > 2) return; 574 | //cout << recursionNumber << "1 is in position " << ver 575 | for (int i=0; i < size; ++i) { 576 | if (vertexLookup[vertexSets[i]] != i) { 577 | cout << recursionNumber << "(line " << lineNumber << ") : inconsistency -- vertex " << vertexSets[i] << " is supposed to be in position " << vertexLookup[vertexSets[i]] << " but it is in position " << i << "." << endl; 578 | } 579 | } 580 | } 581 | 582 | ////bool IsMaximalClique(std::list const &clique, std::vector> const &adjacencyList) 583 | ////{ 584 | //// set 585 | //// // is clique 586 | //// int index; 587 | //// for (int const vertex : partialClique) { 588 | //// } 589 | //// 590 | //// // is maximal 591 | ////} 592 | 593 | 594 | void InvertGraph(vector> const &adjList) 595 | { 596 | int const n(adjList.size()); 597 | cout << n << endl; 598 | size_t numEdgesInInverse(0); 599 | for (list const &neighbors : adjList) { 600 | numEdgesInInverse += n - neighbors.size() - 1; // all non-edges except loops 601 | } 602 | 603 | cout << numEdgesInInverse << endl; 604 | 605 | for (int i = 0; i < adjList.size(); ++i) { 606 | set setNeighbors; 607 | setNeighbors.insert(adjList[i].begin(), adjList[i].end()); 608 | for (int neighbor=0; neighbor < adjList.size(); neighbor++) { 609 | if (setNeighbors.find(neighbor) == setNeighbors.end() && neighbor != i) { 610 | cout << "(" << i << "," << neighbor << i << ")" << endl; 611 | } 612 | } 613 | } 614 | } 615 | 616 | string Tools::GetTimeInSeconds(clock_t delta, bool const brackets) { 617 | stringstream strm; 618 | 619 | strm.precision(2); 620 | strm.setf(std::ios::fixed, std::ios::floatfield); 621 | if (brackets) { 622 | strm << "[" << (double)(delta)/(double)(CLOCKS_PER_SEC) << "s]"; 623 | } else { 624 | strm << (double)(delta)/(double)(CLOCKS_PER_SEC) << "s"; 625 | } 626 | return strm.str(); 627 | } 628 | 629 | vector Tools::ReadMetisOrdering(string const &fileName) 630 | { 631 | ifstream instream(fileName.c_str()); 632 | 633 | vector ordering; 634 | 635 | int u, v; // endvertices, to read edges. 636 | 637 | if (!instream.good() || instream.eof()) { 638 | fprintf(stderr, "ERROR: Problem reading line 1 in file %s\n", fileName.c_str()); 639 | exit(1); 640 | } 641 | 642 | while (instream.good() && !instream.eof()) { 643 | 644 | string line; 645 | std::getline(instream, line); 646 | stringstream strm(line); 647 | //// bool debug(true); ////u == 40656 || u == 40653); 648 | ////if (debug) cout << (u+1) << " : " << endl << flush; 649 | ////if (debug) cout << "Read Line: " << line << endl << flush; 650 | ////if (debug) cout << "Actually Read: "; 651 | if (!line.empty() && strm.good() && !strm.eof()) { 652 | strm >> v; 653 | ////if (!strm.good()) break; 654 | ////if (debug) cout << v << " "; 655 | cout << "read: " << v << endl; 656 | 657 | assert(v > -1); 658 | 659 | ordering.push_back(v); 660 | } 661 | ////if (debug) cout << endl << flush; 662 | } 663 | 664 | #ifdef DEBUG 665 | printArrayOfLinkedLists(adjList, n); 666 | #endif 667 | 668 | return ordering; 669 | } 670 | 671 | -------------------------------------------------------------------------------- /src/Tools.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_MISC_H_ 17 | #define _DJS_MISC_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | class Algorithm; 25 | 26 | /*! \file Tools.h 27 | 28 | \brief see misc.c 29 | 30 | \author Darren Strash (first name DOT last name AT gmail DOT com) 31 | 32 | \copyright Copyright (c) 2011 Darren Strash. This code is released under the GNU Public License (GPL) 3.0. 33 | 34 | \image html gplv3-127x51.png 35 | 36 | \htmlonly 37 |
38 | See GPL 3.0 here 39 |
40 | \endhtmlonly 41 | */ 42 | 43 | #include 44 | //#define max(x,y) (x > y? x:y) 45 | //#define min(x,y) (x < y? x:y) 46 | 47 | int nodeComparator(int node1, int node2); 48 | 49 | void printArray(int* array, int size); 50 | 51 | void printArrayWithIndexArrows(int* array, int size, int index1, int index2, int index3); 52 | 53 | void printArrayOfLinkedLists(std::vector> const &listOfLists, int size); 54 | 55 | void destroyCliqueResults(std::list> &cliques); 56 | 57 | std::vector> readInGraphAdjList(int* n, int* m); 58 | 59 | std::vector> readInGraphAdjList(int &n, int &m, std::string const &fileName); 60 | std::vector> readInGraphAdjListEdgesPerLine(int &n, int &m, std::string const &fileName); 61 | 62 | void runAndPrintStatsMatrix(long (*function)(char**, 63 | int), 64 | const char* algName, 65 | char** adjMatrix, 66 | int n ); 67 | 68 | void RunAndPrintStats(Algorithm* pAlgorithm, std::list> &cliques, bool const outputLatex); 69 | 70 | void printListAbbv(std::list const &linkedList, void (*printFunc)(int)); 71 | 72 | /*! \brief process a clique, which may include printing it in 73 | one of several formats and/or adding the 74 | clique to a linked list. 75 | 76 | \param clique the clique to add to the linked list 77 | 78 | */ 79 | 80 | inline void processClique(std::list const &clique) 81 | { 82 | #ifdef PRINT_CLIQUES_TOMITA_STYLE 83 | printf("c "); 84 | #endif 85 | } 86 | 87 | void DescribeVertex(int const lineNumber, int *vertexSets, int *vertexLookup, int const size, int const vertex, int const beginX, int const beginD, int const beginP, int const beginR); 88 | 89 | void DescribeSet(std::string const &setName, int const begin, int const end); 90 | 91 | void DescribeState(int const lineNumber, int *vertexSets, int *vertexLookup, int const size, int const beginX, int const beginD, int const beginP, int const beginR); 92 | 93 | void CheckConsistency(int const lineNumber, size_t const recursionNumber, int *vertexSets, int *vertexLookup, int const size); 94 | 95 | void CheckReverseConsistency(int const lineNumber, size_t const recursionNumber, int *vertexSets, int *vertexLookup, int const size); 96 | 97 | bool IsMaximalClique(std::list const &clique, std::vector> const &adjacencyList); 98 | 99 | namespace Tools 100 | { 101 | void printList(std::list const &linkedList, void (*printFunc)(int)); 102 | void printInt(int integer); 103 | std::vector ReadMetisOrdering(std::string const &filename); 104 | std::string GetTimeInSeconds(clock_t delta, bool brackets=true); 105 | }; 106 | 107 | #endif 108 | 109 | -------------------------------------------------------------------------------- /src/main.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 | // local includes 17 | #include "ArraySet.h" 18 | #include "Tools.h" 19 | #include "CliqueTools.h" 20 | 21 | // maximum clique algorithms 22 | #include "MCQ.h" 23 | #include "MCR.h" 24 | #include "StaticOrderMCS.h" 25 | #include "MCS.h" 26 | 27 | // maximum independent set algorithms 28 | #include "MISQ.h" 29 | #include "MISR.h" 30 | #include "StaticOrderMISS.h" 31 | #include "MISS.h" 32 | 33 | 34 | // system includes 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | using namespace std; 45 | 46 | /*! \file main.cpp 47 | 48 | \brief Main entry point for quick cliques software. This is where we parse the command line options, read the inputs, and decide which clique method to run. 49 | 50 | \author Darren Strash (first name DOT last name AT gmail DOT com) 51 | 52 | \copyright Copyright (c) 2016 Darren Strash. This code is released under the GNU Public License (GPL) 3.0. 53 | 54 | \image html gplv3-127x51.png 55 | 56 | \htmlonly 57 |
58 | See GPL 3.0 here 59 |
60 | \endhtmlonly 61 | */ 62 | 63 | bool isValidAlgorithm(string const &name) 64 | { 65 | return (name == "mcq" || name == "mcr" || name == "static-order-mcs" || name == "mcs"); 66 | } 67 | 68 | void ProcessCommandLineArgs(int const argc, char** argv, map &mapCommandLineArgs) 69 | { 70 | for (int i = 1; i < argc; ++i) { 71 | //// cout << "Processing argument " << i << endl; 72 | string const argument(argv[i]); 73 | //// cout << " Argument is " << argument << endl; 74 | size_t const positionOfEquals(argument.find_first_of("=")); 75 | //// cout << " Position of = " << positionOfEquals << endl; 76 | if (positionOfEquals != string::npos) { 77 | string const key (argument.substr(0,positionOfEquals)); 78 | string const value(argument.substr(positionOfEquals+1)); 79 | //// cout << " Parsed1: " << key << "=" << value << endl; 80 | mapCommandLineArgs[key] = value; 81 | } else { 82 | //// cout << " Parsed2: " << argument << endl; 83 | mapCommandLineArgs[argument] = ""; 84 | } 85 | } 86 | } 87 | 88 | void PrintDebugWarning() 89 | { 90 | cout << "\n\n\n\n\n" << flush; 91 | cout << "#########################################################################" << endl << flush; 92 | cout << "# #" << endl << flush; 93 | cout << "# WARNING: Debugging is turned on. Don't believe the run times... #" << endl << flush; 94 | cout << "# #" << endl << flush; 95 | cout << "#########################################################################" << endl << flush; 96 | cout << "\n\n\n\n\n" << flush; 97 | } 98 | 99 | void PrintExperimentalWarning() 100 | { 101 | cout << "NOTE: Open MCS v1.0." << endl << flush; 102 | } 103 | 104 | string basename(string const &fileName) 105 | { 106 | string sBaseName(fileName); 107 | 108 | size_t const lastSlash(sBaseName.find_last_of("/\\")); 109 | if (lastSlash != string::npos) { 110 | sBaseName = sBaseName.substr(lastSlash+1); 111 | } 112 | 113 | size_t const lastDot(sBaseName.find_last_of(".")); 114 | if (lastDot != string::npos) { 115 | sBaseName = sBaseName.substr(0, lastDot); 116 | } 117 | 118 | return sBaseName; 119 | } 120 | 121 | int main(int argc, char** argv) 122 | { 123 | int failureCode(0); 124 | 125 | map mapCommandLineArgs; 126 | 127 | ProcessCommandLineArgs(argc, argv, mapCommandLineArgs); 128 | 129 | bool const bQuiet(mapCommandLineArgs.find("--verbose") == mapCommandLineArgs.end()); 130 | bool const bOutputLatex(mapCommandLineArgs.find("--latex") != mapCommandLineArgs.end()); 131 | bool const bOutputTable(mapCommandLineArgs.find("--table") != mapCommandLineArgs.end()); 132 | string const inputFile((mapCommandLineArgs.find("--input-file") != mapCommandLineArgs.end()) ? mapCommandLineArgs["--input-file"] : ""); 133 | string const algorithm((mapCommandLineArgs.find("--algorithm") != mapCommandLineArgs.end()) ? mapCommandLineArgs["--algorithm"] : ""); 134 | bool const bComputeIndependentSet(mapCommandLineArgs.find("--compute-independent-set") != mapCommandLineArgs.end()); 135 | bool const bPrintHeader(mapCommandLineArgs.find("--header") != mapCommandLineArgs.end()); 136 | 137 | bool const bTableMode(bOutputLatex || bOutputTable); 138 | 139 | if (!bTableMode) { 140 | #ifdef DEBUG_MESSAGE 141 | PrintDebugWarning(); 142 | #endif //DEBUG_MESSAGE 143 | } 144 | 145 | if (inputFile.empty()) { 146 | cout << "ERROR: Missing input file " << endl; 147 | // ShowUsageMessage(); 148 | // return 1; // TODO/DS 149 | } 150 | 151 | string name(algorithm); 152 | if (!bTableMode && algorithm.empty()) { 153 | cout << "NOTE: Missing algorithm name, using mcs." << endl; 154 | name = "mcs"; 155 | // ShowUsageMessage(); 156 | // return 1; // TODO/DS 157 | } 158 | 159 | if (argc <= 1 || !isValidAlgorithm(name)) { 160 | cout << "usage: " << argv[0] << " --input-file= [--compute-independent-set] --algorithm=> adjacencyList; 174 | if (inputFile.find(".graph") != string::npos) { 175 | if (!bTableMode) cout << "Reading .graph file format. " << endl << flush; 176 | adjacencyList = readInGraphAdjListEdgesPerLine(n, m, inputFile); 177 | } else { 178 | if (!bTableMode) cout << "Reading .edges file format. " << endl << flush; 179 | adjacencyList = readInGraphAdjList(n, m, inputFile); 180 | } 181 | 182 | bool const bComputeAdjacencyMatrix(adjacencyList.size() < 20000); 183 | bool const bShouldComputeAdjacencyMatrix(name == "mcq" || name == "mcr" || name == "static-order-mcs" || name == "mcs" || name == "misq" || name == "misr" || name == "static-order-miss" || name == "miss"); 184 | 185 | bool const addDiagonals(name == "misq" || name == "misr" || name == "static-order-miss" || name == "miss"); 186 | 187 | if (bShouldComputeAdjacencyMatrix && !bComputeAdjacencyMatrix) { 188 | cout << "ERROR: unable to compute adjacencyMatrix, since the graph is too large: " << adjacencyList.size() << endl << flush; 189 | exit(1); 190 | } 191 | 192 | vector> vAdjacencyMatrix; 193 | 194 | if (bComputeAdjacencyMatrix) { 195 | vAdjacencyMatrix.resize(n); 196 | 197 | for(int i=0; i const &clique) { 232 | bool const isIS = CliqueTools::IsClique(vAdjacencyMatrix, clique, true /* verbose */); 233 | if (!isIS) { 234 | cout << "ERROR: Set " << (isIS ? "is" : "is not" ) << " a clique!" << endl; 235 | } 236 | }; 237 | 238 | auto verifyIndependentSetMatrix = [&vAdjacencyMatrix](list const &clique) { 239 | bool const isIS = CliqueTools::IsIndependentSet(vAdjacencyMatrix, clique, true /* verbose */); 240 | if (!isIS) { 241 | cout << "ERROR: Set " << (isIS ? "is" : "is not" ) << " an independent set!" << endl; 242 | } 243 | }; 244 | 245 | auto printCliqueSize = [](list const &clique) { 246 | cout << "Found clique of size " << clique.size() << endl << flush; 247 | }; 248 | 249 | //// pAlgorithm->AddCallBack(printCliqueSize); 250 | //// pAlgorithm->AddCallBack(printClique); 251 | 252 | if (!bComputeAdjacencyMatrix) { 253 | assert(0); 254 | } else { 255 | //// pAlgorithm->AddCallBack(verifyCliqueMatrix); 256 | //// pAlgorithm->AddCallBack(verifyIndependentSetMatrix); 257 | } 258 | 259 | // Run algorithm 260 | list> cliques; 261 | 262 | pAlgorithm->SetQuiet(bQuiet); 263 | 264 | RunAndPrintStats(pAlgorithm, cliques, bTableMode); 265 | 266 | //// cout << "Last clique has size: " << cliques.back().size() << endl << flush; 267 | 268 | cliques.clear(); 269 | 270 | vAdjacencyMatrix.clear(); 271 | delete pAlgorithm; pAlgorithm = nullptr; 272 | 273 | #ifdef DEBUG_MESSAGE 274 | PrintDebugWarning(); 275 | #endif 276 | 277 | return 0; 278 | } 279 | -------------------------------------------------------------------------------- /test_all.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | cd $DIR 5 | 6 | make clean 7 | make -j4 8 | 9 | if [ ! -d data ]; then 10 | echo "untarring data..." 11 | tar -xf data.tar.gz 12 | fi 13 | 14 | echo "Graph Name Size Time" 15 | for i in data/* 16 | do 17 | data_set_name=`echo $i | sed -e "s%^data/%%g" | sed -e "s/\.graph$//g"` 18 | echo -n "$data_set_name " 19 | bin/open-mcs --algorithm=mcs --input-file=$i 2>&1 | grep "mcs:" | sed -e 's/mcs: Found maximum clique of size \(.*\) in \(.*\) seconds/\1 \2s/g' 20 | done 21 | -------------------------------------------------------------------------------- /test_fast.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | cd $DIR 5 | 6 | make clean 7 | make -j4 8 | 9 | if [ ! -d data ]; then 10 | echo "untarring data..." 11 | tar -xf data.tar.gz 12 | fi 13 | 14 | echo "Graph Name Size Time" 15 | 16 | data_set_names="MANN_a27 p_hat300-3 p_hat500-2 p_hat700-2 san200_0.9_1 san200_0.9_2 san400_0.7_1 san400_0.7_2 san400_0.7_3 san1000 sanr200_0.7" 17 | for i in $data_set_names 18 | do 19 | data_set_name=`echo $i | sed -e "s%^data/%%g" | sed -e "s/\.graph$//g"` 20 | echo -n "$data_set_name " 21 | bin/open-mcs --algorithm=mcs --input-file=data/$i.graph 2>&1 | grep "mcs:" | sed -e 's/mcs: Found maximum clique of size \(.*\) in \(.*\) seconds/\1 \2s/g' 22 | done 23 | --------------------------------------------------------------------------------