From: <jom...@us...> - 2013-09-09 00:53:43
|
Revision: 1748 http://sourceforge.net/p/jason/svn/1748 Author: jomifred Date: 2013-09-09 00:53:39 +0000 (Mon, 09 Sep 2013) Log Message: ----------- unification changed to deal with negated variables Modified Paths: -------------- trunk/applications/as-unit-test/src/jason/tests/TestAll.java trunk/release-notes.txt trunk/src/jason/asSemantics/TransitionSystem.java trunk/src/jason/asSemantics/Unifier.java trunk/src/jason/asSyntax/VarTerm.java trunk/src/jason/stdlib/create_agent.java trunk/src/test/ASParserTest.java trunk/src/test/VarTermTest.java Added Paths: ----------- trunk/applications/as-unit-test/src/jason/tests/TestNegatedVar.java Modified: trunk/applications/as-unit-test/src/jason/tests/TestAll.java =================================================================== --- trunk/applications/as-unit-test/src/jason/tests/TestAll.java 2013-09-09 00:51:53 UTC (rev 1747) +++ trunk/applications/as-unit-test/src/jason/tests/TestAll.java 2013-09-09 00:53:39 UTC (rev 1748) @@ -25,6 +25,7 @@ TestPlanFailure.class, TestVarInContext.class, TestUnnamedVar.class, - TestCopyTerm.class + TestCopyTerm.class, + TestNegatedVar.class }) public class TestAll { } Added: trunk/applications/as-unit-test/src/jason/tests/TestNegatedVar.java =================================================================== --- trunk/applications/as-unit-test/src/jason/tests/TestNegatedVar.java (rev 0) +++ trunk/applications/as-unit-test/src/jason/tests/TestNegatedVar.java 2013-09-09 00:53:39 UTC (rev 1748) @@ -0,0 +1,32 @@ +package jason.tests; + +import jason.asunit.TestAgent; + +import org.junit.Before; +import org.junit.Test; + +public class TestNegatedVar { + + TestAgent ag; + + // initialisation of the agent test + @Before + public void setupAg() { + ag = new TestAgent(); + ag.setDebugMode(true); + + // defines the agent's AgentSpeak code + ag.parseAScode( + "+!start <- +b. " + + "+B <- !~B. " + + "+!X <- jason.asunit.print(X)." + ); + } + + @Test(timeout=2000) + public void testContext() { + ag.addGoal("start"); + ag.assertPrint("~b[source(self)]", 5); + } + +} Modified: trunk/release-notes.txt =================================================================== --- trunk/release-notes.txt 2013-09-09 00:51:53 UTC (rev 1747) +++ trunk/release-notes.txt 2013-09-09 00:53:39 UTC (rev 1748) @@ -11,7 +11,7 @@ - the internal action .wait accepts a logical expression as argument, as in ...; .wait(b(X) & X > 10); .... - The intention will be suspended until the agent belief b(X) with X > 10. + The intention will be suspended until the agent believes b(X) with X > 10. Timeout and elapse time arguments can be used as previously. --------------------------- Modified: trunk/src/jason/asSemantics/TransitionSystem.java =================================================================== --- trunk/src/jason/asSemantics/TransitionSystem.java 2013-09-09 00:51:53 UTC (rev 1747) +++ trunk/src/jason/asSemantics/TransitionSystem.java 2013-09-09 00:53:39 UTC (rev 1748) @@ -580,31 +580,36 @@ Term bTerm = h.getBodyTerm(); // de-var bTerm - while (bTerm instanceof VarTerm) { + //while (bTerm instanceof VarTerm) { + if (bTerm instanceof VarTerm) { // check if bTerm is ground - //if (bTerm.isGround()) { - if (((VarTerm)bTerm).hasValue()) { + /*if (((VarTerm)bTerm).hasValue()) { bTerm = ((VarTerm)bTerm).getValue(); continue; // restart the loop - } + }*/ // h should be 'groundable' (considering the current unifier) - Term bValue = u.get((VarTerm)bTerm); + bTerm = bTerm.clone(); // clone before apply + bTerm.apply(u); + //Term bValue = u.get((VarTerm)bTerm); //System.out.println("*** "+bTerm+"="+bValue+" "+bTerm.isGround()+" "+u); - if (bValue == null) { // the case of !A with A not ground + //if (bValue == null) { // the case of !A with A not ground + if (bTerm.isVar()) { // the case of !A with A not ground String msg = h.getSrcInfo()+": "+ "Variable '"+bTerm+"' must be ground."; if (!generateGoalDeletion(conf.C.SI, JasonException.createBasicErrorAnnots("body_var_without_value", msg))) logger.log(Level.SEVERE, msg); return; } - if (bValue.isPlanBody()) { + //if (bValue.isPlanBody()) { + if (bTerm.isPlanBody()) { if (h.getBodyType() != BodyType.action) { // the case of ...; A = { !g }; +g; .... - String msg = h.getSrcInfo()+": "+ "The operator '"+h.getBodyType()+"' is lost with the variable '"+bTerm+"' unified with a plan body '"+bValue+"'. "; + String msg = h.getSrcInfo()+": "+ "The operator '"+h.getBodyType()+"' is lost with the variable '"+bTerm+"' unified with a plan body. "; if (!generateGoalDeletion(conf.C.SI, JasonException.createBasicErrorAnnots("body_var_with_op", msg))) logger.log(Level.SEVERE, msg); return; } - h = (PlanBody)bValue; + //h = (PlanBody)bValue; + h = (PlanBody)bTerm; if (h.getPlanSize() > 1) { // the case of A unified with {a;b;c} h.add(im.getCurrentStep().getBodyNext()); im.insertAsNextStep(h.getBodyNext()); @@ -612,7 +617,7 @@ bTerm = h.getBodyTerm(); } else { ListTerm annots = ((VarTerm)bTerm).getAnnots(); - bTerm = bValue; + //bTerm = bValue; if (bTerm.isLiteral() && annots != null) { bTerm = ((Literal)bTerm).forceFullLiteralImpl(); ((Literal)bTerm).addAnnots(annots); Modified: trunk/src/jason/asSemantics/Unifier.java =================================================================== --- trunk/src/jason/asSemantics/Unifier.java 2013-09-09 00:51:53 UTC (rev 1747) +++ trunk/src/jason/asSemantics/Unifier.java 2013-09-09 00:53:39 UTC (rev 1748) @@ -89,6 +89,18 @@ if (vl != null && vl.isVar()) { // optimised deref return get((VarTerm)vl); } + if (vl == null) { // try negated value of the var + //System.out.println("for "+vtp+" try "+new VarTerm(vtp.negated(), vtp.getFunctor())+" in "+this); + vl = function.get( new VarTerm(vtp.negated(), vtp.getFunctor()) ); + //System.out.println(" and found "+vl); + if (vl != null && vl.isVar()) { + vl = get((VarTerm)vl); + } + if (vl != null && vl.isLiteral()) { + vl = vl.clone(); + ((Literal)vl).setNegated(((Literal)vl).negated()); + } + } return vl; } @@ -233,21 +245,20 @@ final VarTerm t2gv = t2gisvar ? deref((VarTerm)t2g) : null; // get their values - final Term t1vl = t1gisvar ? function.get(t1gv) : t1g; - final Term t2vl = t2gisvar ? function.get(t2gv) : t2g; + //final Term t1vl = t1gisvar ? function.get(t1gv) : t1g; + //final Term t2vl = t2gisvar ? function.get(t2gv) : t2g; + final Term t1vl = t1gisvar ? get(t1gv) : t1g; + final Term t2vl = t2gisvar ? get(t2gv) : t2g; - if (t1vl != null && t2vl != null) { - // unifies the two values of the vars + if (t1vl != null && t2vl != null) { // unifies the two values of the vars return unifiesNoUndo(t1vl, t2vl); - } else if (t1vl != null) { - bind(t2gv, t1vl); + } else if (t1vl != null) { // unifies var with value + return bind(t2gv, t1vl); } else if (t2vl != null) { - bind(t1gv, t2vl); - } else { //if (t1gv != null && t2gv != null) { - // unify two vars - bind(t1gv, t2gv); + return bind(t1gv, t2vl); + } else { // unify two vars + return bind(t1gv, t2gv); } - return true; } // both terms are not vars @@ -307,23 +318,43 @@ return v; } - - - public void bind(VarTerm vt1, VarTerm vt2) { + public boolean bind(VarTerm vt1, VarTerm vt2) { + if (vt1.negated() && vt2.negated()) { // in the case of ~A = ~B, put A=B in the unifier + vt1 = new VarTerm(vt1.getFunctor()); + vt2 = new VarTerm(vt2.getFunctor()); + } + final int comp = vt1.compareTo(vt2); if (comp < 0) { - function.put((VarTerm)vt1.clone(), vt2); + function.put((VarTerm)vt1.clone(), vt2.clone()); } else if (comp > 0){ - function.put((VarTerm)vt2.clone(), vt1); + function.put((VarTerm)vt2.clone(), vt1.clone()); } // if they are the same (comp == 0), do not bind + return true; } - public void bind(VarTerm vt, Term vl) { + public boolean bind(VarTerm vt, Term vl) { + if (vt.negated()) { // negated vars unifies only with negated literals + if (vl.isLiteral()) { + if (!((Literal)vl).negated()) { + return false; + } else { + // put also the positive case in the unifier + Literal vlp = (Literal)vl.clone(); + vlp.setNegated(Literal.LPos); + unifies(new VarTerm(vt.getFunctor()), vlp); + } + } else { + return false; + } + } + if (!vl.isCyclicTerm() && vl.hasVar(vt, this)) { vl = new CyclicTerm((Literal)vl, (VarTerm)vt.clone()); - //System.out.println("changing "+vt+" <- "+vl+" in "+this); } + function.put((VarTerm) vt.clone(), vl); + return true; } public void clear() { Modified: trunk/src/jason/asSyntax/VarTerm.java =================================================================== --- trunk/src/jason/asSyntax/VarTerm.java 2013-09-09 00:51:53 UTC (rev 1747) +++ trunk/src/jason/asSyntax/VarTerm.java 2013-09-09 00:53:39 UTC (rev 1748) @@ -65,6 +65,9 @@ e.printStackTrace(); } } + public VarTerm(boolean negated, String s) { + super(negated, s); + } /** @deprecated prefer ASSyntax.parseVar(...) */ public static VarTerm parseVar(String sVar) { @@ -83,6 +86,7 @@ } else { // do not call constructor with term parameter! VarTerm t = new VarTerm(super.getFunctor()); + t.setNegated(!negated()); t.srcInfo = this.srcInfo; if (hasAnnot()) t.setAnnots(getAnnots().cloneLT()); @@ -135,7 +139,7 @@ // P[step(N)] if (vl.isPred() && this.hasAnnot()) // if this var has annots, add them in the value's annots (Experimental) ((Pred)vl).addAnnots(this.getAnnots()); - + value = vl; resetHashCodeCache(); return true; @@ -148,8 +152,7 @@ public boolean apply(Unifier u) { if (value == null) { - Term vl = u.get(this); - //System.out.println("applying "+this+"="+vl+" un="+u); + Term vl = u.get(this); if (vl != null) { if (!vl.isCyclicTerm() && vl.hasVar(this, u)) { //logger.warning("The value of a variable contains itself, variable "+super.getFunctor()+" "+super.getSrcInfo()+", value="+vl+", unifier="+u); @@ -200,7 +203,7 @@ if (t instanceof VarTerm) { final VarTerm tAsVT = (VarTerm) t; if (tAsVT.getValue() == null) { - return getFunctor().equals(((VarTerm)t).getFunctor()); + return negated() == ((VarTerm)t).negated() && getFunctor().equals(((VarTerm)t).getFunctor()); } } } @@ -212,10 +215,14 @@ return value.compareTo(t); else if (t == null || t.isUnnamedVar()) return -1; - else if (t.isVar()) - return getFunctor().compareTo(((VarTerm)t).getFunctor()); - else - return 1; + else if (t.isVar()) { + if (!negated() && ((VarTerm)t).negated()) + return -1; + else + return getFunctor().compareTo(((VarTerm)t).getFunctor()); + } else { + return 1; + } } @Override @@ -476,9 +483,10 @@ public String toString() { if (value == null) { String s = getFunctor(); - if (hasAnnot()) { + if (hasAnnot()) s += getAnnots(); - } + if (negated()) + s = "~" + s; return s; } else { return value.toString(); @@ -668,7 +676,10 @@ @Override public boolean negated() { - return value != null && getValue().isLiteral() && ((Literal) getValue()).negated(); + if (value == null) + return super.negated(); + else + return getValue().isLiteral() && ((Literal) getValue()).negated(); } @Override Modified: trunk/src/jason/stdlib/create_agent.java =================================================================== --- trunk/src/jason/stdlib/create_agent.java 2013-09-09 00:51:53 UTC (rev 1747) +++ trunk/src/jason/stdlib/create_agent.java 2013-09-09 00:53:39 UTC (rev 1748) @@ -28,23 +28,17 @@ import jason.asSemantics.TransitionSystem; import jason.asSemantics.Unifier; import jason.asSyntax.ListTerm; -import jason.asSyntax.SourceInfo; import jason.asSyntax.StringTerm; import jason.asSyntax.StringTermImpl; import jason.asSyntax.Structure; import jason.asSyntax.Term; -import jason.asSyntax.VarTerm; import jason.mas2j.ClassParameters; import jason.runtime.RuntimeServicesInfraTier; import java.io.File; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - /** <p>Internal action: <b><code>.create_agent</code></b>. Modified: trunk/src/test/ASParserTest.java =================================================================== --- trunk/src/test/ASParserTest.java 2013-09-09 00:51:53 UTC (rev 1747) +++ trunk/src/test/ASParserTest.java 2013-09-09 00:53:39 UTC (rev 1748) @@ -40,6 +40,18 @@ super.setUp(); } + public void testNegVar() throws ParseException { + Literal l = ASSyntax.parseLiteral("~B"); + assertTrue(l.isVar()); + assertTrue(l.negated()); + l = (Literal)l.clone(); + assertTrue(l.isVar()); + assertTrue(l.negated()); + Literal l1 = ASSyntax.parseLiteral("~B"); + Literal l2 = ASSyntax.parseLiteral("B"); + assertFalse(l1.equals(l2)); + } + public void testKQML() { Agent ag = new Agent(); ag.initAg(); Modified: trunk/src/test/VarTermTest.java =================================================================== --- trunk/src/test/VarTermTest.java 2013-09-09 00:51:53 UTC (rev 1747) +++ trunk/src/test/VarTermTest.java 2013-09-09 00:53:39 UTC (rev 1748) @@ -5,6 +5,7 @@ import jason.asSemantics.Unifier; import jason.asSyntax.ASSyntax; import jason.asSyntax.ArithExpr; +import jason.asSyntax.ArithExpr.ArithmeticOp; import jason.asSyntax.Atom; import jason.asSyntax.ListTerm; import jason.asSyntax.ListTermImpl; @@ -18,7 +19,6 @@ import jason.asSyntax.Term; import jason.asSyntax.UnnamedVar; import jason.asSyntax.VarTerm; -import jason.asSyntax.ArithExpr.ArithmeticOp; import jason.asSyntax.parser.ParseException; import jason.asSyntax.parser.SimpleCharStream; import jason.asSyntax.parser.Token; @@ -561,4 +561,107 @@ assertTrue(X.compareTo(new NumberTermImpl(1)) > 0); assertTrue(new NumberTermImpl(1).compareTo(X) < 0); } + + public void testUnifyNegVar() throws ParseException { + Literal l1 = ASSyntax.parseLiteral("~B"); + Literal l2 = ASSyntax.parseLiteral("~p(1)"); + Unifier u = new Unifier(); + assertTrue(u.unifies(l1, l2)); // ~B = ~p(1) + assertEquals(u.get((VarTerm)l1).toString(),"~p(1)"); + l1.apply(u); // apply in ~B should result in ~p(1) + assertEquals(l1.toString(),"~p(1)"); + + VarTerm b = new VarTerm("B"); + b.apply(u); + assertEquals(b.toString(),"p(1)"); + + l1 = ASSyntax.parseLiteral("~B"); + l2 = ASSyntax.parseLiteral("p(1)"); + u = new Unifier(); + assertFalse(u.unifies(l1, l2)); + + assertFalse(u.unifies(l1, ASSyntax.parseTerm("10"))); + + l1 = ASSyntax.parseLiteral("B"); + l2 = ASSyntax.parseLiteral("~p(1)"); + u = new Unifier(); + assertTrue(u.unifies(l1, l2)); + assertEquals(u.get("B").toString(),"~p(1)"); + l1.apply(u); + assertEquals(l1.toString(),"~p(1)"); + + l1 = ASSyntax.parseLiteral("~B"); + l2 = ASSyntax.parseLiteral("~A"); + u = new Unifier(); + assertTrue(u.unifies(l1, l2)); + // if A = p(10), apply in ~B should be ~p(10). + VarTerm va = new VarTerm("A"); + u.unifies(va,ASSyntax.parseLiteral("p(10)")); + va.apply(u); + assertEquals(va.toString(),"p(10)"); + l1.apply(u); + assertEquals(l1.toString(),"~p(10)"); + l2.apply(u); + assertEquals(l2.toString(),"~p(10)"); + + l1 = ASSyntax.parseLiteral("~B"); + l2 = ASSyntax.parseLiteral("~A"); + u = new Unifier(); + assertTrue(u.unifies(l1, l2)); // A = B + // if ~A = ~p(10), apply in B should be p(10). + assertTrue(u.unifies(l2, ASSyntax.parseLiteral("~p(10)"))); + l2.apply(u); + assertEquals(l2.toString(),"~p(10)"); + l1.apply(u); + assertEquals(l1.toString(),"~p(10)"); // ~B is ~p(10) + VarTerm vb = new VarTerm("B"); + vb.apply(u); + assertEquals(vb.toString(),"p(10)"); // B is p(10) + + u = new Unifier(); + u.unifies(new VarTerm("A"),ASSyntax.parseLiteral("p(10)")); + u.unifies(new VarTerm("B"),ASSyntax.parseLiteral("~p(10)")); + assertFalse(u.unifies(new VarTerm("A"), new VarTerm("B"))); + l1 = ASSyntax.parseLiteral("~B"); + l2 = ASSyntax.parseLiteral("~A"); + assertFalse(u.unifies(l1, l2)); + + u = new Unifier(); + u.unifies(new VarTerm("A"),ASSyntax.parseLiteral("p(10)")); + assertFalse(u.unifies(new VarTerm(Literal.LNeg,"B"),new VarTerm("A"))); + + u = new Unifier(); + u.unifies(new VarTerm("A"),ASSyntax.parseLiteral("~p(10)")); + vb = new VarTerm(Literal.LNeg,"B"); + assertTrue(u.unifies(vb,new VarTerm("A"))); + vb.apply(u); + assertEquals(vb.toString(),"~p(10)"); + + u = new Unifier(); + u.unifies(new VarTerm("A"),ASSyntax.parseLiteral("~p(10)")); + vb = new VarTerm(Literal.LNeg,"B"); + assertTrue(u.unifies(vb,new VarTerm("A"))); + vb = new VarTerm("B"); + vb.apply(u); + assertEquals(vb.toString(),"p(10)"); + + // B = ~A + // A = p(10) + // => apply B is ~p(10) + // apply A is p(10) + // apply ~A is ~p(10) + l1 = ASSyntax.parseLiteral("B"); + l2 = ASSyntax.parseLiteral("~A"); + u = new Unifier(); + assertTrue(u.unifies(l1, l2)); + va = new VarTerm("A"); + u.unifies(va,ASSyntax.parseLiteral("p(10)")); + va.apply(u); + assertEquals(va.toString(),"p(10)"); + l1.apply(u); + assertEquals(l1.toString(),"~p(10)"); + l2.apply(u); + assertEquals(l2.toString(),"~p(10)"); + + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |