Knight's Tour Generator
Tourneys and the Fast Generation and Obfuscation of Closed Knight's Tours
TakefujiLee.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 "TakefujiLee.h"
27 #include "Helpers.h"
28 #include "Random.h"
29 #include "Includes.h"
30 #include "Defines.h"
31 #include "Board.h"
32 
33 extern MoveDeltas g_vecDeltas;
34 extern std::atomic_bool g_bFinished;
35 
40 
41 CTakefujiLee::CTakefujiLee(int w, int h, int seed):
42  CNeuralNet(w*h, seed), m_nWidth(w), m_nHeight(h), m_nSize(w*h)
43 {
44  for(int srcy=0; srcy<m_nHeight; srcy++)
45  for(int srcx=0; srcx<m_nWidth; srcx++){
46  const int src = srcy*m_nWidth + srcx;
47 
48  for(auto delta: g_vecDeltas){
49  const int destx = srcx + delta.first;
50 
51  if(0 <= destx && destx < m_nWidth){
52  const int desty = srcy + delta.second;
53 
54  if(0 <= desty && desty < m_nHeight){
55  const int dest = desty*m_nWidth + destx;
56 
57  if(src < dest)
58  InsertNeuron(src, dest);
59  } //if
60  } //if
61  } //for
62  } //for
63 
64  Reset();
65 } //constructor
66 
69 
71  for(CEdge* pEdge: m_vEdgeList){
72  CNeuron* pNeuron = (CNeuron*)pEdge;
73  pNeuron->SetOutput(m_cRandom.randf() < 0.5f);
74  pNeuron->SetState(0);
75  } //for
76 
78 } //Reset
79 
82 
84  for(CEdge* pEdge: m_vEdgeList){ //update neuron states
85  CNeuron* pNeuron = (CNeuron*)pEdge;
86  int newstate = pNeuron->GetState() + 4;
87 
88  UINT v0, v1;
89  pEdge->GetVertexIndices(v0, v1);
90 
91  for(UINT v: {v0, v1}){
92  std::vector<CEdge*>* adj = m_pVertexList[v].GetAdjacencyList();
93 
94  for(CEdge* pEdge2: *adj)
95  if(((CNeuron*)pEdge2)->GetOutput())
96  newstate -= 1;
97  } //for
98 
99  pNeuron->SetState(newstate);
100 
101  if(newstate > 3)pNeuron->SetOutput(true);
102  else if(newstate < 0)pNeuron->SetOutput(false);
103  } //for
104 
105  return IsStable();
106 } //Update
107 
110 
112  for(CEdge* pEdge: m_vEdgeList)
113  if(((CNeuron*)pEdge)->IsStable())
114  return false;
115 
116  return true;
117 } //IsStable
118 
122 
124  int* degree = new int[m_nNumVerts];
125 
126  for(UINT i=0; i<m_nNumVerts; i++)
127  degree[i] = 0;
128 
129  for(CEdge* pEdge: m_vEdgeList){
130  CNeuron* pNeuron = (CNeuron*)pEdge;
131 
132  if(pNeuron->GetOutput()){
133  UINT i, j;
134  pNeuron->GetVertexIndices(i, j);
135  degree[i]++;
136  degree[j]++;
137  } //if
138  } //for
139 
140  bool bDegree2 = true;
141 
142  for(UINT i=0; i<m_nNumVerts && bDegree2; i++)
143  bDegree2 = bDegree2 && degree[i] == 2;
144 
145  delete [] degree;
146 
147  return bDegree2;
148 } //HasDegree2
149 
152 
154  bool bFinished = false;
155  bool bStable = false;
156 
157  while(!bFinished && !g_bFinished){
158  Reset();
159  bStable = false;
160 
161  for(int j=0; j<400 && !bStable; j++)
162  bStable = Update();
163 
164  bFinished = HasDegree2();
165  } //while
166 
167  if(bFinished)
168  GraphToBoard(b);
169 } //Generate
170 
174 
176  b.Clear();
177 
178  for(UINT i=0; i<m_nNumVerts; i++)
179  m_pVertexList[i].Mark(false);
180 
181  UINT startindex = 0;
182  while(startindex < m_nNumVerts && m_pVertexList[startindex].Marked())
183  startindex++;
184 
185  while(startindex < m_nNumVerts){
186  CVertex* start = &m_pVertexList[startindex];
187  CVertex* prev = start;
188  prev->Mark();
189 
190  CEdge* pEdge = nullptr;
191  auto adj = prev->GetAdjacencyList();
192 
193  for(auto it=(*adj).begin(); it!=(*adj).end(); it++){
194  CNeuron* pNeuron = (CNeuron*)*it;
195  if(pNeuron->GetOutput() == 1){
196  if(!pNeuron->GetNextVertex(prev)->Marked()){
197  pEdge = *it;
198  break;
199  } //if
200  } //if
201  } //for
202 
203  CVertex* cur = pEdge->GetNextVertex(prev);
204  b.InsertUndirectedMove(prev->GetIndex(), (int)cur->GetIndex());
205 
206  while(cur != start && !cur->Marked()){
207  cur->Mark();
208 
209  CEdge* pNextEdge = nullptr;
210  auto adj = cur->GetAdjacencyList();
211 
212  for(auto it=(*adj).begin(); it!=(*adj).end(); it++){
213  CNeuron* pNeuron = (CNeuron*)*it;
214  if(pNeuron->GetOutput() == 1 && (*it) != pEdge){
215  pNextEdge = *it;
216  break;
217  } //if
218  } //for
219 
220  CVertex* next = pNextEdge->GetNextVertex(cur);
221  prev = cur;
222  cur = next;
223  b.InsertUndirectedMove(prev->GetIndex(), (int)cur->GetIndex());
224 
225  pEdge = pNextEdge;
226  } //while
227 
228  while(startindex < m_nNumVerts && m_pVertexList[startindex].Marked())
229  startindex++;
230  } //while
231 } //GraphToBoard
232 
236 
237 void CTakefujiLee::GetAdjacentVertices(std::vector<CVertex*>& v, CVertex* p){
238  v.clear();
239  if(p == nullptr)return;
240 
241  std::vector<CEdge*>* adjacencylist = p->GetAdjacencyList();
242 
243  for(CEdge* pEdge: *adjacencylist){
244  CVertex* pNext = pEdge->GetNextVertex(p);
245  if(pNext != nullptr)
246  v.push_back(pNext);
247  } //for
248 } //GetAdjacentVertices
249 
251 
253  const size_t n = m_vEdgeList.size();
254 
255  for(size_t i=0; i<n; i++){
256  const int j = m_cRandom.randn((UINT)i, (UINT)n - 1);
257  std::swap(m_vEdgeList[i], m_vEdgeList[j]);
258  } //for
259 } //RandomizeEdgeList
CVertex * GetNextVertex(CVertex *p)
Get vertex at other end of edge.
Definition: Graph.cpp:47
int GetState()
Get neuron state.
Definition: NeuralNet.cpp:43
bool IsStable()
Stability test.
std::atomic_bool g_bFinished
Search termination flag.
UINT GetIndex()
Get index;.
Definition: Graph.cpp:107
bool HasDegree2()
Degree test.
Header for the neural network tourney generator CTakefujiLee.
void GraphToBoard(CBoard &b)
Convert graph to board.
Defines, enumerated types, and typedefs.
void SetOutput(bool b)
Set neuron output.
Definition: NeuralNet.cpp:73
int m_nWidth
Board width.
Definition: TakefujiLee.h:49
bool GetOutput()
Get neuron output.
Definition: NeuralNet.cpp:66
CRandom m_cRandom
Random number generator.
Definition: Graph.h:112
void Mark(bool b=true)
Mark or unmark.
Definition: Graph.cpp:114
Useful includes.
Neuron in a Hopfield network.
Definition: NeuralNet.h:41
MoveDeltas g_vecDeltas
Move deltas for all possible knight's moves.
Definition: Helpers.cpp:68
UINT randn()
Get a random unsigned integer.
Definition: Random.cpp:49
int m_nHeight
Board height.
Definition: TakefujiLee.h:50
Hopfield network.
Definition: NeuralNet.h:64
float randf()
Get a random floating point number.
Definition: Random.cpp:86
Header for helper functions.
void GetAdjacentVertices(std::vector< CVertex * > &v, CVertex *p)
Get adjacent vertices.
std::vector< CEdge * > m_vEdgeList
Edge list.
Definition: Graph.h:104
unsigned int UINT
Abbreviation for unsigned integer.
Definition: Defines.h:84
CTakefujiLee(int w, int h, int seed)
Constructor.
Definition: TakefujiLee.cpp:41
void SetState(int n)
Get neuron state.
Definition: NeuralNet.cpp:58
Graph vertex.
Definition: Graph.h:70
Chessboard.
Definition: Board.h:42
bool Update()
Update all neurons.
Definition: TakefujiLee.cpp:83
Header for the pseudo-random number generator CRandom.
UINT m_nNumVerts
Number of vertices.
Definition: Graph.h:108
Header for the chessboard CBoard.
void Reset()
Reset.
Definition: TakefujiLee.cpp:70
bool Marked()
Get mark.
Definition: Graph.cpp:121
void InsertNeuron(UINT i, UINT j)
Insert a neuron.
Definition: NeuralNet.cpp:99
void Generate(CBoard &b)
Generate a tourney.
std::vector< CEdge * > * GetAdjacencyList()
Get adjacency list.
Definition: Graph.cpp:128
std::vector< MoveDelta > MoveDeltas
Move deltas for knight's moves.
Definition: Helpers.h:43
Graph edge.
Definition: Graph.h:41
void RandomizeEdgeList()
Randomize the edge list.
CVertex * m_pVertexList
Vertex list.
Definition: Graph.h:107
bool InsertUndirectedMove(int src, int dest)
Insert an undirected move.
Definition: BaseBoard.cpp:482
void Clear()
Clear the board of moves.
Definition: BaseBoard.cpp:89
void GetVertexIndices(UINT &i0, UINT &i1)
Get vertex indices.
Definition: Graph.cpp:78