Заменялка

Научно-технические вопросы применения русского языка в программировании. Проекты с сайта программирование-по-русски.рф, кроме ЯОС . Информация об организациях и людях, использующих или изучающих русский язык в программировании. Сравнение операционных систем.
Ответить
БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Заменялка

Сообщение БудДен » 10.09.23 12:44

https://tvoygit.ru/budden/zamenjalka - проект для облегчения разрушающей локализации. Понадобился для работы, но хочу его в коллекцию проектов п-п-р, поэтому работаю за свой счёт. Жмут сроки выпуска рабочего проекта, не знаю, успею ли.

Здесь буду вести дневник своих действий и мыслей. Общую идею можно почитать на странице проекта, а сейчас - текущие мысли:

Я сделал дифф в терминах массивов, но это неустойчиво ни к чему, надо всё же делать словари? Но если в словарях будет ключом
имя процедуры, то как порядок будет учтён?


https://www.linux.org.ru/forum/developm ... d=17346328 - вот пример вывода списка на Hylang.

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 10.09.23 12:58

Возможное решение:

* ключом группы является полный путь к ней
* одним из этапов разбора является уникализация ключй. Допустим, если есть

Код: Выделить всё

let a = 1
let a = a + 1
То ко второй группе a нужно добавить формальный счётчик номера группы.
После этого все группы выводятся в виде одноуровневого словаря, который позволяет понять содержимое группы.

А последовательность следования групп выводится в отдельном узле. Только неясно, должна ли она быть иерархической или тоже линейной.

Тогда diff найдёт отдельно изменения в содержании групп и в их порядке следования. Проблемой в любом случае останется переименование группы, поэтому
мы сейчас проверим, насколько diff в этом умён.

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 10.09.23 17:49

deepdiff сразу не смог определить такую перестановку (в распечатанных группах).

Код: Выделить всё

let a = 
    let b = 1 in
    let b = 2

let c = 
    print("abc");
против

Код: Выделить всё

let c = 
    print("abc");

let a = 
    let b = 1 in
    let b = 2
Это скверно. Попробую сделать более сложное:
* каждой группе назначаем уникальный ключ, для случая

Код: Выделить всё

let b = 1 in  (* ключ будет (b 1) *)
let b = 2     (* ключ будет (b 2) *)
- но этот этап пока пропустим, а просто сделаем ключём полный путь.
* все группы складываем в один словарь, при том ключ - это преобразованный к строке полный путь, а значение - полный текст группы
* параллельно к тому, последовательность ключей кладём в список.
* сравнивать это можно за одно или за два действия
* потом понадобится этап оптимизации, чтобы минимизировать сценарий замены
* ох, провалюсь я.

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 10.09.23 22:12

Две проблемы:

* первая группа не свернулась
* к группам приклеиваются концы строк, которые к делу не относятся

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 11.09.23 11:17

Первую проблему решил, а вот что делать с концами строк?

Кроме того, переименовал одну группу и она не показывает что "значение удалилось" и "значение добавилось", а что добавилось - не выводится. Похоже, что
это неправильный diff, теряющий информацию. Ну и попадалово блин. А другой подобной библиотеки нет. Где-то рядом есть patch ещё, надо его посмотреть.

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 11.09.23 20:09

План:

* разбиваем группы до вручную заданного уровня (группы более глубокой вложенности сливаются в одну гигантскую простыню текста)
* сравниваем это
* где нашлись изменения - разбиваем группы только на лексемы (отдельная песня - как их найти по диффу, ведь там нет поля "что заменяем", а только "на что заменяем")
* по заранее заданному набору замен смотрим, подошло или нет.

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 11.09.23 22:19

Развернул библиотеку, примерно так:

Код: Выделить всё

python3.7 -m pip venv venv
source venv/bin/activate
python3.7 -m pip install -r requirements.txt
python3.7 -m pip install -e .

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 11.09.23 23:48

Скопировал (форкнул, прости господи) библиотеку https://tvoygit.ru/budden/python-json-patch и добавил в неё нужную операцию. В принципе, руками уже можно писать скрипты замен. Но желательно ещё научиться автоматически генерировать эти скрипты из сравнения файлов.

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 12.09.23 12:29

Текущий план:
* добавить в операцию замены информацию об удаляемом блоке
* разбивать оба блока на лексемы и найти замены.

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 15.09.23 11:15

Не забыть, что удаление нас не пугает, если там нет заменяемого, а вставка - если нет заменяющего.

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 21.09.23 16:23

В случае, когда нет списка замен (для локализации сообщений) всё совсем плохо работает.
Попробуем алгоритм развёртывания дерева:

* начинаем с некоего уровня детализации, допустим, 2
* если в какой-то группе есть замена, то пытаемся только эту группу развернуть и посмотреть, не получится ли патч меньшего размера. Размер патча смотрим по суммарной длине полей данных. Ы? Или с учётом количества элементов тоже?

Для этого не хватает примитивов:
* вывести под Гжель, сравнить выделенную подгруппу.

Не сработает у нас для переименованных на верхнем уровне групп. Что ж, се ля ви. Или надо додумать что-то.
Кто не в теме, код здесь:

https://tvoygit.ru/budden/zamenjalka

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 22.09.23 01:08

Ох я запутался. Нам теперь надо по ключу найти группу. Более того, нам надо делать это по ходу изменения дерева. Похоже, что надо
воспользоваться методами из самого jsonpatch - он-то умеет искать группы. Другое дело, что он всё равно найдёт не саму группу, а только её представление под Гжель. Т.е. задачу найти группу по её ключу в представлении под Гжель всё равно решать нам.

Проблема в том, что я уже несколько дней назад отложил этот код и теперь у меня в голове путаются группы как таковые и их представления под Гжель.

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 22.09.23 23:23

Не осилил (надеюсь, это ещё не "Акела промахнулся"). Задача оказалась с хорошими зубами, а пытался решить с наскока исходя из сжатости сроков. Маловероятно, что вернусь к этой задаче в будущем - а жаль, это могло бы вырасти в интересные проекты. Поскольку задачу по работе всё же решить надо, попробую другой подход для "разрушающей локализации": текст каждой лексемы выводится на отдельной строки. Далее напускаем на это diff. Каждый перевод превращается в элемент заплатки. Режем дифф и превращаем элементы заплатки в глобальную команду (однократной) контекстной замены. Там, где замена не однократная - там руками надо будет написать какой-то скрипт (возможно, в этот момент и пригодится уже разработанный механизм применения заплаток и представление "под гжель"). Но более простым будет просто вынести все неудачные замены в отдельный, рукописный коммит.

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 22.09.23 23:53

Нда, и тут всё пошло не так. Ну что ж, 400 замен руками - это не более 2 дней работы.

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 22.09.23 23:55

Утро вечера мудренее, конечно, но похоже, что раз я за 2 недели не смог решить задачу, а положение со сроками только ухудшилось, дальше не стоит пытаться. Однако ТЗ на более умную заменялку может быть и стоило бы сформулировать. Общая идея, что нужно искать только замены определённых классов. И, естественно, алгоритм поиска заплаток должен быть изрядно умным и оптимизирующим. Проблема здесь в том, что разницу между двумя файлами можно представить бесконечным количеством способов в виде последовательности заплаток, и явно нужна какая-то "наука", чтобы найти "достаточно хорошую" заплатку, удовлетворяющую к тому же нужным требованиям. То, что я пытался, было "полунаукой", надеялся проскочить на шару, но не не вышло.

Аватара пользователя
Лис [Вежливый]
Сообщения: 563
Зарегистрирован: 08.10.18 13:32

Re: Заменялка

Сообщение Лис [Вежливый] » 23.09.23 06:13

«Нет ничего практичнее хорошей теории» (q) Больцман

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 23.09.23 07:47

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

Аватара пользователя
Лис [Вежливый]
Сообщения: 563
Зарегистрирован: 08.10.18 13:32

Re: Заменялка

Сообщение Лис [Вежливый] » 23.09.23 08:01

неудача любого моего проекта будет прокомментирована Лисом
Это обобщение. Один (или любое фиксированное количество) проект был прокомментирован (причём совершенно нейтрально), из этого был сделан необоснованный индуктивный логический вывод об отношении Лиса ко всем проектам БудДена. Это однозначно называется "гипотеза".

Лис сообщает, что это не просто гипотеза, а клеветническая гипотеза (т.е. созданная с целью продвижения теории о Лисе, с целью загрязнения моего пушистого образа). Скриньте.

УК РФ Статья 128.1. Клевета
2. Клевета, содержащаяся в публичном выступлении, публично демонстрирующемся произведении, средствах массовой информации либо совершенная публично с использованием информационно-телекоммуникационных сетей, включая сеть "Интернет", либо в отношении нескольких лиц, в том числе индивидуально не определенных, - наказывается штрафом в размере до одного миллиона рублей или в размере заработной платы или иного дохода осужденного за период до одного года, либо обязательными работами на срок до двухсот сорока часов, либо принудительными работами на срок до двух лет, либо арестом на срок до двух месяцев, либо лишением свободы на срок до двух лет.
Я, конечно, подавать в суд на БудДена не буду, просто хочу показать, что это менее вежливо, чем разговаривать матом.

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 23.09.23 12:27

Наутро понял, что проблема была в том, что я сделал 2 ортогональных представления - порядок групп и их содержимое, а потом сложил их в массив и напустил на них операцию diff (разность). В итоге при попытке заменять части полученной заплатки на распознанные уткнулся в непреодолимые трудности, поскольку изменения ключа группы меняют и порядок (там заменяется элемент), и содержимое (исчезает группа со старым полным путём и появляется с новым). Нужно править заплатку в двух местах, это сразу резко усложняет алгоритм, например, по той причине, что нужно учитывать порядок следования операций в заплатке, который может переплетаться с другими операциями и в итоге мы можем построить неправильный алгоритм, не имея представления о динамике изменения исходного текста по мере применения операций заплатки.

А надо на самом деле запускать операцию сравнения N раз и получится N отдельных заплаток. Как сделать, чтобы эти заплатки были "композабельны", т.е. их можно было бы применить в правильной последовательности к исходному файлу и получить целевой файл?

Кроме того, проделав часть преобразований, мы можем применить полученную частичную заплатку к исходному дереву и повторить всё сравнение целиком. Тогда наша последующая работа будет относиться к правильному промежуточному состоянию дерева.

Попробую:
* для каждого файла делаем разбор и к верховной группе каждого файла применяем алгоритм ПостройЗаплаткуДляГруппы, он строится так:

Код: Выделить всё

проц ПостройХорошуюЗаплаткуДляГруппы(лГ, пГ)
"""
:param лГ: - левая иерархическая группа лексем (до изменений), 
:param пГ: - правая иерархическая группа группа (то же место после изменений)
:return: [данныеЗаплатки, списокРаспознанныхЗамен, списокПроблем]
"""

Код: Выделить всё

  лД, пД = строим, как и раньше, директорию (т.е. для лексемы выводим её текст, а для подгруппы - локальный ключ, пополненный до уникального), и всё это в массиве. 
  словарьХорошихЗаплатокПодгрупп = dict()
  для каждой подгруппы П, которая в подгруппе Л существует с этим же ключом.
    изменениеДляНеподвижнойПодгруппы = ПостройХорошуюЗаплаткуДляГруппы(этаПодгруппаСлева, этаПодгруппаСправа)
    словарьХорошихЗаплатокПодгрупп[ключЭтойПодгруппы] = изменениеДляНеподвижнойПодгруппы

Код: Выделить всё

  комбинацияИзмененийПодгрупп = скомбинируйОртогональныеИзменения(словарьХорошихЗаплатокПодгрупп)
  промежуточноеСостояние = примениИзменение(лГ, комбинацияИзмененийПодгрупп)
  остаточнаяЗаплатка = ПостройОбычнуюЗаплаткуДляГруппы(промежуточноеСостояние, пГ)
  изменениеСЗаходомВПодгруппы = комбинацияИзмененийПодгрупп + остаточнаяЗаплатка
  изменениеНаУровнеТекстаГруппы = ПредставьИзменениеКакЗаменуТекста(лГ, пГ)
  возврат лучшаяИзДвухЗаплаток(изменениеСЗаходомВПодгруппы, изменениеНаУровнеТекстаГруппы)

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 23.09.23 12:42

Этот алгоритм - убогий, и он провалит все места, где группа верхнего уровня переименована. Но учитывая общий статус проекта как "полный провал", если превратить его в "успех в 3/4 случаев" - будет всё ещё хорошо.

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 23.09.23 16:51

Лис, где же теперь твои ценные замечания?

Аватара пользователя
Лис [Вежливый]
Сообщения: 563
Зарегистрирован: 08.10.18 13:32

Re: Заменялка

Сообщение Лис [Вежливый] » 23.09.23 18:07

БудДен, ты делаешь хорошее дело, но мне сейчас нехватает мозгов, много разных задач и я не успеваю подумать над этой. Попробуй призвать новых программистов с разных других мест интернета. ̶Е̶щ̶ё̶ ̶д̶о̶п̶о̶л̶н̶и̶т̶е̶л̶ь̶н̶ы̶е̶ ̶м̶о̶з̶г̶и̶ ̶м̶о̶ж̶н̶о̶ ̶а̶р̶е̶н̶д̶о̶в̶а̶т̶ь̶ ̶з̶а̶ ̶д̶е̶н̶ь̶г̶и̶,̶ ̶н̶о̶ ̶д̶л̶я̶ ̶э̶т̶о̶г̶о̶ ̶н̶а̶д̶о̶ ̶п̶р̶е̶д̶в̶а̶р̶и̶т̶е̶л̶ь̶н̶о̶ ̶р̶е̶ш̶и̶т̶ь̶ ̶д̶р̶у̶г̶и̶е̶ ̶з̶а̶д̶а̶ч̶и̶ ̶(̶и̶ ̶п̶о̶э̶т̶о̶м̶у̶ ̶я̶ ̶с̶ч̶и̶т̶а̶ю̶,̶ ̶ч̶т̶о̶ ̶о̶н̶и̶ ̶б̶о̶л̶е̶е̶ ̶п̶р̶и̶о̶р̶и̶т̶е̶т̶н̶ы̶е̶)̶.̶

Я сталкивался с похожей проблемой ранее, но не стал разбираться. У меня нет идей по этой теме.

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 26.09.23 19:09

Кое-что получилось, но время уже совсем-совсем вышло, а работы конь не валялся. По идее научился распознавать замены в структурах.
Но!

* для распознавания нужно каждый раз подстраивать формулы, принимающие решение
* нужно реализовать обобщение замен на возможно более широкую область действия (это в принципе я уже делал)
* нужно пользоваться другой формулой пути, т.е. преобразовывать зпуть в гпуть (вроде не выглядит очень сложным)
* после применения текстовой замены на широкой области действия файл нужно переразбирать (это не страшно, можно делать при выполнении скрипта)

ИЗ всего этого, не считая того, что время закончилось, страшным выглядит только п.1

БудДен
Сообщения: 2873
Зарегистрирован: 07.10.18 14:01

Re: Заменялка

Сообщение БудДен » 27.09.23 13:48

В общем, проект провалился, можно сказать, с грандиозным треском студенческого уровня.
При постановке задачи реальность была грубейшим образом проигнорирована. Несмотря на определённые успехи,
в целом проект не может быть завершён, поскольку полностью упущен основной сценарий использования. Я сделал,
можно сказать, только ядро скриптового движка, распознающее замены, но к нему ещё нужны инструменты, которые
бы позволили практически его применять, и это целая, по сути дела, ИСР для языка программирования, поскольку
такой язык скриптов, модифицирующих исходники - это не менее, чем язык программирования, пусть и специализированный.
Сложность реализации среды разработки состоит в том, что основной режим работы - это трёхстороннее слияние файлов,
т.е. это не обычная разработка, а особая.

При этом даже с самим ядром оказалось всё сложнее, чем казалось изначально.

Таким образом, при оценке реализуемости проекта была упущена вся подводная
часть айсберга. Как итог - теперь сидеть мне и вручную с помощью meld сливать 400 изменений.

Во всяком случае, поупражнялся в Питоне и приобщился к культуре:

* поработал с json, yaml
* научился (пусть не до конца) делать форки библиотек
* получил опыт работы с venv (опять же, о полноте говорить рано)
* получил опыт создания модульных тестов "по писанному"
* получил больше опыта работы в соавторстве с ChatGPT
* глянул мельком на язык Hy (лисп для Питона)
* первая относительно крупная программа на Python, написанная мной с именами в кириллице (15 файлов, 2000 строк)
* массированно применял F2 (переименуй идентификатор) для питоновских программ
* коротко посмотрел на варианты русификации ключевых слов python (и не нашёл хороших)
* узнал о существовании git rerere

Ответить