An example Prolog program

April 9, 2007 - 3:27 pm

Way back at university (like, 3 years ago), I did a couple of papers that covered Prolog. Unlike most procedural top-down programming languages that us software developers are used to using, Prolog is a logic programming language. A typical Prolog program consists of facts, rules and queries. Although I don’t have a Prolog interpreter on my machine at the moment, we used SICStus Prolog on NetBSD at university.

Speaking of SICStus Prolog – apparently it now has integrated support for developing web based applications using a new module called PrologBeans. Using this module, SICStus Prolog can be called from a Java-based application server. Awesome!!

Anyway, for those interested in what Prolog looks like, below is an old assignment that I submitted for a course on Artificial Intelligence. If I remember correctly, the assignment was for us to simulate a robot cleaning dishes. We were asked to implement all the facts and rules, in Prolog, for such a robot. When the robot encounters dirty dishes, it is supposed to clean them. If it encounters wet dishes, it is meant to dry them.

When the program is run with an initial state, the output is a list of steps that the robot would take according to the prolog rules written in the program.

Below is the code for this program.



%-*-prolog-*-
% operator(-Op, -Pre, -Del, -Add)
% operator definitions
% Pre is a list of state preconditions
% After Op is applied
% Del gets deleted from state
% Add gets added to state


operator(putDirtyDishFromBench(X), pre: [dirty(X), at(X,bench)], del: [at(X,bench)], add: [at(X,sink)]).


operator(putDirtyDishFromDrainer(X), pre: [dirty(X), at(X,drainer)], del: [at(X,drainer)], add: [at(X,sink)]).


operator(putDryDishInSink(X), pre: [dry(X), at(X,drainer)], del: [dry(X), at(X,drainer)], add: [cleanButWet(X), at(X,sink)]).


operator(putDryDishInCupboardFromDrainer(X), pre: [dry(X), at(X,drainer)], del: [at(X,drainer)], add: [at(X,cupboard)]).


operator(putDryDishInCupboardFromBench(X), pre: [dry(X), at(X,bench)], del: [at(X,bench)], add: [at(X,cupboard)]).


operator(putCleanButWetDishFromSink(X), pre: [cleanButWet(X), at(X,sink)], del: [at(X,sink)], add: [at(X,drainer)]).


operator(putCleanButWetDishFromBench(X), pre: [cleanButWet(X), at(X,bench)], del: [at(X,bench)], add: [at(X,drainer)]).


operator(pickUpTool(X,Y), pre: [holding(X)], del: [holding(X)], add: [holding(Y)]).


operator(processInSink(X), pre: [dirty(X), at(X, sink), holding(dishbrush)], del: [dirty(X)], add: [cleanButWet(X)]).


operator(processInDrainer(X), pre: [cleanButWet(X), at(X, drainer), holding(teatowel)], del: [cleanButWet(X)], add: [dry(X)]).


% instantiate(?Operator)
% Makes Operator ground (including its pre, del and add lists)


instantiate(putDirtyDishFromBench(X)) :- dish(X).
instantiate(putDirtyDishFromDrainer(X)) :- dish(X).
instantiate(putDryDishInSink(X)) :- dish(X).
instantiate(putDryDishInCupboardFromDrainer(X)) :- dish(X).
instantiate(putDryDishInCupboardFromBench(X)) :- dish(X).
instantiate(putCleanButWetDishFromSink(X)) :- dish(X).
instantiate(putCleanButWetDishFromBench(X)) :- dish(X).
instantiate(pickUpTool(X,Y)) :- tool(X), tool(Y), X\==Y.
instantiate(processInSink(X)) :- dish(X).
instantiate(processInDrainer(X)) :- dish(X).


% dish(?Object)
% Object is a dish
dish(dish1).
dish(dish2).
dish(dish3).
dish(dish4).
dish(dish5).


% tool(?Object)
% Object is a tool
tool(dishbrush).
tool(teatowel).
tool(nothing).


% location(?Object)
% Object is a location
location(bench).
location(sink).
location(drainer).
location(cupboard).

An example of how to use this prolog program:


TESTDISHES1:


testdishes1 :- goal_stack_plan([at(dish1, bench), dirty(dish1), holding(nothing)], [at(dish1, cupboard), dry(dish1)], Plan, FinalState, []).

And the plan found by the program when TESTDISHES1 is run:


PLAN FOUND FOR TESTDISHES1:


====================================
Plan to achieve [at(dish1,cupboard),dry(dish1)]
Starting at [at(dish1,bench),dirty(dish1),holding(nothing)] putDirtyDishFromBench(dish1) pickUpTool(nothing,teatowel) pickUpTool(teatowel,dishbrush) processInSink(dish1) putCleanButWetDishFromSink(dish1) pickUpTool(dishbrush,teatowel) processInDrainer(dish1) putDryDishInCupboardFromDrainer(dish1)
Ending in state: [holding(teatowel),dry(dish1),at(dish1,cupboard)]
====================================
yes | ?-

If this looks like something you might wanna have a go with, try looking at this tutorial.

Leave a Reply