Posts

Showing posts from February, 2009

Adventures in Prolog - Simplify Sum (2)

The last post showed how to compute simple addition expressions. To provide a more structured approach to the problem at hand, I decided to write a small Prolog program that actually recognizes such addition expressions. This program basically represents a Prolog conversion of the grammar underlying such addition expressions. Because Prolog notation and grammer are so close, I will not comment on the following Prolog clauses. addition_expression (A) :- sum_term (A). addition_expression (A) :- A = X + Y, addition_expression (X), sum_term (Y). sum_term (X) :- number (X). sum_term (X) :- atom (X). sum_term (X) :- prod_term (X). prod_term (X) :- X = A * B, number (A), atom (B). prod_term (X) :- X = A * B, atom (A), number (B).

Adventures in Prolog - Simplify Sum (1)

Today's post is concerned with (the first part of) an example task from the book "Prolog Programming For Artificial Intelligence" - it is a about the simplification of additive terms using Prolog's facilities to reason about the type of some symbol. For example, Prolog offers the following (and more) built-in predicates: number /1 - is the argumet passed, a number, e.g. number(1) returns true atom /1 - is the passed argument an atom, e.g. atom(x) returns true compound /1 - is the passed argument a compound term, e.g. compound(X+Y) returns true Now, that we know how to inspect the type of some Prolog symbol, we may take a look onto today's task. Given some summation, the task is to simplify this summation, using some predicate called simplify_sum or simp_sum (for short). For example: 1 +2 +3 = 6 1 +a = a +1 a + b + 1 + c = a+ b +c + 1 a + 1 +2 + b = a + b + 3 So in short, the summation should be ordered with atoms first and aggregated numbers last. The original t...

Adventures in Prolog - Computations with lists II

As mentioned in my last post, this post is concerned with building some abstraction when computing with lists. For this, I will abstract the the addList and mulList prodecures into one more general processList procedure. processList will iterate over a list and process it according to some user-defined function. Users of F# might recognize this from F#'s map function offered by a list object. At first we define the processList function. processList takes 4 input parameters - a list, a processing function some identity element and the result. processList processes some input list according to the provided processing function. The identity Identity element is used to process the empty list. The result of this operation is placed into the variable Res . %processList/4 processList ([], F, Identity, Identity) :- functor (_, F, 3). processList ([HT], F, Identity, Res) :- functor (_, F, 2), processList (T, F, Identity, L1), apply (F, [H, L1, Res]). The functor procedure checks ...

Adventures in Prolog - Computations with lists

My last post was concerned with basic computations in Prolog using the powerful technique - recursion. Today's post is concerned with recursion as well, but this time recursion is applied to Prolog's main data structure - the list. A list in Prolog is a recursive data structure itself. Why? Because a list can be built by remembering the following ... 1. the empty list [] is a list 2. a list can be built by appending any list T to an item H, which yields [HT] Using this definition we can see that the list [1, 2, 3, 4] is indeed a list with H = 1 and T = [2, 3, 4]. Consequently, a list cannot only be built from points 1. and 2. but also decomposed according to 1. and 2. Therefore 1. and 2. form the underlying principle when computing with lists in Prolog. Now that we have covered the basic principle underlying a list. I will present two operations on lists - the addition of elements of a list (sumList) and the multiplication of elements of a list (mulList). Both operations make u...

Adventures in Prolog - Simple computations

This time I present a way to calculate the ith power of some integer j (i is also an integer number). Clearly, this is nothing too sophisticated but it will be helpful for some other program, I want to show later on. Power is implemented as a simple ternary relation, which uses recursion. The base cases for power are of course the 0th and 1st power of some integer number. All other powers will be dependant on this anchor. The ith power of j means that j is multiplied with itself i times. For instance, the 3rd power of 2 is eigth, which is 2 * 2 * 2 = 8. This is used to implement the recursive core of power, which is ith power of j is the j * (i-1)th power of j. After the basic power relation, power10 and power2 show how to use existing relations to implement some simple abstractions. %power/3 power (X, 0, 1). power (X, 1, X). power (X, Y, Z) :- Y1 is Y - 1, power (X, Y1, Z1), Z is X * Z1. %power10/2 power10 (P, R) :- power (10, P, R). %power2/2 power2 (P, R) :- power (2, P, R).

Adventures in Prolog - Fibonacci

As I have played around with Prolog lately, I wanted to share some enriching moments with my new favourite pet. We start of with the famous Fibonnaci numbers and their computation in Prolog. To spice things up, I used the dynamic clause, which enables one to add clauses to an existing database. :- dynamic (fib/2). fib (0, 1). fib (1, 1). fib (F, X) :- F1 is F-1, F2 is F-2, fib (F1, X1), fib (F2, X2), X is X1 + X2, asserta (fib(F, X)). So what does this listing do? Clearly, it computes the ith value of the Fibonacci sequence using recoursion. Therefore, the recoursion anchor - 1st and 0th value - of the sequence is established first. After that the definition of the sequence is given in its known form. By making the predicate fib/2 dynamic, we can add facts to the list of clauses covering fib/2 . Dynamic has to be executed upon loading the fib database. That is why we write :- dynamic(fib/2). . Now new knowledge about the Fibonnaci values can be added to the database. Th...