Files
KI/P2/AI_2.ipynb
2025-06-23 22:41:23 +02:00

861 lines
34 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "3cf53c1e",
"metadata": {},
"source": [
"# 8 Queen Problem\n",
"## Install Requirements\n",
"create a virtual environment in current directory by\n",
"\n",
"```\n",
"python3 -m venv .env # macos\n",
"python -m venv .env # linux\n",
"```\n",
"## Imports"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "39ee826a",
"metadata": {},
"outputs": [],
"source": [
"import random"
]
},
{
"cell_type": "markdown",
"id": "f6decafe",
"metadata": {},
"source": [
"## Field"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "33790f0d",
"metadata": {},
"outputs": [],
"source": [
"class Field:\n",
" \"\"\"\n",
" Represents the 8 Queens problem state and provides methods for state manipulation. Encodes initial state, actions, transition model, and heuristic functions.\n",
" \"\"\"\n",
"\n",
" def __init__(self, init_state=None, model=None):\n",
" \"\"\"\n",
" Initialize a new Field instance for the 8 Queens problem.\n",
" \n",
" Args:\n",
" init_state (list, optional): Initial queen positions [1-8] for a number of columns.\n",
" If None, generates random positions.\n",
" model (str, optional): Solution method to use (\"genetic\" or \"backtrack\").\n",
" \"\"\"\n",
" self.state = []\n",
" self.domain_values = [1, 2, 3, 4, 5, 6, 7, 8]\n",
"\n",
" if init_state is None:\n",
" self.move_all_queens()\n",
" else:\n",
" self.move_all_queens(init_state)\n",
"\n",
" self.threats = self.collisions(self.state)\n",
" self.fitness = 28 - self.threats\n",
"\n",
" self.model = model\n",
"\n",
" def get_fitness(self):\n",
" \"\"\"\n",
" Returns the fitness value of the current state.\n",
" \n",
" Returns:\n",
" int: Fitness\n",
" \"\"\"\n",
" return self.fitness\n",
"\n",
" def get_state(self):\n",
" \"\"\"\n",
" Returns the current state representation.\n",
" \n",
" Returns:\n",
" list: List of queen row positions for each column [1-8].\n",
" \"\"\"\n",
" return self.state\n",
"\n",
" def get_domain_values(self):\n",
" \"\"\"\n",
" Returns the current domain values for constraint satisfaction.\n",
" \n",
" Returns:\n",
" list: Available row positions for queen placement in next column.\n",
" \"\"\"\n",
" return self.domain_values\n",
"\n",
" # Actions\n",
" def set_state(self, column, row=None):\n",
" \"\"\"\n",
" Sets the queen position for a specific column and updates fitness and threats.\n",
" \n",
" Args:\n",
" column (int): Column index [0-7] to place queen.\n",
" row (int, optional): Row position [1-8]. If None, places randomly.\n",
" \"\"\"\n",
" if row is None:\n",
" if column == len(self.state):\n",
" self.state.append(random.randint(1, 8))\n",
" elif 0 < row < 9:\n",
" if column < len(self.state):\n",
" self.state[column] = row\n",
" elif column == len(self.state):\n",
" self.state.append(row)\n",
"\n",
" self.threats = self.collisions()\n",
" self.fitness = 28 - self.threats\n",
"\n",
" def set_domain_values(self, new_domain):\n",
" \"\"\"\n",
" Updates the domain values for constraint satisfaction.\n",
" \n",
" Args:\n",
" new_domain (list): New set of valid row positions.\n",
" \"\"\"\n",
" self.domain_values = new_domain\n",
"\n",
" def add_queen(self, row):\n",
" \"\"\"\n",
" Adds a new queen to the next available column.\n",
" \n",
" Args:\n",
" row (int): Row position [1-8] for the new queen.\n",
" \"\"\"\n",
" if len(self.get_state()) < 8:\n",
" self.set_state(len(self.get_state()), row)\n",
"\n",
" def move_queen(self, column, new_row=None):\n",
" \"\"\"\n",
" Moves a queen to a new row position.\n",
" \n",
" Args:\n",
" column (int): Column index [0-7] of queen to move.\n",
" new_row (int, optional): New row position [1-8]. If None, moves randomly.\n",
" \"\"\"\n",
" if column <= len(self.get_state()):\n",
" self.set_state(column, new_row)\n",
"\n",
" def move_all_queens(self, new_state=None):\n",
" \"\"\"\n",
" Moves all queens to new positions.\n",
" \n",
" Args:\n",
" new_state (list, optional): Complete new state configuration.\n",
" If None, moves all queens randomly.\n",
" \"\"\"\n",
" if new_state is None:\n",
" for i in range(8):\n",
" self.move_queen(i)\n",
" else:\n",
" for i, new_row in enumerate(new_state):\n",
" self.move_queen(i, new_row)\n",
"\n",
" # heuristics functions\n",
" def collisions(self, current_state=None):\n",
" \"\"\"\n",
" Calculates the number of queen threats (heuristic function).\n",
" Counts horizontal and diagonal attacks between queens.\n",
" \n",
" Args:\n",
" current_state (list, optional): State to evaluate. Uses self.state if None.\n",
" \n",
" Returns:\n",
" float: Number of conflicting queen pairs.\n",
" \"\"\"\n",
" # wagerechte haben die gleiche row zahl stehe\n",
" # diagonale haben einen wert der um den spalten-abstand gemindert ist => gleichseitiges rechtwinkliges Dreieck\n",
" # Beachte die Spalten/ Linien Nr ist um eins verringert [0, 1, ...,7]\n",
" if current_state is None:\n",
" current_state = self.get_state()\n",
"\n",
" threats = 0\n",
" for i, row_i in enumerate(current_state):\n",
" for j, row_j in enumerate(current_state):\n",
" if j != i:\n",
" # horizontal diagonal in both sides up and down and counting \"twice\"\n",
" if row_i == row_j or row_j == (row_i + abs(j - i)) or row_j == (row_i - abs(j - i)):\n",
" threats += 1\n",
" # print(f\"{i+1}-{row_i} <=> {j+1}-{row_j}\") # Debugging\n",
" return threats / 2\n",
"\n",
" def print_field(self):\n",
" \"\"\"\n",
" Displays an ASCII representation of the chess board with queens.\n",
" \"\"\"\n",
" print(\"\\n ┌───┬───┬───┬───┬───┬───┬───┬───┐\")\n",
" for row in range(8, 0, -1): # (0:8]\n",
" row_string = \"\"\n",
" for line in range(8):\n",
" if line < len(self.state) and row == self.state[line]: # is there a Queen in this line (spalte) in this row\n",
" if (row + line) % 2 == 0:\n",
" row_string += \"▌Q▐│\"\n",
" else:\n",
" row_string += \" Q │\"\n",
"\n",
" elif (row + line) % 2 == 0:\n",
" row_string += \"███│\"\n",
" else:\n",
" row_string += \" │\"\n",
"\n",
" print(f\"{row} │{row_string}\")\n",
" if row > 1: print(\" ├───┼───┼───┼───┼───┼───┼───┼───┤\")\n",
"\n",
" print(\" └───┴───┴───┴───┴───┴───┴───┴───┘\")\n",
" print(\" A B C D E F G H \\n\")\n",
" print(f\"Threats: {self.threats}\")\n",
" print(f\"Fitness: {self.fitness}\")\n",
"\n",
" def calc(self):\n",
" \"\"\"\n",
" Executes the specified solution algorithm based on the model type.\n",
" Updates based on the selected model the current state with the solution and displays the result.\n",
" \"\"\"\n",
" if self.model == \"genetic\":\n",
" best_field = Genetic().calc()\n",
" self.move_all_queens(best_field.get_state())\n",
" self.print_field()\n",
"\n",
" elif self.model == \"backtrack\":\n",
" Backtrack().calc()"
]
},
{
"cell_type": "markdown",
"id": "10c258e5",
"metadata": {},
"source": [
"## Genetic Algorithm"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "2ca3efc5",
"metadata": {},
"outputs": [],
"source": [
"class Genetic:\n",
" \"\"\"\n",
" Implements genetic algorithm for solving the 8 Queens problem.\n",
" Uses fitness-based selection, crossover, and mutation operations.\n",
" \"\"\"\n",
" def __init__(self, size=1000):\n",
" \"\"\"\n",
" Initialize genetic algorithm with random population.\n",
" \n",
" Args:\n",
" size (int): Population size for the genetic algorithm.\n",
" \"\"\"\n",
" self.initial_population = []\n",
" self.p_mutation = 0.1\n",
"\n",
" for i in range(size):\n",
" self.initial_population.append(Field())\n",
"\n",
" def random_selection(self, population):\n",
" \"\"\"\n",
" Performs fitness-proportionate selection from population.\n",
" Higher fitness individuals have higher probability of selection.\n",
" Basierend auf der Verteilung der heuristischen Werte (Fitness) soll zufällig ein Eintrag (Field) gewählt werden, d.h. je höher der heuritische Wert (Fitness) ist, umso höher soll die Wahrscheinlichkeit sein, dass ein Field ausgewählt wird\n",
" \n",
" Args:\n",
" population (list): List of Field instances to select from.\n",
" \n",
" Returns:\n",
" Field: Selected individual based on fitness distribution.\n",
" \"\"\"\n",
" fitness = []\n",
" for field in population:\n",
" fitness.append(field.get_fitness())\n",
"\n",
" # Weighted random selection based on fitness values\n",
" chosen = random.choices(population, weights=fitness, k=1)[0]\n",
"\n",
" return chosen\n",
"\n",
" def mutation(self, field):\n",
" \"\"\"\n",
" Performs single random mutation on an individual by moving one queen.\n",
" \n",
" Args:\n",
" field (Field): an Individual to mutate.\n",
" \"\"\"\n",
" field.move_queen(random.randint(0, 7), random.randint(1, 8))\n",
"\n",
" def reproduce(self, x, y):\n",
" \"\"\"\n",
" Creates child individual through crossover of two parent individuals.\n",
" Uses single-point crossover at random position c.\n",
" \n",
" Args:\n",
" x (Field): First parent individual.\n",
" y (Field): Second parent individual.\n",
" \n",
" Returns:\n",
" Field: Child individual\n",
" \"\"\"\n",
" child = []\n",
" n = len(x.get_state())\n",
" c = random.randint(1, n)\n",
"\n",
" # Slice operator Syntax [a:b)\n",
" child.extend(x.get_state()[:c]) # [0:c)\n",
" child.extend(y.get_state()[c:]) # [c:end)\n",
"\n",
" return Field(child)\n",
" \n",
" def remove_unfit(self, population, limit):\n",
" new_population = []\n",
" for i, field in enumerate(population):\n",
" if field.get_fitness() >= limit:\n",
" new_population.append(field) \n",
" \n",
" # filling up the removed fields\n",
" if len(new_population) < len(population):\n",
" for i in range(len(population) - len(new_population)):\n",
" random_field = new_population[random.randint(0,len(new_population))]\n",
" new_population.append(random_field)\n",
" return new_population\n",
"\n",
"\n",
" def genetic_algorithm(self, n):\n",
" \"\"\"\n",
" Main genetic algorithm loop for evolving population.\n",
" \n",
" Args:\n",
" n (int): Maximum number of generations to run.\n",
" \n",
" Returns:\n",
" Field: Best individual found after n generations.\n",
" \"\"\"\n",
" current_population = self.initial_population\n",
" new_population = []\n",
" best_field = self.initial_population[0]\n",
"\n",
" for i in range(n):\n",
" current_population = self.remove_unfit(current_population, 14)\n",
" for j in range(len(current_population)):\n",
" x = self.random_selection(current_population)\n",
" y = self.random_selection(current_population)\n",
"\n",
" child = self.reproduce(x, y)\n",
"\n",
" if random.random() < self.p_mutation:\n",
" self.mutation(child)\n",
"\n",
" new_population.append(child)\n",
"\n",
" if child.get_fitness() > best_field.get_fitness():\n",
" best_field = child\n",
" if best_field.get_fitness() == 28:\n",
" break\n",
"\n",
" print(f\"{i} {best_field.get_state()} {best_field.get_fitness()}\")\n",
" if best_field.get_fitness() == 28:\n",
" break\n",
"\n",
" current_population = new_population\n",
" new_population = []\n",
"\n",
" return best_field\n",
"\n",
" def calc(self, n=100):\n",
" \"\"\"\n",
" Executes genetic algorithm for specified number of generations.\n",
" \n",
" Args:\n",
" n (int): Number of generations to evolve (default: 100).\n",
" \n",
" Returns:\n",
" Field: Best solution found by genetic algorithm.\n",
" \"\"\"\n",
" best_genetic_field = self.genetic_algorithm(n)\n",
" return best_genetic_field"
]
},
{
"cell_type": "markdown",
"id": "bc171a9e",
"metadata": {},
"source": [
"## Backtracking"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "14a6ab56",
"metadata": {},
"outputs": [],
"source": [
"class Backtrack:\n",
" \"\"\"\n",
" Implements backtracking search for finding all solutions to 8 Queens problem.\n",
" Uses constraint satisfaction with consistency checking and inference.\n",
" \"\"\"\n",
"\n",
" def __init__(self):\n",
" \"\"\"\n",
" Initialize backtracking solver with empty results list.\n",
" \"\"\"\n",
" self.results = []\n",
"\n",
" def consistency(self, field, new_row):\n",
" \"\"\"\n",
" Checks if adding a queen at new_row maintains consistency.\n",
" Tests if the new configuration violates any constraints.\n",
" \n",
" Args:\n",
" field (Field): Current partial solution.\n",
" new_row (int): Row position for new queen.\n",
" \n",
" Returns:\n",
" bool: True if placement is consistent, False otherwise.\n",
" \"\"\"\n",
" current_state = field.get_state().copy()\n",
" current_state.append(new_row)\n",
" new_field = Field(current_state)\n",
"\n",
" if new_field.threats > 0:\n",
" return False\n",
" else:\n",
" return True\n",
"\n",
" def inference(self, field):\n",
" \"\"\"\n",
" Performs constraint propagation to reduce domain values.\n",
" Eliminates impossible row positions for the next column based on current state.\n",
" \n",
" Args:\n",
" field (Field): Current partial solution.\n",
" \n",
" Returns:\n",
" bool: True if domain is not empty, False if no valid moves remain.\n",
" \"\"\"\n",
" if len(field.get_state()) >= 8:\n",
" return True\n",
" \n",
" # Reset domain for current column\n",
" field.set_domain_values([1, 2, 3, 4, 5, 6, 7, 8]) \n",
" inferences = []\n",
"\n",
" for new_row in range(1, 9):\n",
" if not self.consistency(field, new_row):\n",
" inferences.append(new_row)\n",
"\n",
" for row in inferences:\n",
" if row in field.get_domain_values():\n",
" field.get_domain_values().remove(row)\n",
"\n",
" if len(field.get_domain_values()) == 0:\n",
" return False\n",
"\n",
" return True\n",
"\n",
" def backtracing(self, field):\n",
" \"\"\"\n",
" Recursive backtracking search to find all valid solutions.\n",
" \n",
" Args:\n",
" field (Field): Current partial solution.\n",
" \n",
" Returns:\n",
" list: List of complete solutions found from this state.\n",
" \"\"\"\n",
" if len(field.get_state()) == 8:\n",
" return [Field(field.get_state().copy())]\n",
"\n",
" solutions = []\n",
"\n",
" for row in field.get_domain_values():\n",
" # old_domain_values = field.get_domain_values().copy()\n",
" if self.consistency(field, row):\n",
" field.add_queen(row)\n",
" if self.inference(field): # nur für die nächste Spalte\n",
" result = self.backtracing(field)\n",
" if len(result) != 0:\n",
" solutions.extend(result)\n",
"\n",
" field.get_state().pop()\n",
" # field.domain_values = old_domain_values\n",
"\n",
" return solutions\n",
"\n",
" def calc(self):\n",
" for i in range(1, 9):\n",
" result = self.backtracing(Field([i]))\n",
" self.results.extend(result)\n",
" for i, result in enumerate(self.results):\n",
" print(f\"{i + 1} {result.get_state()}\")"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "0ba915ff",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"------- Genetic -------\n",
"0 [8, 4, 7, 1, 2, 6, 1, 3] 26.0\n",
"1 [8, 4, 7, 1, 2, 6, 1, 3] 26.0\n",
"2 [8, 4, 7, 1, 2, 6, 1, 3] 26.0\n",
"3 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"4 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"5 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"6 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"7 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"8 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"9 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"10 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"11 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"12 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"13 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"14 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"15 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"16 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"17 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"18 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"19 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"20 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"21 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"22 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"23 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"24 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"25 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"26 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"27 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"28 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"29 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"30 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"31 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"32 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"33 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"34 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"35 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"36 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"37 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"38 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"39 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"40 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"41 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"42 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"43 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"44 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"45 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"46 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"47 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"48 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"49 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"50 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"51 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"52 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"53 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"54 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"55 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"56 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"57 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"58 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"59 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"60 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"61 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"62 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"63 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"64 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"65 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"66 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"67 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"68 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"69 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"70 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"71 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"72 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"73 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"74 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"75 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"76 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"77 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"78 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"79 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"80 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"81 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"82 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"83 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"84 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"85 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"86 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"87 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"88 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"89 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"90 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"91 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"92 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"93 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"94 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"95 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"96 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"97 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"98 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"99 [3, 6, 8, 1, 5, 7, 2, 7] 27.0\n",
"\n",
" ┌───┬───┬───┬───┬───┬───┬───┬───┐\n",
"8 │███│ │▌Q▐│ │███│ │███│ │\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"7 │ │███│ │███│ │▌Q▐│ │▌Q▐│\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"6 │███│ Q │███│ │███│ │███│ │\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"5 │ │███│ │███│ Q │███│ │███│\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"4 │███│ │███│ │███│ │███│ │\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"3 │ Q │███│ │███│ │███│ │███│\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"2 │███│ │███│ │███│ │▌Q▐│ │\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"1 │ │███│ │▌Q▐│ │███│ │███│\n",
" └───┴───┴───┴───┴───┴───┴───┴───┘\n",
" A B C D E F G H \n",
"\n",
"Threats: 1.0\n",
"Fitness: 27.0\n"
]
}
],
"source": [
"def genetic():\n",
" print(\"------- Genetic -------\")\n",
" gen_field = Field(model=\"genetic\")\n",
" gen_field.calc()\n",
"\n",
"genetic()"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "8be85fd2",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"------- Backtrack -------\n",
"1 [1, 5, 8, 6, 3, 7, 2, 4]\n",
"2 [1, 6, 8, 3, 7, 4, 2, 5]\n",
"3 [1, 7, 4, 6, 8, 2, 5, 3]\n",
"4 [1, 7, 5, 8, 2, 4, 6, 3]\n",
"5 [2, 4, 6, 8, 3, 1, 7, 5]\n",
"6 [2, 5, 7, 1, 3, 8, 6, 4]\n",
"7 [2, 5, 7, 4, 1, 8, 6, 3]\n",
"8 [2, 6, 1, 7, 4, 8, 3, 5]\n",
"9 [2, 6, 8, 3, 1, 4, 7, 5]\n",
"10 [2, 7, 3, 6, 8, 5, 1, 4]\n",
"11 [2, 7, 5, 8, 1, 4, 6, 3]\n",
"12 [2, 8, 6, 1, 3, 5, 7, 4]\n",
"13 [3, 1, 7, 5, 8, 2, 4, 6]\n",
"14 [3, 5, 2, 8, 1, 7, 4, 6]\n",
"15 [3, 5, 2, 8, 6, 4, 7, 1]\n",
"16 [3, 5, 7, 1, 4, 2, 8, 6]\n",
"17 [3, 5, 8, 4, 1, 7, 2, 6]\n",
"18 [3, 6, 2, 5, 8, 1, 7, 4]\n",
"19 [3, 6, 2, 7, 1, 4, 8, 5]\n",
"20 [3, 6, 2, 7, 5, 1, 8, 4]\n",
"21 [3, 6, 4, 1, 8, 5, 7, 2]\n",
"22 [3, 6, 4, 2, 8, 5, 7, 1]\n",
"23 [3, 6, 8, 1, 4, 7, 5, 2]\n",
"24 [3, 6, 8, 1, 5, 7, 2, 4]\n",
"25 [3, 6, 8, 2, 4, 1, 7, 5]\n",
"26 [3, 7, 2, 8, 5, 1, 4, 6]\n",
"27 [3, 7, 2, 8, 6, 4, 1, 5]\n",
"28 [3, 8, 4, 7, 1, 6, 2, 5]\n",
"29 [4, 1, 5, 8, 2, 7, 3, 6]\n",
"30 [4, 1, 5, 8, 6, 3, 7, 2]\n",
"31 [4, 2, 5, 8, 6, 1, 3, 7]\n",
"32 [4, 2, 7, 3, 6, 8, 1, 5]\n",
"33 [4, 2, 7, 3, 6, 8, 5, 1]\n",
"34 [4, 2, 7, 5, 1, 8, 6, 3]\n",
"35 [4, 2, 8, 5, 7, 1, 3, 6]\n",
"36 [4, 2, 8, 6, 1, 3, 5, 7]\n",
"37 [4, 6, 1, 5, 2, 8, 3, 7]\n",
"38 [4, 6, 8, 2, 7, 1, 3, 5]\n",
"39 [4, 6, 8, 3, 1, 7, 5, 2]\n",
"40 [4, 7, 1, 8, 5, 2, 6, 3]\n",
"41 [4, 7, 3, 8, 2, 5, 1, 6]\n",
"42 [4, 7, 5, 2, 6, 1, 3, 8]\n",
"43 [4, 7, 5, 3, 1, 6, 8, 2]\n",
"44 [4, 8, 1, 3, 6, 2, 7, 5]\n",
"45 [4, 8, 1, 5, 7, 2, 6, 3]\n",
"46 [4, 8, 5, 3, 1, 7, 2, 6]\n",
"47 [5, 1, 4, 6, 8, 2, 7, 3]\n",
"48 [5, 1, 8, 4, 2, 7, 3, 6]\n",
"49 [5, 1, 8, 6, 3, 7, 2, 4]\n",
"50 [5, 2, 4, 6, 8, 3, 1, 7]\n",
"51 [5, 2, 4, 7, 3, 8, 6, 1]\n",
"52 [5, 2, 6, 1, 7, 4, 8, 3]\n",
"53 [5, 2, 8, 1, 4, 7, 3, 6]\n",
"54 [5, 3, 1, 6, 8, 2, 4, 7]\n",
"55 [5, 3, 1, 7, 2, 8, 6, 4]\n",
"56 [5, 3, 8, 4, 7, 1, 6, 2]\n",
"57 [5, 7, 1, 3, 8, 6, 4, 2]\n",
"58 [5, 7, 1, 4, 2, 8, 6, 3]\n",
"59 [5, 7, 2, 4, 8, 1, 3, 6]\n",
"60 [5, 7, 2, 6, 3, 1, 4, 8]\n",
"61 [5, 7, 2, 6, 3, 1, 8, 4]\n",
"62 [5, 7, 4, 1, 3, 8, 6, 2]\n",
"63 [5, 8, 4, 1, 3, 6, 2, 7]\n",
"64 [5, 8, 4, 1, 7, 2, 6, 3]\n",
"65 [6, 1, 5, 2, 8, 3, 7, 4]\n",
"66 [6, 2, 7, 1, 3, 5, 8, 4]\n",
"67 [6, 2, 7, 1, 4, 8, 5, 3]\n",
"68 [6, 3, 1, 7, 5, 8, 2, 4]\n",
"69 [6, 3, 1, 8, 4, 2, 7, 5]\n",
"70 [6, 3, 1, 8, 5, 2, 4, 7]\n",
"71 [6, 3, 5, 7, 1, 4, 2, 8]\n",
"72 [6, 3, 5, 8, 1, 4, 2, 7]\n",
"73 [6, 3, 7, 2, 4, 8, 1, 5]\n",
"74 [6, 3, 7, 2, 8, 5, 1, 4]\n",
"75 [6, 3, 7, 4, 1, 8, 2, 5]\n",
"76 [6, 4, 1, 5, 8, 2, 7, 3]\n",
"77 [6, 4, 2, 8, 5, 7, 1, 3]\n",
"78 [6, 4, 7, 1, 3, 5, 2, 8]\n",
"79 [6, 4, 7, 1, 8, 2, 5, 3]\n",
"80 [6, 8, 2, 4, 1, 7, 5, 3]\n",
"81 [7, 1, 3, 8, 6, 4, 2, 5]\n",
"82 [7, 2, 4, 1, 8, 5, 3, 6]\n",
"83 [7, 2, 6, 3, 1, 4, 8, 5]\n",
"84 [7, 3, 1, 6, 8, 5, 2, 4]\n",
"85 [7, 3, 8, 2, 5, 1, 6, 4]\n",
"86 [7, 4, 2, 5, 8, 1, 3, 6]\n",
"87 [7, 4, 2, 8, 6, 1, 3, 5]\n",
"88 [7, 5, 3, 1, 6, 8, 2, 4]\n",
"89 [8, 2, 4, 1, 7, 5, 3, 6]\n",
"90 [8, 2, 5, 3, 1, 7, 4, 6]\n",
"91 [8, 3, 1, 6, 2, 5, 7, 4]\n",
"92 [8, 4, 1, 3, 6, 2, 7, 5]\n"
]
}
],
"source": [
"\n",
"def backtrack():\n",
" print(\"------- Backtrack -------\")\n",
" back_field = Field(model=\"backtrack\")\n",
" back_field.calc()\n",
"\n",
"backtrack()"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "b5371c6e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"------- My Field -------\n",
"\n",
" ┌───┬───┬───┬───┬───┬───┬───┬───┐\n",
"8 │▌Q▐│ │███│ │███│ │███│ │\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"7 │ │███│ │███│ │▌Q▐│ │███│\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"6 │███│ │███│ │███│ │███│ │\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"5 │ │███│ Q │▌Q▐│ Q │███│ │███│\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"4 │███│ │███│ │███│ │▌Q▐│ Q │\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"3 │ │███│ │███│ │███│ │███│\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"2 │███│ │███│ │███│ │███│ │\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"1 │ │▌Q▐│ │███│ │███│ │███│\n",
" └───┴───┴───┴───┴───┴───┴───┴───┘\n",
" A B C D E F G H \n",
"\n",
"Threats: 6.0\n",
"Fitness: 22.0\n",
"[8, 1, 5, 5, 5, 7, 4, 4]\n",
"\n",
" ┌───┬───┬───┬───┬───┬───┬───┬───┐\n",
"8 │▌Q▐│ │███│ │███│ │███│ │\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"7 │ │███│ │███│ │▌Q▐│ │███│\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"6 │███│ │███│ │███│ │███│ │\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"5 │ │███│ Q │▌Q▐│ Q │███│ │███│\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"4 │███│ Q │███│ │███│ │▌Q▐│ Q │\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"3 │ │███│ │███│ │███│ │███│\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"2 │███│ │███│ │███│ │███│ │\n",
" ├───┼───┼───┼───┼───┼───┼───┼───┤\n",
"1 │ │███│ │███│ │███│ │███│\n",
" └───┴───┴───┴───┴───┴───┴───┴───┘\n",
" A B C D E F G H \n",
"\n",
"Threats: 9.0\n",
"Fitness: 19.0\n",
"[8, 4, 5, 5, 5, 7, 4, 4]\n"
]
}
],
"source": [
"\n",
"def main():\n",
" print(\"------- My Field -------\")\n",
" myField = Field()\n",
" myField.print_field()\n",
" print(myField.get_state())\n",
" myField.move_queen(1,4)\n",
" myField.print_field()\n",
" print(myField.get_state())\n",
"\n",
"main()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".env",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.18"
}
},
"nbformat": 4,
"nbformat_minor": 5
}