[Из песочницы] Препроцессоры и метаязыки в программах исправления ошибок

Компьютерная лингвистика очень консервативна, несмотря на огромное количество уже созданных программ, решающих весьма сложные задачи предварительной обработки целенаправленных языков (подобные программы редко используются в программах проверки орфографии). Далее на примере общепринятого «сложного» случая корректировки «ться» и «тся» я попытаюсь показать, как «консерватизм» программистов приводит к специфическому классу ошибок.А. Реформатский, будучи весьма прозорливым лингвистом, писал, что существуют ошибки как результат неумелого преподавания в школе грамматики. Алпатов, человек язвительный, заметил, цитирую: «можно сказать, русская грамматика взяла за основу представления петербургских немцев о русском языке». Учитывая дефекты школьного преподавания и особенности психологии составителей грамматик, ться и тся остаются изгоями в компьютерных программах проверки орфографии.Видимо, своей мрачной славе эти случаи обязаны также тем, что в грамматиках жестко рекомендуют «проверять» правильность написания вопросами «что делать» и «что делает», исключая иные способы. Конечно, если поступать рекомендованным образом, никакая алгоритмизация и последующая корректировка невозможны. Остается только «анаграмматический подход» (когда на выходе программы мы получаем несколько вариантов «исправленного» слова). Видимо, отсюда попытка разделить С.А. Крыловым программы на пуристские и лаксистские.

«Зацикленность» программистов, работающих в команде с профессиональными лингвистами на разборе предложения очевидно связана с недостаточным пониманием лингвистами принципов программирования и «навязыванием» лингвистических представлений программистам. И здесь уважаемый С.А. Крылов демонстрирует подобное — см пост на известном форуме. Это лингвистический взгляд, но не взгляд программиста, для которого важными остаются вопросы иного плана: возможно ли алгоритмизировать грамматическое правило или алгоритмизация невозможна, следует использовать «словарный» подход для проверки слова.Правка ошибочного написания возвратных глаголов удивительно легка в 40% (и более) случаев, если отказаться от «что делает, что делать», а понимать возвратный глагол именно так, как следует, по значению: собственно возвратное; взаимно-возвратное; безобъектно-возвратное; общевозвратное & etc. В этом случае задача исправления слова сводится к а) «препроцессорной» обработке фразы, слова; б) создания простейшего метаязыка, позволяющего использовать некие описания для «правил», и этот метаязык будет похожим на классический потоковый редактор, то есть хорошо известный класс программ.

Итак, пусть «топливом» для «препроцессора» у нас будет массив из семи (или меньше) последних букв слов на тся и ться (для примера берем словарь Зализняка). Если взять большее число букв, то «точность» увеличится, это очевидно.Полученные данные мы разместим в массиве по принципу «елочка корнями в небо» — это оптимизирует и ускорит поиск, а также избавит от возможных ошибок (см. код).

Если кто-то рискнет повторить мой эксперимент со словарем Зализняка, то результат вряд ли удивит: в подобном массиве будет всего 3548 окончаний (т.е. семь или менее последних букв в слове), когда однозначно пишется ться или тся. Число окончаний, где возможно чередование «ться» / «тся» столь же мало — всего 407. Удивительно, правда? Ведь теперь достаточно «прогнать» через массивы проверяемое слово и мы на корню избавимся от неправильных написаний слов типа «кажетЬся», «придетЬся» и т.д. и пресловутых «анаграмм». (Для второго массива, когда возможны варианты написания, потребуется воспользоваться «метаязыком».)

Так выглядит массив «возможен только один вариант» (конечно, это несколько строк из 3548):

// «Елочка в небо«Для ться — до разделителя ошибочное написание, после — правильное.ящатся: ящатьсяяхатся: яхатьсяятатся: ятатьсяястся: ястьсяыстся: ыстьсяызтся: ызтьсяртся: ртьсяотся: отьсязтся: зться

Для тся — до разделителя ошибочное написание, после — правильное:

ящаються: ящаютсяящаеться: ящаетсяридеться: ридетсязеються: зеютсязееться: зеетсязвяться: звятсязвяться: рутсяоються: оютсяоеться: оетсяються: ются

//Массив для случаев, когда невозможно определить правильное написание (для тся, но очевидно, что для ться следует лишь вставить мягкий знак)

яшитсяячитсяячатсяушатсяучитсяслятсярщитсяоитсянятсянутсяятсяытсяутсястсяитсяетсяатся

Для примера — простой код, позволяющий искать совпадения в базах:

string correction_verbs (string str) { // Здесь нельзя использовать map, так как map автоматически сортирует массив vector < pair < string, string > >data; vector < pair < string, string > >:: iterator it; // Классы и функции настолько очевидны, что описывать их бессмысленно. file_operations file_io; // это просто класс для чтения из файлов в массив string_utilities str_ut; // это класс, где существует утилита replace_all string first_str, second_str, separator; // Получаем пути к файлам с данными и загружаем массив string verbs = global: file_paths.find («verbs_cfg»)→second; data = file_io.readf_vector_pair (verbs, separator);

for (it = data.begin (); it!= data.end (); ++it) { // Выводим графему после разделителя (может быть любым) и до разделителя first_str = it→first; // неправильное написание second_str = it→second; // правильное // Поиск совпадений в строке // Если найдено совпадение, то заменяем ться на тся (или наоборот) if (str.find (second_str) != string: npos) { str = str_ut.replace_all (str, second_str, first_str); // Прекращаем работу функции break; } } // Очищаем массив data.clear (); return str; } Несмотря на столь очевидное и часто используемое в программирование решение, например, при разборе искусственных языков, представленная на рынке лингвистическая программа Орфо (не самая неудачная, пожалуй, даже совершенная во многом) неспособна решить полноценно задачу ться/тся — у нее нет «препроцессора», вместо «препроцессора» используются все те же пресловутые анаграмматические алгоритмы «вычисления расстояний», с неизбежностью «заставляющие» Орфо предлагать какие-то безумные варианты правок.

Смотрим здесь: online.orfo.ruВводим фразу с ошибкой: «придеться исправить ошибку».На выходе получаем, как и ожидалось, следующий пассаж: приодеться, придется, приметься, продеться, прибиться.Выводы делайте сами.(Пожалуй, достойный пример того, как лингвисты «прогнули» программистов, получив на выходе неполноценное и безграмотное решение.)

Посмотрим на работу вышеописанного препроцессора. В переменной str у нас будет слово «придеться». В массиве будут только возвратные глаголы «с однозначным написанием». На выходе мы получаем (программа ищет совпадения по последним буквам, начиная с вершины массива) слово, где ридеться однозначно заменяется на ридется (см базы данных, иных вариантов не существует). Если программа не найдет в массиве совпадений, то функция вернет слово без изменений. Разумеется, далее следует произвести проверку в базе «ться» / «тся», применяя некий набор описаний. Но о «метаязыках» в подобных лингвистических программах я напишу в следующем посте, чтобы сообщение не получилось громоздким.

P.S. Безусловно, «препроцессорная» обработка имеет свои недостатки, но программа «мыслит по-человечески», а на выходе все-таки более вменяемый результат.

© Habrahabr.ru