Professional Documents
Culture Documents
programació
Creació i resolució de laberints
2n Batxillerat B
IES Front Marítim
2019-2020
Resum
Català
Aquest treball de recerca consisteix en l’aprenentatge de programació en llenguatge
Python i en la seva implementació. He desenvolupat dos programes informàtics, l’objectiu
dels quals és la creació d’un laberint, que pot ser de diversos tipus, i la resolució del
laberint, de dues maneres diferents, perquè el robot pugui trobar-hi la sortida. La
resolució del laberint està dissenyada aplicant el Machine Learning (Aprenentatge
Automàtic) de tal manera que el programa aprèn per si mateix la solució del laberint a
partir de les dades que va obtenint dels seus propis errors. Per a assolir aquests objectius
he hagut d‘aprendre a programar i dissenyar algoritmes.
El treball consta d’una part d’introducció que conté la història de la informàtica i els
ordinadors i una explicació del que és la programació. El cos del treball està constituït
per l’explicació dels dos programes, el de creació i el de resolució. Com a informació
complementària, he afegit uns càlculs estadístics per a poder avaluar l’eficiència de les
dues maneres diferents que he programat de resoldre el laberint.
English
This research work consists of learning how to program in Python and in its
implementation. I have developed two computer programs whose purpose is the creation
of a maze, which can be of different types, and the resolution of that maze, in two different
ways, so that the robot can find the exit. The solving of the maze is designed to apply
Machine Learning in such a way that the program learns for itself the solution of the maze
based on the data it obtains form its own errors. To achieve these goals, I had to learn
how to code and design algorithms.
The work consists of an introductory part which contains the history of computing and
computer science and an explanation of what programming is. The body of the work is
constituted by the explanation of both programs, the one for creation and the one for
resolution. As a complementary information, I have added some statistical calculations to
evaluate the efficiency of the two different ways that I have programmed, of solving the
maze.
1
Castellano
Este trabajo de investigación consiste en el aprendizaje de la programación en el
lenguaje Python y en su implementación. He desarrollado dos programas informáticos,
cuyo objetivo es la creación de un laberinto, que puede ser de varios tipos, y la resolución
de este mismo, de dos maneras diferentes, para que el robot pueda encontrar la salida.
La resolución del laberinto esta diseñada aplicando el Machine Learning (Aprendizaje
Automático) de tal manera que el programa aprende por sí mismo la solución del laberinto
a partir de los datos que va obteniendo de sus propios errores. Para alcanzar estos
objetivos he tenido que aprender a programar y diseñar algoritmos.
2
Índex
1. Introducció .......................................................................................................... 4
5. Conclusions ...................................................................................................... 47
6. Bibliografia ........................................................................................................ 49
7. Annex ................................................................................................................ 51
3
1. Introducció
Sempre he trobat fascinant la informàtica i la tecnologia electrònica, tot i que encara no
he arribat a entendre al detall el funcionament dels ordinadors, al llarg de la meva vida
m’han despertat una forta curiositat. En part, la tecnologia moderna ha donat forma al
món i les societats en les quals vivim, els ordinadors i la informàtica han marcat la forma
de vida moderna. Tot i la seva elevada complexitat, tenim un ordinador o un dispositiu
electrònic potent al nostre abast la major part del nostre dia a dia.
En aquest treball de recerca, la meva intenció era aprendre a programar. Havia fet uns
cursos de programació amb Python fa uns anys però no vaig arribar a consolidar els
coneixements i volia aprofitar aquesta oportunitat per aprendre una habilitat molt útil i que
cada cop ho és més. La programació és una àrea molt àmplia i complexa, cal recórrer un
llarg camí per a dominar-la, el meu objectiu, però, era adquirir una habilitat i uns
coneixements bàsics que poguessin actuar com a fonaments pel meu futur en la
programació.
Vaig decidir fer el treball de recerca sobre la programació i la creació d’un programa
informàtic perquè volia fer un treball que em resultés útil de cara al futur i on aprengués
habilitats noves. També, la programació em semblava un tema molt interessant, útil i amb
un bon potencial per ser recercat i explicat.
El meu treball de recerca consisteix en, i té l’objectiu de, la creació d’un programa
informàtic per mitjà de la programació. El programa estarà fet en un llenguatge de
programació anomenat Python, un llenguatge d’ús general i utilitzat àmpliament avui en
dia. Per a aprendre a programar vaig fer una barreja de dos cursos, sense incloure el
que havia fet anteriorment. Així, com ja havia fet un curs anteriorment, no començava
des de zero i partia d’unes idees molt bàsiques de programació que van anar ressorgint
a mesura que estudiava amb més profunditat per aquest treball de recerca. El primer
curs que vaig fer fa uns anys era de Coursera, els altres dos eren de CodeAcademy i
Snakify.
L’objectiu del meu treball és crear un programa principal que inclou dos programes
diferents. El primer programa consisteix en la construcció d’un laberint, mentre que el
4
segon consisteix en la resolució d’aquest laberint utilitzant l’aplicació del Machine
Learning. He triat, com a programa per a fer, la creació i resolució de laberints perquè
m’ha semblat quelcom molt interessant, inusual i complex, però alhora sense una
dificultat excessiva. Cal remarcar que la resolució del laberint és completament
independent a la creació, comença des de zero i no rep cap informació del programa de
creació que el pugui ajudar. A més a més, he dissenyat i programat dues maneres
diferents tant de construir el laberint com de resoldre’l.
El treball està iniciat per una introducció que consta, primerament, de la història de la
informàtica i els ordinadors i, en segon lloc, d’una explicació de la programació, no per a
aprendre a programar, sinó per poder entendre-la. En cos del treball he explicat els
programes de creació i de resolució de laberints. Com he dissenyat dues maneres de fer
i de resoldre laberints, m’ha semblat interessant afegir, de forma complementària, una
part de càlcul estadístic per a poder comparar els diferents tipus de programes de
construcció i resolució dissenyats.
5
2. Història de la Informàtica i la Computació
2.1. Introducció
Tot i que els ordinadors electrònics són relativament moderns, la necessitat de processar
i calcular informació no ho és. Durant la història de la humanitat, s'han desenvolupat
màquines cada cop més complexes i potents, amb més capacitat de processament i
automatisme. La informàtica i l'ordinador modern no són, per tant, una invenció puntual
d'una sola persona sinó que són producte d'un esforç acumulat i del desenvolupament
col·lectiu fet pels humans al llarg de la història, sobretot els últims 400 anys.
L'àbac, la primera eina creada per ajudar als humans a processar informació, va ser
creada al voltant del 2500 aC pels antics Sumeris, i va ser utilitzada per la majoria de les
principals civilitzacions antigues. L'àbac era una eina molt simple que consistia en fileres
de 10 boles cada una. Cada fila representava una potència de 10 diferent, es comptaven
el nombre d’unitats, de desenes, de centenars, milers, ... Aquesta èina facilitava
considerablement la tasca de comptar sumar i restar i, precisament, es va inventar i va
ser uilitzat quan l'escala de la societat era, simplement, massa gran per a una sola
persona pogués emmagatzemar i manipular amb la seva ment.
6
fixes, estaria accionada amb una màquina de vapor i imprimia els resultats en una taula.
Una dècada més endavant atura el desenvolupament de la Màquina de Diferència i
comença a treballar en la Màquina Analítica o Analitical Engine en anglès. Aquesta
màquina era una versió més complexa i potent que l'anterior, podia emmagatzemar
dades i llegir instruccions de cartes perforades, essencialment fent-lo un ordinador
mecànic programable. Per motius econòmics cap dels seus dissenys mai van
poder prendre forma física.
Ada Lovelace, “La primera programadora”, treballava junt amb Charles Babagge i l’any
1842 va idear un algoritme dissenyat per a la Màquina Analítica de Babagge que
calcularia nombres de Bernoulli, també va establir alguns dels fonaments de la
programació com l’anàlisi de dades, looping (repeticions) i memory adressing
(Organització de la memòria o dades emmagatzemades, perquè siguin d’accés fàcil per
la Unitat Central de Processament (CPU)).
1
Els resultats del cens de població és una de les principals informacions utilitzades per a entendre les situacions socials,
7
passat. Per a fer el cens de població, se’ls hi donaven unes cartes als enquestats a les
quals feien uns forats a les respostes que volien marcar. Un cop es tenia la targeta
perforada, s’introduïa a la màquina i una sèrie de pins intentaven fer contacte amb els
seus receptors corresponents per a deixar passar corrent; segons on eren els forats de
la targetes només uns pins determinats arribaven a fer contacte, això accionava un motor
que manipulava el comptador. La màquina de Hollerith va tenir molt èxit en facilitar
enormement la tasca del Census Bureau, la qual anteriorment es feia mà.
Durant les següents dècades, les màquines de càlcul van ser aplicades en molts governs
i empreses per la seva eficiència i reducció de la dificultat d’algunes tasques.
L’any 1936 Konrad Zuse, un enginyer alemany, inventa el Z3, el primer ordinador
programable. Aquest ordinador llegia instruccions d’una cinta perforada i era el primer
ordinador que utilitzava lògica booleana i el sistema binari a través de l’ús del relé.
Un material conductor genera un camp magnètic quan corrent elèctric passa per
ell. Aquest principi s’utilitza en el funcionament del relé: quan el corrent de control
és activat, passa per una bobina i genera un camp magnètic. Aquest camp
magnètic atrau i mou un braç metàl·lic que, en canviar de posició, provoca un
contacte amb el terminal que obre el circuit principal.
8
Sistema Binari
Els relés, tubs de buit i transistors són variacions d’un mateix principi que és, bàsicament,
un interruptor que controla el pas d’electricitat a través d’un segon canal d’electricitat.
Aquests dos estats de l’electricitat impliquen que totes les dades que manipula un
ordinador estan en forma binària. Un transistor equival a = 1 BIT (Binary digiT), i 1 Byte
= 8 bits. Com un byte té vuit dígits, pot “comptar” des de 0 fins a 255. Generalment, una
dada individual (número o lletra) s’emmagatzema en un byte (si es necessita més es
poden sumar bytes o adjuntar-los per a crear fins a 16 xifres binàries).
Els números es poden passar fàcilment a base 2 (binari), per exemple: el número 1
equival a 1, el 2 a 10, 3 a 11, el 8 a 1000, el 53 a 110101 i el 255 a 11111111. Si escrivim
aquests nombres en bytes sencers, serien 00000001, 00000010, 00000011, 0001000,...
Les lletres i els caràcters es passen a binari mitjançant el codi ASCII (American Standard
Code for Information Interchange), que converteix les dades d’un ordinador, que només
pot estar en nombres binaris, a lletres i viceversa. Cada caràcter (puntuació, lletres,
números, etc.) li correspon una combinació d’un byte.
Per exemple, la lletra “A”, en majúscula, té un número ASCII de 65, el 65 equival a unes
8 xifres binàries determinades. (“A”: num ASCII = 65 -> 01000001). Si en un processador
de text escrius “A”, vol dir que en algun lloc del teu ordinador hi ha una filera de transistors
amb el patró 0 1 0 0 0 0 0 1.
9
Àlgebra Booleana
L’àlgebra booleana va ser creada per George Boole al S XIX, i es basa en àlgebra on les
variables poden prendre valors True (veritat o 1) I false (mentida o 0) i les operacions no
són matemàtiques sinó lògiques.
AND, dona True com a resposta si, i només si, les seves dues entrades són True.
XOR, dona True com a resposta si, i només si, una de les seves entrades és True.
Totes aquestes operacions es poder fer físicament amb transistors i quan aquestes
operacions lògiques es posen en un sistema ordenat i es desenvolupen es pot arribar a
crear un sistema lògic capaç de fer operacions matemàtiques i, amb més
desenvolupament, es poden crear les bases per als ordinadors potents com els d’avui
dia.
Seguint amb el desenvolupament dels ordinadors, uns anys després del Z3, Zuse
utilitzaria cintes perforades per a codificar informació en binari, essencialment
convertint-los en els primers dispositius d’emmagatzemament de dades. L’any 1942,
Zuse treu al mercat el primer ordinador comercial (Z4) i per això se’l coneix com “l’inventor
de l’ordinador modern”.
Al 1937 Howard Aken junt amb els seus companys de Harvard i la col·laboració d’IBM
van començar a construir el Harvard Mark I. Era una calculadora programable inspirada
en la màquina analítica de Babagge. Era extremadament gran i complex, capaç
d’emmagatzemar 72 números de fins a 23 dígits (decimals) de llarg, podia fer tres sumes
o restes per segon, una multiplicació en sis segons, una divisió en quinze segons i
logaritmes o funcions trigonomètriques en un minut.
10
2.4. Computació Digital Moderna
2.4.1. Primera Generació - Tubs de Buit
La investigació i recerca dels anys trenta i quaranta, va proporcionar al món de la
informàtica i la computació una eina que va resultar molt útil, els tubs de buit com a
substitut dels antics relés. Els tubs de buit eren completament electrònics (digitals) i eren
més eficients, ràpids i fiables.
Des de l’any 1937 fins al 1942 John Atanasoff i Cliford Berry van construir el primer
ordinador digital, anomenat l’ABC. Al contrari que els ordinadors construïts prèviament,
com els de Zuse, aquest no utilitzava relés, sinó els tubs de buit, per tant era
completament digital. Aquest ordinador estava dissenyat per a resoldre equacions lineals
i implementava matemàtica binària i lògica booleana per a resoldre fins a 29 equacions
simultàniament.
11
L’Enigma, una màquina, també electromecànica, que utilitzaven els alemanys durant la
segona guerra mundial per encriptar i desencriptar els seus missatges secrets.
L’aplicació de The Bombe va donar als aliats un molt valuós avantatge durant la guerra.
El Colossus era un ordinador digital que també s’utilitzava per a desxifrar codis críptics
alemanys, aquest, però, desxifrava quelcom molt més difícil, el Xifrat de Lorenz, que era
producte d’unes altres màquines electromecàniques, les SZ40, SZ42a i SZ42b.
Implementava tubs de buit, no com The Bombe que utilitzava relés. Al contrari de, l’ABC
el Colossus era completament programable, titulant-lo el primer ordinador digital
completament programable. La programació, en aquest cas, es feia connectant cents de
cables en un panell d’una forma determinada i, així, preparant a l’ordinador per a fer les
operacions adequadament, per tant havia d’estar configurat per a resoldre un càlcul
específic i s’havia de reconfigurar si es volia fer un càlcul diferent.
Durant el desenvolupament del ENIAC, John Von Neumann va idear el principi d’un
programa integrat emmagatzemat a la memòria electrònica del mateix ordinador que
podia ser manipulat i modificat de la mateixa forma que les dades i ser descodificat en
binari. Això contrastava amb els altres ordinadors del moment, on les instruccions i la
programació estaven emmagatzemades en panells amb conneccions o en cintes
perforades. Aquest principi ideat va portar a l’Arquitectura Von Neumann, que formula un
model que ha de segur un ordinador, que consisteix en una CPU (element central de
processament), una memòria interna i uns dispositius d’ entrada i sortida; aquesta
arquitectura és una implementació física dels estudis de Turing. Von Neumann va assistir
en el desenvolupament de l’EDVAC (Electronic Discrete Variable Automatic Computer),
el successor l’ENIAC, completat l’any del 1950. Aquest ordinador va ser el primer amb
programa emmagatzemat i podia executar mil instruccions per segon.
12
2.4.2. Segona Generació - Transistors
Tot i que els tubs de buit eren una gran millora respecte als relés, seguien sent cars de
produir, utilitzaven molta energia i eren poc fiables, ja que es cremaven sovint. Els tubs
de buit també ocupaven i pesaven molt, aquest és la raó per la qual els ordinadors
d’aquell temps pesaven tones i ocupaven habitacions senceres.
Amb aquesta nova era es comencen a veure grans desenvolupaments, tant del hardware
com del software. Recordem que el hardware és tot el maquinari físic de l’ordinador i el
software és tot el programari. Pel costat del hardware veiem la introducció del Random
Access Magnetic Core Store o, com el coneixem avui dia, el RAM l’any 1951. També
veiem el primer disc dur, produït per IBM l’any 1957; pesava una tona i podia
emmagatzemar fins a 5Mb. Pel costat del software es va progressar molt, gràcies a que
es va estandarditzar el hardware i l’arquitectura dels ordinadors. Fins aquell moment el
programa d’un ordinador estava escrit en machine code que podia ser executat
directament per l’ordinador. Però des de llavors es van crear llenguatges de programació
d’alt nivell i de baix nivell. Els llenguatges de programació d’alt nivell són els que
13
s’adaptaven millor als humans i com a conseqüència, són els més utilitzats avui en dia.
També existeixen els llenguatges de baix nivell, que s’aproximen més al machine code.
Tot i que els llenguatges de baix nivell eren menys complexes que el machine code, es
seguia necessitant un ampli coneixement de l’arquitectura del ordinador per a
desenvolupar-lo, aquest no era el cas amb els llenguatges d’alt nivell.
14
El progrés de la tecnologia al llarg dels últims segles i, sobretot, des de la invenció del
transistor i el circuit integrat, han permès a la tecnologia i la informàtica arribar al punt on
ara estan. Com a curiositat, una calculadora no científica actual té una potència de
processament similar a l’ordinador de 30 kg utilitzat a les missions Apollo2 de la NASA,
l’Apollo Guidance Computer.
2
L’Apollo 11 és la missió on, per pimera vegada a la hisòria, un humà va estar a la superfície de la lluna.
15
3. Introducció a la programació
En l'actualitat tenim una infinitat d'aplicacions informàtiques a la nostra disposició, moltes
de les quals, ni ens adonem que les estem fent servir. Acostumem a donar per fet el
funcionament de la tecnologia, però què és realment el que fa que la tecnologia moderna
funcioni? Què hi ha darrere de les pantalles i la resta de hardware? La resposta és el
software, o, en altres paraules, els programes.
Avui en dia trobem programes a tot arreu, des dels processadors de text com el Word,
als programes d'un cotxe intel·ligent de conducció pròpia, passant per les aplicacions
que tenim al mòbil, els sistemes de reconeixement de cares que utilitzen els serveis
d'intel·ligència, els videojocs moderns o, fins i tot, per controlar el Mars Pathfinder de la
NASA a més de 200 milions de km de nosaltres. I doncs, què són els programes, aquest
quelcom que sembla omnipresent en el nostre món?
16
llenguatge estrictament numèric que està dissenyat per a ser executat el més ràpid
possible. Tot i que és possible escriure un programa directament en machine code, és
una tasca extremadament complexa que només es fa servir en algunes circumstàncies
per a correcció de certs errors en un programa o si s'ha d'invertir el procés de compilació
(passar de machine code a source code).
Per entendre què és la programació, es podria comparar a donar ordres a una persona,
per exemple: -aixeca el braç dret -analitza aquesta frase
-digues: “Hola, bon dia!” -fes un dibuix d’una casa
-resol aquesta equació
La diferència és que un ordinador no té intuïció per sí sol i no pot fer res que no li hagis
ordenat, un ordinador es podria equiparar a una persona molt capaç i amb molt potencial
però sense cap coneixement, ni intuïció, ni intel·ligència. Posem un exemple: si li volem
dir a una persona que es renti les dents és tan simple com dir-li “renta’t les dents”, però
a un robot li hauríem d’ordenar d’una forma molt diferent. En primer lloc hauríem de dividir
la tasca de rentar-se les dents en vàries subtasques més simples, per exemple, “troba el
raspall de dents”, “troba el dentífric”, “posa la pasta de dents a sobre el raspall”, etc. Però
no és tan simple, només estem començant, doncs cada una d’aquestes tasques més
simples s’han de tornar a dividir en subtasques i així progressivament fins que la tasca
sigui executable per l’ordinador i que la compilació d’aquestes tasques petites ens doni
el resultat que vulguem. Per exemple, si volem posar la pasta de dents sobre el raspall,
hauríem de dividir la tasca i dir “agafa i mou el raspall de dents i el dentífric davant teu”,
“apreta el dentífric amb 0,3N de força durant 1 segon”, etc. Cada cop simplifiquem més
la tasca perquè sigui més fàcil d’executar. Aquestes últimes ordes estan lluny, però, de
que les pugui executar un robot, hauríem de dividir-les molt més amb un programa
d’identificació d’imatges que pogués trobar el raspall i el dentífric, amb un accionament
dels motors per a ser capaços de realitzar cada moviment, etc. Un enriquiment que es
podria afegir a aquest programa de rentar-se les dents és posar una condició a l’inici: “Si
són les 10 de la nit i has sopat segueix el programa:”. Una altra ampliació que podríem
aplicar-li seria introduir un bucle a l’ordre de raspallar-se les dents:
“Repeteix durant 2 minuts:”
“Mou el raspall horitzontalment endavant i enrere.”
17
Totes aquestes ordres són exemples que semblen evidents o trivials per a nosaltres, els
humans, però una màquina no les podria executar per falta del coneixement, i intuïció si
no se li indiquen perfectament desglossades
La complexitat d’un programa pot variar molt, des d’aquest petit programa de sumes que
he escrit fins a la creació d’una consciència artificial, fita en la qual s’està treballant
actualment.
18
Machine learning, o aprenentatge automàtic en català, és una de les àrees de la
intel·ligència artificial. Es basa en el fet que és més eficient “ensenyar” als ordinadors a
aprendre que “ensenyar-los” a fer qualsevol tasca possible. Machine learning pretén
donar als ordinadors l’habilitat d’aprendre sense ser programats explícitament, recolzant-
se, en canvi, en patrons; això s’aconsegueix mitjançant la modificació i millora contínua
del seu programa a mesura que se li introdueixen dades. Per tant, es necessiten unes
dades determinades que serveixen d’entrenament, llavors el programa anirà aprenent i
ajustant-se segons les noves iteracions. Un exemple d’això que s’ha utilitzat en la vida
real és, com un robot apren a caminar mitjançant la prova i error. El robot té l’objectiu
d’arribar a una certa distància, farà un nombre elevat de proves on a cada prova farà una
petita modificació i calcularà un ajustament segons les conseqüències de la modificació.
Amb moltes iteracions es va perfeccionant el programa fins a poder arribar a l’objectiu.
Fig. 3: Dibuix que representa les diferències de la programació tradicional i una que implementa machine
3 learning. A l’esquema de la dreta, que implementa machine learning es veu com el machine learning modifica el
programa segons l’imput que se li dóna i els outputs anteriors.
Més endavant veurem com el programa de resolució del laberint implementa un cert
machine learning molt bàsic.
Fig. 3, Font: Seminari Lisboa de Machine Learning i Inteligència Artificial (2018), Cisco Systems
19
4. Programació amb Python
4.1. Creació del Laberint
Creació de la quadrícula
L’objectiu és programar dos programes diferents, un que crea un laberint i l’altre que el
resol independentment. El llenguatge de programació que he utilitzat és el Python i ho
he fet a través d’un programa informàtic anomenat PyCharm, que m’ha servit de
plataforma per a treballar-hi. PyCharm es podria descriure com un processador de text
dissenyat per programació que pot executar els programes ell mateix.
En primer lloc caldrà crear la taula / quadricula on dibuixarem el nostre laberint. Això ho
farem a través d’una llista de llistes. Una llista d’elements on cada element serà una altra
llista, creant, per tant, una llista de dues dimensions o una quadrícula.
De moment, tots els valors de les llistes secundàries seran 1. Tots els valors 1
representaran un camí i tots els valors 0 representaran una paret.
20
Un cop tenim la quadrícula creada li introduirem les parets que envoltaran el laberint.
Recordem que les parets tenen un valor de 0.
Amb el procediment anterior hem acabat la quadrícula, ara només falta establir una
sortida i entrada aleatòriament a les parets superior i inferior. Un cop s’hagi fet això,
estem preparats per a pintar-hi el laberint.
21
Creació del Laberint
Hi ha una gran varietat de procediments
possibles per a crear un laberint. Em vaig
decidir per un sistema molt interessant i
relativament simple.
Explicació general
El programa de la creació del laberint es basa en una estructura recursiva on una funció
determinada es crida a ella mateixa amb uns paràmetres nous.
Per a crear el laberint dibuixarem a la taula dues línies perpendiculars que faran de
parets, i obrirem un forat (casella de camí) a tres dels fragments que s’han creat. Això
serà una iteració de l’algoritme, es a dir, una aplicació de la funció.
Fig. 12: Dues línies perpendiculars Fig. 13: Tres obertures a les línies
perpendiculars.
22
Al dibuixar les línies perpendiculars, l’àrea inicial s'haurà dividit en quatre i s’hauran creat
quatre quadrants o àrees.
1 2
3 4
Fig. 14: Els quatre quadrants creats.
1 2
1 2
3 4
3 4
Fig. 15: Els quatre quadrants creats on Fig. 16: Els quatre quadrants més petits, creats
s’aplicarà la funció al aplicar la funció a un dels quadrants de la
imatge anterior. La funció també s’aplicarà a
aquests nous quadrants i als quadrants que es
crearan llavors i els que es crearan llavors, etc.
23
Fig. 17: Laberint complert
Per a simplificar la creació i minimitzar problemes farem que les línies de les parets
només es dibuixin en caselles imparelles (les línies veritcals en unes casellles x
imparelles, i les línies horitzontals en unes caselles y imparelles).
Funcions recursives
Una Funció recursiva és una funció que es crida a si mateixa. La idea general és resoldre
un problema dividint-lo en problemes més petits però que es solucionen de la mateixa
manera que el problema original. En el moment que ja no es pugui dividir en problemes
més petits s’arribarà a una solució simple, que serà la base de les solucions dels
problemes anteriors.
A() és una funció recursiva, ja que es crida directament a ella mateixa, té aquesta forma
genèrica:
24
else call funció (arguments més simples) // en el cas que no es compleixi la condició:
autocrida amb una versió més simple
Donada una funció recursiva, fa falta el que s’estableixi una condició de finalització, és a
dir, una condició que faci que la funció aturi el procés de cridar-se ella mateixa. Si no es
dóna el cas simple o condició de finalització, es torna a cridar la funció amb paràmetres
més simplificats.
Exemple: n!
Computar n! Recursivament.
Per computar n! S’ha de computar (n - 1)!, és a dir, un problema més simple que es resol
de la mateixa manera. Per això es pot resoldre amb una funció recursiva.
Ara escrivim amb Python la funció que calcula el factorial d’un sencer donat. Apliquem la
funció general recursiva anterior:
Def Factorial(n):
else: (Si n ≠ 0, s’obtindrà [ n * (la funció factorial amb n-1) ] on s’ha cridat la funció.)
25
Explicació en detall
El laberint es crea repetint una funció recursivament, el que farà aquesta funció serà:
- Dibuixar les línies perpendiculars
- Alliberar tres caselles determinades de les línies perpendiculars
- Cridar la mateixa funció amb uns nous paràmetres
Aquests paràmetres són les coordenades (x1,y1) i (x2,y2) de la diagonal que defineix el
quadrant. En el moment inicial els paràmetres seran els de la quadrícula sencera.
Això permet que, a l’hora de cridar-se a ella mateixa, introdueixi als paràmetres els valors
x i y de les noves parets que s’han creat i la funció nova només actuarà en aquelles
dimensions. Per tant, cada funció es crida a ella mateixa ( ) quatre vegades diferents
per als quatre quadrants:
26
Fig. 19: Algoritme que tria una posició per les línes horitzontal i
vertical i canvia el valor de les caselles de les dues línies a 0, és a
dir, paret. També pinta els quadrats a la interfície gràfica.
La posició x de la línia vertical serà un nombre imparell entre les parets dreta i esquerra,
i la posició y de la línia horitzontal serà un nombre imparell entre les parets superior i
inferior. Els valors es poden triar de forma aleatòria o poden ser el valor mitjà entre les
dues parets.
27
Si fem una línia amb un valor de posició aleatori i l’altra línia amb un valor de posició
mitjà, acabem amb un laberint de la següent forma:
Fig. 22.1: Laberint fet amb valors mitjans Fig. 22.2: Laberint fet amb valors
a la y i aleatoris a la x. Solució única. mitjans a la x i aleatoris a la y. Solució
única.
Un cop tenim els quatre trams, triarem un nombre aleatori del 0 al 3. Aquest nombre serà
el tram al qual no li farem un forat. Si volguéssim fer un laberint amb múltiples solucions,
obriríem els quatre trams i saltaríem aquest pas.
28
Fig. 24.1: Laberint amb única solució. Fig. 24.2: Laberint amb múltiples solucions.
Per a cada tram, menys el que hem decidit aleatòriament que no, triarem un nombre
aleatori entre el punt de contacte amb la paret i el punt de tall de les dues línies principals,
aquest nombre serà la posició dins del tram del punt al qual canviarem el valor i on
crearem camí.
29
Fig. 26: Resultat désprés de canviar el valor a tres caselles per a crear camí.
1 s’executi a ella mateixa quatre vegades diferents per als quatre quadrants. ( )
2. Sàpiga quan parar i que no es cridi més a ella mateixa. Això s’anomena condició de
sortida. ( )
Un cop hem establert que el nou quadrant és prou gran per a aplicar-hi la funció, faltarà
cridar la funció ( ) introduint-hi els nous paràmetres. (recordem que els paràmetres
eren les quatre parets que delimiten els quadrants on s’aplica la funció). Aquesta vegada
els paràmetres seran dues de les parets del quadrant vell i dos dels trams creats per les
línies perpendiculars.
c Fig. 28: Representació dels límits del nou quadrant, és a dir, els seus
paràmetres.
d
:
Ara que ja hem cridat de nou les funcions que havíem de cridar ja haurem acabat de
dissenyar la funció. Quan executem el programa tindrem el laberint fet.
Segons la forma en la qual està escrita el programa, la primera funció a ser cridada és la
del quadrant superior esquerra, per tant, es treballarà sempre aquest quadrant primer
abans que el superior dret i els dos inferiors. Això vol dir que abans de passar a treballar
el següent quadrant, primer han d’estar acabat tots els quadrants que inclou l’actual,
aquest comportament es compleix per a cada iteració de la funció, per tant, a mesura
que es van creant nous quadrants es resoldran primer sempre els superiors esquerra.
Això també vol dir que la primera iteració de la funció també serà l’última en acabar-se
d’executar, ja que no acabarà fins que es completi l’últim quadrant inferior-dreta (l’últim
en ser cridat) de tots els anteriors quadrants inferiors-dreta.
31
Fig. 29. Representació de la prioritat i execució dels quadrants.
32
4.2. Resolució del Laberint
Versió fixa
Ara que ja hem creat el laberint és hora de
fer el programa que el resoldrà. Recordem
els programes de creació i solució són dos
programes diferents i independents. El
programa que resol no obté cap mena
d’informació del que crea el laberint.
L’algoritme que resoldrà el laberint no tindrà una visió completa de tot el laberint sinó
només de les quatre caselles al voltant seu, per tant, haurà de resoldre el laberint des
d’un punt de vista de l’interior del laberint i no pas d’una vista vertical com la que temin
nosaltres quan en resolem un en un paper. No podrà planejar la ruta a priori, sinó que
haurà d’anar provant camins i reculant quan entri en un camí sense sortida fins que robi
el final del laberint.
= Robot
L’estructura del programa consisteix en un algoritme repetitiu, un bucle, que farà una
iteració per a cada casella a la qual es mou el robot. Cada iteració consistirà d’una sèrie
de condicions i respostes per a cada condició. Hem de tenir en compte totes i cada una
de les possibilitats amb les quals es podrà trobar el robot a cada casella per a poder
formular una resposta adequada.
33
Per a establir per on ha passat el robot i per on ha reculat seguirem un principi similar a
les molles de pa de Hansel i Grettel. Recordem que quan una casella té valor 0 és una
paret i quan té un valor 1, és un camí. El que farà el robot serà incrementar el valor en
+1 cada casella que trepitgi (ja estigui descobrint camí nou o reculant), per tant, un cop
el robot descobreixi la sortida, haurà deixat tota una sèrie de caselles, que inicialment
tenien un valor d’1, amb valors de 2 i 3. Els valors 2 seràn la solució i els valors 3 serà
per on haurà reculat el robot. Totes les caselles amb valor 1 serà camí verge per on no
haurà passat el robot.
Ja que l’única informació que rebrà el robot serà quines són les caselles del seu voltant
i els seus valors, necessitem saber la posició i el valor de les quatre caselles que el
rodegen. També cal establir una prioritat en la qual avançar caselles. Per exemple, si el
robot arriba a una paret frontal i es troba amb una bifurcació que li permet anar a la dreta
o a l’esquerra, cap a on va?
34
Una possibilitat per a la prioritat és girar, sempre que pot, a l’esquerra (o a la dreta, és el
mateix). L’opció que he triat jo, és que el robot intenta anar endavant sempre que pot,
quan no pot gira a l’esquerra i si tampoc pot, gira a la dreta. Una altra opció seria fer que
avanci sempre que pugui i que decideixi la prioritat d’esquerra o dreta aleatòriament quan
té l’opció d’anar a un costat o l’altre simultàniament.
Saber quina és la casella “de la dreta” és més complex del que sembla. Primerament ens
referim a la casella dreta del robot, des del seu punt de vista, no pas a la de la dreta
absoluta segons la veiem nosaltres. Només serien les mateixes si el robot avança en
direcció vertical i cap amunt.
Com volem que les caselles siguin relatives al robot i no pas al nostre punt de vista
haurem de fer un algoritme que pugui calcular-les. Per a saber les caselles del voltant
del robot necessitarem una sèrie de paràmetres: primerament, la posició del robot (x1,
y1) i, en segon lloc, la direcció i sentit del moviment del robot (∆x, ∆y) (∆ vol dir increment
de ...), la qual es renovarà cada vegada que el robot avanci una casella*. El robot només
es pot moure en vertical i horitzontal, no en diagonal, per tant, sempre hi haurà un dels
increments de la direcció que serà 0, l’altre increment podrà prendre un valor d’1 o -1.
*Sempre que el robot canviï de direcció caldrà ajustar els increments, ja que hauran
variat.
Fig. 35: Increments a aplicar a (x1,y1) per a obetnir les quatre caselles del voltant.
Nota: l’eix Y està invertit per la forma en la qual està construïda la quadrícula, és
a dir, el (0,0) el tenim dalt a l’esquerra, per tant, si ens desplacem verticalment i
cap dalt estarem restant -1 a la coordenada Y del robot.
35
Per a calcular la posició de la casella del davant del robot, és tan fàcil com [ (x1+∆x),
(y1+∆y) ], ja que els increments seran els mateixos que portava inicialment. Si el que
volem calcular és la casella del darrere del robot, també resulta fàcil: [ (x1-∆x), (y1-∆y) ].
Es complica més, però, quan volem calcular les caselles laterals, això dependrà de si el
valor de ∆x és igual a 0 o no, en altres paraules, si el robot s’està movent verticalment
(∆x = 0) o horitzontalment (∆x ≠ 0).
Per acabar, per calcular el punt dret, serà [ (x1+∆x3), (y1+∆y3) ], tal que: ∆x3 = -∆y i ∆y3
= 0 si s’està movent verticalment, i [ (x1+∆x1), (y1+∆y1) ], tal que: ∆x3 = 0 i
∆y3 = ∆x si s’està movent horitzontalment.
Amb aquests càlculs podem saber la posició de les caselles que rodegen el robot i, per
tant, podem saber el seu valor. Des d’aquest punt, analitzarem les caselles del davant i
els costats i respondrem adequadament segons els seus valors. En el cas que el robot
es mogui cap enrere o lateralment caldrà canviar els valors dels increments (∆x, ∆y), ja
que haurà canviat de direcció. (∆x, ∆y) prendran el valor que li hem sumat a (x1,y1) per
a arribar a la casella actual.
36
Un cop tenim els valors de les caselles del voltant, hem arribat a l’hora de prendre
decisions segons aquests valors. Aquestes decisions es poden dividir en dues etapes:
les decisions que es prenen si el robot està explorant camí verge i les decisions que es
prenen en el cas que no hi hagi camí verge possible, on es recularà de casella en casella.
Cada vegada que es prengui una decisió i el robot es mogui una casella es reiniciarà de
nou tot el bucle i es repetirà per a la casella nova.
37
Si hem fet les tres comprovacions i cap d’elles és un
valor 1, això vol dir que estem en un camí sense
sortida, per tant, girarem cua i començarem a recular.
Quan estiguem reculant, el robot es mourà per
caselles de valor 2 i deixarà enrere caselles de valor
3 (els hi haurà incrementat un punt per a indicar que
ja hi ha passat, algoritme de molles de pa). Un cop
hem girat cua, aplicarem, a cada casella a la qual
reculem, tot el bucle sencer, per tant, mirarà, per
cada casella, si en té una als costats amb valor 1.
Quan trobi una casella amb valor 1, és a dir, camí
verge, haurà arribat a l’última bifurcació que hauria
deixat el robot i repetirà el procés per aquell nou
camí. Aquest bucle de resolució no s’acabarà fins
que el robot trobi la sortida del laberint.
38
Versió Dinàmica
Aquest mètode de resolució fix funciona i és eficaç, el robot sempre acaba trobant la
sortida. Tot i això, volia provar de fer un algoritme dinàmic i semi intel·ligent que fos més
eficient. Aquí podem veure als dos algoritmes diferents en acció
Fig. 38.1: resolució amb el nou l’algoritme dinàmic Fig. 38. 2: resolució amb l’algoritme fix
Aquest nou algoritme de resolució te en compte una informació que l’altre algoritme no
tenia, les coordenades de la sortida. L’algoritme consisteix, bàsicament, en decidir l’ordre
de prioritat a les bifurcacions de forma intel·ligent i no a l’atzar. Ho fa calculant la distància
que hi ha des de la sortida a cada una de les caselles 1 a les que es pot moure (caselles
del voltant que tenen valor 1), i tria la casella que tingui la distància més curta a la sortida
del laberint. Calcula la distància amb el Teorema de Pitàgores per a cada casella.
39
Aquesta imatge mostra el càlcul de la distància a la sortida per a cada casella, = robot.
En aquest cas, les caselles 1 i 2 serien caselles de camí i per això calcula la distància a
la sortida (h1 i h2). Si la casella 3 també fos camí, també en calcularia la distància, però
no ho he representat per a no dificultar la comprensió del dibuix. Segons si h 1 < h2 o
h1 > h2 avançarà a la casella 1 o a la 2.
Fig. 39:
Representació del càlcul de les distàncies.
40
4.3. Anàlisi Estadístic
En primer lloc, vull deixar clar que aquesta petita anàlisi no és pas la part de “recerca”
del meu Treball de Recerca, simplement és una obtenció de dades i de les seves
conclusions que permeten comparar els dos algoritmes de resolució.
Per a poder comparar els dos algoritmes, el de resolució fix i el de resolució dinàmica,
he fet una recol·lecció de dades i les he analitzat estadísticament per treure’n unes
conclusions. He aplicat certes modificacions al programa que consisteixen en uns
comptadors que miren el nombre passos totals (un pas = moure’s una casella) i el nombre
de passos correctes, és a dir, el nombre de caselles amb valor 2. Recordem que en el
laberint de múltiples solucions hi ha múltiples camins possibles per arribar al final, per
tant, els “passos correctes” són simplement el camí que ha seguit per a arribar al final,
valor que podrà variar, no essent així en el cas del laberint de solució única.
L’objectiu de l’estudi era observar si, en general, l’algoritme dinàmic feia menys passos
per a arribar a la sortida que l’algoritme fix.
La prova consistia en executar els dos programes de resolució diferents per a un mateix
laberint, i obtenir dues mesures per a cada solució:
1. El nombre de total de passos fets.
2. El nombre de passos correctes fets, és a dir, el nombre de caselles amb valor 2.
2. Tot aplicant el càlcul de percentatge d'eficiència del punt anterior en mil laberints
diferents, obtenir, mitjançant dos comptadors, el nombre de vegades que cada
algoritme ha sigut més eficient que l'altre.
3. La relació de passos totals de l’algoritme dinàmic respecte els de l’algoritme fix.
𝑝𝑎𝑠𝑠𝑜𝑠 𝑡𝑜𝑡𝑎𝑙𝑠 𝑑𝑒 𝑙′𝑎𝑙𝑔𝑜𝑟𝑖𝑡𝑚𝑒 𝑑𝑖𝑛à𝑚𝑖𝑐
En forma de percentatge: × 100,
𝑝𝑎𝑠𝑠𝑜𝑠 𝑡𝑜𝑡𝑎𝑙𝑠 𝑑𝑒 𝑙′𝑎𝑙𝑔𝑜𝑟𝑖𝑡𝑚𝑒 𝑓𝑖𝑥
41
He fet la prova en un laberint aleatori amb una única solució i en un laberint aleatori amb
múltimples solucions, amb quadrícula de 25x25. He repetit la prova mil vegades per a
cada laberint i he programat el càlcul per obtenir les mitjanes de totes les mesures. A
mode d’exemple, mostro a continuació cinc proves amb els valors obtinguts i les mitjanes
calculades, tant pel laberint de múltiples solucions com pel laberint d’única solució. En
finalitzar els exemples tenim els resultats per a l’estudi, les mil repeticions.
Prova de 5 repeticions
Per a cada tipus de laberint (solució única i solucions múltiples) he aplicat cinc vegades
cada un dels dos algoritmes de resolució (fixe i dinàmic). Aquí veiem els resultats:
42
Algoritme Algoritme 𝑃𝑎𝑠𝑠𝑜𝑠 𝑡𝑜𝑡𝑎𝑙𝑠 𝑑𝑖𝑛à𝑚𝑖𝑐𝑠
fix dinàmic 𝑃𝑎𝑠𝑠𝑜𝑠 𝑡𝑜𝑡𝑎𝑙𝑠 𝑓𝑖𝑥𝑒𝑠
Fig. 40: Resolució d’un mateix laberint amb l’algoritme fix (dreta) i el dinàmic
(esquerra)
Observacions
Amb les dades que hem extret de les cinc proves anteriors podem veure que, en general,
l’algoritme dinàmic resol el laberint en un nombre total de passos molt menor, amb una
eficiència mitjana de 59,1% respecte al 31,28% en el cas de l’algoritme fixe. Podem
veure, també que en dos ocasions, a la prova 2 i la prova 5, l’algoritme dinàmic ha
43
aconseguit resoldre el laberint sense haver de recular (eficiència del 100%). Es pot
apreciar com la diferència de passos totals varia significativament entre proves, per
exemple, a la prova 1 es veu una relació de les dues mesures de quasi 90%, en canvi, a
la prova 5 es veu una relació al voltant del 9%
Si repetim el proccés anterior per a un laberint amb múltipes solucions, obtenim uns
resultats semblants:
Nota: ara els passos correctes seran el nombre de caselles que té la solució trobada.
44
Algoritme Algoritme 𝑃𝑎𝑠𝑠𝑜𝑠 𝑡𝑜𝑡𝑎𝑙𝑠 𝑑𝑖𝑛à𝑚𝑖𝑐𝑠
fix dinàmic 𝑃𝑎𝑠𝑠𝑜𝑠 𝑡𝑜𝑡𝑎𝑙𝑠 𝑓𝑖𝑥𝑒𝑠
Observacions
Amb les dades que hem extret de les 5 proves anteriors podem veure que, en general,
l’algoritme dinàmic resol el laberint en un nombre total de passos molt menor, quasi en
una tercera part dels passos, amb una eficiència mitjana del 65,18% respecte al
28,23% en el cas de l’algoritme fix. Podem veure, també que en una ocasió, a la prova
5, l’algoritme dinàmic ha aconseguit resoldre el laberint sense haver de recular
(eficiència del 100%). En una altre ocasió, a la prova 4, l’algoritme dinàmic ha trobat
una solució més llarga i en més passes totals (relació del 116,82%) que l’algoritme fix.
Nota: Vaig repetir la prova de les mil repeticions vàries vegades per comprovar si
donava uns valors més o menys constants, i sí que ho eren.
45
Mitjanes per a 1000 repeticions, laberint d’una única solució
Nota: Vaig repetir la prova de les mil repeticions vàries vegades per comprovar si
donava uns valors més o menys constants, i sí que ho eren.
46
5. Conclusions del Treball de Recerca
El primer objectiu del meu treball de recerca era aprendre a programar i considero que
l’he assolit, ja que he adquirit un nivell bàsic de programació. Tot i que encara em queda
molt per a aprendre i descobrir, he arribat a un nivell que em permet dissenyar i construir
programes de certa complexitat i també em serveix com a fonaments per a la meva
programació més avançada en el futur.
En general, la tasca ha resultat més difícil de l'esperat, ha presentat forts reptes per a
mi i m’ha obligat a emprar algoritmes d’estructura més complexa, com els recursius.
En tot cas, he pogut desenvolupar un programa prou efectiu tenint en compte el meu
nivell de programació.
El programa de resolució, el que fa que el robot trobi la sortida del laberint, ha resultat
també més complex de l'esperat. L'aplicació de l'algoritme de Hansel i Grettel, tot i que
és intuïtiu pels humans, no ha estat tan fàcil d'implementar en el robot. El programa
funciona i, fins i tot, he pogut fer una optimització a l’algoritme de resolució, creant així,
un segon algoritme de resolució que prenia decisions de forma intel·ligent.; també vaig
poder comparar aquests dos programes de resolució en els diversos tipus de laberints
mitjançant un estudi estadístic.
47
parets del laberint) i seria capaç d’arribar al seu objectiu, si és que en té, el qual seria
una localització, posició o coordenades determinades.
En general, estic molt satisfet amb el resultat del meu treball i especialment perquè he
aconseguit superar reptes que han resultat ser desafiants. En termes de l’aprenentatge,
he après a programar i, també, alguns dels conceptes principals sobre els ordinadors i la
informàtica.
Per acabar, m’agradaria remarcar que m’ho he passat molt bé programant i es podria dir
que, a part d’una habilitat adquirida, és també una nova afició i ja tinc pensats alguns
projectes que m’agradaria desenvolupar en un futur pròxim.
48
6. Bibliografia
Cursos de programació
RICE UNIVERSITY: www.coursera.org - “An Introduction to Interactive Programming in
Python”
Dubtes de programació
CHUWIKI: chuwiki.chuidiang.org
PROGRAMIZ: www.programiz.com
Informació
BIOGRAFIAS Y VIDAS: www.biografiasyvidas.com
EL-PRO-CUS: www.elprocus.com
EMERJ: www.emerj.com
EXPLAINTHATSTUFF: www.explainthatstuff.com
FORBES: www.forbes.com
HOWSTUFFWORKS: www.computer.howstuffworks.com
MEDIUM: www.medium.com
49
MICHIGAN STATE UNIVERSITY: www.canr.msu.edu
QUORA: www.quora.com
RAPIDTABLES www.rapidtables.com
TECHOPEDIA: www.techopedia.com
WIKIPEDIA: en.wikipedia.org
YOUTUBE: www.youtube.com
50
7. Annex
El programa sencer
51
52
53