Fixed #41 : Implement concept 'and'

This commit is contained in:
2021-03-06 19:12:22 +01:00
parent 05577012f3
commit bd8e027827
6 changed files with 153 additions and 98 deletions
+9
View File
@@ -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
+29
View File
@@ -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)
+3 -3
View File
@@ -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 |
|----|------| ---------------|
+1 -1
View File
@@ -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()
+7 -94
View File
@@ -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)