Fixed #100 : SheerkaAdmin: Add builtins() command

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
This commit is contained in:
2021-07-31 08:52:00 +02:00
parent 7dcaa9c111
commit e69745adc8
70 changed files with 1561 additions and 455 deletions
+73 -10
View File
@@ -7,8 +7,10 @@ from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept, ConceptParts, DEFINITION_TYPE_BNF, concept_part_value
from core.global_symbols import NotInit, NotFound, INIT_AST_PARSERS, DEFAULT_EVALUATORS
from core.rule import Rule
from core.sheerka.services.SheerkaExecute import ParserInput
from core.tokenizer import Tokenizer, TokenKind
from core.utils import as_bag
from parsers.BaseExpressionParser import compile_disjunctions, AndNode
from parsers.BaseNodeParser import SourceCodeNode, ConceptNode, UnrecognizedTokensNode, SourceCodeWithConceptNode, \
RuleNode, LexerNode
from parsers.BaseParser import ParsingError
@@ -205,7 +207,7 @@ def only_successful(context, return_values):
def resolve_ambiguity(context, concepts):
"""
From the list of concepts, elect the one(s) that best suit(s) the context
Use the PRE metadata to choose the correct concepts
Use the PRE and WHERE metadata to choose the correct concepts
:param context:
:param concepts:
:return:
@@ -214,8 +216,9 @@ def resolve_ambiguity(context, concepts):
# we first sort by condition complexity. The more complex is the PRE condition, the more likely
# the concept matches the context
by_complexity = {}
parts = [concept_part_value(ConceptParts.PRE), concept_part_value(ConceptParts.WHERE)]
for c in concepts:
by_complexity.setdefault(get_condition_complexity(c, concept_part_value(ConceptParts.PRE)), []).append(c)
by_complexity.setdefault(get_concept_complexity(context, c, parts), []).append(c)
remaining_concepts = []
for complexity in sorted(by_complexity.keys(), reverse=True):
@@ -226,14 +229,14 @@ def resolve_ambiguity(context, concepts):
evaluated = context.sheerka.evaluate_concept(context, c,
eval_body=False,
validation_only=True,
metadata=[ConceptParts.PRE])
metadata=[ConceptParts.PRE, ConceptParts.WHERE])
if context.sheerka.is_success(evaluated) or evaluated.key == c.key:
remaining_concepts.append(c)
if len(remaining_concepts) > 0:
break # no need to check concept with lower complexity
if len(remaining_concepts) in (0, 1):
if len(remaining_concepts) < 2:
return remaining_concepts # they all failed the pre conditions or one champ is found
# for concepts with the same condition complexity, we choose the one that has the less number of variables
@@ -246,19 +249,58 @@ def resolve_ambiguity(context, concepts):
return by_number_of_vars[min(by_number_of_vars.keys())]
def get_condition_complexity(concept, concept_part_str):
def get_condition_complexity(context, condition):
if condition is None or condition.strip() == "":
return 0
# # count the number of conjunctions
from parsers.LogicalOperatorParser import LogicalOperatorParser
parser = LogicalOperatorParser()
res = parser.parse(context, ParserInput(condition))
if not res.status:
return 0
disjunctions = compile_disjunctions(res.body.body)
complexity = 0
for conjunction in disjunctions:
node_complexity = len(conjunction.parts) if isinstance(conjunction, AndNode) else 1
if node_complexity > complexity:
complexity = node_complexity
return complexity
def get_concept_complexity(context, concept, concepts_parts):
"""
Need to find a proper algorithm to compute the complexity of a concept metadata
So far, the concept is considered as complex if it has concept_part_str (so far with concept_part_str='pre')
:param context:
:param concept:
:param concept_part_str:
:param concepts_parts:
:return:
"""
value = getattr(concept.get_metadata(), concept_part_str)
if value is None or value.strip() == 0:
return 0
complexity = 0
for i, parts in enumerate(reversed(concepts_parts)):
return 1 # no real computing as of now
for part in parts.split("|"):
value = getattr(concept.get_metadata(), part)
part_complexity = get_condition_complexity(context, value)
if part_complexity > 0:
complexity += part_complexity + (i * 100)
return complexity
def get_concepts_complexity(context, concepts, concepts_parts):
"""
compute the complexity of the concepts, relatively to each others
:param context:
:param concepts: concepts
:param concepts_parts: metadata to use to compute the complexity
:return:
"""
return {c.id or c.name: get_concept_complexity(context, c, concepts_parts) for c in concepts}
def only_parsers_results(context, return_values):
@@ -723,6 +765,27 @@ def set_is_evaluated(concepts, check_nb_variables=False):
concepts.get_hints().is_evaluated = True
def update_concepts_hints(concepts, is_evaluated=None, recognized_by=None, is_instance=None):
if concepts is None:
return
def update_concept_hints(c, _is_evaluated, _recognized_by, _is_instance):
if _is_evaluated is not None:
c.get_hints().is_evaluated = _is_evaluated
if _recognized_by is not None:
c.get_hints().recognized_by = _recognized_by
if _is_instance is not None:
c.get_hints().is_instance = _is_instance
if hasattr(concepts, "__iter__"):
for concept in concepts:
update_concept_hints(concept, is_evaluated, recognized_by, is_instance)
else:
update_concept_hints(concepts, is_evaluated, recognized_by, is_instance)
def ensure_concept(*concepts):
if hasattr(concepts, "__iter__"):
for concept in concepts: