Word_Form* Word_Form::CreateNewVersioned( const std::set<int> & ialt ) const { lem::MCollect<Word_Form*> cluster; const int nver = 1 + CastSizeToInt(GetAlts().size()); for( std::set<int>::const_iterator iver=ialt.begin(); iver!=ialt.end(); ++iver ) { const int iiver = *iver; const Word_Form &wf = iiver==0 ? *this : *GetAlts()[iiver-1]; Word_Form * new_wf = new Word_Form( wf, false ); new_wf->SetOriginPos( GetOriginPos() ); cluster.push_back( new_wf ); } if( cluster.empty() ) { // Это странная ситуация. return new Word_Form(*this); } if( cluster.size()==1 ) return cluster.front(); // Словоформы кластера надо объединить. Word_Form *head = cluster.front(); #if !defined SOL_NO_AA for( lem::Container::size_type i=1; i<cluster.size(); ++i ) head->AddAlt( cluster[i] ); #endif return head; }
bool ModelTagMatcher::Match( const Word_Form & wf, Solarix::Dictionary & dict ) const { if( !lexeme.empty() ) { if( !lexeme.eqi( *wf.GetName() ) ) return false; } else if( !id_lemma.empty() ) { bool m=false; for( lem::Container::size_type i=0; i<id_lemma.size(); ++i ) if( id_lemma[i] == wf.GetEntryKey() ) { m=true; break; } if( !m ) return false; } else if( !pos.empty() ) { bool m=false; const int ekey = wf.GetEntryKey(); const SG_Entry & e = dict.GetSynGram().GetEntry(ekey); const int wf_pos = e.GetClass(); for( lem::Container::size_type i=0; i<pos.size(); ++i ) if( pos[i]==wf_pos ) { m=true; break; } if( !m ) return false; } if( !pairs.empty() ) { for( lem::Container::size_type i=0; i<pairs.size(); ++i ) { const GramCoordPair & p = pairs[i]; if( wf.GetPairs().FindOnce(p)!=UNKNOWN ) continue; // для бистабильных координат - состояние 0 равнозначно отсутствию вообще такой пары if( dict.GetSynGram().coords()[ p.GetCoord().GetIndex() ].IsBistable() ) { if( wf.GetPairs().FindOnce( p.GetCoord().GetIndex() ) != UNKNOWN ) return false; } else return false; } } return true; }
void Tree_Node::LoadBin(lem::Stream &bin) { bin.read(&ilink, sizeof(ilink)); Word_Form *wf = new Word_Form; wf->LoadBin(bin); node = boost::shared_ptr<Word_Form>(wf); child.LoadBin(bin); dims.LoadBin(bin); return; }
lem::Ptr<TrValue> TrFun_CreateWordform::Run( const ElapsedTimeConstraint & constraints, PM_Automat &pm, TrFunContext &ctx, TrTrace *trace_log ) const { const int mark = TrTraceActor::seq++; if( trace_log!=NULL ) trace_log->Enter( new TrTraceFunCall(mark,src_location,this,&ctx,false) ); SynGram &sg = pm.GetDict().GetSynGram(); const int ekey = ientry->Run(constraints,pm,ctx,trace_log)->GetInt(); const SG_Entry &e = sg.GetEntry( ekey ); Word_Form *wf = new Word_Form( form_name.empty() ? e.GetName() : form_name, e.GetKey() ); // Скопируем в словоформу атрибуты статьи for( lem::Container::size_type i=0; i<e.attrs().size(); ++i ) { wf->SetState( e.attrs()[i] ); } { // Теперь зададим измерения, которые определены внутри {...} for( lem::Container::size_type i=0; i<coords.size(); ++i ) { const int icoord = coords[i]->Run(constraints,pm,ctx,trace_log)->GetInt(); const int istate = states[i]->Run(constraints,pm,ctx,trace_log)->GetInt(); wf->SetState( GramCoordPair( icoord, istate ) ); } } if( form_name.empty() ) { wf->Rename_By_States(sg); } Tree_Node *tn = new Tree_Node(wf,true); lem::Ptr<TrValue> ret( new TrValue(tn,true) ); if( trace_log!=NULL ) trace_log->Leave( new TrTraceFunCall(mark,src_location,this,&ctx,false) ); return ret; }
int TF_ClassFilter::Score( const Word_Form &wf, const Dictionary &dict ) const { if( allowed_classes.empty() ) return 0; const int ekey = wf.GetEntryKey(); if( lem::is_quantor(ekey) ) return 0; const int iclass = dict.GetSynGram().GetEntry(ekey).GetClass(); return (iclass==UNKNOWN || allowed_classes.find(iclass)!=UNKNOWN) ? 0 : -100; }
bool Solarix::eq_states( const Word_Form &Node1, const GramCoordAdr &Coord1, const Word_Form &Node2, const GramCoordAdr &Coord2 ) { for( Container::size_type i1=0; i1<Node1.pairs().size(); i1++ ) if( Node1.pairs()[i1].GetCoord()==Coord1 ) for( Container::size_type i2=0; i2<Node2.pairs().size(); i2++ ) if( Node2.pairs()[i2].GetCoord()==Coord2 && ( Node1.pairs()[i1].GetState() == Node2.pairs()[i2].GetState() || Node1.pairs()[i1].GetState() == ANY_STATE || Node2.pairs()[i2].GetState() == ANY_STATE ) ) return true; return false; }
bool GeneratorLexer::Fetch( const LexerTextPos * current, const TokenExpectation * unused, lem::MCollect<const LexerTextPos*> & next ) { if( current==NULL ) { next.push_back( GetBeginToken() ); return true; } if( current->IsEnd() ) { return false; } next.clear(); // поищем в кэше уже найденные продолжения. std::pair<CACHED_EDGES::const_iterator,CACHED_EDGES::const_iterator> p_edges = edges.equal_range(current); if( p_edges.first!=p_edges.second ) { for( CACHED_EDGES::const_iterator it=p_edges.first; it!=p_edges.second; ++it ) { next.push_back( it->second ); } return true; } // Посмотрим, какие токены были перед данным, и какие слова они уже использовали. lem::MCollect<int> indeces; CollectUsedWords( current, indeces ); /* #if LEM_DEBUGGING==1 if( current->GetWordform()->GetName()->eqi(L"ловит") ) { lem::mout->printf("!\n"); } #endif */ bool token_created=false; lem::MCollect<const LexerTextPos*> matched_by_literal_ngrams, matched_by_normalized_ngrams, all_next_tokens; lem::Ptr<Ngrams> ngrams; lem::UCString prev_lemma; if( UseNGrams ) ngrams = dict->GetNgrams(); // Теперь неиспользованные ранее слова порождают новые токены. for( lem::Container::size_type i=0; i<words.size(); ++i ) if( indeces.find(i)==UNKNOWN ) { // слово не использовалось. typedef INDEX2WORDFORM::const_iterator IT; std::pair<IT,IT> p = index2wordform.equal_range( CastSizeToInt(i) ); for( IT it=p.first; it!=p.second; ++it ) { const Word_Form * wordform = it->second; const int word_index = current->IsRealWord() ? current->GetWordIndex()+1 : 0; const int start_pos = current->IsRealWord() ? (current->GetStartPosition()+current->GetWordLength()+1) : 0; // Нам нужно создать новый вариант этой словоформы. Word_Form * wf = new Word_Form( *wordform, true ); wf->SetOriginPos( word_index ); wordforms.push_back(wf); LexerTextPos * new_token = new LexerTextPos( current, wf, 0, start_pos, wf->GetName()->length(), word_index ); positions.push_back(new_token); all_next_tokens.push_back( new_token ); token2word.insert( std::make_pair(new_token,CastSizeToInt(i)) ); token_created = true; // Слово сочетается с предыдущим? if( UseNGrams && current->IsRealWord() ) { const lem::UCString & prev_word = * current->GetWordform()->GetNormalized(); const lem::UCString & new_word = * new_token->GetWordform()->GetNormalized(); float w2=0; int iw2=0; if( ngrams->FindLiteralNGrams( prev_word, new_word, w2, iw2 ) ) { // TODO: использовать частотность подошедшей N-граммы для взвешивания созданных токенов. matched_by_literal_ngrams.push_back( new_token ); } else { if( prev_lemma.empty() ) { const int prev_ekey = current->GetWordform()->GetEntryKey(); const SG_Entry & prev_e = dict->GetSynGram().GetEntry( prev_ekey ); prev_lemma = prev_e.GetName(); } const int new_ekey = new_token->GetWordform()->GetEntryKey(); const SG_Entry & new_e = dict->GetSynGram().GetEntry( new_ekey ); const lem::UCString & new_lemma = new_e.GetName(); if( ngrams->FindRawNGrams( prev_lemma, new_lemma, w2, iw2 ) ) { // TODO: использовать частотность подошедшей N-граммы для взвешивания созданных токенов. matched_by_normalized_ngrams.push_back( new_token ); } } } } } if( !matched_by_literal_ngrams.empty() ) { // найдена по крайней мере одна буквальная 2-грамма, поэтому отбрасываем все неподтвержденные варианты токенов. next = matched_by_literal_ngrams; } else if( !matched_by_normalized_ngrams.empty() ) { next = matched_by_normalized_ngrams; } else { next = all_next_tokens; } for( lem::Container::size_type i=0; i<next.size(); ++i ) { edges.insert( std::make_pair(current, const_cast<LexerTextPos*>( next[i] ) ) ); } /* #if LEM_DEBUGGING==1 lem::mout->printf( "%60h-\n" ); for( lem::Container::size_type i=0; i<next.size(); ++i ) { lem::mout->printf( "FETCHED: %us(%p) -> %us(%p)\n", current->GetWordform()->GetName()->c_str(), current, next[i]->GetWordform()->GetName()->c_str(), next[i] ); } #endif */ if( !token_created ) { // Возвращаем правую границу. next.push_back( GetEndToken(current) ); return true; } return false; }
/********************************************************************** Проверяет равенство координатных пар, хранимых в списке pair здесь и в указанной словоформе wf, причем из процедуры сравнения исключаются переданные в списке excoord координаты. Также проверяется совпадение хранимой лексической информации. ***********************************************************************/ bool Word_Form::AreEqualExcept( const Word_Form &wf, const CA_Array &excoord ) const { // Прежде всего должна совпасть хранимая лексическая информация. if( entry_key==UNKNOWN_STATE || wf.entry_key==UNKNOWN_STATE ) return wf.GetName() == GetName(); if( entry_key != wf.entry_key ) return false; // Собираем координаты для нашей словоформы. const Container::size_type npair=pair.size(); CA_Array pairs; pairs.reserve( npair+1 ); for( Container::size_type i1=0; i1<npair; i1++ ) { const GramCoordAdr pair_index = pair[i1].GetCoord(); if( // Если координата уже попала в список, и она встречается второй раз, // то это AND-координата, мы ее второй раз в список не будем включать. pairs.find(pair_index)!=UNKNOWN || // Координаты из списка excoord не включаем в проверку. excoord.find(pair_index)!=UNKNOWN ) continue; pairs.push_back(pair_index); } // Добавляем координаты второй синтаксемы. const Container::size_type nwfpair=wf.GetnPair(); for( Container::size_type i2=0; i2<nwfpair; i2++ ) { const GramCoordAdr pair_index = wf.pair[i2].GetCoord(); if( // Если координата уже попала в список, и она встречается второй раз, // то это AND-координата. pairs.find(pair_index)!=UNKNOWN || excoord.find(pair_index)!=UNKNOWN ) continue; pairs.push_back(pair_index); } // Проверяем совпадение координат из списка собранных нами. // // Требуем от обеих словоформ дать списки состояний по очередной // координате из приготовленного списка pairs. При этом мы учтем // И-координаты. Далее проверяем, чтобы у полученных списков // состояний совпали хотя бы по одному состоянию. for( Container::size_type i3=0; i3<pairs.size(); i3++ ) { const IntCollect pair_states1 = GetStates(pairs[i3]); const IntCollect pair_states2 = wf.GetStates(pairs[i3]); if( !find_any(pair_states1,pair_states2) ) return false; } // Список координат для проверки оказался пуст - считаем, что все совпали. return true; }