Fixed #41 : Implement concept 'and'
This commit is contained in:
@@ -27,6 +27,15 @@ def concept x has a y as hasa(x,y) pre is_question()
|
||||
def concept x has an y as hasa(x,y) pre is_question()
|
||||
# no need to auto eval as it's a question
|
||||
|
||||
def concept x and y as x and y pre is_question()
|
||||
set_is_lesser(__PRECEDENCE, c:x and y:, 'Sya')
|
||||
set_is_less_than(__PRECEDENCE, c:q:, c:x and y:, 'Sya')
|
||||
|
||||
def concept x or y as x or y pre is_question()
|
||||
set_is_lesser(__PRECEDENCE, c:x or y:, 'Sya')
|
||||
set_is_greater_than(__PRECEDENCE, c:x and y:, c:x or y:, 'Sya')
|
||||
set_is_less_than(__PRECEDENCE, c:q:, c:x or y:, 'Sya')
|
||||
|
||||
# default
|
||||
def concept male
|
||||
def concept female
|
||||
|
||||
@@ -18,6 +18,22 @@ EVAL_STEPS = PARSE_STEPS + [BuiltinConcepts.BEFORE_EVALUATION, BuiltinConcepts.E
|
||||
PARSERS = ["EmptyString", "ShortTermMemory", "Sequence", "Bnf", "Sya", "Python"]
|
||||
|
||||
|
||||
def remove_python_nodes(context, return_values):
|
||||
"""
|
||||
Try to reduce the number of return_values by removing return values with python node
|
||||
:param context:
|
||||
:param return_values:
|
||||
:return:
|
||||
"""
|
||||
res = []
|
||||
for ret_val in return_values:
|
||||
value = context.sheerka.objvalue(ret_val)
|
||||
if not hasattr(value, "get_python_node"):
|
||||
res.append(ret_val)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def is_same_success(context, return_values):
|
||||
"""
|
||||
Returns True if all returns values are successful and have the same value
|
||||
@@ -89,12 +105,25 @@ def expect_one(context, return_values):
|
||||
|
||||
# too many winners, which one to choose ?
|
||||
if number_of_successful > 1:
|
||||
# first, try to remove python node results.
|
||||
# In case of conflict, the concept take precedence over the natural Python result
|
||||
# as it is considered as an override (overload ?)
|
||||
successful_results = remove_python_nodes(context, successful_results)
|
||||
|
||||
if len(successful_results) == 1:
|
||||
return sheerka.ret(
|
||||
context.who,
|
||||
True,
|
||||
successful_results[0].body,
|
||||
parents=return_values)
|
||||
|
||||
if is_same_success(context, successful_results):
|
||||
return sheerka.ret(
|
||||
context.who,
|
||||
True,
|
||||
successful_results[0].value,
|
||||
parents=return_values)
|
||||
|
||||
else:
|
||||
if context.logger and context.logger.isEnabledFor(logging.DEBUG):
|
||||
context.log(f"Too many successful results found by expect_one()", context.who)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
To make Jupyter notebook recognize Sheerka,
|
||||
the file kernel.json must be copied where the kernels are declared
|
||||
|
||||
* First, open the kernel.json file and make sure that the path to SheerkaKernel is correct.
|
||||
* First, open the kernel.json file and make sure that the path to SheerkaKernel.py is correct.
|
||||
* The copy it to the correct location
|
||||
* You can use the command 'jupyter kernelspec install </path/to/kernel>'
|
||||
* or simply copy it using cp ;-)
|
||||
* or simply copy 'Sheerka/kernel.json' into the folder 'kernels' (You may have to create it!)
|
||||
|
||||
Valid locations for kernel.json are
|
||||
Valid locations for 'Sheerka/kernel.json' are
|
||||
|
||||
| | Unix | Windows |
|
||||
|----|------| ---------------|
|
||||
|
||||
@@ -57,7 +57,7 @@ class Event(object):
|
||||
return self._digest
|
||||
|
||||
if not isinstance(self.message, str):
|
||||
raise NotImplementedError
|
||||
raise NotImplementedError(f"message={self.message}")
|
||||
|
||||
to_hash = f"Event:{self.user_id}{self.date}{self.message}{self.parents}".encode("utf-8")
|
||||
self._digest = hashlib.sha256(to_hash).hexdigest()
|
||||
|
||||
@@ -1299,102 +1299,15 @@ as:
|
||||
|
||||
assert sheerka.objvalue(res[0].body.get_value("qty")) == 2
|
||||
|
||||
def test_i_can_implement_implement_the_concept_and(self):
|
||||
init = [
|
||||
"def concept x and y as x and y",
|
||||
"set_is_lesser(__PRECEDENCE, c:x and y:, 'Sya')",
|
||||
]
|
||||
sheerka = self.init_scenario(init)
|
||||
|
||||
class TestSheerkaNonRegFile(TestUsingFileBasedSheerka):
|
||||
def test_i_can_def_several_concepts(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluate_user_input("def concept foo")
|
||||
|
||||
sheerka = self.get_sheerka()
|
||||
res = sheerka.evaluate_user_input("def concept bar")
|
||||
res = sheerka.evaluate_user_input("def concept foo x y where x > 1 and y > 2")
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body.id == "1002"
|
||||
|
||||
def test_i_can_create_concept_with_bnf_definition(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept_a = self.bnf_concept("a", expression=OrderedChoice(StrMatch("one"), StrMatch("two")))
|
||||
sheerka.create_new_concept(self.get_context(sheerka), concept_a)
|
||||
|
||||
res = sheerka.evaluate_user_input("def concept plus from bnf a ('plus' plus)?")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, BuiltinConcepts.NEW_CONCEPT)
|
||||
|
||||
saved_concept = sheerka.om.current_sdp().get(SheerkaConceptManager.CONCEPTS_BY_KEY_ENTRY, "plus")
|
||||
assert saved_concept.key == "plus"
|
||||
assert saved_concept.get_metadata().definition == "a ('plus' plus)?"
|
||||
assert "a" in saved_concept.values()
|
||||
assert "plus" in saved_concept.values()
|
||||
|
||||
expected_bnf = Sequence(
|
||||
ConceptExpression(concept_a, rule_name="a"),
|
||||
Optional(Sequence(StrMatch("plus"), ConceptExpression("plus"))))
|
||||
|
||||
new_concept = res[0].value.body
|
||||
assert new_concept.get_metadata().name == "plus"
|
||||
assert new_concept.get_metadata().definition == "a ('plus' plus)?"
|
||||
assert new_concept.get_bnf() == expected_bnf
|
||||
assert "a" in new_concept.values()
|
||||
assert "plus" in new_concept.values()
|
||||
|
||||
def test_i_can_recognize_bnf_definitions_from_separate_instances(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept_a = sheerka.evaluate_user_input("def concept a from bnf 'one' 'two'")[0].body.body
|
||||
|
||||
sheerka = self.get_sheerka()
|
||||
res = sheerka.evaluate_user_input("one two")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, concept_a)
|
||||
|
||||
# add another bnf definition
|
||||
concept_b = sheerka.evaluate_user_input("def concept b from bnf a 'three'")[0].body.body
|
||||
|
||||
sheerka = self.get_sheerka()
|
||||
res = sheerka.evaluate_user_input("one two") # previous one still works
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, concept_a)
|
||||
|
||||
res = self.get_sheerka().evaluate_user_input("one two three") # new one works
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, concept_b)
|
||||
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(eval_body=True), res[0].value)
|
||||
assert evaluated.body == "one two three"
|
||||
assert evaluated.get_value("a") == sheerka.new(concept_a.key, body="one two").init_key()
|
||||
|
||||
def test_i_can_eval_sophisticated_bnf_concepts_after_restart(self):
|
||||
self.init_scenario([
|
||||
"def concept one as 1",
|
||||
"def concept number",
|
||||
"set_isa(one, number)",
|
||||
"def concept twenty as 20",
|
||||
"set_isa(twenty, number)",
|
||||
"def concept twenties from bnf twenty number where number < 10 as twenty + number",
|
||||
"set_isa(twenties, number)",
|
||||
"def concept thirty as 30",
|
||||
"set_isa(thirty, number)",
|
||||
"def concept thirties from bnf thirty number where number < 10 as thirty + number",
|
||||
"set_isa(thirties, number)",
|
||||
])
|
||||
|
||||
sheerka = self.get_sheerka() # another instance
|
||||
|
||||
assert sheerka.evaluate_user_input("eval twenty one")[0].body == 21
|
||||
assert sheerka.evaluate_user_input("eval thirty one")[0].body == 31
|
||||
|
||||
def test_i_can_pop_ontology_after_restart(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluate_user_input("push_ontology('test')")
|
||||
|
||||
sheerka = self.new_sheerka_instance(False)
|
||||
|
||||
res = sheerka.evaluate_user_input("pop_ontology()")
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].body, BuiltinConcepts.ONTOLOGY_REMOVED)
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
from core.builtin_concepts_ids import BuiltinConcepts
|
||||
from core.sheerka.services.SheerkaConceptManager import SheerkaConceptManager
|
||||
from parsers.BnfNodeParser import OrderedChoice, StrMatch, Sequence, ConceptExpression, Optional
|
||||
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
|
||||
|
||||
|
||||
class TestSheerkaNonRegFile(TestUsingFileBasedSheerka):
|
||||
def test_i_can_def_several_concepts(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluate_user_input("def concept foo")
|
||||
|
||||
sheerka = self.get_sheerka()
|
||||
res = sheerka.evaluate_user_input("def concept bar")
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert res[0].body.body.id == "1002"
|
||||
|
||||
def test_i_can_create_concept_with_bnf_definition(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept_a = self.bnf_concept("a", expression=OrderedChoice(StrMatch("one"), StrMatch("two")))
|
||||
sheerka.create_new_concept(self.get_context(sheerka), concept_a)
|
||||
|
||||
res = sheerka.evaluate_user_input("def concept plus from bnf a ('plus' plus)?")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, BuiltinConcepts.NEW_CONCEPT)
|
||||
|
||||
saved_concept = sheerka.om.current_sdp().get(SheerkaConceptManager.CONCEPTS_BY_KEY_ENTRY, "plus")
|
||||
assert saved_concept.key == "plus"
|
||||
assert saved_concept.get_metadata().definition == "a ('plus' plus)?"
|
||||
assert "a" in saved_concept.values()
|
||||
assert "plus" in saved_concept.values()
|
||||
|
||||
expected_bnf = Sequence(
|
||||
ConceptExpression(concept_a, rule_name="a"),
|
||||
Optional(Sequence(StrMatch("plus"), ConceptExpression("plus"))))
|
||||
|
||||
new_concept = res[0].value.body
|
||||
assert new_concept.get_metadata().name == "plus"
|
||||
assert new_concept.get_metadata().definition == "a ('plus' plus)?"
|
||||
assert new_concept.get_bnf() == expected_bnf
|
||||
assert "a" in new_concept.values()
|
||||
assert "plus" in new_concept.values()
|
||||
|
||||
def test_i_can_recognize_bnf_definitions_from_separate_instances(self):
|
||||
sheerka = self.get_sheerka()
|
||||
concept_a = sheerka.evaluate_user_input("def concept a from bnf 'one' 'two'")[0].body.body
|
||||
|
||||
sheerka = self.get_sheerka()
|
||||
res = sheerka.evaluate_user_input("one two")
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, concept_a)
|
||||
|
||||
# add another bnf definition
|
||||
concept_b = sheerka.evaluate_user_input("def concept b from bnf a 'three'")[0].body.body
|
||||
|
||||
sheerka = self.get_sheerka()
|
||||
res = sheerka.evaluate_user_input("one two") # previous one still works
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, concept_a)
|
||||
|
||||
res = self.get_sheerka().evaluate_user_input("one two three") # new one works
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].value, concept_b)
|
||||
|
||||
evaluated = sheerka.evaluate_concept(self.get_context(eval_body=True), res[0].value)
|
||||
assert evaluated.body == "one two three"
|
||||
assert evaluated.get_value("a") == sheerka.new(concept_a.key, body="one two").init_key()
|
||||
|
||||
def test_i_can_eval_sophisticated_bnf_concepts_after_restart(self):
|
||||
self.init_scenario([
|
||||
"def concept one as 1",
|
||||
"def concept number",
|
||||
"set_isa(one, number)",
|
||||
"def concept twenty as 20",
|
||||
"set_isa(twenty, number)",
|
||||
"def concept twenties from bnf twenty number where number < 10 as twenty + number",
|
||||
"set_isa(twenties, number)",
|
||||
"def concept thirty as 30",
|
||||
"set_isa(thirty, number)",
|
||||
"def concept thirties from bnf thirty number where number < 10 as thirty + number",
|
||||
"set_isa(thirties, number)",
|
||||
])
|
||||
|
||||
sheerka = self.get_sheerka() # another instance
|
||||
|
||||
assert sheerka.evaluate_user_input("eval twenty one")[0].body == 21
|
||||
assert sheerka.evaluate_user_input("eval thirty one")[0].body == 31
|
||||
|
||||
def test_i_can_pop_ontology_after_restart(self):
|
||||
sheerka = self.get_sheerka()
|
||||
sheerka.evaluate_user_input("push_ontology('test')")
|
||||
|
||||
sheerka = self.new_sheerka_instance(False)
|
||||
|
||||
res = sheerka.evaluate_user_input("pop_ontology()")
|
||||
|
||||
assert len(res) == 1
|
||||
assert res[0].status
|
||||
assert sheerka.isinstance(res[0].body, BuiltinConcepts.ONTOLOGY_REMOVED)
|
||||
Reference in New Issue
Block a user