bool IsPreposition(SolarixGrammarEngineNET.SyntaxTreeNode token) { if (token.VersionCount() == 1) { int id_entry = token.GetEntryID(); int pos = gren.GetEntryClass(id_entry); if (pos == SolarixGrammarEngineNET.GrammarEngineAPI.PREPOS_ru) { return(true); } } return(false); }
static int GetPOS(SolarixGrammarEngineNET.GrammarEngine2 gren, SolarixGrammarEngineNET.SyntaxTreeNode node) { int id_entry = node.GetEntryID(); int pos_id = gren.GetEntryClass(id_entry); return(pos_id); }
static List <string> GetWordFeatures(SolarixGrammarEngineNET.GrammarEngine2 gren, SolarixGrammarEngineNET.SyntaxTreeNode word, string feature_prefix) { List <string> features = new List <string>(); if (emit_shingles) { // шинглы features.AddRange(GetShingles(word.GetWord()).Select(z => $"shingle[{feature_prefix}]={z}")); } if (emit_morphtags) { // морфологические фичи int id_class = gren.GetEntryClass(word.GetEntryID()); features.Add(string.Format("class[{0}]={1}", feature_prefix, id_class)); int nfeat = SolarixGrammarEngineNET.GrammarEngine.sol_GetNodePairsCount(word.hNode); for (int i = 0; i < nfeat; ++i) { int id_coord = SolarixGrammarEngineNET.GrammarEngine.sol_GetNodePairCoord(word.hNode, i); int id_state = SolarixGrammarEngineNET.GrammarEngine.sol_GetNodePairState(word.hNode, i); features.Add(string.Format("{0}[{2}]={1}", id_coord, id_state, feature_prefix)); } } return(features); }
public bool Match(SolarixGrammarEngineNET.SyntaxTreeNode proj, int iver, SolarixGrammarEngineNET.GrammarEngine2 gren) { if (lexeme != null) { return(proj.GetWord().Equals(lexeme, StringComparison.InvariantCultureIgnoreCase)); } if (id_lemma != null) { int ekey = proj.GetVersionEntryID(iver); if (id_lemma.Contains(ekey)) { return(true); } return(false); } if (pos != null) { bool pos_matched = false; int ekey = proj.GetVersionEntryID(iver); if (ekey != -1) { int id_class = gren.GetEntryClass(ekey); pos_matched = pos.Contains(id_class); } if (!pos_matched) { return(false); } } if (pairs != null) { bool contains_all_required_pairs = true; foreach (SolarixGrammarEngineNET.CoordPair p in pairs) { if (!proj.VersionContains(iver, p)) { contains_all_required_pairs = false; break; } } if (!contains_all_required_pairs) { return(false); } } return(true); }
public string GetContextPoint(SolarixGrammarEngineNET.GrammarEngine2 gren) { System.Text.StringBuilder b = new StringBuilder(); if (!string.IsNullOrEmpty(lexem)) { b.AppendFormat("\"{0}\"", lexem); } else { if (id_class != -1) { b.AppendFormat("{0}:*", gren.GetClassName(id_class)); } else { int pos = gren.GetEntryClass(id_entry); b.AppendFormat("{0}:{1}", gren.GetClassName(pos), gren.GetEntryName(id_entry)); } b.Append("{"); // выводим список координатных пар foreach (SolarixGrammarEngineNET.CoordPair p in pairs) { string CoordName = gren.GetCoordName(p.CoordID); if (gren.CountCoordStates(p.CoordID) == 0) { if (p.StateID == 1) { b.AppendFormat(" {0}", CoordName); } else { b.AppendFormat(" ~{0}", CoordName); } } else { string StateName = gren.GetCoordStateName(p.CoordID, p.StateID); b.AppendFormat(" {0}:{1}", CoordName, StateName); } } b.Append(" }"); } return(b.ToString()); }
public int MatchTags(SolarixGrammarEngineNET.SyntaxTreeNode token, SolarixGrammarEngineNET.GrammarEngine2 gren) { foreach (TagMatcher m in matchers) { if (m.Match(token, gren)) { return(m.GetId()); } } int entry_id = token.GetEntryID(); int pos_id = gren.GetEntryClass(entry_id); string part_of_speech = gren.GetClassName(pos_id); string tags = string.Join(" ", token.GetPairs().Select(z => string.Format("{0}={1}", gren.GetCoordName(z.CoordID), gren.GetCoordStateName(z.CoordID, z.StateID))).ToArray()); string msg = string.Format("Can not find tag for {0} {{ {1} {2} }}", token.GetWord(), part_of_speech, tags); throw new ApplicationException(msg); }
public bool Match(SolarixGrammarEngineNET.SyntaxTreeNode token, SolarixGrammarEngineNET.GrammarEngine2 gren) { if (!string.IsNullOrEmpty(lexem)) { return(lexem.Equals(token.GetWord(), StringComparison.CurrentCultureIgnoreCase)); } // Признаём сопоставимость с любой версией токена. int nver = token.VersionCount(); for (int iver = 0; iver < nver; ++iver) { int version_ekey = token.GetVersionEntryID(iver); if (id_entry != -1 && version_ekey == id_entry) { return(true); } if (id_class != -1 && gren.GetEntryClass(version_ekey) == id_class) { return(true); } bool pairs_matched = true; foreach (SolarixGrammarEngineNET.CoordPair p in pairs) { if (!token.VersionContains(iver, p)) { pairs_matched = false; break; } } if (pairs_matched) { return(true); } } return(true); }
public FootPrintToken(SolarixGrammarEngineNET.GrammarEngine2 gren, SolarixGrammarEngineNET.SyntaxTreeNode root) { Contract.Ensures(!string.IsNullOrEmpty(this.word)); Contract.Ensures(this.node != null); Contract.Ensures(this.tags != null); this.word = root.GetWord(); this.tags = new List <string>(); this.node = root; this.tags.Add(root.GetWord().ToLower()); if (root.GetWord().Equals("не", StringComparison.OrdinalIgnoreCase)) { this.tags.Add("neg"); } int part_of_speech = gren.GetEntryClass(root.GetEntryID()); switch (part_of_speech) { case SolarixGrammarEngineNET.GrammarEngineAPI.CONJ_ru: this.tags.Add("conj"); break; // союз case SolarixGrammarEngineNET.GrammarEngineAPI.PRONOUN_ru: this.tags.Add("pr"); break; // местоимение Я case SolarixGrammarEngineNET.GrammarEngineAPI.NOUN_ru: this.tags.Add("n"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.ADJ_ru: this.tags.Add("adj"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.VERB_ru: this.tags.Add("v"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.INFINITIVE_ru: this.tags.Add("v"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.GERUND_2_ru: this.tags.AddRange("adv adv_v".Split(' ')); break; case SolarixGrammarEngineNET.GrammarEngineAPI.ADVERB_ru: { this.tags.Add("adv"); if (StringExtender.InCI(word, "очень крайне наиболее наименее чрезвычайно почти".Split())) // модификаторы наречий и прилагательных { this.tags.Add("a_modif"); } string adv_cat = AdverbCategory.GetQuestionWordForAdverb(word); if (!string.IsNullOrEmpty(adv_cat)) { this.tags.Add("adv_" + adv_cat); } break; } case SolarixGrammarEngineNET.GrammarEngineAPI.PREPOS_ru: this.tags.Add("p"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.PRONOUN2_ru: this.tags.Add("pr"); break; default: this.tags.Add("x"); break; } foreach (var p in root.GetPairs()) { if (p.CoordID == SolarixGrammarEngineNET.GrammarEngineAPI.CASE_ru) { switch (p.StateID) { case SolarixGrammarEngineNET.GrammarEngineAPI.NOMINATIVE_CASE_ru: this.tags.Add("nom"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.GENITIVE_CASE_ru: this.tags.Add("gen"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.ACCUSATIVE_CASE_ru: this.tags.Add("acc"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.DATIVE_CASE_ru: this.tags.Add("dat"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.PREPOSITIVE_CASE_ru: this.tags.Add("prep"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.PARTITIVE_CASE_ru: this.tags.Add("part"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.LOCATIVE_CASE_ru: this.tags.Add("loc"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.INSTRUMENTAL_CASE_ru: this.tags.Add("instr"); break; } } if (p.CoordID == SolarixGrammarEngineNET.GrammarEngineAPI.NUMBER_ru) { switch (p.StateID) { case SolarixGrammarEngineNET.GrammarEngineAPI.SINGULAR_NUMBER_ru: this.tags.Add("sing"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.PLURAL_NUMBER_ru: this.tags.Add("pl"); break; } } if (p.CoordID == SolarixGrammarEngineNET.GrammarEngineAPI.TENSE_ru) { switch (p.StateID) { case SolarixGrammarEngineNET.GrammarEngineAPI.PAST_ru: this.tags.Add("past"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.PRESENT_ru: this.tags.Add("pres"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.FUTURE_ru: this.tags.Add("future"); break; } } if (p.CoordID == SolarixGrammarEngineNET.GrammarEngineAPI.FORM_ru) { switch (p.StateID) { case SolarixGrammarEngineNET.GrammarEngineAPI.ANIMATIVE_FORM_ru: this.tags.Add("anim"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.INANIMATIVE_FORM_ru: this.tags.Add("inanim"); break; } } if (p.CoordID == SolarixGrammarEngineNET.GrammarEngineAPI.GENDER_ru) { switch (p.StateID) { case SolarixGrammarEngineNET.GrammarEngineAPI.MASCULINE_GENDER_ru: this.tags.Add("masc"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.FEMININE_GENDER_ru: this.tags.Add("fem"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.NEUTRAL_GENDER_ru: this.tags.Add("neut"); break; } } if (p.CoordID == SolarixGrammarEngineNET.GrammarEngineAPI.PERSON_ru) { switch (p.StateID) { case SolarixGrammarEngineNET.GrammarEngineAPI.PERSON_1_ru: this.tags.Add("1"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.PERSON_2_ru: this.tags.Add("2"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.PERSON_3_ru: this.tags.Add("3"); break; } } if (p.CoordID == SolarixGrammarEngineNET.GrammarEngineAPI.VERB_FORM_ru) { switch (p.StateID) { case SolarixGrammarEngineNET.GrammarEngineAPI.VB_INF_ru: this.tags.Add("vf1"); break; case SolarixGrammarEngineNET.GrammarEngineAPI.VB_ORDER_ru: this.tags.Add("imper"); break; } } } }
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; }
string GetNodeNonterminal(SolarixGrammarEngineNET.SyntaxTreeNode node) { string res = string.Empty; int e1 = node.GetEntryID(); int c1 = gren.GetEntryClass(e1); if (c1 == SolarixGrammarEngineNET.GrammarEngineAPI.NOUN_ru || c1 == SolarixGrammarEngineNET.GrammarEngineAPI.PRONOUN_ru || c1 == SolarixGrammarEngineNET.GrammarEngineAPI.PRONOUN2_ru) { int id_case = node.GetCoordState(SolarixGrammarEngineNET.GrammarEngineAPI.CASE_ru); string case_str = string.Empty; switch (id_case) { case SolarixGrammarEngineNET.GrammarEngineAPI.NOMINATIVE_CASE_ru: case_str = "им"; break; case SolarixGrammarEngineNET.GrammarEngineAPI.INSTRUMENTAL_CASE_ru: case_str = "твор"; break; case SolarixGrammarEngineNET.GrammarEngineAPI.GENITIVE_CASE_ru: case_str = "род"; break; case SolarixGrammarEngineNET.GrammarEngineAPI.ACCUSATIVE_CASE_ru: case_str = "вин"; break; case SolarixGrammarEngineNET.GrammarEngineAPI.DATIVE_CASE_ru: case_str = "дат"; break; } res = string.Format("Сущ_{0}", case_str); } else if (c1 == SolarixGrammarEngineNET.GrammarEngineAPI.ADJ_ru) { int id_case = node.GetCoordState(SolarixGrammarEngineNET.GrammarEngineAPI.CASE_ru); string case_str = string.Empty; switch (id_case) { case SolarixGrammarEngineNET.GrammarEngineAPI.NOMINATIVE_CASE_ru: case_str = "им"; break; case SolarixGrammarEngineNET.GrammarEngineAPI.INSTRUMENTAL_CASE_ru: case_str = "твор"; break; case SolarixGrammarEngineNET.GrammarEngineAPI.GENITIVE_CASE_ru: case_str = "род"; break; case SolarixGrammarEngineNET.GrammarEngineAPI.ACCUSATIVE_CASE_ru: case_str = "вин"; break; case SolarixGrammarEngineNET.GrammarEngineAPI.DATIVE_CASE_ru: case_str = "дат"; break; } res = string.Format("Прил_{0}", case_str); } else if (c1 == SolarixGrammarEngineNET.GrammarEngineAPI.ADVERB_ru) { res = string.Format("Наречие_{0}", node.GetWord()); } else if (c1 == SolarixGrammarEngineNET.GrammarEngineAPI.PREPOS_ru) { res = string.Format("Предлог_{0}", node.GetWord()); } else if (c1 == SolarixGrammarEngineNET.GrammarEngineAPI.PARTICLE_ru) { res = string.Format("Частица_{0}", node.GetWord()); } else if (c1 == SolarixGrammarEngineNET.GrammarEngineAPI.INFINITIVE_ru) { res = string.Format("Инф_{0}", node.GetWord()); } else if (c1 == SolarixGrammarEngineNET.GrammarEngineAPI.PUNCTUATION_class) { res = string.Empty; } else if (c1 == SolarixGrammarEngineNET.GrammarEngineAPI.CONJ_ru) { res = string.Empty; } else { res = string.Empty; } return(res); }
public string GetContextPoint(SolarixGrammarEngineNET.GrammarEngine2 gren) { return(string.Format("[\"{0}\"{{class:{1}}}]", word, gren.GetClassName(gren.GetEntryClass(id_entry)))); }
public TokenTagsEnumerator(bool IsBoundaryToken, SolarixGrammarEngineNET.SyntaxTreeNode _token, SolarixGrammarEngineNET.GrammarEngine2 gren) { token = _token; list = new List <TokenRecognizer>(); int id_entry = token.GetEntryID(); int id_class = gren.GetEntryClass(id_entry); // Подготовим список измерений и атрибутов. List <SolarixGrammarEngineNET.CoordPair> dims = new List <SolarixGrammarEngineNET.CoordPair>(); List <SolarixGrammarEngineNET.CoordPair> attrs = new List <SolarixGrammarEngineNET.CoordPair>(); List <SolarixGrammarEngineNET.CoordPair> pairs = token.GetPairs(); foreach (SolarixGrammarEngineNET.CoordPair p in pairs) { int t = gren.GetCoordType(id_class, p.CoordID); if (t == 0 || t == 2) { attrs.Add(p); } else if (t == 1) { dims.Add(p); } } // ------------------------------------------------------ // Часть речи - самый общий случай // ------------------------------------------------------ TokenRecognizer tr4 = new TokenRecognizer(id_class, -1); list.Add(tr4); List <TokenRecognizer> more_abstract = new List <TokenRecognizer>(); more_abstract.Add(tr4); // ------------------------------------------------------ // Часть речи и комбинации атрибутов // ------------------------------------------------------ if (attrs.Count > 0) { List <TokenRecognizer> created_recognizers = new List <TokenRecognizer>(); bool[] dim_bit = new bool[attrs.Count]; for (int i = 0; i < attrs.Count; ++i) { dim_bit[i] = false; } while (true) { List <SolarixGrammarEngineNET.CoordPair> selected_pairs = new List <SolarixGrammarEngineNET.CoordPair>(); for (int i = 0; i < attrs.Count; ++i) { if (dim_bit[i]) { selected_pairs.Add(attrs[i]); } } if (selected_pairs.Count > 0) { TokenRecognizer tr3 = new TokenRecognizer(id_class, -1, selected_pairs); tr3.SetMoreAbstract(more_abstract); list.Add(tr3); created_recognizers.Add(tr3); } // Следующая комбинация int carry = 1; for (int ibit = dim_bit.Length - 1; ibit >= 0; --ibit) { if (dim_bit[ibit] == false) { dim_bit[ibit] = true; carry = 0; break; } else { dim_bit[ibit] = false; } } if (carry == 1) { break; } } more_abstract = created_recognizers; } // Лемма - только id словарной статьи. Это боее частный случай, чем указание части речи. TokenRecognizer tr2 = new TokenRecognizer(-1, id_entry); tr2.SetMoreAbstract(more_abstract); list.Add(tr2); more_abstract = new List <TokenRecognizer>(); more_abstract.Add(tr2); if (dims.Count > 0) { List <TokenRecognizer> created_recognizers = new List <TokenRecognizer>(); // ----------------------------------------------------------------------- // Лемма (то есть id словарной статьи) и различные комбинации измерений. // ----------------------------------------------------------------------- bool[] dim_bit = new bool[dims.Count]; for (int i = 0; i < dims.Count; ++i) { dim_bit[i] = false; } while (true) { List <SolarixGrammarEngineNET.CoordPair> selected_pairs = new List <SolarixGrammarEngineNET.CoordPair>(); for (int i = 0; i < dims.Count; ++i) { if (dim_bit[i]) { selected_pairs.Add(dims[i]); } } if (selected_pairs.Count > 0) { TokenRecognizer tr5 = new TokenRecognizer(-1, id_entry, selected_pairs); tr5.SetMoreAbstract(more_abstract); created_recognizers.Add(tr5); list.Add(tr5); } // Следующая комбинация int carry = 1; for (int ibit = dim_bit.Length - 1; ibit >= 0; --ibit) { if (dim_bit[ibit] == false) { dim_bit[ibit] = true; carry = 0; break; } else { dim_bit[ibit] = false; } } if (carry == 1) { break; } } more_abstract = created_recognizers; } // ---------------------------------- // Лексема - самый частный случай. // ---------------------------------- /* * if( !IsBoundaryToken ) * { * TokenRecognizer tr0 = new TokenRecognizer( token.GetWord() ); * tr0.SetMoreAbstract( more_abstract ); * list.Add( tr0 ); * } */ return; }
public static bool IsPartOfSpeech(this SolarixGrammarEngineNET.SyntaxTreeNode node, SolarixGrammarEngineNET.GrammarEngine2 gren, int part_of_speech) { int p = gren.GetEntryClass(node.GetEntryID()); return(p == part_of_speech); }
public bool Match(SolarixGrammarEngineNET.SyntaxTreeNode token, SolarixGrammarEngineNET.GrammarEngine2 gren) { if (lexeme != null) { return(token.GetWord().Equals(lexeme, StringComparison.InvariantCultureIgnoreCase)); } if (id_lemma != null) { for (int iver = 0; iver < token.VersionCount(); ++iver) { int ekey = token.GetVersionEntryID(iver); if (id_lemma.Contains(ekey)) { return(true); } } return(false); } if (pos != null) { bool pos_matched = false; for (int iver = 0; iver < token.VersionCount(); ++iver) { int ekey = token.GetVersionEntryID(iver); if (ekey != -1) { int id_class = gren.GetEntryClass(ekey); pos_matched = pos.Contains(id_class); if (pos_matched) { break; } } } if (!pos_matched) { return(false); } } if (pairs != null && pairs.Count > 0) { bool a_version_matched = false; for (int iver = 0; iver < token.VersionCount(); ++iver) { bool ver_ok = true; foreach (SolarixGrammarEngineNET.CoordPair p in pairs) { if (!token.VersionContains(iver, p)) { ver_ok = false; break; } } if (ver_ok) { a_version_matched = true; break; } } return(a_version_matched); } return(true); }
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 void ProcessTree(SolarixGrammarEngineNET.SyntaxTreeNode node, SolarixGrammarEngineNET.GrammarEngine2 gren) { int p_ekey = node.GetEntryID(); int id_class = gren.GetEntryClass(p_ekey); if ( id_class == SolarixGrammarEngineNET.GrammarEngineAPI.NOUN_ru || id_class == SolarixGrammarEngineNET.GrammarEngineAPI.PRONOUN2_ru || id_class == SolarixGrammarEngineNET.GrammarEngineAPI.PRONOUN_ru ) { SetLabel(node, string.Format("NP:{0}", chunk_num++), true); for (int ileaf = 0; ileaf < node.leafs.Count; ++ileaf) { SolarixGrammarEngineNET.SyntaxTreeNode leaf = node.leafs[ileaf]; if ( node.GetLinkType(ileaf) == SolarixGrammarEngineNET.GrammarEngineAPI.RIGHT_GENITIVE_OBJECT_link || node.GetLinkType(ileaf) == SolarixGrammarEngineNET.GrammarEngineAPI.OBJECT_link ) { SetLabel(leaf, string.Format("NP:{0}", chunk_num++), true); } } } else if (id_class == SolarixGrammarEngineNET.GrammarEngineAPI.PREPOS_ru) { SetLabel(node, string.Format("PN:{0}", chunk_num++), true); for (int ileaf = 0; ileaf < node.leafs.Count; ++ileaf) { SolarixGrammarEngineNET.SyntaxTreeNode leaf = node.leafs[ileaf]; int p_ekey2 = leaf.GetEntryID(); int id_class2 = gren.GetEntryClass(p_ekey2); if ( id_class2 == SolarixGrammarEngineNET.GrammarEngineAPI.NOUN_ru || id_class2 == SolarixGrammarEngineNET.GrammarEngineAPI.ADJ_ru || id_class2 == SolarixGrammarEngineNET.GrammarEngineAPI.PRONOUN_ru || id_class2 == SolarixGrammarEngineNET.GrammarEngineAPI.PRONOUN2_ru || id_class2 == SolarixGrammarEngineNET.GrammarEngineAPI.NUMBER_ru ) { SetLabel(leaf, string.Format("NP:{0}", chunk_num++), true); } } } else if ( id_class == SolarixGrammarEngineNET.GrammarEngineAPI.IMPERSONAL_VERB_ru || id_class == SolarixGrammarEngineNET.GrammarEngineAPI.VERB_ru || id_class == SolarixGrammarEngineNET.GrammarEngineAPI.INFINITIVE_ru ) { SetLabel(node, string.Format("VP:{0}", chunk_num++), true); SetLabel(node, string.Format("VX:{0}", chunk_num++), false); // корневой глагол отмечаем как VX for (int ileaf = 0; ileaf < node.leafs.Count; ++ileaf) { SolarixGrammarEngineNET.SyntaxTreeNode leaf = node.leafs[ileaf]; if (node.GetLinkType(ileaf) == SolarixGrammarEngineNET.GrammarEngineAPI.SUBJECT_link) { SetLabel(leaf, string.Format("NP:{0}", chunk_num++), true); } else if (node.GetLinkType(ileaf) == SolarixGrammarEngineNET.GrammarEngineAPI.OBJECT_link) { SetLabel(leaf, string.Format("NP:{0}", chunk_num++), true); } } } for (int ileaf = 0; ileaf < node.leafs.Count; ++ileaf) { SolarixGrammarEngineNET.SyntaxTreeNode leaf = node.leafs[ileaf]; ProcessTree(leaf, gren); } return; }
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); }