Reputation: 141
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:
:-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?
The first set of rules says that "there exists a student whose id is 1 and name is mike":
and "two students with the same id should have the same name and age" (which is a key constraint):
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":
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
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