Introduction to Prolog

Prolog is what’s called a “Logic Programming Language”. Instead of telling the computer what to do and how to do it, you tell it facts and then query those facts. Here is a very basic example of what working with prolog is like, in plain English:
You: Alice is a female.
You: Bob is a male.
You: Charlie is a male.
You: Charlie is the child of Bob.
You: Charlie is the child of Alice.
You: X is the son of Y if X is male and X is a child of Y.
You: Who is Bob's son?
Prolog: Charlie.

There are many software packages that use this language, each with their own variations, so for the purposes of this document I will be referring to a very common one called SWI-Prolog.

Basic Language Structure

File name

Prolog code should be stored in .pl files, not unlike PERL files.

Predicates

Predicates are basic facts about your system, contrary to rules. Predicates have a name and parameters. They are defined as follows:
predicate_one(parameter_one).
predicate_one(parameter_two).
predicate_two(paramter_one,parameter_two).

Note that any parameter starting with a capital letter is understood to be a variable, so your parameters should always start with a lower-case letter if they are static. The above code creates two predicates called predicate_one/1 and predicate_two/2. In Prolog, the /n signifies how many parameters that predicate takes. You will often see it when debugging.

Rules

Rules are like predicates, but with variables instead of static parameters. Rules are defined as follows:
rule_one(X,Y) :- predicate_one(X), \+ predicate_one(Y).
rule_one(X,Y) :- predicate_one(Y), predicate_two(X,Y).

The first line states that rule_one is true if predicate_one is true for X and not true for Y. The second line states that rule_one is also true if predicate_one is true for Y and predicate_two is true of X and Y. In a functional language, we can think of this as the following conditional statement:
bool function rule_one(X,Y) {
if(predicate_one(X) and !predicate_two(Y)) return(true);
else if(predicate_one(Y) and predicate_two(X,Y)) return(true);
else return(false);
}

Equivalence

Predicates can be rewritten as rules using equivalence. This is useful in some cases when doing comparisons. i.e. male(bob). can be rewritten as male(X) :- X = bob..

Stopping a rule early (Cut)

If you have a rule where at a certain point you don’t want prolog to backtrack, you use what is called a ‘cut’. Placing an exclamation mark (!) in your rule will make sure that if everything before that mark is true, prolog will not backtrack to any other possible variations of that rule, and will only continue from where the exclamation mark is. See the quick reference section below for details.

Don’t-care variable

A don’t-care variable is a variable whose value is irrelevant. This is important because it will help us suppress warnings and make code more readable to human beings. Suppose you wanted to write a rule is_colder_than/2 where it is true when X is colder than Y. We know that nothing is colder than absolute zero, so we could write is_colder_than(absolute_zero,Y). meaning absolute_zero is colder than any Y. However, we would get a warning because we are not using Y for any comparisons in the rule’s body. As such, we can replace Y with _ and simply say is_colder_than(absolute_zero,_)..

Advanced Prolog Use

Loading other files

There are many instances where you may want to separate your prolog program into multiple files (i.e. one for all your basic predicates, one for rules, etc.). You can load files using the following syntax: [file_name].. You can do this from within a file, also from within the console.

Queries within a file

If you want to perform a query instead of stating a predicate/rule from within your prolog file, you can prefix your query with ‘:-‘. For example, say you want prolog to automatically display if bob is a male, you can add :- male(bob). to your file.

Writing formatted output

write/1 will display whatever you need to the console. To display a mix of variables and text you can just call write multiple times. Example: write(X),write(' is a male'),nl.. Note the ‘nl’ will create a new line at the end.

Iterating over sets of elements (bagof/setof)

Bagof and Setof are two different prolog constructs that look at all the elements of a group for which a rule is true. The difference is that setof will never repeat elements whereas bagof can. Suppose you wanted to display all elements that are male:
maleq(X) :- male(X),write(X),write('is a male'),nl.
:- bagof(_,maleq(_),_).

Dynamic Predicates

If you try to define predicates after loading them, you will get an error that says something like “unable to modify static procedure …”. However, it is still possible to change predicates after loading them. Before defining any members of a predicate, define it to be dynamic by doing dynamic(male/1).. Define all your base predicates, then to add a new one you can do something like assert(male(doug)).. To delete a predicate you can use retract/1 or retractall/1. Note that dynamic/1 needs to be run from the console, so to do it from within a file you must use :- dynamic(...).

Quick Reference

What How to do it Example
Negation Add a \+ in front of the predicate or rule \+ tiger(calvin)
Don’t-care Variable Replace the variable’s name with _ can_be_imagined(_).
Cut Add a ‘!’ in the rule, where appropriate. is_colder_than(X,_) :- X = absolute_zero, !.
Bagof/Setof See example. Setof will not repeat elements. likes(mary,pizza).
likes(marco,pizza).
likes(Human,pizza) :- italian(Human).
italian(marco).

?- bagof(Person,likes(Person,pizza), Bag).
Person = _G180
Bag = [mary,marco,marco]

Example taken from the Prolog Dictionary.

Additional Resources

0 Comments

Leave a Reply

Your email address will not be published.