Variables in Answer Set Programming
Date: Fri, 31 Dec 2004
From: Vladimir Lifschitz
To: TAG
I'm thinking these days about the use of variables in ASP programs. Here
is a simple program with variables in the input language of lparse:
a(1).
{b(X):a(X)}.
The second rule means, intuitively, that b is an arbitrary subset of a, and
smodels tells us that this program has two answer sets:
Answer: 1
Stable Model: a(1)
Answer: 2
Stable Model: b(1) a(1)
Consider now the following program P:
a(1).
a(2) :- b(1).
{b(X):a(X)}.
lparse doesn't accept P as correct input, and this is related to the fact,
I think, that P is not omega-restricted (Tommi Syrjanen, "Omega-restricted
Logic Programs", in Proc. LPNMR-01). I'm wondering whether refusing to
define the concept of an answer set for programs like P is a reasonable
semantic choice.
I expect that P will have 3 answer sets
a(1)
a(1), a(2), b(1)
a(1), a(2), b(1), b(2)
once we give an appropriate definition of an answer set for programs with
variables. I don't know what this definition will look like, but here are
some observations and questions that may help us invent it.
1. If we rewrite the last rule of P as
{X:b(X)} subset {X:a(X)}
we'll get, I think, a program in the language ASET ("A-Prolog with sets")
defined and implemented by Michael Gelfond and his students. Is it
meaningful and executable in ASET?
2. If we rewrite the last rule of P as
b(X); not b(X) :- a(X)
the result P' will be a program with nested expressions, except that
we need to decide how to ground it. I suspect that if we choose *any*
set of symbols that includes 1 and 2, and ground P' by substituting
these symbols for X, the answer sets for the resulting ground program
will be always the sets shown above. In this sense, P' is "domain
independent."
3. P' can be also viewed as a formula of first-order equilibrium logic
that David Pearce is working on. What is the status of P' in that logic?
Please share with me your thoughts about P and about the semantics of
variables in answer set programming in general.
======
Date: Fri, 31 Dec 2004
From: Michael Gelfond
To: Vladimir Lifschitz
Program
a(1).
a(2) :- b(1).
{X:b(X)} subset {X:a(X)}
of ASET has three answer sets:
a(1).
b(1),a(1),a(2).
b(1),b(2),a(1), a(2).
Intuitively, 'b' is an arbitrary subset of 'a' which is defined
by rules 1 and 2 of the program. (in a sense the definition
is mutually recursive)
The answer sets are reasonably in tune with the intuitive
meaning of rules.
I do not have ASET on my computer so cannot check now
but it should be executable.
I do not really know if the program is meaningful.
I do not remember such recursive definitions in mathematics.
Does anyone? In my programs I usually define 'a' and after that
say "let 'b' be a subset of 'a'. ''
(i.e. in ASET the problem is not really that closely realated to "treatment
of variables" . Rather it is about which definitions of sets are useful.)
======
Date: Sat, 1 Jan 2005
From: Vladimir Lifschitz
To: Michael Gelfond
One more observation: we can rewrite the last rule of P
{b(X):a(X)}
as the disjunctive rule
b(X) v c(X) :- a(X)
(intuitively, c is the complement of b) and execute the program under dlv.
Then we'll get three answer sets similar to those shown in your message:
{a(1), b(1), a(2), c(2)}
{a(1), b(1), a(2), b(2)}
{a(1), c(1)}
> I do not really know if the program is meaningful.
> I do not remember such recursive definitions in mathematics.
> Does anyone? In my programs I usually define 'a' and after that
> say "let 'b' be a subset of 'a'. ''
> (i.e. in ASET the problem is not really that closely realated to "treatment
> of variables" . Rather it is about which definitions of sets are useful.)
It seems to me that even if programs like P are not useful, it may be a good
idea to aim at a semantics of programs with variables that is applicable to
P and to other programs that are not omega-restricted. An attempt to define
a more general semantics may lead to a *simpler* semantics. There was a time,
for instance, when the best available semantics of negation as failure was
the iterated fixpoint semantics for stratified programs. Stratifications
are messy. Even if all useful programs were stratified, aiming at a
semantics that doesn't rely on stratifications would have been a good idea:
the definitions of the well-founded model and of stable models are simpler,
besides being more general.
======
Date: Sun, 2 Jan 2005
From: Michael Gelfond
To: Vladimir Lifschitz
Interesting.
This transformation seems to be rather general.
Is it equivalent (modulo new predicate symbols)
to {b(X) : a(X)} where 'a' is 'legal' from thev stanpoint of lparse?
> It seems to me that even if programs like P are not useful, it may be a good
> idea to aim at a semantics of programs with variables that is applicable to
> P and to other programs that are not omega-restricted. An attempt to define
> a more general semantics may lead to a *simpler* semantics. There was a time,
> for instance, when the best available semantics of negation as failure was
> the iterated fixpoint semantics for stratified programs. Stratifications
> are messy. Even if all useful programs were stratified, aiming at a
> semantics that doesn't rely on stratifications would have been a good idea:
> the definitions of the well-founded model and of stable models are simpler,
> besides being more general.
I agree. It may lead to a simpler semantics.
However the first thing we did after reading the stratification
paper was to look for meaningful examples of non-stratified programs.
It was useful too.
One more comment:
You say that 'intuitively, the rule {b(X):a(X)} says that 'b' is an arbitrary
subset of 'a'.
It seems to me that according to this reading the program P
a1(1).
a2(2).
{b(X) : a1(X)}
{b(X) : a2(X)}
should have one answer set {a1(1),a2(2)}.
Smodels however will produce four of them.
This was one of the reasons I introduced ASET.
======
Date: Sun, 2 Jan 2005
From: Paolo Ferraris
To: TAG
My way of understanding a rule of the form
{b(X):a(X)} :- body (1)
is as the following rule
{b(X)} :- a(X), body. (2)
(This is Vladimir's second proposal, except that here I am not
considering (2) as a rule with nested expressions.)
Some nice properties of this characterization are that (2), at least
when body is empty, is "domain independent" as Vladimir said, and it
seems to me that, when (1) and (2) can be grounded by lparse, two
strongly equivalent sets of rules are generated.
However, this characterization doesn't seem to make things easier for
lparse: by taking Vladimir's example, lparse cannot ground
a(1).
a(2) :- b(1). (3)
{b(X)} :- a(X).
It doesn't even ground the following program equivalent to (3) that does
not contain choice rules:
a(1).
a(2) :- b(1).
b(X) :- a(X), {not b(X)} 0.
======
Date: Mon, 3 Jan 2005
From: Vladimir Lifschitz
To: Paolo Ferraris
> My way of understanding a rule of the form
>
> {b(X):a(X)} :- body (1)
>
> is as the following rule
>
> {b(X)} :- a(X), body. (2)
You are right, in this case X can be equivalently treated as a "global"
variable. But there are cases, I think, when it's not clear how to get
rid of local variables:
a(1).
a(2) :- b(1).
1 {b(X):a(X)}.
(The last rule means, intuitively, that b is an arbitrary nonempty subset
of a.) Do we know how to define the concept of an answer set for programs
like this? I would expect two answer sets in this example:
a(1), a(2), b(1)
a(1), a(2), b(1), b(2)
======
Date: Mon, 3 Jan 2005
From: Monica Nogueira
To: TAG
As you may recall, the Lparse manual (pp.29) states that a previous
parser, "parse", would accept and ground programs containing (positive)
non-domain predicates in the body of the rules. More specifically, I think,
it accepted what today is called weakly restricted variables.
That was discontinued with lparse because of implementation/performance
issues.
When writing program P, I would add a "dumb" domain predicate to 'guide'
the grounding process, as follows:
grd(1..2).
a(1).
a(2) :- b(X).
{b(X)} :- a(X), grd(X).
hide grd(X).
As expected, this program is accepted and grounded by lparse, and
has the following answer sets:
1. a(1)
2. b(1) a(1) a(2)
3. b(1) a(1) b(2) a(2)
It's clear that this is no solution to general cases or large programs.
But it can be useful if one wants to check the models computed by
such a program.
Michael wrote:
> It seems to me that according to this reading the program
>
> a1(1).
> a2(2).
> {b(X) : a1(X)}.
> {b(X) : a2(X)}.
>
> should have one answer set {a1(1),a2(2)}.
> Smodels however will produce four of them.
I'm not sure why a unique answer set in this case.
Would you mind to elaborate?
======
Date: Mon, 3 Jan 2005
From: Michael Gelfond
To: Monica Nogueira
Rule 3 says that 'b' is a subset of a1.
Rule 4 says that it is a subset of a2.
The only set which satisfies both conditions is the empty set.
So 'b' is empty.
======
Date: Mon, 3 Jan 2005
From: Vladimir Lifschitz
To: Michael Gelfond and Monica Nogueira
Here is how I understand this. Reading the rule
{b(X) : a1(X)}.
as "b is an arbitrary subset of a1" implicitly assumes that the program
has no other rules with b in the head. So in the presence of the rule
{b(X) : a2(X)}.
this reading is not acceptable. This is similar to how definitions work
in logic programming. Reading the pair of rules
q(X,Y) :- p(X,Y).
q(X,Z) :- q(X,Y), q(Y,Z).
as "q is the transitive closure of p" implicitly assumes that the program
has no other rules with q in the head.
======
Date: Mon, 3 Jan 2005
From: Paolo Ferraris
To: Vladimir Lifschitz
>You are right, in this case X can be equivalently treated as a "global"
>variable. But there are cases, I think, when it's not clear how to get
>rid of local variables:
>
> a(1).
> a(2) :- b(1).
> 1 {b(X):a(X)}.
>
>(The last rule means, intuitively, that b is an arbitrary nonempty subset
> of a.) Do we know how to define the concept of an answer set for programs
> like this? I would expect two answer sets in this example:
>
> a(1), a(2), b(1)
> a(1), a(2), b(1), b(2)
I agree. I think that it may be convenient to consider rule
1 {b(X):a(X)}.
as a shorthand for
{b(X):a(X)}.
:- {b(X):a(X)} 0.
and similarly for any choice rule with nontrivial bounds in the head.
In this way, local variables in the language of lparse can be explained
if we understand the meaning of
- variable X in rules of the form
{b(X):a(X)} :- body.
and
- local variables in cardinality constraints that are in the body of rules.
Local variables of this second kind are still unclear to me.
======
Date: Mon, 3 Jan 2005
From: Vladimir Lifschitz
To: Monica Nogueira
> It's clear that this is no solution to general cases or large programs.
I'd like to understand limitations of your trick with "dumb domain
predicates." What would be an example of an lparse program that
intuitively seems meaningful but does not seem to be translatable,
using tricks like this, into a program that lparse can ground? Take,
for instance, my last example
a(1).
a(2) :- b(1).
1 {b(X):a(X)}.
Or we can rewrite this program in the form suggested by Paolo:
a(1).
a(2) :- b(1).
{b(X)} :- a(X).
:- {b(X):a(X)} 0.
Can we "massage" it into a form accepted by lparse using auxiliary
predicates?
======
Date: Mon, 3 Jan 2005
From: Vladimir Lifschitz
To: Michael Gelfond
e
> Interesting.
> This transformation seems to be rather general.
> Is it equivalent (modulo new predicate symbols)
> to {b(X) : a(X)} where 'a' is 'legal' from thev stanpoint of lparse?
I suspect that the answer is yes.
CONJECTURE. Take any program with nested expressions containing a rule of
the form
p ; not p <- Body (*)
where p is an atom. Replace (*) with
p ; q <- Body
where q is a new atom. Then the answer sets for the new program are
identical to the answer sets for the old program with q added to those
that don't contain p.
To see how this conjecture is related to your question, note that (*) is
a possible way to understand
{p} <- Body
according to the paper by Ferraris and Lifschitz "Weight constraints as
nested expressions," TPLP Vol. 5(1&2) (CoRR: cs.AI/0312045).
======
Date: Sat, 15 Jan 2005
From: Gerald Pfeifer
To: TAG
Wouldn't it be better if someone invested time to remove those limitations
Lparse currently has instead of continuously pondering on how to work
around them?
I believe it has been sufficiently proven that one can implement an
efficient (both in terms of run-time and size of the generated grounding)
instantiator for ASP programs without requiring domain predicates.
People really seem to like choice rules, so I wonder whether one rainy
weekend I should add (some form of) these to DLV?
Then you could write the second variant of the first program as
a(1).
a(2) :- b(1).
{b(X)} :- a(X).
:- #count{X : b(X)} < 1.
instead of the following which uses standard ASP plus DLV's aggregates:
a(1).
a(2) :- b(1).
b(X) v nb(X) :- a(X).
:- #count{X : b(X)} < 1.
If someone is interested, sending me a specification of such a new
extension (and translations into standard ASP+DLV's aggregates) might
speed this up. ;-)
======
Date: Sun, 16 Jan 2005
From: Veena Mellarkod
To: Vladimir Lifschitz
The program:
---------------------------
a(1).
a(2) :- b(1).
{X:b(X)} subset {X:a(X)}.
compute 0, {}.
show a.
show b.
---------------------------
is executable in ASET and the answer sets
returned by ASET are:
Answer Set #1 : a(1)
Answer Set #2 : a(1) a(2) b(1)
Answer Set #3 : a(1) a(2) b(1) b(2)
---------------------------
======
Date: Thu, 20 Jan 2005
From: Vladimir Lifschitz
To: Veena Mellarkod
Thank you for checking this. I'd like to understand how the computational
process is organized. Marcello called ASET a "front-end" in one of his
messages. It's a front-end for what program? Does its output serve as
input for the usual lparse? Or is its output a grounded program that can
be directly fed into smodels?
======
Date: Thu, 20 Jan 2005
From: Vladimir Lifschitz
To: Gerald Pfeifer
> Wouldn't it be better if someone invested time to remove those limitations
> Lparse currently has instead of continuously pondering on how to work
> around them?
Maybe you are right. But my main point is that this is not merely the
question of extending lparse. It seems to me that we didn't yet see a
definition of "correct grounding" for a class of programs in the
language of lparse that includes my examples. We don't know how to define
the concept of a "good" ("groundable") program in the language of lparse
that would be wider than "omega-restricted." In other words, we'll need
to do some theoretical work first, to define a specification for such an
extended lparse.
Or maybe I am wrong, and we can try to understand the meaning of
non-omega-restricted rules in the language of lparse by rewriting
them in the language of dlv. Take an lparse rule with "conditional
literals" in the body, such as
:- {p(X,Y) : a(X)} 0, b(Y).
It means: for every Y from b, the set of all X's from a such that p(X,Y)
belongs to the answer set is not allowed to be empty. How would you
express this in the language of dlv?
> People really seem to like choice rules, so I wonder whether one rainy
> weekend I should add (some form of) these to DLV?
>
>
> Then you could write the second variant of the first program as
>
> a(1).
> a(2) :- b(1).
>
> {b(X)} :- a(X).
> :- #count{X : b(X)} < 1.
>
> instead of the following which uses standard ASP plus DLV's aggregates:
>
> a(1).
> a(2) :- b(1).
>
> b(X) v nb(X) :- a(X).
> :- #count{X : b(X)} < 1.
It seems to me that the need to use auxiliary predicates, such as nb,
which are typically not needed anywhere else in the program, is a blemish on
the input language of dlv that would be easy to remove. Please do this
one rainy weekend!
> If someone is interested, sending me a specification of such a new
> extension (and translations into standard ASP+DLV's aggregates) might
> speed this up. ;-)
For grounded programs something like this is done in the paper
Paolo Ferraris, Answer sets for propositional theories,
http://www.cs.utexas.edu/users/otto/papers/proptheories.ps .
It shows how the choice construct and all the main elements of the
language of dlv except for variables (that is, disjunctive heads and
aggregates) can be treated as syntactic sugar, once we extended the
definition of an answer set to propositional formulas.
======
Date: Thu, 20 Jan 2005
From: Veena Mellarkod
To: Vladimir Lifschitz
There are 2 parts to ASET computational process (similar to lparse-smodels).
1. Grounder
2. Inference Engine
Given an ASet-Prolog program P:
The grounder uses a prolog program (set_parse) to rewrite set-literals and
function-literals in P in a way that lparse could ground P. After
grounding, the set-literals and function-literals are added back to
ground(P).
The inference engine is similar to smodels but computes answer sets for
ground ASet-Prolog programs.
======
Date: Thu, 20 Jan 2005
From: Vladimir Lifschitz
To: Veena Mellarkod
Okay, so ASET works like this:
your standard adding set-literals your inference engine
-> set_parse -> lparse -> and function-literals -> (similar to smodels) ->
Is this right?
If so, here is my question: if the input of set_parse is our program
a(1).
a(2) :- b(1).
{X:b(X)} subset {X:a(X)}.
compute 0, {}.
show a.
show b.
then what is its output, what is the program that set_parse asks lparse
to ground?
The reason I am interested in this is that your set_parse is apparently
capable of translating our program into the language of lparse without
making it "non-omega-restricted" -- that's the kind that lparse refuses to
ground. And I'm curious how this is done.
======
Date: Wed, 26 Jan 2005
From: Veena Mellarkod
To: Vladimir Lifschitz
set_parse has 3 main procedures: transform1, ground and transform2.
transform1 replaces all sets with newly generated A-Prolog predicates
containing the free variables as arguments. It also records the changes.
For our program:
a(1).
a(2) :- b(1).
{X:b(X)} subset {X:a(X)}.
compute 0, {}.
show a.
show b.
The output of transform1 is:
a(1).
a(2):-b(1).
my_new_atom1.
b(1):-not my_temp_atom,b(1).
my_temp_atom:-not b(1),b(1).
The rule "my_new_atom1." represents the 3rd rule in our program. The last
two rules of the output are introduced so that lparse does not remove b(1)
as false.
This output is the input to ground procedure. The ground calls lparse and
the result of the lparse is the output of ground. The transform2 procedure
uses the recorded changes by transform1 and re-inserts the sets with
proper grounding of the free variables. This output is the input to
inference engine.
======
Date: Mon, 31 Jan 2005
From: Vladimir Lifschitz
To: Veena Mellarkod
Thank you for explaining how ASET uses LPARSE.
It looks like ASET "tricks" LPARSE into doing what it needs. Here is what
I mean. Among other things that it does, LPARSE simplifies its input in
various ways. For instance, if an atom doesn't occur in the heads of the
rules of the input program then LPARSE drops this atom from the bodies of
all rules; it knows that this transformation doesn't change the meaning of
the program. But LPARSE is not clever enough to notice that dropping
trivial rules such as
b(1):-not my_temp_atom,b(1).
doesn't change the meaning of the program either. This is why the last two
rules in the output of transform1 have the desired effect.
======
Date: Sun, 6 Feb 2005
From: Gerald Pfeifer
To: Vladimir Lifschitz
> Among other things that it does, LPARSE simplifies its input in
> various ways. For instance, if an atom doesn't occur in the heads of the
> rules of the input program then LPARSE drops this atom from the bodies of
> all rules; it knows that this transformation doesn't change the meaning of
> the program.
as far as I can see this transformation is only safe when this atom occurs
negated (as a negative body literal). When you make this transformation
and remove a positive body literal, you may well change the semantics of
the program.
Consider the program following, which has the empty answer set:
a :- b.
If you remove b, which does not occur in the head of any rule, from the
body of this rule, we will get {a} as an answer set.
======
Date: Sun, 13 Feb 2005
From: Vladimir Lifschitz
To: Gerald Pfeifer
You are right, thanks for the correction. I should have said: replaces the
atom by "false." That amounts to removing the atom when it occurs in the
body negated, and removing the whole role when the it occurs in the body
without negation.