воскресенье, 28 сентября 2008 г.

Про мой переводчик. Структура.

Продолжение. Начало смотрим тут. 

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

... правда семантического анализа у меня еще нет.

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

В процессе разработки был придуман следующий подход к процессу перевода предложений:

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

Как видно - получившийся алгоритм оказался жизнеспособным.

Вот так вот мутировал изначальный линейный алгоритм в процессе развития:

... синие блоки примерно соответствуют блокам на первом рисунке.

Ну и напоследок - степень завершенности ключевых модулей анализа:

Продолжение следует...

Grammar framework

Нашел некий Grammar framework с исходниками. Если я правильно понял, то основное что он умеет это склонять русские слова. Вообщем, надо смотреть - может и полезная штука :)

пятница, 26 сентября 2008 г.

:)

Чтение из файловых потоков у файлов на NTFS разделах

Как известно, файловая система NTFS позволяет в одном файле хранить т.н. потоки. Цитирую ixbt.com:

Каждый файл на NTFS, в общем-то, имеет несколько абстрактное строение - у него нет как таковых данных, а есть потоки (streams). Один из потоков и носит привычный нам смысл - данные файла. Но большинство атрибутов файла - тоже потоки! Таким образом, получается, что базовая сущность у файла только одна - номер в MFT, а всё остальное опционально. Данная абстракция может использоваться для создания довольно удобных вещей - например, файлу можно "прилепить" еще один поток, записав в него любые данные - например, информацию об авторе и содержании файла, как это сделано в Windows 2000 (самая правая закладка в свойствах файла, просматриваемых из проводника). Интересно, что эти дополнительные потоки не видны стандартными средствами: наблюдаемый размер файла - это лишь размер основного потока, который содержит традиционные данные. Можно, к примеру, иметь файл нулевой длинны, при стирании которого освободится 1 Гбайт свободного места - просто потому, что какая-нибудь хитрая программа или технология прилепила в нему дополнительный поток (альтернативные данные) гигабайтового размера. Но на самом деле в текущий момент потоки практически не используются, так что опасаться подобных ситуаций не следует, хотя гипотетически они возможны.


Так вот, здесь рассказывают как работать с этими потоками используя C#.

Поиск

Товарищи! А не кажется ли вам что Google последнее время стал искать хуже? Ну не то чтобы совсем уж плохо - не получается ткнуть пальцем и сказать, что "вот раньше находил, а теперь нет!". Но уже не первый раз замечаю, что последнее время частенько отсутствует реакция на знаки + и - перед словами. Слова, заключенные в кавычки, зачем-то разделяются и ищутся по отдельности и т.п.

На некоторые запросы вообще выдается такой бред - круче Рамблера :( Попробуйте, например, найти информацию о том, какой у нас в стране срок за геронтофилию. Нет, ну я, конечно, понимаю, что вопрос дурацкий - но вот как-то на работе народ заинтересовался и что? А ничего! Фигни много - полезного так и не нашли...

И последнее время такое все чаще...


Странно это всё...

пятница, 19 сентября 2008 г.

Обновления Google Chrome

Если интересно узнать, что именно изменилось в обновленной сборке Google Chrome - можно почитать блог Google Chrome Releases

вторник, 16 сентября 2008 г.

Про мой переводчик. История.

Вместо предисловия



Давным-давно, аж в далеком 2002 году я совершенно случайно наткнулся на книжки замечательной писательницы Лорел К. Гамильтон. На тот момент на русский язык были переведены только первые 6 книг из серии про Аниту Блейк.

В то время я уже отказался от чтения современной американской фантастики и фэнтези ввиду их примитивности (в сравнении с отчественными). Поэтому вдвойне удивительно то, что эти книжки так меня увлекли, что я полез в сеть в поисках продолжения :) Которое и нашел на фанатском сайте.

Но радость была недолгой - пятая книга, переведенная силами фанатов обрывалась (по закону подлости) на самом интересном месте.

К счастью - в наличии был английский текст книжки и даже еще две книги-продолжения :)

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

И я совершил страшное. Я запустил ПРОМТ и перевел книжку...

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

При чтении я как-то обратил внимание, что, в принципе, основные ошибки перевода ПРОМТа - это ошибки склонения слов (естественно, в тех случаях, когда предложение было разобрано верно).

Вот тогда-то и появилась идея (нет-нет, не переводчика!) программы-корректора, которая бы подправляла текст, сгенерированный ПРОМТом.

Примечание: в то далекое время я еще ничего не знал про Microsoft .Net Framework. Да и был он в стадии "почти релиза" и особо нигде не упоминался. Так что писал на том, что знал - C++ Builder 6.0.



Этап №1



Была написана маленькая программа, со своим словарем слов, которая заменяла отдельные слова на альтернативные. Изначально хотелось увидев "неправильное" слово или словосочетание заменить их на "правильное".

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

Стало понятно, что необходим собственный алгоритм построения склонения/спряжения слов. Алгоритм был написан и успешно заработал. Причем он оказался настолько успешным, что без особых изменений переползал из версии в версию и существует и используется и поныне :)

Однако, алгоритм склонения не сильно помог - стало понятно, что простое склонение пар слов относительно друг-друга нужного эффекта не даёт - необходимо, как минимум, знать связи между словами.



Этап №2



Вот тогда-то и появилась амбициозная идея написать "свой" переводчик, в котором можно было бы контролировать процесс перевода.

Именно тогда родился тот подход к синтаксическому анализу, который я использую и сейчас. Как раз тогда я впервые прочитал про регулярные выражения (regexp) и подумалось: "да это же самый простой способ определить вид предложения!".

Сам алгоритм анализа основанный на регулярных выражениях был написан всего за 4 часа. А вот уже загрузчик правил писался долго и муторно. Достаточно сказать, что пока я не начал использовать формат xml для хранения этих правил анализа алгоритм чтения файла с правилами продолжал глючить и падать от малейшего чиха. И это при том, что он постоянно правился в течение нескольких месяцев! Именно после этого я так невзлюбил Си++...

Кстати, та самая реализация алгоритма анализа до сих пор вполне успешно используется :) Ну понятно, что она нексколько мутировала, но все-таки...



Этап №3



Где-то в районе 2004-го года мне попадается интересная статья про Mono. И как-то руки зачесались попробовать :) А там как раз стало понятно, что Mono и .Net Framework - братья. А там и SharpDevelop попался... Вообщем, был написан тестовый редактор правил - благо правила уже давно хранились в формате xml, поэтому, фактически, писалась оболочка.

И как-то оно всё так хорошо пошло, что буквально за неделю весь проект переполз на C#. Я сам не ожидал, честно :) Ну не без глюков, конечно... Но в целом - изменения в коде были минимальные и в основном касались работы со строками.

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



Этапы №4 и далее



Становится понятно, что то, что получилось, в принципе, даже работает. И где-то даже правильно. И вообще...

Система довольно длительное время развивается пока не упирается в принципиальный тупик: разбора только одного варианта предложения недостаточно. Вероятность ошибки неверного разбора предложения прямо зависела от того, вариант какой части речи стоял у слова в словаре первым.

Поэтому был добавлен маленький кусочек кода из-за которого пришлось переписывать половину программы :) А занимался он генерацией вариантов предложений. Основная идея - в предложении каждое слово имеет варианты перевода только одной части речи.

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

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

Примечание: Например, если после артикля the стоит слово - это слово 100% не глагол. И т.д и т.п.

В итоге, на самом большом моем тестовом тексте я до сих пор получаю не более 17 вариантов предложения. Что, конечно много, но, во-первых, правил не так уж и много, а во-вторых, при существующей производительности железа - это крайне мало.



Этап №14



Худо-бедно система развивалась, пока я не уперся в потолок - каждое последующее изменение требовало все больше и больше усилий. Я думаю, многим это знакомо.

Это было страшное время :( Когда понятно, что надо сделать, но непонятно как это сделать так, чтобы ничего не сломалось...

Поэтому в начале 2006-го года было принятно решение все переписать :)

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

Какое-то время удавалось поддерживать новую версию на плаву... Пока я не уперся в тот же самый потолок.



Этап №15



Собственно, деваться было некуда и пришлось полностью менять подход к созданию крупных программ. Благо уже "созрел".

К лету 2006-го стало понятно, что надо делать модульную систему. К такому решению подталкивало два фактора:

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


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

В конце-концов, процесс подошел к своей конечной стадии. По пути программа лишилась удобного интерфейса выбора варианта перевода предложения и алгоритма поиска фраз (который был хоть и кривой и недоделанный, но все равно - жалко). Нет-нет! Они не совсем умерли. Просто пока что руки не доходят реализовать их по-новому - надо сначала доделать то, что важнее.

Зато появилось много чего нового и интересного :)

В конечном итоге - оно того стоило.



Продолжение следует...

четверг, 11 сентября 2008 г.

понедельник, 8 сентября 2008 г.

Отображение иконок для зарегистрированных типов файлов

Учитывая что тема про системные иконки является чуть ли не самой посещаемой в блоге решил поделиться еще одной полезной ссылкой на эту тему.

Вот здесь рассказывают как получить иконки для зарегистрированных в системе типов файлов.

пятница, 5 сентября 2008 г.

Жуть какая...

А бывают и вот такие извращения. Это компилятор C# в 16-ти битный код для MS-DOS. Выходной формат - .com-файл.

Вообще, конечно, интересно. Но все равно - извращение :) 25392226.a5e351c855901a7acefacc6448e97458.1221637119.f9852a452174cf0405f79164021d6cbe

среда, 3 сентября 2008 г.

Вы все еще не верите в безопасность? Тогда мы идем к вам!

Специалист по интернет-безопасности Авив Рафф (Aviv Raff) заявил, что нашел уязвимость в новом браузере Chrome компании Google.

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


А ведь прошло меньше суток... Для скачивания браузер был выложен где-то после 23:00 2-го сентября 2008.

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