public FindPartOfSpeech ( string PartOfSpeechName ) : int | ||
PartOfSpeechName | string | |
return | int |
static void Main(string[] args) { string parsed_sentences = @"F:\Corpus\parsing\ru\SENT4.parsing.txt"; string result_path = @"f:\tmp\negative3.dat"; string dict_path = @"e:\MVoice\lem\bin-windows64\dictionary.xml"; // Загрузим морфологический словарь, он нам понадобится для смены падежей слов. SolarixGrammarEngineNET.GrammarEngine2 gren = new SolarixGrammarEngineNET.GrammarEngine2(); gren.Load(dict_path, true); string[] files = null; if (System.IO.Directory.Exists(parsed_sentences)) { files = System.IO.Directory.GetFiles(parsed_sentences, "*.parsing.txt"); } else { files = new string[1] { parsed_sentences } }; List <TreeTemplate> templates = new List <TreeTemplate>(); templates.Add(new TreeTemplate("[class:ГЛАГОЛ]( <PREPOS_ADJUNCT>[class:ПРЕДЛОГ].<OBJECT>[class:МЕСТОИМЕНИЕ,СУЩЕСТВИТЕЛЬНОЕ,ПРИЛАГАТЕЛЬНОЕ] )")); sample_count = 0; using (wrt = new System.IO.StreamWriter(result_path)) { foreach (string file in files) { Console.WriteLine("Processing {0}...", file); using (Sentences src = new Sentences(file)) { while (src.Next()) { Sentence sent = src.GetFetched(); if (sent.root != null) { #region AdjNounAdjNoun for (int i1 = 0; i1 < sent.Tokens.Count; ++i1) { if (sent.Tokens[i1].part_of_speech == "СУЩЕСТВИТЕЛЬНОЕ") { SNode node1 = sent.Nodes.Where(z => z.index == i1).First(); if (node1.edge_types.Count > 0) { int edge1 = -1; for (int j1 = 0; j1 < node1.edge_types.Count; ++j1) { if (node1.edge_types[j1] == "ATTRIBUTE") { if (sent.Tokens[node1.children[j1].index].part_of_speech == "ПРИЛАГАТЕЛЬНОЕ") { edge1 = j1; break; } } } if (edge1 != -1) { // Нашли первое существительное с атрибутирующим прилагательным. int noun_ie1 = gren.FindEntry(sent.Tokens[i1].word, gren.FindPartOfSpeech(sent.Tokens[i1].part_of_speech)); SToken adj1 = sent.Tokens[node1.children[edge1].index]; adj1.word = adj1.word.ToLower(); for (int i2 = i1 + 2; i2 < sent.Tokens.Count; ++i2) { if (sent.Tokens[i2].part_of_speech == "СУЩЕСТВИТЕЛЬНОЕ") { int noun_ie2 = gren.FindEntry(sent.Tokens[i2].word, gren.FindPartOfSpeech(sent.Tokens[i2].part_of_speech)); if (noun_ie1 != noun_ie2) { int gender1 = gren.GetEntryAttrState(noun_ie1, SolarixGrammarEngineNET.GrammarEngineAPI.GENDER_ru); int gender2 = gren.GetEntryAttrState(noun_ie2, SolarixGrammarEngineNET.GrammarEngineAPI.GENDER_ru); if (gender1 == gender2) { string number1 = sent.Tokens[i1].tags.Where(z => z.StartsWith("ЧИСЛО:")).First().Split(':')[1]; string number2 = sent.Tokens[i2].tags.Where(z => z.StartsWith("ЧИСЛО:")).First().Split(':')[1]; if (number1 == number2) { SNode node2 = sent.Nodes.Where(z => z.index == i2).First(); if (node2.edge_types.Count > 0) { int edge2 = -1; for (int j2 = 0; j2 < node2.edge_types.Count; ++j2) { if (node2.edge_types[j2] == "ATTRIBUTE") { if (sent.Tokens[node2.children[j2].index].part_of_speech == "ПРИЛАГАТЕЛЬНОЕ") { edge2 = j2; break; } } } if (edge2 != -1) { // Нашли второе существительное с атрибутирующим прилагательным. SToken adj2 = sent.Tokens[node2.children[edge2].index]; adj2.word = adj2.word.ToLower(); // Сгенерируем предложение, в котором эти прилагательные поменяны местами. List <SToken> tokens2 = new List <SToken>(); foreach (SToken t in sent.Tokens) { if (t.index == adj1.index) { tokens2.Add(adj2); } else if (t.index == adj2.index) { tokens2.Add(adj1); } else { tokens2.Add(t); } } StoreSample(sent, tokens2); } else { // у второго существительного нет атрибутирующего прилагательного. // перенесем прилагательное от первого ко второму существительному. List <SToken> tokens2 = new List <SToken>(); foreach (SToken t in sent.Tokens) { if (t.index == adj1.index) { continue; } else if (t.index == i2) { tokens2.Add(adj1); tokens2.Add(sent.Tokens[i2]); } else { tokens2.Add(t); } } StoreSample(sent, tokens2); } } } } } } } } } } } #endregion AdjNounAdjNoun #region NounNoun // Ищем два существительных, связанных в конструкцию родительного дополнения: // "восход солнца" // Генерируем предложение с перестановкой слов и сменой падежей: // "солнце восхода" foreach (SNode n1 in sent.Nodes) { SToken t1 = sent.Tokens[n1.index]; // восход if (t1.part_of_speech == "СУЩЕСТВИТЕЛЬНОЕ") { if (n1.children.Count > 0) { int gen_edge_index = n1.edge_types.IndexOf("RIGHT_GENITIVE_OBJECT"); if (gen_edge_index != -1) { SToken t2 = sent.Tokens[n1.children[gen_edge_index].index]; // солнца if (gen_edge_index != -1 && t2.part_of_speech == "СУЩЕСТВИТЕЛЬНОЕ") { List <SToken> tokens2 = new List <SToken>(); bool t12_ok = true; foreach (SToken t in sent.Tokens) { if (t.index == t1.index) { // сюда вставляем слово "солнца" и меняем его падеж на падеж слова t string t_case = t.tags.Where(z => z.StartsWith("ПАДЕЖ:")).First().Split(':')[1]; string t_number = t2.tags.Where(z => z.StartsWith("ЧИСЛО:")).First().Split(':')[1]; int ie_t2 = gren.FindEntry(t2.lemma, gren.FindPartOfSpeech(t2.part_of_speech)); if (ie_t2 != -1) { List <int> coords = new List <int>(); List <int> states = new List <int>(); coords.Add(SolarixGrammarEngineNET.GrammarEngineAPI.CASE_ru); states.Add(gren.FindState(SolarixGrammarEngineNET.GrammarEngineAPI.CASE_ru, t_case)); coords.Add(SolarixGrammarEngineNET.GrammarEngineAPI.NUMBER_ru); states.Add(gren.FindState(SolarixGrammarEngineNET.GrammarEngineAPI.NUMBER_ru, t_number)); List <string> forms = gren.GenerateWordforms(ie_t2, coords, states); if (forms.Count > 0) { string new_word = gren.RestoreCasing(ie_t2, forms[0]); SToken new_t = new SToken(); new_t.index = t.index; new_t.word = new_word; new_t.lemma = t.lemma; new_t.part_of_speech = t1.part_of_speech; tokens2.Add(new_t); } else { t12_ok = false; } } else { t12_ok = false; } } else if (t.index == t2.index) { // сюда вставляем слово "восход" и меняем его падеж на родительный string t_number = t1.tags.Where(z => z.StartsWith("ЧИСЛО:")).First().Split(':')[1]; int ie_t1 = gren.FindEntry(t1.lemma, gren.FindPartOfSpeech(t1.part_of_speech)); if (ie_t1 != -1) { List <int> coords = new List <int>(); List <int> states = new List <int>(); coords.Add(SolarixGrammarEngineNET.GrammarEngineAPI.CASE_ru); states.Add(SolarixGrammarEngineNET.GrammarEngineAPI.GENITIVE_CASE_ru); coords.Add(SolarixGrammarEngineNET.GrammarEngineAPI.NUMBER_ru); states.Add(gren.FindState(SolarixGrammarEngineNET.GrammarEngineAPI.NUMBER_ru, t_number)); List <string> forms = gren.GenerateWordforms(ie_t1, coords, states); if (forms.Count > 0) { string new_word = gren.RestoreCasing(ie_t1, forms[0]); SToken new_t = new SToken(); new_t.index = t.index; new_t.word = new_word; new_t.lemma = t.lemma; new_t.part_of_speech = t.part_of_speech; tokens2.Add(new_t); } else { t12_ok = false; } } else { t12_ok = false; } } else { tokens2.Add(t); } } if (t12_ok) { StoreSample(sent, tokens2); } } } } } } #endregion NounNoun #region PrepObject // Ищем предлог. foreach (SToken token_prepos in sent.Tokens) { if (token_prepos.part_of_speech == "ПРЕДЛОГ") { // Нашли предлог. Теперь перенесем его в другую позицию. List <Tuple <SToken, float> > tokens2 = sent.Tokens.Where(z => z.index != token_prepos.index).Select(z => new Tuple <SToken, float>(z, z.index)).ToList(); foreach (var t2 in tokens2.Where(z => z.Item1.index != token_prepos.index + 1)) { // Ставим предлог в позицию ПЕРЕД токеном t2 и генерируем предложение. List <Tuple <SToken, float> > tokens3 = new List <Tuple <SToken, float> >(); tokens3.AddRange(tokens2); tokens3.Add(new Tuple <SToken, float>(token_prepos, t2.Item2 - 0.5f)); StoreSample(sent, tokens3.OrderBy(z => z.Item2).Select(z => z.Item1).ToList()); } } } #endregion PrepObject /* * foreach (TreeTemplate t in templates) * { * if (t.Match(sent)) * { * } * } */ } } } } } Console.WriteLine("\nsample_count={0}", sample_count); return; } }
static void Main(string[] args) { string parsed_sentences = @"F:\Corpus\parsing\ru\SENT4.parsing.txt"; string result_path = @"f:\tmp\negative3.dat"; string dict_path = @"e:\MVoice\lem\bin-windows64\dictionary.xml"; // Загрузим морфологический словарь, он нам понадобится для смены падежей слов. SolarixGrammarEngineNET.GrammarEngine2 gren = new SolarixGrammarEngineNET.GrammarEngine2(); gren.Load(dict_path, true); string[] files = null; if (System.IO.Directory.Exists(parsed_sentences)) files = System.IO.Directory.GetFiles(parsed_sentences, "*.parsing.txt"); else files = new string[1] { parsed_sentences }; List<TreeTemplate> templates = new List<TreeTemplate>(); templates.Add(new TreeTemplate("[class:ГЛАГОЛ]( <PREPOS_ADJUNCT>[class:ПРЕДЛОГ].<OBJECT>[class:МЕСТОИМЕНИЕ,СУЩЕСТВИТЕЛЬНОЕ,ПРИЛАГАТЕЛЬНОЕ] )")); sample_count = 0; using (wrt = new System.IO.StreamWriter(result_path)) { foreach (string file in files) { Console.WriteLine("Processing {0}...", file); using (Sentences src = new Sentences(file)) { while (src.Next()) { Sentence sent = src.GetFetched(); if (sent.root != null) { #region AdjNounAdjNoun for (int i1 = 0; i1 < sent.Tokens.Count; ++i1) { if (sent.Tokens[i1].part_of_speech == "СУЩЕСТВИТЕЛЬНОЕ") { SNode node1 = sent.Nodes.Where(z => z.index == i1).First(); if (node1.edge_types.Count > 0) { int edge1 = -1; for (int j1 = 0; j1 < node1.edge_types.Count; ++j1) { if (node1.edge_types[j1] == "ATTRIBUTE") { if (sent.Tokens[node1.children[j1].index].part_of_speech == "ПРИЛАГАТЕЛЬНОЕ") { edge1 = j1; break; } } } if (edge1 != -1) { // Нашли первое существительное с атрибутирующим прилагательным. int noun_ie1 = gren.FindEntry(sent.Tokens[i1].word, gren.FindPartOfSpeech(sent.Tokens[i1].part_of_speech)); SToken adj1 = sent.Tokens[node1.children[edge1].index]; adj1.word = adj1.word.ToLower(); for (int i2 = i1 + 2; i2 < sent.Tokens.Count; ++i2) { if (sent.Tokens[i2].part_of_speech == "СУЩЕСТВИТЕЛЬНОЕ") { int noun_ie2 = gren.FindEntry(sent.Tokens[i2].word, gren.FindPartOfSpeech(sent.Tokens[i2].part_of_speech)); if (noun_ie1 != noun_ie2) { int gender1 = gren.GetEntryAttrState(noun_ie1, SolarixGrammarEngineNET.GrammarEngineAPI.GENDER_ru); int gender2 = gren.GetEntryAttrState(noun_ie2, SolarixGrammarEngineNET.GrammarEngineAPI.GENDER_ru); if (gender1 == gender2) { string number1 = sent.Tokens[i1].tags.Where(z => z.StartsWith("ЧИСЛО:")).First().Split(':')[1]; string number2 = sent.Tokens[i2].tags.Where(z => z.StartsWith("ЧИСЛО:")).First().Split(':')[1]; if (number1 == number2) { SNode node2 = sent.Nodes.Where(z => z.index == i2).First(); if (node2.edge_types.Count > 0) { int edge2 = -1; for (int j2 = 0; j2 < node2.edge_types.Count; ++j2) { if (node2.edge_types[j2] == "ATTRIBUTE") { if (sent.Tokens[node2.children[j2].index].part_of_speech == "ПРИЛАГАТЕЛЬНОЕ") { edge2 = j2; break; } } } if (edge2 != -1) { // Нашли второе существительное с атрибутирующим прилагательным. SToken adj2 = sent.Tokens[node2.children[edge2].index]; adj2.word = adj2.word.ToLower(); // Сгенерируем предложение, в котором эти прилагательные поменяны местами. List<SToken> tokens2 = new List<SToken>(); foreach (SToken t in sent.Tokens) { if (t.index == adj1.index) { tokens2.Add(adj2); } else if (t.index == adj2.index) { tokens2.Add(adj1); } else { tokens2.Add(t); } } StoreSample(sent, tokens2); } else { // у второго существительного нет атрибутирующего прилагательного. // перенесем прилагательное от первого ко второму существительному. List<SToken> tokens2 = new List<SToken>(); foreach (SToken t in sent.Tokens) { if (t.index == adj1.index) { continue; } else if (t.index == i2) { tokens2.Add(adj1); tokens2.Add(sent.Tokens[i2]); } else { tokens2.Add(t); } } StoreSample(sent, tokens2); } } } } } } } } } } } #endregion AdjNounAdjNoun #region NounNoun // Ищем два существительных, связанных в конструкцию родительного дополнения: // "восход солнца" // Генерируем предложение с перестановкой слов и сменой падежей: // "солнце восхода" foreach (SNode n1 in sent.Nodes) { SToken t1 = sent.Tokens[n1.index]; // восход if (t1.part_of_speech == "СУЩЕСТВИТЕЛЬНОЕ") { if (n1.children.Count > 0) { int gen_edge_index = n1.edge_types.IndexOf("RIGHT_GENITIVE_OBJECT"); if (gen_edge_index != -1) { SToken t2 = sent.Tokens[n1.children[gen_edge_index].index]; // солнца if (gen_edge_index != -1 && t2.part_of_speech == "СУЩЕСТВИТЕЛЬНОЕ") { List<SToken> tokens2 = new List<SToken>(); bool t12_ok = true; foreach (SToken t in sent.Tokens) { if (t.index == t1.index) { // сюда вставляем слово "солнца" и меняем его падеж на падеж слова t string t_case = t.tags.Where(z => z.StartsWith("ПАДЕЖ:")).First().Split(':')[1]; string t_number = t2.tags.Where(z => z.StartsWith("ЧИСЛО:")).First().Split(':')[1]; int ie_t2 = gren.FindEntry(t2.lemma, gren.FindPartOfSpeech(t2.part_of_speech)); if (ie_t2 != -1) { List<int> coords = new List<int>(); List<int> states = new List<int>(); coords.Add(SolarixGrammarEngineNET.GrammarEngineAPI.CASE_ru); states.Add(gren.FindState(SolarixGrammarEngineNET.GrammarEngineAPI.CASE_ru, t_case)); coords.Add(SolarixGrammarEngineNET.GrammarEngineAPI.NUMBER_ru); states.Add(gren.FindState(SolarixGrammarEngineNET.GrammarEngineAPI.NUMBER_ru, t_number)); List<string> forms = gren.GenerateWordforms(ie_t2, coords, states); if (forms.Count > 0) { string new_word = gren.RestoreCasing(ie_t2, forms[0]); SToken new_t = new SToken(); new_t.index = t.index; new_t.word = new_word; new_t.lemma = t.lemma; new_t.part_of_speech = t1.part_of_speech; tokens2.Add(new_t); } else { t12_ok = false; } } else { t12_ok = false; } } else if (t.index == t2.index) { // сюда вставляем слово "восход" и меняем его падеж на родительный string t_number = t1.tags.Where(z => z.StartsWith("ЧИСЛО:")).First().Split(':')[1]; int ie_t1 = gren.FindEntry(t1.lemma, gren.FindPartOfSpeech(t1.part_of_speech)); if (ie_t1 != -1) { List<int> coords = new List<int>(); List<int> states = new List<int>(); coords.Add(SolarixGrammarEngineNET.GrammarEngineAPI.CASE_ru); states.Add(SolarixGrammarEngineNET.GrammarEngineAPI.GENITIVE_CASE_ru); coords.Add(SolarixGrammarEngineNET.GrammarEngineAPI.NUMBER_ru); states.Add(gren.FindState(SolarixGrammarEngineNET.GrammarEngineAPI.NUMBER_ru, t_number)); List<string> forms = gren.GenerateWordforms(ie_t1, coords, states); if (forms.Count > 0) { string new_word = gren.RestoreCasing(ie_t1, forms[0]); SToken new_t = new SToken(); new_t.index = t.index; new_t.word = new_word; new_t.lemma = t.lemma; new_t.part_of_speech = t.part_of_speech; tokens2.Add(new_t); } else { t12_ok = false; } } else { t12_ok = false; } } else { tokens2.Add(t); } } if (t12_ok) { StoreSample(sent, tokens2); } } } } } } #endregion NounNoun #region PrepObject // Ищем предлог. foreach (SToken token_prepos in sent.Tokens) { if (token_prepos.part_of_speech == "ПРЕДЛОГ") { // Нашли предлог. Теперь перенесем его в другую позицию. List<Tuple<SToken, float>> tokens2 = sent.Tokens.Where(z => z.index != token_prepos.index).Select(z => new Tuple<SToken, float>(z, z.index)).ToList(); foreach (var t2 in tokens2.Where(z => z.Item1.index != token_prepos.index + 1)) { // Ставим предлог в позицию ПЕРЕД токеном t2 и генерируем предложение. List<Tuple<SToken, float>> tokens3 = new List<Tuple<SToken, float>>(); tokens3.AddRange(tokens2); tokens3.Add(new Tuple<SToken, float>(token_prepos, t2.Item2 - 0.5f)); StoreSample(sent, tokens3.OrderBy(z => z.Item2).Select(z => z.Item1).ToList()); } } } #endregion PrepObject /* foreach (TreeTemplate t in templates) { if (t.Match(sent)) { } } */ } } } } } Console.WriteLine("\nsample_count={0}", sample_count); return; }
public TagMatcher(string line, SolarixGrammarEngineNET.GrammarEngine2 gren) { source = line.Trim(); id = ++seq_id; string[] toks = source.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); foreach (string tok in toks) { if (tok[0] == '\'' && tok[tok.Length - 1] == '\'') { lexeme = tok.Substring(1, tok.Length - 2); } else if (tok[0] == '"' && tok[tok.Length - 1] == '"') { lexeme = tok.Substring(1, tok.Length - 2); } else { if (tok.IndexOf(':') == -1) { string pos_name = tok.Trim(); int id_class = gren.FindPartOfSpeech(pos_name); if (id_class != -1) { if (pos == null) { pos = new List <int>(); pos_names = new List <string>(); } pos.Add(id_class); pos_names.Add(pos_name); } else { int state = 1; string t = tok.Trim(); if (t.StartsWith("~")) { t = t.Substring(1); state = 0; } int id_coord = gren.FindCoord(t); if (id_coord == -1) { throw new ApplicationException(string.Format("Can not find coord [{0}]", tok)); } if (gren.CountCoordStates(id_coord) != 0) { throw new ApplicationException(string.Format("[{0}] is not bistable", tok)); } if (pairs == null) { pairs = new List <SolarixGrammarEngineNET.CoordPair>(); } SolarixGrammarEngineNET.CoordPair p; p.CoordID = id_coord; p.StateID = state; pairs.Add(p); } } else { string[] t3 = tok.Split(':'); string coord_name = t3[0].Trim(); string state_name = t3[1].Trim(); int id_class = gren.FindPartOfSpeech(coord_name); if (id_class != -1) { id_lemma = new List <int>(); entry_names = new List <string>(); pos_names = new List <string>(); pos_names.Add(coord_name); int ip = state_name.IndexOf('{'); string ename = state_name.Substring(0, ip); int ekey = gren.FindEntry(ename, id_class); if (ekey == -1) { throw new ApplicationException(string.Format("Can not find word entry {0}:{1}", coord_name, ename)); } id_lemma.Add(ekey); entry_names.Add(ename); if (entry_pos == null) { entry_pos = new List <int>(); } if (!entry_pos.Contains(id_class)) { entry_pos.Add(id_class); } } else { int id_coord = gren.FindCoord(coord_name); if (id_coord == -1) { throw new ApplicationException(string.Format("Can not find coord [{0}]", coord_name)); } int id_state = -1; if (gren.CountCoordStates(id_coord) == 0) { id_state = int.Parse(state_name); if (id_state < 0 || id_state > 1) { throw new ApplicationException(string.Format("Invalid state name {0} for bistable coord {1}", state_name, coord_name)); } } else { id_state = gren.FindState(id_coord, state_name); if (id_state == -1) { throw new ApplicationException(string.Format("Can not find state [{0}:{1}]", coord_name, state_name)); } } if (pairs == null) { pairs = new List <SolarixGrammarEngineNET.CoordPair>(); } SolarixGrammarEngineNET.CoordPair p; p.CoordID = id_coord; p.StateID = id_state; pairs.Add(p); } } } } }