static void Main(string[] args) { string result_folder = @"f:\tmp"; List <string> parsed_sentences = new List <string>(); int MAX_SAMPLE = int.MaxValue; int MAX_LEN = int.MaxValue; string dictionary_path = ""; string syntax_templates = ""; string[] filters = { "3" }; #region Command_Line_Options for (int i = 0; i < args.Length; ++i) { if (args[i] == "-parsing") { parsed_sentences.Add(args[i + 1]); i++; } else if (args[i] == "-dict") { dictionary_path = args[i + 1]; i++; } else if (args[i] == "-templates") { syntax_templates = args[i + 1]; i++; } else if (args[i] == "-output") { result_folder = args[i + 1]; i++; } else if (args[i] == "-max_samples") { MAX_SAMPLE = int.Parse(args[i + 1]); i++; } else if (args[i] == "-skip") { nb_skip = int.Parse(args[i + 1]); i++; } else if (args[i] == "-max_len") { MAX_LEN = int.Parse(args[i + 1]); i++; } else if (args[i] == "-filter") { filters = args[i + 1].Split(','); i++; } else { throw new ApplicationException(string.Format("Unknown option {0}", args[i])); } } #endregion Command_Line_Options preprocessor = new Preprocessor(); if (!string.IsNullOrEmpty(syntax_templates)) { syntax_checker.LoadTemplates(syntax_templates); } Console.WriteLine("Loading dictionary {0}", dictionary_path); SolarixGrammarEngineNET.GrammarEngine2 gren = new SolarixGrammarEngineNET.GrammarEngine2(); gren.Load(dictionary_path, true); // Файл для сохранения отобранных предложений-фактов. wrt_samples = new System.IO.StreamWriter(System.IO.Path.Combine(result_folder, "facts.txt")); // Предложения, которые не прошли детальную проверку синтаксической структуры wrt_skipped = new System.IO.StreamWriter(System.IO.Path.Combine(result_folder, "skipped.txt")); // Фильтр для предиката, с возможными значениями "3", "2s" и "1s" string filter_verb = filters.Where(z => "3 1s 2s".Split(' ').Contains(z)).FirstOrDefault(); // Фильтр типа предложения. Допустимые значение - пустое или "q" string filter_sent = (filters.Where(z => "q".Split(' ').Contains(z)).FirstOrDefault()) ?? ""; DateTime start_time = DateTime.Now; #region Processing_All_Files foreach (string mask in parsed_sentences) { string[] files = null; if (System.IO.Directory.Exists(mask)) { files = System.IO.Directory.GetFiles(mask, "*.parsing.txt"); } else if (mask.IndexOfAny("*?".ToCharArray()) != -1) { files = System.IO.Directory.GetFiles(System.IO.Path.GetDirectoryName(mask), System.IO.Path.GetFileName(mask)); } else { files = new string[1] { mask }; } Console.WriteLine("Number of parsing files={0}", files.Length); foreach (string file in files) { if (sample_count >= MAX_SAMPLE) { break; } Console.WriteLine("Processing {0}...", file); using (Sentences src = new Sentences(file)) { while (src.Next() && sample_count < MAX_SAMPLE) { Sentence sent = src.GetFetched(); sample_count++; if (sent.root == null) { continue; } if (sample_count > 0 && (sample_count % 10000) == 0) { Console.Write("{0} samples extracted\r", sample_count); } if (sample_count >= nb_skip) { //Console.WriteLine("DEBUG [{0}] {1}", sample_count, sent.GetText()); ProcessSentence(gren, sent, MAX_LEN, filter_verb, filter_sent); } } } } } #endregion Processing_All_Files wrt_samples.Close(); wrt_skipped.Close(); return; }
public PanelLoading() { InitializeComponent(); TBSentence.Text = Sentences.Next(); }
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; } }