Formulae

Материал из Course Orchestra
Перейти к: навигация, поиск

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

  • преобразование в обе стороны между каноническим и XML- представлением формулы,
  • компиляция формулы, заданной каноническим представлением,
  • выдача перечня свободных параметров формулы,
  • возможность задания значений свободных параметров формулы,
  • вычисление значения формулы при условии, что свободные параметры заданы (формула может вычисляться к логическому, числовому или текстовому значению)
  • утилита, склеивающая из компонент ссылку в виде [aaa].[bbb].[ccc]... и, наоборот, разбивающая ссылку на компоненты.


Описание API классов расчётного модуля

ru.curs.formulae.ReferenceParser

Парсер ссылок в формате [aaa].[bbb]....

Статические методы:

  • String combine(String... components) -- составляет текст ссылки из компонент, заключая их в квадратные скобки и разделяя точкой.
  • String[] split(String string) -- разбивает ссылку на компоненты, снимая с них квадратные скобки.

ru.curs.formulae.Formula

Класс формулы.

Для того, чтобы создать экземпляр формулы на основе канонического (не XML!) представления формулы, необходимо воспользоваться методом

Formula.compile(String formula)

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

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

Если формула имеется не в каноническом виде, а в виде XML, его сначала надо сконвертировать в канонический вид при помощи класса XMLParser, описанного ниже.

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

  • Set<String> getParams() - Возвращает набор свободных параметров формулы (т. е. всех переменных, значения которых можно затем присваивать).
  • void setParam(String name, int/double/boolean/String val) - Устанавливает числовое, булевское или строковое значение параметра по его имени.
  • void setArrayParam(String name, int.../double.../boolean.../String.../Value... val) - Устанавливает параметр-массив по его имени.
  • void resetParam(String name) - Сбрасывает значение указанного по имени параметра в NA (No Answer).
  • Value calcValue() - вычисляет значение формулы, возвращая экземпляр класса Value, описанного ниже.
  • String asXML() - Представляет формулу в частично разложенном в XML виде (пригодном для вывода в XForms).
  • String asText(), String asText(boolean useRussian) - Представляет формулу каноническом виде. Параметр useRussian==true указывает на необходимость использования русских ключевых слов. Формула собирается из объектного представления, т. е. форматируется заново.

ru.curs.formulae.Value

Класс значения вычисления. Доступны следующие методы:

  • ExprType getType() - возвращает значение enum ExprType, одно из трёх: NUMERIC/TEXT/BOOLEAN.
  • boolean asBoolean() - значение в виде булевского значения или ошибка, если это не булевское значение.
  • double asNumber() - значение в виде числа или ошибка, если это не число и его нельзя сконвертировать в число.
  • String asText() - значение в виде текста.
  • Date asDate() - значение в виде даты (класс java.util.Date).

Кроме того, доступна специальная статическая константа Value.NA, соответствующая значению «нет ответа».

ru.curs.formulae.XMLParser

Содержит единственный статический метод:

  • String translate(String xml) - преобразует XML-строку в строковое каноническое представление формулы.

Например,

<?xml version="1.0" encoding="UTF-8"?>
<and>
  <or>
    <relop op="&gt;"><expr>[cc]</expr><expr>5.0</expr></relop>
    <relop op="="><expr>[bb]</expr><expr>5.0</expr></relop>
  </or>
  <not>
    <expr>[dd] in (5.0, 6.0 + [ee])</expr>
  </not>
</and>

преобразуется в

([cc] > 5.0 or [bb] = 5.0) and  not [dd] in (5.0, 6.0 + [ee])

При этом следует учитывать, что AND имеет приоритет над OR, так что XML

<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<or><and><expr>[a]</expr><expr>[b]</expr></and><and><expr>[c]</expr><expr>[d]</expr></and></or>

преобразуется в

[a] and [b] or [c] and [d]

но

<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<and><or><expr>[a]</expr><expr>[b]</expr></or><or><expr>[c]</expr><expr>[d]</expr></or></and>

преобразуется в ВНИМАНИЕ!

([a] or [b]) and ([c] or [d])

Описание синтаксиса канонических представлений формул

Литералы и переменные

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

3.primary term.png

Допустимы следующие типы литералов:

  • Числовой литерал — стандартный способ представления числа с плавающей точкой, как в большинстве языков программирования.
  • Текстовый литерал — текст в одинарных кавычках ('...'), с удвоением кавычки, если она должна быть частью текста (как в большинстве языков программирования).
  • Литерал даты — выражение в формате DYYYYMMDD. Например, литерал D20140803 указывает на дату "3 августа 2014 года".

Кроме того, дату можно задать двумя другими способами:

  • Функция DATE() без параметров возвращает текущую (на момент вычисления формулы) дату.
  • Функция DATE(y, m, d) возвращает дату по заданному году, месяцу и дню.

Арифметические и специальные операции

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

  • (,) - группирующие скобки.
  • Арифметические операции (в порядке убывания приоритета)
    • ^ возведение в степерь
    • - унарный минус
    • *, / — умножение и деление
    • +, - — сложение и вычитание
  • Строковая операция
    • || — конкатенация строк
  • Специальные операции
    • CASE WHEN... — условный оператор
    • COUNT(..., ...) — подсчёт ненулевых значений
    • ISNA(...) — определение значения NA
  • Конструкторы даты
    • DATE() — возвращает текущую (на момент вычисления формулы) дату
    • DATE(..., ..., ...) — возвращает дату на данный год, месяц и день

Конкатенация строк имеет минимальный приоритет, так что выражение 6 || 5 + 2 будет иметь результат '67.0'. (5 + 2 = 7, преобразование в строку даёт '7.0', конкатенация с 6 даёт '67.0').

Арифметические операции + и - имеют особое значение при работе с датами.

  • Сложение даты и целого числа N (в любом порядке) даёт новую дату, полученную прибавлением N дней к указанной дате. Например, D20140805 + 2 = D20140807.
  • Вычитание из даты целого числа N даёт новую дату, полученную вычитанием N дней из указанной даты. Например, D20140805 - 2 = D20140803.
  • Вычитание из одной даты другой даты даёт целое число — разницу в днях между датами. Например, D20140805 - D20140803 = 2.

Прочее использование арифметических операций с датами (как и с другими типами данных) приведёт к ошибке.


Синтаксическая диаграмма:

1.term.png

  • Операция case [a] when [b1] then [c1] when [b2] then [c2] ... else [d] - операция case...when, соответствует таковой для языка SQL.

2.CASE WHEN term.png

Результат выражения CASE ... WHEN вычисляется следующим образом: значение терма, идущего за CASE, сравнивается с идущими за словом WHEN, и как только оно совпадёт, выводится значение, идущее за THEN. Если значение CASE-терма не совпало ни с одним из WHEN-значений, выводится значение ELSE.

Если за словом CASE не следует терм, то каждое из WHEN-значений сравнивается со значением TRUE.

Если значения ELSE нет и ни одно из значений не совпало, выводится ошибка, поэтому использование CASE без значения ELSE не рекомендуется.

3.COUNT term.png

Результат выполнения COUNT представляет собой количество аргументов, которые не равны 0 или FALSE. Если аргумент COUNT только один и при этом имеет тип «массив», то происходит подсчёт внутри массива.

4.ISNA term.png

Результат выполнения ISNA — булевское значение, True если аргумент равен NA (No Answer).

5.date part term.png

Результат выполнения DAY, YEAR или MONTH — номер года, месяца или дня в дате, являющейся аргументом этих функций. Ошибка, если аргумент — не дата.

Операции сравнения

  • Операции сравнения:
    • =, >, <, >=, <=, <> - простые (бинарные) операции сравнения. Наравне с этими знаками, можно использовать Unicode-символы ≠, ≤, ≥.
    • [a] between [b] and [c] - соответствует between в языке SQL и эквивалентно [a] >= [b] and [a] <= [с].
    • [a] in ([b], [c], [d]..) - соответствует in в языке SQL и эквивалентно [a] = [b] or [a] = [d] or ... При этом, в правой части в скобках стоит единственное значение и оно имеет тип «массив», то поиск происходит внутри массива.

5.predicate.png

Логические операции

  • Логические операции (в порядке убывания приоритета):
    • not -- унарная логическая операция
    • and -- операция И
    • or -- операция ИЛИ.

4.condition.png

Операция and имеет приоритет над операцией or.

Значение NA

По умолчанию всем параметрам формулы присваивается специальное значение Value.NA (сокращение от "No Answer"). Любые операции с этим значением имеют результат NA (например, 2 + NA есть NA, NA < 5 есть NA). Исключение составляют логические операции OR и AND:

  • NA OR True есть True
  • True OR NA есть True
  • NA AND False есть False
  • False AND NA есть False

Определить, что результат вычисления чего-либо равен NA, можно при помощи функции ISNA(...)

Синонимы ключевых слов на естественном языке

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

Ключевое слово Синоним
TRUE ИСТИНА
FALSE ЛОЖЬ
CASE ВЫБОР
WHEN ЕСЛИ
THEN ТО
ELSE ИНАЧЕ
END КОНЕЦ
IN В
BETWEEN МЕЖДУ
AND И
OR ИЛИ
NOT НЕ
COUNT КОЛВО
ISNA ПУСТО
DATE ДАТА
YEAR ГОД
MONTH МЕСЯЦ
DAY ДЕНЬ
>=
<=
<>