You are on page 1of 6

FAKULTA INFORMATIKY A INFORMAČNÝCH

TECHNOLÓGIÍ SLOVENSKÁ TECHNICKÁ


UNIVERZITA
lkovičova 2, 842 16 Bratislava 4

Umelá Inteligencia
2023/2024
Zadanie č.1
Problém 1, úloha B)

Dokumentacia
RIEŠENÝ PROBLÉM

Opis
Mojou úlohou je vyriešiť problém „Bláznivá križovatka“ pomocou cyklicky sa prehlbujúceho
vyhľadávacieho mechanizmu. Problém zahŕňa mriežku, v ktorej sú vozidlá (autá a nákladné autá)
usporiadané v rôznych konfiguráciách. Cieľom probému je posunúť určené auto označené znakom 'C' k
východu, čo je pravý okraj mriežky, posunutím ostatných vozidiel z jeho cesty.

Operátory:
Operátory reprezentujú možné ťahy, ktoré môžete vykonať s autom. Môžete posúvať auto nahor, nadol,
vľavo alebo vpravo. Počet krokov, o ktorý sa auto posunie, je tiež súčasťou operátora.

Uzol:
Uzol je reprezentovaný triedou Node a obsahuje informácie o aktuálnom stave hry (aktualizovanej
mriežke), rodičovskom uzle, liste v ktorom sú detské uzly, hĺbke uzlu a informácie o vykonanom ťahu,
ktorý viedol k tomuto stavu.

Heuristika:
Funkcia heuristic je použitá na odhadovanie počtu krokov potrebných na dosiahnutie cieľa. Počítava
počet blokujúcich áut a krokov potrebných na ich odstránenie z cesty hlavného auta.
Cyklické prehľadávanie do hľbky:
Táto metóda sa používa v funkcii cds_search, ktorá skúma všetky možné ťahy na rôznych úrovniach
hĺbky až do stanoveného limitu. Funkcia vracia riešenie v prípade, že ho nájde, alebo None, ak sa riešenie
nenájde.

Celé riešenie som naprogramoval v Python, pričom som implementoval hĺbkové prehľadávanie s
ohraničenou hĺbkou. Použil som aj heuristickú funkciu, ktorá hodnotila počet blokujúcich áut a potrebný
počet krokov na ich odstránenie. Vo výpise výsledku mojho riešenia môžete vidieť detailný prehľad o
aktuálnej hĺbke prehľadávania, počte preskúmaných a vytvorených uzlov, ako aj o aktuálnej veľkosti
zásobníka.
ZHRNUTIE KÓDU
Definoval som triedy Car a Board, ktoré reprezentujú autá a stav hracej dosky, respektíve. Trieda Node
reprezentuje uzol v strome vyhľadávania, kde každý uzol obsahuje informácie o aktuálnom stave dosky,
operácii, ktorá viedla k tomuto stavu, a odkaz na rodičovský uzol. Hlavnú funkciu vyhľadávania som
nazval cds_search. Táto funkcia sa snaží nájsť riešenie pomocou iteratívneho hĺbkového prehľadávania s
ohraničenou hĺbkou. Na udržiavanie fronty ešte nepreskúmaných uzlov som použil zoznam. Pre pohyb
áut na doske a generovanie nasledujúcich stavov som vytvoril funkcie possible_moves a apply_move. Čo
sa týka samotného výpisu v konzole, zabezpečil som, aby bol čo najinformatívnejší. To mi následne
uľahčilo debugovanie a optimalizáciu kódu. Program navyše meria čas potrebný na nájdenie riešenia.
KÓD DO PODROBNA
HLAVNÝ CYKLUS:
V mojom zadaní bol požadovaný cyklicky sa prehlbujuci vyhľadávací algoritmus cds_search. Jeho
cieľom je nájsť optimálnu cestu (postupnosť krokov) na dosiahnutie cieľového stavu pomocou hĺbkového
prehľadávania. Vytvorí sa počiatočný uzol s aktuálnym stavom dosky. Do zoznamu frontier sa pridá tento
počiatočný uzol. Algoritmus pokračuje v cykle, kým tento zoznam nie je prázdny. V každej iterácii sa
zoznam uzlov aktualizuje s novými uzlami na základe možných ťahov. Po vybraní uzlu sa skontroluje, či
je v cieľovom stave. Ak áno, cyklus končí. Inak sa vytvorí nový uzol na základe aplikovaného pohybu a
tento nový uzol sa pridá do zoznamu na ďalšie spracovanie. Ak cyklus skončí a riešenie nebolo nájdené,
vráti sa, že riešenie neexistuje.
HEURISTIKA:
heuristic(board): Táto metóda sa pokúša odhadnúť počet krokov potrebných na dosiahnutie cieľového
stavu. Hodnotí, koľko áut blokuje východ pre hlavné auto ('C') a odhaduje, koľko krokov bude
potrebných na odstránenie týchto prekážok.
Ako je Heuristika Zakomponovaná v Kóde?
Použil som metódu s názvom heuristic, ktorá berie dosku (board) ako vstup a vráti číslo, ktoré
reprezentuje počet áut blokujúcich cestu auta "C" k východu a počet pohybov potrebných na odstránenie
týchto áut. V metóde create_child_nodes(parent_node) som potom využil túto heuristickú funkciu na
vypočítanie heuristických hodnôt pre všetkých vygenerovaných potomkov (nasledujúce stavy).
Čo to vlastne znamená? Keď algoritmus generuje možné pohyby z aktuálneho stavu, každý nový
vygenerovaný stav (potomok) dostane svoju heuristickú hodnotu. Táto hodnota nám hovorí, aký "sľubný"
je tento stav v kontexte riešenia problému. Potom som tieto potomky zoradil podľa ich heuristických
hodnôt. Týmto spôsobom algoritmus skúma najskôr tieto "sľubnejšie" stavy, namiesto toho, aby ich
skúmal náhodne alebo v poradí, v akom boli vygenerované.

GENEROVANIE STAVOV:

possible_moves(board): Táto metóda generuje všetky možné pohyby pre daný stav dosky. Vracia zoznam
možných pohybov pre každé auto na doske.

apply_move(board, move): Táto metóda aplikuje daný pohyb na dosku a vráti nový stav dosky po
vykonaní pohybu.
GRAFICKÉ ZOBRAZENIE:
Pomocou tkinter je vytvorená grafická verzia hry. Hračská doska je reprezentovaná cez triedu
GameCanvas, ktorá zobrazuje jednotlivé autá ako farebné obdĺžniky na hracej ploche a animuje riešenie,
keď je nájdené.
SPUSTENIE PROGRAMU
Ak si chcem zadať vlastný grid zadám ho do initial_grid a napíšem ho do premennej grid. Ak chcem
random grid, tak do grid prepíšem random_grid

SPÔSOB TESTOVANIA
MINIMÁLNE RIEŠENIE:
Inicializačná doska(C-červené auto):

Finálna doska:
Dostali sme očakávaný výsledok, čiže algoritmus našiel riešenie ihneď, keďže počiatočný stav je už
cieľový stav. Počet vytvorených a spracovaných bol 1.

RIEŠENIE KRÁTKEJ CESTY:


Inicializačná doska:

Finálna doska:

Algoritmus našiel riešenie v krátkom čase s malým počtom spracovaných uzlov, keďže počiatočný stav je
len dva kroky od cieľového stavu.

RIEŠENIE VZDIALENÉHO POČIATOČNÉHO STAVU:


Tu som použil vraj najtažší hlavolam na tento problem a vyšiel na 33 krokov.
Inicializačná doska:

Finálna doska:
Priemerný čas riešenia sa vôbec nemení a normálny čas riešenia sa podľa počtu lineárne zväčšuje.

ZÁVER
Počas tvorby tohto kódu som prešiel nespočetnými výzvami a každá z nich mi poskytla cenné
lekcie. Bol som nútený zamyslieť sa nad logikou hry, modelovať rôzne stavy a predvídať možné
výsledky, aby som mohol optimalizovať svoje riešenia. Keď som narazil na prekážku, musel som
sa naučiť byť trpezlivý, analyzovať svoj prístup a byť pripravený na zmenu stratégie. Tento
projekt mi tiež ukázal, aká dôležitá je dôkladná plánovacia fáza. Skutočné pochopenie problému,
s ktorým pracujem, a predstavovanie si jeho rôznych aspektov predtým, než začnem kódovať, mi
mnohokrát ušetrilo hodiny práce.

You might also like