41namespace LinguisticProcessing {
59 return (r1->
setOfRules().front()->getWeight() >
76 m_automatonControlParams(),
87 LDEBUG <<
"Recognizer::Recognizer copy constructor";
112 LDEBUG <<
"Recognizer::Recognizer operator=";
135 LDEBUG <<
"Recognizer::init" << (
void*)
this;
151 m_language=manager->getInitializationParameters().language;
156 if (!rulesFile.isEmpty())
168 LERROR <<
"No param 'rules' in recognizer group for language " << (int)
m_language;
175 uint64_t val=atol(str.c_str());
178 LWARN <<
"maxDepthStack is 0: keep default value";
191 uint64_t val=atol(str.c_str());
194 LWARN <<
"maxTransitionsExplored is 0: keep default value";
207 uint64_t val=atol(str.c_str());
210 LWARN <<
"maxNbResults is 0: keep default value";
223 uint64_t val=atol(str.c_str());
226 LWARN <<
"maxResultSize is 0: keep default value";
252 map<Rule*,Rule*> pointersMap;
261 for (uint64_t i(0); i<r.
m_rules.size(); i++)
265 for (uint64_t j(0); j<r.
m_rules[i].second.size(); j++)
284 for (uint64_t i(0); i<
m_rules.size(); i++)
332 vector<RecognizerMatch>& matches,
333 std::set<Common::MediaticData::EntityType>* forbiddenTypes,
334 bool stopAtFirstSuccess,
335 bool onlyOneSuccessPerType,
336 bool applySameRuleWhileSuccess)
const {
342 if( gazeteerTrigger != 0 ) {
345 deque<LinguisticGraphVertex> vertices;
347 bool match = gazeteerTrigger->
matchPath(graph, position, end, &searchGraph, analysis, token, vertices, data);
349 for( std::deque<LinguisticGraphVertex>::const_iterator vIt = vertices.begin(); vIt != vertices.end() ; vIt++ ) {
355 triggermatch.
setHead(position);
362 triggermatch.
setHead(position);
370 if (onlyOneSuccessPerType && forbiddenTypes==0) {
371 LERROR <<
"Recognizer::testSetOfRules: cannot use onlyOneSuccessPerType "
372 <<
"when forbidden types are not allowed";
373 onlyOneSuccessPerType=
false;
377 uint64_t nbSuccess(0);
384 LDEBUG <<
"Recognizer::testSetOfRules: testing set of rules triggered by " << trigger <<
" on vertex " << position;
385 LDEBUG <<
"onlyOneSuccessPerType=" << onlyOneSuccessPerType;
386 if (logger.isDebugEnabled()) {
387 std::ostringstream oss;
388 for (
const auto& rule: rules) {
389 oss <<
" - " << rule->getWeight();
391 LDEBUG <<
"Rule weights" << oss.str();
395 bool reapplySameRule(
false);
397 for (
auto rule = rules.cbegin(); rule != rules.cend(); rule++) {
398 const auto& currentRule = *rule;
400 if (logger.isDebugEnabled()) {
401 LDEBUG <<
"Recognizer::testSetOfRules: testing rule "<<*currentRule <<
","
402 << currentRule->getRuleId() <<
" of type "
403 << currentRule->getType() <<
",reapply="
404 << reapplySameRule <<
" from " << position;
408 if (forbiddenTypes && forbiddenTypes->find(currentRule->getType()) != forbiddenTypes->end()) {
429 bool constraintsVerified =
true;
430 for (
const auto& elt: triggermatch) {
431 if (!trigger.
checkConstraints(graph, elt.getVertex(),analysis, constraintCheckList)) {
433 constraintsVerified=
false;
437 if (! constraintsVerified) {
439 if (!currentRule->negative()) {
440 currentRule->executeActions(graph,
454 bool success = currentRule->test(graph, left, right,
455 begin, end, analysis,
456 leftmatch, rightmatch,
457 constraintCheckList,forward,backward,
461 std::unique_ptr<RecognizerMatch> match=
nullptr;
466 match=std::make_unique<RecognizerMatch>(leftmatch);
467 if (leftmatch.
getHead() != 0) {
468 match->setHead(leftmatch.
getHead());
479 match->addBack(triggermatch);
481 if (triggermatch.
getHead() != 0) {
482 match->setHead(triggermatch.
getHead());
485 match->addBack(rightmatch);
487 match->removeUnkeptAtExtremity();
489 match->setType(currentRule->getType());
490 match->setLinguisticProperties(currentRule->getLinguisticProperties());
491 match->setContextual(currentRule->contextual());
498 bool actionSuccess =
true;
499 if (!currentRule->negative()) {
500 actionSuccess = currentRule->executeActions(graph, analysis,
508 if (logger.isDebugEnabled()) {
516 LDEBUG <<
"Recognizer::testSetOfRules: trigger " << v <<
"[" << str <<
"]:rule "
517 << currentRule->getRuleId() <<
"-> success=" << success
518 <<
",actionSuccess=" << actionSuccess;
522 LDEBUG <<
"Recognizer::testSetOfRules: vertex " << v <<
"[" << str <<
"]:rule "
523 << currentRule->getRuleId() <<
"-> success= false";
528 if (success && actionSuccess) {
529 if (forbiddenTypes && currentRule->negative()) {
530 forbiddenTypes->insert(currentRule->getType());
534 LINFO <<
"Recognizer::testSetOfRules: execute rule " << currentRule->getRuleId()
535 <<
" of type "<< currentRule->getType()
537 <<
") on vertex " << position;
539 if (stopAtFirstSuccess||(recoData !=
nullptr && !recoData->
getNextVertices().empty())) {
540 matches.push_back(*match);
542 if (logger.isDebugEnabled() && recoData !=
nullptr) {
543 LDEBUG <<
"Recognizer::testSetOfRules: Returning from testSetOfRules cause stopAtFirstSuccess ("
544 << stopAtFirstSuccess <<
") or next vertices empty ("
552 if (applySameRuleWhileSuccess) {
553 if (reapplySameRule) {
554 if (*match==matches.back()) {
559 reapplySameRule=
false;
568 reapplySameRule=
true;
572 matches.push_back(*match);
574 if (onlyOneSuccessPerType) {
577 forbiddenTypes->insert(currentRule->getType());
584 reapplySameRule=
false;
601 if (norm.isEmpty()) {
620 std::vector<RecognizerMatch>& result,
621 bool testAllVertices,
622 bool stopAtFirstSuccess,
623 bool onlyOneSuccessPerType,
624 bool returnAtFirstSuccess,
625 bool applySameRuleWhileSuccess)
const
636 onlyOneSuccessPerType,
637 returnAtFirstSuccess,
638 applySameRuleWhileSuccess);
650 std::vector<RecognizerMatch>& result,
651 bool testAllVertices,
652 bool stopAtFirstSuccess,
653 bool onlyOneSuccessPerType,
654 bool returnAtFirstSuccess,
655 bool applySameRuleWhileSuccess)
const
662 if (returnAtFirstSuccess) {
663 stopAtFirstSuccess=
true;
669 << begin <<
" to vertex " << end;
670 LDEBUG <<
" up bound: " << upstreamBound <<
"; down bound: " << downstreamBound <<
"; testAllVertices: " << testAllVertices;
671 LDEBUG <<
" stopAtFirstSuccess: " << stopAtFirstSuccess <<
"; onlyOneSuccessPerType: " << onlyOneSuccessPerType;
672 LDEBUG <<
" returnAtFirstSuccess: " << returnAtFirstSuccess <<
"; applySameRuleWhileSuccess: " << applySameRuleWhileSuccess;
675 uint64_t numberOfRecognized(0);
679 std::deque<LinguisticGraphVertex> toVisit;
680 std::set<LinguisticGraphVertex> visited;
682 toVisit.push_back(begin);
687 set<LinguisticGraphVertex> afterTheEnd;
689 auto [outEdge,outEdge_end]=out_edges(downstreamBound,*(graph.
getGraph()));
690 for (; outEdge!=outEdge_end; outEdge++) {
692 afterTheEnd.insert(next);
696 bool lastReached =
false;
697 while (!toVisit.empty())
699 auto currentVertex = toVisit.front();
702 if (visited.find(currentVertex) != visited.end())
707 visited.insert(currentVertex);
709 LDEBUG <<
"to visit size=" << toVisit.size() <<
" ; currentVertex=" << currentVertex;
717 if (currentVertex == end ) {
721 if (currentVertex != graph.
firstVertex() && currentVertex != begin) {
723 LDEBUG <<
"Recognizer: test on vertex " << currentVertex;
726 upstreamBound,downstreamBound,
729 onlyOneSuccessPerType,
730 applySameRuleWhileSuccess);
732 numberOfRecognized++;
733 if (returnAtFirstSuccess)
734 return numberOfRecognized;
735 if (! testAllVertices) {
739 if (currentVertex==end || afterTheEnd.find(currentVertex)!=afterTheEnd.end()) {
741 LDEBUG <<
"success: reached the end, stop";
746 LDEBUG <<
"success: continue from vertex " << currentVertex;
764 auto [outEdge,outEdge_end] = out_edges(currentVertex,*(graph.
getGraph()));
766 for (; outEdge!=outEdge_end; outEdge++) {
767 auto next=target(*outEdge,*(graph.
getGraph()));
768 if (visited.find(next)==visited.end()) {
770 LDEBUG <<
"Recognizer: adding out edge target vertex to the 'to visit' list: " << next;
772 toVisit.push_back(next);
780 LDEBUG <<
"Recognizer: already visited:" << next;
784 auto recoData = std::dynamic_pointer_cast<RecognizerData>(analysis.
getData(
"RecognizerData"));
785 if (
nullptr != recoData)
787 auto& nextVertices = recoData->getNextVertices();
788 if (!nextVertices.empty())
791 LDEBUG <<
"Recognizer: adding next vertices to the 'to visit' list";
793 for (
auto nvit = nextVertices.begin(), nvit_end = nextVertices.end(); nvit != nvit_end; nvit++)
798 toVisit.push_front(*nvit);
800 nextVertices.clear();
804 LDEBUG <<
"Recognizer: 'to visit' list size is now: " << toVisit.size();
807 return numberOfRecognized;
820 std::vector<RecognizerMatch>& result,
821 bool stopAtFirstSuccess,
822 bool onlyOneSuccessPerType,
823 bool applySameRuleWhileSuccess)
const
831 LERROR <<
"no token for vertex " << current;
837 LERROR <<
"no data for vertex " << current;
842 vector<TriggerRule*> matchingRules;
843 set<Common::MediaticData::EntityType> forbiddenTypes;
844 uint64_t nbSuccess=0;
848 if (! matchingRules.empty()) {
849 for (
auto ruleSet=matchingRules.begin(), ruleSet_end=matchingRules.end(); ruleSet!=ruleSet_end; ruleSet++) {
850 auto nbSuccessForTheseRules=
852 (*ruleSet)->setOfRules(),
853 graph, current, begin, end, analysis,
854 result, &forbiddenTypes,
856 onlyOneSuccessPerType,
857 applySameRuleWhileSuccess);
858 if (nbSuccessForTheseRules>0) {
859 nbSuccess+=nbSuccessForTheseRules;
862 auto& lastSuccess=result.back();
864 auto currentTokenEnd=t->position()+t->length();
865 auto recoData = std::dynamic_pointer_cast<RecognizerData>(analysis.
getData(
"RecognizerData"));
866 if (stopAtFirstSuccess||(recoData != 0 && !recoData->getNextVertices().empty())) {
867 if (lastSuccess.positionEnd() >= currentTokenEnd) {
868 current=lastSuccess.getEnd();
874 for(
auto rule: matchingRules) {
880 forbiddenTypes.clear();
894 typedef std::vector<RecognizerMatch>::iterator vectorRecognizerMatchIterator;
896 uint64_t numberOfOverlappingEntities(0);
898 if (listEntities.empty()) {
899 return numberOfOverlappingEntities;
904 vectorRecognizerMatchIterator currentEntity(listEntities.begin());
905 vectorRecognizerMatchIterator nextEntity(currentEntity);
907 while (nextEntity != listEntities.end()) {
908 if (currentEntity->isOverlapping(*nextEntity)) {
909 numberOfOverlappingEntities++;
910 currentEntity=listEntities.erase(currentEntity);
911 nextEntity=currentEntity;
922 vectorRecognizerMatchIterator currentEntity(listEntities.begin());
923 vectorRecognizerMatchIterator previousEntity(currentEntity);
925 while (currentEntity != listEntities.end()) {
926 if (currentEntity->isOverlapping(*previousEntity)) {
927 numberOfOverlappingEntities++;
928 currentEntity=listEntities.erase(currentEntity);
938 vectorRecognizerMatchIterator currentEntity(listEntities.begin());
939 vectorRecognizerMatchIterator previousEntity(currentEntity);
941 while (currentEntity != listEntities.end()) {
942 if (currentEntity->isOverlapping(*previousEntity)) {
943 numberOfOverlappingEntities++;
944 if (currentEntity->numberOfElements()
945 < previousEntity->numberOfElements()) {
946 currentEntity=listEntities.erase(currentEntity);
949 previousEntity=listEntities.erase(previousEntity);
950 currentEntity=previousEntity;
965 return numberOfOverlappingEntities;
978 std::vector<TriggerRule*>& matchingSetOfRules)
const
980 matchingSetOfRules.clear();
983 std::vector<const TriggerRule*> matchingRules;
984 m_searchStructure.findMatchingTransitions(graph,vertex,analysis,token,data,matchingRules);
989 for (
auto rule: matchingRules) {
990 for (
auto r: rule->setOfRules()) {
998 if (! matchingSetOfRules.empty()) {
999 auto it=matchingSetOfRules.begin();
1000 auto currentTrigger=(*it)->transitionUnit();
1003 while (next!=matchingSetOfRules.end()) {
1004 if ((*next)->transitionUnit() == currentTrigger) {
1005 (*it)->second.push_back((*next)->setOfRules().front());
1007 next=matchingSetOfRules.erase(next);
1011 currentTrigger=(*it)->transitionUnit();
1023 LDEBUG <<
"Recognizer::initializeSearchStructure" << (
void*)macro << (
void*)micro;
1048 for (uint64_t i(0); i<
m_rules.size(); i++)
1050 if (*(
m_rules[i].first) == *trigger)
1052 m_rules[i].second.push_back(rule);
1063 const uint64_t index)
1066 for (uint64_t i(0); i<
m_rules.size(); i++)
1068 if (*(
m_rules[i].first) == *trigger)
1103 for (uint64_t i(0); i<
m_rules.size(); i++)
1105 cout <<
"<k>" <<
m_rules[i].first->printValue() <<
"</k>"
1106 <<
"<o>" << i <<
"</o>" << endl;
1115 for (uint64_t i(0); i<r.
m_rules.size(); i++)
1117 os <<
"trigger "<< i <<
" = "
1118 << *(r.
m_rules[i].first) << endl;
1119 for (uint64_t j(0); j<r.
m_rules[i].second.size(); j++)
1121 os <<
"rule " << j <<
":"
#define DEFAULT_ATTRIBUTE
LinguisticGraph::vertex_descriptor LinguisticGraphVertex
Defines a Factory to create Object of type Base.
Holds all data that pass through the ProcessUnits Analysis data are shared pointers,...
std::shared_ptr< AnalysisData > getData(const QString &id)
return AnalysisData by id
std::string & getParamsValueAtKey(const std::string &key)
return a message when a 'param' was not found
Use this exception to signal an error in one of the configuration files.
const std::set< LinguisticGraphVertex > & getNextVertices() const
␈rief a class for control parameters for the search using the automata
void setMaxResultSize(const uint64_t val)
void setMaxNbResults(const uint64_t val)
void setMaxTransitionsExplored(const uint64_t val)
void setMaxDepthStack(const uint64_t val)
void readRecognizer(const std::string &filename, Recognizer &reco)
bool operator()(Rule *r1, Rule *r2) const
void setFeature(const std::string &name, const ValueType &value)
void setHead(const LinguisticGraphVertex &v)
const EntityFeatures & features() const
LinguisticGraphVertex getHead() const
bool matchPath(const LinguisticAnalysisStructure::AnalysisGraph &graph, const LinguisticGraphVertex &vertex, const LinguisticGraphVertex &limit, const SearchGraph *searchGraph, AnalysisContent &analysis, const LinguisticAnalysisStructure::Token *token, std::deque< LinguisticGraphVertex > &vertices, const LinguisticAnalysisStructure::MorphoSyntacticData *) const
void addBackVertex(const LinguisticGraphVertex &, bool isKept=true, const LimaString &ruleElementId="")
LimaString getNormalizedString(const FsaStringsPool &sp) const
bool operator()(const Recognizer::TriggerRule *r1, const Recognizer::TriggerRule *r2)
const SetOfRules & setOfRules() const
␈rief a class for the definition of a complete recognizer
Recognizer & operator=(const Recognizer &)
void findNextSetOfRules(const LinguisticAnalysisStructure::AnalysisGraph &graph, LinguisticGraphVertex &vertex, AnalysisContent &analysis, const LinguisticAnalysisStructure::Token *token, const LinguisticAnalysisStructure::MorphoSyntacticData *data, std::vector< TriggerRule * > &matchingSetOfRules) const
void listTriggers() const
uint64_t testOnVertex(const LinguisticAnalysisStructure::AnalysisGraph &graph, LinguisticGraphVertex ¤t, const LinguisticGraphVertex &begin, const LinguisticGraphVertex &end, AnalysisContent &analysis, std::vector< RecognizerMatch > &result, bool stopAtFirstSuccess=true, bool onlyOneSuccessPerType=false, bool applySameRuleWhileSuccess=false) const
test the recognizer on a given vertex : check if this vertex is a trigger and if a rule applies,...
void initializeSearchStructure()
TransitionSearchStructure< TriggerRule > m_searchStructure
std::vector< TriggerRule > m_rules
uint64_t testSetOfRules(const TransitionUnit &trigger, const SetOfRules &rules, const LinguisticAnalysisStructure::AnalysisGraph &graph, const LinguisticGraphVertex &position, const LinguisticGraphVertex &begin, const LinguisticGraphVertex &end, AnalysisContent &analysis, std::vector< RecognizerMatch > &match, std::set< Common::MediaticData::EntityType > *forbiddenTypes=0, bool stopAtFirstSuccess=true, bool onlyOneSuccessPerType=false, bool applySameRuleWhileSuccess=false) const
TODO: toBeDeleted Parse tokens paths from the trigger point.
AutomatonControlParams m_automatonControlParams
parameters to control the search of the automaton
uint64_t addRuleInStorage(Rule *rule)
add a rule in the storage zone
uint64_t apply(const LinguisticAnalysisStructure::AnalysisGraph &graph, const LinguisticGraphVertex &begin, const LinguisticGraphVertex &end, AnalysisContent &analysis, std::vector< RecognizerMatch > &result, bool testAllVertices=false, bool stopAtFirstSuccess=true, bool onlyOneSuccessPerType=false, bool returnAtFirstSuccess=false, bool applySameRuleWhileSuccess=false) const
apply the recognizer on a graph
void copy(const Recognizer &a)
void clearSearchStructure()
void setNormalizedForm(const LimaString &norm, RecognizerMatch &match) const
uint64_t resolveOverlappingEntities(std::vector< RecognizerMatch > &listEntities, const OverlapResolutionStrategy &strategy=DEFAULT_OVERLAP_STRATEGY) const
resolve the problem of overlapping entities in the list of entities : when two entities are overlapin...
uint64_t findRuleIndex(Rule *) const
uint64_t addRule(TransitionUnit *trigger, Rule *rule)
add a rule in the recognizer : add the rule in the storage zone, and associate the trigger to the rul...
bool checkConstraints(const LinguisticAnalysisStructure::AnalysisGraph &graph, const LinguisticGraphVertex &vertex, AnalysisContent &analysis, ConstraintCheckList &) const
virtual TransitionUnit * clone() const =0
An AnalysisData containing a LinguisticGraph with a language and an id.
const LinguisticGraphVertex & lastVertex(void) const
Returns the last vertex of the graph.
const LinguisticGraph * getGraph(void) const
Returns the underlying graph structure.
const LinguisticGraphVertex & firstVertex(void) const
Returns the first vertex of the graph.
Holds morphosyntactic informations.
holds surface data of a token
const LimaString & stringForm() const
static const MediaticData & single()
const singleton accessor
static MediaticData & changeable()
singleton accessor
QString findFileInPaths(const QString &paths, const QString &fileName, const QChar &separator)
Find the given file in the given paths.
std::ostream & operator<<(std::ostream &os, const DFFSPos &x)
OverlapResolutionStrategy
an enumerated type to indicate which kind of strategy adopt to deal with two overlapping entities
@ IGNORE_SECOND
the second entity is ignored => assumes the leftmost trigger is more important
@ IGNORE_SMALLEST
the smallest entity is ignored (the one that covers the smallest number of words is assumed to be les...
@ IGNORE_FIRST
the first entity is ignored => assumes the rightmost trigger is more important
std::vector< ConstraintCheckListElement > ConstraintCheckList
SimpleFactory< AbstractResource, Recognizer > recognizerFactory(RECOGNIZER_CLASSID)
recognizer factory
std::vector< Rule * > SetOfRules
the SetOfRules type is defined as a vector of pointers on Rule
PUGI__FN void sort(I begin, I end, const Pred &pred)
#define RECOGNIZER_CLASSID
launch exception related to the configuration file parsing