Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
/**********************************************************************
 Проверяет равенство координатных пар, хранимых в списке 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;
}