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;
}
}