Prolog using Examples – Part 2

Lets begin with cases related with recursion:

In an imperative style,  you would use a loop to produce a result, while in an functional style, it is common to use recursion to produce the same result.

The most common example related with recursion is the factorial recursion, in which for example the factorial of 6 (6! = 5 * 4 * 3 * 2 * 1) would give us

/* Base case of the factorial, when N is 0 then return 1 */
factorial(0, 1).

factorial(N, M) :-
    N1 is N - 1,
    factorial(N1, M1),
    M is N * M1.
?- factorial(6, T).
T = 720;
ERROR: Out of local stack

Note: As you can see, when we added the OR ‘;’, prolog tried to find another  answer and went out of bound.
To prevent this we can do an small modification as follows:

/* Base case of the factorial, when N is 0 then return 1 */
factorial(0, 1).

factorial(N, M) :-
    N > 0
    N1 is N - 1,
    factorial(N1, M1),
    M is N * M1.
?- factorial(6, T).
T = 720;
False

In this case, when we tell Prolog that we wish to find another possible answer, Prolog would indicate false since it cannot find any other possible solution.

Lets go over some examples:

Example 1: We have a family and we wish to know the descendent of some individual.

/* Maria is_mother_of Pedro */
is_mother_of(Maria, Pedro).

/* Susana is_mother_of Maria */
is_mother_of(Susana, Maria).

/* Pepe is_father_of Pedro */
is_father_of(Pepe, Pedro).

/* Diego is_father_of Pepe */
is_father_of(Diego, Pepe).

/* Person is_parent_of Child if Person is_mother_of Child */
is_parent_of(Person, Child):- is_mother_of(Person, Child).

/* OR */

/* Person is_parent_of Child if Person is_father_of_Child */
is_parent_of(Person, Child):- is_father_of(Person, Child) */

/* Begin RECURSION */

/* Recursion Base */

/* Person is_decendent_of Adult if Adult is_parent_of Person */
is_decendent_of(Person, Adult) :- is_parent_of(Adult, Person).

/* Recursion */
/* Person is_decendent_of Adult if Older(person) is_parent_of Person AND Older is_decendent_of Adult */
 is_decendent_of(Person, Adult) :- is_parent_of(Older, Person), is_decendent_of(Older, Adult).

Example 2: Fibonacci (http://en.wikipedia.org/wiki/Fibonacci_number) is an integer sequence such as 0, 1, 1, 2, 3, 5, 8… As you may notice, the first two numbers are 0 and 1, an the subsequence is form by a number created from the sum of the two previous numbers: 0 + 1 = 1 (0,1,1) , 1 + 1 = 2 (1,1,2), 1 + 2 = 3 (1,2,3), 2 + 3 = 5 (2,3,5) …

/* Recursion base case */
fibonacci(0, 0).

/* Recursion base case */
fibonacci(1, 1).

/* Recursion */
fibonacci(N, F) :-
    N1 is N - 1,
    N2 is N - 2,
    fibonacci(N1, F1),
    fibonacci(N2, F2),
    F is F1 + F2.

?- fibonacci(8, T).
T = 21;
ERROR: Out of local stack

Again in this case, when asking prolog to find another answer, it would go out of bounds because there is no case that stop it to keep calling itself. We need to modify this program:

/* Recursion base cases */
fibonacci(0, 0).
fibonacci(1, 1).

/* Recursion */
fibonacci(N, F) :-
    N > 0,
    N1 is N - 1,
    N2 is N - 2,
    fibonacci(N1, F1),
    fibonacci(N2, F2),
    F is F1 + F2. ?- fibonacci(8, T).
T = 21;
False

Again, Prolog couldn’t find a different answer when we ask it to search for it and let it know by returning false after the OR ‘;’.

Example 3: The following code is the Ackermann’s predicate (http://en.wikipedia.org/wiki/Ackermann_function).
One of the purposes to doing this kind of function could be to test the limits of the compiler.
The Ackermann’s functions is defined as follows:
ackermann( m,n ) =    n + 1                                                             if m = 0
ackermann( m,n ) =    ackermann(m – 1, 1)                                if n = 0 and m > 0
ackermann( m,n ) =    ack( m-1, ackermann( m, n-1 ) )          if n >0 and m > 0

/* ackermann(m, n) = n + 1 if m = 0 */
ackermann(Mi, Ni, No):- Mi = 0, No is Ni + 1.

/* ackermann(m, n) = ackermann(m - 1, ackermann(m, n - 1)) if n > 0 and m > 0 */
ackermann(Mi, Ni, No):-
    Mi > 0, Ni > 0,
    Mi2 is Mi - 1, Ni2 is Ni - 1,
    ackermann(Mi, Ni2, No2),
    ackermann(Mi2, No2, No).

/* ackermann(m, n) = ackermann(m - 1, 1) if n = 0 and m > 0 */
ackermann(Mi, Ni, No):-
    Mi > 0, Ni = 0,
    Mi2 is Mi - 1, Ni2 is 1,
    ackermann(Mi2, Ni2, No).

In the next blog posting, we are going to see Lists in Prolog.

Share
Leave a comment

Prolog using Examples – Part 1

Prolog is a programming language which works around relations not functions.
Prolog is homoiconic due the structure of its clauses and database that provide it the ability to represent itself.
Note: A language is homoiconic when the language is self-defined. This means that if we run on the interpreter a copy of itself, it should work. Another behaviour of an homoiconic language is to lets the programmer to create, change, and run the code on the fly.
Prolog is not fully reflective, but close, Prolog seems like reflective language because  a program that can resolve a problem by itself by just using relationships, facts, rules, structures, and a database. A fully reflective language should be able to create relationships, rules, structures, and database by itself as needed to find a solution.

In Prolog, facts are clauses with an empty body, eg:

is_mother_of(Maria, Matias). /* Maria is_mother_of Matias */

Rules are clauses with a head and body (head():- body), eg:

/* A Person is_parent_of the Child if (Smile the Person is_mother_of the Child */
is_parent_of(Person, Child) :- is_mother_of(Person, Child).

Predicate are clauses using the same head with different bodies, eg:

/* A Person is_parent_of the Child if (Smile the Person is_mother_of the Child */
is_parent_of(Person, Child) :- is_mother_of(Person, Child).
/* A Person is_parent_of the Child if (Smile the Person is_father_of the Child */
is_parent_of(Person, Child) :- is_father_of(Person, Child).

Note: Every code written before ‘?-‘ are facts and rules. Code written following ‘?-‘ are queries, and all code after ‘?-‘ are the results that prolog returns. eg:

is_mother_of(Marina, Marcos).   /* This is a fact */
is_parent_of(Person, Child) :- is_mother_of(Person, Child). /* This is a rule */
?- is_parent_of(Marina, Marcos). /* This is a query */
True /* This is a result. note that this comment will not show up */
?- is_parent_of(Marina, Lucia). /* This is a query */
False

Lets talk about unification.

/* A unified with B if and only if A and B are the same */
?- =(A, B).
A = B.

/* This is the same as =(A, B) */
?- A = B.
A = B.

Note that A = 1 + 2 will not give you 3 but A = 1 + 2 which means you are unifying A with 1 + 2.
If you to obtain a mathemarical result you should use the following code, eg:

?- A is 1 + 2.
A = 3.

The follows are some examples of unification:

/* a is a constant (also known as an atom) */
/* Since constants can unify with themselves then this is true */
?- a = a.
True

/* a and b are constants, but b is not the same as a, when trying to unify a with b, this will give you false */
?- a = b.
False

/* In case you are unifying facts with constants */
?- foo(a, b) = foo(a, b).
True.

/* This case fails since in both facts, at least one of the constants are nor the same */
?- foo(a, b) = foo(a, c).
False.

?- foo(a, b) = foo(b, a).
False.

Unification can also being use to unify a constant with a variable (Variables start with capital letter), eg:

?- A = a.
A = a.

/* In this case for example we can unify A with c and B with d */
?- foo(A, B) = foo(c, d).
A = c,
B = d.

Note that in Prolog, a variable cannot be modified after

You may have notice the comma after A = c. In Prolog, ‘,’ have the same meaning as AND, while a new line or ‘;’ means OR.

Example:

/* Lets say that prolog provide us with an answer */
?- foo(a, X) = foo(a, b).
X = b; /* <- if we add this semicolon ';' instead of a newline to ask another answer (OR) */
False  /* We get a false because there is no other case */

/* Person is_parent_of Child if Person is_mother_of Child OR Person is_father_of Child */
is_parent_of(Person, Child) :- is_mother_of(Person, Child).
is_parent_of(Person, Child) :- is_father_of(Person, Child).

/* Person is_mother_of Child if Person is_parent_of Child AND Person is_female */
is_mother_of(Person, Child) :- is_parent_of(Person, Child), is_female(Person).

/* Another example of AND and unification */
/* A is unified with B AND A is unified with constant z AND B is unified with Y */
?- A = B, A = z, B = Y.
A = z, /* A was unified with z */
B = z, /* Since A = B and A = z then B = z */
Y = z. /* Since B = A = z then Y = z */

Explicit versus Implicit:

Explicit:

relationship(Z, Z).
is_related(X, Y):-
    relationship(X, b),
    relationship(a, Y).
?- check(First, Second).
First = b,
Second = a.

Implicit:

relationship(Z, Z).
?- is_related(relationship(First, b), relationship(a, Second)).
First = a,
Second = b.

More examples of simple Facts and Rules:

Example 1: Lets do a modification of the game of Yahtzee (http://en.wikipedia.org/wiki/Yahtzee).
Yahtzee is played with 5 dices, and depending of the combination you can obtain: Chance, Three-Of-A-Kind, Four-Of-A-Kind, Full House, Small Straight, Large Straight, and Yahtzee.
We are going to do only the Yahtzee combination for this example and the user will input values from 1 to 6.

/* Establish the facts and rules */

/* Yahtzee: All five dices show the same face. */
yahtzee(A, A, A, A, A).
?- yahtzee(5,5,5,5,5).
True

?- yahtzee(5,4,5,4,5).
False

Example 2: Lets do some adding. This is a way that you can do adding by using successor(0)
as a numeral.

/* When 0 is the same as 0, then Y = 0 */
add(0, Y, Y).
/* */
add(successor(X), Y, successor(Z)) :- add(X, Y, Z).
/* Example of behavior when used in the wrong way */
?- add(A, B, C).
A = 0,
B = C;
A = successor(0),
C = successor(B);
A = successor(successor(0)),
C = successor(successor(B));
... /* This keeps on going if you use OR ';' */
/* Example of behavior when used in the wrong way */
?- add(A, 0, C).
A = 0,
C = 0;
A = successor(0),
C = successor(0);
A = successor(successor(0)),
C = successor(successor(0));
... /* This keeps on going if you use OR ';' */
/* Example of behavior when used in the wrong way */
?- add(0, B, C).
A = 0,
B = 0.
/* Example of behavior when used in the wrong way */
?- add(0, 1, C).
false.
/* Do 1 + 1 = 2: successor(0) + successor(0) = successor(successor(0)). */
?- add(successor(0), successor(0), X).
X = successor(successor(0)).
/* Do 2 + 1 = 3. */
/* successor(successor(0)) + successor(0) = successor(successor(successor(0))). */
?- add(successor(successor(0)), successor(0), X).
X = successor(successor(successor(0))).

Notice that a rule can behave different depending who you define your inputs and outputs.

Example:

/* Here we find that we are doing -1 + 1 = 0 */
?- add(successor(0), X, successor(0)).
X = 0.
/* Here we have 2 - 1 = 1 */
?- add(successor(0), X, successor(successor(0))).
X = successor(0).
/* While this give you X = 0, it would fail in a different case */
?- add(X, successor(0), successor(0)).
X = 0
/* Here this fails */
?- add(X, successor(successor(0)), successor(0)).
false.

In the next submittion we are going to see recursion in Prolog.

Share
Leave a comment

Making a cheap large table

I was taking a class of physics to review some things at Broome Community College which required me to use a table with minimum of  one meter by one meter in proportion. The first problem was money and the second problem was space.

Lucky for me, I found out that one of my neighbours thought to the trash an old table for kids.

I pick up that table. I bought a board for  less than 10 dollars. A little work, and magic.

Just some pointers:

1. Always wear safety glasses for any work you may do. NO EXCEPTIONS.

2. If you are going to make holes,

a. Get a piece of wood under the piece you are planning to make the hole

b.Using a nail and hammer, place a mark where you are going to make the hole. The mark will make your drilling easier and prevent the drill moving to a different location.

c. Measure twice and drill once.

d. Don’t apply extreme force, let the drill do its work, be patience.

Share
Leave a comment

Group Project: 3D Game for the iphone and itouch!

Its official!

Our group is going to develop a new game for the iphone! A new system for first shooters. So far, I have not found anyone that came up with the same idea. Therefore, it will be in secret until the game in publish.

Our team right now if form by:

Alejandro G. Carlstein Ramos Mejia – Game Concept Designer, Programmer, Administration

Agustin Alejandro Benavidez: Project Manager

Philibian Lindo: Programmer, Audio and Visual effects, Animation

Stephen Brower: Programmer.

Adam Willson: Graphic Designer

Joshua R. Smith: Code tester

Extra help from:

Marina Carlstein Ramos Mejia: Graphic Designer

The team

Share
Leave a comment