Inheritance: IDisposable
Esempio n. 1
0
    static string GetFeatures(SolarixGrammarEngineNET.GrammarEngine2 gren, SolarixGrammarEngineNET.AnalysisResults words, int focus_index)
    {
        List <string> features = new List <string>();

        for (int offset = -window; offset <= window; ++offset)
        {
            int word_index = focus_index + offset;
            if (word_index >= 1 && word_index < words.Count - 1)
            {
                features.AddRange(GetWordFeatures(gren, words[word_index], offset.ToString()));

                if (word_index == 1)
                {
                    features.Add($"start[{offset}]");
                }

                if (word_index == words.Count - 2)
                {
                    features.Add($"end[{offset}]");
                }
            }
        }

        return(string.Join("\t", features));
    }
    public int Match(SolarixGrammarEngineNET.AnalysisResults tokens, int left_i, SolarixGrammarEngineNET.GrammarEngine2 gren)
    {
        // Проверяем, что не-омонимичные термы сопоставляются.
        bool m = true;

        for (int iterm = 0; iterm < points.Count; ++iterm)
        {
            if (points[iterm] != null)
            {
                SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[left_i + iterm];
                if (!points[iterm].Match(token, gren))
                {
                    m = false;
                    break;
                }
            }
        }

        if (m)
        {
            // Осталось проверить, правильно ли снята омонимия.
            SolarixGrammarEngineNET.SyntaxTreeNode omonym_token = tokens[left_i + omonym_point.GetPosition()];
            return(omonym_point.Match(omonym_token) ? 1 : 0);
        }

        return(-1);
    }
Esempio n. 3
0
    public bool ProcessSample(string line)
    {
        // синтаксический разбор в дерево
        SolarixGrammarEngineNET.AnalysisResults trees = gren.AnalyzeSyntax(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY, SolarixGrammarEngineNET.GrammarEngine.SyntaxFlags.SOL_GREN_REORDER_TREE);

        Collect(trees);

        return(true);
    }
Esempio n. 4
0
    public void Collect(SolarixGrammarEngineNET.AnalysisResults trees)
    {
        for (int iroot = 1; iroot < trees.Count - 1; ++iroot)
        {
            ProcessTree(trees[iroot]);
        }

        return;
    }
Esempio n. 5
0
    private void AssembleEdges(SolarixGrammarEngineNET.AnalysisResults syntax_tree, List <Edge4Stat> edges, Dictionary <string, NodeLeafCount> leaves)
    {
        for (int iroot = 1; iroot < syntax_tree.Count - 1; ++iroot)
        {
            AssembleEdges(syntax_tree[iroot], edges, leaves);
        }

        return;
    }
Esempio n. 6
0
    private void Assemble3Grams(SolarixGrammarEngineNET.AnalysisResults syntax_tree, List <Rule3Gram> ngrams)
    {
        for (int iroot = 1; iroot < syntax_tree.Count - 1; ++iroot)
        {
            Assemble3Grams(syntax_tree[iroot], ngrams);
        }

        return;
    }
Esempio n. 7
0
    public bool ProcessSample(string line)
    {
        n_learn_samples++;

        // Морфологический разбор
        using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY))
        {
            List <string> sfx       = new List <string>();
            List <int>    sfx_index = new List <int>();

            List <string> sfx_lemma       = new List <string>();
            List <int>    sfx_lemma_index = new List <int>();

            int last_word_index = tokens.Count - 1;

            for (int iword = 0; iword < tokens.Count; ++iword)
            {
                string word = tokens[iword].GetWord().ToLower();

                string suffix = GetTokenSuffix(iword, last_word_index, tokens[iword]);
                sfx.Add(suffix);

                int index = MatchSuffix(suffix, true);
                sfx_index.Add(index);

                int    ekey  = tokens[iword].GetEntryID();
                string ename = gren.GetEntryName(ekey);
                string lemma;
                if (IsUnknownLexem(ename))
                {
                    lemma = word;
                }
                else
                {
                    lemma = ename.ToLower();
                }

                sfx_lemma.Add(GetSuffix(lemma));
                sfx_lemma_index.Add(MatchSuffix(GetSuffix(lemma), true));
            }

            for (int iword = 1; iword < tokens.Count - 1; ++iword)
            {
                string tag1 = TagLabel(-1, sfx_index[iword - 1]);
                string tag2 = TagLabel(0, sfx_index[iword]);
                string tag3 = TagLabel(1, sfx_index[iword + 1]);

                string res = ResultLabel(sfx_lemma_index[iword]);
                WriteTrain(tag1, tag2, tag3, res);
            }
        }

        return(true);
    }
Esempio n. 8
0
    static void FindChunks(SolarixGrammarEngineNET.AnalysisResults root, Dictionary <int /*word_index*/, int /*chunk_index*/> labels)
    {
        var root_node = root[1];

        labels[root_node.GetWordPosition()] = root_node.GetWordPosition();

        for (int i = 0; i < root_node.leafs.Count; ++i)
        {
            var child_node  = root_node.leafs[i];
            int chunk_index = child_node.GetWordPosition();
            GetChunkNodes(child_node, chunk_index, labels);
        }
    }
    public OmonymContextEnumerator(SolarixGrammarEngineNET.AnalysisResults tokens, int _omonym_position, int _left_i, int _len, SolarixGrammarEngineNET.GrammarEngine2 _gren)
    {
        gren            = _gren;
        left_i          = _left_i;
        len             = _len;
        omonym_position = _omonym_position;

        recognizers = new List <ContextRecognizer>();

        // Для каждого токена, кроме омонимичной формы, генерируем список вариантов.

        // ... пока только код для контекстов длины=2
        if (len == 2)
        {
            SolarixGrammarEngineNET.SyntaxTreeNode omonym_token = tokens[left_i + omonym_position];

            OmonymTokenRecognizer omonym_point = new OmonymTokenRecognizer(omonym_position, omonym_token);

            if (omonym_position == 0)
            {
                TokenTagsEnumerator tte = new TokenTagsEnumerator(IsBoundaryToken(tokens, left_i + 1), tokens[left_i + 1], gren);

                int n = tte.Count;
                for (int i = 0; i < n; ++i)
                {
                    List <TokenRecognizer> points = new List <TokenRecognizer>();
                    points.Add(null); // это омонимичная форма
                    points.Add(tte[i]);
                    ContextRecognizer ctx_recognizer = new ContextRecognizer(points, omonym_point, gren);
                    recognizers.Add(ctx_recognizer);
                }
            }
            else
            {
                TokenTagsEnumerator tte = new TokenTagsEnumerator(IsBoundaryToken(tokens, left_i), tokens[left_i], gren);

                int n = tte.Count;
                for (int i = 0; i < n; ++i)
                {
                    List <TokenRecognizer> points = new List <TokenRecognizer>();
                    points.Add(tte[i]);
                    points.Add(null); // это омонимичная форма
                    ContextRecognizer ctx_recognizer = new ContextRecognizer(points, omonym_point, gren);
                    recognizers.Add(ctx_recognizer);
                }
            }
        }
    }
    public void ProcessSample(string line, SolarixGrammarEngineNET.AnalysisResults tokens, int LanguageID, SolarixGrammarEngineNET.GrammarEngine2 gren)
    {
        int sample_len = tokens.Count;

        for (int i = 0; i < sample_len; ++i)
        {
            if (tokens[i].GetWord().Equals(word, StringComparison.CurrentCultureIgnoreCase))
            {
                int position = i;

                // Омоним распознан однозначно?
                SolarixGrammarEngineNET.SyntaxTreeNode omonym_token = tokens[position];

                // Создаем все возможные контексты с омонимом - разной длины, с разным местоположением.
                int MIN_CONTEXT_LEN = 2, MAX_CONTEXT_LEN = 2;
                for (int left_i = position - MAX_CONTEXT_LEN + 1; left_i <= position; ++left_i)
                {
                    if (left_i >= 0)
                    {
                        int min_len = Math.Max(position - left_i + 1, MIN_CONTEXT_LEN);
                        for (int ctx_len = min_len; ctx_len <= MAX_CONTEXT_LEN; ++ctx_len)
                        {
                            OmonymContext ctx;
                            ctx.len      = ctx_len;
                            ctx.position = position - left_i;

                            if (rules.ContainsKey(ctx))
                            {
                                rules[ctx].ProcessSample(line, tokens, left_i, gren);
                            }
                            else
                            {
                                OmonymRule rule = new OmonymRule(ctx);
                                rules.Add(ctx, rule);
                                rule.ProcessSample(line, tokens, left_i, gren);
                            }
                        }
                    }
                }
            }
        }

        return;
    }
Esempio n. 11
0
    public void ProcessSample(string line)
    {
        if (samples.Contains(line))
        {
            return;
        }

        samples.Add(line);

        bool complete = false;

        using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeSyntax(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY, 0))
        {
            if (tokens.Count == 3)
            {
                complete = true;
                TraverseNode(tokens[1]);
            }
        }

        if (!complete)
        {
            // Морфологический разбор
            using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY))
            {
                for (int iword = 1; iword < tokens.Count - 2; ++iword)
                {
                    SolarixGrammarEngineNET.SyntaxTreeNode token  = tokens[iword];
                    SolarixGrammarEngineNET.SyntaxTreeNode token2 = tokens[iword + 1];

                    if (IsPreposition(token) && IsNoun(token2))
                    {
                        Store_Prepos_Noun(token, token2);
                    }
                    else if (IsVerb(token) && IsPreposition(token2))
                    {
                        Store_Verb_Prepos(token, token2);
                    }
                }
            }
        }

        return;
    }
Esempio n. 12
0
    public bool ProcessSample(string line)
    {
        // Морфологический разбор
        using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY))
        {
            int last_word_index = tokens.Count - 1;
            for (int i = 0; i < tokens.Count; ++i)
            {
                SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[i];
                int suffix_id1 = GetTokenSuffix(i, last_word_index, token);

                int nver = token.VersionCount();
                for (int j = 0; j < nver; ++j)
                {
                    int    ver_ekey   = token.GetVersionEntryID(j);
                    string ename      = gren.GetEntryName(ver_ekey);
                    int    suffix_id2 = GetFormSuffix(i, last_word_index, ename);
                }
            }
        }

        using (SolarixGrammarEngineNET.AnalysisResults projs = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_TOKENIZE_ONLY))
        {
            int last_word_index = projs.Count - 1;
            for (int i = 0; i < projs.Count; ++i)
            {
                SolarixGrammarEngineNET.SyntaxTreeNode token = projs[i];
                int suffix_id1 = GetTokenSuffix(i, last_word_index, token);

                int nver = token.VersionCount();
                for (int j = 0; j < nver; ++j)
                {
                    int    ver_ekey   = token.GetVersionEntryID(j);
                    string ename      = gren.GetEntryName(ver_ekey);
                    int    suffix_id2 = GetFormSuffix(i, last_word_index, ename);
                }
            }
        }


        return(true);
    }
    public MatchedContextInfo(string _sample, SolarixGrammarEngineNET.AnalysisResults tokens, int left_i, int len)
    {
        sample = _sample;

        System.Text.StringBuilder b = new StringBuilder();
        for (int i = 0; i < len; ++i)
        {
            string word = tokens[left_i + i].GetWord();
            if (i == 0)
            {
                b.AppendFormat("{0}", word);
            }
            else
            {
                b.AppendFormat(" {0}", word);
            }
        }

        context = b.ToString();
        return;
    }
    public bool ProcessSample(string line)
    {
        n_learn_samples++;

        // чтобы получить все возможные теги, надо для каждого слова получить все возможные распознавания.
        using (SolarixGrammarEngineNET.AnalysisResults projs = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_TOKENIZE_ONLY))
        {
            int last_word_index = projs.Count - 1;

            for (int iword = 0; iword < projs.Count; ++iword)
            {
                for (int iproj = 0; iproj < projs[iword].VersionCount(); ++iproj)
                {
                    string lemma = string.Empty;
                    int    ekey  = projs[iword].GetVersionEntryID(iproj);
                    string ename = gren.GetEntryName(ekey);
                    if (IsUnknownLexem(ename))
                    {
                        lemma = projs[iword].GetWord().ToLower();
                    }
                    else
                    {
                        lemma = ename.ToLower();
                    }

                    string sfx = GetTokenSuffix(iword, last_word_index, lemma);

                    int id_lemma = MatchSuffix(sfx, true);
                }
            }
        }


        // Морфологический разбор
        using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY))
        {
            List <string> sfx       = new List <string>();
            List <int>    sfx_index = new List <int>();

            List <string> sfx_lemma       = new List <string>();
            List <int>    sfx_lemma_index = new List <int>();

            int last_word_index = tokens.Count - 1;

            for (int iword = 0; iword < tokens.Count; ++iword)
            {
                string word = tokens[iword].GetWord().ToLower();

                string suffix = GetTokenSuffix(iword, last_word_index, tokens[iword]);
                sfx.Add(suffix);

                int index = MatchSuffix(suffix, true);
                sfx_index.Add(index);

                int    ekey  = tokens[iword].GetEntryID();
                string ename = gren.GetEntryName(ekey);
                string lemma;
                if (IsUnknownLexem(ename))
                {
                    lemma = word;
                }
                else
                {
                    lemma = ename.ToLower();
                }

                string lemma_suffix = GetTokenSuffix(iword, last_word_index, lemma);
                sfx_lemma.Add(lemma_suffix);
                sfx_lemma_index.Add(MatchSuffix(lemma_suffix, true));
            }

            for (int iword = 1; iword < tokens.Count - 1; ++iword)
            {
                string tag1 = LemmaLabel(-1, sfx_lemma_index[iword - 1]); // для Витерби

                // features как контекст +/-1 слово вокруг текущего
                string tag2 = TagLabel(-1, sfx_index[iword - 1]);
                string tag3 = TagLabel(0, sfx_index[iword]);
                string tag4 = TagLabel(1, sfx_index[iword + 1]);

                string res = ResultLabel(sfx_lemma_index[iword]);

                WriteTrain(tag1, tag2, tag3, tag4, res);
            }
        }

        return(true);
    }
Esempio n. 15
0
    public void Check(
        string line,
        ref int total_word_count,
        ref int error_count_no_filter,
        ref int error_count_with_model
        )
    {
        // Морфологический разбор
        using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY))
        {
            List <List <int> > word2tags     = new List <List <int> >();
            List <int>         selected_tags = new List <int>();

            // Токенизация без использования синтаксических правил
            using (SolarixGrammarEngineNET.AnalysisResults projs = gren.AnalyzeMorphology(line, LanguageID,
                                                                                          SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_TOKENIZE_ONLY /*| SolarixGrammarEngineNET.GrammarEngine.SOL_GREN_DISABLE_FILTERS*/))
            {
                if (tokens.Count != projs.Count)
                {
                    return;
                }

                // Преобразуем все проекции каждого слова в варианты распознавания тегов

                List <int> tag_set = new List <int>();

                int start_tag = -1, end_tag = -1;

                //List<string> words = new List<string>();
                bool unmatched_tag = false;

                List <int> suffices        = new List <int>();
                int        last_word_index = tokens.Count - 1;

                for (int i = 0; i < tokens.Count; ++i)
                {
                    SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[i];
                    string word = token.GetWord().ToLower();
                    //   words.Add(word);

                    int suffix_id = GetTokenSuffix(i, last_word_index, token);
                    suffices.Add(suffix_id);


                    SolarixGrammarEngineNET.SyntaxTreeNode proj = projs[i];
                    List <int> wt = new List <int>();
                    for (int j = 0; j < proj.VersionCount(); ++j)
                    {
                        int id_tag = tags.GetIndexById(tags.MatchTags(proj, j, gren));
                        if (id_tag != -1)
                        {
                            if (!wt.Contains(id_tag))
                            {
                                wt.Add(id_tag);
                            }

                            if (!tag_set.Contains(id_tag))
                            {
                                tag_set.Add(id_tag);
                            }
                        }

                        if (i == 0)
                        {
                            start_tag = id_tag;
                        }
                        else if (i == tokens.Count - 1)
                        {
                            end_tag = id_tag;
                        }
                    }

                    if (wt.Count == 0)
                    {
                        // ни один тег не подошел, это ошибка кодовой книги.
                        unmatched_tag = true;
                    }

                    word2tags.Add(wt);
                    selected_tags.Add(wt[0]);
                }

                if (unmatched_tag)
                {
                    return;
                }

                // -----------------------------------------
                // Посчитаем ошибки до применения модели
                // -----------------------------------------
                int n_err = 0;

                for (int iword = 1; iword < tokens.Count - 1; ++iword)
                {
                    SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[iword];
                    int ekey1     = token.GetEntryID();
                    int id_class1 = gren.GetEntryClass(ekey1);

                    int tag = selected_tags[iword];
                    if (tag != -1)
                    {
                        TagMatcher m = tags[tags.GetIdByIndex(tag)];
                        if (!m.MatchPartOfSpeech(id_class1))
                        {
                            n_err++;
                        }
                    }
                }

                error_count_no_filter += n_err;
                total_word_count      += (tokens.Count - 2);

                int Nword  = tokens.Count; // кол-во последовательных шагов - число слов, включая левую и правую границы
                int Nstate = tag_set.Count;

                // Viterbi trellis

                // вероятности для состояний
                double[,] V = new double[Nword, Nstate];
                for (int t = 0; t < Nword; ++t)
                {
                    for (int s = 0; s < Nstate; ++s)
                    {
                        V[t, s] = 0.0;
                    }
                }

                // backpointers для отслеживания лучшего пути
                int[,] BACKPOINTER = new int[Nword, Nstate];
                for (int t = 0; t < Nword; ++t)
                {
                    for (int s = 0; s < Nstate; ++s)
                    {
                        BACKPOINTER[t, s] = -1; // возможно, надо как-то инициализировать дефолтный путь на случай, если найти лучший не получится - то есть надо проставить от начального до конечного.
                    }
                }
                V[0, tag_set.IndexOf(start_tag)] = 1.0; // начальное состояние - стартуем из этого состояния.

                for (int t = 1; t < Nword; ++t)
                {
                    // проставляем вероятность получения состояний на шаге t, исходя из значений на предыдущем шаге.

                    for (int s2 = 0; s2 < Nstate; ++s2) // состояния на шаге t
                    {
                        double max_v           = 0.0;
                        int    best_prev_state = 0;

                        int id_tag2 = tag_set[s2];

                        double b = 0.0;

                        Dictionary <int, double> bx;
                        if (PB.TryGetValue(id_tag2, out bx))
                        {
                            bx.TryGetValue(suffices[t], out b);
                        }

                        for (int s1 = 0; s1 < Nstate; ++s1) // состояния на шаге t-1
                        {
                            int id_tag1 = tag_set[s1];

                            double vt = V[t - 1, s1] * PA[id_tag1, id_tag2] * b;

                            if (vt > max_v)
                            {
                                max_v           = vt;
                                best_prev_state = s1;
                            }
                        }

                        V[t, s2]           = max_v;
                        BACKPOINTER[t, s2] = best_prev_state;
                    }
                }

                // обратный ход по состояниям, указанным в BACKPOINTER.

                int best_state = tag_set.IndexOf(end_tag);

                for (int t = Nword - 1; t > 0; --t)
                {
                    int best_prev_state = BACKPOINTER[t, best_state];

                    int selected_tag = tag_set[best_prev_state];

                    // Делаем вариант распознавания, давший этот токен, первым в списке.
                    // ATT: грубые ошибки выбора тега не допускаем, то есть разрешаем только те теги, которые были
                    // получены при распознавании слова.
                    if (word2tags[t - 1].Contains(selected_tag))
                    {
                        selected_tags[t - 1] = selected_tag;
                    }
                    else
                    {
                        // ... грубая ошибка выбора тега.
                    }

                    best_state = best_prev_state;
                }


                // Теперь проверяем количество ошибок в выборе частей речи.
                for (int iword = 1; iword < tokens.Count - 1; ++iword)
                {
                    SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[iword];
                    int ekey1     = token.GetEntryID();
                    int id_class1 = gren.GetEntryClass(ekey1);

                    int tag = selected_tags[iword];
                    if (tag != -1)
                    {
                        TagMatcher m = tags[tags.GetIdByIndex(tag)];
                        if (!m.MatchPartOfSpeech(id_class1))
                        {
                            error_count_with_model++;
                        }
                    }
                }
            }
        }

        return;
    }
Esempio n. 16
0
    public bool ProcessSample(string line)
    {
        // Морфологический разбор
        using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY))
        {
            List <int> token2tags = new List <int>();

            List <int> suffices = new List <int>();

            int last_word_index = tokens.Count - 1;

            bool all_hit = true;
            for (int i = 0; i < tokens.Count; ++i)
            {
                SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[i];
                string word = token.GetWord().ToLower();

                int suffix_id = GetTokenSuffix(i, last_word_index, token);
                suffices.Add(suffix_id);

                int tt = tags.MatchTags(token, gren);
                if (tt == -1)
                {
                    all_hit = false;
                    break;
                }

                token2tags.Add(tags.GetIndexById(tt));
            }

            if (all_hit)
            {
                for (int i = 0; i < tokens.Count; ++i)
                {
                    int tt1 = token2tags[i];
                    T_counts[tt1]++;

                    //SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[i];
                    //string word = token.GetWord().ToLower();

                    int suffix_id = suffices[i];

                    Dictionary <int, int> word_freq;
                    if (B_counts.TryGetValue(tt1, out word_freq))
                    {
                        int freq0;
                        if (word_freq.TryGetValue(suffix_id, out freq0))
                        {
                            word_freq[suffix_id] = freq0 + 1;
                        }
                        else
                        {
                            word_freq.Add(suffix_id, 1);
                        }
                    }
                    else
                    {
                        word_freq = new Dictionary <int, int>();
                        word_freq.Add(suffix_id, 1);
                        B_counts.Add(tt1, word_freq);
                    }

                    if (i > 0)
                    {
                        int tt0 = token2tags[i - 1];
                        A_counts[tt0, tt1]++;
                    }
                }
            }
        }

        return(true);
    }
Esempio n. 17
0
    static void Main(string[] args)
    {
        string dictionary_path     = @"e:\MVoice\lem\bin-windows\dictionary.xml"; // путь к словарной базе
        string samples_path        = @"E:\MVoice\lem\Слова\rus\SENT5.plain.txt";  // путь к файлу со списком предложений (одно предложение на одной строке)
        int    NSAMPLE             = 20000;                                       // сколько предложений максимум обработать
        int    START_INDEX         = 0;                                           // порядковый номер первого обрабатываемого предложений в исходном файле
        int    MAXARGS             = 20;                                          // beam size
        bool   append_result       = false;                                       // если леммы надо добавлять к существующему файлу, а не формировать файл с нуля
        string save_path           = null;                                        // путь к файлу, куда будут записаны леммы
        int    source_format       = 0;                                           // 0 - token per line, 1 - sentence per line
        bool   output_lemmas       = true;                                        // в результат записывать леммы с приведением к нижнему регистру
        bool   output_suffix       = false;
        bool   output_words        = false;                                       // в результат записывать исходные слова с приведением к нижнему регистру
        int    suffix_len          = 0;
        int    min_sentence_length = 0;                                           // фильтр по минимальной длине предложений
        int    max_sentence_length = int.MaxValue;                                // фильтр по максимальной длине предложений
        bool   reject_unknown      = false;                                       // отбрасывать предложения с несловарными токенами
        bool   emit_eol            = false;                                       // добавлять в выходной файл токены <EOL> для маркировки конца предложения
        int    eol_count           = 0;                                           // кол-во вставляемых <EOL>, гарантированно перекрывающее размер окна в word2vec

        List <System.Text.RegularExpressions.Regex> rx_stop = new List <System.Text.RegularExpressions.Regex>();

        for (int i = 0; i < args.Length; ++i)
        {
            if (args[i] == "-dict")
            {
                ++i;
                dictionary_path = args[i];
            }
            else if (args[i] == "-samples")
            {
                ++i;
                samples_path = args[i];
            }
            else if (args[i] == "-source_format")
            {
                ++i;
                source_format = int.Parse(args[i]);
            }
            else if (args[i] == "-append")
            {
                // Добавлять в конец существующего файла
                append_result = true;
            }
            else if (args[i] == "-emit_eol")
            {
                ++i;
                eol_count = int.Parse(args[i]);
                if (eol_count > 0)
                {
                    emit_eol = true;
                }
            }
            else if (args[i] == "-result")
            {
                // Способ обработки токенов:
                // lemma  => лемматизация
                // suffix => усечение до псевдосуффикса длиной -suffix_len
                // raw    => исходные слова
                ++i;
                output_lemmas = false;
                output_suffix = false;
                output_words  = false;

                if (args[i] == "suffix")
                {
                    output_suffix = true;
                }
                else if (args[i] == "lemma")
                {
                    output_lemmas = true;
                }
                else if (args[i] == "raw")
                {
                    output_words = true;
                }
                else
                {
                    throw new ApplicationException(string.Format("Unknown result format: {0}", args[i]));
                }
            }
            else if (args[i] == "-save")
            {
                // Путь к файлу, куда будут записываться результаты обработки
                ++i;
                save_path = args[i];
            }
            else if (args[i] == "-nsample")
            {
                // кол-во обрабатываемых предложений, начиная с -start_index
                ++i;
                NSAMPLE = int.Parse(args[i]);
            }
            else if (args[i] == "-min_sent_len")
            {
                // Обрабатывать только предложения, содержащие не менее NNN токенов
                ++i;
                min_sentence_length = int.Parse(args[i]);
            }
            else if (args[i] == "-max_sent_len")
            {
                // Обрабатывать только предложения, содержащие не более NNN токенов
                ++i;
                max_sentence_length = int.Parse(args[i]);
            }
            else if (args[i] == "-suffix_len")
            {
                ++i;
                suffix_len = int.Parse(args[i]);
            }
            else if (args[i] == "-start_index")
            {
                // Начинать обработку с предложения с указанным индексом
                ++i;
                START_INDEX = int.Parse(args[i]);
            }
            else if (args[i] == "-reject_unknown")
            {
                reject_unknown = true;
            }
            else if (args[i] == "-rx_stop")
            {
                ++i;
                using (System.IO.StreamReader rdr = new System.IO.StreamReader(args[i]))
                {
                    while (!rdr.EndOfStream)
                    {
                        string line = rdr.ReadLine();
                        if (line == null)
                        {
                            break;
                        }

                        line = line.Trim();
                        if (line.Length > 0)
                        {
                            rx_stop.Add(new System.Text.RegularExpressions.Regex(line));
                        }
                    }
                }
            }
            else
            {
                throw new ApplicationException(string.Format("Unknown option {0}", args[i]));
            }
        }


        Samples sources = null;

        if (source_format == 1)
        {
            sources = new Samples1(samples_path);
        }
        else
        {
            sources = new Samples2(samples_path);
        }

        sources.SetMinSentenceLen(min_sentence_length);
        sources.SetMaxSentenceLen(max_sentence_length);

        if (output_suffix || output_words)
        {
            sources.SetTokenDelimiter('|');
        }

        SolarixGrammarEngineNET.GrammarEngine2 gren = null;
        gren = new SolarixGrammarEngineNET.GrammarEngine2();

        if (output_lemmas)
        {
            gren.Load(dictionary_path, true);
        }

        int counter     = -1;
        int n_processed = 1;
        int MAX_COUNT   = NSAMPLE;

        int LanguageID  = SolarixGrammarEngineNET.GrammarEngineAPI.RUSSIAN_LANGUAGE;
        int Constraints = 120000 | (MAXARGS << 22); // 2 мин и 20 альтернатив

        SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags Flags = SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_MODEL_ONLY |
                                                                      SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_MODEL;

        // сколько всего предложений
        Console.WriteLine("Counting lines in source file {0}...", samples_path);
        int n_total_lines = sources.TotalCount();

        Console.WriteLine("Total number of lines={0}", n_total_lines.ToString("N0", new System.Globalization.CultureInfo("en-US")));

        System.IO.StreamWriter wrt = new System.IO.StreamWriter(save_path, append_result, new UTF8Encoding(false));

        sources.Start();
        while (true)
        {
            string sample = sources.Next();
            if (sample == null)
            {
                break;
            }

            sample = sample.Trim();

            counter++;

            if (counter < START_INDEX)
            {
                continue;
            }

            if (n_processed >= MAX_COUNT)
            {
                break;
            }

            bool contains_insane_chars = false;
            foreach (char c in sample)
            {
                if (c < 32)
                {
                    contains_insane_chars = true;
                    break;
                }
            }

            if (contains_insane_chars)
            {
                System.Text.StringBuilder b = new StringBuilder(sample.Length);
                foreach (char c in sample)
                {
                    if (c >= 32)
                    {
                        b.Append(c);
                    }
                }

                sample = b.ToString();
            }

            n_processed++;

            if (sample.Length == 0)
            {
                continue;
            }


            if (rx_stop.Count > 0)
            {
                bool reject_this_sample = false;
                foreach (var rx in rx_stop)
                {
                    if (rx.Match(sample).Success)
                    {
                        reject_this_sample = true;
                        break;
                    }
                }

                if (reject_this_sample)
                {
                    continue;
                }
            }

            if (output_lemmas)
            {
                using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(sample, LanguageID, Flags, Constraints))
                {
                    for (int i = 1; i < tokens.Count - 1; ++i)
                    {
                        if (char.IsPunctuation(tokens[i].GetWord()[0]))
                        {
                            continue;
                        }

                        int    id_entry = tokens[i].GetEntryID();
                        string lemma    = gren.GetEntryName(id_entry);
                        if (lemma == "???" || lemma.Equals("UNKNOWNENTRY", StringComparison.InvariantCultureIgnoreCase) || lemma.Equals("number_", StringComparison.InvariantCultureIgnoreCase))
                        {
                            lemma = tokens[i].GetWord();
                        }

                        lemma = lemma.ToLower();
                        wrt.Write(" {0}", lemma);
                    }
                }
            }
            else if (output_words)
            {
                string[] tokens = sample.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

                foreach (string token in tokens)
                {
                    if (token.Length >= 1 && char.IsPunctuation(token[0]))
                    {
                        continue;
                    }

                    string norma = token.ToLower();
                    wrt.Write(" {0}", norma);
                }
            }
            else if (output_suffix)
            {
                string[] tokens = sample.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

                foreach (string token in tokens)
                {
                    if (token.Length == 0 || (token.Length == 1 && char.IsPunctuation(token[0])))
                    {
                        continue;
                    }

                    string suffix = token;


                    int num;
                    if (int.TryParse(token, out num))
                    {
                        suffix = token.Substring(token.Length - 1);
                    }
                    else if (token.Length > suffix_len + 1)
                    {
                        suffix = "~" + token.Substring(token.Length - suffix_len);
                    }

                    wrt.Write(" {0}", suffix.ToLower());
                }
            }

            if (emit_eol)
            {
                for (int k = 0; k < eol_count; ++k)
                {
                    wrt.Write(" <EOL>");
                }
            }

            Console.WriteLine("[{1}/{2}] {0}", sample, counter, n_total_lines);

            wrt.Flush();
        }

        wrt.Close();

        return;
    }
Esempio n. 18
0
    /*
     * public void Check( string line )
     * {
     * // Морфологический разбор
     * using( SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology( line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.SOL_GREN_COMPLETE_ONLY ) )
     * {
     * // Токенизация без использования синтаксических правил
     * using( SolarixGrammarEngineNET.AnalysisResults projs = gren.AnalyzeMorphology( line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.SOL_GREN_TOKENIZE_ONLY ) )
     * {
     *  List<List<int>> word2tags = new List<List<int>>();
     *
     *  if( projs.Count != tokens.Count )
     *   return;
     *
     *  total_word_count += projs.Count - 2;
     *
     *  // Для каждого слова получим списки альтернативных лемматизаций.
     *  List<List<string>> word2lemmas = new List<List<string>>();
     *
     *  List<string> lemmas = new List<string>();
     *
     *  int last_word_index = projs.Count - 1;
     *
     *  for( int iword = 0; iword < projs.Count; ++iword )
     *  {
     *   if( iword == 0 || iword == last_word_index )
     *   {
     *    List<string> w2l = new List<string>();
     *    w2l.Add( string.Empty );
     *    word2lemmas.Add( w2l );
     *   }
     *   else
     *   {
     *    List<string> word_lemmas = new List<string>();
     *    for( int iproj = 0; iproj < projs[iword].VersionCount(); ++iproj )
     *    {
     *     string lemma = string.Empty;
     *     int ekey = projs[iword].GetVersionEntryID( iproj );
     *     string ename = gren.GetEntryName( ekey );
     *     if( IsUnknownLexem( ename ) )
     *      lemma = projs[iword].GetWord().ToLower();
     *     else
     *      lemma = ename.ToLower();
     *
     *     if( !word_lemmas.Contains( lemma ) )
     *      word_lemmas.Add( lemma );
     *    }
     *
     *    word2lemmas.Add( word_lemmas );
     *   }
     *
     *   lemmas.Add( word2lemmas[iword][0] );
     *  }
     *
     *
     *  for( int iword = 1; iword < projs.Count - 1; ++iword )
     *  {
     *   string suffix1 = GetTokenSuffix( iword - 1, last_word_index, projs[iword - 1] );
     *   int id_suffix1 = MatchSuffix( suffix1, false );
     *   if( id_suffix1 == -1 )
     *    continue;
     *
     *   string suffix2 = GetTokenSuffix( iword, last_word_index, projs[iword] );
     *   int id_suffix2 = MatchSuffix( suffix2, false );
     *   if( id_suffix2 == -1 )
     *    continue;
     *
     *   string suffix3 = GetTokenSuffix( iword + 1, last_word_index, projs[iword + 1] );
     *   int id_suffix3 = MatchSuffix( suffix3, false );
     *   if( id_suffix3 == -1 )
     *    continue;
     *
     *   string label1 = TagLabel( -1, id_suffix1 );
     *   string label2 = TagLabel( 0, id_suffix2 );
     *   string label3 = TagLabel( 1, id_suffix3 );
     *
     *
     *   System.Collections.ArrayList context = new System.Collections.ArrayList();
     *   context.Add( label1 );
     *   context.Add( label2 );
     *   context.Add( label3 );
     *
     *   double[] probabilities = mModel.Evaluate( (string[])context.ToArray( typeof( string ) ) );
     *
     *   // теперь надо выбрать самый достоверный вариант.
     *   double best_score = 0;
     *
     *   // теперь перебираем проекции и смотрим, которая из них имеет в нормальной форме выбранный суффикс.
     *   for( int iproj = 0; iproj < word2lemmas[iword].Count; ++iproj )
     *   {
     *    string ename = word2lemmas[iword][iproj];
     *    string proj_suffix = GetSuffix( ename.ToLower() );
     *    int id_suffix = MatchSuffix( proj_suffix, false );
     *    if( id_suffix == -1 )
     *     continue;
     *
     *    string res_label = ResultLabel( id_suffix );
     *
     *    if( !result_label2id.ContainsKey( res_label ) )
     *     continue;
     *
     *    int res_label_index = result_label2id[res_label];
     *
     *    double p = probabilities[res_label_index];
     *
     *    if( p > best_score )
     *    {
     *     best_score = p;
     *     lemmas[iword] = ename.ToLower();
     *    }
     *   }
     *  }
     *
     *
     *  // Теперь сравниваем леммы c правильными значениями.
     *  for( int iword = 1; iword < tokens.Count - 1; ++iword )
     *  {
     *   string mustbe = string.Empty;
     *
     *   int ekey = tokens[iword].GetEntryID();
     *   string ename = gren.GetEntryName( ekey );
     *
     *   if( IsUnknownLexem( ename ) ) // не будем учитывать ошибки лемматизации для не-словарных лексем.
     *    continue;
     *
     *   mustbe = ename.ToLower();
     *
     *   if( mustbe != lemmas[iword] )
     *    error_count_with_ngram++;
     *
     *   string lemma0 = string.Empty;
     *   int ekey0 = projs[iword].GetEntryID();
     *   string ename0 = gren.GetEntryName( ekey0 );
     *   if( IsUnknownLexem( ename0 ) )
     *    continue;
     *
     *   lemma0 = ename0.ToLower();
     *
     *   if( mustbe != lemma0 )
     *    error_count_no_filter++;
     *  }
     * }
     * }
     *
     * return;
     * }
     */

    public void Check(string line)
    {
        // Морфологический разбор
        using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY))
        {
            total_word_count += tokens.Count - 2;

            System.Text.StringBuilder b = new System.Text.StringBuilder();
            b.Capacity = 100;

            // Для каждого слова получим списки альтернативных лемматизаций.
            List <List <string> > word2lemmas = new List <List <string> >();

            List <string> lemmas         = new List <string>();
            List <int>    model_lemma_id = new List <int>();

            int last_word_index = tokens.Count - 1;

            for (int iword = 0; iword < tokens.Count; ++iword)
            {
                if (iword == 0 || iword == last_word_index)
                {
                    List <string> w2l = new List <string>();
                    w2l.Add(string.Empty);
                    word2lemmas.Add(w2l);
                }
                else
                {
                    List <string> word_lemmas = new List <string>();

                    string        word    = tokens[iword].GetWord();
                    System.IntPtr hLemmas = SolarixLemmatizatorEngineNET.LemmatizatorEngine.sol_GetLemmasW(lemm_engine, word);
                    if (hLemmas == System.IntPtr.Zero)
                    {
                        throw new System.ApplicationException();
                    }

                    int nlemma = SolarixLemmatizatorEngineNET.LemmatizatorEngine.sol_CountLemmas(hLemmas);
                    for (int i = 0; i < nlemma; ++i)
                    {
                        b.Length = 0;
                        SolarixLemmatizatorEngineNET.LemmatizatorEngine.sol_GetLemmaStringW(hLemmas, i, b, b.Capacity);

                        string lemma = b.ToString().ToLower();

                        if (!word_lemmas.Contains(lemma))
                        {
                            word_lemmas.Add(lemma);
                        }
                    }
                    SolarixLemmatizatorEngineNET.LemmatizatorEngine.sol_DeleteLemmas(hLemmas);

                    word2lemmas.Add(word_lemmas);
                }

                lemmas.Add(word2lemmas[iword][0]);
                model_lemma_id.Add(0);
            }

            for (int iword = 1; iword < tokens.Count - 1; ++iword)
            {
                string suffix1    = GetTokenSuffix(iword - 1, last_word_index, tokens[iword - 1]);
                int    id_suffix1 = MatchSuffix(suffix1, false);
                if (id_suffix1 == -1)
                {
                    continue;
                }

                string suffix2    = GetTokenSuffix(iword, last_word_index, tokens[iword]);
                int    id_suffix2 = MatchSuffix(suffix2, false);
                if (id_suffix2 == -1)
                {
                    continue;
                }

                string suffix3    = GetTokenSuffix(iword + 1, last_word_index, tokens[iword + 1]);
                int    id_suffix3 = MatchSuffix(suffix3, false);
                if (id_suffix3 == -1)
                {
                    continue;
                }

                string label1 = TagLabel(-1, id_suffix1);
                string label2 = TagLabel(0, id_suffix2);
                string label3 = TagLabel(1, id_suffix3);


                System.Collections.ArrayList context = new System.Collections.ArrayList();
                context.Add(label1);
                context.Add(label2);
                context.Add(label3);

                double[] probabilities = mModel.Evaluate((string[])context.ToArray(typeof(string)));

                // теперь надо выбрать самый достоверный вариант.
                double best_score = 0;

                // теперь перебираем проекции и смотрим, которая из них имеет в нормальной форме выбранный суффикс.
                for (int iproj = 0; iproj < word2lemmas[iword].Count; ++iproj)
                {
                    string ename       = word2lemmas[iword][iproj];
                    string proj_suffix = GetSuffix(ename.ToLower());
                    int    id_suffix   = MatchSuffix(proj_suffix, false);
                    if (id_suffix == -1)
                    {
                        continue;
                    }

                    string res_label = ResultLabel(id_suffix);

                    if (!result_label2id.ContainsKey(res_label))
                    {
                        continue;
                    }

                    int res_label_index = result_label2id[res_label];

                    double p = probabilities[res_label_index];

                    if (p > best_score)
                    {
                        best_score            = p;
                        model_lemma_id[iword] = id_suffix;
                        lemmas[iword]         = ename.ToLower();
                    }
                }
            }


            // Теперь сравниваем леммы c правильными значениями.
            for (int iword = 1; iword < tokens.Count - 1; ++iword)
            {
                string mustbe = string.Empty;

                int    ekey  = tokens[iword].GetEntryID();
                string ename = gren.GetEntryName(ekey);

                if (IsUnknownLexem(ename)) // не будем учитывать ошибки лемматизации для не-словарных лексем.
                {
                    continue;
                }

                mustbe = ename.ToLower();

                // отдельно считаем все ошибки модели, так как часть из них могут быть
                // скрыты при выборе леммы в случаях, когда есть только один правильный вариант леммы, и он не совпадает с выбором модели.
                string mustbe_suffix    = GetSuffix(mustbe);
                int    mustbe_id_suffix = MatchSuffix(mustbe_suffix, false);
                if (mustbe_id_suffix != model_lemma_id[iword])
                {
                    raw_model_error_count++;
                }

                if (mustbe != lemmas[iword])
                {
                    error_count_with_ngram++;
                }

                string lemma0 = word2lemmas[iword][0].ToLower();

                if (mustbe != lemma0)
                {
                    error_count_no_filter++;
                }
            }
        }

        return;
    }
Esempio n. 19
0
 public string NormalizePhrase(AnalysisResults linkages)
 {
     return(SolarixGrammarEngineNET.GrammarEngine.NormalizePhraseFX(_hEngine, linkages.GetHandle()));
 }
Esempio n. 20
0
 public AnalysisResults AnalyzeMorphology( string phrase, int id_language )
 {
  IntPtr hPack = GrammarEngine.sol_MorphologyAnalysis( _hEngine, phrase, 0, 0, 0, id_language );
  AnalysisResults res = new AnalysisResults( this, hPack );
  return res;
 }
Esempio n. 21
0
 public AnalysisResults AnalyzeSyntax( string _phrase, int id_language )
 {
  IntPtr hPack = GrammarEngine.sol_SyntaxAnalysis( _hEngine, _phrase, 0, 0, 60000, id_language );
  AnalysisResults res = new AnalysisResults( this, hPack );
  return res;
 }
    public void Check(
        string line,
        ref int total_word_count,
        ref int error_count_no_filter,
        ref int error_count_with_model
        )
    {
        // Морфологический разбор
        using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY))
        {
            // Токенизация без использования синтаксических правил
            using (SolarixGrammarEngineNET.AnalysisResults projs = gren.AnalyzeMorphology(line, LanguageID,
                                                                                          SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_TOKENIZE_ONLY /*| SolarixGrammarEngineNET.GrammarEngine.SOL_GREN_DISABLE_FILTERS*/))
            {
                if (tokens.Count != projs.Count)
                {
                    return;
                }


                int last_word_index = projs.Count - 1;

                // -----------------------------------------
                // Посчитаем ошибки до применения модели
                // -----------------------------------------
                int n_err = 0;
                for (int iword = 1; iword < last_word_index; ++iword)
                {
                    SolarixGrammarEngineNET.SyntaxTreeNode proj = projs[iword];
                    int ekey0     = proj.GetEntryID();
                    int id_class0 = gren.GetEntryClass(ekey0);

                    // Совпадает с точным значением?
                    SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[iword];
                    int ekey1     = token.GetEntryID();
                    int id_class1 = gren.GetEntryClass(ekey1);

                    if (id_class0 != id_class1)
                    {
                        n_err++;
                    }
                }

                error_count_no_filter += n_err;
                total_word_count      += (tokens.Count - 2);



                List <int> n_pos     = new List <int>(); // кол-во разных частей речи для каждого токена
                List <int> word2tags = new List <int>();

                // Преобразуем все проекции каждого слова в варианты распознавания тегов
                for (int i = 0; i < tokens.Count; ++i)
                {
                    SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[i];
                    int index = GetTokenSuffix(i, last_word_index, token);

                    word2tags.Add(index);

                    // На сколько разных частей речи проецируется данное слово
                    List <int> pos_list = new List <int>();
                    for (int k = 0; k < projs[i].VersionCount(); ++k)
                    {
                        int ekey0     = projs[i].GetVersionEntryID(k);
                        int id_class0 = gren.GetEntryClass(ekey0);
                        if (!pos_list.Contains(id_class0))
                        {
                            pos_list.Add(id_class0);
                        }
                    }

                    n_pos.Add(pos_list.Count);
                }


                List <Dictionary <int, int> > pos_score = new List <Dictionary <int, int> >();
                List <int> pos_score_order = new List <int>();

                // Инициализируем вектор частей речи значениями, которые соответствуют
                // чамым частотным словоформам.
                for (int iword = 0; iword < tokens.Count - 1; ++iword)
                {
                    SolarixGrammarEngineNET.SyntaxTreeNode proj = projs[iword];

                    Dictionary <int, int> p = new Dictionary <int, int>();

                    for (int iproj = 0; iproj < proj.VersionCount(); ++iproj)
                    {
                        int ekey     = proj.GetVersionEntryID(iproj);
                        int id_class = gren.GetEntryClass(ekey);

                        if (!p.ContainsKey(id_class))
                        {
                            if (iproj == 0)
                            {
                                p.Add(id_class, 1);
                            }
                            else
                            {
                                p.Add(id_class, 0);
                            }
                        }
                    }

                    pos_score.Add(p);
                    pos_score_order.Add(1);
                }


                // ---------------------------------
                // теперь применим модель
                // ---------------------------------
                bool use_4grams = true;
                bool use_3grams = true;
                bool use_2grams = true;

                for (int iword = 1; iword < tokens.Count - 1; ++iword)
                {
                    string word = tokens[iword].GetWord();

                    bool applied = false;

                    // ==============
                    // ТЕТРАГРАММЫ
                    // ==============

                    if (use_4grams && !applied && iword > 2)
                    {
                        if (n_pos[iword] > 1) // Выбираем POS для iword на основе iword-3,iword-2,iword-1
                        {
                            int tag0 = word2tags[iword - 3];
                            int tag1 = word2tags[iword - 2];
                            int tag2 = word2tags[iword - 1];

                            List <NGram4> n4_list;
                            Int3          k = new Int3(tag0, tag1, tag2);

                            if (tag0_2_ngram4.TryGetValue(k, out n4_list))
                            {
                                // Перебираем варианты, которые вытекают из наличия тегов tag0,tag1,tag2 и прибавляем очки соответствующим частям речи.
                                foreach (NGram4 n4_probe in n4_list)
                                {
                                    int        tag3 = n4_probe.tags3;
                                    TagMatcher m    = selectors[tag3];

                                    List <KeyValuePair <int, int> > changes = new List <KeyValuePair <int, int> >();

                                    Dictionary <int, int> pos2score = pos_score[iword];

                                    foreach (KeyValuePair <int, int> p in pos2score)
                                    {
                                        if (m.MatchPartOfSpeech(p.Key))
                                        {
                                            int m_freq = ngrams4[n4_probe];
                                            changes.Add(new KeyValuePair <int, int>(p.Key, m_freq));
                                            applied = true;
                                        }
                                    }

                                    foreach (var kv in changes)
                                    {
                                        pos2score[kv.Key] = pos2score[kv.Key] + kv.Value;
                                    }

                                    pos_score_order[iword] = 4;
                                }
                            }
                        }
                        else if (n_pos[iword - 1] > 1 && pos_score_order[iword - 1] < 4) // Выбираем POS для iword-1 на основе iword-3,iword-2,iword
                        {
                            int tag0 = word2tags[iword - 3];
                            int tag1 = word2tags[iword - 2];
                            int tag3 = word2tags[iword];

                            List <NGram4> n4_list;
                            Int3          k = new Int3(tag0, tag1, tag3);

                            if (tag1_2_ngram4.TryGetValue(k, out n4_list))
                            {
                                // Перебираем варианты, которые вытекают из наличия тегов tag0,tag1,tag2 и прибавляем очки соответствующим частям речи.
                                foreach (NGram4 n4_probe in n4_list)
                                {
                                    int        tag2 = n4_probe.tags2;
                                    TagMatcher m    = selectors[tag2];

                                    List <KeyValuePair <int, int> > changes = new List <KeyValuePair <int, int> >();

                                    Dictionary <int, int> pos2score = pos_score[iword];

                                    foreach (KeyValuePair <int, int> p in pos2score)
                                    {
                                        if (m.MatchPartOfSpeech(p.Key))
                                        {
                                            int m_freq = ngrams4_1[n4_probe];
                                            changes.Add(new KeyValuePair <int, int>(p.Key, m_freq));
                                            applied = true;
                                        }
                                    }

                                    foreach (var kv in changes)
                                    {
                                        pos2score[kv.Key] = pos2score[kv.Key] + kv.Value;
                                    }

                                    pos_score_order[iword - 1] = 4;
                                }
                            }
                        }
                    }



                    // ==============
                    // ТРИГРАММЫ
                    // ==============

                    if (use_3grams && !applied && iword > 1)
                    {
                        if (n_pos[iword] > 1) // Выбираем POS для iword на основе iword-2,iword-1
                        {
                            {
                                int tag0 = word2tags[iword - 2];
                                int tag1 = word2tags[iword - 1];

                                List <NGram3> n3_list;
                                Int2          k = new Int2(tag0, tag1);

                                if (tag0_2_ngram3.TryGetValue(k, out n3_list))
                                {
                                    // Перебираем варианты, которые вытекают из наличия тегов tag0,tag1, и прибавляем очки соответствующим частям речи.
                                    foreach (NGram3 n3_probe in n3_list)
                                    {
                                        int        tag2 = n3_probe.tags2;
                                        TagMatcher m    = selectors[tag2];

                                        List <KeyValuePair <int, int> > changes = new List <KeyValuePair <int, int> >();

                                        Dictionary <int, int> pos2score = pos_score[iword];

                                        foreach (KeyValuePair <int, int> p in pos2score)
                                        {
                                            if (m.MatchPartOfSpeech(p.Key))
                                            {
                                                int m_freq = ngrams3[n3_probe];
                                                changes.Add(new KeyValuePair <int, int>(p.Key, m_freq));
                                                applied = true;
                                            }
                                        }

                                        foreach (var kv in changes)
                                        {
                                            pos2score[kv.Key] = pos2score[kv.Key] + kv.Value;
                                        }
                                    }
                                }
                            }


                            if (iword < last_word_index)
                            {
                                // iword-1 --> iword <-- iword+1

                                int tag0 = word2tags[iword - 1];
                                int tag2 = word2tags[iword + 1];

                                List <NGram3> n3_list;
                                Int2          k = new Int2(tag0, tag2);

                                if (tag1_2_ngram3.TryGetValue(k, out n3_list))
                                {
                                    // Перебираем варианты, которые вытекают из наличия тегов tag0,tag2, и прибавляем очки соответствующим частям речи.
                                    foreach (NGram3 n3_probe in n3_list)
                                    {
                                        int        tag1 = n3_probe.tags1;
                                        TagMatcher m    = selectors[tag1];

                                        List <KeyValuePair <int, int> > changes = new List <KeyValuePair <int, int> >();

                                        Dictionary <int, int> pos2score = pos_score[iword];

                                        foreach (KeyValuePair <int, int> p in pos2score)
                                        {
                                            if (m.MatchPartOfSpeech(p.Key))
                                            {
                                                int m_freq = ngrams3_1[n3_probe];
                                                changes.Add(new KeyValuePair <int, int>(p.Key, m_freq));
                                                applied = true;
                                            }
                                        }

                                        foreach (var kv in changes)
                                        {
                                            pos2score[kv.Key] = pos2score[kv.Key] + kv.Value;
                                        }

                                        pos_score_order[iword] = 3;
                                    }
                                }
                            }
                        }
                        else if (n_pos[iword - 1] > 1 && pos_score_order[iword - 1] < 3) // Выбираем POS для iword-1 на основе iword-2,iword
                        {
                            int tag0 = word2tags[iword - 2];
                            int tag2 = word2tags[iword];

                            List <NGram3> n3_list;
                            Int2          k = new Int2(tag0, tag2);

                            if (tag1_2_ngram3.TryGetValue(k, out n3_list))
                            {
                                // Перебираем варианты, которые вытекают из наличия тегов tag0,tag2, и прибавляем очки соответствующим частям речи.
                                foreach (NGram3 n3_probe in n3_list)
                                {
                                    int        tag1 = n3_probe.tags1;
                                    TagMatcher m    = selectors[tag1];

                                    List <KeyValuePair <int, int> > changes = new List <KeyValuePair <int, int> >();

                                    Dictionary <int, int> pos2score = pos_score[iword];

                                    foreach (KeyValuePair <int, int> p in pos2score)
                                    {
                                        if (m.MatchPartOfSpeech(p.Key))
                                        {
                                            int m_freq = ngrams3_1[n3_probe];
                                            changes.Add(new KeyValuePair <int, int>(p.Key, m_freq));
                                            applied = true;
                                        }
                                    }

                                    foreach (var kv in changes)
                                    {
                                        pos2score[kv.Key] = pos2score[kv.Key] + kv.Value;
                                    }

                                    pos_score_order[iword] = 3;
                                }
                            }
                        }
                    }


                    // ==============
                    // ДИГРАММЫ
                    // ==============

                    if (use_2grams && !applied && iword > 1)
                    {
                        if (n_pos[iword] > 1) // Выбираем POS для iword на основе iword-1
                        {
                            {
                                int tag0 = word2tags[iword - 1];

                                List <NGram2> n2_list;
                                if (tag0_2_ngram2.TryGetValue(tag0, out n2_list))
                                {
                                    // Перебираем варианты, которые вытекают из наличия тега tag0, и прибавляем очки соответствующим частям речи.
                                    foreach (NGram2 n2_probe in n2_list)
                                    {
                                        int        tag1 = n2_probe.tags1;
                                        TagMatcher m    = selectors[tag1];

                                        List <KeyValuePair <int, int> > changes = new List <KeyValuePair <int, int> >();

                                        Dictionary <int, int> pos2score = pos_score[iword];

                                        foreach (KeyValuePair <int, int> p in pos2score)
                                        {
                                            if (m.MatchPartOfSpeech(p.Key))
                                            {
                                                int m_freq = ngrams2[n2_probe];
                                                changes.Add(new KeyValuePair <int, int>(p.Key, m_freq));
                                                applied = true;
                                            }
                                        }

                                        foreach (var kv in changes)
                                        {
                                            pos2score[kv.Key] = pos2score[kv.Key] + kv.Value;
                                        }

                                        pos_score_order[iword] = 2;
                                    }
                                }
                            }

                            if (iword < last_word_index)
                            {
                                // iword <-- iword+1
                                int tag1 = word2tags[iword + 1];

                                List <NGram2> n2_list;
                                if (tag1_2_ngram2.TryGetValue(tag1, out n2_list))
                                {
                                    // Перебираем варианты, которые вытекают из наличия тега tag1, и прибавляем очки соответствующим частям речи.
                                    foreach (NGram2 n2_probe in n2_list)
                                    {
                                        int        tag0 = n2_probe.tags0;
                                        TagMatcher m    = selectors[tag0];

                                        List <KeyValuePair <int, int> > changes = new List <KeyValuePair <int, int> >();

                                        Dictionary <int, int> pos2score = pos_score[iword];

                                        foreach (KeyValuePair <int, int> p in pos2score)
                                        {
                                            if (m.MatchPartOfSpeech(p.Key))
                                            {
                                                int m_freq = ngrams2_1[n2_probe];
                                                changes.Add(new KeyValuePair <int, int>(p.Key, m_freq));
                                                applied = true;
                                            }
                                        }

                                        foreach (var kv in changes)
                                        {
                                            pos2score[kv.Key] = pos2score[kv.Key] + kv.Value;
                                        }

                                        pos_score_order[iword] = 2;
                                    }
                                }
                            }
                        }
                        else if (n_pos[iword - 1] > 1 && pos_score_order[iword - 1] == 1) // Выбираем POS для iword-1 на основе iword
                        {
                            int tag1 = word2tags[iword];

                            List <NGram2> n2_list;
                            if (tag1_2_ngram2.TryGetValue(tag1, out n2_list))
                            {
                                // Перебираем варианты, которые вытекают из наличия тега tag1, и прибавляем очки соответствующим частям речи.
                                foreach (NGram2 n2_probe in n2_list)
                                {
                                    int        tag0 = n2_probe.tags0;
                                    TagMatcher m    = selectors[tag0];

                                    List <KeyValuePair <int, int> > changes = new List <KeyValuePair <int, int> >();

                                    Dictionary <int, int> pos2score = pos_score[iword - 1];

                                    foreach (KeyValuePair <int, int> p in pos2score)
                                    {
                                        if (m.MatchPartOfSpeech(p.Key))
                                        {
                                            int m_freq = ngrams2_1[n2_probe];
                                            changes.Add(new KeyValuePair <int, int>(p.Key, m_freq));
                                            applied = true;
                                        }
                                    }

                                    foreach (var kv in changes)
                                    {
                                        pos2score[kv.Key] = pos2score[kv.Key] + kv.Value;
                                    }

                                    pos_score_order[iword - 1] = 2;
                                }
                            }
                        }
                    }
                }



                // Все вероятности перехода учтены.

                // Совпадает ли selected_id_class с требуемыми значениями?
                for (int iword = 1; iword < projs.Count - 1; ++iword)
                {
                    Dictionary <int, int> word_pos_scores = pos_score[iword];
                    int best_score = 0;
                    int best_pos   = -1;
                    foreach (KeyValuePair <int, int> k in word_pos_scores)
                    {
                        if (k.Value > best_score)
                        {
                            best_score = k.Value;
                            best_pos   = k.Key;
                        }
                    }

                    SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[iword];
                    int ekey1     = token.GetEntryID();
                    int id_class1 = gren.GetEntryClass(ekey1);

                    if (best_pos != id_class1)
                    {
                        error_count_with_model++;
                    }
                }
            }
        }


        return;
    }
    public void Collect(SolarixGrammarEngineNET.AnalysisResults tokens, SolarixGrammarEngineNET.AnalysisResults trees, SolarixGrammarEngineNET.GrammarEngine2 gren)
    {
        if (trees.Count == 3)
        {
            SolarixGrammarEngineNET.SyntaxTreeNode root = trees[1];
            int p_ekey   = root.GetEntryID();
            int id_class = gren.GetEntryClass(p_ekey);

            if (
                id_class == SolarixGrammarEngineNET.GrammarEngineAPI.IMPERSONAL_VERB_ru ||
                id_class == SolarixGrammarEngineNET.GrammarEngineAPI.VERB_ru ||
                id_class == SolarixGrammarEngineNET.GrammarEngineAPI.INFINITIVE_ru
                )
            {
                ok = true;
            }
        }

        if (ok)
        {
            int N = tokens.Count;

            labels = new List <List <string> >();
            for (int iroot = 0; iroot < N; ++iroot)
            {
                List <string> x = new List <string>();
                x.Add("O");
                labels.Add(x);
            }

            for (int iroot = 1; iroot < trees.Count - 1; ++iroot)
            {
                ProcessTree(trees[iroot], gren);
            }

            // -----------------------------------------------
            // Уточняем разметку для групп существительных
            // -----------------------------------------------
            for (int i = 1; i < N - 1; ++i)
            {
                List <string> l = labels[i];

                if (l[0].StartsWith("NP"))
                {
                    string NP = l[0];

                    // меняем метку у первого токена на B-NP
                    l.RemoveAt(0);
                    l.Insert(0, "B-NP");

                    // идем вправо до появления другой NP-метки.
                    for (int k = i + 1; k < N; ++k)
                    {
                        if (labels[k][0] == NP)
                        {
                            labels[k].RemoveAt(0);
                            labels[k].Insert(0, "I-NP");
                        }
                        else
                        {
                            // Удалим все появления NP-метки далее вправо.
                            for (int q = k; q < N; ++q)
                            {
                                labels[q].Remove(NP);
                            }

                            break;
                        }
                    }
                }
            }


            // Уточняем разметку для глагольных групп.
            for (int i = 1; i < N - 1; ++i)
            {
                List <string> l = labels[i];

                if (l[0].StartsWith("VX"))
                {
                    // Корневой глагол в сказуемом.
                    // Цепочка токенов в группе может быть разорвана из-за того, что наречный оборот, привязанный к сказуемому,
                    // стоит справа от глагольного дополнения. Поэтому проверим наличие таких разрывов.
                    l.RemoveAt(0); // под VX лежит VP, который мы сейчас поднимем
                    string VP = l[0];

                    int vp_begin = i;
                    // ищем разрыв слева
                    for (int k = i - 1; k >= 0; --k)
                    {
                        if (labels[k][0] != VP)
                        {
                            // слева - конец цепочки токенов для этого сказуемого. Удалим все более левые упоминания этого VP.
                            for ( ; k >= 0; --k)
                            {
                                labels[k].Remove(VP);
                            }

                            break;
                        }
                        else
                        {
                            vp_begin = k;
                        }
                    }

                    int vp_end = i;
                    // ищем разрыв справа
                    for (int k = i + 1; k < N; ++k)
                    {
                        if (labels[k][0] != VP)
                        {
                            // справа - конец цепочки токенов для этого сказуемого. Удалим все более правые упоминания этого VP.
                            for ( ; k < N; ++k)
                            {
                                labels[k].Remove(VP);
                            }
                            break;
                        }
                        else
                        {
                            vp_end = k;
                        }
                    }

                    // поставим отметку на первый VP-токен
                    labels[vp_begin].RemoveAt(0);
                    labels[vp_begin].Insert(0, "B-VP");

                    // а остальные пометим как I-VP
                    for (int j = vp_begin + 1; j <= vp_end; ++j)
                    {
                        labels[j].Remove(VP);
                        labels[j].Insert(0, "I-VP");
                    }
                }
            }


            for (int i = 0; i < labels.Count; ++i)
            {
                string   l = labels[i][0];
                string[] t = l.Split(':');
                labels[i].Clear();
                labels[i].Add(t[0]);
            }
        }

        return;
    }
 private bool IsBoundaryToken(SolarixGrammarEngineNET.AnalysisResults tokens, int index)
 {
     return(index == 0 || index == tokens.Count - 1);
 }
Esempio n. 25
0
    public bool ProcessSample2(string line)
    {
        // Морфологический разбор
        using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY))
        {
            List <int> token2tags = new List <int>();
            List <int> suffices   = new List <int>();

            int last_word_index = tokens.Count - 1;

            bool all_hit = true;
            for (int i = 0; i < tokens.Count; ++i)
            {
                SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[i];
                string word = token.GetWord().ToLower();

                int suffix_id = GetTokenSuffix(i, last_word_index, token);
                suffices.Add(suffix_id);

                int lemma_suffix_id = GetLemmaSuffix(i, last_word_index, token);
                token2tags.Add(lemma_suffix_id);
            }

            if (all_hit)
            {
                for (int i = 0; i < tokens.Count; ++i)
                {
                    int tt1 = token2tags[i];
                    T_counts[tt1]++;

                    //SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[i];
                    //string word = token.GetWord().ToLower();

                    int suffix_id = suffices[i];

                    // обновляем матрицу со счетчиками эмиссии.
                    Dictionary <int, int> word_freq;
                    if (B_counts.TryGetValue(tt1, out word_freq))
                    {
                        int freq0;
                        if (word_freq.TryGetValue(suffix_id, out freq0))
                        {
                            word_freq[suffix_id] = freq0 + 1;
                        }
                        else
                        {
                            word_freq.Add(suffix_id, 1);
                        }
                    }
                    else
                    {
                        word_freq = new Dictionary <int, int>();
                        word_freq.Add(suffix_id, 1);
                        B_counts.Add(tt1, word_freq);
                    }

                    if (i > 0)
                    {
                        // обновляем счетчики переходов между суффиксами лемм.
                        int tt0 = token2tags[i - 1];
                        A_counts[tt0, tt1]++;
                    }
                }
            }
        }

        return(true);
    }
    public bool ProcessSample(string line)
    {
        int occurence_count = 0;

        // Морфологический разбор
        using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY))
        {
            for (int i = 1; i < tokens.Count - 1; ++i)
            {
                SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[i];
                string word = token.GetWord().ToLower();

                if (retrieve_omonyms_from_samples)
                {
                    if (omonyms.Contains(word))
                    {
                        occurence_count++;
                        omonym_processors[word].ProcessSample(line, tokens, LanguageID, gren);
                    }
                    else if (!not_omonyms.Contains(word) && omonyms.Count < MaxOmonymPerSession)
                    {
                        bool is_omonym = false;

                        if (!ignore_omonyms.Contains(word))
                        {
                            // сделаем проекцию слова
                            int id_class0 = -1;
                            using (SolarixGrammarEngineNET.WordProjections projs = gren.FindWordForm(word))
                            {
                                for (int j = 0; j < projs.Count; ++j)
                                {
                                    int id_entry = projs.GetEntryKey(j);
                                    int id_class = gren.GetEntryClass(id_entry);
                                    if (id_class0 == -1)
                                    {
                                        id_class0 = id_class;
                                    }
                                    else if (id_class0 != id_class)
                                    {
                                        is_omonym = true;
                                        break;
                                    }
                                }
                            }

                            if (is_omonym)
                            {
                                omonyms.Add(word);
                                OmonymProcessor processor = new OmonymProcessor(word);
                                omonym_processors.Add(word, processor);

                                occurence_count++;
                                omonym_processors[word].ProcessSample(line, tokens, LanguageID, gren);
                            }
                            else
                            {
                                not_omonyms.Add(word);
                            }
                        }
                    }
                }
                else if (omonyms.Contains(word))
                {
                    occurence_count++;
                    omonym_processors[word].ProcessSample(line, tokens, LanguageID, gren);
                }
            }
        }

        return(occurence_count > 0);
    }
Esempio n. 27
0
 public string NormalizePhrase( AnalysisResults linkages )
 {
     return SolarixGrammarEngineNET.GrammarEngine.NormalizePhraseFX( _hEngine, linkages.GetHandle() );
 }
    public void Check(string line)
    {
        // Морфологический разбор
        using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY))
        {
            // Токенизация без использования синтаксических правил
            using (SolarixGrammarEngineNET.AnalysisResults projs = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_TOKENIZE_ONLY))
            {
                List <List <int> > word2tags = new List <List <int> >();

                if (projs.Count != tokens.Count)
                {
                    return;
                }

                total_word_count += projs.Count - 2;

                // Для каждого слова получим списки альтернативных лемматизаций.
                List <List <string> > word2lemmas      = new List <List <string> >();
                List <List <int> >    word2lemma_index = new List <List <int> >();

                List <string> lemmas = new List <string>();

                int last_word_index = projs.Count - 1;

                List <string> word_suffix = new List <string>();

                for (int iword = 0; iword < projs.Count; ++iword)
                {
                    string suffix = GetTokenSuffix(iword, last_word_index, tokens[iword]);
                    word_suffix.Add(suffix);
                }


                for (int iword = 0; iword < projs.Count; ++iword)
                {
                    if (iword == 0 || iword == last_word_index)
                    {
                        List <string> w2l = new List <string>();
                        w2l.Add(string.Empty);
                        word2lemmas.Add(w2l);

                        List <int> w2i = new List <int>();
                        w2i.Add(-1);
                        word2lemma_index.Add(w2i);
                    }
                    else
                    {
                        List <string> word_lemmas  = new List <string>();
                        List <int>    word_results = new List <int>();

                        for (int iproj = 0; iproj < projs[iword].VersionCount(); ++iproj)
                        {
                            string lemma = string.Empty;
                            int    ekey  = projs[iword].GetVersionEntryID(iproj);
                            string ename = gren.GetEntryName(ekey);
                            if (IsUnknownLexem(ename))
                            {
                                lemma = projs[iword].GetWord().ToLower();
                            }
                            else
                            {
                                lemma = ename.ToLower();
                            }

                            if (!word_lemmas.Contains(lemma))
                            {
                                word_lemmas.Add(lemma);

                                int result = MatchSuffix(GetSuffix(lemma), false);
                                word_results.Add(result);
                            }
                        }

                        word2lemmas.Add(word_lemmas);
                        word2lemma_index.Add(word_results);
                    }

                    lemmas.Add(word2lemmas[iword][0]);
                }


                for (int iword = 1; iword < projs.Count - 1; ++iword)
                {
                    List <double> P_lemma = new List <double>();
                    for (int k = 0; k < word2lemma_index[iword].Count; ++k)
                    {
                        if (k == 0)
                        {
                            P_lemma.Add(1.0);
                        }
                        else
                        {
                            P_lemma.Add(1.0);
                        }
                    }

                    // текущее слово
                    string word0      = projs[iword].GetWord().ToLower();
                    string suffix0    = word_suffix[iword];
                    int    id_suffix0 = MatchSuffix(suffix0, false);
                    if (id_suffix0 == -1)
                    {
                        continue;
                    }

                    string tag0 = TagLabel(0, id_suffix0);

                    int N_TOTAL0 = GetFeatureCount(tag0);

                    for (int k = 0; k < word2lemma_index[iword].Count; ++k)
                    {
                        int lemma_index = word2lemma_index[iword][k];
                        int N_LEMMA0    = GetFeature2ResultCount(tag0, lemma_index);

                        if (N_TOTAL0 > 0 && N_LEMMA0 > 0)
                        {
                            double p = ((double)N_LEMMA0) / ((double)N_TOTAL0);
                            P_lemma[k] *= p;
                        }
                    }

                    // предыдущее слово
                    if (iword > 0)
                    {
                        string word1      = projs[iword - 1].GetWord().ToLower();
                        string suffix1    = word_suffix[iword - 1];
                        int    id_suffix1 = MatchSuffix(suffix1, false);
                        if (id_suffix1 == -1)
                        {
                            continue;
                        }

                        string tag1 = TagLabel(-1, id_suffix1);

                        int N_TOTAL1 = GetFeatureCount(tag1);

                        for (int k = 0; k < word2lemma_index[iword].Count; ++k)
                        {
                            int lemma_index = word2lemma_index[iword][k];
                            int N_LEMMA1    = GetFeature2ResultCount(tag1, lemma_index);

                            if (N_TOTAL1 > 0 && N_LEMMA1 > 0)
                            {
                                double p = ((double)N_LEMMA1) / ((double)N_TOTAL1);
                                P_lemma[k] *= p;
                            }
                        }
                    }

                    // следующее слово
                    if (iword < projs.Count - 1)
                    {
                        string word2      = projs[iword + 1].GetWord().ToLower();
                        string suffix2    = word_suffix[iword + 1];
                        int    id_suffix2 = MatchSuffix(suffix2, false);
                        if (id_suffix2 == -1)
                        {
                            continue;
                        }

                        string tag2 = TagLabel(1, id_suffix2);

                        int N_TOTAL2 = GetFeatureCount(tag2);

                        for (int k = 0; k < word2lemma_index[iword].Count; ++k)
                        {
                            int lemma_index = word2lemma_index[iword][k];
                            int N_LEMMA2    = GetFeature2ResultCount(tag2, lemma_index);

                            if (N_TOTAL2 > 0 && N_LEMMA2 > 0)
                            {
                                double p = ((double)N_LEMMA2) / ((double)N_TOTAL2);
                                P_lemma[k] *= p;
                            }
                        }
                    }


                    // теперь надо выбрать самый достоверный вариант.
                    double best_P = 0;

                    for (int iproj = 0; iproj < word2lemmas[iword].Count; ++iproj)
                    {
                        double p = P_lemma[iproj];

                        if (p > best_P)
                        {
                            best_P        = p;
                            lemmas[iword] = word2lemmas[iword][iproj];
                        }
                    }
                }


                // Теперь сравниваем леммы c правильными значениями.
                for (int iword = 1; iword < tokens.Count - 1; ++iword)
                {
                    string mustbe = string.Empty;

                    int    ekey  = tokens[iword].GetEntryID();
                    string ename = gren.GetEntryName(ekey);

                    if (IsUnknownLexem(ename)) // не будем учитывать ошибки лемматизации для не-словарных лексем.
                    {
                        continue;
                    }

                    mustbe = ename.ToLower();

                    if (mustbe != lemmas[iword])
                    {
                        error_count_with_ngram++;
                    }

                    string lemma0 = string.Empty;
                    int    ekey0  = projs[iword].GetEntryID();
                    string ename0 = gren.GetEntryName(ekey0);
                    if (IsUnknownLexem(ename0))
                    {
                        continue;
                    }

                    lemma0 = ename0.ToLower();

                    if (mustbe != lemma0)
                    {
                        error_count_no_filter++;
                    }
                }
            }
        }

        return;
    }
    public void Check(string line)
    {
        // Морфологический разбор
        using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY))
        {
            // Токенизация без использования синтаксических правил
            using (SolarixGrammarEngineNET.AnalysisResults projs = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_TOKENIZE_ONLY))
            {
                List <List <int> > word2tags = new List <List <int> >();

                if (projs.Count != tokens.Count)
                {
                    return;
                }

                total_word_count += projs.Count - 2;

                // Для каждого слова получим списки альтернативных лемматизаций.
                List <List <string> > word2lemmas   = new List <List <string> >();
                List <List <int> >    word2lemma_id = new List <List <int> >();

                List <string> lemmas = new List <string>();

                int last_word_index = projs.Count - 1;


                List <List <double> > viterbi_P           = new List <List <double> >();
                List <List <int> >    viterbi_backpointer = new List <List <int> >();

                for (int iword = 0; iword < projs.Count; ++iword)
                {
                    if (iword == 0 || iword == last_word_index)
                    {
                        List <string> w2l = new List <string>();
                        w2l.Add(string.Empty);
                        word2lemmas.Add(w2l);

                        List <int> w2li = new List <int>();
                        w2li.Add(MatchSuffix(GetTokenSuffix(0, last_word_index, projs[iword]), false));
                        word2lemma_id.Add(w2li);
                    }
                    else
                    {
                        List <string> word_lemmas    = new List <string>();
                        List <int>    word_lemma_ids = new List <int>();
                        for (int iproj = 0; iproj < projs[iword].VersionCount(); ++iproj)
                        {
                            string lemma = string.Empty;
                            int    ekey  = projs[iword].GetVersionEntryID(iproj);
                            string ename = gren.GetEntryName(ekey);
                            if (IsUnknownLexem(ename))
                            {
                                lemma = projs[iword].GetWord().ToLower();
                            }
                            else
                            {
                                lemma = ename.ToLower();
                            }

                            if (!word_lemmas.Contains(lemma))
                            {
                                word_lemmas.Add(lemma);
                                int id_lemma = MatchSuffix(GetSuffix(lemma), false);
                                if (id_lemma == -1)
                                {
                                    throw new System.ApplicationException();
                                }

                                word_lemma_ids.Add(id_lemma);
                            }
                        }

                        word2lemmas.Add(word_lemmas);
                        word2lemma_id.Add(word_lemma_ids);
                    }

                    lemmas.Add(word2lemmas[iword][0]);

                    List <double> px = new List <double>();
                    List <int>    bx = new List <int>();
                    for (int i = 0; i < word2lemmas[iword].Count; ++i)
                    {
                        if (iword == 0)
                        {
                            px.Add(1.0); // состояние START
                        }
                        else
                        {
                            px.Add(0.0); // для остальных столбцов пока не знаем
                        }
                        bx.Add(-1);
                    }

                    viterbi_P.Add(px);
                    viterbi_backpointer.Add(bx);
                }

                // Для каждого слова получим id_suffix
                List <int> word_suffices = new List <int>();

                for (int iword = 0; iword < projs.Count; ++iword)
                {
                    string word      = projs[iword].GetWord().ToLower();
                    string suffix    = GetTokenSuffix(iword, last_word_index, projs[iword]);
                    int    id_suffix = MatchSuffix(suffix, false);
                    if (id_suffix == -1)
                    {
                        continue;
                    }

                    word_suffices.Add(id_suffix);
                }

                // расчет по решетке
                for (int iword = 1; iword < projs.Count - 1; ++iword)
                {
                    // в этом столбце столько разных состояний
                    int n_states = word2lemmas[iword].Count;

                    // сразу получим теги для контекста
                    int id_suffix1 = word_suffices[iword - 1];
                    int id_suffix2 = word_suffices[iword];
                    int id_suffix3 = word_suffices[iword + 1];

                    string label1 = TagLabel(-1, id_suffix1);
                    string label2 = TagLabel(0, id_suffix2);
                    string label3 = TagLabel(1, id_suffix3);

                    for (int istate = 0; istate < n_states; ++istate)
                    {
                        // для состояния istate получим целевую метку для леммы
                        int    id_result_lemma = word2lemma_id[iword][istate];
                        string result_label    = ResultLabel(id_result_lemma);

                        if (!result_label2id.ContainsKey(result_label))
                        {
                            // переходов в такое состояние не было вообще, будет нулевая верояность
                            continue;
                        }

                        int res_label_index = result_label2id[result_label];

                        // просматриваем переходы из состояний предыдущего шага
                        int n_prev_states = word2lemmas[iword - 1].Count;

                        double best_p = -1.0;
                        int    best_prev_state_index = -1;

                        for (int i_prev_state = 0; i_prev_state < n_prev_states; ++i_prev_state)
                        {
                            int    id_prev_lemma    = word2lemma_id[iword - 1][i_prev_state];
                            string prev_lemma_label = LemmaLabel(-1, id_prev_lemma);
                            double P_prev           = viterbi_P[iword - 1][i_prev_state];

                            // запускаем модель для получения достоверности нового состояния
                            System.Collections.ArrayList context = new System.Collections.ArrayList();
                            context.Add(prev_lemma_label);
                            context.Add(label1);
                            context.Add(label2);
                            context.Add(label3);

                            try
                            {
                                double[] probabilities = mModel.Evaluate((string[])context.ToArray(typeof(string)));

                                double p = probabilities[res_label_index];

                                double P12 = p * P_prev; // вероятность данного перехода
                                if (P12 > best_p)
                                {
                                    best_p = P12;
                                    best_prev_state_index = i_prev_state;
                                }
                            }
                            catch (System.Exception ex)
                            {
                                // ... обычно это означает, что встретился ключ, которые не был включен в обучающий набор.
                                // будем считать, что у таких переходов нулевая вероятность.s
                            }
                        }

                        if (n_states == 1)
                        {
                            // если на данном шаге всего 1 состояние, то можем принудительно присвоить ему накопленную достоверность=1 и таким образом
                            // улучшить поведение модели при появлении неизвестных слов, приводящих к обнулению вероятностей.
                            viterbi_P[iword][istate] = 1.0;
                        }
                        else
                        {
                            viterbi_P[iword][istate] = best_p;
                        }

                        viterbi_backpointer[iword][istate] = best_prev_state_index;
                    }
                }

                // Для последнего состояния END просто найдем самое достоверное на пред. шаге
                double best_P1     = 0;
                int    best_state1 = 0;
                for (int i = 0; i < word2lemmas[last_word_index - 1].Count; ++i)
                {
                    double p = viterbi_P[last_word_index - 1][i];
                    if (p > best_P1)
                    {
                        best_P1     = p;
                        best_state1 = i;
                    }
                }

                viterbi_P[last_word_index][0]           = best_P1;
                viterbi_backpointer[last_word_index][0] = best_state1;

                // теперь обратный проход по решетке, через записи в backpointer'ах восстанавливаем самую достоверную цепочку лемм
                // для последнего шага - всего одно состояние END.
                int cur_backpointer = viterbi_backpointer[projs.Count - 1][0];
                int j = projs.Count - 2;

                List <string> best_lemmas = new List <string>();
                for (int k = 0; k < projs.Count; ++k)
                {
                    best_lemmas.Add(string.Empty);
                }

                while (j > 0)
                {
                    // для этого шага - такая лучшая лемма
                    string best_lemma = word2lemmas[j][cur_backpointer];
                    best_lemmas[j] = best_lemma;

                    // определяем лучшее состояние для предыдущего шага
                    int prev_backpointer = viterbi_backpointer[j][cur_backpointer];
                    cur_backpointer = prev_backpointer;

                    j--;
                }

                // Теперь сравниваем леммы c правильными значениями.
                for (int iword = 1; iword < tokens.Count - 1; ++iword)
                {
                    string mustbe = string.Empty;

                    int    ekey  = tokens[iword].GetEntryID();
                    string ename = gren.GetEntryName(ekey);

                    if (IsUnknownLexem(ename)) // не будем учитывать ошибки лемматизации для не-словарных лексем.
                    {
                        continue;
                    }

                    mustbe = ename.ToLower();

                    if (mustbe != best_lemmas[iword])
                    {
                        error_count_with_ngram++;
                    }

                    string lemma0 = string.Empty;
                    int    ekey0  = projs[iword].GetEntryID();
                    string ename0 = gren.GetEntryName(ekey0);
                    if (IsUnknownLexem(ename0))
                    {
                        continue;
                    }

                    lemma0 = ename0.ToLower();

                    if (mustbe != lemma0)
                    {
                        error_count_no_filter++;
                    }
                }
            }
        }

        return;
    }
Esempio n. 30
0
 public AnalysisResults AnalyzeSyntax( string phrase, int id_language, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags morph_flags, SolarixGrammarEngineNET.GrammarEngine.SyntaxFlags syntax_flags, int constraints )
 {
  IntPtr hPack = GrammarEngine.sol_SyntaxAnalysis( _hEngine, phrase, morph_flags, syntax_flags, constraints, id_language );
  AnalysisResults res = new AnalysisResults( this, hPack );
  return res;
 }
Esempio n. 31
0
    static void ProcessSentence2(string phrase, SolarixGrammarEngineNET.GrammarEngine2 gren, int max_len)
    {
        nb_processed += 1;

        if (nb_skip != 0 && nb_processed < nb_skip)
        {
            return;
        }

        if (phrase.Length > 2)
        {
            bool   used       = false;
            string terminator = "";

            if (IsSentenceTerminator(phrase.Last()))
            {
                terminator = new string(phrase.Last(), 1);

                // Удалим финальные символы типа . или !
                int finalizers = 1;
                for (int i = phrase.Length - 2; i > 0; --i)
                {
                    if (IsSentenceTerminator(phrase[i]))
                    {
                        finalizers++;
                    }
                }

                phrase = phrase.Substring(0, phrase.Length - finalizers);
            }

            if (!processed_phrases.Contains(phrase))
            {
                processed_phrases.Add(phrase);

                string phrase2 = Preprocess(phrase, gren);

                // Выполним оценку синтаксического качества предложения, чтобы отсеять мусор.
                int id_language = SolarixGrammarEngineNET.GrammarEngineAPI.RUSSIAN_LANGUAGE;
                SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags morph_flags  = SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY | SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_MODEL;
                SolarixGrammarEngineNET.GrammarEngine.SyntaxFlags     syntax_flags = SolarixGrammarEngineNET.GrammarEngine.SyntaxFlags.DEFAULT;
                int MaxAlt      = 40;
                int constraints = 600000 | (MaxAlt << 22);

                using (SolarixGrammarEngineNET.AnalysisResults linkages = gren.AnalyzeSyntax(phrase2, id_language, morph_flags, syntax_flags, constraints))
                {
                    if (linkages.Count == 3)
                    {
                        SolarixGrammarEngineNET.SyntaxTreeNode        root  = linkages[1];
                        List <SolarixGrammarEngineNET.SyntaxTreeNode> terms = GetTerms(root).OrderBy(z => z.GetWordPosition()).ToList();

                        int score = linkages.Score;

                        bool good = false;
                        if (score >= -4)
                        {
                            good = true;

                            if (!syntax_checker.IsEmpty())
                            {
                                FootPrint footprint = new FootPrint(gren, terms);

                                // Проверим синтаксическую структуру фразы, чтобы отсеять разговорную некондицию.
                                good = syntax_checker.IsGoodSyntax(footprint);
                            }
                        }

                        if (good)
                        {
                            used = true;
                            WriteSample(phrase + terminator);
                            wrt_samples.Flush();
                        }
                        else
                        {
                            SkippedSample(phrase);
                        }
                    }
                }
            }
        }

        Console.Write("{0} processed, {1} stored\r", nb_processed, nb_stored);

        return;
    }
Esempio n. 32
0
 public AnalysisResults AnalyzeMorphology( string phrase, int id_language, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags flags, int constraints )
 {
  IntPtr hPack = GrammarEngine.sol_MorphologyAnalysis( _hEngine, phrase, flags, 0, constraints, id_language );
  AnalysisResults res = new AnalysisResults( this, hPack );
  return res;
 }
Esempio n. 33
0
    /*
     * public void Check( string line, List<int> model_lemma_ids )
     * {
     * // Морфологический разбор
     * using( SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology( line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.SOL_GREN_COMPLETE_ONLY ) )
     * {
     * // Токенизация без использования синтаксических правил
     * using( SolarixGrammarEngineNET.AnalysisResults projs = gren.AnalyzeMorphology( line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.SOL_GREN_TOKENIZE_ONLY ) )
     * {
     *  List<List<int>> word2tags = new List<List<int>>();
     *
     *  if( projs.Count != tokens.Count )
     *   return;
     *
     *  total_word_count += projs.Count - 2;
     *
     *  // Для каждого слова получим списки альтернативных лемматизаций.
     *  List<List<string>> word2lemmas = new List<List<string>>();
     *
     *  List<string> lemmas = new List<string>();
     *
     *  int last_word_index = projs.Count - 1;
     *
     *  for( int iword = 0; iword < projs.Count; ++iword )
     *  {
     *   if( iword == 0 || iword == last_word_index )
     *   {
     *    List<string> w2l = new List<string>();
     *    w2l.Add( string.Empty );
     *    word2lemmas.Add( w2l );
     *   }
     *   else
     *   {
     *    List<string> word_lemmas = new List<string>();
     *    for( int iproj = 0; iproj < projs[iword].VersionCount(); ++iproj )
     *    {
     *     string lemma = string.Empty;
     *     int ekey = projs[iword].GetVersionEntryID( iproj );
     *     string ename = gren.GetEntryName( ekey );
     *     if( IsUnknownLexem( ename ) )
     *      lemma = projs[iword].GetWord().ToLower();
     *     else
     *      lemma = ename.ToLower();
     *
     *     if( !word_lemmas.Contains( lemma ) )
     *      word_lemmas.Add( lemma );
     *    }
     *
     *    word2lemmas.Add( word_lemmas );
     *   }
     *
     *   lemmas.Add( word2lemmas[iword][0] );
     *  }
     *
     *  // model_lemma_ids - это те леммы, которые выбраны моделью.
     *  for( int iword = 1; iword < projs.Count - 1; ++iword )
     *  {
     *   // теперь перебираем проекции и смотрим, которая из них имеет в нормальной форме выбранный суффикс.
     *   for( int iproj = 0; iproj < word2lemmas[iword].Count; ++iproj )
     *   {
     *    string ename = word2lemmas[iword][iproj];
     *    string proj_suffix = GetSuffix( ename.ToLower() );
     *    int id_suffix = MatchSuffix( proj_suffix, false );
     *    if( id_suffix == -1 )
     *     continue;
     *
     *    if( id_suffix == model_lemma_ids[iword] )
     *    {
     *     lemmas[iword] = ename.ToLower();
     *    }
     *   }
     *  }
     *
     *  // Теперь сравниваем леммы c правильными значениями.
     *  for( int iword = 1; iword < tokens.Count - 1; ++iword )
     *  {
     *   string mustbe = string.Empty;
     *
     *   int ekey = tokens[iword].GetEntryID();
     *   string ename = gren.GetEntryName( ekey );
     *
     *   if( IsUnknownLexem( ename ) ) // не будем учитывать ошибки лемматизации для не-словарных лексем.
     *    continue;
     *
     *   mustbe = ename.ToLower();
     *
     *   if( mustbe != lemmas[iword] )
     *    error_count_with_ngram++;
     *
     *   string lemma0 = string.Empty;
     *   int ekey0 = projs[iword].GetEntryID();
     *   string ename0 = gren.GetEntryName( ekey0 );
     *   if( IsUnknownLexem( ename0 ) )
     *    continue;
     *
     *   lemma0 = ename0.ToLower();
     *
     *   if( mustbe != lemma0 )
     *    error_count_no_filter++;
     *  }
     * }
     * }
     *
     * return;
     * }
     */



    public void Check(string line, List <int> model_lemma_ids)
    {
        // Морфологический разбор
        using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY))
        {
            total_word_count += tokens.Count - 2;

            System.Text.StringBuilder b = new System.Text.StringBuilder();
            b.Capacity = 100;

            int last_word_index = tokens.Count - 1;

            for (int iword = 1; iword < tokens.Count - 1; ++iword)
            {
                string word = tokens[iword].GetWord();

                bool hit = false;

                System.IntPtr hLemmas = SolarixLemmatizatorEngineNET.LemmatizatorEngine.sol_GetLemmasW(lemm_engine, word);
                if (hLemmas == System.IntPtr.Zero)
                {
                    throw new System.ApplicationException();
                }

                int nlemma = SolarixLemmatizatorEngineNET.LemmatizatorEngine.sol_CountLemmas(hLemmas);
                for (int i = 0; i < nlemma; ++i)
                {
                    b.Length = 0;
                    SolarixLemmatizatorEngineNET.LemmatizatorEngine.sol_GetLemmaStringW(hLemmas, i, b, b.Capacity);

                    string lemma = b.ToString().ToLower();

                    int id_lemma = MatchSuffix(GetLemmaSuffix(lemma), false);
                    if (id_lemma == -1)
                    {
                        continue;
                    }

                    if (model_lemma_ids[iword] == id_lemma)
                    {
                        // модель выбрала эту лемму. сравним с вариантами точных лемм.
                        bool found_lemma = false;
                        for (int j = 0; j < tokens[iword].VersionCount(); ++j)
                        {
                            string version_lemma  = GetTokenVersionLemma(j, tokens[iword]);
                            string version_suffix = GetLemmaSuffix(version_lemma);
                            int    version_id     = MatchSuffix(version_suffix, true);
                            if (version_id == id_lemma)
                            {
                                found_lemma = true;
                                break;
                            }
                        }

                        hit = found_lemma;
                        break;
                    }
                }

                if (!hit)
                {
                    error_count_with_ngram++;
                }

                SolarixLemmatizatorEngineNET.LemmatizatorEngine.sol_DeleteLemmas(hLemmas);
            }
        }

        return;
    }
    public bool Sentence2Features(string line)
    {
        // синтаксический разбор в дерево
        using (SolarixGrammarEngineNET.AnalysisResults trees = gren.AnalyzeSyntax(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY, 0))
        {
            // Морфологический разбор
            using (SolarixGrammarEngineNET.AnalysisResults tokens = gren.AnalyzeMorphology(line, LanguageID, SolarixGrammarEngineNET.GrammarEngine.MorphologyFlags.SOL_GREN_COMPLETE_ONLY))
            {
                TreeLookup syntax = new TreeLookup();
                syntax.Collect(tokens, trees, gren);

                if (!syntax.ok)
                {
                    return(false);
                }

                int N = tokens.Count;

                List <WordTags> tag_index = new List <WordTags>();
                List <string>   words     = new List <string>();
                List <string>   labels    = new List <string>();

                WordTags start_t = new WordTags();
                start_t.common = START_id;
                tag_index.Add(start_t);
                words.Add("<START>");
                labels.Add("O");

                for (int iword = 1; iword < tokens.Count - 1; ++iword)
                {
                    SolarixGrammarEngineNET.SyntaxTreeNode token = tokens[iword];
                    string word = token.GetWord().ToLower();

                    SolarixGrammarEngineNET.SyntaxTreeNode token_prev = tokens[iword - 1];

                    WordTags t = new WordTags();

                    t.common   = tags.MatchTags(tokens[iword], gren);
                    t.modality = tags_modality.MatchTags(tokens[iword], gren);
                    t.valency  = tags_valency.MatchTags(tokens[iword], gren);

                    tag_index.Add(t);

                    string crf_word = word.Replace(" ", "_");
                    words.Add(crf_word);

                    labels.Add(syntax.GetTokenLabel(iword));
                }

                WordTags end_t = new WordTags();
                end_t.common = END_id;
                tag_index.Add(end_t);
                words.Add("<END>");
                labels.Add("O");

                System.Text.StringBuilder b = new System.Text.StringBuilder();

                int last_word_index = tokens.Count - 1;
                for (int iword = 0; iword < tokens.Count; ++iword)
                {
                    b.Length = 0;

                    string output_label = labels[iword];
                    string word         = words[iword];

//     PullFeatures1( b, tag_index, iword, -3 );
                    PullFeatures1(b, tag_index, iword, -2);
                    PullFeatures1(b, tag_index, iword, -1);
                    PullFeatures1(b, tag_index, iword, 0);
                    PullFeatures1(b, tag_index, iword, 1);
                    PullFeatures1(b, tag_index, iword, 2);
//     PullFeatures1( b, tag_index, iword, 3 );

//     PullFeatures2( b, tag_index, iword, -3, -2 );
                    PullFeatures2(b, tag_index, iword, -2, -1);
                    PullFeatures2(b, tag_index, iword, -1, 0);
                    PullFeatures2(b, tag_index, iword, 0, 1);
                    PullFeatures2(b, tag_index, iword, 1, 2);
//     PullFeatures2( b, tag_index, iword, 3, 4 );

//     PullFeatures3( b, tag_index, iword, -3, -2, -1 );
                    PullFeatures3(b, tag_index, iword, -2, -1, 0);
                    PullFeatures3(b, tag_index, iword, -1, 0, 1);
                    PullFeatures3(b, tag_index, iword, 0, 1, 2);
//     PullFeatures3( b, tag_index, iword, 1, 2, 3 );

                    crf_file.WriteLine("{0}{1}", output_label, b.ToString());

                    visual_file.WriteLine("{0}\t{1}\t{2}", word, output_label, tag_index[iword]);
                }

                crf_file.WriteLine("");
                visual_file.WriteLine("");
            }
        }

        return(true);
    }
    public void ProcessSample(string line, SolarixGrammarEngineNET.AnalysisResults tokens, int left_i, SolarixGrammarEngineNET.GrammarEngine2 gren)
    {
        // В контекст входят слова от left_i по left_i+ctx.len.

        /*
         * // ---- DEBUG
         * System.Text.StringBuilder b = new StringBuilder();
         * for( int i=0; i<ctx.len; ++i )
         * if( i>0 )
         *  b.AppendFormat( " {0}", tokens[left_i+i].GetWord() );
         * else
         *  b.AppendFormat( "{0}", tokens[left_i+i].GetWord() );
         *
         * string context_str = b.ToString();
         * // --- END DEBUG
         */

        // ... todo проверяем, не сопоставляются ли слова с уже имеющимися контекстами.
        for (int i = 0; i < recognizers.Count; ++i)
        {
            ContextRecognizer recognizer = recognizers[i];
            int match = recognizer.Match(tokens, left_i, gren);
            if (match == 1)
            {
                // правило правильно распознало контекст и сняло омонимию.
                recognizer.Success(new MatchedContextInfo(line, tokens, left_i, ctx.len));
            }
            else if (match == 0)
            {
                // правило распознало контекст, но неправильно сняло омонимию.
                recognizer.Fail(new MatchedContextInfo(line, tokens, left_i, ctx.len));
            }
        }

        // Используем сэмпл для генерации правил только в том случае, если омонимичный токен дал 1 вариант словарной статьи.
        bool generate_rule = true;
        int  omonym_ekey   = -1;

        SolarixGrammarEngineNET.SyntaxTreeNode omonym_token = tokens[left_i + ctx.position];
        int omonym_versions = omonym_token.VersionCount();

        for (int iver = 0; iver < omonym_versions; ++iver)
        {
            int ekey = omonym_token.GetVersionEntryID(iver);
            if (omonym_ekey == -1)
            {
                omonym_ekey = ekey;
            }
            else if (omonym_ekey != ekey)
            {
                // омонимичный токен распознан как несколько разных лемм, поэтому не будет генерировать для него правила.
                generate_rule = false;
                break;
            }
        }

        if (generate_rule)
        {
            // Генерируем варианты распознавания контекста, начиная от самого конкретного - через лексемы не-мононимичных слов, для самых
            // общих - частей речи для них же.
            OmonymContextEnumerator ctx_generator = new OmonymContextEnumerator(tokens, ctx.position, left_i, ctx.len, gren);

            for (int i = 0; i < ctx_generator.Count; ++i)
            {
                ContextRecognizer recognizer = ctx_generator[i];

                // проверим, что такого распознавателя еще нет.
                bool is_unique = true;
                foreach (ContextRecognizer r in recognizers)
                {
                    if (r.EqualTokens(recognizer))
                    {
                        is_unique = false;
                        break;
                    }
                }

                if (is_unique)
                {
                    recognizer.Success(new MatchedContextInfo(line, tokens, left_i, ctx.len));
                    recognizers.Add(recognizer);
                }
            }
        }

        return;
    }