Project 3: Logic and Classical Planning (100 points, Deadline: October 14,11:59PM)


Table of Contents


Logical Pacman,
Food is good AND ghosts are bad,
Spock would be so proud

Introduction

In this project, you will use/write simple Python functions that generate logical sentences describing Pacman physics, aka pacphysics.

Then you will use a SAT solver, pycosat, to solve the logical inference tasks associated with planning(generating action sequences to reach goal locations).

As in previous programming assignments, this assignment includes an autograder for you to grade your answers on your machine. This can be run with the command:

python autograder.py

The code for this project consists of several Python files, some of which you will need to read and understand in order to complete the assignment, and some of which you can ignore.

You can download all the code and supporting files as a zip archive.

Files you will edit:
logicPlan.py Where you will put your code for the various logical agents.
Files you might want to look at
logic.py Propsitional logic code originally from https://code.google.com/p/aima-python/ with modifications for our project. There are several useful utility functions for working with logic in here.
logicAgents.py The file that defines in logical planning form the two specific problems that Pacman will encounter in this project.
pycosat_test.py Quick test main function that checks that the pycosat module is installed correctly.
game.py The internal simulator code for the Pacman world. The only thing you might want to look at in here is the Grid class.
test_cases/ Directory containing the test cases for each question
Files you will not edit
pacman.py The main file that runs Pacman games.
logic_util.py Utility functions for logic.py
util.py Utility functions primarily for other projects
logic_planTestClasses.py Project specific autograding test classes
graphicsDisplay.py Graphics for Pacman
graphicsUtils.py Support for Pacman graphics
textDisplay.py ASCII graphics for Pacman
ghostAgents.py Agents to control ghosts
keyboardAgents.py Keyboard interfaces to control Pacman
layout.py Code for reading layout files and storing their contents
autograder.py Project autograder
testParser.py Parses autograder test and solution files
testClasses.py General autograding test classes

Files to Edit and Submit: You will fill in portions of logicPlan.py during the assignment. You should submit these files with your code and comments. Please do not change the other files in this distribution or submit any of our original files other than these files.

Report (5 points) This should include stats such as number of nodes expanded, memory usage and running time for each search strategy that you have used in this project. The report should conclude with a critical analysis of the search methods based on your collected stats.

Evaluation: Your code will be autograded for technical correctness. Please do not change the names of any provided functions or classes within the code, or you will wreak havoc on the autograder. However, the correctness of your implementation -- not the autograder's judgements -- will be the final judge of your score. If necessary, we will review and grade assignments individually to ensure that you receive due credit for your work.

Academic Dishonesty:We will be checking your code against other submissions in the class for logical redundancy. If you copy someone else's code and submit it with minor changes, we will know. These cheat detectors are quite hard to fool, so please don't try. We trust you all to submit your own work only; please don't let us down. If you do, we will pursue the strongest consequences available to us.

Getting Help: You are not alone! If you find yourself stuck on something, contact the course staff for help. Office hours, section, and the discussion forum are there for your support; please use them. If you can't make our office hours, let us know and we will schedule more. We want these projects to be rewarding and instructional, not frustrating and demoralizing. But, we don't know when or how to help unless you ask.

Discussion: Please be careful not to post spoilers.


The Expr Class

In the first part of this project, you will be working with the Expr class defined in logic.py to build propositional logic sentences. An Expr object is implemented as a tree with logical operators (∧, ∨, ¬, →, ↔) at each node and with literals (A, B, C) at the leaves. Here is an example sentence and its representation:

(A ∧ B) ↔ (¬ C ∨ D)

Example logic tree.

To instantiate a symbol named 'A', call the constructor like this:

A = Expr('A')

The Expr class allows you to use Python operators to build up these expressions. The following are the available Python operators and their meanings:

So to build the expression A ∧ B, you would type this:

A = Expr('A')

B = Expr('B')

a_and_b = A & B

(Note that A to the left of the assignment operator in that example is just a Python variable name, i.e. symbol1 = Expr('A') would have worked just as well.)

A note on conjoin and disjoin

One last important thing to note is that you must use conjoin and disjoin operators wherever possible. conjoin creates a chained & (logical AND) expression, and disjoin creates a chained | (logical OR) expression. Let's say you wanted to check whether conditions A, B, C, D, and E are all true. The naive way to achieve this is writing condition = A & B & C & D & E, but this actually translates to ((((A & B) & C) & D) & E), which creates a very nested logic tree (see (1) in diagram below) and becomes a nightmare to debug. Instead, conjoin makes a flat tree (see (2) in diagram below).

Example logic tree.

Prop Symbol Names (Important!)

For the rest of the project, please use the following variable naming conventions:

Rules

Pacphysics symbols

There is additional, more detailed documentation for the Expr class in logic.py.

SAT Solver Setup

A SAT (satisfiability) solver takes a logic expression which encodes the rules of the world and returns a model (true and false assignments to logic symbols) that satisfies that expression if such a model exists. To efficiently find a possible model from an expression, we take advantage of the pycosat module, which is a Python wrapper around the picoSAT library.

Unfortunately, this requires installing this module/library on each machine.

To install this software on your conda env, please follow these steps:

  1. Activate your conda env: conda activate cse537 (if your env is called cse537)
  2. Install pycosat: On command line run: pip install pycosat. (Note: you may need to run: sudo pip3 install pycosat.) If you get errors, try instead conda install -c anaconda pycosat.

Testing pycosat installation:

After unzipping the project code and changing to the project code directory, run:

python pycosat_test.py

This should output:

[1, -2, -3, -4, 5].

Please let us know if you have issues with this setup. This is critical to completing the project, and we don't want you to spend your time fighting with this installation process.


Question 1 (10 points): Logic Warm-up

This question will give you practice working with the Expr data type used in the project to represent propositional logic sentences. You will implement the following functions in logicPlan.py:

Before you continue, try instantiating a small sentence, e.g. A ∧ B → C, and call to_cnf on it. Inspect the output and make sure you understand it (refer to AIMA section 7.5.2 for details on the algorithm to_cnf implements).

To test and debug your code run:

python autograder.py -q q1

Question 2 (10 points): Logic Workout

Implement the following three functions in logicPlan.py:

Each of these methods takes a list of Expr literals and returns a single Expr expression that represents the appropriate logical relationship between the expressions in the input list. An additional requirement is that the returned Expr must be in CNF (conjunctive normal form). You may NOT use the to_cnf function in your method implementations (or any of the helper functions logic.eliminate_implications, logic.move_not_inwards, and logic.distribute_and_over_or).

Don't run to_cnf on your knowledge base when implementing your planning agents in later questions. This is because to_cnf makes your logical expression much longer sometimes, so you want to minimize this effect, and findModel does this already. In later questions, reuse your implementations for atLeastOne(.), atMostOne(.), and exactlyOne(.) instead of re-engineering these functions (to avoid accidentally making an unreasonably slow non-CNF-based implementation) from scratch.

You may utilize the logic.pl_true function to test the output of your expressions. pl_true takes an expression and a model and returns True if and only if the expression is true given the model.

To test and debug your code run:

python autograder.py -q q2

Question 3 (25 points): Pacphysics and Satisfiability

In this question, you will implement the basic pacphysics logical expressions, as well as learn how to prove where pacman is and isn’t by building an appropriate knowledge base (KB) of logical expressions.

Implement the following functions in logicPlan.py:

Reminder: the variable for whether Pacman is at (x, y) at time t is PropSymbolExpr(pacman_str, x, y, time=t), wall exists at (x, y) is PropSymbolExpr(wall_str, x, y), and action is taken at t is PropSymbolExpr(action, time=t).

To test and debug your code run:

python autograder.py -q q3

Question 4 (50 points): Path Planning with Logic

Pacman is trying to find the end of the maze (the goal position). Implement the following method using propositional logic to plan Pacman's sequence of actions leading him to the goal:

Disclaimer: the methods from now on will be decently slow. This is because a SAT solver is very general and simply crunches logic, unlike our previous algorithms that employ a specific human-created algorithm to specific type of problem. Of note, Pycosat's main algorithm is in C, which is generally a much much faster language to execute than Python, and it's still this slow.

You will not be implementing a search algorithm, but creating expressions that represent pacphysics for all possible positions at each time step. This means that at each time step, you should be adding general rules for all possible locations on the grid, where the rules do not assume anything about Pacman's current position.

You will need to code up the following sentences for your knowledge base, in the following pseudocode form:

Test your code on smaller mazes using:

python pacman.py -l maze2x2 -p LogicAgent -a fn=plp
python pacman.py -l tinyMaze -p LogicAgent -a fn=plp

To test and debug your code run:

python autograder.py -q q4

Note that with the way we have Pacman's grid laid out, the leftmost, bottommost space occupiable by Pacman (assuming there isn't a wall there) is (1, 1), as shown below (not (0, 0)).

Summary of Pacphysics used in Q3 and Q4 (also found at AIMA chapter 7.7):

Note that the above always hold true regardless of any specific game, actions, etc. To the above always-true/ axiom rules, we add information consistent with what we know.

Debugging hints: