What is a good Prolog representation for tables with order-insensitive attribute in a relational db?

173 views
Skip to first unread message

Rex

unread,
Oct 9, 2014, 2:40:09 PM10/9/14
to swi-p...@googlegroups.com
To map facts stored as tables with their attributes in a relational database to Prolog facts, each table is an object, and one can naturally choose table names as predicate names, with their attributes as parameters of the corresponding predicate.

But the question is, attributes in a table, say SQL table, are order-insensitive, while the parameters of a predicate is order sensitive. p(a,b,c) != p(b,a,c).

What I can think for such a representation is to represent all facts as
tableName(attribute1(PK, value)).
tableName(attribute2(PK, value)).

...

where PK is the PrimaryKey of the table,
and do a query using Answer Set Prolog (AnsProlog), which allows us to define conjunction of predicates in the head:
tableName(attribute1(PK, value)), tableName(attribute2(PK, value)).


Is there any better Prolog representation for this? I wish to use SWI-Prolog.


Jan Wielemaker

unread,
Oct 9, 2014, 2:55:46 PM10/9/14
to Rex, swi-p...@googlegroups.com
I would definitely store the raw data as p(a,b,c). It is the most compact
representation and it fully exploits (JIT) indexing. How you _access_ it
is another matter. You could exploit SWI7 dicts and write

....,
p{a:A, b:B, c:C},
....

That would also allow for writing the following, indicating that order
is not important and you can omit columns you don't care about.

p{c:C, b:B}

Now, how does this work? Dicts are not valid goals by themselves. You
can however use goal_expansion/2 to turn them into a valid goal:

goal_expansion(Dict, Goal) :-
is_dict(Dict, p), % Dict is p{...}
Dict :< _{a:A,b:B,c:C}, !,
Goal = p(A,B,C).

Note that this gives you a similar result as ECLiPSe, which provides
read macros that allow you to declare that p{k:v, ...} maps to a term
p(...)

The only price is that, if you create p{...} dynamically, you cannot
call it. You must do expand_goal(p{...}, Goal), call(Goal).

Dicts are a quite elegant solution to this, but of course you can
also define that p(a=>A, b=>B, ...) serves this purpose using the
same goal expansion technique.

Hope this helps

--- Jan

Rex

unread,
Oct 14, 2014, 4:37:49 AM10/14/14
to swi-p...@googlegroups.com
Jan,

That's quite helpful! It is very convenient to use dicts here.

One further question is for the case when two or more attributes contain multiple values, then we need (m x n x k) lines to represent one record, where "m, n, k,.." are the number of multiple values of corresponding attributes of a record.

With my early representation as follows,
tableName(attribute1(PK, value)).
tableName(attribute2(PK, value)).


it only takes (m+n+k+...) lines to represent a record. But as Jan mentioned, this representation will not benefit from the JIT indexing.

Can we store multiple values of an attribute as a list in the dict?
for example,
   p{a:[A1, A2, A3], b:[B1, B2], c:[C]}.

Jan Wielemaker

unread,
Oct 14, 2014, 4:58:32 AM10/14/14
to Rex, swi-p...@googlegroups.com
On 10/14/2014 10:37 AM, Rex wrote:
> Jan,
>
> That's quite helpful! It is very convenient to use dicts here.
>
> One further question is for the case when two or more attributes contain
> multiple values, then we need (m x n x k) lines to represent one record,
> where "m, n, k,.." are the number of multiple values of corresponding
> attributes of a record.
>
> With my early representation as follows,
> tableName(attribute1(PK, value)).
> tableName(attribute2(PK, value)).
>
> it only takes (m+n+k+...) lines to represent a record. But as Jan
> mentioned, this representation will not benefit from the JIT indexing.
>
> Can we store multiple values of an attribute as a list in the dict?
> for example,
> p{a:[A1, A2, A3], b:[B1, B2], c:[C]}.

I didn't suggest using dicts for storing, but for providing a nice
frontend to the programmer. I think you got that though. Yes, you
can store values as

tableName(object, attribute, [value1, value2, ...])

That is fine if you don't want to ask the question "Which object has
value X as attribute?". If you do want to answer that question quickly,
you'll need

tableName(object, attribute, value1).
tableName(object, attribute, value2).

Of course, you also have this, which might be interesting if you have
high-arity tables. It all depends on the data, the ways you want to
access it and the famous time/space tradeof.

tableName(object, attribute, record0001).

value(record0001, value1).
value(record0001, value2).
...

That is why it is wise to abstract the access from the concrete
datastructure. That also allows you to move to an external DB,
the RDF db, etc.

Cheers --- Jan
> --
> You received this message because you are subscribed to the Google
> Groups "SWI-Prolog" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to swi-prolog+...@googlegroups.com
> <mailto:swi-prolog+...@googlegroups.com>.
> Visit this group at http://groups.google.com/group/swi-prolog.
> For more options, visit https://groups.google.com/d/optout.

Rex

unread,
Oct 21, 2014, 1:39:36 AM10/21/14
to swi-p...@googlegroups.com
Dear Jan,

Dict in SWI-Prolog v7 is very powerful!

For a general application of goal_expansion of Dicts, say, we have hundreds of Dicts with different attributes.
How to express the goal_expansion in a general form, so that we don't need to write hundreds of goal_expansions as follows?


goal_expansion(Dict, Goal) :-
        is_dict(Dict, p),        % Dict is p{...}
        Dict :< _{a:A,b:B,c:C}, !,
        Goal = p(A,B,C).

Thank you again!



On Thursday, October 9, 2014 11:55:46 AM UTC-7, Jan Wielemaker wrote:

Jan Wielemaker

unread,
Oct 21, 2014, 4:16:10 AM10/21/14
to Rex, swi-p...@googlegroups.com
On 10/21/2014 07:39 AM, Rex wrote:
> Dear Jan,
>
> Dict in SWI-Prolog v7 is very powerful!
>
> For a general application of goal_expansion of Dicts, say, we have
> hundreds of Dicts with different attributes.
> How to express the goal_expansion in a general form, so that we don't
> need to write hundreds of goal_expansions as follows?
>
> goal_expansion(Dict, Goal) :-
> is_dict(Dict, p), % Dict is p{...}
> Dict :< _{a:A,b:B,c:C}, !,
> Goal = p(A,B,C).

You will need some kind of declaration that tells you which predicates
have which column names. So, first figure out how you would like to
write that information down (or get it from somewhere). Then you can
either generate the goal_expansion/2 clauses or write a more general one
that uses the declarations written down elsewhere. Note that the use of
goal_expansion/2 only affects compilation speed. So, for most
not-really-large applications, the performance doesn't matter very much.

In any case, the idea behind Prolog is to first think how you would like
the problem to be represented. In other words, what you would like to
type and read. You are only limited by the Prolog syntax, although
SWI-Prolog's quasi quotations allow you to embed fragments with a
totally different syntax in your source as well. Then you write a
transformation or meta-interpretation layer that makes it work.

Cheers --- Jan
Reply all
Reply to author
Forward
0 new messages