Русский
Русский
English
Статистика
Реклама

Онтологии

Из песочницы Образование для образованных 2020

22.09.2020 18:18:39 | Автор: admin

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


Я давно слежу за блогом Левенчука и за его деятельностью. В том числе в мае 2020 проходил курс у него ровно с таким же названием. Я довольно близко знаком с материалом книги и с нетерпением ждал ее выхода. Летом она вышла и вот я ее прочитал.


О чем книга


Книга задает полный стек современных базовых знаний в представлении автора. Это представление базируется на современных исследованиях. Отдельно подчеркивается, что современный понимается как 2020 год не 2000 или 2015, а вот прям 2020. Используется термин SoTA, state of the art этот означает самые свежие представления в какой-то отрасли. Это SoTA постоянно меняется, так как сейчас изменения постоянны и более того, даже скорость этих изменений возрастает. Стек базовых знаний выбран для целей усиления интеллекта, а интеллект понимается как способность быстро разобраться в новой области. Получается, если проработать эту книжку, а потом проработать те трансдисциплины, про которые в ней рассказаны, станешь умнее и будешь быстрее достигать результатов. Трансдисциплины противопоставляются прикладным дисциплинам. Прикладная дисциплина это то умение, которое непосредственно используется в деятельности. Примеры: Scrum в разработке, какие-нибудь техники продаж в маркетинге. Прикладных дисциплин тысячи. Трансдисциплин много меньше. В книге тщательно отобраны трансдисциплины таким образом, чтобы изучение небольшого их количества привело к максимальным результатам.


Отдельно отмечу, что прагматизм вшит в философию книги, абсолютно все, что предлагается практично и в первую очередь предназначено для использования и изменения мира или себя, как части мира.


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


Множество вещей неочевидно и подразумевается интуитивно. Например логика или этика. Веди себя правильно и не веди себя неправильно. В книге ОдО выведено в осознанное поле из интуиции громадное количество вещей и ткнуто изучи эти вещи явно. Например, оказывается, что известная поговорка всех статистиков "корреляция не означает причинности" уже устарела, об этом подробно в книжке The Book of Why написано. Или оказывается, что совершенно неполезно в физкультуре нагружать себя до боли в мышцах и молочной кислоты.


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


Стек трансдисциплин


О каких же дисциплинах идет речь? Перечислю здесь, как я это понял в порядке важном для изучения и почему это важно для практики усиления интеллекта. Развивать можно любой уровень независимо, но лучше обращать внимания на все и каждый хоть по чуть-чуть.


  • Стратегирование и развитие интеллекта. Тут обсуждается глобально вопрос целей и создания стратегий. Ставится под сомнение классический путь меднолобого достижения целей, взамен этого предлагается концепция бесконечного развития. Для бесконечного развития предлагается стек трансдисциплин.
  • Психопрактики. Тут изучается, как уметь сосредоточенно работать не обнаруживая себя зависшим в фейсбуке, как иметь нормальную эмоциональную сферу. Тут самое важное работа с вниманием на разных временных масштабах.
  • Фитнес. Тут системный фитнес и вывод в осознанную сферу работу с мышцами
  • Мышление письмом и экзокортекс. Важно писать много текстов, чтобы мышление работало; важно широко использовать экзокортекс. Тут же GTD для управления делами. Заявляется, что пока мысль не записана, ее нет.
  • Философские основания. Автор называет это онтологикой. Что лежит в основе рассуждений, в основе науки, в частности? Всяческие логические рассуждения. Так в 2020 их надо изучать заново, даже если вы вдруг были знакомы с ними, там все поменялось. Онтология, логика, эпистемология. Это дисциплины, которые используются каждый день каждым человеком неосознанно. А раз неосознанно, то значит не лучшим образом просто, как сложилось. Их тоже надо выводить в осознанность и использовать эти дисциплины лучшим образом, по текущему SoTA 2020. Прагматизм тоже философская штука. Рассуждение, действие должно менять что-то в мире, если это не происходит, то этого по факту нет.
  • Коммуникация. Для того, чтобы хорошо общаться с людьми и достигать целей есть SoTA практики.
  • Системное мышление. Есть набор понятий, позволяющий компактно описывать самые разные явления. Этот набор понятий из системного мышления. Мир представляется как набор систем и о совершенно разных вещах можно мыслить как о системах. Клево уметь рассуждать примерно одинаковым образом о столовых приборах, корпорации Google, автомобиле Toyota Camry, полете на воздушном шаре или учебе в университете. И не только размышлять, а что-то делать в этих системах, в том числе конструировать их. Системное мышление противопоставлено редукционизму, когда все сводится к каким-то мелким деталям и автомобиль рассматривается как ведро с болтами. В системном мышлении осознанно выделяются различные системные уровни и между уровнем болтов и уровнем автомобиля выделяются еще десяток промежуточных уровней.
  • Вычислительное мышление. За последние 50 лет произошел взрывной рост вычислительной техники и она проникла в каждую область жизни. Мало кто понимает, как именно работают современные вычисления. Даже программисты за пределами своей работы обычно не имеют этого кругозора. А там много всего интересного, нейросетки, ИИ, различные парадигмы программирования. Автор называет все это вычислительным мышлением и утверждает что общее понимание этого также трансдисциплина, важная для каждого.
  • Кругозор в инженерии, менеджменте, предпринимательстве. Большая часть человечества так или иначе занята в этих областях, поэтому хорошо бы кругозорно знать, какие есть практики в этих областях. Если прокачан философский уровень и уровень системного мышления, такой кругозор будет получить существенно легче, видно на что обращать внимание.
  • Кругозор в других областях деятельности.
  • Далее прикладные практики, в книге про них не говорится, кроме того, что они есть. Книга про базовые знания, для прикладных дисциплин есть другие книги.

ОдО обзорная книга, она широкими мазкам размечает SoTA трансдисциплин, требуемых для изучения.


Изучение трансдисциплин


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


Во-первых, почему именно этот набор трансдисциплин, можно ли верить автору? А что если, какая-то важная трансдисциплина в ОдО не упомянута?


Автору верить необходимости нет, в книге множество первоисточников, она не является самодостаточным произведением, а базируется на множестве цивилизационных знаний "разлитых в воздухе", в статьях, в книгах. Я вполне допускаю, что какие-то важные трансдисциплины не упомянуты, но это не умаляет важности проработки упомянутых в ОдО трансдисциплин.


Во-вторых, будет ли достаточно просто прочитать ОдО и книги по трансдисциплинам?


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


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


Постановка полезных практик вещь более тонкая. Можно хорошо понять книгу и концепции заложенные в нее, но если не использовать эти концепции, то нельзя сказать, что ты получил всё от книги. Например, недостаточно хорошо понимать концепции системного фитнеса, нужно еще этот системный фитнес практиковать. Другой пример: оценка вероятностей разных событий байесианство. Современная важная штука, которая при должной интеграции позволяет более здраво относится к пандемиям. Очень практичная на текущий момент. Так вот прочитать, понять и записать мысли по поводу байесианства абсолютно недостаточно. Нужно еще потренироваться по оценки вероятностей в реальной жизни.


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


В-третьих, где учиться трасдисциплинам, где брать книжки?


В идеале, обучаться лучше всего у преподавателя. Это нужно, чтобы была обратная связь и возможность поправить, если что-то идет не так. Можно изучать самому, в ОдО много ссылок на литературу. Там своя сложность, т.к. SoTA разлит в воздухе, то частенько книжек нет, например нет книжки по системному фитнесу, по психопрактикам. Что делать с этим? Изучать самому, если тема интересна и может написать книжку со временем. Или пользоваться той инфой, которая есть в статьях. Еще есть вариант ничего не делать, довольствоваться той инфой, что есть, но все же примерно представлять, каково современное состояние дел на переднем крае этой области.


Резюмируя, для меня книга ОдО прям важна, она определяет спектр дисциплин для изучения на ближайшее время. Этот спектр включает в себя мышление письмом, онтологику, коммуникацию и системное мышление. Системный фитнес я и так использую все время. Еще есть вопрос изучения английского языка. Это тоже базовая штука, в ОдО знание англиского подразумевается. У меня он довольно слаб, хотя читать книги я вполне могу.


Куда двигаться дальше станет ясно после проработки этих дисциплин. На самом деле примерно все это я и так планировал делать после курса Образования для образованных от мая 2020, на который я так и не написал отзыв. Можно считать, этот текст отзывом как на курс, так и на книжку.


Кому читать?


Советую ли я книгу? Довольно непростой вопрос. Зависит от целей. В книге много непривычных концепций. Если хочется легкого чтива, то лучше не надо, чтиво непростое.


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


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


Ссылки


Подробнее..

Из песочницы Проектируем мульти-парадигменный язык программирования. Часть 1 Для чего он нужен?

29.09.2020 12:13:11 | Автор: admin
Хабр это замечательное место, где можно смело делиться своими идеями (даже если они и выглядят безумно). Хабр видел много самодельных языков программирования, расскажу и я о своих экспериментах в этой области. Но мой рассказ будет отличаться от остальных. Во-первых, это будет не просто язык программирования, а гибридный язык, сочетающий в себе несколько парадигм программирования. Во-вторых, одна из парадигм будет довольно необычной она будет предназначена для декларативного описания модели предметной области. А в-третьих, сочетание в одном языке декларативных средств моделирования и традиционных объектно-ориентированного или функционального подходов способно породить новый оригинальный стиль программирования онтологически-ориентированное программирование. Я планирую раскрыть в первую очередь теоретические проблемы и вопросы, с которыми я столкнулся, и рассказать не только о результате, но и о процессе создания дизайна такого языка. Будет много обзоров технологий и научных подходов, а также философских рассуждений. Материала очень много, придется разбить его на целую серию статей. Если вас заинтересовала такая масштабная и сложная задача, приготовьтесь к долгому чтению и погружению в мир компьютерной логики и гибридных языков программирования.

Вкратце опишу основную задачу


Она заключается в том, чтобы создать такой язык программирования, который был бы удобен как для описания модели предметной области, так и для работы с ней. Чтобы описание модели было как можно более естественным, понятным для человека и близким к спецификациям программного обеспечения. Но при этом оно должно быть частью кода на полноценном языке программирования. Для этого модель будет иметь форму онтологии и состоять из конкретных фактов, абстрактных понятий и отношений между ними. Факты будут описывать непосредственные знания о предметной области, а понятия и логические отношения между ними ее структуру.

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

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

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

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


Многим из нас приходилось заниматься поддержкой сложных проектов, созданных другими людьми. Хорошо, если в команде есть люди, которые ориентируются в коде проекта и могут объяснить, как он работает, есть документация, код чист и понятен. Но в реальности часто бывает и по-другому авторы кода уволились задолго до того, как вы попали на этот проект, документации или нет совсем или она очень обрывочная и давным-давно устарела, а о бизнес-логике нужного компонента бизнес-аналитик или проект-менеджер может рассказать лишь в общих чертах. В этом случае чистота и понятность кода является критическим показателем.
Качество кода имеет много аспектов, один из них правильный выбор языка программирования, который должен соответствовать решаемой задаче. Чем проще и естественней разработчик может реализовать свои замыслы в коде, тем быстрее он сможет решить задачу и меньше ошибок допустит. Сейчас у нас есть выбор из довольно большого числа парадигм программирования, каждая из которых имеет свою область применения. Например, функциональное программирование предпочтительней для приложений с акцентом на вычисления, так как оно дает больше возможностей для структурирования, комбинирования и повторного использования функций, реализующих операции над данными. Объектно-ориентированное программирование упрощает создание структур из данных и функций за счет инкапсуляции, наследования, полиморфизма. ООП подходит для приложений, ориентированных на данные. Логическое программирование удобно для задач, ориентированных на правила, требующих работы со сложными, рекурсивно-определенными типами данных, такими как деревья и графы, подходит для решения комбинаторных задач. Также свои сферы применения имеют реактивное, событийно-ориентированное, мультиагентное программирование.

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

Гибридное функционально-логическое программирование тоже имеет давнюю историю, но за пределы академического мира так и не вышло. Меньше всего внимания уделено объединению логического и императивного ООП программирования (более подробно о них я планирую рассказать в одной из следующих публикаций). Хотя на мой взгляд, логический подход мог бы быть весьма полезным в традиционной сфере применения ООП серверных приложениях корпоративных информационных систем. Просто на него нужно взглянуть немного под другим углом.

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


Попробую обосновать свою точку зрения.

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

С одной стороны, серверное приложение хранит данные в одной или нескольких базах данных. С другой отвечает на запросы, приходящие от конечных точек API, обрабатывает приходящие сообщения, реагирует на события. Структуры сообщений и запросов почти никогда не совпадают со структурами, хранимыми в базах данных. Форматы входных/выходных данных предназначены для использования извне, оптимизированы под потребителя этой информации и скрывают сложность приложения. Форматы хранимых данных оптимизированы под систему их хранения, например, под реляционную модель данных. Поэтому нужен некоторый промежуточный слой понятий, который позволит совместить между собой вход/выход приложения с системами хранения данных. Обычно этот промежуточный слой называется слоем бизнес-логики и реализует правила и принципы поведения объектов предметной области.

Задача связывания содержимого базы данных с объектами приложения тоже не так проста. Если структура таблиц в хранилище соответствует структуре понятий на уровне приложения, то можно воспользоваться ORM технологией. Но для более сложных случаев чем доступ к записям по первичному ключу и CRUD операций приходится выделить отдельный слой логики работы с базой данных. Обычно схема базы данных имеет максимально общую форму, так, что с ней могут работать разные сервисы. Каждый из которых отображает эту схему данных на свою объектную модель. Структура приложения становится еще более запутанной, если приложение работает не с одним хранилищем данных, а с несколькими, разного типа, загружает данные из сторонних источников, например, через API других сервисов. В этом случае необходимо создать унифицированную модель предметной области и отобразить на нее данные из разных источников.
В некоторых случаях модель предметной области может иметь сложную многоуровневую структуру. Например, при составлении аналитических отчетов одни показатели могут строиться на основе других, которые в свою очередь будут источником для построения третьих и т. д. Также входные данные могут иметь слабоструктурированную форму. Эти данные не имеют строгой схемы как, например, у реляционной модели данных, но все же содержат какую-либо разметку, позволяющую выделить из них полезную информацию. Примерами таких данных могут быть ресурсы семантической паутины, результаты парсинга WEB-страниц, документы, журналы событий, показания датчиков, результаты предварительной обработки неструктурированных данных, таких как тексты, видео и изображения и т.п. Схема данных этих источников будет строиться исключительно на уровне приложения. Там же будет и код, преобразующий исходные данных в объекты бизнес-логики.

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

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


Предположим, у нас есть 2 CSV файла. В первом файле:

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

Во втором файле:
В первой колонке хранится идентификатор клиента.
Во второй имя.
В третьей адрес электронной почты.

Введем некоторые определения:
Счет включает в себя идентификатор клиента, дату, выставленную суммы, суммы оплаты и долга из ячеек одной строки файла 1.
Сумма долга это разница между выставленной суммой и суммой оплаты.
Клиент описывается с помощью идентификатора клиента, имени и адреса электронной почты из ячеек одной строки файла 2.
Неоплаченный счет это счет с положительным долгом.
Счета связаны с клиентом по значению идентификатора клиента.
Должник это клиент, у которого существует хотя бы один неоплаченный счет, дата которого старше текущей даты на 1 месяц.
Злостный неплательщик это клиент, имеющий более 3х неоплаченных счетов.

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

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

Структурирование программы в объектно-ориентированном стиле позволяет смягчить эту проблему. Каждая сущность предметной области представляется объектом, поля данных которого соответствуют атрибутам сущности. А отношения между сущностями реализуются в виде отношений между объектами, частично на основе принципов ООП наследования, абстракции данных и полиморфизма, частично с помощью шаблонов проектирования. Но в большинстве случаев отношения приходится реализовывать, кодируя их в методах объектов. Также кроме создания классов, представляющих сущности, понадобятся также структуры данных для их упорядочения, алгоритмы для заполнения этих структур и поиска информации в них.

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

Наиболее близкой к описанию будет реализация концептуальной модели на языках представления знаний. Примерами таких языков являются Prolog, Datalog, OWL, Flora и другие. Об этих языках я планирую рассказать в третьей публикации. В их основе лежит логика первого порядка либо ее фрагменты, например, дескриптивная логика. Эти языки позволяют в декларативном виде задать спецификацию решения задачи, описать структуру моделируемого объекта или явления и ожидаемый результат. А встроенные механизмы поиска автоматически найдут решение, удовлетворяющее заданным условиям. Реализация модели предметной области на таких языках будет исключительно краткой, понятной и близкой к описанию на естественном языке.

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

Сначала мы объявляем факты с содержимым таблиц в формате: ID таблицы, строка, колонка, значение:

cell(Table1,1,1,John). 

Затем дадим имена каждой из колонок:

clientId(Row, Value) :- cell(Table1, Row, 1, Value).

После чего можно объединить все колонки в одно понятие:

bill(Row, ClientId, Date, AmountToPay, AmountPaid) :- clientId(Row, ClientId), date(Row, Date), amountToPay(Row, AmountToPay), amountPaid(Row, AmountPaid).unpaidBill(Row, ClientId, Date, AmountToPay, AmountPaid) :- bill(Row, ClientId, Date, AmountToPay, AmountPaid),  AmountToPay >  AmountPaid.debtor(ClientId, Name, Email) :- client(ClientId, Name, Email), unpaidBill(_, ClientId, _, _, _).

И так далее.

Сложности начнутся при работе с моделью: при реализации логики рассылки сообщений, передаче данных другим сервисам, сложных алгоритмических вычислений. Слабым местом Prolog является описание последовательностей действий. Их декларативная реализация даже в простых случаях может выглядеть очень неестественно и требует значительных усилий и квалификации. Кроме того, синтаксис Prolog не очень соответствует объектно-ориентированной модели, и описания сложных составных понятий с большим количеством атрибутов будут довольно тяжелыми для восприятия.

Как же нам совместить основной функциональный или объектно-ориентированный язык разработки с декларативной природой модели предметной области?


Наиболее известным подходом является предметно-ориентированное проектирование (Domain-Driven Design). Эта методология облегчает создание и реализацию сложных моделей предметной области. Она предписывает, чтобы все понятия модели были выражены в коде явным образом в слое бизнес логики. Понятия модели и реализующие их элементы программы должны быть как можно ближе к друг другу и соответствовать единому языку, понятному как программистам, так и экспертам по предметной области.

Богатая модель предметной области для примера с должниками будет дополнительно содержать классы для понятий Неоплаченный счет и Должник, классы-агрегаты для объединения понятий счетов и клиентов, фабрики для создания объектов. Реализация и поддержка такой модели более трудоемкая, а код громоздкий то, что раньше можно было сделать одной строчкой, в богатой модели требует нескольких классов. В итоге, на практике такой подход имеет смысл только при работе больших команд над сложными масштабными моделями.

В некоторых случаях решением может быть комбинация основного функционального или объектно-ориентированного языка программирования и внешней системы представления знаний. Модель предметной области может быть вынесена во внешнюю базу знаний, например, в Prolog или OWL, а результат запросов к ней обработан на уровне приложения. Но такой подход усложняет решение, одни и те же сущности приходится реализовывать на обеих языках, настраивать взаимодействие между ними через API, дополнительно поддерживать систему представления знаний и т.п. Поэтому он оправдан только при большом размере и сложности модели, требующей логического вывода. Для большинства задач это будет избыточным. К тому же, эту модель не всегда можно безболезненно отделить от приложения.

Еще одним из вариантов совмещения баз знаний и ООП приложения является онтологически-ориентированное программирование. В основе этого подхода лежит сходство между средствами описания онтологии и объектной программной моделью. Классы, сущности и атрибуты онтологии, записанные, например, на языке OWL, могут быть автоматически отображены на классы, объекты и их поля объектной модели. А далее полученные классы можно использованы совместно с другими классами приложения. К сожалению, базовая реализация этой идеи будет иметь довольно ограниченные возможности. Языки онтологий довольно выразительны и далеко не все компоненты онтологии могут быть преобразованы в классы ООП простым и естественным образом. Также для реализации полноценного логического вывода недостаточно просто создать набор классов и объектов. Ему требуется информация об элементах онтологии в явном виде, например, в виде мета-классов. Об этом подходе более подробно я планирую рассказать в одной из следующих публикаций.

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

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

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

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

На первый раз достаточно. В следующей публикации я хочу поговорить о некоторых современных технологиях, совмещающих императивный и декларативный стили PL/SQL, Microsoft LINQ и GraphQL. Для тех, кто не хочет ждать выхода всех публикаций на Хабре, есть полный текст в научном стиле на английском языке, доступный по ссылке:
Hybrid Ontology-Oriented Programming for Semi-Structured Data Processing.
Подробнее..

Проектируем мульти-парадигменный язык программирования. Часть 3 Обзор языков представления знаний

04.11.2020 12:10:51 | Автор: admin
Продолжаем рассказ о создании мульти-парадигменного языка программирования, поддерживающего декларативный логический стиль для описания модели предметной области. Прошлые публикации находятся здесь и здесь. Теперь пришло время для описания основных особенностей и требований к языку описания модели предметной области. Но для начала сделаем небольшой обзор наиболее популярных языков представления знаний. Это довольно обширная область, имеющая давнюю историю и включающая ряд направлений логическое программирование, реляционное исчисление, технологии семантической паутины, фреймовые языки. Я хочу сравнить такие языки как Prolog, SQL, RDF, SPARQL, OWL и Flora, выделить те их особенности, которые были бы полезны в проектируемом мульти-парадигменном языке программирования.

Prolog.


Начнем с логического программирования и языка Prolog. Знания о предметной области представляются в нем в виде набора фактов и правил. Факты описывают непосредственные знания. Факты о клиентах (идентификатор, имя и адрес электронной почты) и счетах (идентификатор счета, клиента, дата, сумма к оплате и оплаченная сумма) из примера из прошлой публикации будут выглядеть следующим образом
client(1, "John", "john@somewhere.net").
bill(1, 1,"2020-01", 100, 50).

Правила описывают абстрактные знания, которые можно вывести из других правил и фактов. Правило состоит из головы и тела. В голове правила нужно задать его имя и список аргументов. Тело правила представляет собой список предикатов, соединенных логическими операциями AND (задается запятой) и OR (задается точкой с запятой). Предикатами могут служить факты, правила или встроенные предикаты, такие как операции сравнения, арифметические операции и др. Связь между аргументами головы правила и аргументами предикатов в его теле задается с помощью логических переменных если одна и та же переменная стоит на позициях двух разных аргументов, то значит, что эти аргументы идентичны. Правило считается истинным тогда, когда истинно логическое выражение тела правила. Модель предметной области можно задать в виде набора ссылающихся друг на друга правил:
unpaidBill(BillId, ClientId, Date, AmoutToPay, AmountPaid) :- bill(BillId, ClientId, Date, AmoutToPay, AmountPaid), AmoutToPay < AmountPaid.
debtor(ClientId, Name, Email) :- client(ClientId, Name, Email), unpaidBill(BillId, ClientId, _, _, _).

Мы задали два правила. В первом мы утверждаем, что все счета, у которых сумма к оплате меньше оплаченной суммы, являются неоплаченными счетами. Во втором, что должником является клиент, у которого есть хотя бы один неоплаченный счет.
Синтаксис Prolog очень простой: основной элемент программы правило, основные элементы правила это предикаты, логические операции и переменные. В правиле внимание сфокусированно на переменных они играют роль объекта моделируемого мира, а предикаты описывают их свойства и отношения между ними. В определении правила debtor мы утверждаем, что если объекты ClientId, Name и Email связанны отношениями client и unpaidBill, то они также будут связаны и отношением debtor. Prolog удобен в тех случаях, когда задача сформулирована в виде набора правил, утверждений или логических высказываний. Например, при работе с грамматикой естественного языка, компиляторами, в экспертных системах, при анализе сложных систем, таких как вычислительная техника, компьютерные сети, объекты инфраструктуры. Сложные, запутанные системы правил лучше описать в явном виде и предоставить среде исполнения Prolog разбираться с ними автоматически.

Prolog основан на логике первого порядка (с включением некоторых элементов логики высшего порядка). Логический вывод выполняется с помощью процедуры, называемой SLD резолюция (Selective Linear Definite clause resolution). Упрощенно ее алгоритм представляет собой обход дерева всех возможных решений. Процедура вывода находит все решения для первого предиката тела правила. Если текущий предикат в базе знаний представлен только фактами, то решениями являются те из них, которые соответствуют текущим привязкам переменных к значениям. Если правилами то потребуется рекурсивная проверка их вложенных предикатов. Если решений не найдено, то текущая ветвь поиска завершается неудачей. Затем для каждого найденного частичного решения создается новая ветвь. В каждой ветви процедура логического вывода выполняет привязку найденных значений к переменным, входящим в состав текущего предиката, и рекурсивно выполняет поиск решения для оставшегося списка предикатов. Работа завершается, если достигнут конец списка предикатов. Поиск решения может войти в бесконечный цикл в случае рекурсивного определения правил. Результатом работы процедуры поиска является список всех возможных привязок значений к логическим переменным.
В примере выше для правила debtor правило резолюции сначала найдет одно решение для предиката client и свяжет его с логическими переменными: ClientId = 1, Name = John, Email = john@somewhere.net. Затем для этого варианта значений переменных будет выполнен поиск решения для следующего предиката unpaidBill. Для этого потребуется сначала найти решения для предиката bill при условии, что ClientId = 1. Результатом будут привязки для переменных BillId = 1, Date = 2020-01, AmoutToPay = 100, AmountPaid = 50. В конце будет выполнена проверка AmoutToPay < AmountPaid во встроенном предикате сравнения.

Семантические сети.


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

RDF.


Семантическая паутина (semantic web) это попытка построить глобальную семантическую сеть на базе ресурсов Всемирной паутины путём стандартизации представления информации в виде, пригодном для машинной обработки. Для этого в HTML-страницы дополнительно закладывается информация в виде специальных атрибутов HTML тэгов, которая позволяет описать смысл их содержимого в виде онтологии набора фактов, абстрактных понятий и отношений между ними.
Стандартным подходом для описания семантической модели WEB ресурсов является RDF (Resource Description Framework или Среда Описания Ресурсов). Согласно ней все утверждения должны иметь форму триплета субъект предикат объект. Например, знания о понятии Кит будут представлены следующим образом: Кит является субъектом, живет в предикатом, Вода объектом. Весь набор таких утверждений можно описать с помощью ориентированного графа, субъекты и объекты являются его вершинами, а предикаты дугами, дуги предикатов направлены от объектов к субъектам. Например, онтологию из примера с животными можно описать в следующем виде:
@prefix : <...some URL...>
@prefix rdf: <http://www.w3.org/1999/02/rdf-schema#>
@prefix rdfs: <http://www.w3.org/2000/01/22-rdf-syntax-ns#>
:Whale rdf:type :Mammal;
:livesIn :Water.
:Fish rdf:type :Animal;
:livesIn :Water.

Такая форма записи называется Turtle, она предназначена для чтения человеком. Но то же самое можно записать и в XML, JSON форматах или с помощью тэгов и атрибутов HTML документа. Хоть в Turtle нотации предикаты и объекты можно сгруппировать вместе по субъектам для удобства чтения, но на семантическом уровне каждый триплет независим.
RDF удобен в тех случаях, когда модель данных сложна и содержит большое количество типов объектов и связей между ними. Например, Wikipedia предоставляет доступ к содержимому своих статей в RDF формате. Факты, описанные в статьях структурированы, описаны их свойства и взаимные отношения, включая факты из других статей.

RDFS


RDF модель представляет собой граф, по умолчанию никакой дополнительной семантики в нем не заложено. Каждый может интерпретировать заложенные в графе связи как посчитает нужным. Добавить в него некоторые стандартные связи можно с помощью RDF Schema набора классов и свойств для построения онтологий поверх RDF. RDFS позволяет описать стандартные отношения между понятиями, такие как принадлежность ресурса некоторому классу, иерархию между классами, иерархию свойств, ограничить возможные типы субъекта и объекта.
Например, утверждение
:Mammal rdfs:subClassOf :Animal.
задает, что Млекопитающее является подклассом понятия Животное и наследует все его свойства. Соответственно, понятие Кит также можно отнести к классу Животное. Но для этого нужно указать, что понятия Млекопитающее и Животное являются классами:
:Animal rdf:type rdfs:Class.
:Mammal rdf:type rdfs:Class.

Так же предикату можно задать ограничения на возможные значения его субъекта и объекта. Утверждение
:livesIn rdfs:range :Environment.
указывает, что объектом отношения живет в всегда должен быть ресурс, относящийся к классу Окружающая среда. Поэтому мы должны добавить утверждение о том, что понятие Вода является подклассом понятия Окружающая среда:
:Water rdf:type :Environment.
:Environment rdf:type rdfs:Class

RDFS позволяет описать схему данных перечислить классы, свойства, задать их иерархию и ограничения их значений. А RDF наполнить эту схему конкретными фактами и задать отношения между ними. Теперь мы можем задать вопрос к этому графу. Сделать это можно на специальном языке запросов SPARQL, напоминающем SQL:
SELECT ?creature
WHERE {
?creature rdf:type :Animal;
:livesIn :Water.
}

Этот запрос вернет нам 2 значения: Whale и Fish.

Пример из предыдущих публикаций со счетами и клиентами можно реализовать приблизительно следующим образом. С помощью RDF можно описать схему данных и наполнить ее значениями:
:Client1 :name "John";
:email "john@somewhere.net".
:Client2 :name "Mary";
:email "mary@somewhere.net".
:Bill_1 :client :Client1;
:date "2020-01";
:amountToPay 100;
:amountPaid 50.
:Bill_2 :client :Client2;
:date "2020-01";
:amountToPay 80;
:amountPaid 80.

Но вот абстрактные понятия, такие как Должник и Неоплаченные счета из первой статьи этого цикла, включают в себя арифметические операции и сравнение. Они не вписываются в статичную структуру семантической сети понятий. Эти понятия можно выразить с помощью SPARQL запросов:
SELECT ?clientName ?clientEmail ?billDate ?amountToPay ?amountPaid
WHERE {
?client :name ?clientName;
:email ?clientEmail.
?bill :client ?client;
:date ?billDate;
:amountToPay ?amountToPay;
:amountPaid ?amountPaid.
FILTER(?amountToPay > ?amountPaid).
}

Секция WHERE представляет собой список шаблонов триплетов и условий фильтрации. В триплеты можно подставлять логические переменные, имя которых начинается с символа "?". Задача исполнителя запроса найти все возможные значения переменных, при которых все шаблоны триплетов содержались бы в графе и выполнялись условия фильтрации.
В отличии от Prolog, где на основе правил можно конструировать другие правила, в RDF запрос не является частью семантической сети. На запрос нельзя ссылаться как на источник данных для другого запроса. Правда у SPARQL есть возможность представить результаты запроса в виде графа. Так что можно попробовать объединить результаты запроса с исходным графом и новый запрос выполнить на объединенном графе. Но такое решение будет явно выходить за рамки идеологии RDF.

OWL.


Важным компонентом технологий семантической паутины является OWL (Web Ontology Language) язык описания онтологий. С помощью словаря RDFS можно выразить только самые базовые отношения между понятиями иерархию классов и отношений. OWL предлагает гораздо более богатый словарь. Например, можно задать, что два класса (или две сущности) являются эквивалентными (или различными). Такая задача часто встречается при объединении онтологий.
Можно создавать составные классы на основе пересечения, объединения или дополнения других классов:
  • При пересечении все экземпляры составного класса должны относиться и ко всем исходным классам. Например, Морское млекопитающее должно быть одновременно и Млекопитающим и Морским жителем.
  • При объединении составной класс включает в себя все экземпляры исходных классов. Например, можно задать, что класс Животное является объединением классов Хищник, Травоядное и Всеядное. Все экземпляры этих классов будут заодно и Животными.
  • При дополнении к составному классу относится все, что не относится к исходному. Например, класс Хладнокровное дополняет класс Теплокровное.
  • Так же можно создавать классы на основе перечислений. Можно указать, что экземпляр составного класса обязательно должен быть экземпляром только одного из исходных классов.
  • Можно задавать наборы непересекающихся классов если экземпляр относится к одному из них, то одновременно он не может относиться к остальным классам из набора.

Такие выражения, позволяющие связать понятия между собой, называются конструкторами.
OWL также позволяет задавать многие важные свойства отношений:
  • Транзитивность. Если выполняются отношения P(x, y) и P(y, z), то обязательно выполняется и отношение P(x, z). Примерами таких отношений являются Больше-Меньше, Родитель-Потомок и т.п.
  • Симметричность. Если выполняется отношение P(x, y), то обязательно выполняется и отношение P(y, x). Например, отношение Родственник.
  • Функциональная зависимость. Если выполняются отношения P(x, y) и P(x, z), то значения y и z должны быть идентичными. Примером является отношение Отец у человека не может быть два разных отца.
  • Инверсия отношений. Можно задать, что если выполняется отношение P1(x, y), то обязательно должно выполняться еще одно отношение P2(y, x). Примером таких отношений являются отношения Родитель и Потомок.
  • Цепочки отношений. Можно задать, что если А связан неким свойством с В, а В с С, то А (или С) относится к заданному классу. Например, если у А есть отец В, а у отца В свой отец С, то А приходится внуком С.

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

Сейчас OWL является фактически стандартным средством для построения онтологий. Этот язык лучше подходит для построения больших и сложных онтологий чем RDFS. Синтаксис OWL позволяет выразить больше разных свойств понятий и отношений между ними. Но и вводит ряд дополнительных ограничений, например, одно и то же понятие нельзя одновременно объявить и как класс и как экземпляр другого класса. Онтологии в OWL жестче, более стандартизированы и, соответственно, более читабельны. Если RDFS это всего лишь несколько дополнительных классов поверх RDF графа, то OWL имеет другую математическую основу дескрипционную логику. Соответственно, становятся доступны и формальные процедуры логического вывода, позволяющие извлекать новую информацию из OWL онтологий, проверять их согласованность и отвечать на вопросы.

Дескрипционная или описательная логика (descriptive logic) является фрагментом логики первого порядка. В ней допустимы только одноместные (например, принадлежность понятия к классу), двухместные предикаты (наличие у понятия свойства и его значения), а также конструкторы классов и свойства отношений, перечисленные выше. Все остальные выражения логики первого порядка в дескрипционной логике отброшены. Например, допустимыми будут утверждения, что понятие Неоплаченный счет относится к классу Счет, понятие Счет имеет свойства Сумма к оплате и Оплаченная сумма. Но вот сделать утверждение, что у понятия Неоплаченный счет свойство Сумма к оплате должно быть больше свойства Оплаченная сумма уже не получится. Для этого понадобится правило, которое будет включать предикат сравнения этих свойств. К сожалению, конструкторы OWL не позволяют сделать это.
Таким образом, выразительность дискрипционной логики ниже, чем у логики первого порядка. Но, с другой стороны, алгоритмы логического вывода в дескрипционной логике гораздо быстрее. Кроме того, она обладает свойством разрешимости решение гарантированно может быть найдено за конечное время. Считается, что на практике такого словаря вполне достаточно для построения сложных и объемных онтологий, и OWL это хороший компромисс между выразительностью и эффективностью логического вывода.

Также стоит упомянуть SWRL (Semantic Web Rule Language), который сочетает возможность создания классов и свойств в OWL с написанием правил на ограниченной версии языка Datalog. Стиль таких правил такой же, как и в языке Prolog. SWRL поддерживает встроенные предикаты для сравнения, математических операций, работы со строками, датами и списками. Это как раз то, чего нам не хватало для того, чтобы с помощью одного простого выражения реализовать понятие Неоплаченный счет.

Flora-2.


В качестве альтернативы семантическим сетям рассмотрим также такую технологию как фреймы. Фрейм это структура, описывающая сложный объект, абстрактный образ, модель чего-либо. Он состоит из названия, набора свойств (характеристик) и их значений. Значением свойства может быть другой фрейм. Также у свойства может быть значение по умолчанию. К свойству может быть привязана функция вычисления его значения. В состав фрейма также могут входить служебные процедуры, в том числе обработчики таких событий так создание, удаление фрейма, изменение значения свойств и др. Важным свойством фреймов является возможность наследования. Дочерний фрейм включает в себя все свойства родительских фреймов.
Система связанных фреймов формирует семантическую сеть, очень похожую на RDF граф. Но в задачах создания онтологий фреймы были вытеснены языком OWL, который сейчас является фактическим стандартом. OWL более выразителен, имеет более продвинутое теоретическое основание формальную дискрипционную логику. В отличии от RDF и OWL, в которых свойства понятий описываются независимо друг от друга, в фреймовой модели понятие и его свойства рассматриваются как единой целое фрейм. Если в моделях RDF и OWL в вершинах графа находятся имена понятий, а в ребрах их свойства, то во фреймовой модели в вершинах графа расположены понятия со всеми их свойствами, а в ребрах связи между их свойствами или отношения наследования между понятиями.
В этом фреймовая модель очень близка модели объектно-ориентированного программирования. Они во многом совпадают, но имеют разную сферу применения фреймы направлены на моделирование сети понятий и отношений между ними, а ООП на моделирование поведения объектов, их взаимодействия между собой. Поэтому в ООП доступны дополнительные механизмы скрытия деталей реализации одного компонента от других, ограничения доступа к методам и полям класса.

Современные фреймовые языки (такие как KL-ONE, PowerLoom, Flora-2) комбинируют составные типы данных объектной модели с логикой первого порядка. В этих языках можно не только описывать структуру объектов, но и оперировать этими объектами в правилах, создавать правила, описывающие условия принадлежности объекта заданному классу и т.д. Механизмы наследования и композиции классов получают логическую трактовку, которая становится доступна для использования процедурам логического вывода. Выразительность этих языков выше, чем у OWL, они не ограничены двухместными предикатами.
В качестве примера попробуем реализовать наш пример с должниками на языке Flora-2. Этот язык включает в себя 3 компонента: фреймовую логику F-logic, объединяющую фреймы и логику первого порядка, логику высших порядков HiLog, предоставляющую инструменты для формирования высказываний о структуре других высказываний и мета-программирования, и логику изменений Transactional Logic, позволяющую в логической форме описывать изменения в данных и побочные эффекты (side effects) вычислений. Сейчас нас интересует только фреймовая логика F-logic. Для начала с ее помощью объявим структуру фреймов, описывающих понятия (классы) клиентов и должников:
client[|name => \string,
email => \string
|].
bill[|client => client,
date => \string,
amountToPay => \number,
amountPaid => \number,
amountPaid -> 0
|].

Теперь мы можем объявить экземпляры (объекты) этих понятий:
client1 : client[name -> 'John', email -> 'john@somewhere.net'].
client2 : client[name -> 'Mary', email -> 'mary@somewhere.net'].
bill1 : bill[client -> client1,
date -> '2020-01',
amountToPay -> 100
].
bill2 : bill[client -> client2,
date -> '2020-01',
amountToPay -> 80,
amountPaid -> 80
].

Символ '->' означает связь атрибута с конкретным значением у объекта и значение по умолчанию в объявлении класса. В нашем примере поле amountPaid класса bill имеет нулевое значение по умолчанию. Символ ':' означает создание сущности класса: client1 и client2 являются сущностями класса client.
Теперь мы можем объявить, что понятия Неоплаченный счет и Должник являются подклассами понятий Счет и Клиент:
unpaidBill :: bill.
debtor :: client.

Символ '::' объявляет отношение наследования между классами. Наследуется структура класса, методы и значения по умолчанию для всех его полей. Осталось объявить правила, задающие принадлежность к классам unpaidBill и debtor:
?x : unpaidBill :- ?x : bill[amountToPay -> ?a, amountPaid -> ?b], ?a > ?b.
?x : debtor :- ?x : client, ?_ : unpaidBill[client -> ?x].

В первом высказывании утверждается, что переменная является сущностью класса unpaidBill, если она является сущностью класса bill, и значение ее поля amountToPay больше значения amountPaid. Во втором, что относится к классу unpaidBill, если она относится к классу client и существует хотя бы одна сущность класса unpaidBill, у которой значение поля client равно переменной . Эта сущность класса unpaidBill будет связана с анонимной переменной ?_, значение которой в дальнейшем не используется.
Получить список должников можно с помощью запроса:
?- ?x:debtor.
Мы просим найти все значения, относящиеся к классу debtor. Результатом будет список всех возможных значений переменной ?x:
?x = client1

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

SQL


Напоследок рассмотрим основные особенности синтаксиса SQL. В прошлой публикации мы говорили, что SQL имеет логическую теоретическую основу реляционное исчисление, и рассмотрели реализацию примера с должниками на LINQ. В плане семантики SQL близок к фреймовым языкам и ООП модели в реляционной модели данных основным элементом является таблица, которая воспринимается как единое целое, а не как набор отдельных свойств.
Синтаксис SQL прекрасно соответствует такой ориентации на таблицы. Запрос разбит на секции. Сущности модели, которые представлены таблицами, представлениями (view) и вложенными запросами, вынесены в секцию FROM. Связи между ними указываются с помощью операций JOIN. Зависимости между полями и другие условия находятся в секциях WHERE и HAVING. Вместо логических переменных, связывающих аргументы предикатов, в запросе мы оперируем полями таблиц напрямую. Такой синтаксис описывает структуру модели предметной области более наглядно по сравнению с линейным синтаксисом Prolog.

Каким я вижу стиль синтаксиса языка моделирования.


На примере со неоплаченными счетами мы можем сравнить такие подходы как логическое программирование (Prolog), фреймовую логику (Flora-2), технологии семантической паутины (RDFS, OWL и SWRL) и реляционное исчисление (SQL). Их основные характеристики я свел в таблицу:
Язык Математическая основа Ориентация стиля Сфера применения
Prolog Логика первого порядка На правила Системы, основанные на правилах, сопоставление с образцом.
RDFS Граф На связи между понятиями Схема данных WEB ресурса
OWL Дескрипционная логика На связи между понятиями Онтологии
SWRL Урезанная версия логики первого порядка как у Datalog На правила поверх связей между понятиями Онтологии
Flora-2 Фреймы + логика первого порядка На правила поверх структуры объектов Базы данных, моделирование сложных систем, интеграция разрозненных данных
SQL Реляционное исчисление На структуры таблиц Базы данных

Теперь нужно подобрать математическую основу и стиль синтаксиса для языка моделирования, предназначенного для работы со слабоструктурированными данными и интеграцией данных из разрозненных источников, который бы сочетался с объектно-ориентированными и функциональными языками программирования общего назначения.
Наиболее выразительными языками является Prolog и Flora-2 они основаны на полной логике первого порядка с элементами логики высших порядков. Остальные подходы являются ее подмножествами. За исключением RDFS он вообще не связан с формальной логикой. На данном этапе полноценная логика первого порядка мне видится предпочтительным вариантом. Для начала я планирую остановиться на нем. Но и ограниченный вариант в виде реляционного исчисления или логики дедуктивных баз данных тоже имеет свои преимущества. Он обеспечивает большую производительность при работе с большими объемами данных. В будущем его стоит рассмотреть отдельно. Дескрипционная логика выглядит слишком ограниченной и неспособной выразить динамические отношения между понятиями.
С моей точки зрения, для работы со слабоструктурированными данными и интеграции разрозненных источников данных фреймовая логика подходит больше, чем Prolog, ориентированный на правила, или OWL, ориентированный на связи и классы понятий. Фреймовая модель описывает структуры из объектов в явном виде, фокусирует на них внимание. В случае объектов с большим количеством свойств фреймовая форма гораздо более читабельна, чем правила или триплеты субъект-свойство-объект. Наследование также является очень полезным механизмом, позволяющим значительно сократить объем повторяющегося кода. По сравнению с реляционной моделью фреймовая логика позволяет описать сложные структуры данных, такие как деревья и графы, более естественным образом. И, самое главное, близость фреймовой модели описания знаний к модели ООП позволит интегрировать их в одном языке естественным образом.
У SQL я хочу позаимствовать структуру запроса. Определение понятия может иметь сложную форму и его не помешает разбить на секции, чтобы подчеркнуть его составные части и облегчить восприятие. Кроме того, для большинства разработчиков синтаксис SQL довольно привычен.

Итак, за основу языка моделирования я хочу взять фреймовую логику. Но поскольку целью является описание структур данных и интеграция разрозненных источников данных я попробую отказаться от синтаксиса, ориентированного на правила, и заменить его на структурированный вариант, позаимствованный у SQL. Основным элементом модели предметной области будет понятие (concept). В его определение я хочу включить всю информацию, необходимую для извлечения его сущностей (entities) из исходных данных:
  • имя понятия;
  • набор его атрибутов;
  • набор исходных (родительских) понятий, служащих для него источниками данных;
  • набор условий, связывающих между собой атрибуты производного и исходного понятий;
  • набор условий, ограничивающих возможные значения атрибутов понятий.

Определение понятия будет напоминать SQL запрос. А вся модель предметной области будет иметь форму взаимосвязанных понятий.

Получившийся синтаксис языка моделирования я планирую показать в следующей публикации. Для тех, кто хочет познакомиться с ним уже сейчас, есть полный текст в научном стиле на английском языке, доступный по ссылке:
Hybrid Ontology-Oriented Programming for Semi-Structured Data Processing

Ссылки на предыдущие публикации:
Проектируем мульти-парадигменный язык программирования. Часть 1 Для чего он нужен?
Проектируем мульти-парадигменный язык программирования. Часть 2 Сравнение построения моделей в PL/SQL, LINQ и GraphQL
Подробнее..

Проектируем мульти-парадигменный язык программирования. Часть 4 Основные конструкции языка моделирования

26.11.2020 14:19:49 | Автор: admin
Продолжаем рассказ о создании мульти-парадигменного языка программирования, сочетающего декларативный стиль с объектно-ориентированным и функциональным, который был бы удобен при работе со слабоструктурированными данными и интеграции данных из разрозненных источников. Наконец-то после введения и обзоров существующих мульти-парадигменных технологий и языков представления знаний мы добрались до описания той части гибридного языка, которая ответственна за описание модели предметной области. Я назвал ее компонентой моделирования.
Компонента моделирования предназначена для декларативного описания модели предметной области в форме онтологии сети из экземпляров данных (фактов) и абстрактных понятий, связанных между собой с помощью отношений. В ее основе лежит фреймовая логика гибрид объектно-ориентированного подхода к представлению знаний и логики первого порядка. Ее основной элемент понятие, описывающее моделируемый объект с помощью набора атрибутов. Понятие строится на основе других понятий или фактов, исходные понятия назовем родительскими, производное дочерним. Отношения связывают значения атрибутов дочернего и родительских понятий или ограничивают их возможные значения. Я решил включить отношения в состав определения понятия, чтобы вся информация о нем находилась по возможности в одном месте. Стиль синтаксиса для определений понятий будет похож на SQL атрибуты, родительские понятия и отношения между ними должны быть разнесены по разным секциям.
В этой публикации я хочу представить основные способы определения понятий.

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

Начнем с фактов.


Факты представляют собой описание конкретных знаний о предметной области в виде именованного набора пар ключ-значение:
fact <имя факта> {
<имя атрибута> : <значение атрибута>
...
}

Например:
fact product {
name: Cabernet Sauvignon,
type: red wine,
country: Chile
}


Имя факта может быть не уникальным, например, может быть множество продуктов с разным названием, типом и страной происхождения. Будем считать факты идентичными, если совпадают их имена, а также имена и значения их атрибутов.
Можно провести аналогию между фактами компоненты моделирования и фактами языка Prolog. Их отличие заключается только в синтаксисе. В Prolog аргументы фактов идентифицируются по их позиции, а атрибуты фактов компоненты моделирования по имени.

Понятия.


Понятие представляет собой структуру, описывающую абстрактную сущность и основанную на других понятиях и фактах. Определение понятия включает в себя имя, списки атрибутов и дочерних понятий. А также логическое выражение, описывающее зависимости между его (дочернего понятия) атрибутами и атрибутами родительских понятий, позволяющие вывести значение атрибутов дочернего понятия:
concept <имя понятия> <псевдоним понятия> (
<имя атрибута> = <выражение>,
...
)
from
<имя родительского понятия> <псевдоним родительского понятия> (
<имя атрибута> = <выражение>
...
),

where <выражение отношений>

Пример определения понятия profit на основе понятий revenue и cost:
concept profit p (
value = r.value c.value,
date
) from revenue r, cost c
where p.date = r.date = c.date


Определение понятия похоже по форме на SQL запрос, но вместо имени таблиц нужно указывать имена родительских понятий, а вместо возвращаемых столбцов атрибуты дочернего понятия. Кроме того, понятие имеет имя, по которому к нему можно обращаться в определениях других понятий или в запросах к модели. Родительским понятием может быть как непосредственно понятие, так и факты. Выражение отношений в секции where это булево выражение, которое может включать логические операторы, условия равенства, арифметические операторы, вызовы функций и др. Их аргументами могут быть переменные, константы и ссылки на атрибуты как родительских так и дочернего понятий. Ссылки на атрибуты имеют следующий формат:
<псевдоним понятия>.<имя атрибута>
По сравнению с фреймовой логикой в определении понятия его структура (атрибуты) объединена с отношениями с другими понятиями (родительские понятия и выражение отношений). С моей точки зрения это позволяет сделать код более понятным, так как вся информация о понятии собрана в одном месте. А также соответствует принципу инкапсуляции в том смысле, что детали реализации понятия скрыты внутри его определения. Для сравнения небольшой пример на языке фреймовой логики можно найти в прошлой публикации.
Выражение отношений имеет конъюнктивную форму (состоит из выражений, соединенных логическими операциями AND) и должно включать условия равенства для всех атрибутов дочернего понятия, достаточные для определения их значений. Кроме того, в него могут входить условия, ограничивающие значения родительских понятий или связывающие их между собой. Если в секции where будут связаны между собой не все родительские понятия, то механизм логического вывода вернет все возможные комбинации их значений в качестве результата (аналогично операции FULL JOIN языка SQL).
Для удобства часть условий равенства атрибутов может быть вынесена в секции атрибутов дочернего и родительских понятий. Например, в определении понятия profit условие для атрибута value вынесено в секцию атрибутов, а для атрибута date оставлено в секции where. Также можно перенести их и в секцию from:
concept profit p (
value = r.value c.value,
date = r.date
) from revenue r, cost c (date = r.date)

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

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

Поскольку список родительских понятий и условия отношений разнесены по отдельным секциям, логический вывод будет немного отличаться от такового в Prolog. Опишу в общем виде его алгоритм. Вывод родительских понятий будет выполнен в том порядке, в котором они указаны в секции from. Поиск решения для следующего понятия выполняется для каждого частичного решения предыдущих понятий так же, как и в SLD резолюции. Но для каждого частичного решения выполняется проверка истинности выражения отношений из секции where. Поскольку это выражение имеет форму конъюнкции, то каждое подвыражение проверяется отдельно. Ели подвыражение ложно, то данное частичное решение отвергается и поиск переходит к следующему. Если часть аргументов подвыражения еще не определена (не связана со значениями), то его проверка откладывается. Если подвыражением является оператор равенства и определен только один из его аргументов, то система логического вывода найдет его значение и попытается связать его с оставшимся аргументом. Это возможно, если свободным аргументом является атрибут или переменная.
Например, при выводе сущностей понятия profit сначала будут найдены сущности понятия revenue, и, соответственно, значения его атрибутов. После чего равенство p.date = r.date = c.date в секции where даст возможность связать со значениями атрибуты date и других понятий. Когда логический поиск доберется до понятия cost, значение его атрибута date будет уже известно и будет является входным аргументом для этой ветви дерева поиска. Подробно рассказать об алгоритмах логического вывода я планирую в одной из следующих публикаций.
Отличие от Prolog заключается в том, что в правилах Prolog все является предикатами и обращения к другим правилам и встроенные предикаты равенства, сравнения и др. И порядок их проверки нужно указывать явным образом, например, сначала должны идти два правила а затем равенство переменных:
profit(value,date) :- revenue(rValue, date), cost(cValue, date), value = rValue cValue
В таком порядке они и будут выполнены. В компоненте моделирования же предполагается, что все вычисления условий в секции where являются детерминированными, то есть не требуют рекурсивного погружения в следующую ветвь поиска. Поскольку их вычисление зависит только от их аргументов, они могут быть вычислены в произвольном порядке по мере связывания аргументов со значениями.

В результате логического вывода все атрибуты дочернего понятия должны быть связаны со значениями. А также выражение отношений должно быть истинно и не содержать неопределенных подвыражений. Стоит заметить, что вывод родительских понятий не обязательно должен быть успешным. Допустимы случаи, когда требуется проверить неудачу выведения родительского понятия из исходных данных, например, в операциях отрицания. Порядок родительских понятий в секции from определяет порядок обхода дерева решений. Это дает возможность оптимизировать поиск решения, начав его с тех понятий, которые сильнее ограничивают пространство поиска.
Задача логического вывода найти все возможные подстановки атрибутов дочернего понятия и каждую из них представить в виде объекта. Такие объекты считаются идентичными если совпадают имена их понятий, имена и значения атрибутов.

Допустимым считается создание нескольких понятий с одинаковым именем, но с разной реализацией, включая различный набор атрибутов. Это могут быть разные версии одного понятия, родственные понятия, которые удобно объединить под одним именем, одинаковые понятия из разных источников и т.п. При логическом выводе будут рассмотрены все существующие определения понятия, а результаты их поиска будут объединены. Несколько понятий с одинаковыми именами аналогичны правилу в языке Prolog, в котором список термов имеет дизъюнктивную форму (термы связаны операцией ИЛИ).

Наследование понятий.


Одними из наиболее распространенных отношений между понятиями являются иерархические отношения, например род-вид. Их особенностью является то, что структуры дочернего и родительского понятий будут очень близки. Поэтому поддержка механизма наследования на уровне синтаксиса очень важна, без нее программы будут переполнены повторяющимся кодом. При построении сети понятий было бы удобно повторно использовать как их атрибуты, так и отношения. Если список атрибутов легко расширять, сокращать или переопределять некоторые из них, то с модификацией отношений дело обстоит сложнее. Поскольку они представляют собой логическое выражение в конъюнктивной форме, то к нему легко прибавить дополнительные подвыражения. Но удаление или изменение может потребовать значительного усложнения синтаксиса. Польза от этого не так очевидна, поэтому отложим эту задачу на будущее.
Объявить понятие на основе наследования можно с помощью следующей конструкции:
concept <имя понятия> <псевдоним понятия> is
<имя родительского понятия> <псевдоним родительского понятия> (
<имя атрибута> = <выражение>,
...
),
...
with <имя атрибута> = <выражение>, ...
without <имя родительского атрибута>, ...
where <выражение отношений>

Секция is содержит список наследуемых понятий. Их имена можно указать напрямую в этой секции. Или же указать полный список родительских понятий в секции from, а в is псевдонимы только тех из них, которые будут наследоваться:
concept <имя понятия> <псевдоним понятия> is
<псевдоним родительского понятия>,

from
<имя родительского понятия> <псевдоним родительского понятия> (
<имя атрибута> = <выражение>
...
),

with <имя атрибута> = <выражение>, ...
without <имя родительского атрибута>, ...
where <выражение отношений>

Секция with позволяет расширить список атрибутов наследуемых понятий или переопределить некоторые из них, секция without сократить.

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

Рассмотрим несколько примеров использования механизма наследования. Наследование позволяет создать понятие на основе уже существующего избавившись от тех атрибутов, которые имеют смысл только для родительского, но не для дочернего понятия. Например, если исходные данные представлены в виде таблицы, то ячейкам определенных столбцов можно дать свои имена (избавившись от атрибута с номером столбца):
concept revenue is tableCell without columnNum where columnNum = 2
Также можно преобразовать несколько родственных понятий в одну обобщенную форму. Секция with понадобится для того, чтобы преобразовать часть атрибутов к общему формату и добавить недостающие. Например, исходными данными могут быть документы разных версий, список полей которых менялся со временем:
concept resume is resumeV1 with skills = 'N/A'
concept resume is resumeV2 r with skills = r.coreSkills

Предположим, что в первой версии понятия Резюме не было атрибута с навыками, а во второй он назывался по-другому.
Расширение списка атрибутов может потребоваться во многих случаях. Распространенными задачами являются смена формата атрибутов, добавление атрибутов, функционально зависящих от уже существующих атрибутов или внешних данных и т.п. Например:
concept price is basicPrice with valueUSD = valueEUR * getCurrentRate('USD', 'EUR')
Также можно просто объединить несколько понятий под одним именем не меняя их структуру. Например, для того чтобы указать, что они относятся к одному роду:
concept webPageElement is webPageLink
concept webPageElement is webPageInput

Или же создать подмножество понятия, отфильтровав часть его сущностей:
concept exceptionalPerformer is employee where performanceEvaluationScore > 0.95

Возможно также множественное наследование, при котором дочернее понятие наследует атрибуты всех родительских понятий. При наличии одинаковых имен атрибутов приоритет будет отдан тому родительскому понятию, которое находится в списке левее. Также можно решить этот конфликт вручную, явно переопределив нужный атрибут в секции with. Например, такой вид наследования был бы удобен, если нужно собрать в одной плоской структуре несколько связанных понятий:
concept employeeInfo is employee e, department d where e.departmentId = d.id

Наследование без изменения структуры понятий усложняет проверку идентичности объектов. В качестве примера рассмотрим определение exceptionalPerformer. Запросы к родительскому (employee) и дочернему (exceptionalPerformer) понятиям вернут одну и ту же сущность сотрудника. Объекты, представляющие ее, будут идентичны по смыслу. У них будет общий источник данных, одинаковый список и значения атрибутов, на разное имя понятия, зависящее от того, к какому понятию был выполнен запрос. Поэтому операция равенства объектов должна учитывать эту особенность. Имена понятий считаются равными, если они совпадают или связаны транзитивным отношением наследования без изменения структуры.

Наследование это полезный механизм, позволяющий выразить явным образом такие отношения между понятиями как класс-подкласс, частное-общее, множество-подмножество. А также избавиться от дублирования кода в определениях понятий и сделать код более понятным. Механизм наследования основан на добавлении/удалении атрибутов, объединении нескольких понятий под одним именем и добавлении условий фильтрации. Никакой специальной семантики в него не вкладывается, каждый может воспринимать и применять его как хочет. Например, построить иерархию от частного к общему как в примерах с понятиями resume, price и webPageElement. Или, наоборот, от общего к частному, как в примерах с понятиями revenue и exceptionalPerformer. Это позволит гибко подстроиться под особенности источников данных.

Понятие для описания отношений.


Было решено, что для удобства понимания кода и облегчения интеграции компоненты моделирования с ООП моделью, отношения дочернего понятия с родительскими должны быть встроены в его определение. Таким образом, эти отношения задают способ получения дочернего понятия из родительских. Если модель предметной области строится слоями, и каждый новый слой основан на предыдущем, это оправдано. Но в некоторых случаях отношения между понятиями должны быть объявлены отдельно, а не входить в определение одного из понятий. Это может быть универсальное отношение, которое хочется задать в общем виде и применить к разным понятиям, например, отношение Родитель-Потомок. Либо отношение, связывающее два понятия, необходимо включить в определение обоих понятий, чтобы можно было бы найти как сущности первого понятия при известных атрибутах второго, так и наоборот. Тогда, во избежание дублирования кода отношение удобно будет задать отдельно.
В определении отношения необходимо перечислить входящие в него понятия и задать логическое выражение, связывающее их между собой:
relation <имя отношения>
between <имя вложенного понятия> <псевдоним вложенного понятия> (
<имя атрибута> = <выражение>,
...
),
...
where <логическое выражение>

Например, отношение, описывающее вложенные друг в друга прямоугольники, можно определить следующим образом:
relation insideSquareRelation between square inner, square outer
where inner.xLeft > outer.xLeft and inner.xRight < outer.xRight
and inner.yBottom > outer.yBottom and inner.yUp < outer.yUp

Такое отношение, по сути, представляет собой обычное понятие, атрибутами которого являются сущности вложенных понятий:
concept insideSquare (
inner = i
outer = o
) from square i, square o
where i.xLeft > o.xLeft and i.xRight < o.xRight
and i.yBottom > o.yBottom and i.yUp < o.yUp


Отношение можно использовать в определениях понятий наряду с другими родительскими понятиями. Понятия, входящие в отношения, будут доступны извне и будут играть роль его атрибутов. Имена атрибутов будут соответствовать псевдонимам вложенных понятий. В следующем примере утверждается, что в HTML форму входят те HTML элементы, которые расположены внутри нее на HTML странице:
сoncept htmlFormElement is e
from htmlForm f, insideSquareRelation(inner = e, outer = f), htmlElement e

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

Отношению можно придать и функциональную семантику использовать его как функцию булева типа для проверки, выполняется ли отношение для заданных сущностей вложенных понятий:
сoncept htmlFormElement is e
from htmlElement e, htmlForm f
where insideSquareRelation(e, f)

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

Теперь пришло время рассмотреть небольшой пример.


Определений фактов и основных видов понятий достаточно, чтобы реализовать пример с должниками из первой публикации. Предположим, что у нас есть два файла в формате CSV, хранящих информацию о клиентах (идентификатор клиента, имя и адрес электронной почты) и счетах (идентификатор счета, идентификатор клиента, дата, сумма к оплате, оплаченная сумма).
А также имеется некая процедура, которая считывает содержимое этих файлов и преобразовывает их в набор фактов:
fact cell {
table: TableClients,
value: 1,
rowNum: 1,
columnNum: 1
};
fact cell {
table: TableClients,
value: John,
rowNum: 1,
columnNum: 2
};
fact cell {
table: TableClients,
value: john@somewhere.net,
rowNum: 1,
columnNum: 3
};

fact cell {
table: TableBills,
value: 1,
rowNum: 1,
columnNum: 1
};
fact cell {
table: TableBills,
value: 1,
rowNum: 1,
columnNum: 2
};
fact cell {
table: TableBills,
value: 2020-01-01,
rowNum: 1,
columnNum: 3
};
fact cell {
table: TableBills,
value: 100,
rowNum: 1,
columnNum: 4
};
fact cell {
table: TableBills,
value: 50,
rowNum: 1,
columnNum: 5
};


Для начала дадим ячейкам таблиц осмысленные имена:
concept clientId is cell where table = TableClients and columnNum = 1;
concept clientName is cell where table = TableClients and columnNum = 2;
concept clientEmail is cell where table = TableClients and columnNum = 3;
concept billId is cell where table = TableBills and columnNum = 1;
concept billClientId is cell where table = TableBills and columnNum = 2;
concept billDate is cell where table = TableBills and columnNum = 3;
concept billAmountToPay is cell where table = TableBills and columnNum = 4;
concept billAmountPaid is cell where table = TableBills and columnNum = 5;


Теперь можно объединить ячейки одной строки в единый объект:
concept client (
id = id.value,
name = name.value,
email = email.value
) from clientId id, clientName name, clientEmail email
where id.rowNum = name.rowNum = email.rowNum;


concept bill (
id = id.value,
clientId = clientId.value,
date = date.value,
amountToPay = toPay.value,
amountPaid = paid.value
) from billId id, billClientId clientId, billDate date, billAmountToPay toPay, billAmountPaid paid
where id.rowNum = clientId.rowNum = date.rowNum = toPay.rowNum = paid.rowNum;


Введем понятия Неоплаченный счет и Должник:
concept unpaidBill is bill where amountToPay > amountPaid;
concept debtor is client c where exist(unpaidBill {clientId: c.id});


Оба определения используют наследование, понятие unpaidBill является подмножеством понятия bill, debtor понятия client. Определение понятия debtor содержит вложенный запрос к понятию unpaidBill. Подробно механизм вложенных запросов мы рассмотрим позже в одной следующих публикаций.
В качестве примера плоского понятия определим также понятие Долг клиента, в котором объединим некоторые поля из понятия Клиент и Счет:
concept clientDebt (
clientName = c.name,
billDate = b.date,
debt = b. amountToPay b.amountPaid
) from unpaidBill b, client c(id = b.client);


Зависимость между атрибутами понятий client и bill вынесена в секцию from, а зависимости дочернего понятия clientDebt в секцию его атрибутов. При желании все они могут быть помещены в секцию where результат будет аналогичным. Но с моей точки зрения текущий вариант более краток и лучше подчеркивает назначение этих зависимостей определять связи между понятиями.

Теперь попробуем определить понятие злостного неплательщика, который имеет как минимум 3 неоплаченных счета подряд. Для этого понадобится отношение, позволяющее упорядочить счета одного клиента по их дате. Универсальное определение будет выглядеть следующим образом:
relation billsOrder between bill next, bill prev
where next.date > prev.date and next.clientId = prev.clientId and not exist(
bill inBetween
where next.clientId = inBetween.clientId
and next.date > inBetween.date > prev.date
);

В нем утверждается, что два счета идут подряд, если они принадлежат одному клиенту, дата одного больше даты другого и не существует другого счета, лежащего между ними. На данном этапе я не хочу останавливаться на вопросах вычислительной сложности такого определения. Но если, например, мы знаем, что все счета выставляются с интервалом в 1 месяц, то можно его значительно упростить:
relation billsOrder between bill next, bill prev
where next.date = prev.date + 1 month and next.clientId = prev.clientId;


Последовательность из 3х неоплаченных счетов будет выглядеть следующим образом:
concept unpaidBillsSequence (clientId = b1.clientId, bill1 = b1, bill2 = b2, bill3 = b3)
from
unpaidBill b1,
billsOrder next1 (next = b1, prev = b2)
unpaidBill b2
billsOrder next2 (next = b2, prev = b3)
unpaidBill b3;

В этом понятии сначала будет найдены все неоплаченные счета, затем для каждого из них с помощью отношения next1 будет найден следующий счет. Понятие b2 позволит проверить, что этот счет является неоплаченным. По этому же принципу с помощью next2 и b3 будет найден и третий неоплаченный счет подряд. Идентификатор клиента вынесен в список атрибутов отдельно, чтобы в дальнейшем облегчить связывание этого понятия с понятием клиентов:
concept hardCoreDefaulter is client c where exist(unpaidBillsSequence{clientId: c.id});

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

Краткие выводы.


Итак, я предложил три основных вида понятий компоненты моделирования гибридного языка:
  • понятия, созданные на основе трансформации других понятий;
  • понятия, наследующие структуру и отношения других понятий;
  • понятия, задающие отношения между другими понятиями.

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

В отличии от языков RDF и OWL, компонента моделирования не делает различия между понятиями и отношениями все является понятиями. В отличии от языков фреймовой логики фреймы, описывающие структуру понятия, и правила, задающие связи между ними, объединены вместе. В отличии от традиционных языков логического программирования, таких как Prolog основным элементом модели являются понятия, имеющие объектно-ориентированную структуру, а не правила, имеющие плоскую структуру. Такой дизайн языка может быть не так удобен для создания масштабных онтологий или набора правил, но зато гораздо лучше подходит для работы со слабоструктурированными данными и для интеграции разрозненных источников данных. Понятия компоненты моделирования близки к классам ООП модели, что должно облегчить задачу включения декларативного описания модели в код приложения.

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

Полный текст в научном стиле на английском языке доступен по ссылке: papers.ssrn.com/sol3/papers.cfm?abstract_id=3555711

Ссылки на предыдущие публикации:
Проектируем мульти-парадигменный язык программирования. Часть 1 Для чего он нужен?
Проектируем мульти-парадигменный язык программирования. Часть 2 Сравнение построения моделей в PL/SQL, LINQ и GraphQL
Проектируем мульти-парадигменный язык программирования. Часть 3 Обзор языков представления знаний
Подробнее..

Из песочницы Методология IDEF5. Графический язык

23.08.2020 12:14:59 | Автор: admin

Вступление


Данная статья предназначена для тех, кто знаком с таким понятием как онтология хотя бы на начальном уровне. Если Вы не знакомы с онтологиями, то, скорее всего, Вам будет не ясна цель онтологий и данной статьи в частности. Советую ознакомиться с данным явлением, прежде чем начать чтение данной статьи (возможно хватит даже статьи с Википедии).

Итак Онтология это детальная характеристика некой рассматриваемой предметной области. Такая характеристика должна быть дана на каком-либо четко сформулированном языке. Для описания онтологий можно использовать методологию IDEF5, которая имеет в своем арсенале 2 языка:

  • Схематический язык IDEF5. Этот язык является визуальным и использует графические элементы.
  • Текстовый язык IDEF5. Этот язык представляется в виде структурированного текста.

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

Объекты


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

Зачастую, в онтологии используются как обобщенные сущности, так и конкретные объекты. Обобщенные сущности называются видами. Изображаются они в виде окружности с меткой (названием объекта) внутри:

image

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

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



Также в рамках обсуждения объектов стоит упомянуть такие объекты как процессы.

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

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

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



Процессы используются в схемах перехода одних объектов в другие. Подробнее об этом будет рассказано далее.

Помимо процессов, в таких схемах используются логические операторы. Тут все достаточно просто для тех, кто знаком с предикатами, булевой алгеброй или программированием. В IDEF5 используются три основных логических оператора:

  • логическое И (AND);
  • логическое ИЛИ (OR);
  • исключающее ИЛИ (XOR).

В стандарте IDEF5 (http://personeltest.ru/away/idef.ru/documents/Idef5.pdf большинство информации из данного источника) определено изображение логических операторов в виде малых окружностей (по сравнению с видами и экземплярами) с меткой в виде символов. Однако в разрабатываемой графической среде IDEF5 мы отошли от данного правила по многим причинам. Одна из них сложная идентификация этих операторов. Поэтому мы используем текстовое обозначение операторов с идентификационным номером:



Пожалуй на этом с объектами закончим.

Отношения


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

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

  1. Схемы композиции.
  2. Схемы классификации.
  3. Схемы переходов.
  4. Функциональные схемы.
  5. Комбинированные схемы.

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

Ну а теперь по порядку о каждой из видов схем.

Схемы композиции


Данный тип схем используется для представления состава какого-либо объекта, системы, структуры и т.д. Типичный пример детали автомобиля. В самом укрупненном составе, автомобиль состоит из кузова и трансмиссии. В свою очередь, кузов делится на раму, двери и прочие детали. Такую декомпозицию можно продолжать дальше все зависит от необходимого уровня детализации в данной конкретной задаче. Пример такой схемы:

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

Схемы классификации


Схемы классификации призваны выражать определение видов, их подвидов и экземпляры видов. Например, автомобили могут быть легковыми и грузовыми. То есть вид Автомобиль имеет два подвида. ВАЗ-2110 конкретный экземпляр подвида Легковой автомобиль, а ГАЗ-3307 экземпляр подвида Грузовой автомобиль:



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

Схемы переходов


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



Отношение перехода обозначается стрелкой с наконечником в конце и с кружком в центре. Как видно из схемы, процессы относятся к отношениям, а не к объектам.

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



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

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



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

Функциональные схемы


Такие схемы используются для указания структуры взаимодействия между объектами. Например, автомеханик проводит техобслуживание автомобилей, а менеджер автосервиса принимает заявки на ремонт и передает их автослесарю:



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

Комбинированные схемы


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

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



В конкретном случае в комбинированной схеме используются схема композиции (зеркало + автомобиль без зеркала = автомобиль с зеркалом) и схема перехода (автомобиль с зеркалом под воздействием процесса покраски красной краской становится красным автомобилем). Причем автомобиль с зеркалом не выражается явно вместо этого указывается логический оператор И.

Заключение


В данной статье я постарался описать основные объекты и отношения в методологии IDEF5. В качестве примера я использовал предметную область, связанную с автомобилями, поскольку на их примере оказалось гораздо проще строить схемы. Однако схемы IDEF5 могут быть использованы в любой другой области знаний.

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

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

Надеюсь данная статья станет полезна для начинающих в данной области, может быть даже для тех, кто уже давно занимается вопросом онтологического анализа. Весь основной материал данной статьи переведен и осмыслен был позаимствован из стандарта IDEF5, на который я ссылался раньше (дублирую). Также вдохновлялся замечательной книжкой от авторов из НОУ ИНТУИТ (ссылка на их книгу).
Подробнее..

Дата-центрическая архитектура волшебная пуля от интеграционных проблем

16.06.2021 18:22:08 | Автор: admin

Любой корпоративный ИТ-ландшафт состоит из множества приложений, большинство из которых имеет собственные базы данных. В этих базах хранятся информационные объекты, представляющие бизнес-объекты, события и фазы бизнес-процессов. Многие объекты бизнес-процессов имеют "отражения" сразу в нескольких базах данных: например, единица оборудования промышленного предприятия с разных точек зрения описана в системах бухучета, управления ремонтами и обслуживанием, управления производством и др.

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

А что, если найдется способ избавиться от всех интеграционных проблем разом? Такая "волшебная пуля" существует, и называется она - дата-центрическая архитектура. Ее основная идея состоит в том, чтобы сделать центральным элементом корпоративной ИТ-архитектуры не бизнес-приложения, а данные. Этот принцип изложен в Манифесте дата-центрической архитектуры.

Представьте, что в компании существует единое виртуальное хранилище данных, в котором каждый бизнес-объект или событие существует в единственном экземпляре. Для наглядности можно вообразить, что идея системы MDM (Master Data Management) доведена до логически полного воплощения, и именно MDM является хранилищем всех корпоративных данных; бизнес-приложения не имеют собственных СУБД и работают только с объектами данных из MDM. Преимущества такой архитектуры очевидны:

  • Раз и навсегда отменяется необходимость в интеграционных процедурах.

  • Снижаются затраты на хранение данных за счет избавления от множества копий каждого бизнес-объекта в разных системах.

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

  • Повышается качество данных за счет избавления от неполных, не актуальных представлений бизнес-объектов.

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

"Это какая-то фантастика", скажут некоторые. Нельзя же выбросить все существующие бизнес-приложения и начать с чистого листа, вывернув наизнанку всю корпоративную ИТ-архитектуру?

Нужен плавный процесс перехода, и его вполне можно обеспечить, если думать о корпоративной платформе управления данными не только как о физическом хранилище, содержащем материализованные представления всех бизнес-объектов, но и как о логической витрине данных, способной извлекать эти объекты из любых хранилищ, в том числе баз данных и сервисов унаследованных бизнес-приложений. Клиенту платформы должно быть безразлично, где находятся нужные ему данные - в одном из множества хранилищ, спрятанных внутри платформы, или в СУБД какого-либо бизнес-приложения. На практике, вероятнее всего, нужный объект данных будет собран платформой в момент выполнения запроса из нескольких источников.

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

Чем такой подход отличается от создания "обычного" корпоративного облака данных (corporate data cloud) или озера данных (data lake)? Прежде всего - методологией использования платформы, особым вниманием к структуре данных и некоторой функциональной спецификой. Если обычный data lake часто представляет собой коллекцию наборов данных, созданных кем-то для решения конкретных задач и заведомо содержащих копию уже существующей где-то информации, то для дата-центрической архитектуры принципиально соблюдение принципа "один объект в реальном мире - один объект данных". И никаких физических срезов, по крайней мере персистентных...

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

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

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

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

  • Поддерживать хранение состояния каждого объекта данных на любой момент времени. Объекты данных - не просто отражения текущего состояния объектов или событий реального мира, а "четырехмерные" описания всех состояний на протяжении всего времени жизни объекта.

  • Хранить непрерывную историю модели (структуры) данных. Структура данных столь же изменчива, как и сами данные. Платформа должна иметь возможность представлять объекты данных в соответствии с любой версией структуры. Структура должна формально описывать смысл каждого элемента данных.

  • Поддерживать множество API для работы с данными, включая REST, GraphQL, SPARQL.

  • Предоставлять возможности обнаружения и поиска данных.

  • Иметь развитые инструменты управления доступом к данным и защиты конфиденциальной информации.

  • Поддерживать инструменты прослеживания происхождения данных (data provenance), контроля их качества (data quality), описания степени доверия к данным.

Построение подобных платформ с использованием онтологических моделей открывает и другие возможности. В онтологической модели можно описать в машинно-читаемой и автоматически исполняемой форме не только структуру данных, но и алгоритмы их обработки - правила контроля целостности, арифметических вычислений, дополнения информации (см. спецификации SHACL и SHACL Advanced Functions). Это позволяет по-новому взглянуть и на принцип low code: если в единой корпоративной платформе управления данными хранятся не только данные и описание их структуры, но и машинно-читаемое описание алгоритмов обработки данных, то новые бизнес-приложения, ориентированные на использование таких описаний, станут еще гибче и смогут изменять свое поведение "на лету" без вмешательства не только в код, но и в настройки приложений.

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

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru