I am quite new with Programming in Logic, but it seems to be a great language for querying a data store and storing facts. In many ways it is so similar to SQL, and in many cases, I am sure, it would be much more convenient. Read Logic Programming with Perl and Prolog if you want an introduction to Prolog with some Perl modules or Other online Prolog tutorials to learn more about the power of programming in logic. So why there are no databases built to support Prolog? Is it too difficult?

At least with Perl you can dump your database as a Prolog program:

use strict; use DBIx::Class::Loader; use AI::Prolog; my $loader = DBIx::Class::Loader->new( dsn => $ARGV[0], user => $ARGV[1], password => $ARGV[2], namespace => 'Data', ); my $prog; for my $c ( $loader->classes ) { my $rs = $c->search(); $prog .= '% ' . join ( ',', $c->columns ) . "\n"; while ( my $row = $rs->next ){ $prog .= $c->table . '('; my @quoted = map {AI::Prolog->quote($row->$_)} $c->columns; $prog .= join ',', @quoted; $prog .= ").\n"; } } print $prog;
Let's see what we can get with this from a simple database like this:
create table usr(id integer primary key, name varchar(100), cityid int +eger); create table city (id integer primary key, name varchar(100)); insert into usr values (1, 'John', 1); insert into usr values (2, 'Marry', 1); insert into usr values (3, 'Eva', 2); insert into usr values (4, 'Zby', 3); insert into city values (1, 'New York'); insert into city values (2, 'London'); insert into city values (3, 'Warsaw');
Run the dumper:
perl dump.pl dbi:Pg:dbname=prolog > mytables
What I get in the mytables file is:
% name,id city('New York',1). city('London',2). city('Warsaw',3). % cityid,name,id usr(1,'John',1). usr(1,'Marry',2). usr(2,'Eva',3). usr(3,'Zby',4).
The sequence of columns is not retained by DBIx::Class::Loader - that's why I added the column names in the Prolog comments (lines starting with '%'), this will be usefull for creating the queries. That's our logic database. Now let's query it. I'll run the full SWI prolog engine here and load the above program, I do this because I cannot get AI::Prolog to work with compound queries that I need.
zby@zby:~/progs/prologdata$ swipl Welcome to SWI-Prolog (Multi-threaded, Version 5.2.13) Copyright (c) 1990-2003 University of Amsterdam. SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. Please visit http://www.swi-prolog.org for details. For help, use ?- help(Topic). or ?- apropos(Word). ?- [mytables]. % mytables compiled 0.00 sec, 1,400 bytes Yes ?-
Now the database is loaded, and we can query it. How about a table join? Let's look for all users that are from 'New York'. Now I need the comments that tell me the sequence of columns.
?- usr(Cityid, Name, Id), city('New York', Cityid). Cityid = 1 Name = 'John' Id = 1 ; Cityid = 1 Name = 'Marry' Id = 2 ; No ?-
Great, it found both.

And here is some code you can add to the first program to ask the query at once without saving the intermediate Prolog program. Unfortunately I did not found any way how to do conjunction in the queries (needed for table joins here).

my $prologDB = AI::Prolog->new( $prog ); $prologDB->query( "usr(1,Name,Uid)." ); while (my $results = $prologDB->results) { print "@$results\n"; }

For sure there are other ways how to convert relational databases to logic, I hope other monks here will share their ideas on how to do that and how to use it.

Replies are listed 'Best First'.
Re: Query database in Prolog
by Ovid (Cardinal) on Dec 29, 2005 at 21:09 UTC

    I'll run the full SWI prolog engine here and load the above program, I do this because I cannot get AI::Prolog to work with compound queries that I need.

    This is due to the limited grammar which AI::Prolog supports. Changing your query to a rule will permit this. Add the following rule to the mytables file:

    city_usr(City, Name, Id) :- city(City, City_ID), usr(City_ID, Name, Id).

    Then you can run the shell:

    AI-NeuralNet-Simple-0.03 $ aiprolog mytables.pro Welcome to AI::Prolog v 0.732 Copyright (c) 2005, Curtis "Ovid" Poe. AI::Prolog comes with ABSOLUTELY NO WARRANTY. This library is free so +ftware; you can redistribute it and/or modify it under the same terms as Perl +itself. Type '?' for help. ?- listing. 1. city_usr/3: city_usr(A, B, C) :- city(A, D), usr(D, B, C). 2. usr/3: usr(1, John, 1). usr(1, Marry, 2). usr(2, Eva, 3). usr(3, Zby, 4). 3. city/2: city('New York', 1). city(London, 2). city(Warsaw, 3). listing Yes ?- city_usr('New York', User, ID). city_usr('New York', John, 1) ; city_usr('New York', Marry, 2) ; No ?-

    There are other techniques, but that's the easiest.

    As for why databases don't support Prolog, there are a variety of reasons for that. The primary reason is that DBMS don't really handle the relational model all that well. Queries frequently return bags instead of sets, SQL does not handle recursion well -- a core requirement of Prolog -- and Prolog allows lists, something databases also don't handle well for a single column.

    Querying databases is something I would like to have in AI::Prolog, but in a more general nature. However, what if you've retrieved 15 out of 20 results and the engine backtracks over your function? You need to be able to add previous results to the AI::Prolog::KnowledgeBase and fetch them from there, if appropriate. Only if they are not found should subsequent results be pulled from the database.

    To handle this, we'd need some way of registering external functions and having them call the correct primitive from AI::Prolog::Engine::Primitives (a primitive for external functions would need to be added). There's also the question of side effects. What happens when you backtrack over a predicate which deletes file? diotalevi and I have discussed much of this, but regrettably, I'm terribly busy at work and don't have time to work on this.

    Cheers,
    Ovid

    New address of my CGI Course.

      What I was imagining was using Prolog in place of RDBMS. That is a prolog engine to which you could connect using an analogue to ODBC, store facts there and query them. But this means you need a way to delete the facts as well - I don't know how this can be added to the Prolog computational model. I just started with Prolog and I don't really understand your sentence about backtracking over query results - but I think that backtracking in this environment would have to be limited by a transaction boundary.

        In reality, deleting facts is generally not something one wants to do as it's considered a "non-logical" operation. However, you can use retract/1 if you really need to:

        AI-NeuralNet-Simple-0.03 $ aiprolog Welcome to AI::Prolog v 0.732 Copyright (c) 2005, Curtis "Ovid" Poe. AI::Prolog comes with ABSOLUTELY NO WARRANTY. This library is free so +ftware; you can redistribute it and/or modify it under the same terms as Perl +itself. Type '?' for help. ?- help('retract/1') retract/1 Remove facts from the database. You cannot remove rules. This may change in the future. See assert(X). retract(loves(ovid,java)). help(retract/1) Yes ?-

        You can also just type "help" at the aiprolog prompt to see a list of all built-in predicates you can get help for:

        ?- help. Help is available for the following builtins: !/0 assert/1 call/1 consult/1 div/2 eq/2 fail/0 ge/2 gt/2 halt/1 if/3 is/2 le/2 listing/0 listing/1 lt/2 minus/2 mod/2 mult/2 ne/2 nl/0 not/1 notrace/0 once/1 or/2 plus/2 pow/2 print/1 println/1 retract/1 trace/0 true/0 var/1 write/1 writeln/1 help Yes ?-

        If you really want to get a decent grounding in Prolog, see Amzi's "Adventure in Prolog". It's a free online book which lets guides through building four different Prolog applications. It's quite cool. Most of the basics work in AI::Prolog, but it could still use a lot of work/patches.

        Cheers,
        Ovid

        New address of my CGI Course.

Re: Query database in Prolog
by diotalevi (Canon) on Dec 29, 2005 at 19:52 UTC

    [Added: Prolog SQL has some good info. You should definately avoid re-inventing a wheel. The real Prolog people have already been hacking on this problem.]


    I was thinking about this yesterday. It seemed most natural that you'd patch AI::Prolog to be able to query this stuff. You might want to introduce a new built-in function to represent joins. You've got a problem in that SQL relations have no order to columns so you'll either need to ignore that or instruct AI::Prolog in what order to read columns when querying the database.

    % A "normal" lookup city('New York', Cityid), usr(Cityid, Name, Id). % An id-less query. Maybe the engine notices the join and transforms t +his into the prior behind the scenes. % Maybe an invented built-in like references/4 cause the transformatio +n. :- references( 'USR', 'CITY_ID', 'USR', 'CITY_ID' ). usr( city( 'New York' ), Name ).

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

      I plan to patch DBIx::Class to retain the order, but I think about other possibilities as well.

        "Retain" the order? The db provides no order!

        ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊