Action Languages and Elaboration Tolerance, Part 2 Date: Wed, 19 Sep 2001 From: Vladimir Lifschitz To: Michael Gelfond After reading your last message, I understand your approach a lot better. I'll try to describe, first of all, my current understanding of your method, and please tell me if anything here is incorrect. ============================================================================= I. If we want to formalize the original form of MCP and don't care about elaboration tolerance, this can be done in action language B. In such a formalization, the requirement that missionaries be not outnumbered by cannibals is expressed by a static law that corresponds to the logic programming constraint :- time(T), num(N), num(N1), gt(N,N1), gt(N1,0), h(located(cannibal,N),T), h(located(missionary,N1),T). II. If, however, we want to be better prepared to formalize elaborations of MCP, then we should use a more expressive action language B+. Besides inertial fluents available in B, this extension has also symbols for non-inertial fluents. Besides static and dynamic laws, in B+ we can also write propositions of a new kind -- "defaults". This feature allow us to improve the formalization of the requirement mentioned above. The new formalization uses the non-inertial fluent harmless, which is essentially an abnormality predicate. It includes a default expressing that this fluent is normally false. The requirement that missionaries be not outnumbered by cannibals is expressed now by a static law that corresponds to the constraint with an additional atom in the body: :- time(T), num(N), num(N1), gt(N,N1), gt(N1,0), h(located(cannibal,N),T), h(located(missionary,N1),T), nh(harmless,T). This modification leaves the transition diagram essentially unchanged -- it is still a formalization of the original MCP. But now we are ready for the next step. III. To disable the restriction on the number of missionaries and cannibals in the case when cannibals have been converted, we simply add a static law that corresponds to the rule h(harmless,T) :- time(T), h(converted,T). ============================================================================= Now here is where I see a problem with this method. The claim that the modification described in Part II leaves the transition diagram essentially unchanged seems to be incorrect. According to the semantics of B+, states are defined in the same way as in B: a state is a consistent and complete collection of fluent literals which is closed under the static rules. Consequently, nothing prevents fluent harmless from being true. Replacing formalization I by formalization II adds many new states to the transition diagram; the states in which harmless is false correspond to the states in the original formalization, and the states in which harmless is true are new states, which are rather peculiar. These strange states cannot result from executing any action. If we try to execute the wait action in such a state, we may find that it is nonexecutable; if it is executable, the result will be a different state -- harmless will change its value from true to false. Is this correct? ========= Date: Sun, 23 Sep 2001 From: Michael Gelfond To: Vladimir Lifschitz In the beginning your statements are marked with >>>. >>> Now here is where I see a problem with this method. >>> The claim that the modification described in Part II leaves the >>> transition diagram essentially unchanged seems to be incorrect. I do not think I made such a claim. I maybe missing something though. >>> According to the semantics of B+, states >>> are defined in the same way as in B: a state is a consistent and complete >>> collection of fluent literals which is closed under the static rules. and defaults, of course, which are just a special form of static rules. >>> Consequently, nothing prevents fluent harmless from being true. Replacing >>> formalization I by formalization II adds many new states to the transition >>> diagram; the states in which harmless is false correspond to the states >>> in the original formalization, and the states in which harmless is true are >>> new states, Right. >>> which are rather peculiar. These strange states cannot result >>> from executing any action. >>> If we try to execute the wait action in such a >>> state, we may find that it is nonexecutable; Why? >>> if it is executable, the result >>> will be a different state -- harmless will change its value from true to >>> false. Is this correct? Yes A few comments: I understand that you may find states containing harmless to be strange. I am not so sure myself but notice that we can easily get rid of such states. That is what I was trying to suggest in the beginning of the discussion: Here is a quote from me: >>>>>> Vladimir, as far as I understand you want >>>>>> to expand B by a default statements like >>>>>> 3. Normally F if G (p.s. I named it d) >>>>>> Is that right? >>>>>> If so then I think this can be done simply by expanding >>>>>> B by statements of the form (3) which should be given names >>>>>> and by statements >>>>>> 4. exception(Q,d) >>>>>> which says that Q is an exception to default d. >>>>>> So let d be of the type (3). Then its meaning is >>>>>> 'any state containing G and not containing >>>>>> exceptions to d contains F'. p.s. (Exceptions here are viewed as 'strong' exceptions, i.e. any state containing exception Q also contains ~F. ) I am not sure I made it completely clear though. I was suggesting to consider a new definition of the state. More formally: We say that any collection, S, of literals is 'CLOSED under default d' if S contains F whenever S contains G and does not contain any Q such that exception(Q,d) is in AD. This is different from a standard notion of closure I used before. A STATE of AD is a consistent and complete set of literals closed under 'old' static laws and the defaults of AD. Now we could consider a language, say B++, obtained from B by adding non-inertial fluents and statements of the type (3) and (4) where F is non-inertial. The semantics is again defined by translation to logic programming. (3) and (4) are translated into h(F,T) <-- h(G,T), not ab(d,T). ab(d,T) <-- exception(Q,d), h(Q,T). ~h(F,T) <-- exception(Q,d), h(Q,T). The rest is as in B+. To continue my quote: >>>> So if your action description does not contain 4 then >>>> (G,Q,~F) is not a state. >>>> If 4 is added then it does become a state. Note that if we are given a domain description D consisting of action description AD containing (3) without exceptions and a collection of observations h(G,0). ~h(F,0). then D is inconsistent in B++. If D is viewed as a domain description of B+ then it is consistent. The difference between the semantics of B+ and B++ depends on their understanding of defaults and their exceptions. The approach of B+ assumed that default (3) can be defeated by ~F. The approach of B++ assumed that every default is supplied with a complete list of exceptions and that the default can be defeated only by one of them. You said before: >>>>>My "normally" represents a very strong default. To override it, we have to >>>>>explicitly mention the abnormality predicate. which probably corresponds to the view of B++. I am not sure which is better but I think now that B++ should satisfy your original requirements. Am I right? If so it may be interesting to see what is its relationship with your new C. ========= Date: Sun, 23 Sep 2001 From: Vladimir Lifschitz To: Michael Gelfond It seems to me now that my attempt to summarize your position was inadequate. Part II of my summary doesn't reflect your views correctly, right? Your view is that the action language needed to handle this elaboration by adding rules is language B++, not B+, correct? > > Now here is where I see a problem with this method. > > The claim that the modification described in Part II leaves the > > transition diagram essentially unchanged seems to be incorrect. > > I do not think I made such a claim. I maybe missing something though. No, you didn't. I referred to Part II of my attempt to summarize your position. That summary, as I now see, was inadequate. > > According to the semantics of B+, states > > are defined in the same way as in B: a state is a consistent and complete > > collection of fluent literals which is closed under the static rules. > > and defaults, of course, which are just a special form of static rules. This is something that I am not clear about. First, your description of B+ gave me the impression that defaults in B+ are propositions of a new kind, not a special case of static or dynamic laws. In the description of B+ you wrote: > Transition diagrams (over this signature) are defined by > static and dynamic causal laws as in B, impossibility > conditions, and defaults, i.e. statement of the form > > 'Normally a NON-inertial fluent F has the value true (false)' Second, what do we mean by saying that a set of fluent literals is closed under a default? Recall that we are talking now about B+, not about B++. > > These strange states cannot result from executing any action. > > If we try to execute the wait action in such a > > state, we may find that it is nonexecutable; > > Why? Maybe I am wrong, but here is what I was thinking. Consider a state in which harmless is true, and missionaries are outnumbered on one bank. According to the semantics of B+, will the wait action be executable in this state? > I understand that you may find states > containing harmless to be strange. > I am not so sure myself but notice that we can easily get rid of > such states. Easily, but not until we move from B+ to B++, right? What bothers me is not so much that we get these states, but that we apparently cannot get rid of them without making changes in the definition of the action language. > I think now > that B++ should satisfy your original requirements. I think so too. In the message that started this discussion, I wrote: So here is the source of many of our difficulties: the set of states in the transition diagram denoted by a set of propositions depends on that set monotonically. In a sufficiently expressive action language, this should not be the case. It seems to me that you overcome this difficulty by moving from B and B+ to B++. > If so it may be interesting to see what is its relationship with your new C. As a step in this direction, consider an application of our "new C" -- C with statically determined fluents -- to a problem that is not related to elaboration tolerance. The problem is to give a description of the blocks world such that the set of states of the corresponding transition diagram doesn't include any physically impossible states, in which some blocks form circular configurations in space: on(b1,b2), on(b2,b3), on(b3,b1). In our new C, we can achieve this goal by defining the transitive closure ("above") of the predicate on; then we introduce the constraint requiring that every block be located above the table. But this will only work if the transitive closure is treated as a statically defined fluent; we could not do this in the old C. Can you give such a "perfect" description of the blocks world in B++ ? ======= Date: Tue, 2 Oct 2001 From: Michael Gelfond To: Vladimir Lifschitz M. > and defaults, of course, which are just a special form of static rules. V. > This is something that I am not clear about. You are right. This is complete nonsense. I was probably thinking about B++. You are also right saying that 'wait' maybe non-executable in B+. And I agree that this is unintuitive. M. > I think now that B++ should satisfy your original requirements. V. > I think so too. In the message that started this discussion, I wrote: So here is the source of many of our difficulties: the set of states in the transition diagram denoted by a set of propositions depends on that set monotonically. In a sufficiently expressive action language, this should not be the case. It seems to me that you overcome this difficulty by moving from B and B+ to B++. Good, so we seem to be in agreement. M. > If so it may be interesting to see what is its relationship with > your new C. V. > As a step in this direction, consider an application of our "new C" > -- C with statically determined fluents -- to a problem that is not > related to elaboration tolerance. The problem is to give a > description of the blocks world such that the set of states of the > corresponding transition diagram doesn't include any physically > impossible states, in which some blocks form circular configurations > in space: > > on(b1,b2), on(b2,b3), on(b3,b1). > > In our new C, we can achieve this goal by defining the transitive > closure ("above") of the predicate on; then we introduce the > constraint requiring that every block be located above the table. > But this will only work if the transitive closure is treated as a > statically defined fluent; we could not do this in the old C. > > Can you give such a "perfect" description of the blocks world in B++ ? I am not sure. At least I do not immediately see how. But remember, I crafted B++ just to better understand 'what is wrong with action languages'. In general I represent knowledge (in particular knowledge about dynamic domains) in A-Prolog (and not in B++), and have of course no difficulty in avoiding circular configurations by simply saying :- block(B), not above(B,t). To capture this I need a more powerful dialect of B. There are many ways of doing that. At some point, for instance, Richard had a notion of 'defined' fluent which will probably work here. Let me suggest another variant of B, say B*, which I believe will also work. SYNTAX: Signature: inertial and non-inertial fluents (to simplify writing by fluents I'll mean fluent literals), actions, and names of normative statements. Statements: 1. D: Normally A causes F if P 2. D: Normally F if P 3. D: Normally impossible A if P 4. Q is an exception to D 5. D: Default F if P (where F is a non-inertial fluent) The first three statements can be defeated only by the listed exceptions. In this sense they correspond to 'strong' defaults as in B++. (In terminology advocated by Son and I such statements, though defeasible, are not defaults). Statement (5) is a default. It can be defeated by defeating its conclusion, as well as by exceptions. Notice, that (5) is applicable only to non-inertial fluents. Notice also that statements (1)-(3) with no exceptions correspond to statements of B. We can make an agreement that if 'normally' is omitted from a sentence then exceptions to it are not allowed. SEMANTICS. (By translation. I am violating Prolog agreement here. Capital letters A,F,P,D are constants. Variable T ranges over [0,1]). (a) Laws (1)-(3) are written as h(F,1) :- occurs(A,0), h(P,0), not ab(D,0). h(F,T) :- h(P,T), not ab(D,T). :- occurs(A,0), h(P,0), not ab(D,0). (b) The law (5) is written as h(F,T) :- h(P,T), not ~h(F,T). (c) Exception (4) to the law of form (1) is translated as ab(D,0) :- h(Q,0). ~h(F,1) :- occurs(A,0), h(Q,0), h(P,0). (Marcello noticed correctly that I missed h(P,0) in my description of semantics of B++. So we know that someone else is reading this.) Exception to the law of form (2) is written as ab(D,T) :- h(Q,T). ~h(F,T) :- h(Q,T), h(P,T). to the law (3) as ab(D,T) :- h(Q,T). and to the law (5) as ~h(F,T) :- h(Q,T), h(P,T). Adding the Inertia and standard rules to deal with '~' we obtain a program, say, T(AD), where AD is an action description in B*. The transition diagram is defined as in B++, i.e. the successor states of (S0,A) correspond to answer sets of T(AD) + {h(F,0) : F in S0} + o(A,0) ---------------------------------------------------------------------------- Going back to the block's world: I'd define 'above' as a non-inertial fluent whose behavior is fully determined by the laws: above(A,B) if on(A,B). above(A,B) if on(A,C), above(C,B). default ~above(A,B). false if block(B), ~above(B,t). This is of course only a sketch, but I think it works. ---------------------------------------------------------------------------- B* seems to be a powerful language and may deserve an investigation. In a sense it is a combination of B+ and B++. I can however come up with examples of action descriptions which are simple in A-Prolog and are either impossible or non-trivial in B*. Any comments? ====== Date: Fri, 5 Oct 2001 From: Vladimir Lifschitz To: Michael Gelfond Your B* approach looks interesting. And I am curious about Richard's notion of a defined fluent that you mention. This may be similar to "statically determined" fluents that we are now adding to C. In fact, at first we were even thinking of calling these fluents "defined", but then decided against it. In many cases, the static laws characterizing such a fluent provide its definition in terms of other fluents, but generally this is not the case. ====== Date: Thu, 11 Oct 2001 From: Richard Watson To: Vladimir Lifschitz For me, the idea of a defined fluent came about when I found I often wanted to express statements of the form "l is true iff P1 or P2 or .. or Pn is true" where each Pi is a set of literals. In my dissertation, the corresponding definition propositions have the form: definition(l,P1). ... definition(l,Pn)}. I had the following restrictions on the use of such proposition: 1) if l is a defined literal, it neither it nor its negation can belong to the head of a static or dynamic causal law. 2) for any fluent f, there may be definition propositions for f or neg(f) but not both. Semantically, definition propositions are simply a shorthand for a larger set of static causal laws: {causes(l0,P1),...,causes(l0,Pm)} + {causes(neg(l0),Q) | where Q is a minimal set of literals falsifying all Pi's}. Is this similar to what you are doing with "statically determined" fluents in C? ====== Date: Thu, 11 Oct 2001 From: Vladimir Lifschitz To: Richard Watson Thank you for reminding me about the treatment of defined fluents in your dissertation. Yes, there is some similarity with our definition of statically determined fluents. Can your definitions be recursive? For instance, can you treat the above relation in the blocks world as a defined fluent? The syntax that we plan to use is a bit different though: instead of a new kind of propositions definition(l,P) we'll write the corresponding static laws. The fact that these static laws are viewed as a logic-programming style definition of l is conveyed by classifying l as "statically determined" in the definition of the language. Accordingly, instead of prohibiting such fluents in the heads of both static and dynamic laws, we prohibit them in the heads of dynamic laws only. ====== Date: Fri, 12 Oct 2001 From: Richard Watson To: Vladimir Lifschitz Yes, the syntax and semantics of definition propositions allowed them to be recursive. However I'm not sure the translation to Logic Programming I used is valid if they are. ====== Date: Tue, 20 Nov 2001 From: Pedro Cabalar To: TAG I've made an overall follow-up of the recent discussion about limitations of action languages. The representational problems that motivated the discussion are also present in PAL, since its only allowed default is inertia. I had planned to extend this in two different ways: (1) nonmonotonicity in the observations (specially thinking about the initial situation) (2) defeasible rules (for solving the qualification problem) but this is still future work. From your discussion, it seems that both problems are solved by defining (so-called) "static"/ "defined"/ "non-inertial" fluents, and applying them as abnormality predicates. I have a question: is this similar to the approach in [Baral&Lobo97]? If I remember correctly, they used there 2 levels of abnormality: ab_1 for defeasible rules and ab_0 for inertia. Which would be the respective differences w.r.t. your new proposals B++ and "new C"? [Baral&Lobo97] C. Baral and J. Lobo. Defeasible Specifications in Action Theories. Proc. of IJCAI'97 (pp 1441--1446). Nagoya, Japan. --------- Apart from this question, I have also an objection about the particular example of predicate above. In the beginning, I couldn't see the actual need for considering above as non-inertial. I mean, for me, it is clear that above(B,L) sometimes persists and sometimes is caused: i.e., inertia intuitively affects above! Of course, I understand that defining inertia for above would lead to a conflict with the rule asserting that above is false by default. However, this seems to be a technical problem rather than a real reason to supress inertia for above. The question is: can we still formalize above as an inertial fluent? I guess that this should be possible using other approaches. These are my experiments in PAL, using some recently incorporated features, like quantifiers. My first attempt was this one: options not concurrent; sets block = [1,3]; location = block + {table}; actions move: block -> location; fluents loc: block -> location; clear: block -> boolean; above: block x location -> boolean; vars B: block; L:location; rules loc(B):=move(B); clear(B):=not (exists C:block. C!=B and loc(C)=B); above(B,L):= loc(B)=L or (exists C:block. C!=B and C!=L and loc(B)=C and above(C,L)); false if pert(move(B)) and not prev(clear(B)); false if not prev(clear(move(B))); false if not above(B,table); initially loc(B):=table,not above(B,C),above(B,table),clear(B); Note that both clear and above are "assigned" the truth of a whole formula. For a boolean p, we could understand any p:=F as the pair of rules p if F not p if not F Unfortunately this did not work. The simple execution: do { move(1):=2; } yielded no model when translated into stable models, whereas under wfs, the answer left all the `above' ground instances undefined. The reason is that there is an "active" negative cycle to establish whether above(B,L) persists or not: i.e., the recursive definition leads to a conflict. Then I had the following idea: while loc(B)=L persists true (it is not altered) the corresponding above(B,L) should also persist true (i.e., its rule should be disabled), regardless any modification on the location of other blocks. This kind of reasoning can be now done in PAL by using what I call "safe" (or "persistence shortcircuit") operators `&&' `||' `exists_' and `forall_'. The corresponding change in the definition of above would simply be: above(B,L):= loc(B)=L || (exists_ C:block. C!=B && C!=L && loc(B)=C && above(C,L)); Something similar can be done for clear clear(B):=not (exists_ C:block. C!=B && loc(C)=B); though it is not necessary to solve the conflict. Now, the execution do {move(1):=2; move(3):=1; } leads to: 1) move(1):=2 loc(1):=2 clear(2):=false clear(3):=true above(1,1):=false above(1,table):=true above(1,2):=true above(1,3):=false 2) move(3):=1 loc(3):=1 clear(1):=false above(3,1):=true above(3,table):=true above(3,2):=true above(3,3):=false both under wfs and stable models. The answer shows all the relevant or "caused" facts. At each situation, non-displayed fluents persist with their previous value. Note for instance how the second block movement does not alter above(1,2) or above(1,table). i.e., these facts persist. Of course, I know that the experiments are not sufficiently explained, but I just wanted to see whether you find these results interesting or at least reasonable. ====== Date: Tue, 27 Nov 2001 From: Vladimir Lifschitz To: Pedro Cabalar This is a reply to the two questions that you raised in a recent message to TAG. 1. Is the idea of a statically determined fluent similar to the difference between two kinds of abnormality (ab_1 for defeasible rules and ab_0 for inertia) in the IJCAI-97 paper by Baral and Lobo? I don't see any close relationship here. A detailed discussion of statically determined fluents is available now in Section 4 of the paper "Nonmonotonic causal theories" mentioned in my previous message to TAG, and I hope that this will make it easier to compare our proposal with others. 2. Is it necessary to treat the above predicate in the blocks world as non-inertial? You may very well be right that this is not necessary. After all, the commonsense law of inertia is merely a default, and a default can always be disabled. But, once we postulated a definition of a fluent F in terms of other fluents, it would be strange, it seems to me, to postulate inertia for F. The definition of F will allow us to compute the value of F after performing an action on the basis of the values of other fluents in the same state without using inertia. Assuming inertia for a defined fluent is sometimes harmful, sometimes not, but it is never useful! ====== Date: Wed, 12 Dec 2001 From: Michael Gelfond To: Pedro Cabalar Pedro: What is the relationship between B* and the ADC language of [Baral&Lobo97] C. Baral and J. Lobo. Defeasible Specifications in Action Theories. Proc. of IJCAI'97 (pp 1441--1446). Nagoya, Japan. M. (You actually asked about B++ but B* is probably more interesting). Well, ideologically both languages are very close. As far as I know their paper contains the first published account of the idea of defining the transition function of an action language via the notion of answer set. This is of course what I am doing in defining B* and other similar languages. Unfortunately, I cannot answer your question more precisely. I suspect that B* is an extension of ADC but cannot say for sure. After your question I spend some time looking at the paper but the end of semester is too hectic a time. One of the problems is that their translation to logic programs looks somewhat strange to me now. (Chitta may remember a rational for using two ab's and for having the same ab's in the bodies of different defaults, etc). If someone decides to take B* or a variant seriously this question of course should be answered. (If this happens please let me know - I think that some study of B* will be useful and will be glad to take part in it.) Pedro. Apart from this question, I have also an objection about the particular example of predicate above. In the beginning, I couldn't see the actual need for considering above as non-inertial. I mean, for me, it is clear that above(B,L) sometimes persists and sometimes is caused: i.e., inertia intuitively affects above! Of course, I understand that defining inertia for above would lead to a conflict with the rule asserting that above is false by default. However, this seems to be a technical problem rather than a real reason to suppress inertia for above. The question is: can we still formalize above as an inertial fluent? M. We sure can. Suppose instead of statement of type (5) in B* I allow 5. D: Default F if P (where F is an arbitrary fluent) Then all I need to add to my translation is a statement saying that this default is preferred to inertia. To make the translation short I'll write the inertia as h(F,T+1) :- h(F,T), not ab(d1(F),T), not ~h(F,T+1). ~h(F,T+1) :- h(F,T), not ab(d2(F),T), not h(F,T+1). and for each default (5) such that F is a fluent add: ab(d2(F),T) :- h(P,T). If head of default (5) is ~F add ab(d1(F),T) :- h(P,T). Now I do not need to worry if F is inertial or not. Is that what you wanted? P. it is clear that above(B,L) sometimes persists and sometimes is caused: i.e., inertia intuitively affects above! M. Here I believe is the root of the problem. For you inertia seems to be something which really (physically) affects the fluent. When I say that fluent is inertial it simply means that in my knowledge base the fluent's truth values are defined by the inertia axiom and its exceptions. You seem to be more interested in modeling 'physical' causality and 'physical' inertia while I am mainly concerned with finding convenient ways of representing knowledge. The latter representation of the 'above' maybe more suitable from your perspective, while from mine it is redundant and hence less elegant. (Judging by his last message Vladimir shares this perspective.) Is this a reasonable analysis? P. Of course, I understand that defining inertia for above would lead to a conflict with the rule asserting that above is false by default. However, this seems to be a technical problem rather than a real reason to suppress inertia for above. M. I am not sure I follow that. Can you elaborate? P. These are my experiments in PAL, using some recently incorporated features, like quantifiers. My first attempt was this one: options not concurrent; sets block = [1,3]; location = block + {table}; actions move: block -> location; fluents loc: block -> location; clear: block -> boolean; above: block x location -> boolean; vars B: block; L:location; rules loc(B):=move(B); clear(B):=not (exists C:block. C!=B and loc(C)=B); above(B,L):= loc(B)=L or (exists C:block. C!=B and C!=L and loc(B)=C and above(C,L)); false if pert(move(B)) and not prev(clear(B)); false if not prev(clear(move(B))); false if not above(B,table); initially loc(B):=table,not above(B,C),above(B,table),clear(B); Note that both clear and above are "assigned" the truth of a whole formula. For a boolean p, we could understand any p:=F as the pair of rules p if F not p if not F Unfortunately this did not work. The simple execution: do { move(1):=2; } yielded no model when translated into stable models, whereas under wfs, the answer left all the `above' ground instances undefined. The reason is that there is an "active" negative cycle to establish whether above(B,L) persists or not: i.e., the recursive definition leads to a conflict. M. I think I follow this, even though some English descriptions of the rules would help. What do you mean when you say this didn't work? Is it a problem with the semantics of PAL or with the translation into logic programs? In your terminology, is the problem 'real' or 'technical'? The solution you suggest does not seem 'natural' to me but more detailed description may easily change this impression. P. I just wanted to see whether you find these results interesting or at least reasonable. M. If they help you to understand something then of course they are reasonable. For me to really answer your question though I need to know what is the goal you are trying to achieve.