Пример #1
0
/*****************************************************************************
 Ищем вершины Сети и добавляем их в список finitees. Эта процедура вызываетс
 после построения Сети при подготовке фразоблока к проекции. Нам нужно
 заполнить список finitees - конечные узлы (листья). Стартуя из корня Сети,
 мы продвигаемся по каждой ветке, достигая конца. Внимание: не все найденные
 таким образом листья являются правильными: дело в том, что построение Сети
 для некоторых веток может обрываться алгоритмом, и нужно уметь обнаруживать,
 что лист не заканчивает на самом деле ветку. Это легко сделать, зная общее
 число слов в исходном предложении nword и параметры каждого узла Сети.
******************************************************************************/
void MLNetNode::FindFinitees(
    MCollect<const MLNetNode*> &finitees,
    int nword
) const
{
    // Если данный узел не имеет прикрепленных к нему последующих,
    // то мы нашли один из конечных узлов Сети Потока Распознования.
    const int nchild = GetnChild();
    if (!nchild)
    {
        if (from + n == nword)
            // Истинный лист - ветка доведена до конца предложения.
            finitees.push_back(this);

        return;
    }

    // Рекурсивно перепоручим последующим узлам найти конечные.
    for (int i = 0; i < nchild; i++)
    {
        GetChild(i).FindFinitees(finitees, nword);
    }

    return;
}
Пример #2
0
void LA_WordProjBuffer::Pick_Projection(
                                        LA_ProjList *sublist,
                                        int i_proj,
                                        MCollect<Word_Coord> &coord_list,
                                        MCollect<ProjScore> &val_list,
                                        PtrCollect<LA_ProjectInfo>& prj_extra_inf
                                       )
{
 // Нашли проекцию для данной мультилексемы!
 n_succ++;

 const MCollect<Word_Coord> &coords_to_copy = (*sublist)[i_proj].GetCoord();
 const MCollect<ProjScore> &vals_to_copy = (*sublist)[i_proj].GetVal();

 for( Container::size_type j=0; j<coords_to_copy.size(); j++ )
  {
   coord_list.push_back( coords_to_copy[j] );
   val_list.push_back( vals_to_copy[j] );
   prj_extra_inf.push_back(NULL);
  }

 (*sublist)[i_proj].Used();
 return;
}
Пример #3
0
MLNetNode::MLNetNode(
    const MLNetNode* prev,
    int ifrom,
    int nword,
    int tot_len,
    const MCollect<MLProjJob*> &proj,
    const MCollect<MLProjList*> &job_list,
    const MCollect<int> &word_job,
    const MCollect<Lexem> &words,
    Dictionary &dict
)
{
    // Наш узел описывает мультилексемы, начнающиеся с позиции ifrom и
    // содержащие nword лексем.
    previous = prev;
    from = ifrom;
    n = nword;

    const int njob = CastSizeToInt(job_list.size());

    // Собираем пробные мультилексемы, начиная с позиции from предложения.
    // Общая длина предложения задана как tot_len, максимальная длина
    // создаваемых мультилексем равна max_ml_len. Информация о пробных
    // мультилексемах будет хранится в подключаемых узлах.
    const int iFrom = ifrom + nword; // Индекс начала следующих мультилексем.

    if (iFrom == tot_len)
        return;

    int IPROJ_found = UNKNOWN;
    bool PROJ_found = false;

    int max_ml_len = dict.GetSynGram().IsMultiLexemBegin(words[iFrom]);
    if (max_ml_len <= 0)
        max_ml_len = 1;

    Lexem ml;

    SynGram &sg = dict.GetSynGram();

    for (int len = 1; len <= max_ml_len && (iFrom + len) <= tot_len; len++)
    {
        if (len == 1)
        {
            PROJ_found = true;

            const int m0 = tot_len - iFrom;
            const int m1 = std::min(m0, max_ml_len);
            if (m1 == 2)
            {
                if (!sg.IsWordForm(words[iFrom]))
                {
                    ml = words[iFrom];
                    ml.Add(words[iFrom + 1]);
                    if (sg.IsMultiLexem(ml))
                        continue;
                }
                else if (!sg.IsWordForm(words[iFrom + 1]))
                {
                    ml = words[iFrom];
                    ml.Add(words[iFrom + 1]);
                    if (sg.IsMultiLexem(ml))
                        continue;
                }
            }
            else if (m1 == 3)
            {
                ml = words[iFrom];
                ml.Add(words[iFrom + 1]);
                ml.Add(words[iFrom + 2]);
                if (sg.IsMultiLexem(ml))
                {
                    ml = words[iFrom + 1];
                    ml.Add(words[iFrom + 2]);
                    if (!sg.IsMultiLexem(ml))
                    {
                        if (!sg.IsWordForm(words[iFrom + 1]) || !sg.IsWordForm(words[iFrom + 2]))
                            continue;
                    }
                }
            }
        }
        else
        {
            PROJ_found = false;
            IPROJ_found = UNKNOWN;

            ml.clear();
            for (int ii = 0; ii < len; ii++)
                ml.Add(words[iFrom + ii]);

            if (dict.GetSynGram().IsMultiLexem(ml))
            {
                // Если в списке job_list заданий на проекцию мультилексем фразоблока
                // удастся найти задание для нашей мультилексемы и эта мультилексема
                // хоть раз спроецирована, то имеет смысл продолжать построение сети
                // далее.
                for (int ijob = 0; ijob < njob; ijob++)
                {
                    if (
                        *(job_list[ijob]->GetContent()) == ml &&
                        job_list[ijob]->IsProjected()
                        )
                    {
                        PROJ_found = true;
                        IPROJ_found = ijob;
                        break;
                    }
                }
            }
        }

        if (!PROJ_found)
            continue;

        MLNetNode *to_add = new MLNetNode(
            this,
            iFrom,
            len,
            tot_len,
            proj,
            job_list,
            word_job,
            words,
            dict
        );

        child.push_back(to_add);

        // Выставим для узла to_add значение достоверности и индекса задания на
        // проекцию.
        if (len == 1)
        {
            const MLProjJob &prj = *proj[word_job[iFrom]];
            to_add->val = prj.GetVal();
            to_add->proj_job_i = prj.GetiJob();

            //mout.printf( "ml=%us val=%f\n",  proj[word_job[iFrom]].GetContent()->string().c_str(), prj.GetVal().GetFloat() );
        }
        else
        {
            Real1 VAL(100);
            to_add->val = VAL;
            to_add->proj_job_i = IPROJ_found;
        }
    }

    return;
}
Пример #4
0
/*****************************************************************************

                         ФОНЕТИЧЕСКИЙ АЛЕФ-АВТОМАТ.

  Именно его деятельность привносит в Систему особый шик распознавания слов,
  написанных НЕ СОВСЕМ верно, к примеру, с орфографическими ошибками.

  ВХОДНЫЕ ПАРАМЕТРЫ;

   proj - задание на проекцию, содержит мультилексему, реально присутствующую
          в исходном предложении.

  ВОЗВРАЩАЕМЫЙ РЕЗУЛЬТАТ:

   Через параметр proj возвращается список фонетических инвариантов дл
   слова-аргумента.
*****************************************************************************/
void LexicalAutomat::ProducePhonInv(MLProjList &proj, int id_language, LA_RecognitionTrace *trace)
{
    // В число оригиналов входят и "ломанные"
    int n_org = 1 + CastSizeToInt(proj.get_Broken().size());

    std::set<lem::UCString> created_phonetic_variants;

    for (int iorg = 0; iorg < n_org; iorg++)
    {
        const RC_Lexem &word = !iorg ?
            proj.GetContent() :
            proj.get_Broken()[iorg - 1];

        const Lexem &mlex = *word;

        // Сама исходная, неискаженная лексема также примет участие в микшировании.
        // Для однолексем брать оригинал не имеет смысла - его и так спроецировали.
        if (created_phonetic_variants.find(mlex) == created_phonetic_variants.end())
        {
            created_phonetic_variants.insert(mlex);

            // Получим списки фонетических инвариантов для каждой из nlex лексем,
            // входящий в мультилексему.
            MCollect<LA_AA_list*> packs;
            LA_AA_list *list = new LA_AA_list;
            list->reserve(16);
            list->push_back(LA_AA_item(mlex, Real1(100)));

            // Теперь мутированные варианты.
            LA_Pack *pack = AlephAuto(id_language, mlex, proj.get_Miss_Parameter(), trace);

            for (Container::size_type j = 0; j < pack->size(); j++)
            {
                const Solarix::Lexem &ph_lex = *(pack->get(j));

                if (created_phonetic_variants.find(ph_lex) == created_phonetic_variants.end())
                {
                    created_phonetic_variants.insert(ph_lex);
                    list->push_back(LA_AA_item(ph_lex, pack->get(j)->get_Val()));
                }
            }

            delete pack;

            packs.push_back(list);

            const int NTOT = CastSizeToInt(packs.front()->size());

            // Пропускаем начальную немутированную лексему
            for (int i = 1; i < NTOT; i++)
            {
                const LA_AA_item &x = packs.front()->get(i);
                Lexem *mutated = new Lexem(x);

                proj.AddPhonInv(RC_Lexem(mutated), x.val);
            }

            // Удаляем ненужные далее списки фонетических инвариантов для однолексем.
            ZAP_A(packs);

            // Отсортируем мутации по убыванию достоверности.
            proj.SortPhonInv();

            /*
                 // Можем журнализовать результат.
                 const int ninv=proj.GetnPhonInv();
                 if( ninv && GetDebugLevel()>=2 )
                  {
                   lem::LogFile::logfile->printf( "LA: Phonetic invariants production: %d item(s)\n", ninv );

                   for( int i=0; i<ninv; i++ )
                    {
                     lem::LogFile::logfile->printf( "#%d ", i );
                     const RC_Lexem &ml = proj.GetPhonInv(i);
                     lem::LogFile::logfile->printf( "%us\n", ml->c_str() );
                    }

                   lem::LogFile::logfile->eol();
                  }
            */
        }
    } // for - цикл по оригиналам

    return;
}