From 219f0b17c026ed5fb33dcdd81d67cb4343543fb6 Mon Sep 17 00:00:00 2001 From: Alessandro Date: Fri, 16 Aug 2019 02:50:09 +0200 Subject: [PATCH 1/5] Fix issue #1053 Unify algorithm fixed by performing a perform a cascade substitution when a new mapping is added This issue was already known and fixed in the aima-java repo. --- logic.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/logic.py b/logic.py index 24736c1a9..7bc1add43 100644 --- a/logic.py +++ b/logic.py @@ -1370,7 +1370,9 @@ def unify_var(var, x, s): elif occur_check(var, x, s): return None else: - return extend(s, var, x) + new_s = extend(s, var, x) + cascade_substitution(new_s) + return new_s def occur_check(var, x, s): @@ -1415,6 +1417,33 @@ def subst(s, x): else: return Expr(x.op, *[subst(s, arg) for arg in x.args]) +def cascade_substitution(s): + '''This method allow to return a correct unifier in normal form + and perform a cascade substitution to s. + For every mapping in s perform a cascade substitution on s.get(x) + and if it is replaced with a function ensure that all the function + terms are correctly updates by passing over them again. + + This fix issue: https://github.com/aimacode/aima-python/issues/1053 + unify(P(A, x, F(G(y))), P(z, F(z), F(u))) + must return {z: A, x: F(A), u: G(y)} and not {z: A, x: F(z), u: G(y)} + + >>> s = {x: y, y: G(z)} + >>> cascade_substitution(s) + >>> print(s) + {x: G(z), y: G(z)} + + Parameters + ---------- + s : Dictionary + This contain a substution''' + + for x in s: + s[x] = subst(s, s.get(x)) + if isinstance(s.get(x),Expr) and not is_variable(s.get(x)): + # Ensure Function Terms are correctly updates by passing over + # them again. + s[x] = subst(s, s.get(x)) def standardize_variables(sentence, dic=None): """Replace all the variables in sentence with new variables.""" From 0a0a1ae4dd9c810823ea9413a7d686c5888f010e Mon Sep 17 00:00:00 2001 From: Alessandro Date: Fri, 16 Aug 2019 03:31:08 +0200 Subject: [PATCH 2/5] added two more test in test_logic.py updated documentation for cascade_substitution function in logic.py --- logic.py | 5 ++--- tests/test_logic.py | 6 ++++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/logic.py b/logic.py index 7bc1add43..d0684077d 100644 --- a/logic.py +++ b/logic.py @@ -193,8 +193,7 @@ def parse_definite_clause(s): # Useful constant Exprs used in examples and code: -A, B, C, D, E, F, G, P, Q, x, y, z = map(Expr, 'ABCDEFGPQxyz') - +A, B, C, D, E, F, G, P, Q, a, x, y, z, u = map(Expr, 'ABCDEFGPQaxyzu') # ______________________________________________________________________________ @@ -1425,7 +1424,7 @@ def cascade_substitution(s): terms are correctly updates by passing over them again. This fix issue: https://github.com/aimacode/aima-python/issues/1053 - unify(P(A, x, F(G(y))), P(z, F(z), F(u))) + unify(expr('P(A, x, F(G(y)))'), expr('P(z, F(z), F(u))')) must return {z: A, x: F(A), u: G(y)} and not {z: A, x: F(z), u: G(y)} >>> s = {x: y, y: G(z)} diff --git a/tests/test_logic.py b/tests/test_logic.py index fe9a9c5e3..dd40b1d41 100644 --- a/tests/test_logic.py +++ b/tests/test_logic.py @@ -163,7 +163,13 @@ def test_unify(): assert unify(x & 4 & y, 6 & y & 4, {}) == {x: 6, y: 4} assert unify(expr('A(x)'), expr('A(B)')) == {x: B} assert unify(expr('American(x) & Weapon(B)'), expr('American(A) & Weapon(y)')) == {x: A, y: B} + assert unify(expr('P(F(x,z), G(u, z))'), expr('P(F(y,a), y)')) == {x: G(u, a), z: a, y: G(u, a)} + # test for https://github.com/aimacode/aima-python/issues/1053 + # unify(expr('P(A, x, F(G(y)))'), expr('P(z, F(z), F(u))')) + # must return {z: A, x: F(A), u: G(y)} and not {z: A, x: F(z), u: G(y)} + assert unify(expr('P(A, x, F(G(y))'), expr('P(z, F(z), F(u))')) == {z: A, x: F(A), u: G(y)} + assert unify(expr('P(x, A, F(G(y)))'), expr('P(F(z), z, F(u))')) == {x: F(A), z: A, u: G(y)} def test_pl_fc_entails(): assert pl_fc_entails(horn_clauses_KB, expr('Q')) From 3d5c0952f9837b3df2e615cb846137535da0c10e Mon Sep 17 00:00:00 2001 From: Alessandro Date: Fri, 16 Aug 2019 03:50:31 +0200 Subject: [PATCH 3/5] Fixed brackets missing in test_logic.py for the new test --- tests/test_logic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_logic.py b/tests/test_logic.py index dd40b1d41..78141be13 100644 --- a/tests/test_logic.py +++ b/tests/test_logic.py @@ -168,7 +168,7 @@ def test_unify(): # test for https://github.com/aimacode/aima-python/issues/1053 # unify(expr('P(A, x, F(G(y)))'), expr('P(z, F(z), F(u))')) # must return {z: A, x: F(A), u: G(y)} and not {z: A, x: F(z), u: G(y)} - assert unify(expr('P(A, x, F(G(y))'), expr('P(z, F(z), F(u))')) == {z: A, x: F(A), u: G(y)} + assert unify(expr('P(A, x, F(G(y)))'), expr('P(z, F(z), F(u))')) == {z: A, x: F(A), u: G(y)} assert unify(expr('P(x, A, F(G(y)))'), expr('P(F(z), z, F(u))')) == {x: F(A), z: A, u: G(y)} def test_pl_fc_entails(): From 9b682e10bab8a5786e3c43e607da1068f629dffc Mon Sep 17 00:00:00 2001 From: Alessandro Date: Fri, 16 Aug 2019 13:50:25 +0200 Subject: [PATCH 4/5] Fixed typo error, missing space and double quotes for docstrings --- logic.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/logic.py b/logic.py index d0684077d..f6c36f84d 100644 --- a/logic.py +++ b/logic.py @@ -1417,13 +1417,13 @@ def subst(s, x): return Expr(x.op, *[subst(s, arg) for arg in x.args]) def cascade_substitution(s): - '''This method allow to return a correct unifier in normal form + """This method allows to return a correct unifier in normal form and perform a cascade substitution to s. For every mapping in s perform a cascade substitution on s.get(x) and if it is replaced with a function ensure that all the function - terms are correctly updates by passing over them again. + terms are correct updates by passing over them again. - This fix issue: https://github.com/aimacode/aima-python/issues/1053 + This issue fix: https://github.com/aimacode/aima-python/issues/1053 unify(expr('P(A, x, F(G(y)))'), expr('P(z, F(z), F(u))')) must return {z: A, x: F(A), u: G(y)} and not {z: A, x: F(z), u: G(y)} @@ -1435,12 +1435,12 @@ def cascade_substitution(s): Parameters ---------- s : Dictionary - This contain a substution''' + This contain a substution""" for x in s: s[x] = subst(s, s.get(x)) - if isinstance(s.get(x),Expr) and not is_variable(s.get(x)): - # Ensure Function Terms are correctly updates by passing over + if isinstance(s.get(x), Expr) and not is_variable(s.get(x)): + # Ensure Function Terms are correct updates by passing over # them again. s[x] = subst(s, s.get(x)) From 01876d5dac12fdd9bf12d699eab28ff002e45f23 Mon Sep 17 00:00:00 2001 From: Alessandro Date: Fri, 16 Aug 2019 14:38:19 +0200 Subject: [PATCH 5/5] comments changed to cascade_substitution function in logic.py --- logic.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/logic.py b/logic.py index f6c36f84d..4b4c4e36d 100644 --- a/logic.py +++ b/logic.py @@ -1435,13 +1435,13 @@ def cascade_substitution(s): Parameters ---------- s : Dictionary - This contain a substution""" + This contain a substution + """ for x in s: s[x] = subst(s, s.get(x)) if isinstance(s.get(x), Expr) and not is_variable(s.get(x)): - # Ensure Function Terms are correct updates by passing over - # them again. + # Ensure Function Terms are correct updates by passing over them again. s[x] = subst(s, s.get(x)) def standardize_variables(sentence, dic=None):