e69745adc8
Fixed #99 : SheerkaQueryManager: I can manage contains predicate when filtering objects Fixed #97 : ERROR: list indices must be integers or slices, not Concept Fixed #96 : SequenceNodeParser: SequenceNodeParser must correctly handle concept definition Fixed #95 : ResolveAmbiguity must not remove concepts that do not require evaluation Fixed #94 : Concepts with the same key are lost when new ontology Fixed #93 : Introduce BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED Fixed #92 : ExpressionParser: Implement compile_disjunctions() Fixed #91 : Implement get_concepts_complexity(context, concepts, concept_parts) Fixed #90 : ResolveAmbiguity : where predicate is not used to resolve ambiguity Fixed #89 : ResolveAmbiguityEvaluator: Concepts embedded in ConceptNode are not resolved Fixed #88: SyaNodeParser: Parse multiple parameters when some of the are not recognized Fixed #87: SyaNodeParser : Parse the multiple parameters
233 lines
8.9 KiB
Python
233 lines
8.9 KiB
Python
import pytest
|
|
|
|
from core.builtin_concepts import BuiltinConcepts
|
|
from core.concept import Concept
|
|
from core.sheerka.services.SheerkaExecute import ParserInput
|
|
from evaluators.BaseEvaluator import BaseEvaluator
|
|
from evaluators.ResolveAmbiguityEvaluator import ResolveAmbiguityEvaluator
|
|
from parsers.ExactConceptParser import ExactConceptParser
|
|
from parsers.SyaNodeParser import SyaNodeParser
|
|
from tests.BaseTest import BaseTest
|
|
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
|
|
|
pretval = BaseTest.pretval
|
|
|
|
|
|
class TestResolveAmbiguityEvaluator(TestUsingMemoryBasedSheerka):
|
|
|
|
@pytest.mark.parametrize("return_values, expected", [
|
|
([pretval(Concept("foo"), source="source"), pretval(Concept("bar"), source="source")], True),
|
|
([pretval(Concept("foo"), source="source"), pretval(Concept("bar"), source="source", status=False)], False),
|
|
([pretval(Concept("foo"), source="source1"), pretval(Concept("bar"), source="source2")], False),
|
|
])
|
|
def test_i_can_match(self, return_values, expected):
|
|
context = self.get_context()
|
|
assert ResolveAmbiguityEvaluator().matches(context, return_values) == expected
|
|
|
|
def test_i_can_match_when_the_input_comes_from_an_evaluator(self):
|
|
ret_val1 = pretval(Concept("foo"), source="source", parser=BaseEvaluator.get_name("evaluator"))
|
|
ret_val2 = pretval(Concept("bar"), source="source", parser=BaseEvaluator.get_name("evaluator"))
|
|
return_values = [ret_val1, ret_val2]
|
|
|
|
context = self.get_context()
|
|
assert ResolveAmbiguityEvaluator().matches(context, return_values)
|
|
|
|
def test_i_can_match_when_concept_nodes(self):
|
|
sheerka, context, a, foo_1, foo_2 = self.init_concepts(
|
|
Concept("a"),
|
|
Concept("foo x").def_var("x"),
|
|
Concept("foo y").def_var("y"),
|
|
create_new=True
|
|
)
|
|
|
|
return_values = SyaNodeParser().parse(context, ParserInput("foo a"))
|
|
assert ResolveAmbiguityEvaluator().matches(context, return_values)
|
|
|
|
def test_i_can_match_when_concept_node_mixed_with_concept(self):
|
|
sheerka, context, a, foo_1, foo_a = self.init_concepts(
|
|
Concept("a"),
|
|
Concept("foo x").def_var("x"),
|
|
Concept("foo a"),
|
|
create_new=True
|
|
)
|
|
|
|
sya_return_value = SyaNodeParser().parse(context, ParserInput("foo a"))
|
|
|
|
assert ResolveAmbiguityEvaluator().matches(context, [sya_return_value, pretval(foo_a, source="foo a")])
|
|
|
|
def test_i_can_manage_when_no_source(self):
|
|
context = self.get_context()
|
|
return_values = [BaseTest.retval(Concept("foo"))]
|
|
|
|
assert not ResolveAmbiguityEvaluator().matches(context, return_values)
|
|
|
|
def test_i_can_eval(self):
|
|
context = self.get_context()
|
|
return_values = [
|
|
self.pretval(Concept("hello a").def_var("a", "world"), "hello word"),
|
|
self.pretval(Concept("hello world"), "hello word"),
|
|
self.pretval(Concept("hello world", pre="False"), "hello word"),
|
|
self.retval(Concept("not a parser result")),
|
|
self.retval(Concept("status is false"), status=False),
|
|
self.pretval(Concept("false parser result"), status=False),
|
|
]
|
|
|
|
evaluator = ResolveAmbiguityEvaluator()
|
|
evaluator.matches(context, return_values)
|
|
res = evaluator.eval(context, return_values)
|
|
|
|
assert len(res) == 1
|
|
resolved = res[0]
|
|
|
|
assert resolved.who == evaluator.name
|
|
assert resolved.body == return_values[1].body
|
|
assert resolved.parents == [
|
|
return_values[0],
|
|
return_values[1],
|
|
return_values[2],
|
|
]
|
|
|
|
@pytest.mark.parametrize("concepts, expected", [
|
|
([Concept("c1"), Concept("c2", where="True")], "c2"),
|
|
([Concept("c1"), Concept("c2", pre="True")], "c2"),
|
|
([Concept("c1"), Concept("c2", where="False")], "c1"),
|
|
([Concept("c1"), Concept("c2", pre="False")], "c1"),
|
|
([Concept("c1", pre="True"), Concept("c2", where="True")], "c1"),
|
|
([Concept("c1", pre="False"), Concept("c2", where="True")], "c2"),
|
|
([Concept("c1", pre="False"), Concept("c2", where="False")], BuiltinConcepts.NO_RESULT),
|
|
])
|
|
def test_i_can_eval_2(self, concepts, expected):
|
|
context = self.get_context()
|
|
return_values = [self.pretval(c, source="foo") for c in concepts]
|
|
|
|
evaluator = ResolveAmbiguityEvaluator()
|
|
evaluator.matches(context, return_values)
|
|
res = evaluator.eval(context, return_values)
|
|
|
|
assert len(res) == 1
|
|
if expected != BuiltinConcepts.NO_RESULT:
|
|
selected_concept = res[0].body.body
|
|
assert selected_concept.name == expected
|
|
else:
|
|
assert res[0].body == BuiltinConcepts.NO_RESULT
|
|
|
|
@pytest.mark.parametrize("concepts", [
|
|
[Concept("c1"), Concept("c2")],
|
|
[Concept("c1", pre="True"), Concept("c2", pre="True")],
|
|
])
|
|
def test_i_can_eval_when_same_complexity(self, concepts):
|
|
context = self.get_context()
|
|
return_values = [self.pretval(c, "foo") for c in concepts]
|
|
|
|
evaluator = ResolveAmbiguityEvaluator()
|
|
evaluator.matches(context, return_values)
|
|
res = evaluator.eval(context, return_values)
|
|
|
|
assert res is None
|
|
|
|
def test_i_can_eval_all_fail(self):
|
|
context = self.get_context()
|
|
return_values = [
|
|
self.pretval(Concept("hello world", pre="2 < 1"), "hello word"),
|
|
self.pretval(Concept("hello world", pre="False"), "hello word"),
|
|
]
|
|
|
|
evaluator = ResolveAmbiguityEvaluator()
|
|
evaluator.matches(context, return_values)
|
|
res = evaluator.eval(context, return_values)
|
|
|
|
assert len(res) == 1
|
|
resolved = res[0]
|
|
|
|
assert resolved.who == evaluator.name
|
|
assert resolved.body == BuiltinConcepts.NO_RESULT
|
|
assert resolved.parents == [
|
|
return_values[0],
|
|
return_values[1],
|
|
]
|
|
|
|
def test_i_can_eval_all_pass(self):
|
|
"""
|
|
If they all pass, that means that no concept was reduced
|
|
-> We need to act like resolve ambiguity was not called
|
|
:return:
|
|
"""
|
|
context = self.get_context()
|
|
return_values = [
|
|
self.pretval(Concept("hello world 1"), "hello word"),
|
|
self.pretval(Concept("hello world 2"), "hello word"),
|
|
]
|
|
|
|
evaluator = ResolveAmbiguityEvaluator()
|
|
evaluator.matches(context, return_values)
|
|
res = evaluator.eval(context, return_values)
|
|
|
|
assert res is None
|
|
|
|
def test_i_can_eval_to_the_simplest_concept(self):
|
|
"""
|
|
def concept foo x where x
|
|
def concept foo a
|
|
|
|
When the input is foo a, 'foo x' must be discarded as concept 'foo a' is more accurate
|
|
:return:
|
|
"""
|
|
|
|
sheerka, context, a, foo_1, foo_a = self.init_concepts(
|
|
Concept("a"),
|
|
Concept("foo x").def_var("x"),
|
|
Concept("foo a"),
|
|
create_new=True
|
|
)
|
|
|
|
sya_return_value = SyaNodeParser().parse(context, ParserInput("foo a"))
|
|
exact_concept_return_value = pretval(foo_a, source="foo a")
|
|
return_values = [sya_return_value, exact_concept_return_value]
|
|
evaluator = ResolveAmbiguityEvaluator()
|
|
|
|
evaluator.matches(context, return_values)
|
|
res = evaluator.eval(context, return_values)
|
|
|
|
assert len(res) == 1
|
|
assert res[0].who == evaluator.name
|
|
assert res[0].body == exact_concept_return_value.body
|
|
assert res[0].parents == return_values
|
|
|
|
def test_i_can_eval_to_the_simplest_concept_when_concept_nodes(self):
|
|
"""
|
|
Same explanation than test_i_can_eval_to_the_simplest_concept()
|
|
:return:
|
|
"""
|
|
sheerka, context, a, b, foo_1, foo_2 = self.init_concepts(
|
|
Concept("a"),
|
|
Concept("b"),
|
|
Concept("foo x y").def_var("x").def_var("y"),
|
|
Concept("foo a x").def_var("x"),
|
|
create_new=True
|
|
)
|
|
|
|
return_values = SyaNodeParser().parse(context, ParserInput("foo a b"))
|
|
evaluator = ResolveAmbiguityEvaluator()
|
|
|
|
evaluator.matches(context, return_values)
|
|
res = evaluator.eval(context, return_values)
|
|
|
|
assert len(res) == 1
|
|
assert res[0].who == evaluator.name
|
|
assert sheerka.isinstance(res[0].body.body[0].concept, foo_2)
|
|
|
|
def test_i_can_eval_when_non_instance_concepts(self):
|
|
sheerka, context, foo_1, foo_2 = self.init_concepts(
|
|
Concept("foo x", body="1", pre="True").def_var("x"),
|
|
Concept("foo x", body="2", pre="True").def_var("x"),
|
|
create_new=True
|
|
)
|
|
|
|
exact_parser_return_values = ExactConceptParser().parse(context, ParserInput("c:foo x:"))
|
|
evaluator = ResolveAmbiguityEvaluator()
|
|
|
|
evaluator.matches(context, exact_parser_return_values)
|
|
res = evaluator.eval(context, exact_parser_return_values)
|
|
|
|
assert res is None # means that there is nothing to resolve as the concepts are not instances
|