LIMA
Libre Multilingual Analyzer — C++ API
Loading...
Searching...
No Matches
ChainsDisambiguator.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
16#include "ChainsDisambiguator.h"
17
18using namespace Lima::Common::MediaticData;
20
21namespace Lima
22{
23namespace LinguisticProcessing
24{
25namespace SyntacticAnalysis
26{
27
28#define MAXPATHS 15
29
31 const LinguisticGraphVertex& s,
32 const LinguisticGraphVertex& t,
33 MediaId language,
34 uint64_t depGraphMaxBranchingFactor) :
35 m_hypsStack(),
36 m_completePaths(),
37 m_data(data),
38 m_srcVertex(s),
39 m_tgtVertex(t),
40 m_language(language),
41 m_depGraphMaxBranchingFactor(depGraphMaxBranchingFactor)
42{
43 m_microAccessor=&static_cast<const Common::MediaticData::LanguageData&>(Common::MediaticData::MediaticData::single().mediaData(language)).getPropertyCodeManager().getPropertyAccessor("MICRO");
44}
45
47 m_hypsStack(cd.m_hypsStack),
48 m_completePaths(cd.m_completePaths),
49 m_data(cd.m_data),
50 m_srcVertex(cd.m_srcVertex),
51 m_tgtVertex(cd.m_tgtVertex),
52 m_language(cd.m_language),
53 m_depGraphMaxBranchingFactor(cd.m_depGraphMaxBranchingFactor),
54 m_microAccessor(cd.m_microAccessor)
55{}
56
58{
59 m_hypsStack = cd.m_hypsStack;
60 m_completePaths = cd.m_completePaths;
61 m_data = cd.m_data;
62 m_srcVertex = cd.m_srcVertex;
63 m_tgtVertex = cd.m_tgtVertex;
64 m_language = cd.m_language;
65 m_depGraphMaxBranchingFactor = cd.m_depGraphMaxBranchingFactor;
66 m_microAccessor = cd.m_microAccessor;
67 return *this;
68}
69
71{
72 const LinguisticGraph* graph = m_data->graph();
73 LinguisticGraphVertex currentVertex = m_srcVertex;
74 if (currentVertex == m_data->iterator()->firstVertex() || (currentVertex==m_data->iterator()->lastVertex()) )
75 {
76 uint64_t id = currentVertex;
77 std::set< uint64_t> chainsToIgnore;
78 Path initialPath(id, chainsToIgnore);
79 m_hypsStack.push_front(initialPath);
80 return;
81 }
82 CVertexDataPropertyMap dataMap = get(vertex_data, *graph);
83 const MorphoSyntacticData* currentData = dataMap[currentVertex];
84 LinguisticCode currentMicroCateg= currentData->firstValue(*m_microAccessor);
85 CVertexChainIdPropertyMap chainsMap = get(vertex_chain_id, *graph);
86 const std::set< ChainIdStruct >& currentVertexChains = chainsMap[currentVertex];
87 uint64_t id = currentVertex;
88 if (currentVertexChains.empty())
89 {
90 std::set< uint64_t> chainsToIgnore;
91 Path initialPath(id, chainsToIgnore);
92 initialPath.outChainsWordsNb()++;
93 if (static_cast<const Common::MediaticData::LanguageData&>(Common::MediaticData::MediaticData::single().mediaData(m_language)).isAPropositionIntroductor(currentMicroCateg))
94 initialPath.idealConjVerbNb()++;
95 m_hypsStack.push_front(initialPath);
96 }
97 else
98 {
99 unsigned char type = 1;
100 std::set< ChainIdStruct >::const_iterator currentChainIt, currentChainIt_end;
101 currentChainIt = currentVertexChains.begin();
102 currentChainIt_end = currentVertexChains.end();
103 for (; currentChainIt != currentChainIt_end ; currentChainIt++)
104 {
105 std::set< uint64_t> chainsToIgnore;
106 std::set< ChainIdStruct >::const_iterator otherChainIt, otherChainIt_end;
107 otherChainIt = currentVertexChains.begin();
108 otherChainIt_end = currentVertexChains.end();
109 for (; otherChainIt != otherChainIt_end ; otherChainIt++)
110 {
111 if (currentChainIt != otherChainIt)
112 {
113 chainsToIgnore.insert(otherChainIt->chainId());
114 }
115 }
116 Path initialPath(id, chainsToIgnore, type, currentChainIt->chainId());
117 if (static_cast<const Common::MediaticData::LanguageData&>(Common::MediaticData::MediaticData::single().mediaData(m_language)).isAPropositionIntroductor(currentMicroCateg))
118 initialPath.idealConjVerbNb()++;
119 else if (static_cast<const Common::MediaticData::LanguageData&>(Common::MediaticData::MediaticData::single().mediaData(m_language)).isAConjugatedVerb(currentMicroCateg))
120 initialPath.conjVerbNb()++;
121 initialPath.chainsNb()++;
122 m_hypsStack.push_front(initialPath);
123 }
124 }
125}
126
128{
129// SADLOGINIT;
130 const LinguisticGraph* graph = m_data->graph();
131 CVertexDataPropertyMap dataMap = get(vertex_data, *graph);
132 CVertexChainIdPropertyMap chainsMap = get(vertex_chain_id, *graph);
133 while (!m_hypsStack.empty())
134 {
135 if (m_hypsStack.size() > MAXPATHS)
136 m_hypsStack.pop_back();
137 Path currentHyp = m_hypsStack.front();
138 m_hypsStack.pop_front();
139 if (currentHyp.key().id() == m_tgtVertex)
140 {
141 m_completePaths.insert(currentHyp);
142 }
143 else
144 {
145 Key& currentKey = currentHyp.key();
146 LinguisticGraphVertex currentVertex = currentKey.id();
147 const std::set< ChainIdStruct >& currentVertexChains = chainsMap[currentVertex];
148// LDEBUG << "New hyp on " << currentVertex;
149 const Elem& currentElem = *(currentHyp.elems().rbegin());
150// LDEBUG << "Current elem: " << currentElem;
151 LinguisticGraphOutEdgeIt it, it_end;
152 boost::tie(it, it_end) = boost::out_edges(currentVertex, *graph);
153 uint64_t branchNum = 0;
154 for (; it != it_end; it++)
155 {
156 if (++branchNum >= m_depGraphMaxBranchingFactor)
157 {
159 LWARN << "Breaking computePaths inner loop on "<<currentVertex<<" due to excessive branching factor.";
160 break;
161 }
162
163 LinguisticGraphVertex nextVertex = target(*it, *graph);
164// LDEBUG << "Looking at next vertex: " << nextVertex << " (current is "<<currentVertex<<")";
165 if (currentVertex==0 && nextVertex==1)
166 continue;
167 const std::set< ChainIdStruct >& nextVertexChains = chainsMap[nextVertex];
168 LinguisticCode nextMicroCateg;
169 const MorphoSyntacticData* nextData = dataMap[nextVertex];
170 if (nextData == 0 || nextData->empty())
171 {
173 LWARN << "vertex " << nextVertex << " has no data";
174 // @TODO ensure that continuing with a 0 microcateg is a good solution
175// continue;
176 }
177 else
178 {
179 nextMicroCateg = nextData->firstValue(*m_microAccessor);
180 }
181// LDEBUG << "vertex microcateg is " << nextMicroCateg;
182 if ( currentElem.type() == 0 ) // no chain on current vertex
183 {
184// LDEBUG << "no chain on current vertex";
185 // no chain on the new vertex
186 if (nextVertexChains.empty())
187 {
188// LDEBUG << "no chain on the new vertex";
189 Path newHyp(currentHyp);
190 Key newKey(nextVertex);
191 Elem newElem(nextVertex);
192 newHyp.elems().push_back(newElem);
193 newHyp.key(newKey);
194 newHyp.updateParams(nextMicroCateg, false, true, m_language);
195 m_hypsStack.push_front(newHyp);
196 if (m_hypsStack.size() > MAXPATHS)
197 m_hypsStack.pop_back();
198 }
199 // one chain on the new vertex
200 else if (nextVertexChains.size() == 1)
201 {
202// LDEBUG << "one chain on the new vertex";
203 Path newHyp(currentHyp);
204 Key newKey(nextVertex);
205 ChainIdStruct nextVertexChain = (*(nextVertexChains.begin()));
206 uint64_t nextVertexChainId = nextVertexChain.chainId();
207 Elem newElem(nextVertex);
208 if ( ( nextVertexChain.elemType() == BEGIN ) ||
209 ( nextVertexChain.elemType() == UNIGRAM ) )
210 {
211 newElem = Elem(nextVertexChainId, 1);
212 newElem.elems().push_back(nextVertex);
213 newHyp.updateParams(nextMicroCateg, true, false, m_language);
214 }
215 else //END ou PART
216 {
217 newKey.chainsToIgnore().insert(( nextVertexChainId));
218 newHyp.updateParams(nextMicroCateg, false, true, m_language);
219 }
220 newHyp.elems().push_back(newElem);
221 newHyp.key(newKey);
222 m_hypsStack.push_front(newHyp);
223 if (m_hypsStack.size() > MAXPATHS)
224 m_hypsStack.pop_back();
225 }
226 // several chains on the new vertex
227 else
228 {
229// LDEBUG << "several chains on the new vertex";
230 startWithSeveralChainsOnNewVertex(nextVertex, nextVertexChains, currentHyp);
231 }
232 }
233 else if ( currentKey.chainsToIgnore().empty() ) // a chain on current vertex and no chain to ignore
234 {
235// LDEBUG << "a chain on current vertex and no chain to ignore";
236 uint64_t currentElemChainId = currentElem.id();
237 ChainIdStruct currentElemChainIdStruct;
238 std::set< ChainIdStruct >::const_iterator currentVertexChainsIt, currentVertexChainsIt_end;
239 currentVertexChainsIt = currentVertexChains.begin();
240 currentVertexChainsIt_end = currentVertexChains.end();
241 for (; currentVertexChainsIt != currentVertexChainsIt_end; currentVertexChainsIt++)
242 {
243 if ( (*currentVertexChainsIt).chainId() == currentElemChainId )
244 {
245 currentElemChainIdStruct = *currentVertexChainsIt;
246 break;
247 }
248 }
249 if (currentVertexChainsIt == currentVertexChainsIt_end)
250 throw std::runtime_error("Current elem chain id not found in current elem chains.");
251
252 if (nextVertexChains.empty()) // the current chain does not continue
253 {
254 // current chain was finished, no new chain
255 if ( (currentElemChainIdStruct.elemType() == END) ||
256 (currentElemChainIdStruct.elemType() == UNIGRAM) )
257 {
258// LDEBUG << "current chain was finished, no new chain";
259 Path newHyp(currentHyp);
260 Key newKey(nextVertex);
261 Elem newElem(nextVertex);
262 newHyp.key(newKey);
263 newHyp.elems().push_back(newElem);
264 newHyp.updateParams(nextMicroCateg, false, true, m_language);
265 m_hypsStack.push_front(newHyp);
266 if (m_hypsStack.size() > MAXPATHS)
267 m_hypsStack.pop_back();
268 }
269 // current chain was not finished, we are on a divergent branch
270 // current chain elem has to be removed and replaced by vertices elems
271 // made from its elements
272 else
273 {
274// LDEBUG << "current chain was not finished, we are on a divergent branch";
275// LDEBUG << "current chain elem has to be removed and replaced by vertices elems";
276// LDEBUG << "made from its elements";
277 Path newHyp(currentHyp);
278 cancelCurrentChain(currentElem, newHyp);
279 Key newKey(nextVertex);
280 Elem newElem(nextVertex);
281 newHyp.key(newKey);
282 newHyp.elems().push_back(newElem);
283 newHyp.updateParams(nextMicroCateg, false, true, m_language);
284 m_hypsStack.push_front(newHyp);
285 if (m_hypsStack.size() > MAXPATHS)
286 m_hypsStack.pop_back();
287 }
288 }
289 // one chain on the new vertex
290 else if (nextVertexChains.size() == 1)
291 {
292// LDEBUG << "one chain on the new vertex";
293 // verify if we continue the same chain
294 // or finish it and start a new one
295 // or finish it and new vertex is a confluent on another chain
296
297 // continue the same chain
298 if ( (*(nextVertexChains.begin())).chainId() == currentElem.id() )
299 {
300// LDEBUG << "continue the same chain";
301 Path newHyp(currentHyp);
302 Key newKey(nextVertex);
303 Elem& newElem = *(newHyp.elems().rbegin());
304 newElem.elems().push_back(nextVertex);
305 newHyp.key(newKey);
306 newHyp.updateParams(nextMicroCateg, false, false, m_language);
307 m_hypsStack.push_front(newHyp);
308 if (m_hypsStack.size() > MAXPATHS)
309 m_hypsStack.pop_back();
310 }
311 else // 1. finish it or cancel it if it was not finished
312 // 2. start a new chain or add to ignore if new vertex is a confluent on another chain (begin or continued)
313 {
314// LDEBUG << "1. finish it or cancel it if it was not finished";
315// LDEBUG << "2. start a new chain or add to ignore if new vertex is a confluent on another chain (begin or continued)";
316 Path newHyp(currentHyp);
317 // current chain was not finished, we are on a divergent branch
318 // current chain elem has to be removed and replaced by vertices elems
319 // made from its elements
320 if (!( (currentElemChainIdStruct.elemType() == END) ||
321 (currentElemChainIdStruct.elemType() == UNIGRAM) ))
322 {
323// LDEBUG << "current chain was not finished, we are on a divergent branch";
324// LDEBUG << "current chain elem has to be removed and replaced by vertices elems";
325 cancelCurrentChain(currentElem, newHyp);
326 }
327 // now continue as when there was no chain on current vertex
328 Key newKey(nextVertex);
329 ChainIdStruct nextVertexChain = (*(nextVertexChains.begin()));
330 uint64_t nextVertexChainId = nextVertexChain.chainId();
331 Elem newElem(nextVertex);
332 if ( ( nextVertexChain.elemType() == BEGIN ) ||
333 ( nextVertexChain.elemType() == UNIGRAM ) )
334 {
335 newElem = Elem(nextVertexChainId, 1);
336 newElem.elems().push_back(nextVertex);
337 newHyp.updateParams(nextMicroCateg, true, false, m_language);
338 }
339 else //END ou PART
340 {
341 newKey.chainsToIgnore().insert(( nextVertexChainId));
342 newHyp.updateParams(nextMicroCateg, false, true, m_language);
343 }
344 newHyp.elems().push_back(newElem);
345 newHyp.key(newKey);
346 m_hypsStack.push_front(newHyp);
347 if (m_hypsStack.size() > MAXPATHS)
348 m_hypsStack.pop_back();
349 }
350 }
351 // several chains on the new vertex
352 else
353 {
354// LDEBUG << "several chains on the new vertex";
355 // verify if we continue the same chain
356 // or finish it and start a new one
357 // or finish it and new vertex is a confluent on another chain
358
359 // continue the same chain
360 bool currentChainFound = false;
361 std::set< uint64_t > nextVertexChainsIdsToIgnore;
362 std::set< ChainIdStruct >::const_iterator nextVertexChainsIt, nextVertexChainsIt_end;
363 nextVertexChainsIt = nextVertexChains.begin();
364 nextVertexChainsIt_end = nextVertexChains.end();
365 for(; nextVertexChainsIt != nextVertexChainsIt_end; nextVertexChainsIt++)
366 {
367 if ( (*nextVertexChainsIt).chainId() == currentElem.id() )
368 currentChainFound = true;
369 else
370 nextVertexChainsIdsToIgnore.insert((*nextVertexChainsIt).chainId());
371 }
372 // continue the same chain
373 if (currentChainFound)
374 {
375// LDEBUG << "continue the same chain";
376 Path newHyp(currentHyp);
377 Key newKey(nextVertex, nextVertexChainsIdsToIgnore);
378 Elem& newElem = *(newHyp.elems().rbegin());
379 newElem.elems().push_back(nextVertex);
380 newHyp.key(newKey);
381 newHyp.updateParams(nextMicroCateg, false, false, m_language);
382 m_hypsStack.push_front(newHyp);
383 if (m_hypsStack.size() > MAXPATHS)
384 m_hypsStack.pop_back();
385 }
386 else // 1. finish it or cancel it if it was not finished
387 // 2. start a new chain or add to ignore if new vertex is a confluent on another chain (begin or continued)
388 {
389// LDEBUG << "1. finish it or cancel it if it was not finished;";
390// LDEBUG << "2. start a new chain or add to ignore if new vertex is a confluent on another chain (begin or continued)";
391 Path newHyp(currentHyp);
392 // current chain was not finished, we are on a divergent branch
393 // current chain elem has to be removed and replaced by vertices elems
394 // made from its elements
395 if (!( (currentElemChainIdStruct.elemType() == END) ||
396 (currentElemChainIdStruct.elemType() == UNIGRAM) ))
397 {
398// LDEBUG << "current chain was not finished, we are on a divergent branch";
399// LDEBUG << "current chain elem has to be removed and replaced by vertices elems made from its elements";
400 cancelCurrentChain(currentElem, newHyp);
401 }
402 // now continue as when there was no chain on current vertex
403// LDEBUG << "now continue as when there was no chain on current vertex";
404 startWithSeveralChainsOnNewVertex(nextVertex, nextVertexChains, currentHyp);
405 }
406 }
407 }
408 else // a chain on current vertex and one (or more) chain(s) to ignore
409 {
410// LDEBUG << "a chain on current vertex and one (or more) chain(s) to ignore";
411 uint64_t currentElemChainId = currentElem.id();
412 ChainIdStruct currentElemChainIdStruct;
413 std::set< ChainIdStruct >::const_iterator currentVertexChainsIt, currentVertexChainsIt_end;
414 currentVertexChainsIt = currentVertexChains.begin();
415 currentVertexChainsIt_end = currentVertexChains.end();
416 for (; currentVertexChainsIt != currentVertexChainsIt_end; currentVertexChainsIt++)
417 {
418 if ( (*currentVertexChainsIt).chainId() == currentElemChainId )
419 {
420 currentElemChainIdStruct = *currentVertexChainsIt;
421 break;
422 }
423 }
424 if (currentVertexChainsIt == currentVertexChainsIt_end)
425 throw std::runtime_error("Current elem chain id not found in current elem chains.");
426
427 if (nextVertexChains.empty()) // no chain on next vertex: the current chain does not continue
428 {
429// LDEBUG << "no chain on next vertex: the current chain does not continue";
430 // current chain was finished, continuing normaly
431 if ( (currentElemChainIdStruct.elemType() == END) ||
432 (currentElemChainIdStruct.elemType() == UNIGRAM) )
433 {
434// LDEBUG << "current chain was finished, continuing normaly";
435 Path newHyp(currentHyp);
436 Key newKey(nextVertex, currentKey.chainsToIgnore());
437 Elem newElem(nextVertex);
438 newHyp.key(newKey);
439 newHyp.elems().push_back(newElem);
440 newHyp.updateParams(nextMicroCateg, false, true, m_language);
441 m_hypsStack.push_front(newHyp);
442 if (m_hypsStack.size() > MAXPATHS)
443 m_hypsStack.pop_back();
444 }
445 // current chain was not finished, we are on a divergent branch
446 // current chain elem has to be removed and replaced by vertices elems
447 // made from its elements
448 else
449 {
450// LDEBUG << "current chain was not finished, we are on a divergent branch ; current chain elem has to be removed and replaced by vertices elems made from its elements";
451 Path newHyp(currentHyp);
452 cancelCurrentChain(currentElem, newHyp);
453 Key newKey(nextVertex, currentKey.chainsToIgnore());
454 newKey.chainsToIgnore().insert(currentElemChainId);
455 Elem newElem(nextVertex);
456 newHyp.key(newKey);
457 newHyp.elems().push_back(newElem);
458 newHyp.updateParams(nextMicroCateg, false, true, m_language);
459 m_hypsStack.push_front(newHyp);
460 if (m_hypsStack.size() > MAXPATHS)
461 m_hypsStack.pop_back();
462 }
463 }
464 // one chain on the new vertex
465 else if (nextVertexChains.size() == 1)
466 {
467// LDEBUG << "one chain on the new vertex";
468 // verify if we continue the same chain
469 // or finish it and start a new one
470 // or finish it and new vertex is a confluent on another chain
471
472 // continue the same chain
473 if ( (*(nextVertexChains.begin())).chainId() == currentElem.id() )
474 {
475// LDEBUG << "continue the same chain";
476 Path newHyp(currentHyp);
477 Key newKey(nextVertex);
478 Elem& newElem = *(newHyp.elems().rbegin());
479 newElem.elems().push_back(nextVertex);
480 newHyp.key(newKey);
481 newHyp.updateParams(nextMicroCateg, false, false, m_language);
482 m_hypsStack.push_front(newHyp);
483 if (m_hypsStack.size() > MAXPATHS)
484 m_hypsStack.pop_back();
485 }
486 else
487 // 1. finish it or cancel it if it was not finished
488 // 2. start a new chain or add to ignore if new vertex is a confluent on another chain (begin or continued)
489 // 3. continue without chain if new chain have to be ignored
490 {
491// LDEBUG << "does not continue the same chain";
492 Path newHyp(currentHyp);
493 // current chain was not finished, we are on a divergent branch
494 // current chain elem has to be removed and replaced by vertices elems
495 // made from its elements
496 if (!( (currentElemChainIdStruct.elemType() == END) ||
497 (currentElemChainIdStruct.elemType() == UNIGRAM) ))
498 {
499// LDEBUG << "current chain was not finished, we are on a divergent branch";
500 cancelCurrentChain(currentElem, newHyp);
501 }
502 else
503 {
504// LDEBUG << "current chain was finished";
505 }
506
507// LDEBUG << "now continue as when there was no chain on current vertex";
508 // now continue as when there was no chain on current vertex
509 Key newKey(nextVertex, currentKey.chainsToIgnore());
510 ChainIdStruct nextVertexChain = (*(nextVertexChains.begin()));
511 uint64_t nextVertexChainId = nextVertexChain.chainId();
512 Elem newElem(nextVertex);
513 if ( ( ( nextVertexChain.elemType() == BEGIN ) ||
514 ( nextVertexChain.elemType() == UNIGRAM ) ) &&
515 ( newKey.chainsToIgnore().find(nextVertexChainId) == newKey.chainsToIgnore().end() ) )
516 {
517 newElem = Elem(nextVertexChainId, 1);
518 newElem.elems().push_back(nextVertex);
519 newHyp.updateParams(nextMicroCateg, true, false, m_language);
520 }
521 else //END or PART or chain to ignore
522 {
523 newKey.chainsToIgnore().insert(( nextVertexChainId));
524 newHyp.updateParams(nextMicroCateg, false, true, m_language);
525 }
526 newHyp.elems().push_back(newElem);
527 newHyp.key(newKey);
528 m_hypsStack.push_front(newHyp);
529 if (m_hypsStack.size() > MAXPATHS)
530 m_hypsStack.pop_back();
531 }
532 }
533 // several chains on the new vertex
534 else
535 {
536// LDEBUG << "several chains on the new vertex";
537 // verify if we continue the same chain
538 // or finish it and start a new one
539 // or finish it and new vertex is a confluent on another chain
540
541 bool currentChainFound = false;
542 std::set< uint64_t > nextVertexChainsIdsToIgnore = currentKey.chainsToIgnore();
543 std::set< ChainIdStruct >::const_iterator nextVertexChainsIt, nextVertexChainsIt_end;
544 nextVertexChainsIt = nextVertexChains.begin();
545 nextVertexChainsIt_end = nextVertexChains.end();
546 for(; nextVertexChainsIt != nextVertexChainsIt_end; nextVertexChainsIt++)
547 {
548 if ( (*nextVertexChainsIt).chainId() == currentElem.id() )
549 currentChainFound = true;
550 else
551 nextVertexChainsIdsToIgnore.insert((*nextVertexChainsIt).chainId());
552 }
553 // continue the same chain
554 if (currentChainFound)
555 {
556// LDEBUG << "continue the same chain";
557 Path newHyp(currentHyp);
558 Key newKey(nextVertex, nextVertexChainsIdsToIgnore);
559 Elem& newElem = *(newHyp.elems().rbegin());
560 newElem.elems().push_back(nextVertex);
561 newHyp.key(newKey);
562 newHyp.updateParams(nextMicroCateg, false, false, m_language);
563 m_hypsStack.push_front(newHyp);
564 if (m_hypsStack.size() > MAXPATHS)
565 m_hypsStack.pop_back();
566 }
567 else
568 // 1. finish it or cancel it if it was not finished
569 // 2. start a new chain or add to ignore if new vertex is a confluent on another chain (begin or continued)
570 {
571// LDEBUG << "1. finish it or cancel it if it was not finished ;";
572// LDEBUG << "2. start a new chain or add to ignore if new vertex is a confluent on another chain (begin or continued)";
573 Path newHyp(currentHyp);
574 // current chain was not finished, we are on a divergent branch
575 // current chain elem has to be removed and replaced by vertices elems
576 // made from its elements
577 if (!( (currentElemChainIdStruct.elemType() == END) ||
578 (currentElemChainIdStruct.elemType() == UNIGRAM) ))
579 {
580 cancelCurrentChain(currentElem, newHyp);
581 }
582 // now continue as when there was no chain on current vertex
583 startWithSeveralChainsOnNewVertex(nextVertex, nextVertexChains, newHyp);
584 }
585 }
586 }
587 }
588 }
589 }
590}
591
594void ChainsDisambiguator::startWithSeveralChainsOnNewVertex(
595 LinguisticGraphVertex nextVertex,
596 const std::set< ChainIdStruct >& nextVertexChains,
597 const Path& currentHyp)
598{
599// SADLOGINIT;
600// LDEBUG << "startWithSeveralChainsOnNewVertex: " << nextVertex;
601 const Key& currentKey = currentHyp.key();
602 const LinguisticGraph* graph = m_data->graph();
603 CVertexDataPropertyMap dataMap = get(vertex_data, *graph);
604 const MorphoSyntacticData* nextData = dataMap[nextVertex];
605 LinguisticCode nextMicroCateg;
606 if (nextData != 0 && !nextData->empty())
607 {
608 nextMicroCateg = m_microAccessor->readValue(nextData->begin()->properties);
609 }
610 uint64_t nextVertexChainId = std::numeric_limits<uint64_t>::max();
611 std::set< ChainIdStruct >::const_iterator nextVertexChainsIt, nextVertexChainsIt_end;
612 nextVertexChainsIt = nextVertexChains.begin();
613 nextVertexChainsIt_end = nextVertexChains.end();
614 std::set<uint64_t> newChainsToIgnore;
615 std::set<uint64_t> nextVertexChainsIds;
616 std::set<uint64_t> nextVertexBeginChainsIds;
617 for (; nextVertexChainsIt != nextVertexChainsIt_end; nextVertexChainsIt++)
618 {
619 if ( ( ( (*nextVertexChainsIt).elemType() == BEGIN ) ||
620 ( (*nextVertexChainsIt).elemType() == UNIGRAM ) ) &&
621 ( currentKey.chainsToIgnore().find(nextVertexChainId) == currentKey.chainsToIgnore().end() ) )
622 nextVertexBeginChainsIds.insert((*nextVertexChainsIt).chainId());
623 nextVertexChainsIds.insert((*nextVertexChainsIt).chainId());
624 }
625 if (nextVertexBeginChainsIds.empty()) //no chain begin found
626 {
627// LDEBUG << "no chain begin found" << nextVertex;
628 Key newKey(nextVertex, currentKey.chainsToIgnore());
629 Path newHyp(currentHyp);
630 newChainsToIgnore = nextVertexChainsIds;
631 newKey.chainsToIgnore().insert(newChainsToIgnore.begin(), newChainsToIgnore.end());
632 Elem newElem(nextVertex);
633 newHyp.elems().push_back(newElem);
634 newHyp.key(newKey);
635 newHyp.updateParams(nextMicroCateg, false, true, m_language);
636 m_hypsStack.push_front(newHyp);
637 if (m_hypsStack.size() > MAXPATHS)
638 m_hypsStack.pop_back();
639 }
640 else //chain(s) begin(s) found
641 {
642// LDEBUG << "chain(s) begin(s) found" << nextVertex;
643 std::set<uint64_t>::const_iterator nextVertexBeginChainsIdsIt, nextVertexBeginChainsIdsIt_end;
644 nextVertexBeginChainsIdsIt = nextVertexBeginChainsIds.begin();
645 nextVertexBeginChainsIdsIt_end = nextVertexBeginChainsIds.end();
646 for (; nextVertexBeginChainsIdsIt != nextVertexBeginChainsIdsIt_end; nextVertexBeginChainsIdsIt++)
647 {
648 std::set<uint64_t> nextVertexChainsIdsToIgnore = nextVertexChainsIds;
649 nextVertexChainsIdsToIgnore.erase(*nextVertexBeginChainsIdsIt);
650
651 Key newKey(nextVertex, currentKey.chainsToIgnore());
652 newKey.chainsToIgnore().insert(nextVertexChainsIdsToIgnore.begin(), nextVertexChainsIdsToIgnore.end());
653 Path newHyp(currentHyp);
654 Elem newElem(*nextVertexBeginChainsIdsIt, 1);
655 newElem.elems().push_back(nextVertex);
656 newHyp.updateParams(nextMicroCateg, true, false, m_language);
657 newHyp.elems().push_back(newElem);
658 newHyp.key(newKey);
659 m_hypsStack.push_front(newHyp);
660 if (m_hypsStack.size() > MAXPATHS)
661 m_hypsStack.pop_back();
662 }
663 }
664// LDEBUG << "END startWithSeveralChainsOnNewVertex: " << nextVertex;
665}
666
669{
670// SADLOGINIT;
671// LDEBUG << "ChainsDisambiguator::applyDisambiguisation on " << m_completePaths.size() << " complete paths";
672 if (m_completePaths.empty()) return;
673 std::set< Path > updatedPaths;
674 std::multiset< Path >::const_iterator pathsIt, pathsIt_end;
675 pathsIt = m_completePaths.begin();
676 pathsIt_end = m_completePaths.end();
677 for (; pathsIt != pathsIt_end ; pathsIt++)
678 {
679 Path path = *pathsIt;
680 uint64_t nb = computeDepsNb(path);
681 path.depsNb(nb);
682// LDEBUG << path;
683 updatedPaths.insert(path);
684 }
685 const Path& selectedPath = *(updatedPaths.begin());
686// LDEBUG << "Selected path: " << selectedPath;
687 std::set< LinguisticGraphVertex > selectedVertices;
688 std::list< Elem >::const_iterator it, it_end;
689 it = selectedPath.elems().begin();
690 it_end = selectedPath.elems().end();
691 for (; it != it_end; it++)
692 {
693 const Elem& elem = *it;
694 if (elem.type() == 0)
695 selectedVertices.insert(elem.id());
696 else
697 {
698 std::vector< uint64_t >::const_iterator elit, elit_end;
699 elit = elem.elems().begin();
700 elit_end = elem.elems().end();
701 for (; elit != elit_end; elit++)
702 {
703 selectedVertices.insert(*elit);
704 }
705 }
706 }
707 LinguisticGraph& graph = *(m_data->graph());
708 DependencyGraph& depGraph = *(m_data->dependencyGraph());
709 std::list< LinguisticGraphVertex > verticesToExplore;
710 std::set< LinguisticGraphVertex > scheduledVertices;
711 verticesToExplore.push_back(m_srcVertex);
712 scheduledVertices.insert(m_srcVertex);
713
714 // clearing unselected vertices
715 while (! verticesToExplore.empty() )
716 {
717 LinguisticGraphVertex currentVertex = verticesToExplore.front();
718 verticesToExplore.pop_front();
719 LinguisticGraphOutEdgeIt it, it_end;
720 boost::tie(it, it_end) = boost::out_edges(currentVertex, graph);
721 for (; it != it_end; it++)
722 {
723 LinguisticGraphVertex nextVertex = target(*it, graph);
724 if ( (nextVertex != m_tgtVertex) && (nextVertex != 1) &&
725 (scheduledVertices.find(nextVertex) == scheduledVertices.end() ) )
726 {
727 scheduledVertices.insert(nextVertex);
728 verticesToExplore.push_back(nextVertex);
729 }
730 }
731 if (selectedVertices.find(currentVertex) == selectedVertices.end())
732 {
733// LDEBUG << "Clearing " << currentVertex << "(dep="<<m_data->depVertexForTokenVertex(currentVertex)<<")";
734 boost::clear_vertex(m_data->depVertexForTokenVertex(currentVertex), depGraph );
735 boost::clear_vertex(currentVertex, graph);
736 //boost::remove_vertex(currentVertex, graph);
737 }
738 }
739
740 //removing unselected chains from selected vertices
741 VertexChainIdPropertyMap chainsMap = get(vertex_chain_id, graph);
742// EdgeDepChainIdPropertyMap edcipm = get(edge_depchain_id,depGraph);
743
744 it = selectedPath.elems().begin();
745 it_end = selectedPath.elems().end();
746 for (; it != it_end; it++)
747 {
748 const Elem& elem = *it;
749 if (elem.type() == 0)
750 {
751 LinguisticGraphVertex currentVertex = elem.id();
752 chainsMap[currentVertex] = std::set< ChainIdStruct >();
753// DependencyGraphVertex currentDepVertex = m_data->depVertexForTokenVertex(currentVertex);
754// DependencyGraphOutEdgeIt dit, dit_end;
755// boost::tie(dit, dit_end) = boost::out_edges(currentDepVertex, depGraph);
756// std::list< LinguisticGraphEdge > edgesToRemove;
757// for (; dit != dit_end; dit++)
758// {
759// DependencyGraphEdge edge = *dit;
760// if ( edcipm[edge].chainId() != UINT_MAX )
761// edgesToRemove.push_back(edge);
762// }
763// std::list< LinguisticGraphEdge >::iterator itr, itr_end;
764// itr = edgesToRemove.begin(); itr_end = edgesToRemove.end();
765// for (; itr != itr_end; itr++)
766// {
767// remove_edge(*itr, depGraph);
768// }
769 }
770 else
771 {
772 uint64_t chainId = elem.id();
773 LinguisticGraphVertex currentVertex = *(elem.elems().begin());
774 std::set< ChainIdStruct >& currentVertexChains = chainsMap[currentVertex];
775 ChainIdStruct cisToKeep;
776 std::set< ChainIdStruct >::const_iterator currentVertexChainsIt, currentVertexChainsIt_end;
777 currentVertexChainsIt = currentVertexChains.begin();
778 currentVertexChainsIt_end = currentVertexChains.end();
779 for (; currentVertexChainsIt != currentVertexChainsIt_end; currentVertexChainsIt++)
780 {
781 if ( (*currentVertexChainsIt).chainId() == chainId)
782 {
783 cisToKeep = *currentVertexChainsIt;
784 break;
785 }
786 }
788 throw std::runtime_error("Selected chain not found on current vertex");
789 std::vector< uint64_t >::const_iterator elit, elit_end;
790 elit = elem.elems().begin();
791 elit_end = elem.elems().end();
792 for (; elit != elit_end; elit++)
793 {
794 std::set< ChainIdStruct > newCurrentVertexChains;
795 ChainIdStruct cisToKeepCopy = cisToKeep;
796 if (elem.elems().size() == 1)
797 cisToKeepCopy.elemType(UNIGRAM);
798 else if (elit == elem.elems().begin())
799 cisToKeepCopy.elemType(BEGIN);
800 else if ( (elit+1) == elem.elems().end())
801 cisToKeepCopy.elemType(END);
802 else
803 cisToKeepCopy.elemType(PART);
804 newCurrentVertexChains.insert(cisToKeepCopy);
805 chainsMap[*elit] = newCurrentVertexChains;
806
807 DependencyGraphVertex currentDepVertex = m_data->depVertexForTokenVertex(*elit);
808 DependencyGraphOutEdgeIt dit, dit_end;
809 boost::tie(dit, dit_end) = boost::out_edges(currentDepVertex, depGraph);
810 std::list< LinguisticGraphEdge > edgesToRemove;
811 while (dit != dit_end)
812 {
813// DependencyGraphOutEdgeIt dit_copy = dit;
814 dit++;
815// DependencyGraphEdge edge = *dit_copy;
816/* if ( ( edcipm[edge].chainId() != UINT_MAX ) &&
817 ( edcipm[edge].chainId() != chainId ) )*/
818// edgesToRemove.push_back(edge);
819 }
820 std::list< LinguisticGraphEdge >::iterator itr, itr_end;
821 itr = edgesToRemove.begin(); itr_end = edgesToRemove.end();
822 for (; itr != itr_end; itr++)
823 {
824 remove_edge(*itr, depGraph);
825 }
826 }
827 }
828 }
829}
830
831uint64_t ChainsDisambiguator::computeDepsNb(const Path& path)
832{
833 LIMA_UNUSED(path);
834 uint64_t nb = 0;
835// const DependencyGraph& depGraph = *(m_data->dependencyGraph());
836// CEdgeDepChainIdPropertyMap edcipm = get(edge_depchain_id,depGraph);
837// std::list< Elem >::const_iterator ite, ite_end;
838// ite = path.elems().begin(); ite_end = path.elems().end();
839// for (; ite != ite_end; ite++)
840// {
841// const Elem& el = *ite;
842// if (el.type() == 0)
843// {
844// DependencyGraphVertex currentDepVertex = m_data->depVertexForTokenVertex(el.id());
845// DependencyGraphOutEdgeIt dit, dit_end;
846// boost::tie(dit, dit_end) = boost::out_edges(currentDepVertex, depGraph);
847// for (; dit != dit_end; dit++)
848// {
849// const DependencyGraphEdge& edge = *dit;
850// if ( edcipm[edge].chainId() == UINT_MAX )
851// nb++;
852// }
853// }
854// else
855// {
856// std::vector< uint64_t >::const_iterator itee, itee_end;
857// itee = el.elems().begin(); itee_end = el.elems().end();
858// for (; itee != itee_end; itee++)
859// {
860// DependencyGraphVertex currentDepVertex = m_data->depVertexForTokenVertex(*itee);
861// DependencyGraphOutEdgeIt dit, dit_end;
862// boost::tie(dit, dit_end) = boost::out_edges(currentDepVertex, depGraph);
863// for (; dit != dit_end; dit++)
864// {
865// const DependencyGraphEdge& edge = *dit;
866// if ( ( edcipm[edge].chainId() == UINT_MAX ) ||
867// ( edcipm[edge].chainId() == el.id() ) )
868// nb++;
869// }
870// }
871// }
872// }
873 return nb;
874}
875
877void ChainsDisambiguator::cancelCurrentChain(Elem elem, Path& hyp)
878{
879 hyp.elems().pop_back();
880 std::vector<uint64_t>::const_iterator elemElemsIt, elemElemsIt_end;
881 elemElemsIt = elem.elems().begin();
882 elemElemsIt_end = elem.elems().end();
883 for (; elemElemsIt != elemElemsIt_end; elemElemsIt++)
884 {
885 Elem newCurrentElem(*elemElemsIt);
886 hyp.elems().push_back(newCurrentElem);
888 hyp.chainsNb(hyp.chainsNb()-1);
889 }
890}
891
893{
894 m_id = elem.m_id;
895 m_type = elem.m_type;
896 m_elems = elem.m_elems;
897 return *this;
898}
899
901{
902 m_id = key.m_id;
903 m_chainsToIgnore = key.m_chainsToIgnore;
904 return *this;
905}
906
908 uint64_t id,
909 const std::set< uint64_t>& chainsToIgnore,
910 unsigned char type,
911 uint64_t chainId) :
912 m_key(id, chainsToIgnore),
913 m_elems(),
914 m_idealConjVerbNb(1),
915 m_conjVerbNb(0),
916 m_outChainsWordsNb(0),
917 m_chainsNb(0),
918 m_depsNb(0)
919{
920 if (type == 0)
921 m_elems.push_back(Elem(id,type));
922 else if ( (type != 0) && (chainId != std::numeric_limits<uint64_t>::max()) )
923 {
924 Elem elem(chainId,type);
925 elem.elems().push_back(id);
926 m_elems.push_back(elem);
927 }
928 else if (type == 1)
929 throw std::runtime_error("Chains disambiguation: Chain id not given while creating path beginning by a chain.");
930 else
931 throw std::runtime_error("Chains disambiguation: Unsupported elem type while creating a Path.");
932}
933
934Path::Path(const Path& path) :
935 m_key(path.m_key),
936 m_elems(path.m_elems),
937 m_idealConjVerbNb(path.m_idealConjVerbNb),
938 m_conjVerbNb(path.m_conjVerbNb),
939 m_outChainsWordsNb(path.m_outChainsWordsNb),
940 m_chainsNb(path.m_chainsNb),
941 m_depsNb(path.m_depsNb)
942{}
943
945{
946 m_key = path.m_key;
947 m_elems = path.m_elems;
948 m_idealConjVerbNb = path.m_idealConjVerbNb;
949 m_conjVerbNb = path.m_conjVerbNb;
950 m_outChainsWordsNb = path.m_outChainsWordsNb;
951 m_chainsNb = path.m_chainsNb;
952 m_depsNb = path.m_depsNb;
953 return *this;
954}
955
956bool Path::operator<(const Path& path) const
957{
958 if ( ( ( m_idealConjVerbNb == m_conjVerbNb ) && ( path.m_idealConjVerbNb == path.m_conjVerbNb ) ) ||
959 ( ( m_idealConjVerbNb != m_conjVerbNb ) && ( path.m_idealConjVerbNb != path.m_conjVerbNb ) ) )
960 {
961 if ( m_outChainsWordsNb < path.m_outChainsWordsNb)
962 return true;
963 else if ( m_outChainsWordsNb > path.m_outChainsWordsNb)
964 return false;
965 else
966 {
967 if ( m_chainsNb < path.m_chainsNb)
968 return true;
969 else if ( m_chainsNb > path.m_chainsNb)
970 return false;
971 else
972 return ( m_depsNb > path.m_depsNb );
973 }
974 }
975 else
976 return ( m_idealConjVerbNb == m_conjVerbNb );
977}
978
980 const LinguisticCode& microCategory,
981 bool incrChainsNb,
982 bool incrOutChainsWordsNb,
983 MediaId language)
984{
985 if (static_cast<const Common::MediaticData::LanguageData&>(Common::MediaticData::MediaticData::single().mediaData(language)).isAConjugatedVerb(microCategory))
986 m_conjVerbNb++;
987 else if (static_cast<const Common::MediaticData::LanguageData&>(Common::MediaticData::MediaticData::single().mediaData(language)).isAPropositionIntroductor(microCategory))
988 m_idealConjVerbNb++;
989
990 if (incrChainsNb) m_chainsNb++;
991 if (incrOutChainsWordsNb) m_outChainsWordsNb++;
992}
993
994std::ostream& operator<<(std::ostream &os, const Key& k)
995{
996 os << k.id() << " ( ";
997 std::set< uint64_t >::const_iterator it, it_end;
998 it = k.chainsToIgnore().begin(); it_end = k.chainsToIgnore().end();
999 for (; it != it_end; it++)
1000 {
1001 os << *it << " ";
1002 }
1003 os << ")";
1004 return os;
1005}
1006
1007std::ostream& operator<<(std::ostream &os, const Elem& e)
1008{
1009 if (e.type() != 0)
1010 {
1011 os << "[" << e.id() << ": ";
1012 std::vector< uint64_t >::const_iterator it, it_end;
1013 it = e.elems().begin(); it_end = e.elems().end();
1014 for (; it != it_end; it++)
1015 {
1016 os << *it << " ";
1017 }
1018 os << "]";
1019 }
1020 else
1021 os << e.id();
1022 return os;
1023}
1024
1025std::ostream& operator<<(std::ostream &os, const Path& p)
1026{
1027 os << p.key() << " | ";
1028 std::list< Elem >::const_iterator it, it_end;
1029 it = p.elems().begin(); it_end = p.elems().end();
1030 for (; it != it_end; it++)
1031 {
1032 os << *it << " ";
1033 }
1034 os << " | " << p.idealConjVerbNb() << "/" << p.conjVerbNb() << " "
1035 << p.outChainsWordsNb() << " " << p.chainsNb() << " " << p.depsNb() << std::endl;
1036 return os;
1037}
1038} // closing namespace SyntacticAnalysis
1039} // closing namespace LinguisticProcessing
1040} // closing namespace Lima
#define MAXPATHS
Definition of classes for disambiguation of syntagmatic chains paths.
#define SADLOGINIT
DependencyGraph::out_edge_iterator DependencyGraphOutEdgeIt
DependencyGraph::vertex_descriptor DependencyGraphVertex
boost::adjacency_list< boost::vecS, boost::vecS, boost::bidirectionalS, DepVertexProperties, DepEdgeProperties > DependencyGraph
The dependency graph class.
#define LWARN
Definition LimaCommon.h:160
#define LIMA_UNUSED(x)
Definition LimaCommon.h:224
boost::property_map< LinguisticGraph, vertex_data_t >::const_type CVertexDataPropertyMap
boost::property_map< LinguisticGraph, vertex_chain_id_t >::type VertexChainIdPropertyMap
LinguisticGraph::vertex_descriptor LinguisticGraphVertex
boost::property_map< LinguisticGraph, vertex_chain_id_t >::const_type CVertexChainIdPropertyMap
@ 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.
@ vertex_chain_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.
const LinguisticGraphVertex & lastVertex(void) const
Returns the last vertex of the graph.
const LinguisticGraphVertex & firstVertex(void) const
Returns the first vertex of the graph.
LinguisticCode firstValue(const Common::PropertyCode::PropertyAccessor &propertyAccessor) const
Return the first non empty value for the given accessor.
Builds possible chains paths between two vertices.
ChainsDisambiguator(SyntacticData *data, const LinguisticGraphVertex &s, const LinguisticGraphVertex &t, MediaId language, uint64_t depGraphMaxBranchingFactor)
Main constructor.
ChainsDisambiguator & operator=(const ChainsDisambiguator &cd)
Affectation operator.
void applyDisambiguisation()
Modify the graph to keep only the selected path.
An element of a Path (out of chain vertex or candidate chain)
unsigned char type() const
Accessor to the type of this elem: vertex or chain.
const std::vector< uint64_t > & elems() const
Const accessor to the subelements collection.
uint64_t id() const
Accessor to the vertex or chain id.
Stores a path end vertex id and the chains ids that have been found to ignore.
const std::set< uint64_t > & chainsToIgnore() const
Path(uint64_t id, const std::set< uint64_t > &chainsToIgnore, unsigned char type=0, uint64_t chainId=std::numeric_limits< uint64_t >::max())
void updateParams(const LinguisticCode &microCateg, bool incrChainsNb, bool incrOutChainsWordsNb, MediaId language)
Updates the parameters used to compute the weight of this path.
This class points to a graph, its dependency graph and the structure that holds the maping between th...
DependencyGraphVertex depVertexForTokenVertex(const LinguisticGraphVertex &v) const
LinguisticAnalysisStructure::AnalysisGraph * iterator()
static const MediaticData & single()
const singleton accessor
Definition Singleton.h:51
std::ostream & operator<<(std::ostream &os, const Key &k)
Operators to dump to stream the classes defined here.
NAUTITIA.