Li Danyuan
Li Danyuan

Reputation: 141

How can I realize key constraints in clingo?

I'm now learning prolog and try to use clingo to model key constraints but have met some troubles, hope someone can give me a hand. Here are my problems:

  1. I want to build a key constraint and write something like the following in clingo
:-stu(X,Y1,Y2),stu(X,Z1,Z2),not(Y1=Z1,Y2=Z2).

as an integrity constraint but get a syntax error. I tried another way to put it and it seemed to work.

Y1=Z1:-stu(X,Y1,Y2),stu(X,Z1,Z2).
Y2=Z2:-stu(X,Y1,Y2),stu(X,Z1,Z2).

But still I wonder if I can put the seperated constraints together into just one key constraint so to make the program more concise?

  1. Another problem is about how to build fact 'there exists something' in clingo, what I want to achieve is to use clingo to judge if two given sets of rules are satisfiable or not, and here is an example.

The first set of rules says that "there exists a student whose id is 1 and name is mike":

enter image description here

and "two students with the same id should have the same name and age" (which is a key constraint):

enter image description here

So I write the first set of rules in Clingo as:

stu(1,"mike",v).
:-stu(X,Y1,Y2),stu(X,Z1,Z2),(Y1,Y2)!=(Z1,Z2).

Suppose the second set of rules is given which says that "there exists a student whose id is 1 and age is 27":

enter image description here

and the second set of rules is written in Clingo as:

stu(1,v,27).

My problem is that if simply put these two sets of rules in a program, Clingo will judge that they can not be satisfiable cause ("mike",v) != (v, 27). So there must be something wrong with my solution (probably with the way to build existence), because the two sets of rules are actually satisfiable if you have a student with id = 1, name = "mike" and age = 27. I wonder if there is a way to use Clingo to judge satisfiability of two sets of rules like mentioned above, thanks!

Upvotes: 0

Views: 459

Answers (1)

Max Ostrowski
Max Ostrowski

Reputation: 623

If you want to post an integrity constraint using a tuple comparison

:-stu(X,Y1,Y2),stu(X,Z1,Z2), (Y1,Z2)!=(Z1,Z2).

is probably what you want to write.

A rule like

Y1=Z1:-stu(X,Y1,Y2),stu(X,Z1,Z2).

is equivalent to

:-stu(X,Y1,Y2),stu(X,Z1,Z2), Y1!=Z1.

To answer your second question:

Seperate the age and the name into two predicates. You introduced an arbitrary "v" as a placeholder holder for "not given" which is the reason for your problems. None of your problems exist, and it is also much cleaner style if it possible to not have a name or age.

stu_name(123,"steve").
stu_age(123,42).
% it is not possible to have the same ID but different names
:- stu_name(ID,Name1), stu_name(ID,Name2), Name1 != Name2.
% it is not possible to have the same ID but different ages
:- stu_age(ID,Age1), stu_age(ID,Age2), Age1 != Age2.

Seperating name and age allows you to not have one of the two entries. When you use the ternary stu(ID,Name,Age) predicate you actually always have to give a Name AND and age ("v" isnt something magical, it will be interpreted as name or age)

To avoid several studens with the same id, you could write:

stu(123,"Anne",30).
stu(123,"Mia",14).
% it is not possible to have the same ID but not completely equal entries
:- stu(ID,Name1,Age1), stu(ID,Name2,Age2), (Name1,Age1)!=(Name2,Age2).

Upvotes: 1

Related Questions