/*********************************************************************** Подготовка к работе после загрузки содержимого из текстового файла Словаря. Процедура вызывается модулем Словаря автоматически. Выполняем некоторые операции, которые позволят реализовать быстрый алгоритм проецирования мультилексем на Лексикон. То есть, мы создадим и сохраним некоторые информационные структуры, чтобы при поиске словоформ не отвлекаться на создание этих структур снова и снова. Только после выполнения этой процедуры Лексикон готов к использованию другими автоматами. ***********************************************************************/ void SynGram::Prepare( const lem::Path &outdir, const Binarization_Options &opts ) { Grammar::Prepare(outdir,opts); word_entries->CommitCompilation( GetIO().merr() ); storage->CommitCompilation(); Generate_Links(opts); Write_Declarations(outdir); for( std::map<UCString,CplxLeft*>::iterator it=cplx_map.begin(); it!=cplx_map.end(); ++it ) { const CplxLeft &x = * it->second; GetStorage().StoreCplxLeft(x.headword,x.minlen,x.maxlen); } // Инициализируем частоты словарных статей и словоформ. if( wordfreq_filename.NotNull() ) { wordfreq_file.Delete(); lem::BinaryReader rdr( *wordfreq_filename ); const int dbg = 1; if( dbg>0 ) { // Длительная операция: сообщаем пользователю. GetIO().mecho().printf( "%vfESG%vn: updating word frequencies..." ); GetIO().mecho().flush(); } MCollect<Word_Coord> found_list; MCollect<ProjScore> val_list; PtrCollect<LA_ProjectInfo> inf_list; LexicalAutomat &la = GetDict().GetLexAuto(); while( !rdr.eof() ) { SG_calibrator c; c.LoadBin(rdr); if( rdr.eof() ) break; found_list.clear(); val_list.clear(); inf_list.clear(); Lexem uword(c.GetWord()); int language_id=UNKNOWN; // если указан грамматический класс, то берем id языка оттуда. if( c.GetClass()!=UNKNOWN ) { const Solarix::SG_Class & pos = GetClass( c.GetClass() ); language_id = pos.GetLanguage(); } la.TranslateLexem( uword, true, language_id ); RC_Lexem rc_name( &uword, null_deleter() ); la.ProjectWord( rc_name, found_list, val_list, inf_list, LexicalAutomat::Wordforms, 0, language_id, NULL ); if( c.IsWordEntry() ) { lem::MCollect<int> processed; for( lem::Container::size_type j=0; j<found_list.size(); ++j ) { if( processed.find(found_list[j].GetEntry())==UNKNOWN ) { processed.push_back( found_list[j].GetEntry() ); SG_Entry& e = GetEntries().GetEntryForChange( found_list[j].GetEntry() ); if( c.GetClass()!=UNKNOWN && c.GetClass()!=e.GetClass() ) continue; // Задаем частоту либо для всей словарной статьи e.UpdateFreq( c.GetFreq() ); } } } else if( c.IsWordForm() ) { if( found_list.empty() ) { GetIO().mecho().printf( "\nUnknown word [%us] in word_frequency rule\n", c.GetWord().c_str() ); throw lem::E_BaseException(); } for( lem::Container::size_type j=0; j<found_list.size(); ++j ) { const SG_Entry &e = GetEntry(found_list[j].GetEntry()); if( c.GetClass()!=UNKNOWN && c.GetClass()!=e.GetClass() ) { continue; } const SG_EntryForm &f = e.forms()[found_list[j].GetForm()]; if( c.MatchCoords( f.coords() ) ) { GetStorage().SetWordformFrequency( found_list[j].GetEntry(), found_list[j].GetForm(), c.GetFreq() ); } } } else { LEM_STOPIT; } } rdr.close(); wordfreq_filename->DoRemove(); if( dbg>0 ) { GetIO().mecho().printf( "%vfAOK%vn\n" ); } } return; }
/*********************************************************************** Подготовка к работе после загрузки содержимого из текстового файла Словаря. Процедура вызывается модулем Словаря автоматически. Выполняем некоторые операции, которые позволят реализовать быстрый алгоритм проецирования мультилексем на Лексикон. То есть, мы создадим и сохраним некоторые информационные структуры, чтобы при поиске словоформ не отвлекаться на создание этих структур снова и снова. Только после выполнения этой процедуры Лексикон готов к использованию другими автоматами. ***********************************************************************/ void SynGram::Prepare( const lem::Path &outdir, const Binarization_Options &opts ) { Grammar::Prepare(outdir,opts); word_entries->CommitCompilation( GetIO().merr() ); storage->CommitCompilation(); Generate_Links(opts); Write_Declarations(outdir); for( std::map<UCString,CplxLeft*>::iterator it=cplx_map.begin(); it!=cplx_map.end(); ++it ) { const CplxLeft &x = * it->second; GetStorage().StoreCplxLeft(x.headword,x.minlen,x.maxlen); } // Инициализируем частоты словарных статей и словоформ. // Нам потребуется быстро найти словарные статьи по их леммам. std::multimap<lem::UCString,int> lemma2id; lem::Ptr<WordEntryEnumerator> wenum( word_entries->ListEntries() ); while( wenum->Fetch() ) { lem::UCString entry_name = lem::to_upper( GetEntry( wenum->GetId() ).GetName() ); lemma2id.insert( std::make_pair( entry_name, wenum->GetId() ) ); } if( wordfreq_filename.NotNull() ) { wordfreq_file.Delete(); lem::BinaryReader rdr( *wordfreq_filename ); // Длительная операция: сообщаем пользователю. GetIO().mecho().printf( "%vfESG%vn: updating word frequencies..." ); GetIO().mecho().flush(); MCollect<Word_Coord> found_list; MCollect<ProjScore> val_list; PtrCollect<LA_ProjectInfo> inf_list; LexicalAutomat &la = GetDict().GetLexAuto(); int counter=0; while( !rdr.eof() ) { SG_calibrator c; c.LoadBin(rdr); if( rdr.eof() ) break; counter++; if( counter>0 && (counter%10000)==0 ) { lem::mout->printf( " %d", counter/10000 ); lem::mout->flush(); } Lexem uword( lem::to_upper( c.GetWord() ) ); if( c.IsWordFormsScore() ) { // Заданы оценки для всех форм слова lem::MCollect<int> ies; typedef std::multimap<lem::UCString,int>::const_iterator L2E_CIT; std::pair<L2E_CIT,L2E_CIT> r = lemma2id.equal_range( uword ); for( L2E_CIT it=r.first; it!=r.second; ++it ) { int id_entry = it->second; if( c.GetClass()==UNKNOWN || GetEntries().GetEntry( id_entry ).GetClass() == c.GetClass() ) { SG_Entry& e = GetEntries().GetEntryForChange( id_entry ); for( int iform=0; iform<e.forms().size(); ++iform ) { const SG_EntryForm &f = e.forms()[iform]; if( c.MatchCoords( f.coords() ) ) { GetStorage().SetWordformFrequency( id_entry, iform, c.GetFreq() ); } } } } } else if( c.GetClass()!=UNKNOWN && c.IsWordEntryFreq() ) { lem::MCollect<int> ies; typedef std::multimap<lem::UCString,int>::const_iterator L2E_CIT; std::pair<L2E_CIT,L2E_CIT> r = lemma2id.equal_range( uword ); for( L2E_CIT it=r.first; it!=r.second; ++it ) { int id_entry = it->second; if( GetEntries().GetEntry( id_entry ).GetClass() == c.GetClass() ) { SG_Entry& e = GetEntries().GetEntryForChange( id_entry ); e.UpdateFreq( c.GetFreq() ); } } } else if( c.IsWordFormScore() ) { // задан скоринг для словоформы. int language_id=UNKNOWN; // если указан грамматический класс, то берем id языка оттуда. if( c.GetClass()!=UNKNOWN ) { const Solarix::SG_Class & pos = GetClass( c.GetClass() ); language_id = pos.GetLanguage(); } la.TranslateLexem( uword, true, language_id ); RC_Lexem rc_name( &uword, null_deleter() ); found_list.clear(); val_list.clear(); inf_list.clear(); la.ProjectWord( rc_name, found_list, val_list, inf_list, LexicalAutomat::Wordforms, 0, language_id, NULL ); // задан скоринг для словоформы. if( found_list.empty() ) { GetIO().mecho().printf( "\nUnknown word [%us] in word_frequency rule\n", c.GetWord().c_str() ); throw lem::E_BaseException(); } for( lem::Container::size_type j=0; j<found_list.size(); ++j ) { const SG_Entry &e = GetEntry(found_list[j].GetEntry()); if( c.GetClass()!=UNKNOWN && c.GetClass()!=e.GetClass() ) { continue; } const SG_EntryForm &f = e.forms()[found_list[j].GetForm()]; if( c.MatchCoords( f.coords() ) ) { GetStorage().SetWordformFrequency( found_list[j].GetEntry(), found_list[j].GetForm(), c.GetFreq() ); } } } else { LEM_STOPIT; } } rdr.close(); wordfreq_filename->DoRemove(); GetIO().mecho().printf( "%vfAOK%vn\n" ); } return; }