Beispiel #1
0
    ParsingContext ParseAndReturnBest(ParsingContext org_context)
    {
        ParsingContexts contexts = new ParsingContexts(org_context);

        int n_pass = 0;

        while (true)
        {
            n_pass++;
            for (int ictx = 0; ictx < contexts.Count(); ++ictx)
            {
                ParsingContext cur_context = contexts[ictx];
                int            ntoken      = cur_context.tokens.Count;

                for (int iword = 0; iword < cur_context.tokens.Count; ++iword)
                {
                    // ищем правила, применимые для сборки контекста вокруг слова в iword.
                    ParsingToken headword = cur_context.tokens[iword];

                    for (int rule_layer = 0; rule_layer < 2; ++rule_layer)
                    {
                        ParsingContext new_ctx = null;

                        /*
                         *    if( rule_layer == 0 )
                         *    {
                         *     if( cur_context.tokens.Count > 2 )
                         *     {
                         *      // проверяем 3-граммы
                         *      NGrams4Headword ngrams = null;
                         *      if( headword_ngrams.TryGetValue( headword.GetToken(), out ngrams ) )
                         *      {
                         *       if( iword + 2 <= cur_context.tokens.Count - 1 )
                         *       {
                         *        // ROOT + NODE + SUBNODE
                         *        ParsingToken node_token = cur_context.tokens[iword + 1];
                         *        ParsingToken subnode_token = cur_context.tokens[iword + 2];
                         *
                         *        int score = ngrams.FindRule_Root_Node_Subnode( node_token.GetToken(), subnode_token.GetToken() );
                         *        if( score > 0 )
                         *        {
                         *         // создаем новый контекст
                         *
                         *         List<ParsingToken> new_tokens = new List<ParsingToken>();
                         *         for( int j = 0; j < cur_context.tokens.Count; ++j )
                         *          if( j != iword + 1 && j != iword + 2 )
                         *           new_tokens.Add( cur_context.tokens[j] );
                         *
                         *         Edge4Stat_Words e1 = new Edge4Stat_Words();
                         *         e1.l_token = headword;
                         *         e1.r_token = node_token;
                         *         e1.root_index = 0;
                         *
                         *         Edge4Stat_Words e2 = new Edge4Stat_Words();
                         *         e2.l_token = node_token;
                         *         e2.r_token = subnode_token;
                         *         e2.root_index = 0;
                         *
                         *         List<Edge4Stat_Words> new_edges = new List<Edge4Stat_Words>();
                         *         new_edges.AddRange( cur_context.edges );
                         *         new_edges.Add( e1 );
                         *         new_edges.Add( e2 );
                         *
                         *         new_ctx = new ParsingContext( new_tokens, cur_context.GetScore() + score, new_edges );
                         *
                         *
                         *        }
                         *       }
                         *      }
                         *     }
                         *    }
                         *    else
                         *    {
                         */

                        Rules4Headword rules = null;

                        bool head_found;

                        if (rule_layer == 0)
                        {
                            head_found = headword_rules.TryGetValue(headword.GetToken(), out rules);
                        }
                        else
                        {
                            head_found = headword_sx_rules.TryGetValue(headword.GetTag(), out rules);
                        }

                        if (head_found)
                        {
                            for (int offset = -2; offset <= 2; ++offset)
                            {
                                if (offset == 0)
                                {
                                    continue;
                                }

                                int remove_index = iword + offset;

                                if (remove_index < 0 || remove_index >= ntoken)
                                {
                                    continue; // слово за пределами цепочки
                                }
                                ParsingToken child_word     = cur_context.tokens[remove_index];
                                int          child_position = offset < 0 ? -1 : 1;

                                int score = rules.FindRule(rule_layer == 0 ? child_word.GetToken() : child_word.GetTag(), child_position);

                                if (score > 0)
                                {
                                    // для непроективных дальных ребер штрафуем через уменьшение частотности
                                    int freq = score / Math.Abs(offset);

                                    // также штраф за лист, если зависимый токен не имеет веток
                                    int leaf_fine = 0;
                                    if (!cur_context.HasChildren(cur_context.tokens[remove_index].GetPosition()))
                                    {
                                        leaf_score.TryGetValue(cur_context.tokens[remove_index].GetToken(), out leaf_fine);
                                    }


                                    // зависимое слово убираем из контекста
                                    List <ParsingToken> new_tokens = new List <ParsingToken>();
                                    for (int j = 0; j < cur_context.tokens.Count; ++j)
                                    {
                                        if (j != remove_index)
                                        {
                                            new_tokens.Add(cur_context.tokens[j]);
                                        }
                                    }

                                    Edge4Stat_Words e = new Edge4Stat_Words();
                                    if (child_position == -1)
                                    {
                                        e.l_token    = child_word;
                                        e.r_token    = headword;
                                        e.root_index = 1;
                                    }
                                    else
                                    {
                                        e.r_token    = child_word;
                                        e.l_token    = headword;
                                        e.root_index = 0;
                                    }

                                    List <Edge4Stat_Words> new_edges = new List <Edge4Stat_Words>();
                                    new_edges.AddRange(cur_context.edges);
                                    new_edges.Add(e);

                                    new_ctx = new ParsingContext(new_tokens, cur_context.GetScore() + freq - leaf_fine, new_edges);
                                }
                            }
                        }



                        if (new_ctx != null)
                        {
                            // проверим уникальность
                            bool do_add = true;
                            for (int i = 0; i < contexts.Count(); ++i)
                            {
                                if (contexts[i].GetHashCode() == new_ctx.GetHashCode())
                                {
                                    if (contexts[i].Equals(new_ctx))
                                    {
                                        if (contexts[i].GetScore() < new_ctx.GetScore())
                                        {
                                            contexts[i] = new_ctx;
                                        }

                                        do_add = false;
                                        break;
                                    }
                                }
                            }

                            if (do_add)
                            {
                                for (int i = 0; i < contexts.new_contexts.Count(); ++i)
                                {
                                    if (contexts.new_contexts[i].GetHashCode() == new_ctx.GetHashCode())
                                    {
                                        if (contexts.new_contexts[i].Equals(new_ctx))
                                        {
                                            if (contexts.new_contexts[i].GetScore() < new_ctx.GetScore())
                                            {
                                                contexts.new_contexts[i] = new_ctx;
                                            }

                                            do_add = false;
                                            break;
                                        }
                                    }
                                }

                                if (do_add)
                                {
                                    contexts.Add(new_ctx);
                                }
                            }
                        }
                    }
                }
            }

            if (contexts.Commit() == 0)
            {
                break;
            }
        }

        // теперь берем самый лучший результат
        ParsingContext best = contexts.GetBest();

        return(best);
    }
Beispiel #2
0
    public bool ProcessSample(SampleData sample)
    {
        /*
         * List<Rule3Gram> ngrams = new List<Rule3Gram>();
         * Assemble3Grams( sample.syntax_tree, ngrams );
         *
         * foreach( Rule3Gram ngram in ngrams )
         * {
         * if( ngram.root.GetWordPosition() < ngram.node.GetWordPosition() &&
         *     ngram.node.GetWordPosition() < ngram.subnode.GetWordPosition() )
         * {
         *  NGrams4Headword nx;
         *  if( !headword_ngrams.TryGetValue( ngram.root.GetWord().ToUpper(), out nx ) )
         *  {
         *   nx = new NGrams4Headword();
         *   headword_ngrams.Add( ngram.root.GetWord().ToUpper(), nx );
         *  }
         *
         *  nx.Add_Root_Node_Subnode( ngram.node.GetWord().ToUpper(), ngram.subnode.GetWord().ToUpper() );
         * }
         * // TODO ELSE остальные топологии
         * }
         */


        List <Edge4Stat> edges = new List <Edge4Stat>();

        AssembleEdges(sample.syntax_tree, edges, leaves_count);

        foreach (Edge4Stat e in edges)
        {
            int child_position = e.from.GetWordPosition() > e.to.GetWordPosition() ? -1 : 1;

            // --- ПРАВИЛО ДЛЯ ТОЧНЫХ СЛОВ ---
            string headword   = NormalizeToken(e.from.GetWord());
            string child_word = NormalizeToken(e.to.GetWord());

            Rules4Headword rx;
            if (!headword_rules.TryGetValue(headword, out rx))
            {
                rx = new Rules4Headword(headword);
                headword_rules.Add(headword, rx);
            }

            rx.AddRule(child_word, child_position, 1);


            // --- ПРАВИЛО ДЛЯ СУФФИКСОВ СЛОВ ---
            string headword_sx   = NormalizeTokenSx(e.from.GetWord());
            string child_word_sx = NormalizeTokenSx(e.to.GetWord());

            Rules4Headword rx_sx;
            if (!headword_sx_rules.TryGetValue(headword_sx, out rx_sx))
            {
                rx_sx = new Rules4Headword(headword_sx);
                headword_sx_rules.Add(headword_sx, rx_sx);
            }

            rx_sx.AddRule(child_word_sx, child_position, 1);
        }

        return(true);
    }