| BSc KI — Cursus Natuur & Berekening | 2025-26 |
In deze Java opdracht gaan jullie een A.I. schrijven die de “Evader” bestuurt in een variant op het “Pursuer Evader” (of Pursuit-evasion) spel. Het gedrag van de evader wordt bepaald door een Self-Organizing Map (SOM) te implementeren, die getraind kan worden door een groot aantal ronden van het spel te spelen. De resultaten worden weergegeven in een tabel of grafiek die het percentage dat de evader wint over een groot aantal ronden weergeeft. Het is de bedoeling dat dit percentage toeneemt naarmate het spel vordert, en dat de evader uiteindelijk zoveel mogelijk ronden wint.
In de Pursuer Evader Tracking (PET) game zijn er twee spelers: een pursuer en een evader. De evader probeert te ontkomen van de pursuer, terwijl de pursuer de taak heeft de evader te pakken te krijgen. Het spel wordt gespeeld op een oneindig groot, twee-dimensionaal veld, waarbij de agents een constante startpositie t.o.v. elkaar hebben, maar een willekeurige startrichting. De spanning in het spel ligt in het feit dat de pursuer zich met een hogere snelheid voortbeweegt, terwijl de evader weer sneller kan draaien.
Omdat het niet voor iedereen duidelijk is hoe ze de SOM moeten implementeren en vooral vastlopen op het gedeelte van de 'output', is hier extra uitleg en wat hints.
Qua input: Het aantal dimensies voor de input is een vrije keuze, maar het meest logisch zou zijn om te kiezen voor 2 of 3 dimensies. Deze keuze bepaald naast de input, dan ook het aantal gewichten in de nodes. Bij het kiezen van de inputs is het belangrijk om je af te vragen of de informatie relevant is, er geen of weinig overlap is tussen de verschillende dimensies en of het voldoende informatie is.
Qua output: Naast een x aantal weights, heeft de SOM in dit geval (dus niet zoals bij de voorbeelden in de links hieronder) ook een variabele voor de output. Deze wordt bij het aanmaken van de node geinitialiseerd (op 0, random of via een heuristiek). Op een vergelijkbare manier als de input weights, tellen de outputs alleen mee als ze in de neighborhood van de BMU zit en hoe dichterbij de BMU hoe zwaarder ze meetellen.
Leren: Nadat de outputs zijn geinitialiseerd, wil je ze kunnen aanpassen (dus leren). Dit doe je via een simpel algoritme: 1) Bepaal de wenselijkheid van de situatie waar je nu in zit (fitness functie). 2) Bepaal de output zoals hierboven bepaald. 3) Pas de output van 2 aan via een beetje ruis. Onthoud deze output voor de volgende stap en onthoud de BMU 4) Gebruik de output om de BMU aan te sturen 5) Bepaal opnieuw de wenselijkheid. dan zijn er 2 situaties: 5a) beter: leer 5b) slechter: leer niet Ga daarna verder met stap2
De library bestaat uit een jar file, die je zult moeten importeren in je Java project. We nemen even aan dat je Eclipse gebruikt, maar bij de andere editor zoals Netbeans is de procedure vergelijkbaar.
Wanneer je de voorbeeld klasse start zal er een Java Applet opstarten die beide spelers laat zien. De pursuer is roodgekleurd en bezit een standaard, hard-coded, AI. De evader loopt in de standaard-implementatie slechts vooruit. Zodra je de applet start zal er meteen een spel beginnen voor vijf ronden. De pursuer probeert de evader te vangen, en heeft hier een bepaalde tijd voor. Als dit hem lukt binnen de tijd dan wint hij, anders wint de evader. Zoals je ziet wint de pursuer lang niet altijd (de winstverdeling is ongeveer 50%-50%), maar de strategie van de evader is verre van optimaal.
In de Applet kun je kiezen tussen verschillende perspectieven. Wanneer je kiest voor het Relative (all) perspectief, zullen de bewegingen van de evader altijd relatief t.o.v. van die van de persuer zijn. De pursuer staat dus altijd op (0,0) en heeft een heading van 0. Deze modus is handig bij het maken van een AI, omdat hij het aantal variabelen reduceert, maar het is niet verplicht om hiermee te werken.
Probeer eerst een simpel algoritme te bedenken (b.v. een aantal if-else statements, random gedrag of iets anders slims) dat het al aardig doet. De besturing van de evader werkt erg eenvoudig: je kunt alleen de hoek aangeven waarmee je wilt dat de evader in de volgende tick van richting veranderd . Doel van deze (sub)opdracht is om bekend te raken met de mogelijkheden van de library. Lees hiervoor eerst de Javadoc van de klassen ExampleAI, GameCommunicator en AgentListener door. Lever deze klasse ook in.
Maak een klasse die je gaat gebruiken voor de nodes van je SOM, hierin worden de invoer waarden opgeslagen. Probeer alvast te bedenken welke en hoeveel invoerwaardes je wil gebruiken. Belangrijke vraag om hierbij te stellen is welke informatie relevant is. Deze klasse moet de afstand tot een andere node kunnen berekenen (het is handig om hiervoor de euclidische afstand te gebruiken). Voeg ook alvast functies toe voor het optellen en vermenigvuldigen van 2 nodes, en het vermenigvuldigen van de waardes in de node met een double.
Deze nodes worden in een grid/array gezet om samen de SOM te maken. Maak een klasse die hier voor zorgt en die alle relevante waardes initialiseert. Begin bijvoorbeeld met een array van 15x15 nodes. Dit kun je later veranderen.
Zorg er nu voor dat gedurende het lopen van het spel de SOM informatie binnen krijgt om te leren. Het is nog niet nodig om de SOM te output te laten bepalen. Controleer eerst dat de SOM datgene doet wat je ervan verwacht. Een mogelijkheid is om het getrainde netwerk uit te printen om zo de ontwikkeling te zien. De informatie die het SOM binnen krijgt moet er natuurlijk voor kunnen zorgen dat de evader een goede strategie ontwikkelt. Je zou bijvoorbeeld de hoek van de evader t.o.v. de pursuer kunnen gebruiken, en de heading van de evader.
Het is de bedoeling dat elke node ook een output bevat en dat hiervoor een optimale waarde geleerd wordt. De waarde die de functie zal teruggeven is het gewogen gemiddelde over de outputs, aan de hand van de geselecteerde node en de neighborhood. De geselecteerde node zal dus de uitvoer voor het grootste deel bepalen, maar de omliggende nodes dragen hier ook aan bij. De output zal de volgende actie van de evader zijn. De output is altijd de verandering in heading in de volgende tick, omdat dit het enige is wat je kunt instellen.
Om de optimale uitvoer te benaderen, voegen we tijdens het leren elke keer aan de uitvoer wat ruis toe, en kijken we of dit de prestatie heeft verbeterd. Het is handig om hier de volgende stappen te nemen:
Hier staat wat moet.* Bij afwijking van randvoorwaarden worden punten in mindering gebracht.
Je wordt geacht om de volgende stukken in te leveren:
| Laatst gewijzigd op woensdag 13 november 2024, om 15:02 uur | Auteur(s): Jori van Schijndel en Marc van Zee | Translate to en, ru, or tr |