<commit_before>\documentclass[12pt,a4paper,oneside]{extarticle}
\usepackage{fontspec,xltxtra,xcolor}
\usepackage{microtype}
\usepackage{polyglossia}
\usepackage[hidelinks]{hyperref}
\usepackage[top=0.75in, bottom=0.75in, left=0.75in, right=0.75in]{geometry}
\usepackage[style=gost-footnote,sortlocale=ru,natbib=true]{biblatex}
\setdefaultlanguage{russian}
\setotherlanguages{english,greek,churchslavonic} % set as "other" so English hyphenation active
\def\hyph{-\penalty0\hskip0pt\relax}

\defaultfontfeatures{Mapping=tex-text}
\setromanfont{Linux Libertine O}
\setsansfont{Linux Biolinum O}
\newfontfamily\churchslavonicfont[Script=Cyrillic,HyphenChar=_]{Ponomar Unicode}
\newfontfamily{\cyrillicfonttt}{Linux Libertine O}
\newfontfamily\greekfont[Script=Greek]{Old Standard}
\providecommand{\keywords}[1]{\textbf{Ключевые слова}: #1}

\bibliography{hyphenation}

\title{Автоматизация слогоделения и переноса строки в церковнославянских текстах}
\author{<NAME>\thanks{<NAME> -- магистр богословия, магистр экономических наук, аспирант кафедры Церковно-практических дисциплин Санкт-Петербургской духовной академии; \url{<EMAIL>}.} \and <NAME>\thanks{Добавить информацию о себе.}}
\date{\vspace{-1em}}  % hack to remove some wasted vertical blank space

\begin{document}
\clubpenalty=10000
\widowpenalty=10000
\interfootnotelinepenalty=0
\maketitle

\begin{abstract}
Решение проблемы автоматизации слогоделения и переноса строки
(\textenglish{hyphenation}) в системе \TeX{} было впервые предложено для английского языка в 1983~г.
Ф.~Льянгом. Однако до сих пор метод Льянга не применялись к
церковнославянским текстам. Тем не менее проблема
автоматизации переноса строки и слогоделения является актуальной при
верстки текстов, как в научных изданиях, так и в богослужебных книгах. В данной статье
формулируются правила переноса строки для церковнославянского языка и
предлагается автоматизированное решение, основанное на методе Льянга.
Авторы описывают процедуру разработки шаблонов переноса (\textenglish{hyphenation patterns})
и впервые предлагают методы оценки их эффективности.
\end{abstract}

\keywords{типографика, морфология, компьютерные алгоритмы, Юникод}

\section{Введение}

При наборе церковнославянского текста на компьютере, пользователь сталкивается с проблемой переноса строки. Необходимость переноса строки особенно актуальна при наборе богослужебных текстов, т.~к. богослужебные книги обычно форматируются с выравниванием по ширине (\textenglish{justified alignment}). В этом случае наличие сложных, многослоговых слов (которые нередко встречаются в церковнославянских текстах) приводит к нежелательному растягиванию пробелов между словами. Перенос строки помогает выравнять текст по ширине и сократить ширину пробелов. Перенос строки также актуален при наборе текстов в нескольких колонках и при отображении церковнославянских текстов на мобильных устройствах с ограниченным эффективным пространством экрана.

При современном типографском наборе, перенос строки обычно выполняется программой верстки текста автоматически, используя алгоритм переноса (\textenglish{hyphenation algorithm}). Алгоритм переноса зависит от языка текста и культурных особенностей (так, для американского и британского английского существуют разные правила переноса). Однако в современных программах верстки текста нет алгоритма переноса для церковнославянского языка. Очевидно, что пользователь не может просто применить алгоритм переноса для русского языка к церковнославянскому тексту, т.~к. церковнославянский язык имеет свой, отличный от русского языка набор букв и использует большое количество выносных диакритических знаков. Также, как мы покажем, правила переноса в церковнославянском языке несколько отличаются от правил современного русского языка. Ввиду отсутствия алгоритма переноса для церковнославянского языка, пользователь вынужден переносить текст вручную при наборе церковнославянского текста, что крайне трудоемко и приводит к неизбежным ошибкам. Мало того, современные пособия по грамматике церковнославянского языка не содержат даже описания правил переноса, что весьма затрудняет ручное решение  этой задачи.

В данной статье мы описываем правила переноса и слогоделения для современного церковнославянского языка, т.~е. языка <<синодального извода>>, который используется в богослужебных текстах Русской православной церкви со времени издания Елизаветинской Библии в 1751~г. Далее мы описываем пути решения проблемы автоматизации переноса строки для церковнославянских текстов на основании алгоритма переноса, разработанного для системы верстки текста \TeX{}. Авторами созданы соответствующие пакеты для \TeX{}, которые решают задачу автоматизированного переноса церковнославянских текстов. При этом авторы смогли не только создать необходимые шаблоны переносов, но и разработать и применить методы тестирования их эффективности, которые в данной статье описываются впервые. В статье предлагается краткая инструкция по использованию созданных нами пакетов. Следует отметить, что достигнутые нами результаты применимы не только в системе \TeX{}: на основании разработанных для \TeX{} шаблонов, мы также создали словарь церковнославянских переносов для популярной свободной программы LibreOffice.

\section{Правила слогоделения в церковнославянском языке}

Перенос строки в церковнославянском языке, как и в русском языке, должен происходить на границе слогов. Таким образом с задачей переноса непосредственно связана задача слогоделения в церковнославянском языке. Однако правила слогоделения подробно не описаны ни в одном учебном пособии по современному церковнославянскому языку. Лишь в некоторых учебниках приводятся упоминания, что перенос строки должен производиться по таким же правилам, как и в русском языке. В действительности, просмотрев издания Московской и Санкт-Петербургской синодальных типографий, а также издания Киево-Печерской лавры за 1840--1917~гг., можно прийти к выводу, что, с учетом ряда дополнительных требований, связанных с особенностями церковнославянской орфографии (напр., наличие выносных букв и диакритических знаков), перенос строки в церковнославянских текстах должен следовать правилам слогоделения для русского языка в дореформенной орфографии. Эти дореформенные правила, основанные на морфологическом разборе слов, подробно описаны в классическом пособии Я.~К. Грота <<Русское правописание>>\autocite[][]{grot1902}. Опираясь на указанные Я.~К. Гротом правила для русского языка, мы приводим правила слогоделения для церковнославянского языка.

\begin{table}[h]
\centering
\caption{Примеры морфологического разбора церковнославянских слов \label{one}}
\begin{tabular}{ll}
Правильно   	& 	Неправильно \\
\hline
\textchurchslavonic{свѣ́т-лый} & \textchurchslavonic{свѣ́-тлый} \\
\textchurchslavonic{грѣ́ш-ный} & \textchurchslavonic{грѣ́-шный} \\
\textchurchslavonic{же́н-скїй}	& \textchurchslavonic{же́-нскїй}, \textchurchslavonic{же́нс-кїй} \\
\textchurchslavonic{вѣст-во-ва́-нї-е} & \textchurchslavonic{вѣ-ство-ва́-нї-е} \\
\textchurchslavonic{дѣ́тель-ство-ва} &	\textchurchslavonic{дѣ́тельст-во-ва}, \textchurchslavonic{дѣ́тельс-тво-ва} \\
\hline
\end{tabular}
\end{table}

Для простых слов, следует сначала правильно выделить корень слова и отделить от корня суффиксы и окончания, как указано в примерах в Таблице~\ref{one}. Согласные внутри суффиксов не должны быть разделяемы. К примеру, не должны разделяться суффиксы \textchurchslavonic{-ство}, \textchurchslavonic{-скїй}. Если суффикс начинается с согласной, то он может переноситься на новую строку, как в словах: \textchurchslavonic{же́н-скїй}, \textchurchslavonic{за-блꙋ́жд-шихъ}, \textchurchslavonic{кро́т-кїй}, \textchurchslavonic{свѣ́т-лый}, \textchurchslavonic{се́рд-це}, \textchurchslavonic{скве́р-ный}, \textchurchslavonic{тѣ́с-ный} (но: \textchurchslavonic{при́-сный}), \textchurchslavonic{чис-ло̀} (но: \textchurchslavonic{ма́-сло}), \textchurchslavonic{мо-ли́-тва} (но: \textchurchslavonic{клѧ́т-ва}).

Группы согласных, стоящие вне суффикса (например, внутри корня слова) разделяются по следующему принципу. Если стечение согласных начинается с плавного (\textchurchslavonic{л}, \textchurchslavonic{р}), носового (\textchurchslavonic{н}, \textchurchslavonic{м}) или шипящего (\textchurchslavonic{ш}, \textchurchslavonic{щ}, \textchurchslavonic{ж}, \textchurchslavonic{ч}), то буква, записывающая такой звук, остается на строке, а следующие за ней слогласные, формирующие слог, переносятся: \textchurchslavonic{во́л-ны}, \textchurchslavonic{го́р-дость}, \textchurchslavonic{до́н-деже}, \textchurchslavonic{кам-па́нъ}, \textchurchslavonic{мы́ш-ца}, \textchurchslavonic{ѹ҆мерщ-вле́й}, \textchurchslavonic{лꙋ́ч-ше}. К носовым следует также относить комбинации согласных \textchurchslavonic{-гг-}, \textchurchslavonic{-гк-}, \textchurchslavonic{-гх-} в словах иностранного происхождения, в которых \textchurchslavonic{г}, в соотвествии с правилами греческого языка, читается как \textchurchslavonic{н}. Так мы имеем: \textchurchslavonic{а҆г-кѵ́-ра}, \textchurchslavonic{а҆гаѳаг-ге́лъ} (но: \textchurchslavonic{а҆-гге́й}), \textchurchslavonic{паг-ха́-рїй}); следует иметь ввиду, что иностранные слова могут быть разного происхождения, но в церковнославянский язык они вошли через греческий язык, и, по возможности, сохраняют греческое написание и произношение (напр., \textchurchslavonic{а҆́г-глїа}).

Если стечение согласных начинается с другого звука, например, с губных или зубных, то все согласные стечения переносятся на следующую строку, как в случаях \textchurchslavonic{сре-бро̀}, \textchurchslavonic{га-врїи́лъ}, \textchurchslavonic{є҆-фре́мъ}, \textchurchslavonic{не-пщева́ти}. В особенности не следует разделять согласные после \textchurchslavonic{с}: \textchurchslavonic{па́-сха} (неправильно: \textchurchslavonic{па́с-ха}), \textchurchslavonic{пе-ска̀} (а не \textchurchslavonic{пес-ка̀}), \textchurchslavonic{при́-снѡ}, \textchurchslavonic{го-спо́день}, но: \textchurchslavonic{чис-ло̀}. Также не следует разделять сочетания согласных, в которых происходит смягчение (палатализация): \textchurchslavonic{-мл-}, \textchurchslavonic{-бл-}, \textchurchslavonic{-вл-}, \textchurchslavonic{-пл-}, \textchurchslavonic{-жд-}: \textchurchslavonic{зе-млѧ̀}, \textchurchslavonic{до́-блїй}, \textchurchslavonic{и҆зба-вле́нїе} (но: \textchurchslavonic{і҆а́кѡв-лю}), \textchurchslavonic{ме-ждꙋ̀}.

Правильное разделение стечений согласных является самыми сложным нюансом при слогоделении в церковнославянских словах. В остальных случаях действуют достаточно простые правила, похожие на соответствующие правила в русском языке. Так согласная, стоящая между двумя гласными, начинает новый слог: \textchurchslavonic{мо-на́-си}, \textchurchslavonic{мо-лѧ́-ще}; две одинаковые согласные разделяются: \textchurchslavonic{а҆м-мꙋ́нъ}, \textchurchslavonic{а҆́н-на}, \textchurchslavonic{ва́с-са}; когда одна согласная отделена от другой согласной ерем, то слог начинается после еря: \textchurchslavonic{вель-мѝ}, \textchurchslavonic{де́нь-ги} (вообще, еры никогда не отделяются от предшествующих букв). Две стоящие подряд гласные разделяются за исключением диграфа \textchurchslavonic{ᲂу}, который никогда не разделяется, так как всегда читается как \emph{у}: \textchurchslavonic{а҆-а-рѡ́нъ}, \textchurchslavonic{кле-о́-па}, \textchurchslavonic{ѹ҆́-ме}. Следует иметь ввиду, что буква \textchurchslavonic{ѵ} в тех случаях, когда она читается как \textchurchslavonic{в}, не отделяется от предшествующей ей гласной, если за ней следует согласная: \textchurchslavonic{а҆́ѵ-гꙋстъ}, \textchurchslavonic{є҆ѵ-ге́-нїй} (но: \textchurchslavonic{ле-ѵі́тъ}, \textchurchslavonic{на-ѵи́нъ}). Согласно правилам, приведенным Я.~К. Гротом, в русском языке не разделяются стечения гласных, записывающие иностранные дифтонги (напр., следует писать \emph{туа-летъ}, а не \emph{ту-а-летъ}, от франц. \emph{toilette}), однако согласно правилам церковнославянского произношения, такие стечения гласных произносятся раздельно, а не как дифтонги, и соответственно должны быть разделяемы в церковнославянском языке: \textchurchslavonic{ѹ҆-а-лен-ті́нъ}.

Отдельные правила относятся к слогоделению сложных слов, т.~е. слов, состоящих из нескольких корней или из префикса (приставки) и корня. В этих случаях необходимо разделить слово по слогам так, чтобы сохранить структуру корней и префикса, т.~е. чтобы согласные, принадлежащие корню не были отнесены к префиксу, и наоборот. При этом разделение сложного слова на корни и префиксы может нарушать правила слогоделения для простых слов, указанные выше. Так следует писать: \textchurchslavonic{и҆с-кꙋ-пи́лъ}, \textchurchslavonic{и҆с-по-вѣ́-да-нї-е} (но \textchurchslavonic{и҆-скра̀}, \textchurchslavonic{и҆́-сти-на}); \textchurchslavonic{вос-кли́к-нꙋть} (но \textchurchslavonic{во-скре-се́-нї-е}); \textchurchslavonic{со-зва̀} (а не \textchurchslavonic{соз-ва̀}); \textchurchslavonic{под-но́-жї-е}, \textchurchslavonic{под-кло-ни́-ти} (но  \textchurchslavonic{по́-двигъ}, \textchurchslavonic{по-дра-жа́-ти}); \textchurchslavonic{по-зна̀}, \textchurchslavonic{по́-мнити}; \textchurchslavonic{рас-ка́-ѧ-нї-е}; наконец, \textchurchslavonic{без-ꙋ́м-ный}, \textchurchslavonic{раз-ꙋ́м-нѡ} (в этих случаях в церковнославянском языке часто сохраняется ер в конце префикса, напр. при написании \textchurchslavonic{без̾-ꙋ́м-ный}). Однако если после префикса выпала согласная, относящаяся к корню слова, то гласная, следующая за префиксом не может начинать слога; так следует переносить \textchurchslavonic{ѡ҆-би-та́-ти} (а не \textchurchslavonic{ѡ҆б-и-та́-ти}), \textchurchslavonic{и҆-зы́-де} (а не \textchurchslavonic{и҆з-ы́-де}).

Теперь перейдем к ряду правил, касающихся непосредственно церковнославянской орфографии. В первую очередь следует упомянуть о словах, в которых присутствуют сокращения с титлом или буквенным титлом. Естественно, что нельзя разделять внутри записанного под титлом сокращения, т.~е. нельзя писать \textchurchslavonic{а҆́г-г҃ли}, \textchurchslavonic{воскрⷭ҇-ный}. Обзор изданий церковнославянских богослужебных книг за 1840--1917~гг. показал, что разделение на слоги возможно только: при отделении префикса от сокращенного корня (напр., \textchurchslavonic{во-скрⷭ҇лъ}, \textchurchslavonic{все-чⷭ҇тно́-е}, \textchurchslavonic{пре-чтⷭ҇а-ѧ} и даже \textchurchslavonic{пре-чⷭ҇та-ѧ}); перед гласной, предшествующей сокращенному стечению (напр., \textchurchslavonic{а҆р-ха́гг҃лъ}, \textchurchslavonic{і҆-ерⷭ҇ли́мъ}; впрочем, исходя из правил, указанных Я.~К. Гротом, более правильно было бы писать \textchurchslavonic{а҆рх-а́гг҃лъ} с учетом греческого происхождения слова); или после гласной или еря, начинающих следующий за сокращенным стечением слог (\textchurchslavonic{млⷭ҇рдї-е}, \textchurchslavonic{а҆пⷭ҇ль-скїй}, \textchurchslavonic{мч҃ни-ка}; но \textchurchslavonic{мч҃нка}). Здесь действуют не только принципы морфологического деления слова, но и эстетические соображения.

В русском языке слог, состоящий из одной гласной, находящейся в начале или в конце слова, не может быть перенесен (так, неправильными были бы переносы в русских словах \emph{и-мя}, \emph{тво-ё}). Однако в церковнославянских текстах синодальной эпохи наблюдается перенос после слогов \textchurchslavonic{ѡ҆-}, \textchurchslavonic{ѿ-}, и \textchurchslavonic{ᲂу҆-}, находящихся в начале слова, ввиду того, что они являются префиксами. Так допускаются переносы \textchurchslavonic{ѡ҆-свѧще́нїе}, \textchurchslavonic{ѿ-вале́нъ}, \textchurchslavonic{ѹ҆-дивлѧ́ѧ}.  Другие однобуквенные слоги в начале слова не следует отделять и оставлять на предыдущей строке, равно как не следует переносить однобуквенный слог в конце слова (так, не следует переносить \textchurchslavonic{є҆-вре́и} или \textchurchslavonic{є҆вре́-и}).

\section{Разработка автоматизации слогоделения}

\subsection{Алгоритм слогоделения \TeX{}}

Проблема правильного переноса строки существует столько же, сколько и искусство печатного набора текста. О ней упоминается в первом пособии по типографике, \textenglish{Mechanick Exercises} Джозефа Моксона (1683~г.). С разработкой компьютерной типографики в середине XX~в. появляются и первые попытки автоматизированного решения проблемы переноса строки. Изначально были выявлены два возможных подхода: словарный и логический. При словарном подходе, все возможные слова, вместе с возможными переносами, сохраняются в списке слов; алгоритм выравнивания строки просматривает этот список и выбирает оптимальные переносы. Однако при ограничениях оперативной памяти и скорости процессора для компьютерных систем 60-х--70-х~гг. XX~в., такой подход являлся слишком медленным и неэффективным. С другой стороны был разработан логический подход, при котором описывались правила для возможных переносов исходя из морфологии и орфографии языка (напр., <<перенос разрешается между двумя гласными>>). На практике оказывается, что слишком трудно написать список всех таких правил, и что к ним все равно требуется достаточно пространный словарь исключений.

Уникальное решение проблемы автоматизации переноса строки предложил <NAME> в своей PhD диссертации\autocite[][]{liang1983}. Это решение, известное как <NAME>--Льянга, впоследствии стало стандартным в компьютерной типографике, и применяется не только в системе верстки текста \TeX{}, для которой оно было изначально разработано Льянгом, но и в других программах\autocite[Первое описание системы \TeX{} см. ][]{knuth1979}. Алгоритм Кнута--Льянга основан на идее шаблонов слогоделения (\textenglish{hyphenation pattern}). Каждый такой шаблон записывает последовательность символов (строку), предоставляющую какую-то информацию о возможном слогоделении. Нечетная цифра указывает на место возможного деления. К примеру, чтобы указать, что слогоделение возможно в английском языке перед суффиксом \emph{-tion}, записывает шаблон \verb+1tion+. Однако такие шаблоны могут выдавать ошибочные результаты, например шаблон \verb+1tion+ неправильно делит английское слово \emph{cat-ion}. Для таких исключений алгоритм вводит запрещающие шаблоны (\textenglish{inhibiting pattern}). Места запрета слогоделения в запрещающих шаблонах указаны четными цифрами. К примеру, для запрета слогоделения перед \emph{tion} в слове \emph{cation} можно ввести запрещающий шаблон \verb+ca2tion+. Но запрещающие шаблоны могут, в свою очередь, запретить вполне допустимые деления в других словах, так, шаблон \verb+ca2tion+ запретит перенос в слове \emph{ap-pli-ca-tion}. Для этого слова вводится разрешающий шаблон следующего уровня, например шаблон \verb+lica3tion+. При заданных шаблонах, для того, чтобы разделить слово на слоги, алгоритм разбивает данное слово на группы символов (\textenglish{character clusters}) и ищет соответствующие этим группам шаблоны, причем, если несколько шаблонов подходят к какой-то группе, выбирается шаблон с большей по величине цифрой. В итоге, места между группами, в которых стоит нечетная цифра, являются возможными местами разделения на слоги. В качестве примера, английскому слову \emph{hyphenation} подходят заданные шаблоны \verb+hy3ph+ \verb+he2n+ \verb+hena4+ \verb+hen5at+ \verb+1na+ \verb+n2at+ \verb+1tio+ \verb+2io+, которые в соединении дают результат \verb+hy3phe2n5a4t2ion+, соответствующий правильному слогоделению \emph{hy-phen-ation}\autocite[См. подробнее ][pp.~5--6, 35--40.]{liang1983}.

Следующим достижением Льянга было решение проблемы создания словаря шаблонов. Для автоматизации этой задачи, исследователь написал программу \verb+PATGEN+ (\emph{pattern generator} = генератор шаблонов), которая создает <<оптимальный>> перечень шаблонов из заданного словаря разделенных по слогам слов. Шаблоны подбираются итеративным подходом. Сначала программа просматривает словарь и выбирает разрешающие шаблоны. В последующих итерациях выбираются запрещающие, затем опять разрешающие, шаблоны, с учетом шаблонов, выбранных в предыдущих итерациях. Этот процесс продолжается, пока не будут учтены все возможные слогоделения в словаре. При этом нужен некий критерий для отбора возможных шаблонов. С учетом того, что любой шаблон может сделать некое количество правильных слогоделений (что обозначается переменной $good$) и некое количество ошибочных слогоделений (что обозначается переменной $bad$), его эффективность может быть расценена как $efficiency = good / (1 + bad)$. При той или иной итерации отбираются шаблоны, чья эффективность превышает некий заданный порог, что выражается формулой

\begin{equation}
\label{eff_formula}
good * good\_wt - bad * bad\_wt \geq threshold
\end{equation}

\noindent где параметры $good\_wt$ и $bad\_wt$ устанавливаются для каждой итерации. На самом деле, такой подход является не больше чем ловким эвристическим устройством. Параметры $good\_wt$, $bad\_wt$ и $threshold$ Формулы~\ref{eff_formula} для каждой итерации подбираются эмпирическим путем, основываясь на методе проб и ошибок, и за ними нет никакого теоретического обоснования, в чем признается Льянг\autocite[Ср.: <<We do not have any theoretical justification for these parameters; they just seem to work well>>.][p.~36]{liang1983}. Так как по построению, алгоритм генерирует все шаблоны, необходимые для того, чтобы правильно определить все указанные в заданном словаре слогоделения (для этого при последней итерации устанавливается $threshold = 1$ и $bad\_wt \rightarrow \infty$), единственным критерием, которым руководствуется разработчик шаблонов при выборе параметров является количество дискового пространства, которое занимает созданный словарь шаблонов. В своей диссертации Льянг не предлагает способов тестирования эффективности шаблонов и критериев выбора параметров.

\subsection{Применение Алгоритма Кнута--Льянга к другим языкам}

Алгоритм Кнута--Льянга был изначально предложен только для английского языка, который удобен тем, что записывается ограниченным количеством символов (26 букв латинской азбуки без диакритических знаков). Хотя алгоритм может быть применен к любому языку, в котором перенос строки основан на слогоделении и который записывается азбучным письмом, даже при попытке работать с другими западноевропейскими языками (напр., французским, немецким), пользователь встречается с тем ограничением, что программа \verb+PATGEN+, как собственно и вся система \TeX{}, не предназначена для работы с бо́льшим количеством символов. Впоследствии, возможности \TeX{} были расширены созданием дополнительных кодовых таблиц, позволяющих запись символов различных западноевропейских языков\autocite[Кодировка \textenglish{Extended \TeX{} Font Encoding Scheme} (ET). См. ][]{ferguson1990}, а также других систем письменности, включая кириллицу\autocite[Описание существующих кодировок см. ][]{mittelbach2016}. Так как одновременно возникла и проблема создания шаблонов переноса в этих кодировках, П.~Брейтенлохнер написал расширенную программу \verb+PATGEN2+\autocite[См. описание в пособии ][]{patgen2}, которая была успешно применена к созданию, например, шаблонов для древнегреческого языка\autocite[][]{haralambous1992}.

Однако подход с разработкой альтернативных 8-битных кодировок потерял свою актуальность с созданием стандарта Юникод -- единого стандарта кодирования символов всех систем письменности мира, который был предложен в 1991~г. и за последующее десятилетие стал общепринятым в компьютерных технологиях. Д.~Антош и  П.~Сойка разработали программу \verb+OPatGen+ ($\Omega$ \emph{pattern generator} т.~к. она изначально предполагалась для системы $\Omega$), которая поддерживает Юникод и позволяет работать с большими алфавитами, а также создает неограниченное количество шаблонов\autocite[][]{opatgen}. Хотя программа была использована для таких сложных задач, как автоматизация переносов в тайской письменности (в которой не используются пробелы между словами)\autocite[][]{sojka2003}, на данный момент она устарела и на современных компиляторах \verb!C/C++! более не поддерживается. Для разработки шаблонов для церковнославянского языка потребовалась новая программа, написанная на  высокоуровневом языке программирования. В этих целях <NAME> разработал программу \verb+pypatgen+ -- реализацию метода Льянга на языке \verb+Python+\footnote{Описание и инструкции по пользованию см. \url{https://github.com/pgmmpk/pypatgen}.} (Здесь можно поместить краткое описание возможностей и преимуществ \verb+pypatgen+).

\section{Создание шаблонов для церковнославянского языка}

Отметим, что при современных компьютерных технологиях, ограничения оперативной памяти и скорости процессора более не являются столь актуальными, как в 70-х~гг. XX~в. Однако метод Кнута--Льянга интересен тем, что даже работая с ограниченным словарем, мы имеем надежду, что созданные шаблоны смогут правильно угадать слогоделения и в тех словах, которые не вошли в первоначальный словарь. Таким образом при создании шаблонов для церковнославянского языка перед нами стоит несколько иная задача. Эффективным должен быть признан не только самый минимальный набор шаблонов, но такой набор шаблонов, который с большей точностью может быть применен к словам, не вошедшим в словарь, использованный для создания шаблонов. В этом подразделе мы опишем процедуру создания шаблонов используя программу \verb+pypatgen+, а в следующем разделе -- разработанный нами метод оценки эффективности шаблонов.

\subsection{Генерирование шаблонов}

Процедура создания шаблонов для \TeX{} происходит в следующей последовательности. Для начала был подготовлен словарь церковнославянских слов. В этих целях мы выбрали из словаря, содержащего все слова, встречающиеся в корпусе современных богослужебных текстов\footnote{Этот полный словарь содержит в совокупности $134.392$ слова.}, те, которые отвечают за 90\% случаев употребления слова. К этому списку слов были добавлены случайно выбранные имена собственные из перечня, помещенного в церковнославянском Требнике, а также технические термины (в основном, географические наименования), которые встречаются в церковнославянском разделе Общего хранилища данных о локалях (\textenglish{Common Locale Data Repository}, CLDR)\footnote{См. \url{http://cldr.unicode.org/}.}, и необходимые для локализации компьютерных программ. В итоге мы получили словарь, содержащий $17.525$ церковнославянских слов, которые затем были разбиты по слогам вручную, в соответствии с правилами, обозначенными выше.

Далее над этим словарем был запущен алгоритм генерирования шаблонов используя программу \verb+pypatgen+ (версия 0.2.9). Параметры $good\_wt$, $bad\_wt$ и $threshold$ Формулы~\ref{eff_formula} были установлены в соответствии с результатами процедуры оценки эффективности шаблонов, которая описывается в следующем разделе. В результате мы получили файл \verb+raw_patterns.txt+, содержащий сырые шаблоны и файл \verb+err_raw_patterns.txt+, содержащий исключения, т.~е. слова, которые не могут быть правильно разделены на слоги используя сгенерированные шаблоны. Эти исключения возникают в основном за счет того, что мы, в целях обобщения шаблонов, ограничиваем их длину (об этом также смотри в следующем разделе). Таким образом список исключений содержит много однокоренных слов с <<длинными>> корнями, равно как и слов с <<необычными>> суффиксами, к примеру:

\begin{center}
\begin{churchslavonic}
\begin{tabular}{l}
бо-лѣ́-зней \\
бо-лѣ́-знемъ \\
бо-лѣ́-знен-нѡ \\
бо-лѣ́-знен-ны-ѧ \\
бо-лѣ́-зни \\
\end{tabular}
\end{churchslavonic}
\end{center}

Такие слова могут быть заменены одним шаблоном (в данном случае, шаблоном \textchurchslavonic{.болѣ́7зн}), что было сделано вручную для всех слов в списке исключений. В результате мы получаем файл \verb+root_patterns.txt+, который содержит, в дополнение к сгенерированным <<кратким>> шаблонам, еще и перечень <<длинных>> шаблонов.

На следующем этапе нам необходимо добавить запрещающие шаблоны для случаев, где перенос абсолютно недопустим: перед диакритическими знаками и в некоторых других комбинациях символов. Необходимость в таких шаблонах связана с техническими причинами. В отличии от греческой письменности, для который в Юникоде были закодированы на отдельных кодовых точках не только буквы греческого алфавита (например, \textgreek{Ω}), но и все возможные комбинации буквы с диакритическими символами (например, \textgreek{Ὠ}, \textgreek{Ὥ}, и даже \textgreek{ᾯ}), для кириллицы, за некоторыми исключениями, буквы и диакритические символы вводятся отдельно, а их правильное отображение обрабатывается на уровне шрифта. Таким образом мы должны эксплицитно прописать алгоритму слогоделения, что отрыв диакритического символа от базовой буквы не допускается. С этой целью мы прописываем шаблоны, запрещающие:

\begin{enumerate}
\item перенос внутри диграфа \textchurchslavonic{ᲂу}, который может кодироваться в Юникоде и как \verb!U+1C82 U+0443!, и как \verb!U+043E U+0443!;
\item перенос перед выносными символами ударения и придыхания, перед кендемой, титлом, и выносными буквами\autocite[Полный перечень символов вместе с их кодовыми точками в Юникоде, а также полный перечень возможных слов с титлом или буквенными титлами см. в работе ][]{utn41};
\item перенос перед символом ерок (\verb!U+2E2F!) и перед буквами ер (\verb!U+044A!) и ерь (\verb!U+044C!);
\item перенос вокруг символов паерк (\verb!U+A67F!) и кавыка (\verb!U+A67E!).
\end{enumerate}

Получив на данном этапе полный перечень шаблонов слогоделения, мы далее создаем на его основе перечень шаблонов переноса строки. Разница заключается в том, что при слогоделении возможно отделение однобуквенного слога (напомним пример \textchurchslavonic{є҆-вре́-и}), однако переносить допускается только однобуквенные слоги \textchurchslavonic{ѡ҆-} и \textchurchslavonic{ѿ-} и диграф \textchurchslavonic{ᲂу҆-}. Так как любой начальной гласной в современном церковнославянском языке обязательно следует символ придыхания, мы не можем ограничиться заданием параметров \verb+lefthyphenmin+ и \verb+righthyphenmin+, отвечающих за минимальное количество символов, допустимых для переноса в начале или конце слова (например, для русского языка устанавливаются параметры \verb+lefthyphenmin = 2+ и \verb+righthyphenmin = 2+). Поэтому мы вручную прописываем шаблоны, запрещающие перенос одной буквы в начале и конце слов, за исключением допустимых для переноса слогов.

Наконец на последнем этапе мы учитываем проблему нормализации текста, закодированного в Юникоде. Дело в том, что некоторые комбинации букв с диакритическими знаками все же закодированы в Юникоде на отдельных кодовых точках (к примеру, буква \emph{й} закодирована на кодовой точке \verb!U+0439!). Такие буквы имеют два возможных, канонически тождественных представления; для решения проблемы взаимодействия этих представлений существует Алгоритм нормализации Юникода (\textenglish{Unicode Normalization Algorithm})\autocite[Подробности см. ][]{tr15}. Все словоформы в нашем первоначальном словаре были представлены в Нормализированной форме C (\textenglish{Normal Form C}). Теперь мы создаем в необходимых случаях соответствующие представления в Нормализированной форме D (\textenglish{Normal Form D}). Отметим, что в целях надежности алгоритма, шаблоны должны учитывать все возможные комбинации форм D и C. Так, к примеру, церковнославянское слово \textchurchslavonic{мѡ-ѷ-се́й} имеет четыре возможных, канонически тождественных представления. На этом этапе мы также учитываем наличие двух возможных двусмысленных представлений, которые не учитываются Алгоритмом нормализации Юникода: слитное и раздельное кодирование диграфа \textchurchslavonic{ᲂу҆-} (\verb!U+0479! и \verb!U+1C82 U+0443!) и слитное и раздельное кодирование буквы \textchurchslavonic{ѽ} (\verb!U+047D! и \verb!U+A64D U+0486 U+0311!)\autocite[Специфику нормализации церковнославянского текста см. в работе ][]{utn41}. В итоге мы получаем перечень, содержащий $14.378$ шаблонов и $18$ исключений, который теперь может быть загружен в \TeX{}, и будет предоставлять перенос строки для церковнославянского текста.

\subsection{Анализ эффективности шаблонов}

По построению, созданные шаблоны для \TeX{} будут давать правильный перенос строки для всех слов, включенных в словарь, использованный для создания шаблонов (если, конечно, сам словарь не содержит ошибок). Остается ответить на вопрос, насколько эти шаблоны полезны для слогоделения других слов, т.~е., как наши шаблоны обобщаются для новых слов. Насколько нам известно, какие-то попытки тестировать шаблоны \TeX{} ранее не предпринимались. Обычно разработчики шаблонов работают с очень большими словарями, содержащими сотни тысяч слов, разделенных на слоги и предполагают, что этот словарь содержит все необходимые слова языка; в нашем случае был использован ограниченный словарь, так что вопрос обобщения шаблонов становится актуальным.

В этих целях мы использовали метод перекрестной проверки (\textenglish{cross-validation}). Изначальный словарь разделенных по слогам слов $D$ делиться на $N$ равных по количеству слов разделов $d$, так что $D = \cup_{i = 1}^{N} d_i$. Далее отбираются $N$ наборов данных для генирования шаблонов и $N$ наборов данных для тестирования шаблонов: набор данных для генирования шаблонов $i$ является просто разделом $d_i$, а набор для тестирования -- всем словарем с исключенным разделом $d_i$, т.~е. $\cup_{j \neq i} d_j$. Теперь мы генерируем шаблоны используя каждый из этих $N$ наборов данных и тестируем эти шаблоны на его наборе для тестирования. Мы измеряем эффективность  $i$-ных шаблонов по определению слогоделения набора для тестирования для каждого из $N$ наборов. Наша задача -- максимизировать среднее значение этой эффективности по $N$ наборам данных (что мы называем \textenglish{$N$-fold performance}). Так как по построению, $d_i$ и $\cup_{j \neq i} d_j$ содержат разные слова, то мы можем считать, что результаты отражают реальную ситуацию обобщения шаблонов для слов, не включенных в изначальный словарь.

Единственным методологическим затруднением этого подхода является вопрос, следует ли перемешивать слова перед тем, как генерировать наборы слов $d_i$ и $\cup_{j \neq i} d_j$. Мы решили не перемешивать слова, что объясняется следующими соображениями. Словарь содержит слова в алфавитном порядке, причем перечень имеет много однокоренных слов, записанных по порядку, к примеру:

\begin{center}
\begin{churchslavonic}
\begin{tabular}{l}
бо-лѣ́-зней \\
бо-лѣ́-знемъ \\
бо-лѣ́-знен-нѡ \\
бо-лѣ́-знен-ны-ѧ \\
бо-лѣ́-зни \\
\end{tabular}
\end{churchslavonic}
\end{center}

\noindent Если мы перемешаем слова, то в результате и набор генерирования $d_i$, и набор тестирования $\cup_{j \neq i} d_j$ могут содержать однокоренные слова. Однако нас интересует в первую очередь как раз способность шаблонов корректно разделять на слоги новые корни, т.~к. слогоделение суффиксов предсказывается всеми словами словаря и является более надежным, а слогоделения корней только разучивается алгоритмом за счет слов, содержащих этот корень. Если наборы для генерирования и тестирования созданы без перемешивания, то в худшем случае, они могут содержать однокоренные слова на границах наборов, а также однокоренные слова с другими префиксами, напр., \textchurchslavonic{без-бо-лѣ́-знен-нѡ}. Так как мы ограничиваемся $N \leq 4$, то можно предположить, что эффект присутствия однокоренных слов в этих случаях мизерный.

При генерировании шаблонов помимо параметров $good\_wt$, $bad\_wt$ и $threshold$ Формулы~\ref{eff_formula}, мы также можем установить количество уровней параметров (от одного до девяти). При этом нечетные уровни дают разрешающие шаблоны, а четные уровни -- запрещающие шаблоны. Эмпирические наблюдения показали, что наличие дополнительных уровней никак не повышает эффективность шаблонов. Таким образом, оптимальным количеством уровней является ровно два: один уровень разрешающих шаблонов и один уровень запрещающих шаблонов. Далее, мы можем контролировать длину шаблонов. Наши наблюдения показали, что разрешающие шаблоны длиной в одну букву приводят к большому количеству ошибок; с другой стороны, очень эффективны запрещающие шаблоны длиной в одну букву. Что же касается длинных шаблонов, то шаблоны длиной в более чем четыре буквы приводят к большому количеству ошибок. Таким образом мы ограничиваемся разрешающими шаблонами длиной в две, три или четыре буквы. (Уточнить: буквы или символа!!). Наконец, при выборе параметров отбора шаблонов $good\_wt$, $bad\_wt$ и $threshold$ мы можем контролировать отбор шаблонов либо путем переменной $bad\_wt$, либо переменной $threshold$. На практике оказывается, что лучше всего установить $threshold = 1$ и увеличивать параметр $bad\_wt$.

Mix-and-match inhibition levels -- тут не до конца мне понятна суть. Нужно ли это описывать?

\begin{table}[ht]
\centering
\caption{Результаты перекрестной проверки \label{validation_results}}
\begin{tabular}{cccc}<commit_msg>actual edits, like last time, but no distracting whitespace "edits"<commit_after>\documentclass[12pt,a4paper,oneside]{extarticle}
\usepackage{fontspec,xltxtra,xcolor}
\usepackage{microtype}
\usepackage{polyglossia}
\usepackage[hidelinks]{hyperref}
\usepackage[top=0.75in, bottom=0.75in, left=0.75in, right=0.75in]{geometry}
\usepackage[style=gost-footnote,sortlocale=ru,natbib=true]{biblatex}
\setdefaultlanguage{russian}
\setotherlanguages{english,greek,churchslavonic} % set as "other" so English hyphenation active
\def\hyph{-\penalty0\hskip0pt\relax}

\defaultfontfeatures{Mapping=tex-text}
\setromanfont{Linux Libertine O}
\setsansfont{Linux Biolinum O}
\newfontfamily\churchslavonicfont[Script=Cyrillic,HyphenChar=_]{Ponomar Unicode}
\newfontfamily{\cyrillicfonttt}{Linux Libertine O}
\newfontfamily\greekfont[Script=Greek]{Old Standard}
\providecommand{\keywords}[1]{\textbf{Ключевые слова}: #1}

\bibliography{hyphenation}

\title{Автоматизация слогоделения и переноса строки в церковнославянских текстах}
\author{А.~А.~Андреев\thanks{<NAME> -- магистр богословия, магистр экономических наук, аспирант кафедры Церковно-практических дисциплин Санкт-Петербургской духовной академии; \url{<EMAIL>}.} \and М.~П.~Крутиков\thanks{\url{<EMAIL>}}}
\date{\vspace{-1em}}  % hack to remove some wasted vertical blank space

\begin{document}
\clubpenalty=10000
\widowpenalty=10000
\interfootnotelinepenalty=0
\maketitle

\begin{abstract}
Решение проблемы автоматизации слогоделения и переноса строки
(\textenglish{hyphenation}) в системе \TeX{} было впервые предложено для английского языка в 1983~г.
Ф.~Льянгом. Однако до сих пор метод Льянга не применялся к
церковнославянским текстам в кодировке Юникод. Тем не менее проблема
автоматизации переноса строки и слогоделения является актуальной при
верстки текстов, как в научных изданиях, так и в богослужебных книгах. В данной статье
формулируются правила переноса строки для церковнославянского языка и
предлагается автоматизированное решение, основанное на методе Льянга.
Авторы описывают процедуру разработки шаблонов переноса (\textenglish{hyphenation patterns})
и впервые предлагают методы оценки их эффективности.
\end{abstract}

\keywords{типографика, морфология, компьютерные алгоритмы, Юникод}

\section{Введение}

При наборе церковнославянского текста на компьютере, пользователь сталкивается с проблемой переноса строки. Необходимость переноса строки особенно актуальна при наборе богослужебных текстов, т.~к. богослужебные книги обычно форматируются с выравниванием по ширине (\textenglish{justified alignment}). В этом случае наличие сложных, многослоговых слов (которые нередко встречаются в церковнославянских текстах) приводит к нежелательному растягиванию пробелов между словами. Перенос строки помогает выравнять текст по ширине и сократить ширину пробелов. Перенос строки также актуален при наборе текстов в нескольких колонках и при отображении церковнославянских текстов на мобильных устройствах с ограниченным эффективным пространством экрана.

При современном типографском наборе, перенос строки обычно выполняется программой верстки текста автоматически, используя алгоритм переноса (\textenglish{hyphenation algorithm}). Алгоритм переноса зависит от языка текста и культурных особенностей (так, для американского и британского английского существуют разные правила переноса). Однако в современных программах верстки текста нет алгоритма переноса для церковнославянского языка. Очевидно, что пользователь не может просто применить алгоритм переноса для русского языка к церковнославянскому тексту, т.~к. церковнославянский язык имеет свой, отличный от русского языка набор букв и использует большое количество выносных диакритических знаков. Также, как мы покажем, правила переноса в церковнославянском языке несколько отличаются от правил современного русского языка. Ввиду отсутствия алгоритма переноса для церковнославянского языка, пользователь вынужден переносить текст вручную при наборе церковнославянского текста, что крайне трудоемко и приводит к неизбежным ошибкам. Мало того, современные пособия по грамматике церковнославянского языка не содержат даже описания правил переноса, что весьма затрудняет ручное решение  этой задачи.

В данной статье мы описываем правила переноса и слогоделения для современного церковнославянского языка, т.~е. языка <<синодального извода>>, который используется в богослужебных текстах Русской православной церкви со времени издания Елизаветинской Библии в 1751~г. Далее мы описываем пути решения проблемы автоматизации переноса строки для церковнославянских текстов на основании алгоритма переноса, разработанного для системы верстки текста \TeX{}. Авторами созданы соответствующие пакеты для \TeX{}, которые решают задачу автоматизированного переноса церковнославянских текстов. При этом авторы смогли не только создать необходимые шаблоны переносов, но и разработать и применить методы тестирования их эффективности, которые в данной статье описываются впервые. В статье предлагается краткая инструкция по использованию созданных нами пакетов. Следует отметить, что достигнутые нами результаты применимы не только в системе \TeX{}: на основании разработанных для \TeX{} шаблонов, мы также создали словарь церковнославянских переносов для популярной свободной программы LibreOffice.

\section{Правила слогоделения в церковнославянском языке}

Перенос строки в церковнославянском языке, как и в русском языке, должен происходить на границе слогов. Таким образом с задачей переноса непосредственно связана задача слогоделения в церковнославянском языке. Однако правила слогоделения подробно не описаны ни в одном учебном пособии по современному церковнославянскому языку. Лишь в некоторых учебниках приводятся упоминания, что перенос строки должен производиться по таким же правилам, как и в русском языке. В действительности, просмотрев издания Московской и Санкт-Петербургской синодальных типографий, а также издания Киево-Печерской лавры за 1840--1917~гг., можно прийти к выводу, что, с учетом ряда дополнительных требований, связанных с особенностями церковнославянской орфографии (напр., наличие выносных букв и диакритических знаков), перенос строки в церковнославянских текстах должен следовать правилам слогоделения для русского языка в дореформенной орфографии. Эти дореформенные правила, основанные на морфологическом разборе слов, подробно описаны в классическом пособии Я.~К. Грота <<Русское правописание>>\autocite[][]{grot1902}. Опираясь на указанные Я.~К. Гротом правила для русского языка, мы приводим правила слогоделения для церковнославянского языка.

\begin{table}[h]
\centering
\caption{Примеры морфологического разбора церковнославянских слов \label{one}}
\begin{tabular}{ll}
Правильно   	& 	Неправильно \\
\hline
\textchurchslavonic{свѣ́т-лый} & \textchurchslavonic{свѣ́-тлый} \\
\textchurchslavonic{грѣ́ш-ный} & \textchurchslavonic{грѣ́-шный} \\
\textchurchslavonic{же́н-скїй}	& \textchurchslavonic{же́-нскїй}, \textchurchslavonic{же́нс-кїй} \\
\textchurchslavonic{вѣст-во-ва́-нї-е} & \textchurchslavonic{вѣ-ство-ва́-нї-е} \\
\textchurchslavonic{дѣ́тель-ство-ва} &	\textchurchslavonic{дѣ́тельст-во-ва}, \textchurchslavonic{дѣ́тельс-тво-ва} \\
\hline
\end{tabular}
\end{table}

Для простых слов, следует сначала правильно выделить корень слова и отделить от корня суффиксы и окончания, как указано в примерах в Таблице~\ref{one}. Согласные внутри суффиксов не должны быть разделяемы. К примеру, не должны разделяться суффиксы \textchurchslavonic{-ство}, \textchurchslavonic{-скїй}. Если суффикс начинается с согласной, то он может переноситься на новую строку, как в словах: \textchurchslavonic{же́н-скїй}, \textchurchslavonic{за-блꙋ́жд-шихъ}, \textchurchslavonic{кро́т-кїй}, \textchurchslavonic{свѣ́т-лый}, \textchurchslavonic{се́рд-це}, \textchurchslavonic{скве́р-ный}, \textchurchslavonic{тѣ́с-ный} (но: \textchurchslavonic{при́-сный}), \textchurchslavonic{чис-ло̀} (но: \textchurchslavonic{ма́-сло}), \textchurchslavonic{мо-ли́-тва} (но: \textchurchslavonic{клѧ́т-ва}).

Группы согласных, стоящие вне суффикса (например, внутри корня слова) разделяются по следующему принципу. Если стечение согласных начинается с плавного (\textchurchslavonic{л}, \textchurchslavonic{р}), носового (\textchurchslavonic{н}, \textchurchslavonic{м}) или шипящего (\textchurchslavonic{ш}, \textchurchslavonic{щ}, \textchurchslavonic{ж}, \textchurchslavonic{ч}), то буква, записывающая такой звук, остается на строке, а следующие за ней слогласные, формирующие слог, переносятся: \textchurchslavonic{во́л-ны}, \textchurchslavonic{го́р-дость}, \textchurchslavonic{до́н-деже}, \textchurchslavonic{кам-па́нъ}, \textchurchslavonic{мы́ш-ца}, \textchurchslavonic{ѹ҆мерщ-вле́й}, \textchurchslavonic{лꙋ́ч-ше}. К носовым следует также относить комбинации согласных \textchurchslavonic{-гг-}, \textchurchslavonic{-гк-}, \textchurchslavonic{-гх-} в словах иностранного происхождения, в которых \textchurchslavonic{г}, в соотвествии с правилами греческого языка, читается как \textchurchslavonic{н}. Так мы имеем: \textchurchslavonic{а҆г-кѵ́-ра}, \textchurchslavonic{а҆гаѳаг-ге́лъ} (но: \textchurchslavonic{а҆-гге́й}), \textchurchslavonic{паг-ха́-рїй}); следует иметь ввиду, что иностранные слова могут быть разного происхождения, но в церковнославянский язык они вошли через греческий язык, и, по возможности, сохраняют греческое написание и произношение (напр., \textchurchslavonic{а҆́г-глїа}).

Если стечение согласных начинается с другого звука, например, с губных или зубных, то все согласные стечения переносятся на следующую строку, как в случаях \textchurchslavonic{сре-бро̀}, \textchurchslavonic{га-врїи́лъ}, \textchurchslavonic{є҆-фре́мъ}, \textchurchslavonic{не-пщева́ти}. В особенности не следует разделять согласные после \textchurchslavonic{с}: \textchurchslavonic{па́-сха} (неправильно: \textchurchslavonic{па́с-ха}), \textchurchslavonic{пе-ска̀} (а не \textchurchslavonic{пес-ка̀}), \textchurchslavonic{при́-снѡ}, \textchurchslavonic{го-спо́день}, но: \textchurchslavonic{чис-ло̀}. Также не следует разделять сочетания согласных, в которых происходит смягчение (палатализация): \textchurchslavonic{-мл-}, \textchurchslavonic{-бл-}, \textchurchslavonic{-вл-}, \textchurchslavonic{-пл-}, \textchurchslavonic{-жд-}: \textchurchslavonic{зе-млѧ̀}, \textchurchslavonic{до́-блїй}, \textchurchslavonic{и҆зба-вле́нїе} (но: \textchurchslavonic{і҆а́кѡв-лю}), \textchurchslavonic{ме-ждꙋ̀}.

Правильное разделение стечений согласных является самыми сложным нюансом при слогоделении в церковнославянских словах. В остальных случаях действуют достаточно простые правила, похожие на соответствующие правила в русском языке. Так согласная, стоящая между двумя гласными, начинает новый слог: \textchurchslavonic{мо-на́-си}, \textchurchslavonic{мо-лѧ́-ще}; две одинаковые согласные разделяются: \textchurchslavonic{а҆м-мꙋ́нъ}, \textchurchslavonic{а҆́н-на}, \textchurchslavonic{ва́с-са}; когда одна согласная отделена от другой согласной ерем, то слог начинается после еря: \textchurchslavonic{вель-мѝ}, \textchurchslavonic{де́нь-ги} (вообще, еры никогда не отделяются от предшествующих букв). Две стоящие подряд гласные разделяются за исключением диграфа \textchurchslavonic{ᲂу}, который никогда не разделяется, так как всегда читается как \emph{у}: \textchurchslavonic{а҆-а-рѡ́нъ}, \textchurchslavonic{кле-о́-па}, \textchurchslavonic{ѹ҆́-ме}. Следует иметь ввиду, что буква \textchurchslavonic{ѵ} в тех случаях, когда она читается как \textchurchslavonic{в}, не отделяется от предшествующей ей гласной, если за ней следует согласная: \textchurchslavonic{а҆́ѵ-гꙋстъ}, \textchurchslavonic{є҆ѵ-ге́-нїй} (но: \textchurchslavonic{ле-ѵі́тъ}, \textchurchslavonic{на-ѵи́нъ}). Согласно правилам, приведенным Я.~К. Гротом, в русском языке не разделяются стечения гласных, записывающие иностранные дифтонги (напр., следует писать \emph{туа-летъ}, а не \emph{ту-а-летъ}, от франц. \emph{toilette}), однако согласно правилам церковнославянского произношения, такие стечения гласных произносятся раздельно, а не как дифтонги, и соответственно должны быть разделяемы в церковнославянском языке: \textchurchslavonic{ѹ҆-а-лен-ті́нъ}.

Отдельные правила относятся к слогоделению сложных слов, т.~е. слов, состоящих из нескольких корней или из префикса (приставки) и корня. В этих случаях необходимо разделить слово по слогам так, чтобы сохранить структуру корней и префикса, т.~е. чтобы согласные, принадлежащие корню не были отнесены к префиксу, и наоборот. При этом разделение сложного слова на корни и префиксы может нарушать правила слогоделения для простых слов, указанные выше. Так следует писать: \textchurchslavonic{и҆с-кꙋ-пи́лъ}, \textchurchslavonic{и҆с-по-вѣ́-да-нї-е} (но \textchurchslavonic{и҆-скра̀}, \textchurchslavonic{и҆́-сти-на}); \textchurchslavonic{вос-кли́к-нꙋть} (но \textchurchslavonic{во-скре-се́-нї-е}); \textchurchslavonic{со-зва̀} (а не \textchurchslavonic{соз-ва̀}); \textchurchslavonic{под-но́-жї-е}, \textchurchslavonic{под-кло-ни́-ти} (но  \textchurchslavonic{по́-двигъ}, \textchurchslavonic{по-дра-жа́-ти}); \textchurchslavonic{по-зна̀}, \textchurchslavonic{по́-мнити}; \textchurchslavonic{рас-ка́-ѧ-нї-е}; наконец, \textchurchslavonic{без-ꙋ́м-ный}, \textchurchslavonic{раз-ꙋ́м-нѡ} (в этих случаях в церковнославянском языке часто сохраняется ер в конце префикса, напр. при написании \textchurchslavonic{без̾-ꙋ́м-ный}). Однако если после префикса выпала согласная, относящаяся к корню слова, то гласная, следующая за префиксом не может начинать слога; так следует переносить \textchurchslavonic{ѡ҆-би-та́-ти} (а не \textchurchslavonic{ѡ҆б-и-та́-ти}), \textchurchslavonic{и҆-зы́-де} (а не \textchurchslavonic{и҆з-ы́-де}).

Теперь перейдем к ряду правил, касающихся непосредственно церковнославянской орфографии. В первую очередь следует упомянуть о словах, в которых присутствуют сокращения с титлом или буквенным титлом. Естественно, что нельзя разделять внутри записанного под титлом сокращения, т.~е. нельзя писать \textchurchslavonic{а҆́г-г҃ли}, \textchurchslavonic{воскрⷭ҇-ный}. Обзор изданий церковнославянских богослужебных книг за 1840--1917~гг. показал, что разделение на слоги возможно только: при отделении префикса от сокращенного корня (напр., \textchurchslavonic{во-скрⷭ҇лъ}, \textchurchslavonic{все-чⷭ҇тно́-е}, \textchurchslavonic{пре-чтⷭ҇а-ѧ} и даже \textchurchslavonic{пре-чⷭ҇та-ѧ}); перед гласной, предшествующей сокращенному стечению (напр., \textchurchslavonic{а҆р-ха́гг҃лъ}, \textchurchslavonic{і҆-ерⷭ҇ли́мъ}; впрочем, исходя из правил, указанных Я.~К. Гротом, более правильно было бы писать \textchurchslavonic{а҆рх-а́гг҃лъ} с учетом греческого происхождения слова); или после гласной или еря, начинающих следующий за сокращенным стечением слог (\textchurchslavonic{млⷭ҇рдї-е}, \textchurchslavonic{а҆пⷭ҇ль-скїй}, \textchurchslavonic{мч҃ни-ка}; но \textchurchslavonic{мч҃нка}). Здесь действуют не только принципы морфологического деления слова, но и эстетические соображения.

В русском языке слог, состоящий из одной гласной, находящейся в начале или в конце слова, не может быть перенесен (так, неправильными были бы переносы в русских словах \emph{и-мя}, \emph{тво-ё}). Однако в церковнославянских текстах синодальной эпохи наблюдается перенос после слогов \textchurchslavonic{ѡ҆-}, \textchurchslavonic{ѿ-}, и \textchurchslavonic{ᲂу҆-}, находящихся в начале слова, ввиду того, что они являются префиксами. Так допускаются переносы \textchurchslavonic{ѡ҆-свѧще́нїе}, \textchurchslavonic{ѿ-вале́нъ}, \textchurchslavonic{ѹ҆-дивлѧ́ѧ}.  Другие однобуквенные слоги в начале слова не следует отделять и оставлять на предыдущей строке, равно как не следует переносить однобуквенный слог в конце слова (так, не следует переносить \textchurchslavonic{є҆-вре́и} или \textchurchslavonic{є҆вре́-и}).

\section{Разработка автоматизации слогоделения}

\subsection{Алгоритм слогоделения \TeX{}}

Проблема правильного переноса строки существует столько же, сколько и искусство печатного набора текста. О ней упоминается в первом пособии по типографике, \textenglish{Mechanick Exercises} Джозефа Моксона (1683~г.). С разработкой компьютерной типографики в середине XX~в. появляются и первые попытки автоматизированного решения проблемы переноса строки. Изначально были выявлены два возможных подхода: словарный и логический. При словарном подходе, все возможные слова, вместе с возможными переносами, сохраняются в списке слов; алгоритм выравнивания строки просматривает этот список и выбирает оптимальные переносы. Однако при ограничениях оперативной памяти и скорости процессора для компьютерных систем 60-х--70-х~гг. XX~в., такой подход являлся слишком медленным и неэффективным. С другой стороны был разработан логический подход, при котором описывались правила для возможных переносов исходя из морфологии и орфографии языка (напр., <<перенос разрешается между двумя гласными>>). На практике оказывается, что слишком трудно написать список всех таких правил, и что к ним все равно требуется достаточно пространный словарь исключений.

Уникальное решение проблемы автоматизации переноса строки предложил <NAME> в своей PhD диссертации\autocite[][]{liang1983}. Это решение, известное как <NAME>--Льянга, впоследствии стало стандартным в компьютерной типографике, и применяется не только в системе верстки текста \TeX{}, для которой оно было изначально разработано Льянгом, но и в других программах\autocite[Первое описание системы \TeX{} см. ][]{knuth1979}. <NAME>--Льянга основан на идее шаблонов слогоделения (\textenglish{hyphenation pattern}). Каждый такой шаблон записывает последовательность символов (строку), предоставляющую какую-то информацию о возможном слогоделении. Нечетная цифра указывает на место возможного деления. К примеру, чтобы указать, что слогоделение возможно в английском языке перед суффиксом \emph{-tion}, записывает шаблон \verb+1tion+. Однако такие шаблоны могут выдавать ошибочные результаты, например шаблон \verb+1tion+ неправильно делит английское слово \emph{cat-ion}. Для таких исключений алгоритм вводит запрещающие шаблоны (\textenglish{inhibiting pattern}). Места запрета слогоделения в запрещающих шаблонах указаны четными цифрами. К примеру, для запрета слогоделения перед \emph{tion} в слове \emph{cation} можно ввести запрещающий шаблон \verb+ca2tion+. Но запрещающие шаблоны могут, в свою очередь, запретить вполне допустимые деления в других словах, так, шаблон \verb+ca2tion+ запретит перенос в слове \emph{ap-pli-ca-tion}. Для этого слова вводится разрешающий шаблон следующего уровня, например шаблон \verb+lica3tion+. При заданных шаблонах, для того, чтобы разделить слово на слоги, алгоритм разбивает данное слово на группы символов (\textenglish{character clusters}) и ищет соответствующие этим группам шаблоны, причем, если несколько шаблонов подходят к какой-то группе, выбирается шаблон с большей по величине цифрой. В итоге, места между группами, в которых стоит нечетная цифра, являются возможными местами разделения на слоги. В качестве примера, английскому слову \emph{hyphenation} подходят заданные шаблоны \verb+hy3ph+ \verb+he2n+ \verb+hena4+ \verb+hen5at+ \verb+1na+ \verb+n2at+ \verb+1tio+ \verb+2io+, которые в соединении дают результат \verb+hy3phe2n5a4t2ion+, соответствующий правильному слогоделению \emph{hy-phen-ation}\autocite[См. подробнее ][pp.~5--6, 35--40.]{liang1983}.

Следующим достижением Льянга было решение проблемы создания словаря шаблонов. Для автоматизации этой задачи, исследователь написал программу \verb+PATGEN+ (\emph{pattern generator} = генератор шаблонов), которая создает <<оптимальный>> перечень шаблонов из заданного словаря разделенных по слогам слов. Шаблоны подбираются итеративным подходом. Сначала программа просматривает словарь и выбирает разрешающие шаблоны. В последующих итерациях выбираются запрещающие, затем опять разрешающие, шаблоны, с учетом шаблонов, выбранных в предыдущих итерациях. Этот процесс продолжается, пока не будут учтены все возможные слогоделения в словаре. При этом нужен некий критерий для отбора возможных шаблонов. С учетом того, что любой шаблон может сделать некое количество правильных слогоделений (что обозначается переменной $good$) и некое количество ошибочных слогоделений (что обозначается переменной $bad$), его эффективность может быть расценена как $efficiency = good / (1 + bad)$. При той или иной итерации отбираются шаблоны, чья эффективность превышает некий заданный порог, что выражается формулой

\begin{equation}
\label{eff_formula}
good * good\_wt - bad * bad\_wt \geq threshold
\end{equation}

\noindent где параметры $good\_wt$ и $bad\_wt$ устанавливаются для каждой итерации. На самом деле, такой подход является не больше чем ловким эвристическим устройством. Параметры $good\_wt$, $bad\_wt$ и $threshold$ Формулы~\ref{eff_formula} для каждой итерации подбираются эмпирическим путем, основываясь на методе проб и ошибок, и за ними нет никакого теоретического обоснования, в чем признается Льянг\autocite[Ср.: <<We do not have any theoretical justification for these parameters; they just seem to work well>>.][p.~36]{liang1983}. Так как по построению, алгоритм генерирует все шаблоны, необходимые для того, чтобы правильно определить все указанные в заданном словаре слогоделения (для этого при последней итерации устанавливается $threshold = 1$ и $bad\_wt \rightarrow \infty$), единственным критерием, которым руководствуется разработчик шаблонов при выборе параметров является количество дискового пространства, которое занимает созданный словарь шаблонов. В своей диссертации Льянг не предлагает способов тестирования эффективности шаблонов и критериев выбора параметров.

\subsection{Применение Алгоритма Кнута--Льянга к другим языкам}

Алгоритм Кнута--Льянга был изначально предложен только для английского языка, который удобен тем, что записывается ограниченным количеством символов (26 букв латинской азбуки без диакритических знаков). Хотя алгоритм может быть применен к любому языку, в котором перенос строки основан на слогоделении и который записывается азбучным письмом, даже при попытке работать с другими западноевропейскими языками (напр., французским, немецким), пользователь встречается с тем ограничением, что программа \verb+PATGEN+, как собственно и вся система \TeX{}, не предназначена для работы с бо́льшим количеством символов. Впоследствии, возможности \TeX{} были расширены созданием дополнительных кодовых таблиц, позволяющих запись символов различных западноевропейских языков\autocite[Кодировка \textenglish{Extended \TeX{} Font Encoding Scheme} (ET). См. ][]{ferguson1990}, а также других систем письменности, включая кириллицу\autocite[Описание существующих кодировок см. ][]{mittelbach2016}. Так как одновременно возникла и проблема создания шаблонов переноса в этих кодировках, П.~Брейтенлохнер написал расширенную программу \verb+PATGEN2+\autocite[См. описание в пособии ][]{patgen2}, которая была успешно применена к созданию, например, шаблонов для древнегреческого языка\autocite[][]{haralambous1992}.

Однако подход с разработкой альтернативных 8-битных кодировок потерял свою актуальность с созданием стандарта Юникод -- единого стандарта кодирования символов всех систем письменности мира, который был предложен в 1991~г. и за последующее десятилетие стал общепринятым в компьютерных технологиях. Д.~Антош и  П.~Сойка разработали программу \verb+OPatGen+ ($\Omega$ \emph{pattern generator} т.~к. она изначально предполагалась для системы $\Omega$), которая поддерживает Юникод и позволяет работать с большими алфавитами, а также создает неограниченное количество шаблонов\autocite[][]{opatgen}. Хотя программа была использована для таких сложных задач, как автоматизация переносов в тайской письменности (в которой не используются пробелы между словами)\autocite[][]{sojka2003}, на данный момент она устарела и на современных компиляторах \verb!C/C++! более не поддерживается. Для разработки шаблонов для церковнославянского языка потребовалась новая программа, написанная на  высокоуровневом языке программирования. В этих целях М.~Крутиков разработал программу \verb+pypatgen+ -- реализацию метода Льянга на языке \verb+Python+\footnote{Описание и инструкции по пользованию см. \url{https://github.com/pgmmpk/pypatgen}.}

Собственно, \verb+pypatgen+ является дословной реализацией оригинального алгоритма Льянга, исключая его оригинальный и чрезвычайно эффективный метод хранения и индексации промежуточных вычислений. Вместо этого данные хранятся в стандартных ассоциативных массивах и списках, что существенно облегчает понимание и поддержку исходного кода. Дело в том что проблема экономии процессорного времени и оперативной памяти уже не актуальна. А простота реализации и использование языка высокого уровня открывает возможности для внесения изменений и дальнейшего развития инструментария. Например, поиск шаблонов в словаре церковнославянского языка занимает около 30 секунд на стандартном персональном компьютере (17 тысяч слов). Алгоритм Льянга линеен по количеству слов в словаре, так что даже существенно б\'ольшие словари могут быть обработаны за приемлемое время.

\section{Создание шаблонов для церковнославянского языка}

Отметим, что при современных компьютерных технологиях, ограничения оперативной памяти и скорости процессора более не являются столь актуальными, как в 70-х~гг. XX~в. Однако метод Кнута--Льянга интересен тем, что даже работая с ограниченным словарем, мы имеем надежду, что созданные шаблоны смогут правильно угадать слогоделения и в тех словах, которые не вошли в первоначальный словарь. Таким образом при создании шаблонов для церковнославянского языка перед нами стоит несколько иная задача. Эффективным должен быть признан не только самый минимальный набор шаблонов, но такой набор шаблонов, который с большей точностью может быть применен к словам, не вошедшим в словарь, использованный для создания шаблонов. В этом подразделе мы опишем процедуру создания шаблонов используя программу \verb+pypatgen+, а в следующем разделе -- разработанный нами метод оценки эффективности шаблонов.

\subsection{Генерирование шаблонов}

Процедура создания шаблонов для \TeX{} происходит в следующей последовательности. Для начала был подготовлен словарь церковнославянских слов. В этих целях мы выбрали из словаря, содержащего все слова, встречающиеся в корпусе современных богослужебных текстов\footnote{Этот полный словарь содержит в совокупности $134.392$ слова.}, те, которые отвечают за 90\% случаев употребления слова. К этому списку слов были добавлены случайно выбранные имена собственные из перечня, помещенного в церковнославянском Требнике, а также технические термины (в основном, географические наименования), которые встречаются в церковнославянском разделе Общего хранилища данных о локалях (\textenglish{Common Locale Data Repository}, CLDR)\footnote{См. \url{http://cldr.unicode.org/}.}, и необходимые для локализации компьютерных программ. В итоге мы получили словарь, содержащий $17.525$ церковнославянских слов, которые затем были разбиты по слогам вручную, в соответствии с правилами, обозначенными выше.

Далее над этим словарем был запущен алгоритм генерирования шаблонов используя программу \verb+pypatgen+ (версия 0.2.9). Параметры $good\_wt$, $bad\_wt$ и $threshold$ Формулы~\ref{eff_formula} были установлены в соответствии с результатами процедуры оценки эффективности шаблонов, которая описывается в следующем разделе. В результате мы получили файл \verb+raw_patterns.txt+, содержащий сырые шаблоны и файл \verb+err_raw_patterns.txt+, содержащий исключения, т.~е. слова, которые не могут быть правильно разделены на слоги используя сгенерированные шаблоны. Эти исключения возникают в основном за счет того, что мы, в целях обобщения шаблонов, ограничиваем их длину (об этом также смотри в следующем разделе). Таким образом список исключений содержит много однокоренных слов с <<длинными>> корнями, равно как и слов с <<необычными>> суффиксами, к примеру:

\begin{center}
\begin{churchslavonic}
\begin{tabular}{l}
бо-лѣ́-зней \\
бо-лѣ́-знемъ \\
бо-лѣ́-знен-нѡ \\
бо-лѣ́-знен-ны-ѧ \\
бо-лѣ́-зни \\
\end{tabular}
\end{churchslavonic}
\end{center}

Такие слова могут быть заменены одним шаблоном (в данном случае, шаблоном \textchurchslavonic{.болѣ́7зн}), что было сделано вручную для всех слов в списке исключений. В результате мы получаем файл \verb+root_patterns.txt+, который содержит, в дополнение к сгенерированным <<кратким>> шаблонам, еще и перечень <<длинных>> шаблонов.

На следующем этапе нам необходимо добавить запрещающие шаблоны для случаев, где перенос абсолютно недопустим: перед диакритическими знаками и в некоторых других комбинациях символов. Необходимость в таких шаблонах связана с техническими причинами. В отличии от греческой письменности, для который в Юникоде были закодированы на отдельных кодовых точках не только буквы греческого алфавита (например, \textgreek{Ω}), но и все возможные комбинации буквы с диакритическими символами (например, \textgreek{Ὠ}, \textgreek{Ὥ}, и даже \textgreek{ᾯ}), для кириллицы, за некоторыми исключениями, буквы и диакритические символы вводятся отдельно, а их правильное отображение обрабатывается на уровне шрифта. Таким образом мы должны эксплицитно прописать алгоритму слогоделения, что отрыв диакритического символа от базовой буквы не допускается. С этой целью мы прописываем шаблоны, запрещающие:

\begin{enumerate}
\item перенос внутри диграфа \textchurchslavonic{ᲂу}, который может кодироваться в Юникоде и как \verb!U+1C82 U+0443!, и как \verb!U+043E U+0443!;
\item перенос перед выносными символами ударения и придыхания, перед кендемой, титлом, и выносными буквами\autocite[Полный перечень символов вместе с их кодовыми точками в Юникоде, а также полный перечень возможных слов с титлом или буквенными титлами см. в работе ][]{utn41};
\item перенос перед символом ерок (\verb!U+2E2F!) и перед буквами ер (\verb!U+044A!) и ерь (\verb!U+044C!);
\item перенос вокруг символов паерк (\verb!U+A67F!) и кавыка (\verb!U+A67E!).
\end{enumerate}

Получив на данном этапе полный перечень шаблонов слогоделения, мы далее создаем на его основе перечень шаблонов переноса строки. Разница заключается в том, что при слогоделении возможно отделение однобуквенного слога (напомним пример \textchurchslavonic{є҆-вре́-и}), однако переносить допускается только однобуквенные слоги \textchurchslavonic{ѡ҆-} и \textchurchslavonic{ѿ-} и диграф \textchurchslavonic{ᲂу҆-}. Так как любой начальной гласной в современном церковнославянском языке обязательно следует символ придыхания, мы не можем ограничиться заданием параметров \verb+lefthyphenmin+ и \verb+righthyphenmin+, отвечающих за минимальное количество символов, допустимых для переноса в начале или конце слова (например, для русского языка устанавливаются параметры \verb+lefthyphenmin = 2+ и \verb+righthyphenmin = 2+). Поэтому мы вручную прописываем шаблоны, запрещающие перенос одной буквы в начале и конце слов, за исключением допустимых для переноса слогов.

Наконец на последнем этапе мы учитываем проблему нормализации текста, закодированного в Юникоде. Дело в том, что некоторые комбинации букв с диакритическими знаками все же закодированы в Юникоде на отдельных кодовых точках (к примеру, буква \emph{й} закодирована на кодовой точке \verb!U+0439!). Такие буквы имеют два возможных, канонически тождественных представления; для решения проблемы взаимодействия этих представлений существует Алгоритм нормализации Юникода (\textenglish{Unicode Normalization Algorithm})\autocite[Подробности см. ][]{tr15}. Все словоформы в нашем первоначальном словаре были представлены в Нормализированной форме C (\textenglish{Normal Form C}). Теперь мы создаем в необходимых случаях соответствующие представления в Нормализированной форме D (\textenglish{Normal Form D}). Отметим, что в целях надежности алгоритма, шаблоны должны учитывать все возможные комбинации форм D и C. Так, к примеру, церковнославянское слово \textchurchslavonic{мѡ-ѷ-се́й} имеет четыре возможных, канонически тождественных представления. На этом этапе мы также учитываем наличие двух возможных двусмысленных представлений, которые не учитываются Алгоритмом нормализации Юникода: слитное и раздельное кодирование диграфа \textchurchslavonic{ᲂу҆-} (\verb!U+0479! и \verb!U+1C82 U+0443!) и слитное и раздельное кодирование буквы \textchurchslavonic{ѽ} (\verb!U+047D! и \verb!U+A64D U+0486 U+0311!)\autocite[Специфику нормализации церковнославянского текста см. в работе ][]{utn41}. В итоге мы получаем перечень, содержащий $14.378$ шаблонов и $18$ исключений, который теперь может быть загружен в \TeX{}, и будет предоставлять перенос строки для церковнославянского текста.

\subsection{Анализ эффективности шаблонов}

По построению, созданные шаблоны для \TeX{} будут давать правильный перенос строки для всех слов, включенных в словарь, использованный для создания шаблонов (если, конечно, сам словарь не содержит ошибок). Остается ответить на вопрос, насколько эти шаблоны полезны для слогоделения других слов, т.~е., как наши шаблоны обобщаются для новых слов. Насколько нам известно, какие-то попытки тестировать шаблоны \TeX{} ранее не предпринимались. Обычно разработчики шаблонов работают с очень большими словарями, содержащими сотни тысяч слов, разделенных на слоги и предполагают, что этот словарь содержит все необходимые слова языка; в нашем случае был использован ограниченный словарь, так что вопрос обобщения шаблонов становится актуальным.

В этих целях мы использовали метод перекрестной проверки (\textenglish{cross-validation}). Изначальный словарь разделенных по слогам слов $D$ делиться на $N$ равных по количеству слов разделов $d$, так что $D = \cup_{i = 1}^{N} d_i$. Далее отбираются $N$ наборов данных для генирования шаблонов и $N$ наборов данных для тестирования шаблонов: набор данных для генирования шаблонов $i$ является просто разделом $d_i$, а набор для тестирования -- всем словарем с исключенным разделом $d_i$, т.~е. $\cup_{j \neq i} d_j$. Теперь мы генерируем шаблоны используя каждый из этих $N$ наборов данных и тестируем эти шаблоны на его наборе для тестирования. Мы измеряем эффективность  $i$-ных шаблонов по определению слогоделения набора для тестирования для каждого из $N$ наборов. Наша задача -- максимизировать среднее значение этой эффективности по $N$ наборам данных (что мы называем \textenglish{$N$-fold performance}). Так как по построению, $d_i$ и $\cup_{j \neq i} d_j$ содержат разные слова, то мы можем считать, что результаты отражают реальную ситуацию обобщения шаблонов для слов, не включенных в изначальный словарь.

Единственным методологическим затруднением этого подхода является вопрос, следует ли перемешивать слова перед тем, как генерировать наборы слов $d_i$ и $\cup_{j \neq i} d_j$. Мы решили не перемешивать слова, что объясняется следующими соображениями. Словарь содержит слова в алфавитном порядке, причем перечень имеет много однокоренных слов, записанных по порядку, к примеру:

\begin{center}
\begin{churchslavonic}
\begin{tabular}{l}
бо-лѣ́-зней \\
бо-лѣ́-знемъ \\
бо-лѣ́-знен-нѡ \\
бо-лѣ́-знен-ны-ѧ \\
бо-лѣ́-зни \\
\end{tabular}
\end{churchslavonic}
\end{center}

\noindent Если мы перемешаем слова, то в результате и набор генерирования $d_i$, и набор тестирования $\cup_{j \neq i} d_j$ могут содержать однокоренные слова. Однако нас интересует в первую очередь как раз способность шаблонов корректно разделять на слоги новые корни, т.~к. слогоделение суффиксов предсказывается всеми словами словаря и является более надежным, а слогоделения корней только разучивается алгоритмом за счет слов, содержащих этот корень. Если наборы для генерирования и тестирования созданы без перемешивания, то в худшем случае, они могут содержать однокоренные слова на границах наборов, а также однокоренные слова с другими префиксами, напр., \textchurchslavonic{без-бо-лѣ́-знен-нѡ}. Так как мы ограничиваемся $N \leq 4$, то можно предположить, что эффект присутствия однокоренных слов в этих случаях мизерный.

При генерировании шаблонов помимо параметров $good\_wt$, $bad\_wt$ и $threshold$ Формулы~\ref{eff_formula}, мы также можем установить количество уровней параметров (от одного до девяти). При этом нечетные уровни дают разрешающие шаблоны, а четные уровни -- запрещающие шаблоны. Эмпирические наблюдения показали, что наличие дополнительных уровней никак не повышает эффективность шаблонов. Таким образом, оптимальным количеством уровней является ровно два: один уровень разрешающих шаблонов и один уровень запрещающих шаблонов. Далее, мы можем контролировать длину шаблонов. Наши наблюдения показали, что разрешающие шаблоны длиной в одну букву приводят к большому количеству ошибок; с другой стороны, очень эффективны запрещающие шаблоны длиной в одну букву. Что же касается длинных шаблонов, то шаблоны длиной в более чем четыре буквы приводят к большому количеству ошибок. Таким образом мы ограничиваемся разрешающими шаблонами длиной в две, три или четыре буквы. (Уточнить: буквы или символа!!). Наконец, при выборе параметров отбора шаблонов $good\_wt$, $bad\_wt$ и $threshold$ мы можем контролировать отбор шаблонов либо путем переменной $bad\_wt$, либо переменной $threshold$. На практике оказывается, что лучше всего установить $threshold = 1$ и увеличивать параметр $bad\_wt$.

Итак, мы остановились на двухуровневой системе шаблонов. Первый уровень создает потенциальные позиции слогоделения. Второй уровень <<убирает>> некоторые из них. При такой схеме, для достижения наилучшего результата надо чтобы первый уровень шаблонов находил наибольшее количество правильных точек слогоделения и при этом не предлагал слишком много неправильных точек. Второй уровень должен <<убирать>> как можно больше неправильных точек слогоделения и <<пропускать>> практически все правильные. В идеале, первый уровень будет определять все возможные точки слогоделения и не выдавать ни одного неправильного предложения. Второй уровень, в идеале, должен подавлять все неправильные позиции и пропускать только правильные.

Но поскольку в алгоритме Льянга уровни шаблонов генерируются последовательно, то невозможно создать одновременно хорошии шаблоны для первого и для второго уровня. Если, например, мы подбираем параметры генерации и получаем очень хороший первый уровень, то для создания второго уровня мы будем иметь совсем немного примеров неправильного слогоделения и второму уровню просто не хватит данных для обобщения всех возможных точек неправильного слогоделения и создания качественных шаблонов. Напомним, что мы хотим создать систему шаблонов, которая хорошо работает не только на словах из нашего словаря, но и на новых словах. Именно для этого желательно иметь максимально качественные шаблоны как первого, так и второго уровней.

Чтобы достичь высокого качества шаблонов второго уровня мы изобрели следующий прием: после оптимизации параметров для получения наиболее качественного первого уровня, мы искусственно ухудшаем первый уровень с целью значительного увеличения количества неправильных точек слогоделения. И на таких примерах мы генерируем второй уровень, стараясь оптимизаровать именно производительность второго уровня. После этого окончательный набор шаблонов строится комбинируя шаблоны этих двух отдельных генераций: лучший первый уровень плюс лучший второй уровень. Как показала перекрестная проверка, такой метод снижает абсолютный процент ошибок на 1--2\% (что весьма заметно при общем количестве ошибок порядка 10\%).

\begin{table}[ht]
\centering
\caption{Результаты перекрестной проверки \label{validation_results}}
\begin{tabular}{cccc}
{'fraction_non_alphanumeric': 0.07429128721483454, 'fraction_numerical': 0.006088801613137051, 'mean_word_length': 6.261052631578948, 'pattern_counts': {'":': 0, '<': 58, '<?xml version=': 0, '>': 58, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '53008', 'n_tokens_mistral': 30784, 'n_tokens_neox': 37344, 'n_words': 8283}