|
From: Jomi H. <jom...@gm...> - 2009-12-18 19:29:07
|
Hi Tim,
I include (partially) your suggestions into the SVN of Jason.
(details attached -- I've tried to optimise some parts.... If you
could check...)
notes:
1. we cannot comment the makeVarAnnon in TransitionSystem (I added a
new test to show it)
2. with this line uncommented, one of the tests do not pass. (it could
be a problem in "if" ... I'll see)
best,
Jomi
Revision: 1566
http://jason.svn.sourceforge.net/jason/?rev=1566&view=rev
Author: jomifred
Date: 2009-12-18 19:24:45 +0000 (Fri, 18 Dec 2009)
Log Message:
-----------
add some code from Tim to solve makeVarsAnnon problem (not finished)
Modified Paths:
--------------
trunk/applications/as-unit-test/src/jason/tests/BugUnamedVars.java
trunk/applications/as-unit-test/src/jason/tests/TestAll.java
trunk/src/jason/asSyntax/ArithFunctionTerm.java
trunk/src/jason/asSyntax/Literal.java
trunk/src/jason/asSyntax/Pred.java
trunk/src/jason/asSyntax/Rule.java
trunk/src/jason/asSyntax/Structure.java
trunk/src/jason/asSyntax/VarTerm.java
trunk/src/test/RuleTest.java
trunk/src/test/TermTest.java
Added Paths:
-----------
trunk/applications/as-unit-test/src/jason/tests/TestUnnamedVar.java
Modified: trunk/applications/as-unit-test/src/jason/tests/
BugUnamedVars.java
===================================================================
--- trunk/applications/as-unit-test/src/jason/tests/BugUnamedVars.java
2009-12-18 14:10:31 UTC (rev 1565)
+++ trunk/applications/as-unit-test/src/jason/tests/BugUnamedVars.java
2009-12-18 19:24:45 UTC (rev 1566)
@@ -20,15 +20,26 @@
ag.parseAScode(
"wrap([],[]). "+
"wrap([_ | Rest], [wrapped(_) | Result]) :-
wrap(Rest, Result). "+
+
+ "wrap2([], _). "+
+ "wrap2([_ | Rest], Result) :- wrap2(Rest, Temp) &
Result = wrapped(_, Temp). "+
+
"+!start : wrap([a,b,c],R) & R = [wrapped(a),
wrapped(b), wrapped(c)] <- jason.asunit.print(ok)."+
- "+!start : wrap([a,b,c],R) & R = [wrapped(a),
wrapped(a), wrapped(a)] <- jason.asunit.print(nok). "
+ "+!start : wrap([a,b,c],R) & R = [wrapped(a),
wrapped(a), wrapped(a)] <- jason.asunit.print(nok). " +
+ "+!test2 : wrap2([1, 2, 3], Result) & Result =
wrapped(1, wrapped(2, wrapped(3, 4))) <- jason.asunit.print(ok). "
);
}
@Test(timeout=2000)
- public void testWrap() {
+ public void testWrap1() {
ag.addGoal("start");
ag.assertPrint("ok", 20);
}
+
+ @Test(timeout=2000)
+ public void testWrap2() {
+ ag.addGoal("test2");
+ ag.assertPrint("ok", 20);
+ }
}
Modified: trunk/applications/as-unit-test/src/jason/tests/TestAll.java
===================================================================
--- trunk/applications/as-unit-test/src/jason/tests/TestAll.java
2009-12-18 14:10:31 UTC (rev 1565)
+++ trunk/applications/as-unit-test/src/jason/tests/TestAll.java
2009-12-18 19:24:45 UTC (rev 1566)
@@ -23,6 +23,7 @@
TestLoop.class,
TestPlanbodyAsTerm.class,
TestPlanFailure.class,
- TestVarInContext.class
+ TestVarInContext.class,
+ TestUnnamedVar.class
})
public class TestAll { }
Added: trunk/applications/as-unit-test/src/jason/tests/
TestUnnamedVar.java
===================================================================
--- trunk/applications/as-unit-test/src/jason/tests/
TestUnnamedVar.java (rev 0)
+++ trunk/applications/as-unit-test/src/jason/tests/
TestUnnamedVar.java 2009-12-18 19:24:45 UTC (rev 1566)
@@ -0,0 +1,22 @@
+package jason.tests;
+
+import jason.asunit.TestAgent;
+
+import org.junit.Test;
+
+public class TestUnnamedVar {
+
+ @Test(timeout=2000)
+ public void testUnnamedVar() {
+ TestAgent ag = new TestAgent();
+
+ // defines the agent's AgentSpeak code
+ ag.parseAScode(
+ "+!test <- A=a(B); !t(A); jason.asunit.print(A). "+
+ "+!t(A) <- B=3. "
+ );
+ ag.addGoal("test");
+ ag.assertPrint("a(B)", 10); // cannot print(a(3)
+ }
+
+}
Modified: trunk/src/jason/asSyntax/ArithFunctionTerm.java
===================================================================
--- trunk/src/jason/asSyntax/ArithFunctionTerm.java 2009-12-18
14:10:31 UTC (rev 1565)
+++ trunk/src/jason/asSyntax/ArithFunctionTerm.java 2009-12-18
19:24:45 UTC (rev 1566)
@@ -66,8 +66,17 @@
public boolean isStructure() {
return false;
}
-
+
@Override
+ public Literal makeVarsAnnon(Unifier un) {
+ if (isEvaluated()) {
+ return null;
+ } else {
+ return super.makeVarsAnnon(un);
+ }
+ }
+
+ @Override
public boolean isLiteral() {
return false;
}
@@ -81,7 +90,7 @@
public boolean isEvaluated() {
return value != null;
}
-
+
@Override
public boolean isGround() {
return isEvaluated() || super.isGround();
@@ -97,7 +106,8 @@
*/
@Override
public boolean apply(Unifier u) {
- if (isEvaluated()) return false;
+ if (isEvaluated())
+ return false;
super.apply(u);
if ((function != null && function.allowUngroundTerms()) ||
isGround()) {
Modified: trunk/src/jason/asSyntax/Literal.java
===================================================================
--- trunk/src/jason/asSyntax/Literal.java 2009-12-18 14:10:31 UTC (rev
1565)
+++ trunk/src/jason/asSyntax/Literal.java 2009-12-18 19:24:45 UTC (rev
1566)
@@ -264,7 +264,6 @@
Unifier current = null;
Iterator<Unifier> ruleIt = null; // current rule
solutions iterator
Rule rule; // current rule
- Literal cloneAnnon = null; // a copy of the
literal with makeVarsAnnon
boolean needsUpdate = true;
public boolean hasNext() {
@@ -291,40 +290,28 @@
while (ruleIt != null && ruleIt.hasNext()) {
// unifies the rule head with the result of rule
evaluation
Unifier ruleUn = ruleIt.next(); // evaluation
result
- Literal rhead = rule.headClone();
-
- // unnamed vars should be replaced (see bug of
Tim Cleaver)
- replaceUnnamedVarsToUnnamedVars(rhead);
-
- // then apply and replace other free variables
- rhead.apply(ruleUn);
- rhead.makeVarsAnnon(ruleUn);
-
-
- Unifier unC = un.clone();
- if (unC.unifiesNoUndo(Literal.this, rhead)) {
- current = unC;
+ if (ruleUn.unifiesNoUndo(Literal.this, rule)) {
+ current = ruleUn;
return;
}
}
// try literal iterator
+ //
+ // we make the variables in the belief (be it a fact
or rule) and not
+ // in this as this may be included in the scope of a
plan. if we rename
+ // the variables in this and it is in the scope of a
plan then the
+ // variables in the event and the body of the plan
won't reflect the
+ // naming. thus, making the resulting unifier not
reflect the entire
+ // scope of the plan.
while (il.hasNext()) {
Literal b = il.next(); // b is the relevant entry
in BB
if (b.isRule()) {
- rule = (Rule)b;
-
- // create a copy of this literal, ground it and
- // make its vars anonymous,
- // it is used to define what will be the
unifier used
- // inside the rule.
- if (cloneAnnon == null) {
- cloneAnnon = Literal.this.copy();
- cloneAnnon.apply(un);
- cloneAnnon.makeVarsAnnon(un);
- }
- Unifier ruleUn = new Unifier();
- if (ruleUn.unifiesNoUndo(cloneAnnon, rule))
{ // the rule head unifies with the literal
+ rule = (Rule)b.clone();
+ rule.makeVarsAnnon(); // make the variables
in the rule anonymous
+ Unifier ruleUn = un.clone();
+ if (ruleUn.unifiesNoUndo(Literal.this, rule)) {
+ // the rule head unifies with the literal
so match the body
ruleIt =
rule.getBody().logicalConsequence(ag,ruleUn);
get();
if (current != null) { // if it get a value
@@ -333,7 +320,7 @@
}
} else {
Unifier u = un.clone();
- if (u.unifiesNoUndo(Literal.this, b)) {
+ if (u.unifiesNoUndo(Literal.this, b)) { //
b.copy().makeVarsAnnon())) {
current = u;
return;
}
@@ -345,18 +332,6 @@
};
}
- private void replaceUnnamedVarsToUnnamedVars(Literal l) {
- final int size = l.getArity();
- for (int i=0; i<size; i++) {
- Term ti = l.getTerm(i);
- if (ti.isUnnamedVar()) {
- l.setTerm(i, new UnnamedVar());
- } else if (ti instanceof Literal) {
- replaceUnnamedVarsToUnnamedVars((Literal)ti);
- }
- }
- }
-
/** returns this literal as a list with three elements: [functor,
list of terms, list of annots] */
public ListTerm getAsListOfTerms() {
ListTerm l = new ListTermImpl();
@@ -425,6 +400,11 @@
public Iterator<Unifier> logicalConsequence(final Agent ag,
final Unifier un) {
return LogExpr.createUnifIterator(un);
}
+
+ @Override
+ public Literal clone() {
+ return this;
+ }
}
@SuppressWarnings("serial")
@@ -442,5 +422,10 @@
public Iterator<Unifier> logicalConsequence(final Agent ag,
final Unifier un) {
return LogExpr.EMPTY_UNIF_LIST.iterator();
}
+
+ @Override
+ public Literal clone() {
+ return this;
+ }
}
}
Modified: trunk/src/jason/asSyntax/Pred.java
===================================================================
--- trunk/src/jason/asSyntax/Pred.java 2009-12-18 14:10:31 UTC (rev
1565)
+++ trunk/src/jason/asSyntax/Pred.java 2009-12-18 19:24:45 UTC (rev
1566)
@@ -400,7 +400,7 @@
VarTerm uv = varToReplace(ta, un);
if (uv != null)
lt.setTerm(uv);
- else if (ta.isStructure())
+ else if (ta instanceof Structure)
((Structure)ta).makeVarsAnnon(un);
if (lt.isTail()) {
uv = varToReplace(lt.getNext(), un);
Modified: trunk/src/jason/asSyntax/Rule.java
===================================================================
--- trunk/src/jason/asSyntax/Rule.java 2009-12-18 14:10:31 UTC (rev
1565)
+++ trunk/src/jason/asSyntax/Rule.java 2009-12-18 19:24:45 UTC (rev
1566)
@@ -23,6 +23,8 @@
package jason.asSyntax;
+import jason.asSemantics.Unifier;
+
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -77,6 +79,13 @@
return body;
}
+ @Override
+ public Literal makeVarsAnnon(Unifier un) {
+ if (body instanceof Literal)
+ ((Literal)body).makeVarsAnnon(un);
+ return super.makeVarsAnnon(un);
+ }
+
public Rule clone() {
Rule r = new Rule((Literal)super.clone(),
(LogicalFormula)body.clone());
r.predicateIndicatorCache = null;
Modified: trunk/src/jason/asSyntax/Structure.java
===================================================================
--- trunk/src/jason/asSyntax/Structure.java 2009-12-18 14:10:31 UTC
(rev 1565)
+++ trunk/src/jason/asSyntax/Structure.java 2009-12-18 19:24:45 UTC
(rev 1566)
@@ -281,20 +281,48 @@
for (int i=0; i<size; i++) {
Term ti = getTerm(i);
VarTerm uv = varToReplace(ti, un);
- if (uv != null) {
+ if (uv != null)
setTerm(i,uv);
- } else if (ti.isStructure()) {
- Structure tis = (Structure)ti;
- if (tis.hasTerm()) {
- tis.makeVarsAnnon(un);
- }
- }
+ else if (ti instanceof Structure)
+ ((Structure)ti).makeVarsAnnon(un);
}
resetHashCodeCache();
return this;
}
protected VarTerm varToReplace(Term t, Unifier un) {
+ if (!t.isVar())
+ return null;
+ VarTerm vt = (VarTerm)t;
+ VarTerm deref = un.deref(vt);
+ if (deref.isUnnamedVar())
+ return new UnnamedVar();
+
+ // if the variable hasn't been renamed given the input
unifier, then rename it.
+ if (deref.equals(vt)) {
+ // forget the name
+ VarTerm var = new VarTerm("_" + UnnamedVar.getUniqueId()
+ t);
+ // if deref has annotations then we need to replicate
these in the new variable
+ if (deref.hasAnnot()) {
+ var.setAnnots(deref.getAnnots().cloneLT());
+ var.makeVarsAnnon(un);
+ }
+ un.bind(deref, var);
+ return var;
+ }
+ // otherwise it has already been renamed in this scope so
return
+ // the existing renaming
+ // ensure that if the input term has an annotation and the
existing
+ // renaming doesn't then we add the anonymized annotations
+ if (vt.hasAnnot() && !deref.hasAnnot()) {
+ deref.setAnnots(vt.getAnnots().cloneLT());
+ deref.makeVarsAnnon(un);
+ }
+ return deref;
+ }
+
+ /*
+ protected VarTerm varToReplace(Term t, Unifier un) {
if (t.isVar() && !t.isUnnamedVar()) {
// replace t to an unnamed var
VarTerm vt = un.deref((VarTerm)t);
@@ -309,6 +337,7 @@
return null;
}
}
+ */
@Override
public void makeTermsAnnon() {
Modified: trunk/src/jason/asSyntax/VarTerm.java
===================================================================
--- trunk/src/jason/asSyntax/VarTerm.java 2009-12-18 14:10:31 UTC (rev
1565)
+++ trunk/src/jason/asSyntax/VarTerm.java 2009-12-18 19:24:45 UTC (rev
1566)
@@ -414,6 +414,16 @@
}
@Override
+ public Literal makeVarsAnnon(Unifier un) {
+ if (value == null)
+ return super.makeVarsAnnon(un);
+ else if (getValue().isLiteral())
+ return ((Literal)getValue()).makeVarsAnnon(un);
+ else
+ return null;
+ }
+
+ @Override
public String toString() {
if (value == null) {
String s = getFunctor();
@@ -436,7 +446,7 @@
public void setAnnots(ListTerm l) {
if (value != null)
if (getValue().isPred())
- ((Pred) value).setAnnots(l);
+ ((Pred) getValue()).setAnnots(l);
else
logger.log(Level.WARNING, "The setAnnots '"+l+"' in
"+this+" was lost, since this var value is not a Pred. The value's
class is "+getValue().getClass().getName(), new Exception());
else
Modified: trunk/src/test/RuleTest.java
===================================================================
--- trunk/src/test/RuleTest.java 2009-12-18 14:10:31 UTC (rev 1565)
+++ trunk/src/test/RuleTest.java 2009-12-18 19:24:45 UTC (rev 1566)
@@ -2,9 +2,11 @@
import jason.asSemantics.Agent;
import jason.asSemantics.Unifier;
+import jason.asSyntax.ASSyntax;
import jason.asSyntax.Literal;
import jason.asSyntax.LogExpr;
import jason.asSyntax.Rule;
+import jason.asSyntax.Structure;
import jason.asSyntax.VarTerm;
import java.util.HashMap;
@@ -80,12 +82,20 @@
ag.getBB().add(r);
Iterator<Unifier> iun =
Literal.parseLiteral("r([],a(20),X)").logicalConsequence(ag, new
Unifier());
- assertEquals(iun.next().get("X").toString(),"b(20,4)");
-
+ //assertEquals(iun.next().get("X").toString(),"b(20,4)");
+ assertTrue(iun.hasNext());
+ Literal result = Literal.parseLiteral("r([],a(20),X)");
+ Unifier u = iun.next();
+ assertTrue(u.get("X").isStructure());
+ assertEquals( ((Structure)u.get("X")).getArity(), 2);
+ assertEquals( ((Structure)u.get("X")).getFunctor(), "b");
+ result.apply(u);
+ assertEquals(result,
Literal.parseLiteral("r([],a(20),b(20,4))"));
+
iun =
Literal.parseLiteral("r([],a(20),b(X,Y))").logicalConsequence(ag, new
Unifier());
- Unifier u = iun.next();
- assertEquals(u.get("X").toString(),"20");
- assertEquals(u.get("Y").toString(),"4");
+ u = iun.next();
+ assertEquals(u.get("X"), ASSyntax.createNumber(20));
+ assertEquals(u.get("Y"), ASSyntax.createNumber(4));
}
Modified: trunk/src/test/TermTest.java
===================================================================
--- trunk/src/test/TermTest.java 2009-12-18 14:10:31 UTC (rev 1565)
+++ trunk/src/test/TermTest.java 2009-12-18 19:24:45 UTC (rev 1566)
@@ -16,6 +16,7 @@
import jason.asSyntax.ObjectTermImpl;
import jason.asSyntax.Plan;
import jason.asSyntax.Pred;
+import jason.asSyntax.StringTermImpl;
import jason.asSyntax.Structure;
import jason.asSyntax.Term;
import jason.asSyntax.Trigger;
@@ -27,9 +28,11 @@
import jason.bb.BeliefBase;
import jason.bb.DefaultBeliefBase;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import junit.framework.TestCase;
@@ -601,10 +604,21 @@
l2.makeVarsAnnon();
u.clear();
assertTrue(u.unifies(l1, l2));
+
+ // ensure that the anonymized instance of AgY unified to 32
+ assertEquals(u.get((VarTerm) l1.getTerm(0)), new
NumberTermImpl(32));
+ // ensure that the first anonymized instance of QuadY2
unifies to 33
+ assertEquals(u.get((VarTerm) l1.getTerm(1)), new
NumberTermImpl(33));
+ // ensure that the second anonymized instance of QuadY2
unifies to 33
+ assertEquals(u.get((VarTerm) l1.getTerm(2)), new
NumberTermImpl(33));
+ // ensure that the anonymized instance of V unifies to 33
+ assertEquals(u.get((VarTerm) l2.getTerm(2)), new
NumberTermImpl(33));
+
l2.apply(u);
assertEquals("calc(32,33,33)", l2.toString());
l1.apply(u);
assertEquals("calc(32,33,33)", l1.toString());
+
}
public void testMakeVarAnnon3() {
@@ -636,7 +650,17 @@
}
*/
l.makeVarsAnnon(u);
- assertEquals("p(_2)", l.toString());
+ // ensure that X derefs to _2
+ assertTrue(u.deref(new VarTerm("X")).equals(new
UnnamedVar(2)));
+ // ensure that unifying a value with X will bind a value for
all aliases as well.
+ Term val = new StringTermImpl("value");
+ u.unifies(new VarTerm("X"), val);
+ assertTrue(u.get(new VarTerm("X")).equals(val));
+ assertTrue(u.get(new VarTerm("Y")).equals(val));
+ assertTrue(u.get(new VarTerm("Z")).equals(val));
+ assertTrue(u.get(new UnnamedVar(4)).equals(val));
+ assertTrue(u.get(new UnnamedVar(2)).equals(val));
+ assertTrue(u.get(new UnnamedVar(10)).equals(val));
}
public void testMakeVarAnnon5() {
@@ -648,6 +672,32 @@
assertEquals("[s("+l.getTerm(0)+")]",
l.getAnnots().toString());
}
+ // test from Tim Cleaver
+ public void testMakeVarsAnnon6() {
+ // if we make a literal anonymous multiple times, the
instances should not
+ // be equal but should eb unifiable.
+ Literal literal = Literal.parseLiteral("literal(Variable, _)");
+ List<Literal> literals = new ArrayList<Literal>();
+ literals.add(literal);
+ // create a list of anonymized l1s
+ for (int i = 0; i < 5; i++) {
+ literals.add((literal.copy()).makeVarsAnnon());
+ }
+ // ensure that all the anonymizations of Variable are different
+ // ensure that all the anonymizations of _ are different
+ // ensure that all pairs are unifiable
+ for (Literal l1 : literals) {
+ for (Literal l2 : literals) {
+ if (l1 == l2) {
+ continue;
+ }
+ assertFalse(l1.getTerm(0).equals(l2.getTerm(0)));
+ assertFalse(l1.getTerm(1).equals(l2.getTerm(1)));
+ assertTrue(new Unifier().unifies(l1, l2));
+ }
+ }
+ }
+
public void testAddAnnots() {
Literal p1 = Literal.parseLiteral("p1");
Literal p2 = Literal.parseLiteral("p2[a1,a2]");
This was sent by the SourceForge.net collaborative development
platform, the world's largest Open Source development site.
------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast
and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev
_______________________________________________
Jason-developers mailing list
Jas...@li...
https://lists.sourceforge.net/lists/listinfo/jason-developers
On 14/12/2009, at 21:17, Tim Cleaver wrote:
> Jomi,
>
> Having sent you my updated patch I returned to my personal project.
> However, it seems that your solution isn't sufficient for my needs.
> I had figured that my simplified example was sufficient to capture
> the entire issue. It wasn't. Here is another simple demonstration of
> insufficient anonymous variable renaming that my project
> necessitates. I hope this test case captures all my needs so you
> don't have to reopen this bug again. I am trying to avoid sending my
> actual project code as its complexity hides the real issues.
>
> wrap([], _).
> wrap([_ | Rest], Result) :- wrap(Rest, Temp) & Result = wrapped(_,
> Temp).
>
> !test.
>
> !test : wrap([1, 2, 3], Result) & Result = wrapped(1, wrapped(2,
> wrapped(3, 4))) <- .print("ok").
>
> Similar to last time, each anonymous variable in wrapped(_, Temp)
> should be unique. Unfortunately it seems your fix does not provide
> this. The patch sent in my previous email does. Perhaps it can be
> adapted to work with your fix?
>
> regards,
> Tim
>
>
>
> __________________________________________________________________________________
> See what's on at the movies in your area. Find out now: http://au.movies.yahoo.com/session-times/
--
Jomi Fred Hubner
Department of Automation and Systems Engineering
Federal University of Santa Catarina
PO Box 476, Florianópolis, SC
88040-900 Brasil
http://www.das.ufsc.br/~jomi
|