Skip to content

Commit 5307e4d

Browse files
authored
collab
1 parent fdfdd25 commit 5307e4d

File tree

1 file changed

+359
-0
lines changed

1 file changed

+359
-0
lines changed

The_Knight's_independence (2).ipynb

Lines changed: 359 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,359 @@
1+
{
2+
"nbformat": 4,
3+
"nbformat_minor": 0,
4+
"metadata": {
5+
"colab": {
6+
"provenance": []
7+
},
8+
"kernelspec": {
9+
"name": "python3",
10+
"display_name": "Python 3"
11+
},
12+
"language_info": {
13+
"name": "python"
14+
}
15+
},
16+
"cells": [
17+
{
18+
"cell_type": "code",
19+
"execution_count": 9,
20+
"metadata": {
21+
"id": "cN8DZ70tBImW"
22+
},
23+
"outputs": [],
24+
"source": [
25+
"# The Knight's Independence Problem (The k Knight's problem)\n",
26+
"# Matheus Ribeiro Alencar https://github.com/matheusriale\n",
27+
"import random\n",
28+
"import copy\n",
29+
"\n",
30+
"#initialize the chessboard\n",
31+
"def initialize_chessboard(dim):\n",
32+
" matrix = []\n",
33+
" row = [0]*dim\n",
34+
" for i in range(dim):\n",
35+
" matrix.append(row[:]) #copy of row, no indexing problems later on\n",
36+
" return matrix"
37+
]
38+
},
39+
{
40+
"cell_type": "code",
41+
"source": [
42+
"#Knight's move restrictions, we restrict the squares attacked\n",
43+
"def place_attacks(pos_x,pos_y,chessboard):\n",
44+
" if pos_x+2<dim and pos_y +1<dim:\n",
45+
" chessboard[pos_x+2][pos_y +1] = 'X'\n",
46+
" if pos_x+2<dim and pos_y -1 >=0:\n",
47+
" chessboard[pos_x+2][pos_y -1] = 'X'\n",
48+
" if pos_x+1<dim and pos_y +2<dim:\n",
49+
" chessboard[pos_x+1][pos_y +2] = 'X'\n",
50+
" if pos_x+1<dim and pos_y -2>=0:\n",
51+
" chessboard[pos_x+1][pos_y -2] = 'X'\n",
52+
" if pos_x-2>=0 and pos_y+1<dim:\n",
53+
" chessboard[pos_x-2][pos_y +1] = 'X'\n",
54+
" if pos_x-2>=0 and pos_y-1>=0:\n",
55+
" chessboard[pos_x-2][pos_y -1] = 'X'\n",
56+
" if pos_x-1>=0 and pos_y-2>=0:\n",
57+
" chessboard[pos_x-1][pos_y -2] = 'X'\n",
58+
" if pos_x-1>=0 and pos_y+2<dim:\n",
59+
" chessboard[pos_x-1][pos_y +2] = 'X'"
60+
],
61+
"metadata": {
62+
"id": "EmvnRNUNEEDT"
63+
},
64+
"execution_count": 10,
65+
"outputs": []
66+
},
67+
{
68+
"cell_type": "code",
69+
"source": [
70+
"def check_attacks(chessboard):\n",
71+
" pos_x = None\n",
72+
" pos_y = None\n",
73+
" less_restrictions = -9 # Highest number of squares restricted by the knight's moves is 8\n",
74+
" A = copy.deepcopy(chessboard) # copy of chessboard\n",
75+
" # Insert copies of original object, source: https://docs.python.org/dev/library/copy.html#module-copy\n",
76+
" for i in range(0,len(A)):\n",
77+
" for j in range(0,len(A)):\n",
78+
" restricted_fields = 0\n",
79+
"\n",
80+
" if A[i][j] != 'X' and A[i][j] == 0: #square availabel, we will check if it gets us a good solution\n",
81+
" if i+2<(len(A)) and j+1<(len(A)):\n",
82+
" if A[i+2][j +1] != 'X' and A[i+2][j +1] <= 0:\n",
83+
" restricted_fields = restricted_fields - 1\n",
84+
"\n",
85+
" if i+2<(len(A)) and j -1 >=0:\n",
86+
" if A[i+2][j -1] != 'X' and A[i+2][j -1] <= 0:\n",
87+
" restricted_fields = restricted_fields - 1\n",
88+
"\n",
89+
" if i+1<(len(A)) and j +2<(len(A)):\n",
90+
" if A[i+1][j +2] != 'X' and A[i+1][j +2] <= 0:\n",
91+
" restricted_fields = restricted_fields - 1\n",
92+
"\n",
93+
" if i+1<(len(A)) and j -2>=0:\n",
94+
" if A[i+1][j -2] != 'X' and A[i+1][j -2] <= 0:\n",
95+
" restricted_fields = restricted_fields - 1\n",
96+
"\n",
97+
" if i-2>=0 and j+1<(len(A)):\n",
98+
" if A[i-2][j +1] != 'X' and A[i-2][j +1] <= 0:\n",
99+
" restricted_fields = restricted_fields - 1\n",
100+
"\n",
101+
" if i-2>=0 and j-1>=0:\n",
102+
" if A[i-2][j -1]!= 'X' and A[i-2][j -1] <= 0:\n",
103+
" restricted_fields = restricted_fields - 1\n",
104+
"\n",
105+
" if i-1>=0 and j-2>=0:\n",
106+
" if A[i-1][j -2]!= 'X' and A[i-1][j -2] <= 0:\n",
107+
" restricted_fields = restricted_fields - 1\n",
108+
"\n",
109+
" if i-1>=0 and j+2<len(A):\n",
110+
" if A[i-1][j +2]!= 'X' and A[i-1][j +2] <= 0:\n",
111+
" restricted_fields = restricted_fields - 1\n",
112+
"\n",
113+
"\n",
114+
" A[i][j] = restricted_fields\n",
115+
"\n",
116+
" if less_restrictions <= restricted_fields: #we keep our best solution (highest number, minimum = -8, highest = 0(best scenario))\n",
117+
" less_restrictions = restricted_fields\n",
118+
" pos_x = i\n",
119+
" pos_y = j\n",
120+
"\n",
121+
"\n",
122+
" return (pos_x,pos_y,A)"
123+
],
124+
"metadata": {
125+
"id": "M815-gViEBDJ"
126+
},
127+
"execution_count": 11,
128+
"outputs": []
129+
},
130+
{
131+
"cell_type": "code",
132+
"source": [
133+
"#Placing the knights\n",
134+
"def place_knights(chessboard):\n",
135+
" global current_knight\n",
136+
"\n",
137+
" if current_knight == 1:\n",
138+
" first_move = True\n",
139+
" else:\n",
140+
" first_move = False\n",
141+
" dim = len(chessboard)\n",
142+
"\n",
143+
" if first_move: #On first move, we got no restrictions yet. By our heuristic, we will start in one of the 4 corners since it only blocks 2 squares\n",
144+
"\n",
145+
" #We will choose randomly the first square to be occupied\n",
146+
"\n",
147+
" corners = [0,dim-1]\n",
148+
" pos_x = random.choice(corners)\n",
149+
" pos_y = random.choice(corners)\n",
150+
" chessboard[pos_x][pos_y] = current_knight\n",
151+
"\n",
152+
"\n",
153+
" #We restrict positions on our chessboard based on the knight that was placed\n",
154+
" place_attacks(pos_x,pos_y,chessboard)\n",
155+
"\n",
156+
" current_knight = current_knight + 1\n",
157+
"\n",
158+
"\n",
159+
" #After first move\n",
160+
" else:\n",
161+
" for i in range(dim*dim - 1):\n",
162+
"\n",
163+
" pos = check_attacks(chessboard)\n",
164+
" if pos[0] == None:\n",
165+
" break\n",
166+
" chessboard[pos[0]][pos[1]] = current_knight #Alocamos o i-ésimo cavaleiro a melhor posição possível (segundo nossa heurística).\n",
167+
" place_attacks(pos[0],pos[1],chessboard)\n",
168+
"\n",
169+
" current_knight = current_knight + 1\n",
170+
" #return chessboard\n",
171+
"\n",
172+
" return reset_chessboard()\n",
173+
" return"
174+
],
175+
"metadata": {
176+
"id": "9GR6nY_uD6YS"
177+
},
178+
"execution_count": 12,
179+
"outputs": []
180+
},
181+
{
182+
"cell_type": "code",
183+
"source": [
184+
"#We keep our chessboard and the number of knights on that board\n",
185+
"#We reset the board to start another one, if necessary\n",
186+
"def reset_chessboard():\n",
187+
" global chessboard_solutions\n",
188+
" global solutions\n",
189+
" global current_knight\n",
190+
" global chessboard\n",
191+
"\n",
192+
" chessboard_solutions.append(chessboard)\n",
193+
" n_knights = current_knight - 1\n",
194+
" solutions.append(n_knights)\n",
195+
" current_knight = 1\n",
196+
"\n",
197+
" dim= len(chessboard)\n",
198+
" chessboard = []\n",
199+
" row = [0]*dim\n",
200+
" for i in range(dim):\n",
201+
" chessboard.append(row[:])\n",
202+
"\n",
203+
" return chessboard_solutions,solutions"
204+
],
205+
"metadata": {
206+
"id": "jdA6fqVeD11V"
207+
},
208+
"execution_count": 13,
209+
"outputs": []
210+
},
211+
{
212+
"cell_type": "code",
213+
"source": [
214+
"def branch(P): #we will branch our board P in P0 (without putting a knight on the next position) and in P1(having a knight on the next position)\n",
215+
" P1 = copy.deepcopy(P)\n",
216+
"#----------------------------------------PRUNE-------------------------------------------------------\n",
217+
" next = 1 #variable to allow the continuation of our branches\n",
218+
" #check if we can prune P and consequently P1\n",
219+
" #verify prune comparing the best solution (putting knights in all remaining squares) with the heuristic solution\n",
220+
" max_knights = 0\n",
221+
" for i in range(len(P)):\n",
222+
" for j in range(len(P)):\n",
223+
" if P[i][j] != 'X' and (P[i][j] == 'K' or P[i][j] == 0):\n",
224+
" max_knights = max_knights + 1\n",
225+
" if max_knights < solutions[0]: #if the highest number is lower, it is not worth it, we return None\n",
226+
" P = None\n",
227+
" P1 = None\n",
228+
" return (P,P1,next)\n",
229+
"#-----------------------------------------------------------------------------------------------------\n",
230+
" global final_solutions #vector where we will add our solutions\n",
231+
"\n",
232+
" next = 0\n",
233+
" for i in range(len(P)):\n",
234+
" for j in range(len(P)):\n",
235+
" if P[i][j] == 0: #if exists at least one 0 element (square available), we will put our markings X -> no Knight, K -> Knight\n",
236+
" next = 1\n",
237+
" P[i][j] = 'X'\n",
238+
" P1[i][j] = 'K'\n",
239+
" place_attacks(i,j,P1)\n",
240+
" break\n",
241+
" if next == 1:\n",
242+
" break\n",
243+
" else:\n",
244+
" if P not in final_solutions: #Discarding repeated solutions\n",
245+
" final_solutions.append(P)\n",
246+
" return (P,P1,next)"
247+
],
248+
"metadata": {
249+
"id": "Pkxcmu7-Dvws"
250+
},
251+
"execution_count": 14,
252+
"outputs": []
253+
},
254+
{
255+
"cell_type": "code",
256+
"source": [
257+
"#--------------------------------------------------------- MAIN -------------------------------------------------------------------\n",
258+
"#initializing variables and global variables (our chessboard)\n",
259+
"dim = int(input(\"Chessboard dimension: \\n\"))\n",
260+
"chessboard = initialize_chessboard(dim)\n",
261+
"current_knight = 1\n",
262+
"chessboard_solutions = []\n",
263+
"solutions = [] #number of knights on that board\n",
264+
"first_knight = True #for heuristic's use in first move\n",
265+
"\n",
266+
"#--------------------------------------------------------- MAIN HEURISTIC ---------------------------------------------------------\n",
267+
"#In this section we use our heuristic to estabilish a \"good\" solution\n",
268+
"print(\"\\n-------------------------------------------------------\\n\")\n",
269+
"test_solutions = []\n",
270+
"while len(solutions) < 1:\n",
271+
" test_solutions.append(place_knights(chessboard)) #keep every board solution and it's number of knights\n",
272+
"\n",
273+
"print(\"By our heuristc we have:\")\n",
274+
"for i in chessboard_solutions[0]:\n",
275+
" print(i)\n",
276+
"print('Highest number of knights by our heuristic:',solutions[0],'\\n')\n",
277+
"\n",
278+
"#----------------------------------------------------------------------------------------------------------------------------------\n",
279+
"#Initializing our queue, and solutions vector\n",
280+
"queue = [initialize_chessboard(dim)]\n",
281+
"q_solutions = []\n",
282+
"final_solutions = []\n",
283+
"\n",
284+
"while len(queue) > 0:\n",
285+
" P = queue.pop(0)\n",
286+
" v = branch(P)\n",
287+
" if v[2] == 1:\n",
288+
" if v[0]!= None:\n",
289+
" queue.append(v[0])\n",
290+
" if v[1]!= None:\n",
291+
" queue.append(v[1])\n",
292+
"\n",
293+
"solutions_size = len(final_solutions) #keep our number of possible solutions\n",
294+
"for i in range(solutions_size):\n",
295+
" count = 0\n",
296+
" for j in range(dim):\n",
297+
" for k in range(dim):\n",
298+
" if final_solutions[i][j][k] == 'K':\n",
299+
" count = count + 1\n",
300+
" q_solutions.append(count) #count the number of knights per solution\n",
301+
" #No need to remove all lists from our queue, in the moment we got no more squares available we stop the process\n",
302+
"\n",
303+
"print(\"Solutions possiblle: \", solutions_size)\n",
304+
"max = idx = 0\n",
305+
"for i in range(solutions_size):\n",
306+
" if q_solutions[i] >= max:\n",
307+
" max = q_solutions[i]\n",
308+
" idx = i\n",
309+
"\n",
310+
"print(\"Highest number of knights possible: \",max)\n",
311+
"print(\"Possible chessboard configuration: \")\n",
312+
"for i in final_solutions[idx]:\n",
313+
" print(i)"
314+
],
315+
"metadata": {
316+
"colab": {
317+
"base_uri": "https://localhost:8080/"
318+
},
319+
"id": "rNrH87sMDJMm",
320+
"outputId": "809fc858-880b-4817-cf2a-08d89ea3af95"
321+
},
322+
"execution_count": 15,
323+
"outputs": [
324+
{
325+
"output_type": "stream",
326+
"name": "stdout",
327+
"text": [
328+
"Chessboard dimension: \n",
329+
"3\n",
330+
"\n",
331+
"-------------------------------------------------------\n",
332+
"\n",
333+
"By our heuristc we have:\n",
334+
"[5, 'X', 4]\n",
335+
"['X', 2, 'X']\n",
336+
"[3, 'X', 1]\n",
337+
"Highest number of knights by our heuristic: 5 \n",
338+
"\n",
339+
"Solutions possiblle: 16\n",
340+
"Highest number of knights possible: 5\n",
341+
"Possible chessboard configuration: \n",
342+
"['X', 'K', 'X']\n",
343+
"['K', 'K', 'K']\n",
344+
"['X', 'K', 'X']\n"
345+
]
346+
}
347+
]
348+
},
349+
{
350+
"cell_type": "code",
351+
"source": [],
352+
"metadata": {
353+
"id": "h5daznWRwytg"
354+
},
355+
"execution_count": 15,
356+
"outputs": []
357+
}
358+
]
359+
}

0 commit comments

Comments
 (0)