CPSC 415 - Artificial Intelligence - Fall 2023

Program #1 — Agents and environments

Possible experience: +50XP

Due: Wednesday, Sep. 13, midnight  Thursday, Sep. 14, midnight


This programming assignment is a chance to work with a very basic version of the agent/environment AI architecture in a partially-observable environment. You'll be writing a controller for a variant of the vacuum-cleaner world as described in the book. This environment gives your agent only two boolean percepts: whether or not you just bumped into something, and whether or not your current location is dirty.

Your job will be to write an agent program that takes into account those two percepts — plus whatever other information you choose to compute and store internally — to decide whether to move in one of the four cardinal directions, suck the current carpet location, or do nothing. Your robot should get the room clean and try to minimize the amount of energy it consumes.

Supporting classes

The files main_vacuum.py, visualize.py, agent.py, environment.py, suite_vacuum.py, chunk_vacuum.py, and vacuum.py in the class's github repo contain a framework of Python classes for this project. You don't need to know the details of most of them, although you're encouraged to explore. The only ones you'll need to understand for this project are as follows.

The Thing and Agent classes (agent.py)

Everything that is present in an environment — including walls, dirt, and your own AI vacuum cleaner — is a Thing. Plain old Things don't really do much: this is just an abstract superclass.

An Agent also doesn't do much (anything, actually) by itself. It is a subclass of Thing that represents an intelligent entity. (Dirt doesn't count, but your vacuum cleaner will.) An intelligent entity is one with an agent program that actually does stuff in response to its environment. Accordingly, Agent has an abstract program() method which you'll provide to give it brains.

The VacuumAgent class (vacuum.py)

A VacuumAgent is a specific kind of agent, which again doesn't do much by itself. You'll be inheriting from this class as described below to make your own specific vacuum cleaner. One thing it has is a list of the legal actions your vacuum will be capable of taking.

The VacuumEnvironment class hierarchy (vacuum.py and environment.py)

You don't really need to know much of anything about these, unless you're curious. They contain code for the simulated environment in which your vacuum cleaner will live and move.

The test harness (main_vacuum.py, suite_vacuum.py, and chunk_vacuum.py)

You don't need to know anything about these either, except how to run main_vacuum.py (as described below).

Your mission

Your job is to write a subclass of VacuumAgent that will implement an agent program. The only methods required are a constructor (always called "__init__()" in Python) and the method called "program()" which does your dirty deeds.

You'll use __init__() for any initialization code you want to run just before your vacuum cleaner springs into action. Then, the environment will call your program() function repeatedly when it's your turn to take an action. Each time program() is called, you must return one of the six strings 'Left', 'Right', 'Up', 'Down', 'Suck', or 'NoOp', which is your way of telling the environment what you want to do. The first four of those strings indicate that you want to (try to) move; one says you want to "suck" dirt (if any) from the current square, and the final one says you want to do nothing and conserve energy.

(Btw, the word no-op, pronounced "KNOW opp," is standard computer science terminology for "do nothing during the current time step." Microprocessors all have a no-op instruction in addition to their ADD, MOV, JMP, etc. instructions. When executed, NOOP tells the processor to do nothing during that clock tick.)

Your program() method will be given a tuple of two strings each time it's called: the first will be either the string 'Dirty' or 'Clean', depending on whether the square immediately beneath you contains dirt. The second will be either 'Bump' or 'None'. This tells you whether or not you hit an obstacle the last time you took an action. This is a bit tricky, so pay attention. If your program() chooses to try and move (up, down, left, or right), you will return a value indicating such. However, you won't know whether that "worked" until the next time program() is called. If the next percept you receive contains 'None', that means your move action worked, and you did in fact travel one square in your chosen direction. If it returns 'Bump', though, then you ran into something when you tried to move (perhaps a wall, another vacuum cleaner, or a toddler) and you did not successfully change locations.

Performance measure

Your agent will be evaluated in the following way:

To grade, I'll be running your vacuum agent for 1,000 steps on various rooms of sizes from 10×10 to 20×20. (See the RandomDirtyVacuumEnvironment class in vacuum.py if you're interested in the details of how test rooms will be generated.) The number of XP you receive from this assignment will be directly related to your agent's average performance measure on a variety of random rooms.

Getting started

Begin by cloning the class git repo somewhere on your disk. You can do that with the following command if you're cool and have your github configured to use SSH keys:

git clone git@github.com:divilian/cpsc415.git

or with this command if you're not so cool and want to type your github password a lot this semester:

git clone https://github.com/divilian/cpsc415

(Btw, if you're currently not so cool but want to become more cool and get your github configured to use SSH keys, see Ian's 225 instructions.)

Then, use vim, Spyder, or whatever editor you choose to create a file in your cloned directory (the one that has agent.py, vacuum.py, etc.) with your vacuum agent class in it. Your class will be called YourumwidVacuumAgent, and be defined in a file called yourumwid_vacuum.py. (Please do not name your file or class anything else. Please do not change the name, or change the capitalization, or add/remove underscores, or do any other clever or creative things. Please call the class exactly YourumwidVacuumAgent, capitalized, with your actual (capitalized) UMW Net ID substituted for "Yourumwid", and call the file exactly yourumwid_vacuum.py, with your actual (lowercase) UMW Net ID substituted for "yourumwid". Thanks.)

Here's how the first few lines of your (say) jsmith3_vacuum.py file should look:

from vacuum import VacuumAgent class Jsmith3VacuumAgent(VacuumAgent): def __init__(self): super().__init__() # any initialization you want to do here def program(self, percept): # your amazing AI vacuum cleaner code goes here

For the moment, you could just make your vacuum cleaner sit there on its butt by doing this:

... def program(self, percept): return 'NoOp'

Now, get the simulator to run. At the command line, run:

$ python3 main_vacuum.py yourumwnetid

or in Spyder, type in the IPython console:

In [1]: run main_vacuum.py yourumwnetid

and make sure you get a display that looks something like this:

(likely with a different layout, of course.) If this doesn't come up for you, let me know right away so we can figure out your troubles.

If you're using neither the command line nor Spyder, you may have to Google a bit to find out how to make your IDE accept command-line arguments.

Okay, you are now ready to begin thinking.

Evaluating your program

See the comments in main_vacuum.py for details on how you can run the simulator. The basics are these:

  1. Every time you press the "Go" button (or the Return/Enter key), your vacuum cleaner will take one action.
  2. If you check "Continuous" and press "Go," it will run continuously.
  3. If you add a "suite=#" command-line argument, it will run an entire batch of simulations with random rooms, and print details and a summary output. For instance, if you run:
    $ python3 main_vacuum.py jsmith3 suite=6
    you'll get six runs, with output like this:
    # Score: min 33, max 1560, med 1358
    # Num steps: min 372, max 1388, med 498
    For each run, this gives the random number seed, total score, and number of steps required before the whole room was clean. It also prints the minimum, maximum, and median score & steps for that suite.

The sheer thrill of a partially-observable environment

"How will I know how big the room is?"

You won't.

"How will I know if there are any remaining dirt squares to clean?"

You won't.

"How will I know where in the room I start?"

You won't. (You'll spawn at a random location.)


I will run your agent on 1000 randomly-generated rooms (with consecutive seeds starting with 2021, in honor of the current year). You are guaranteed to receive at least as many XP as your median score divided by 100 (though not over 50).

For instance, if your median score on those 1000 test runs is 2469, you are guaranteed to cash in at least +25XP. (Yes, I'll round up.)

Documenting your process

You will be developing your program using the same techniques that real developers use to write real programs in the real world. In particular, you'll be regularly committing to your git repo, as you work on it. Each time you complete a task and come to a momentary stopping point is a good time to do a git commit, and give it a brief but meaningful commit message that you will recognize later.

(Stage hazard: don't forget to "git add" your yourumwid_vacuum.py file to your repo before doing "git commit" for the first time!)

When you turn in the assignment, you will be sending me your latest git repo as a bundle (see below). When I clone your bundle and perform a git log on it, I should see several early "Stephen commits" followed by your commits. ("Followed by" means "above," since git log prints entries in reverse chronological order.) Before you turn it in, make sure you can do a git log on your own machine and see this.

To get maximum credit, you must have at least 5 meaningful commits in your repo. "Meaningful" means "whatever Stephen deems is meaningful." In general it should contain one non-trivial but non-mammoth set of related changes. (In general, a git commit should probably involve somewhere between 5 and 50 lines of code. I say that just to give you a general idea, though; I'm not judging your commits based on the number of lines.)

If you have fewer than 5 meaningful commits in your repo, I will deduct 10XP from the score you would have otherwise received for each commit short of 5 that you have. (Example: if you only have two meaningful commits in your repo, you would get -30XP incorporated into your final score.)

Every commit should contain code that you understand and can describe. If you choose to use an AI assistant like ChatGPT for any part of this assignment, you must indicate in your commit messages which commits were produced partly or solely by the AI, as well as your description of the change. You must also submit separately the session of prompts and responses that interacting with the AI produced, for each such commit. (See below.)

Turning it in

You will turn this assignment in by attaching a git bundle to an email. (A "git bundle" is essentially a portable, zipped-up git repo.)

To create your bundle, first make sure that all your code is commit to your repo. Running "git status" and ensuring your workspace is clean is a great way to do that. Then, bundle up your git repo:

$ git  bundle  create  yourUmwUsername.git  --all

(Please do not name it literally "yourUmwUsername.git" Substitute your actual UMW username. For instance, "jsmith7.git".)

If you used an AI such as ChatGPT for any part of this assignment, then in addition to your git bundle, also create a single PDF file with all the prompts and responses from your AI session. There should be easily-visible text indicating which commit those prompts/responses pertain to. The name of this PDF file should be "yourUmwUsername_AI_transcript.pdf".

Finally, send me an email with subject line "CPSC 415 Program #1 turnin," with your yourUmwUsername.git file and (optionally) yourUmwUsername_AI_transcript.pdf files as attachments. In the body of the email, tell me your favorite vacuum cleaner joke.

Important note

To be clear, if you turn in this email without a "yourUmwUsername_AI_transcript.pdf" attached, you are implicitly declaring that you wrote all your code by yourself, without using an AI assistant.

Getting help

Come to office hours, or send me email with subject line "CPSC 415 Program #1 help!!"