LIMA
Libre Multilingual Analyzer — C++ API
Loading...
Searching...
No Matches
greedyPosTagger.cpp
Go to the documentation of this file.
1// Copyright 2002-2020 CEA LIST
2// SPDX-FileCopyrightText: 2022 CEA LIST <gael.de-chalendar@cea.fr>
3//
4// SPDX-License-Identifier: MIT
5
6#include "greedyPosTagger.h"
7
16
17#include <iostream>
18#include <iterator>
19#include <set>
20#include <map>
21#include <algorithm>
22
23//using namespace boost;
24using namespace std;
26using namespace Lima::Common::MediaticData;
27
28namespace Lima
29{
30namespace LinguisticProcessing
31{
32namespace PosTagger
33{
34
36
39 Manager* manager)
40
41{
49 m_language=manager->getInitializationParameters().media;
50 m_macroAccessor=&(static_cast<const Common::MediaticData::LanguageData&>(Common::MediaticData::MediaticData::single().mediaData(m_language)).getPropertyCodeManager().getPropertyAccessor("MACRO"));
51 m_microAccessor=&(static_cast<const Common::MediaticData::LanguageData&>(Common::MediaticData::MediaticData::single().mediaData(m_language)).getPropertyCodeManager().getPropertyAccessor("MICRO"));
52 try
53 {
54 auto trigrams = unitConfiguration.getParamsValueAtKey("trigramMatrix");
55 auto res = LinguisticResources::single().getResource(m_language, trigrams);
56 m_trigramMatrix = std::dynamic_pointer_cast<TrigramMatrix>(res);
57 }
59 {
60 LERROR << "No param 'trigramMatrix' in GreedyPosTagger group for language " << (int)m_language;
62 }
63
64 try
65 {
66 string bigrams=unitConfiguration.getParamsValueAtKey("bigramMatrix");
67 auto res = LinguisticResources::single().getResource(m_language, bigrams);
68 m_bigramMatrix = std::dynamic_pointer_cast<BigramMatrix>(res);
69 }
71 {
72 LWARN << "No param 'bigramMatrix' in GreedyPosTagger group for language " << (int)m_language;
74 }
75
76 try
77 {
78 std::string id=unitConfiguration.getParamsValueAtKey("ponctuforte");
79 m_microCatPonctuForte=static_cast<const Common::MediaticData::LanguageData&>(Common::MediaticData::MediaticData::single().mediaData(m_language)).getPropertyCodeManager().getPropertyManager("MICRO").getPropertyValue(id);
80 }
82 {
83 LWARN << "No ponctuforte microcateg category for GreedyPosTagger ! use category PONCTU_FORTE";
84 m_microCatPonctuForte=static_cast<const Common::MediaticData::LanguageData&>(Common::MediaticData::MediaticData::single().mediaData(m_language)).getPropertyCodeManager().getPropertyManager("MICRO").getPropertyValue("PONCTU_FORTE");
85 }
86
87}
88
90{
91
92 // start postagging here !
95 LINFO << "start greedy posTagging";
96
97 auto anagraph = std::dynamic_pointer_cast<AnalysisGraph>(analysis.getData("AnalysisGraph"));
98
99 auto posgraph = std::make_shared<AnalysisGraph>("PosGraph", m_language, false, true, *anagraph);
100
101 // walk on the vertex but don't process a vertex if one
102 // of its predecessor hasn't been processed.
103 auto graph = posgraph->getGraph();
104 LinguisticGraphVertex endVx = posgraph->lastVertex();
105
106 map<LinguisticGraphVertex,uint64_t> processed;
107 set<LinguisticGraphVertex> toProcess;
108 toProcess.insert(anagraph->firstVertex());
109 set<LinguisticGraphVertex> nextToProcess;
110 set<LinguisticGraphVertex>::iterator toProcessItr;
111 map<LinguisticGraphVertex,uint64_t>::iterator processedItr;
112 LinguisticGraphInEdgeIt inItr,inItrEnd;
113 LinguisticGraphOutEdgeIt outItr,outItrEnd;
114
115 while (toProcess.size()!=0)
116 {
117
118 //cout << "toProcess is ";
119 // copy(toProcess.begin(),toProcess.end(),ostream_iterator<LinguisticGraphVertex>(cout,","));
120 // cout << endl;
121
122 for (toProcessItr=toProcess.begin();
123 toProcessItr!=toProcess.end();
124 toProcessItr++)
125 {
126
127 // process vertex
128 processVertex(*toProcessItr, anagraph.get());
129 processed.insert(make_pair(*toProcessItr,out_degree(*toProcessItr,*graph)));
130 //cerr << "processed : insert " << *toProcessItr << " with " << out_degree(*toProcessItr,*graph) << endl;
131
132 // remove processed if necessary
133 boost::tie(inItr,inItrEnd)=in_edges(*toProcessItr,*graph);
134 for (;inItr!=inItrEnd;inItr++)
135 {
136 processedItr=processed.find(source(*inItr,*graph));
137 processedItr->second--;
138 //cerr << "processed : vertex " << processedItr->first << " decremented to " << processedItr->second << endl;
139 if (processedItr->second==0)
140 {
141 //cerr << "processed : remove " << processedItr->first << endl;
142 processed.erase(processedItr);
143 }
144 }
145
146 // check and add nex vertex to process
147 boost::tie(outItr,outItrEnd)=out_edges(*toProcessItr,*graph);
148 for (;outItr!=outItrEnd;outItr++)
149 {
150 LinguisticGraphVertex next=target(*outItr,*graph);
151 if (next==endVx)
152 {
153 continue;
154 }
155 // check if all in vertices have been processed
156 boost::tie(inItr,inItrEnd)=in_edges(next,*graph);
157 bool ok=true;
158 for (;inItr!=inItrEnd;inItr++)
159 {
160 if (processed.find(source(*inItr,*graph))==processed.end())
161 {
162 ok=false;
163 break;
164 }
165 }
166 if (ok)
167 {
168 nextToProcess.insert(next);
169 }
170 }
171
172 }
173
174 toProcess.clear();
175 toProcess.swap(nextToProcess);
176
177 }
178
179 TimeUtils::logElapsedTime("GreedyPosTagger");
180 return SUCCESS_ID;
181}
182
183void GreedyPosTagger::processVertex(LinguisticGraphVertex vx,AnalysisGraph* anagraph) const
184{
185 LinguisticGraph* graph=anagraph->getGraph();
186 LinguisticGraphVertex startVx=anagraph->firstVertex();
187 LinguisticGraphVertex endVx=anagraph->lastVertex();
188
189 PTLOGINIT;
190 if (vx==startVx || vx==endVx)
191 {
192 return;
193 }
194 MorphoSyntacticData* data=get(vertex_data,*graph,vx);
195 Token* token=get(vertex_token,*graph,vx);
196 if (data==0)
197 {
198 LERROR << "MorphoSyntacticData of vertex " << vx << " is NULL !";
199 return;
200 }
201 LDEBUG << "process vertex : " << vx << " : "
203
204 MorphoSyntacticData* posdata=new MorphoSyntacticData(*data);
205 put(vertex_data,*graph,vx,posdata);
206
207 set<LinguisticCode> micros=posdata->allValues(*m_microAccessor);
208 LinguisticCode selectedMicro;
209
210
211 if (micros.size()==0)
212 {
213 LWARN << "Token "
215 << " has no possible dicowords ! build a DicoWord with category 0";
216 selectedMicro=L_NONE;
217 }
218 else if (micros.size()==1)
219 {
220 // no choice, put this category
221 selectedMicro=*(micros.begin());
222 LDEBUG << "GreedyPosTagging : only one choice : " << selectedMicro;
223 }
224 else
225 {
226 // choose the most probable dicoWord
227 set<LinguisticCode>::iterator dwItr,dwMaxTri,dwMaxBi;
228 float maxTri=0;
229 float maxBi=0;
230 LinguisticCode cat1,cat2;
231
232 LinguisticGraphInEdgeIt inItr,inItrEnd;
233 boost::tie(inItr,inItrEnd)=in_edges(vx,*graph);
234 for (;inItr!=inItrEnd;inItr++)
235 {
236 LinguisticGraphVertex predVx=source(*inItr,*graph);
237 MorphoSyntacticData* m2=get(vertex_data,*graph,predVx);
238 if (predVx==startVx && m2!=0 && !m2->empty())
239 {
240 cat2=m_microCatPonctuForte;
241 }
242 else
243 {
244
245 cat2=m_microAccessor->readValue(m2->begin()->properties);
246
247 LinguisticGraphInEdgeIt inItr2,inItr2End;
248 boost::tie(inItr2,inItr2End)=in_edges(vx,*graph);
249 for (;inItr2!=inItr2End;inItr2++)
250 {
251 LinguisticGraphVertex predpredVx=source(*inItr2,*graph);
252 MorphoSyntacticData* m1=get(vertex_data,*graph,predpredVx);
253 if (predpredVx==startVx && m1!=0 && !m1->empty())
254 {
255 cat1=m_microCatPonctuForte;
256 }
257 else
258 {
259 cat1=m_microAccessor->readValue(m1->begin()->properties);
260 }
261 // search better trigram
262 for (dwItr=micros.begin();dwItr!=micros.end();dwItr++)
263 {
264 float p=m_trigramMatrix->freq(cat1,cat2,*dwItr);
265 if (p>maxTri)
266 {
267 maxTri=p;
268 dwMaxTri=dwItr;
269 }
270 }
271 }
272 }
273 if (maxTri==0)
274 {
275 // no trigram has been found, search bigram
276 for (dwItr=micros.begin();dwItr!=micros.end();dwItr++)
277 {
278 float p=m_bigramMatrix->freq(cat1,*dwItr);
279 if (p>maxBi)
280 {
281 maxBi=p;
282 dwMaxBi=dwItr;
283 }
284 }
285
286 }
287
288
289 }
290
291 if (maxTri!=0)
292 {
293 // choose best trigram
294 LDEBUG << "found trigram : choose " << *dwMaxTri << " (p=" << maxTri << ")";
295 selectedMicro=*dwMaxTri;
296 }
297 else if (maxBi!=0)
298 {
299 // choose best bigram
300 LDEBUG << "found bigram : choose " << *dwMaxBi << " (p=" << maxBi << ")";
301 selectedMicro=*dwMaxBi;
302 }
303 else
304 {
305 // no trigram nor bigram has been found
306 // choose better probability as source in bigram then as target in bigram
307 LWARN << "Found no trigram nor bigram (" << cat1 << "," << cat2 << ") ! try heuristics to find a microcategory";
308 for (dwItr=micros.begin();dwItr!=micros.end();dwItr++)
309 {
310 float p=m_bigramMatrix->freq(m_microCatPonctuForte,*dwItr);
311 if (p>maxBi)
312 {
313 maxBi=p;
314 dwMaxBi=dwItr;
315 }
316 }
317 if (maxBi!=0)
318 {
319 LDEBUG << "found bigram with ponctu forte : choose " << *dwMaxBi << " (p=" << maxBi << ")";
320 selectedMicro=*dwMaxBi;
321 }
322 else
323 {
324 selectedMicro=*(micros.begin());
325 LDEBUG << "choose first : " << selectedMicro;
326 }
327 }
328 }
329
330 // filter linguisticelement
331 CheckDifferentPropertyPredicate cdpp(*m_microAccessor, selectedMicro);
332 posdata->erase(remove_if(posdata->begin(), posdata->end(), cdpp),
333 posdata->end());
334
335}
336
337} // PosTagger
338} // LinguisticProcessing
339} // Lima
#define LWARN
Definition LimaCommon.h:160
#define LDEBUG
Definition LimaCommon.h:157
#define LINFO
Definition LimaCommon.h:158
#define LERROR
Definition LimaCommon.h:161
LinguisticGraph::in_edge_iterator LinguisticGraphInEdgeIt
@ vertex_token
LinguisticGraph::vertex_descriptor LinguisticGraphVertex
@ vertex_data
LinguisticGraph::out_edge_iterator LinguisticGraphOutEdgeIt
boost::adjacency_list< boost::vecS, boost::vecS, boost::bidirectionalS, LinguisticVertexProperties > LinguisticGraph
Property to identify the chains in the graph.
#define PTLOGINIT
Defines a Factory to create Object of type Base.
#define L_NONE
Definition StdBitset.h:338
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
Holds linguistic data for one language.
const MediaData & mediaData(MediaId media) const
LinguisticCode readValue(const LinguisticCode &code) const
read a property in a coded int.
return a message when a 'param' was not found
Use this exception to signal an error in one of the configuration files.
Definition LimaCommon.h:345
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.
std::set< LinguisticCode > allValues(const Common::PropertyCode::PropertyAccessor &propertyAccessor) const
void init(Common::XMLConfigurationFiles::GroupConfigurationStructure &unitConfiguration, Manager *manager) override
initialize with parameters from configuration file.
LimaStatusCode process(AnalysisContent &analysis) const override
Process on data in analysisContent.
static const MediaticData & single()
const singleton accessor
Definition Singleton.h:51
static void logElapsedTime(const std::string &mess, const std::string &taskCategory=std::string(""))
log the number of microseconds since last UpdateCurrentTime
static void updateCurrentTime(const std::string &taskCategory=std::string(""))
store current time for new elapsed time computation
Declaration of a PosTagger with a simple greedy algorithm.
#define GREEDYPOSTAGGER_CLASSID
std::string limastring2utf8stdstring(const Lima::LimaString &phrase, uint32_t size0)
Convert a wide string to a string , in dest up to size bytes.
SimpleFactory< MediaProcessUnit, GreedyPosTagger > greedyPosTaggerFactory(GREEDYPOSTAGGER_CLASSID)
NAUTITIA.
LimaStatusCode
Definition LimaCommon.h:236
@ SUCCESS_ID
Definition LimaCommon.h:237
STL namespace.