Skip to content

Выражения классов и вычисление значений свойств

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

  1. для создания т.н. вычисляемых (динамических) классов, экземплярами которых являются любые объекты OSA, удовлетворяющие условиям правила
  2. для вычисления отношений между объектами
  3. для вычисления скалярных свойств
  4. для ограничения диапазонов отношений
  5. для значений свойств по умолчанию при создании экземпляров
  6. для имяобразования экземпляров

Как создавать правила показано в разделе Создание правил.

Работа с текстом правила

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

[Оборудование].[имеет_повреждение].[нормативное_время_устранения__минуты] > 1

Внимание

Объекты OSA добавляются в текст правила единственным способом: нужно начать набирать любую часть названия объекта не содержащую пробелов, нажать комбинацию клавиш на клавиатуре Ctrl+Пробел (Ctrl + Fn + Пробел на macOS) и в выпадающем списке выбрать нужный объект.

Ввод точки сразу после объекта OSA приведет к отображению списка свойств этого объекта:

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

Первым объектом в цепочке объектов может быть "виртуальный" объект [Thing], который обозначает любой объект OSA (класс, отношение, скалярное свойств и экземпляр любого класса). Ввод точки после объекта [Thing] приведет к отображению списка всех отношений и свойств системы.

Скалярные значения (числа, строки, даты) в тексте правила

  • скалярные значения вводятся с клавиатуры
  • строки и даты должны быть заключены в двойные кавычки
  • даты указываются в формате "ГГГГ-ММ-ДД"
  • разделителем целой и дробной части в вещественных числах является точка

Приоритет операции в тексте правила

Для указания приоритета в тексте правила используются круглые скобки ( ) и логические операторы or (или) и and (и).

Выражения классов

В этом разделе приведены ключевые слова и примеры использования правил, используемых для определения т.н. динамических классов. Экземплярами динамических классов являются экземпляры, удовлетворяющие условиям описанным в правилах.

Thing

Любой объект OSA (класс, отношение, скалярное свойств и экземпляр любого класса).

[Thing].[имеет_вес] > 5

Любые экземпляры, которые имеют вес, больший чем 5 кг

[Thing].[name] = "Игорь"

Любые экземпляры, название которых в точности Игорь

inverse

Инверсия отношения

[Человек].inverse([имеет_ребенка]) in ([Человек])

Все объекты суждений Человек имеет ребенка Человек, т.е. люди, являющиеся родителями

in

Указание диапазона поиска типа "любой из указанных в диапазоне".

[Человек].[имеет_ребенка] in ([Человек])

Все субъекты суждений Человек имеет ребенка Человек, т.е. люди, имеющие детей (родители)

[Человек].[имеет_ребенка] in ([Вячеслав],[Дмитрий])

Родители Вячеслава и Дмитрия. Вячеслав и Дмитрий в данном случае - это конкретные (именованные) экземпляры

([Человек].[имеет_ребенка] in ([Вячеслав],[Дмитрий])) and ([Человек] in ([Женщина]))

или

([Человек].[имеет_ребенка] in ([Вячеслав],[Дмитрий])) and ([Человек].[Наследует_классам] = [Женщина])

или

[Женщина].[имеет_ребенка] in ([Вячеслав],[Дмитрий])

Все три правила находят матерей Вячеслава и Дмитрия

in only

Указание диапазона поиска типа "никакие другие, кроме указанного".

Предположим, что в онтологии хранятся следующие утверждения:

Человекимеет питомца
ВладимирБобик, Мурка
НатальяЦарапка
АркадийРэкс
АнатолийМухтар, Пушок, Гоша

при этом Бобик, Мухтар и Рэкс являются экземплярами класса Собака; Мурка, Царапка и Пушок - экземплярами класса Кошка, а Гоша - экземпляр класса Попугай.

[Человек].[имеет_питомца] in ([Кошка])

Правило найдет три экземпляра: Владимир, Наталья и Анатолий, т.к. они имеют питомца Кошка.

[Человек].[имеет_питомца] in only ([Кошка])

Правило найдет один экземпляр Наталья, т.к. только Наталья имеет питомца Кошка и никаких других питомцев не имеет.

in all

Указание диапазона поиска типа "все указанные в диапазоне".

[Человек].[имеет_питомца] in ([Кошка],[Собака])

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

[Человек].[имеет_питомца] in all ([Кошка],[Собака])

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

in only all

Указание диапазона поиска типа "все указанные в диапазоне и никакие другие".

[Человек].[имеет_питомца] in only all ([Кошка],[Собака])

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

not in

Указание диапазона поиска типа "любые, кроме указанных в диапазоне".

[Человек].[имеет_питомца] not in ([Кошка],[Собака])

Правило найдет всех людей, которые имеют любых питомцев, кроме кошек и собак.

max

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

Рассмотрим использование ключевого слова max на примере следующей онтологии:

img

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

[История_цен] in ([История_цен] by max([История_цен].[действует_с]) group [История_цен].[бензин])

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

На иллюстрации ниже представлены экземпляры "динамического" класса Актуальная цена, созданного с использованием приведенного выше правила. Видно, что экземпляр с ценой 40 руб. за бензин марки АИ-92 (действует с 2021-05-01) не был найден, т.к. существует цена на этот бензин, действующая с 2021-06-01.

img

min

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

Рассмотрим использование ключевого слова min на примере следующей онтологии:

img

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

[Цена_поставщика] in ([Цена_поставщика] by min([Цена_поставщика].[цена_руб]) group [Цена_поставщика].[бензин])

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

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

img

count

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

[Люди].count([имеет_собаку]) = 0

Люди, у которых нет собак

[Люди].count([имеет_собаку]) > 2

Люди, у которых больше двух собак

Следующие примеры рассмотрим на онтологии:

Человекимеет мать
АлександрТатьяна
СергейТатьяна
АлексейТатьяна
Татьяна

[Человек].count(inverse([имеет_мать])) >= 3

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

[Человек].count([имеет_мать]) > 0

Это правило находит людей, у которых есть мать. Для рассматриваемой онтологии правило найдет три экземпляра Александр, Алексей и Сергей, т.к. эти три экземпляра связаны с Татьяна по отношению имеет мать.

name

Поиск экземпляров по наименованию.

[Thing].[name] = "Игорь"

Любые экземпляры, наименование которых в точности Игорь

Следующие правила рассмотрим на примере онтологии, содержащей следующие простые суждения:

СубъектПредикатОбъект
Дмитрийнаследует классуМужчина
Вячеславнаследует классуМужчина
Дмитрийимеет отцаВячеслав

[Мужчина].[имеет_отца].[name] = "Вячеслав"

Будут найдены мужчины, отца которых зовут Вячеслав, в нашем случае - это Дмитрий. Т.е. будут найдены дети Вячеслава.

[Мужчина].inverse([имеет_отца]).[name] = "Дмитрий"

Будут найдены мужчины, которые являются отцами для Дмитрий, в нашем случае - это Вячеслав. Ключевое слово inverse определяет направление поиска по отношению, инверсному указанному в правиле.

today

Поиск экземпляров по текущей дате.

[Thing].[Дата_создания] = today

Все экземпляры, созданные в день выполнения правила.

[Thing].[Дата_создания] > today - 7 and [Thing].[Дата_создания] < today + 1

Все экземпляры, созданные за последнюю неделю от даты выполнения правила.

user

Поиск экземпляров по текущему пользователю. Результат правил с использованием ключевого слова user зависит от пользователя, под учетной записью которого выполняется правило.

[Thing].[Экземпляр_создан_пользователем] = user

Все экземпляры, созданные текущим пользователем.

is empty

Поиск экземпляров с неустановленным значением свойства.

[Thing].[Наследует_классам] is empty

эквивалентно

[Thing].count([Наследует_классам]) = 0

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

is not empty

Поиск экземпляров с установленным значением свойства.

[Thing].[Наследует_классам] is not empty

эквивалентно

[Thing].count([Наследует_классам]) > 0

Все экземпляры, которые наследуют хотя бы одному классу.

includes / notIncludes

Поиск экземпляров включающих / не включающих определенные значения в указанном свойстве.

[Человек].[имеет_питомца].[Наследует_классам].includes([Собака])

Все люди, имеющие питомцев-собак.

[Человек].[имеет_питомца].[Наследует_классам].notIncludes([Собака])

Все люди, не имеющие питомцев-собак.

Важно

  1. includes и notIncludes учитывают иерархию классов при вычислении наследования:
  • правило [Человек].[имеет_питомца].[Наследует_классам].includes([Собака]) вернет true даже в том случае, если у человека будет питомец из класса "Такса", являющего подклассом класса "Собака".
  1. includes и notIncludes могут быть использованы для вычисления значений свойств:
  • if ([Человек].[имеет_питомца].[Наследует_классам].includes([Собака])) "Да" else "Нет"

Сравнение строк

Для сравнения строк в правилах могут быть использованы следующие операторы сравнения:

  • ..= - заканчивается на
  • .=. - содержит
  • =.. - начинается с
  • = - строгое равенство

[Thing].[определение] ..= "aaa"

Все экземпляры, определение которых заканчивается на aaa

[Thing].[определение] =.. "aaa" Все экземпляры, определение которых начинается на aaa

[Thing].[определение] .=. "aaa" Все экземпляры, определение которых содержит aaa

[Thing].[определение] = "aaa" Все экземпляры, определение которых в точности совпадает с aaa

Инфо

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

[Человек].[имеет_друга].[name] = "Дмитрий" Все люди, которые имеют друга Дмитрий. Здесь имеет друга это "типизированное" отношение, для которого в качестве домена и диапазона установлен класс Человек.

Также, при работе со строками могут быть использованы следующие функции:

  • substring - поиск экземпляров по подстроке
  • length - поиск экземпляров по длине строки
  • position - поиск экземпляров по позиции подстроки в строке

[Thing].[name].substring(2,3) = "aa"

Все экземпляры, в названиях которых подстрока со второго символа по третий равна aa

[Thing].[name].length = 4 Все экземпляры, названия которых состоят из четырех символов

[Thing].[name].position("BB") = 3 Все экземпляры, в названии которых начиная с 3-го символа находится подстрока BB

Сравнение логических выражений

[Thing].[Наследует_классам] = [Огнетушитель] and not [Thing].[Является_классом]

или

[Thing].[Наследует_классам] = [Огнетушитель] and [Thing].[Является_классом] = false

или

[Thing].[Наследует_классам] = [Огнетушитель] and [Thing].[Является_классом] <> true

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

[Thing].[Наследует_классам] = [Огнетушитель] and [Thing].[Является_классом]

или

[Thing].[Наследует_классам] = [Огнетушитель] and [Thing].[Является_классом] = true

или

[Thing].[Наследует_классам] = [Огнетушитель] and [Thing].[Является_классом] <> false

Все объекты, которые наследуют классу Огнетушитель и при этом являются классами. Другими словами - это классы, которые наследуют классу Огнетушитель на любом уровне наследования. При этом сам класс Огнетушитель не будет являться частью результата правила, т.к. класс не наследует сам себе

Вычисление значений отношений

Внимание

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

Рассмотрим возможность вычисления значений отношений на простом примере: у пары отношений имеет отца и имеет деда и доменом и диапазоном являются классы Человек и Мужчина соответственно. Задача: автоматически вычислять "деда" человека на основании имеющейся информации об отцах людей.

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

[Человек].[имеет_отца].[имеет_отца]

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

Человекимеет отцаимеет деда
ЛевДмитрийВячеслав
ДмитрийВячеслав
Вячеслав

Дополнительные условия (ключевое слово where)

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

Рассмотрим использование ключевого слова where на примере следующей онтологии:

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

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

[Линия].inverse([в_линии]).[точка]

where [Линия].inverse([в_линии]).[предыдущая__точка] is empty

Вычисление значений скалярных свойств

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

Внимание

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

Простая арифметика

100 * [Бюджет].[факт] / [Бюджет].[план]

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

[ШаблонУниверсальный].[актор].[name] + " должен(-а) иметь возможность " + [ШаблонУниверсальный].[действие].[name] + " для " + [ШаблонУниверсальный].[объектДействия].[name]

Для каждого экземпляра класса ШаблонУниверсальный будет вычислена формулировка требования. Здесь актор, действие и объектДействия - это отношения класса ШаблонУниверсальный, а ключевые слова name используются для получения имен экземпляров. Оператор + при использовании со строками работает как оператор конкатенации.

count, sum, avg, min, max

  • count - вычисление количества ссылочных значений
  • min и max - вычисление минимальных и максимальных чисел или дат
  • avg и sum - вычисление среднего и суммы чисел
  • sum - конкатенация строк; разделитель по умолчанию - запятая, но можно переопределить, например, sum("; ")

Рассмотрим примеры использования ключевого слова count. Для каждого человека нужно рассчитать количество его детей. В варианте А через отношение имеетДетей, а в варианте Б - через отношение имеетМать:

[Человек_А].[имеетДетей].count()

[Человек_Б].inverse([имеетМать]).count()

Функции sum, avg, min, max необходимо использовать аналогичным образом. Рассчитаем средний возраст сотрудников подразделений с помощью функции avg на примере следующей онтологии:

[Подразделение].inverse([работает_в]).[возраст].avg()

Важно

Агрегатные функции могут использоваться совместно со служебным словом where для ограничения выборки:

[Подразделение].inverse([работает_в]).[возраст].avg() where [Подразделение].inverse([работает_в]).[пол] = "Ж"

Демонстрация применения правил для вычисления скалярных свойств

Условные конструкции

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

if ([условие]) [значение_если_условие_истинно] else [значение_если_условие_ложно]

возможно также использование вложенных конструкций

if ([условие1]) [значение_если_условие1_истинно] else if ([условие2]) [значение_если_условие2_истинно] else [значение_если_условие2_ложно] и т.д.

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

if ( [Человек].[имеетВозраст] < 13 ) "Ребенок" else if ( [Человек].[имеетВозраст] < 20 ) "Подросток" else "Взрослый"

Пример вычисления отношения имеет группу горючести на основе значения числовых свойств температура дымовых газов и степень повреждения по длине:

if ( [Материал].[температура_дымовых_газов] <= 135 and [Материал].[степень_повреждения_по_длине] <= 65 ) [Г1] else [Г2]

здесь [Г1] и [Г2] --- это экземпляры класса Группа горючести

Ограничение диапазонов отношений

Инфо

Правила, ограничивающие диапазоны отношений, называются правилами зависимостей

Рассмотрим правило для ограничения диапазона отношения на примере следующей онтологии:

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

Написание правила для ограничения диапазона отношения всегда должно начинаться с класса-диапазона отношения. Например, в данном случае мы планируем ограничить диапазон отношения "имеет первую опору", поэтому написание правила начинаем с класса Опора:

[Опора].[относится_к_линии] = self.[относится_к_линии]

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

proptype - шаблонизация правил зависимостей

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

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

  • [Приоритет].[имеет_статус] = [Активно] - привязано к свойству имеет приоритет
  • [Состояние].[имеет_статус] = [Активно] - привязано к свойству имеет состояние

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

Для упрощения можно воспользоваться служебным словом proptype. Система автоматически подставляет вместо proptype фактический класс-диапазон свойства, при применении правила зависимости.

Таким образом, достаточно создать одно универсальное правило :

  • proptype.[имеет_статус] = [Активно]

Это правило можно назначить на оба свойства — имеет приоритет и имеет состояние. При этом система автоматически интерпретирует proptype как Приоритет или Состояние в зависимости от контекста, и фильтрация будет работать корректно.

Значения по умолчанию

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

Имяобразования экземпляров

см. Имяобразование

Создание правил

Создание вычисляемого класса

Создание вычисляемого отношения

Создание вычисляемого скалярного свойства

Создание ограничения диапазона отношения

Для задания ограничения диапазона отношения необходимо указать правило в поле "Список зависимостей для поля или свойства" в карточке отношения.