Knight's Tour Generator
Tourneys and the Fast Generation and Obfuscation of Closed Knight's Tours
Graph.cpp
Go to the documentation of this file.
1 
4 // MIT License
5 //
6 // Copyright (c) 2019 Ian Parberry
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 
26 #include "Graph.h"
27 #include "Random.h"
28 #include "Helpers.h"
29 
31 // CEdge functions.
32 
37 
38 CEdge::CEdge(CVertex* p0, CVertex* p1, UINT index):
39  m_pVertex0(p0), m_pVertex1(p1), m_nIndex(index){
40 } //constructor
41 
46 
48  if(m_pVertex0 == p)return m_pVertex1;
49  else if(m_pVertex1 == p)return m_pVertex0;
50  else return nullptr;
51 } //GetNextVertex
52 
55 
57  return m_nIndex;
58 } //GetIndex
59 
62 
63 void CEdge::Mark(bool b){
64  m_bMarked = b;
65 } //Mark
66 
69 
71  return m_bMarked;
72 } //Marked
73 
77 
79  i0 = m_pVertex0->GetIndex();
80  i1 = m_pVertex1->GetIndex();
81 } //GetVertexIndices
82 
84 // CVertex functions.
85 
87 } //constructor
88 
91 
93  if(pEdge == nullptr)return;
94  m_vAdjacencyList.push_back(pEdge);
95 } //InsertAdjacency
96 
99 
100 void CVertex::SetIndex(const UINT n){
101  m_nIndex = n;
102 } //SetIndex
103 
106 
108  return m_nIndex;
109 } //GetIndex
110 
113 
114 void CVertex::Mark(bool b){
115  m_bMarked = b;
116 } //Mark
117 
120 
122  return m_bMarked;
123 } //Marked
124 
127 
128 std::vector<CEdge*>* CVertex::GetAdjacencyList(){
129  return &m_vAdjacencyList;
130 } //GetAdjacencyList
131 
134 
136  return m_vAdjacencyList.size();
137 } //GetDegree
138 
140 // CGraph functions.
141 
144 
146  m_nNumVerts(n)
147 {
148  m_pVertexList = new CVertex[n];
149 
150  for(UINT i=0; i<n; i++)
151  m_pVertexList[i].SetIndex(i);
152 
153  m_cRandom.srand();
154 } //constructor
155 
157 
159  delete [] m_pVertexList;
160 
161  for(auto p: m_vEdgeList)
162  delete p;
163 } //destructor
164 
171 
172 void CGraph::InsertEdge(const UINT i, const UINT j){
173  if(i >= m_nNumVerts || j >= m_nNumVerts || i == j)return; //bail out
174 
175  CVertex* p0 = &m_pVertexList[i];
176  CVertex* p1 = &m_pVertexList[j];
177 
178  CEdge* pEdge = new CEdge(p0, p1, m_nNumEdges++);
179 
180  m_vEdgeList.push_back(pEdge); //append edge to edge list
181  p0->InsertAdjacency(pEdge); //append edge to adjacency list of first vertex
182  p1->InsertAdjacency(pEdge); //append edge to adjacency list of second vertex
183 } //InsertEdge
184 
188 
189 UINT CGraph::BFSF(std::vector<UINT>& result){
190  UINT numtrees = 0; //number of trees in spanning forest
191 
192  for(UINT i=0; i<m_nNumVerts; i++){
193  if(!m_pVertexList[i].Marked()){
194  m_qBFSQueue.push(&m_pVertexList[i]);
195  m_pVertexList[i].Mark();
196 
197  while(!m_qBFSQueue.empty()){
198  CVertex* current = m_qBFSQueue.front(); //get next queue element
199  m_qBFSQueue.pop(); //remove from queue
200 
201  std::vector<CEdge*>* pAdjList = current->GetAdjacencyList(); //shorthand
202 
203  //random permutation of adjacency list
204 
205  const int n = (int)pAdjList->size();
206  auto& adjacencylist = *pAdjList;
207 
208  for(int i=0; i<n-1; i++)
209  std::swap(adjacencylist[i], adjacencylist[m_cRandom.randn(i, n-1)]);
210 
211  for(CEdge* pEdge: *pAdjList){ //for edges incident with current vertex
212  CVertex* next = pEdge->GetNextVertex(current); //vertex at other end
213 
214  if(next != nullptr && !next->Marked()){ //if next vertex is unvisited
215  result.push_back(pEdge->GetIndex()); //append edge index to result
216  m_qBFSQueue.push(next); //recurse on next vertex
217  next->Mark();
218  } //if
219  } //for
220  } //while
221  } //if
222 
223  numtrees++; //one more tree in the forest
224  } //for
225 
226  //PrintGraph();
227 
228  return numtrees;
229 } //BFSF
230 
232 
234  FILE* output = nullptr;
235  fopen_s(&output, "graph.txt", "wt");
236 
237  if(output != 0){
238  fprintf_s(output, "%d vertices, %d edges\n", m_nNumVerts, m_nNumEdges);
239 
240  for(CEdge* p: m_vEdgeList){
241  UINT i, j;
242  p->GetVertexIndices(i, j);
243  fprintf(output, "(%u, %u)\n", i, j);
244  } //for
245 
246  fclose(output);
247  } //if
248 } //PrintGraph
CVertex * GetNextVertex(CVertex *p)
Get vertex at other end of edge.
Definition: Graph.cpp:47
size_t GetDegree()
Get degree.
Definition: Graph.cpp:135
UINT GetIndex()
Get index;.
Definition: Graph.cpp:107
UINT m_nNumEdges
Number of edges.
Definition: Graph.h:105
CRandom m_cRandom
Random number generator.
Definition: Graph.h:112
UINT m_nIndex
Index into vertex list.
Definition: Graph.h:74
void Mark(bool b=true)
Mark or unmark.
Definition: Graph.cpp:114
#define fprintf_s
fprintf_s for *NIX.
Definition: Helpers.h:36
UINT randn()
Get a random unsigned integer.
Definition: Random.cpp:49
void PrintGraph()
Print the graph to a text file.
Definition: Graph.cpp:233
std::queue< CVertex * > m_qBFSQueue
Queue for breadth-first search.
Definition: Graph.h:110
Header for helper functions.
bool m_bMarked
Mark flag.
Definition: Graph.h:47
std::vector< CEdge * > m_vEdgeList
Edge list.
Definition: Graph.h:104
unsigned int UINT
Abbreviation for unsigned integer.
Definition: Defines.h:84
void InsertAdjacency(CEdge *pEdge)
Add an edge to the edge list.
Definition: Graph.cpp:92
void SetIndex(const UINT n)
Set index.
Definition: Graph.cpp:100
void InsertEdge(const UINT i, const UINT j)
Insert an edge.
Definition: Graph.cpp:172
CVertex * m_pVertex0
Vertex at one end of the edge,.
Definition: Graph.h:43
void Mark(bool b=true)
Mark or unmark.
Definition: Graph.cpp:63
UINT BFSF(std::vector< UINT > &result)
Breadth-first spanning forest.
Definition: Graph.cpp:189
Graph vertex.
Definition: Graph.h:70
std::vector< CEdge * > m_vAdjacencyList
Adjacency list.
Definition: Graph.h:72
bool Marked()
Get mark.
Definition: Graph.cpp:70
UINT GetIndex()
Get index;.
Definition: Graph.cpp:56
CVertex * m_pVertex1
Vertex at the other end of the edge.
Definition: Graph.h:44
Header for the graph CGraph and its vertices CVertex and edges CEdge.
CEdge(CVertex *p0, CVertex *p1, UINT index)
Constructor.
Definition: Graph.cpp:38
void fopen_s(FILE **stream, const char *name, const char *fmt)
fopen_s for *NIX.
Definition: Helpers.cpp:40
CGraph(const UINT n)
Constructor.
Definition: Graph.cpp:145
Header for the pseudo-random number generator CRandom.
CVertex()
Constructor.
Definition: Graph.cpp:86
UINT m_nNumVerts
Number of vertices.
Definition: Graph.h:108
void srand()
Seed the random number generator.
Definition: Random.cpp:39
bool Marked()
Get mark.
Definition: Graph.cpp:121
~CGraph()
Destructor.
Definition: Graph.cpp:158
std::vector< CEdge * > * GetAdjacencyList()
Get adjacency list.
Definition: Graph.cpp:128
bool m_bMarked
Mark flag.
Definition: Graph.h:75
Graph edge.
Definition: Graph.h:41
UINT m_nIndex
Index into edge list.
Definition: Graph.h:46
CVertex * m_pVertexList
Vertex list.
Definition: Graph.h:107
void GetVertexIndices(UINT &i0, UINT &i1)
Get vertex indices.
Definition: Graph.cpp:78