/* Выдает по парадигме прилагательного наречие, которое совпадает с краткой формой среднего рода этого прилагательного, например: "красивый" (ПРИЛ) -> "красиво" (НАР) "лучше" (ПРИЛ) -> "хорошо" (НАР) */ UINT CSemanticsHolder::GetAdverbWith_O_ByAdjective (UINT AdjParadigmId, string AdjWordForm) { string AdvLemma; CFormInfo Paradigm; try { if (!GetRusLemmatizer()->CreateParadigmFromID(AdjParadigmId, Paradigm)) return -1; } catch (...) { return -1; }; // ищем краткое прилагательное среднего рода long k=0; for (; k < Paradigm.GetCount(); k++) { string Form = Paradigm.GetWordForm(k); string AnCode = Paradigm.GetAncode(k); QWORD Grammems; BYTE POS; GetRusGramTab()->ProcessPOSAndGrammems(AnCode.c_str(), POS, Grammems ); if (( Grammems & _QM(rNeutrum)) && POS==ADJ_SHORT) break; }; if (k == Paradigm.GetCount()) return -1; AdvLemma = Paradigm.GetWordForm(k); return GetFirstParadigmId(morphRussian, AdvLemma, (1<<ADV)); };
bool CRusSentence::IsAdjDeclination (const CSynHomonym& H) const { if (!H.IsMorphNoun()) return false; if (H.m_strLemma.length() < 3) return false; if (H.m_lPradigmID == -1) return false; string suffix = H.m_strLemma.substr(H.m_strLemma.length()-2); bool bMasc = (suffix == "»…") || (suffix == "џ…"); bool bFem = (suffix == "јя") || (suffix == "яя"); if (!bMasc && !bFem) return false; CFormInfo Info; GetOpt()->GetLemmatizer()->CreateParadigmFromID(H.m_lPradigmID, Info); for (long k=0; k < Info.GetCount(); k++) { string Ancode = Info.GetAncode(k); QWORD g = GetRusGramTab()->GetAllGrammems(Ancode.c_str()); if ( g & _QM(rSingular) ) if ( g & _QM(rGenitiv) ) { string Form = Info.GetWordForm(k); int l = Form.length(); if (l < 3) return false; if (bMasc) return (Form.substr(l-3) == "≈√ќ") || (Form.substr(l-3) == "ќ√ќ"); else return (Form.substr(l-2) == "ќ…") || (Form.substr(l-2) == "≈…"); }; }; return false; };
int mymain(int argc, char **argv) { setlocale(LC_ALL, "Russian"); init_dicts(); //if (argc != 4) //{ // throw CExpc ("bad number of arguments"); //} /* читаем малый словарь, который состоит из пар слов отдельно на каждой строке типа "аббат abbot" считается, что если пара попала в этот словарь, то у этой пары хороший вес для перевода. Параллелльно считаем скорость морфологии7 */ std::cerr << "Opening small dictionary\t\t\t\r"; std::ifstream SmallDict("C:\\RML\\Dicts\\SrcBinDict\\shira.txt");//<<<<<CONST assert(SmallDict.is_open()); clock_t MorphTime = 0; while (true){ char buff[2048]; SmallDict.getline(buff, 2047); if (!SmallDict) break; /* на самом деле, здесь возможны словосочетания как с русской, так и с англ. стороны От словосочетания всегда берем только первое слово. */ StringTokenizer tok(buff, " \t"); StringVector vec; const char *word; while ((word = tok())) vec.push_back(word); std::string r, e; if (vec.size() < 2) continue; if (vec.size() == 2){ r = vec[0]; e = vec[1]; } else{ r = vec[0]; int i = 1; // проходим все русские слова while ((unsigned char)vec[i][0] > 128 && i < vec.size()) i++; if (i == vec.size() - 1) e = vec[i]; else continue; } // лемматизируем clock_t ltime1 = clock(); DwordVector r_id, e_id; MorphHolderRus.string_to_ids(r.c_str(), r_id, true); MorphHolderEng.string_to_ids(e.c_str(), e_id, true); clock_t ltime2 = clock(); MorphTime += ltime2 - ltime1; for (int R = 0; R < r_id.size(); R++) for (int E = 0; E < e_id.size(); E++) SmallDictSet.insert(std::make_pair(r_id[R], e_id[E])); } SmallDict.close(); std::cerr << "Done\t" << SmallDictSet.size() << "\t\t\t\n"; if (MorphTime > 0) { MorphTime /= CLOCKS_PER_SEC; if (MorphTime > 0) std::cerr << "Morphology of norm norm/second)\t" << double(SmallDictSet.size() * 2 / MorphTime) << "\t\t\t\n"; }; std::cerr << "Parsing aligned sentences\t\t\t\r"; const char *in_str = "C:\\RML\\Texts\\freq_hud.txt"; const char *out_str = "C:\\RML\\Dicts\\BinDict\\freq_hud.bin"; std::ifstream file_list(in_str); out.open(out_str, std::ios::binary); if (!out.is_open()) { std::cerr << "cannot open output file!" << out_str << std::endl; return -1; }; if (!file_list.is_open()) { std::cerr << "cannot open list-file !" << in_str << std::endl; return -1; }; while (true) { std::string file_name; std::string file; file_list >> file; file_name = "C:/RML/" + file; if (!file_list) break; std::ifstream in(file_name.c_str()); assert(in.is_open()); int sent_no = 0; while (true){ char buff[2][4096]; in.getline(buff[0], 4095); in.getline(buff[1], 4095); if (!in) break; const char *word; StringTokenizer r_tok(buff[0], " \t"); StringTokenizer e_tok(buff[1], " \t"); std::vector<CFormInfo> e_id, r_id; while ((word = r_tok())) { std::vector<CFormInfo> p; string w = word; if (MorphHolderRus.m_pLemmatizer->CreateParadigmCollection(false, w, false, false, p)) r_id.insert(r_id.end(), p.begin(), p.end()); } while ((word = e_tok())) { std::vector<CFormInfo> p; string w = word; if (MorphHolderEng.m_pLemmatizer->CreateParadigmCollection(false, w, false, false, p)) e_id.insert(e_id.end(), p.begin(), p.end()); } for (int r = 0; r < r_id.size(); r++) for (int e = 0; e < e_id.size(); e++) if (BinaryDictionary.HavePair(e_id[e].GetParadigmId(), r_id[r].GetParadigmId())) { word_map[word_pair(e_id[e].GetParadigmId(), r_id[r].GetParadigmId())]++; break; } } in.close(); } /* вычисляю максимальную частоту и увеличиваю частоту пары слов, которая была найдена в малом словаре */ long MaxFreq = 0; std::set<std::pair<long, long> > SmallDictUsed; std::map<word_pair, int>::iterator it = word_map.begin(); for (; it != word_map.end(); ++it) { if (SmallDictSet.count(std::make_pair(it->first.r, it->first.e))) { it->second *= 3; if (it->second < 6) it->second = 6; SmallDictUsed.insert(std::make_pair(it->first.r, it->first.e)); } if (it->second > MaxFreq) MaxFreq = it->second; }; // writting out file and dump int written = 0; std::cout << "Frequence of Pair\tRussian Lemma\tEnglish Lemma"; for (it = word_map.begin(); it != word_map.end(); ++it) { std::string rus = MorphHolderRus.id_to_string(it->first.r); std::string eng = MorphHolderEng.id_to_string(it->first.e); out.write((char*)&(it->first.e), sizeof(long)); out.write((char*)&(it->first.r), sizeof(long)); unsigned short freq = it->second; /* частота не должна превышать USHRT_MAX, поэтому нужно нормализовать частоту */ if (MaxFreq > USHRT_MAX) freq *= USHRT_MAX / MaxFreq; out.write((char*)&(freq), sizeof(unsigned short)); // выводим дамп std::cout << it->second << '\t' << rus.c_str() << '\t' << eng.c_str() << std::endl; written++; } /* проходим по малому словарю, если пара из этого словаря не была записана в выходной файл, пишем с частотой пять берутся только существительные, глаголы, прил. и нар, */ for (std::set<std::pair<long, long> >::iterator shira_it = SmallDictSet.begin(); shira_it != SmallDictSet.end(); ++shira_it) { if (SmallDictUsed.count(*shira_it)) continue; CFormInfo rp = MorphHolderRus.id_to_paradigm(shira_it->first); CFormInfo ep = MorphHolderEng.id_to_paradigm(shira_it->second); BYTE r_pos = MorphHolderRus.m_pGramTab->GetPartOfSpeech(rp.GetAncode(0).c_str()); BYTE e_pos = MorphHolderEng.m_pGramTab->GetPartOfSpeech(ep.GetAncode(0).c_str()); BYTE t_pos = 0xff; if (r_pos == NOUN && e_pos == eNOUN)t_pos = 0; if (r_pos == ADJ_FULL && e_pos == eADJ)t_pos = 2; if (r_pos == ADJ_SHORT && e_pos == eADJ)t_pos = 2; if (r_pos == ADV && e_pos == eADV)t_pos = 3; if (r_pos == PREDK && e_pos == eADV)t_pos = 3; if (r_pos == INFINITIVE && e_pos == eVERB)t_pos = 1; if (t_pos == 0xff) continue; long id = ep.GetParadigmId(); out.write((char*)&(id), sizeof(long)); id = rp.GetParadigmId(); out.write((char*)&(id), sizeof(long)); unsigned short freq = 5; out.write((char*)&(freq), sizeof(unsigned short)); std::string rus = MorphHolderRus.id_to_string(shira_it->first); std::string eng = MorphHolderEng.id_to_string(shira_it->second); if (!BinaryDictionary.HavePair(shira_it->second, shira_it->first)) { std::cerr << rus << " " << rp.GetAncode(0).c_str() << " " << eng; std::cerr << " " << ep.GetAncode(0).c_str() << " " << t_pos << " 0 0 0 0" << std::endl; } std::cout << 5 << '\t' << rus << '\t' << eng << std::endl; written++; } std::cerr << "Written " << written << "\t\t\t" << std::endl; out.close(); file_list.close(); return 0; }