Научная статья на тему 'Формальная верификация программной реализации алгоритма пирамидальной сортировки на языке cи-0'

Формальная верификация программной реализации алгоритма пирамидальной сортировки на языке cи-0 Текст научной статьи по специальности «Компьютерные и информационные науки»

CC BY
340
43
i Надоели баннеры? Вы всегда можете отключить рекламу.
Ключевые слова
ФОРМАЛЬНАЯ ВЕРИФИКАЦИЯ / ПИРАМИДАЛЬНАЯ СОРТИРОВКА / ПРОГРАММНЫЙ КОД

Аннотация научной статьи по компьютерным и информационным наукам, автор научной работы — Ковалев Михаил Сергеевич, Далингер Яков Михайлович, Мяготин Антон Владимирович

Представлена формальная верификация программного кода выполненного на языке Cи-0 алгоритма пирамидальной сортировки для массива произвольного типа данных. Основные этапы включают разработку спецификации алгоритма, написание программного кода сортировки, перевод текста программы в среду формальной верификации Isabelle/HOL и выполнение доказательств, устанавливающих соответствие формальной спецификации алгоритма и его реализацииI

i Надоели баннеры? Вы всегда можете отключить рекламу.

Похожие темы научных работ по компьютерным и информационным наукам , автор научной работы — Ковалев Михаил Сергеевич, Далингер Яков Михайлович, Мяготин Антон Владимирович

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.
i Надоели баннеры? Вы всегда можете отключить рекламу.

n this article we report on formal software verification for the C0 implementation of the heapsort algorithm for an array of an arbitrary data type. The working steps include the development of an algorithm specification, writing a program code, code translation into the Isabelle/HOL environment, performing a correctness proof showing equivalence between the program implementation and its specification.

Текст научной работы на тему «Формальная верификация программной реализации алгоритма пирамидальной сортировки на языке cи-0»

Вычислительные машины и программное обеспечение

УДК 519.686.4

М.С. Ковалев, Я.М. Далингер, А.В. Мяготин

формальная верификация программной реализации

алгоритма пирамидальной сортировки на языке 0и-0

Сортировка - самая известная проблема теоретической информатики. Алгоритмы сортировки используются во многих реальных приложениях, например, таких, как организация СУБД. Из-за невысокой вычислительной сложности и отсутствия затрат на выделение дополнительной памяти под временное хранение данных широкое распространение получила пирамидальная сортировка [1]. Корректность обобщенного алгоритма (т. е. в котором опускаются несущественные детали реализации) была показана во многих ранних источниках [2], в то время как корректность его программного исполнения в научной литературе практически не обсуждалась.

В целом проверка корректности программного кода (верификация) является нетривиальной задачей. Различают два принципиальных подхода -динамический и статический [3]. Динамическая верификация подразумевает тестирование программы для различных входных данных. Очевидно, что проверить сложную систему для всех возможных входов и состояний невозможно, т. к. количество тестов имеет экспоненциальную зависимость от размера входа. Как следствие, динамическая верификация не может гарантировать отсутствие ошибок в программе.

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

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

Цель данной статьи - выполнение формального доказательства корректности действующего программного кода пирамидальной сортировки. В отличие от авторов [4], которые показали корректность алгоритма для целочисленного типа данных с использованием интерактивной среды верификации Coq, нами выполнена верификация пирамидальной сортировки массивов содержащих элементы произвольного типа. Для написания кода применялся язык Си-0 [5] являющийся подмножеством языка Си. Работа включала такие этапы, как составление формальной спецификации, написание программного кода и его перевод в среду верификации Isabelle/HOL, проведение доказательств, устанавливающих соответствие между спецификацией алгоритма и его реализацией. Каждый из перечисленных этапов описан в последующих разделах статьи.

Верификация программного кода

Под формальной верификацией программного кода понимается процесс доказательства или опровержения соответствия программной реализации ее спецификации при помощи формализованных методов и средств. В качестве среды верификации в данной статье использовалось интерактивное некоммерческое приложение Isabelle [6]. В сравнении с существующими программно-ориентированными анализаторами, такими, как Frama-C [7], данный инструмент при помощи математического аппарата логики высшего порядка (higher-order logic, HOL) позволяет не только показать отсутствие элементарных ошибок в коде (переполнение, обращение к нулевому указателю, деление на ноль), но и составить предикаты,

описывающие принцип работы программы на абстрактном уровне. Кроме того, данное приложение поставляется с обширным набором вспомогательных теорий, облегчающих процесс основного доказательства. Формальная корректность доказательства программ выбранным методом с использованием Isabelle/HOL показана в [8].

Верификация программы с использованием среды Isabelle/HOL требует выполнения следующих шагов:

1. создание неформальной спецификации программы, словесного описания результата ее выполнения;

2. реализация программы на выбранном языке программирования;

3. перевод исходного текста программы в язык среды верификации;

4. создание формальной спецификации;

5. создание инвариант циклов и условий завершения программы;

6. автоматическая генерация условий верификации;

7. выполнение интерактивного пошагового доказательства;

8. анализ результатов.

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

Программный код пирамидальной сортировки выполнялся на языке Си-0 (шаг 2) являющемся подмножеством ANSI Си. Данный язык имеет ряд синтаксических ограничений [5], которые не влияют на функциональность создаваемого программного кода, но заметно упрощают формальное моделирование и ход доказательства. Дополнительным аргументом в пользу данного языка явилось наличие Си-0 компилятора, корректность которого была показана формально. Следует отметить, что на сегодняшней день активно ведутся исследования в области формальной верификации кода, написанного на языке Си++ [9, 10]. Однако отсутствие полной формальной семантики языка, сложность и обилие механизмов программирования, включающих как низкоуровневые операции с памятью, так и абстрактную объектно-ориентированную модель, являются факторами, сдерживающими использование данных теоретических исследований на практике.

Формальная спецификация алгоритма, ин-

варианты циклов и условия завершения оформлялись с использованием аксиоматической семантики в стиле Хоара (Hoare logic) (шаги 4, 5) представляющей собой набор аксиом и правил, при помощи которых формулируются утверждения о корректности выполнения программного кода [11, 12]. Пусть Z - это пространство состояний (множество значений локальных и глобальных переменных программы), B - булевое множество {0, 1}, тогда утверждение Aнад пространством состояний - это предикат вида A^ = {а | а : X ^ B}. Утверждения позволяют описывать свойства и зависимости переменных, присутствующих в программе, при этом утверждение А eA^, описывающее пространство состояний в начальный момент выполнения программы, называется предусловием, а утверждение BeA^, описывающее результат выполнения программы, называется постусловием. Основополагающим элементом семантики Хоара является тройка Хоара (Hoare triplet) {A}P{B}, представляющая собой функцию:

Ae х х Ae ^ B ,

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

Автоматическая генерация условий верификации (шаг 6) заключается в том, что тройка Хоара преобразуется в набор логических утверждений. Для этих целей в среде верификации Isabelle/HOL присутствует инструмент VCG [13]. Процесс доказательства (шаги 7, 8) сводится к построению последовательности элементарных логических правил, показывающих или опровергающих справедливость сгенерированных условий верификации.

Алгоритм пирамидальной сортировки

Пирамидальная сортировка (heap sort) - классический алгоритм, базирующийся на сравнении элементов входного массива. К достоинствам алгоритма можно отнести то, что при его выполнении не выделяется дополнительная память, и при этом худшее время выполнения составляет O(n log n), где n - размер входного массива. В основе пирамидальной сортировки лежит использование двоичного сортирующего дерева (binary heap), в котором вершины имеют не более двух наследников. За каждой вершиной закреплено некото-

17

10

20

115 1

7 ч

12j G )

1 2 3 4 5 6 7 8 9

20 17 15 10 9 12 4 6 7 1

Рис. 1. Сортирующее дерево и его представление в виде массива

рое значение - ключ. Ключ должен быть меньше или равным ключу родительской вершины - это так называемое основное свойство дерева (heap property). Как следствие, корневая вершина имеет максимальный по значению ключ. Сортирующее дерево реализуется линейным массивом. Вершина дерева, представленная элементом массива с индексом j, имеет родительскую вершину, представленную элементом массива на позиции [ j/2], а наследующие вершины (правая и левая) должны быть расположены на позициях 2j и 2j+1, как показано на рис. 1.

procedure HeapSort(A, N)

for i = N/2 to 0

SiftDown(A, i, N) for i = N to 1

swap(A[0], A[i]) SiftDown(A, 0, i-1)

Обобщенный алгоритм пирамидальной сортировки HeapSortQ состоит из двух шагов (рис. 2):

1. для входного массива создается сортирующее дерево (строки 1-2);

2. в цикле из дерева удаляется корневая вершина, затем процедура SiftDown() (строки 3-5) восстанавливает основное свойство дерева.

Процедура SiftDown() «просеивает» элемент, начиная с позиции корневой вершины root вниз по структуре дерева до тех пор, пока свойство дерева не восстановится. Входной параметр bottom определяет индекс последней вершины сортиру-

procedure SiftDown(A, root, bottom)

6

7

8

9

10 11 12

13

14

15

while root * 2 < bottom

if cmp(A[root * 2 + 1], A[root * 2])

child = root * 2 else

child = root * 2 + 1 if cmp(A[root], A [child]) swap(A[root], A [child]) root = child else

break

Рис. 2. Алгоритм пирамидальной сортировки

ющего дерева. Первым действием (строки 7-10) определяется, какая из двух наследующих вершин имеет больший ключ. Затем индекс этой вершины заносится в переменную child. В строке 11 ключ вершины child сравнивается с ключом вершины root. Если свойство сортирующего дерева не соблюдается, т. е. A [root] < A [child], вершины меняются местами (строки 12-13). Так как после обмена свойство может не выполняться на нижних уровнях, то на следующей итерации цикла while осуществляется проверка для поддерева с корневой вершиной child.

Следует обратить внимание, что тип данных входного массива алгоритмом не оговаривается. Предполагается, что для выбранного типа имеется процедура cmp(a,b), которая реализует отношение «строго меньше», т. е. a< b. Соответственно, если процедура сравнения определена для некоторого типа данных, то становится возможным использование алгоритма для сортировки массива с элементами данного типа.

Вспомогательные предикаты

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

Цель алгоритма сортировки - получение такой перестановки элементов массива A, при которой для любой пары соседних элементов с индексами j и j+1 выполняется условие A[ j] < A [j+1]. Данное утверждение формально записывается следующим предикатом: is_sorted(A, i, N, С) := V/ > 0IN > 1 л j > i л j < N] =>

+ (1) где i определяет индекс элемента, с которого начинает выполняться условие сортировки; N - общее количество элементов в массиве, C(a, b):= a < b - булевая функция сравнения. Предикат (1) далее именуется критерием сортировки. Принимая во внимание, что алгоритм сортировки должен выполняться корректно для произвольного типа данных, функция сравнения C для некоторого фиксированного типа должна обладать следующим набором свойств: not_commutative (С) := \/a,b. С (a, b) —> —iC(b, a);

not_reflexive(C) :=Va.-iC(a, a);

transitive (C) := Va Д c. [C( a, b) a C( b, с)] => C( a, c).

Указанные свойства объединяются в предикате valid_cmp_operator

valid_cmp_operator(C) := not_commutative(C) a not_reflexive(C) л transitive(C). (2)

Основное свойство сортирующего дерева выражается предикатом is_heap():

is_heap( A, i, j, N, С) := Vk.[k > 2i л к < j л j < N] =>

=>-,C(A[l*/2jU[*]> (3)

Здесь i и j задают диапазон индексов массива A, в пределах которых линейный массив является представлением сортирующего дерева. Аналогичным образом введем предикат is_heap_ except(A, i, j, k, N, C), который определяет соответствие массива сортирующему дереву за исключением элемента на позиции k.

Спецификация и программная реализация алгоритма

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

При составлении предусловия процедуры необходимо ссылаться на начальные значения переменных, в то время как в постусловии потребуются как начальные, так и конечные значения. Чтобы различать их условимся, что имя переменной с апострофом (например, bottom') описывает ее значение на момент завершения процедуры, без апострофа - на момент вызова. Чтобы различать в спецификации локальные переменные, имеющие одинаковые названия в разных процедурах, их имена будут расширены названиями функций (например, sDarr, hSarr).

Процедура siftDown(). Программная реализация процедуры siftDownQ на языке Си-0 представлена на рис. 3.

В качестве входных параметров процедура принимает указатель на входной массив arr, индексы root и bottom, в пределах которых после завершения процедуры элементы массива будут представлять сортирующее дерево. В Си-0 (так же как и в ANSI Си) не предусмотрено стандартной возможности программирования кода с

1 bool siftDown (struct array* arr, unsigned int root, unsigned int bottom)

2 {

3 bool done;

4 bool rescomp;

5 unsigned int maxChild;

6 ANY TYPE temp;

7 done = false;

8 while (( root*2u <= bottom) && ( !done ))

9 {

10 if(root * 2u == bottom)

11 maxChild = root * 2u;

12 else

13 {

14 rescomp = cmp(arr->numbers[root*2u + 1u], arr->numbers[root*2u]);

15 if (rescomp == true)

16 maxChild = root * 2u;

17 else

18 maxChild = root * 2u + 1u;

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

19 }

20 rescomp = cmp(arr->numbers[root], arr->numbers[maxChild]);

21 if( rescomp == true )

22 {

23 temp = arr->numbers[root];

24 arr->numbers[root] = arr->numbers[maxChild];

25 arr->numbers[maxChild] = temp; 2 6 root = maxChild;

27 }

28 else

29 done = true;

30 }

31 return true;

32 }

Рис. 3. Программная реализация процедуры siftDown()

произвольным типом данных, поэтому типовая параметризация в тексте программы реализовывалась путем определения типа ANY_TYPE следующим образом: #define MAXNUM 10000 #define ANY_TYPE int

struct array {ANY_TYPE numbers[MAXNUM];} Пространство состояний для процедуры siftDown() имеет вид:

£ = £0 и { sD _ arr, sD _ root, sD _ bottom, sD _ done,

sD _ rescomp, sD _ temp, sD _ maxChild, sD _ res _ bool} _

Предусловие процедурыpre_sD включает следующие предикаты:

pre_sD :=

sD_bottom > sD_root л (4а) is_heap (sD_arr, sD_root+l, sDJbottom,

siz&(sD_arr), стр) л (4б)

sD_arr != Null л (4в)

sDJbottom < size(sD_arr) л (4г)

valid_compare_operator (стр) л (4д)

in_range(sD_bottom * 2+1) (4е)

Условие (4а) устанавливает отношение между начальным и конечным индексами массива. Следующий предикат объявляет, что элементы входного массива, начиная с индекса sD_root+1, являются действительным представлением сортирующего дерева. Условия (4в) и (4г) оговаривают, что указатель на входной массив не нулевой, и конечный индекс sD_bottom не выходит за границы массива. Предикат (4д) устанавливает соответствие используемой функции стр() тре-

рол^О :=

18_Ьеар ($0_агг', зО_гоог, 50_ЬоПот,

ш&{зВ_агг'), стр)

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

Постусловие post_sD составлено в виде следующего логического выражения:

(5а)

Vifc. {к > 0Л к < sD_root) v

{к > sD_bottomлк<size(sD_arr)) =>

sD _ arr\k\ = sD_ arr' [fc] A

яО_агг = 5Б_агг'

Предикат is_heap гарантирует корректность работы процедуры siftDown(), по окончании которой весь входной массив в диапазоне индексов [sD_root,sD_bottom] является представлением сортирующего дерева. Кроме того, элементы входного массива, не входящие в указанный диапазон, остались на своих прежних позициях (5б), и выходной массив является перестановкой исходного (данное отношение обозначено «=») (5в),

(5б) (5в)

т. е. наборы элементов обоих массивов совпадают.

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

Termination_measure := if sD _ root * 2 <sD_ bottom a —¡sD _ done

then (l + sD_ bottom) -2 *sD_ root else 0

Процедура heapSort(). Программный код процедуры heapSort() представлен на рис. 4. В качестве входных параметров она принимает массив arr и его размер array_size. Пространство состояний задано следующим множеством:

X = 20 и {hS _ arr, hS _ array _ size, hS _ i, hS _ temp,

hS _ restemp, hS _ res_boot).

Предусловие pre_hS процедуры имеет вид: preJiS :=

hS_arr != Null Л (6а)

valid_compare_operator {стр) л (6б)

ia_Tange(hS_array_size * 2+1) л (6в)

hS_array_size = siz c(hS_arr) (6г)

Условия (6а), (6б), (6в) аналогичны предусловиям (4в), (4д), (4е) процедуры siftDown(). Выражение (6г) показывает, что переменная array_size действительно содержит длину массива.

1 bool heapSort (struct array* arr, unsigned int array_size)

2 {

3 unsigned int i;

4 ANY TYPE temp;

5 bool restemp;

6 i = ((array_size + 1u)/2u);

7 if (1u < array_size)

8 {

9 while (i > 0u)

10 {

11 restemp = siftDown(arr, i - 1u, array_size - 1u);

12 i = i - 1u;

13 }

14 i = array_size - 1u;

15 while (1u <= i )

16 {

17 temp = arr->numbers[0u];

18 arr->numbers[0u] = arr->numbers[i];

19 arr->numbers[ i] = temp;

20 if ( i - 1u != 0u)

21 restemp = siftDown(arr, 0u, i - 1u);

22 i = i - 1u;

23 }

24 return true;

25 }

Рис. 4. Программная реализация процедуры heapSortQ)

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

post_sD:= (7а)

is_sorted (hS_arr', 0, hS_array_size, стр) Л

hS_arr = hS_arr' (7б)

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

Условия завершения для обоих циклов процедуры heapSort() тривиальны и имеют вид Termination_measure := hS_i

Инварианты циклов и условия корректности

Следующим шагом сформулируем инварианты циклов. Инвариант inv_sD цикла в процедуре siftDown()имеет вид

inv_sD:=

sD _ root * 2 < sD _ bottom л —isD _ done => is_heap_except (sD_arr, sDjroot', sDJbottom,

sD_root, size(sD_arr), cmp) л (8а)

sD _ root * 2 >sD_ bottom v sD_ done =>

is_heap (sD_arr, sD_root', sDJbottom, (8б)

size(sD_arr), cmp) л sD _ root >sD_ root' л (8в)

Vfc. (к > 0 л к < sD _ root) v

(к > sD_bottomлк< size(sD_arr)) =>

sD _ arr[k] = sD_ arr' [Jfc] л (8г)

sD_arr != Null л (8д)

valid_compare_operator (cmp) л (8е)

sD_arr = sD_arr' (8ж)

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

Инвариант первого цикла процедуры heapSortQ имеет вид:

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

invl_hS:=

is_heap (hS_arr, hS_i, h,S_array_size-\,

hS_array_size, cmp) Л (9а)

hS_i < hS_array_size л (9б)

hS_arr != Null л (9в)

valid_compare_operator (cmp) л (9г)

in_range (hS_array_size * 2+1) л (9д)

hS_arr = hS_arr' (9е)

Условие (9а) гарантирует, что часть массива, начиная от элемента с индексом hS_i, является сортирующим деревом. Условие (9б) ограничивает значение hS i сверху. Инвариант второго цикла inv2_hS включает следующие условия:

inv2_hS:= (10а)

is_heap (hS_arr, 0, hS_i, hS_array_size, cmp) Л

is_sorted (hS_arr', hS_i +1, hS_array_size, cmp) л (10б)

Vl.(l>OAl<hS_i + l)A(hS_i + l)<hS_array_size^> (10в)

-icmp(hS _ arr[i +1], hS _ arr[l])

л

А5_г < И.8_аггау_$гге л (10г)

кБ_агг !=Ш11 л (10д)

valid_compaгe_opeгatoг (стр) л (10е)

т_гапде (к8_аггау_81ге * 2+1) л (10ж)

к8_агг = к8_агг' (10з)

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

При помощи инструмента VCG для процедуры siftDown() было сгенерировано три условия верификации:

1) pre _sD=> inv _ sD[sD _ done := false];

2) inv _ sDi a (sD_ root * 2 < sD _ bottom) => inv _ sDi+1;

3) inv_sD a —i(sD_root *2<sD_bottom) => post_sD. Для процедуры heapSort() было сгенерировано пять условий:

1) pre_hS AhS _array _size > 1 invl_hS[hS_i := (hS_array _size +1)/2];

2) invl _ hSi a (hS _ i > 0) => invl _ hSi+1;

3) invl_hS a (hS_i< 0) => inv2_hS[hS _i := hS _array _size -1];

4) inv2 _ hSt a (hS _ i > 0) => invl _ hSi+1;

5) invl_hS a (hS_i< 0) => post_hS.

Доказательство условий корректности

Рассмотрим доказательство корректности сгенерированных условий на примере условия 2 процедуры heapSort(). В теле первого цикла процедуры, описываемого инвариантом (9), происходит вызов процедуры siftDown() с входными параметрами sD arr = hSarr, sD root = (hS_i-1), sD_botom = (hS_array_size-1) и декремент счетчика hSi. Требуется показать, что инвариант цикла остается верным после выполнения одной итерации цикла. Условия (9б-г) напрямую следуют из инварианта предыдущей итерации цикла. Условие (9а) выполняется благодаря постусловию (5 а) процедуры siftDownQ (с учетом декремента hS_i). Для вывода условия (9д) воспользуемся условиями (5б), (5в) и свойством отношения перестановки элементов последовательности. Необходимо показать, что предусловие (4) вызываемой процедуры siftDown() выполняется. После подстановки входных параметров, все условия из (4) напрямую следуют из инварианта (9).

Доказательство корректности программы сортировки проводилось в среде Isabelle/HOL. При

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

Статистические данные объема доказательств, выполненных в IsabeUe/HOL

siftDown heapSort Другие Итого

Леммы 3 5 66 74

Команды 651 461 799 1911

В статье рассмотрен вопрос формальной верификации Си-0 реализации алгоритма пирамидальной сортировки. Исходные коды были переведены в среду верификации Isabelle/HOL, составлена формальная спецификация алгоритма, соответствие которой реализации было доказано посредством пошагового доказательства. Удалось формально показать корректность действующего программного кода алгоритма сортировки для массива с элементами произвольного типа.

СПИСОК ЛИТЕРАТУРЫ

1. Кормен, Т. Алгоритмы построение и анализ [Текст]/Т. Кормен, Ч. Лейзерсон, Р. Ривест.-М.: МЦНМО, 2000.

2. Knuth, D. The Art of Compute Programming [Текст]Ю. Knuth//Sorting and Searchmg.-1997.-VoL3. -Addison-Wesley.

3. Adrion, W.R. Validation, verification, and testing of computer software [Текс^/W.R. Adrion, M.A. Branstad, J.C. Cherniavsky//ACM Comp. Surv.-1982.-Vol.14 (2). -P. 159-192.

4. Filliatre, J.C. Certification of sorting algorithms in

the system Coq [Текст]Л.С. Filliatre, N. Magaud//Theorem Proving in HOL: Emerging Trends, 1999.

5. Leinenbach, D. Towards the formal verification of a C0 compiler: code generation and implementation correctness [Текст]Ю. Leinenbach, W. Paul, E. Petrova// In 3rd Int. IEEE conf. on Software Eng. and Formal Methods.-2005.-P. 2-11.

6. Nipkow, T. Isabelle/HOL: Aproof assistant for higherorder logic [Текст]/Т. Nipkow, L.C. Paulson, M. Wenzel// Lecture Notes on Computer Science.-2002. 2283.

7. http://frama-c.com/ [Электронный ресурс].

8. Schirmer, N. Verification of Sequential Imperative Programs in Isabelle/HOL [TeKCT]/N. Schirmer//PhD thesis. -Technische Universität München, 2006.

9. Norrish, M. A formal Semantics for C++ [TeKCT]/M. Norrish//Technical report, NICTA.-2008. -P. 1-125.

10. Cohen, E. A Precise Yet Efficient Memory Model For C [TeKCT]/E. Cohen, M. Moskal, W. Schulte [et al.]//4th International Workshop on Systems Software Verification (SSV2009)-2009.-P. 20-29.

11. Hoare, C. Procedures and parameters: An axiomatic approach [Текст]/С. Hoare//Lecture Notes in Mathematics-1971.-Vol. 188.-P. 102-116,

12. Непомнящий, В.А. На пути к верификации С-программ. Язык С-Light и его трансформационная семантика [Текст]/В.А. Непомнящий, И.С. Ануреев, А.В. Промский//УкрПРОГ-2006.-С. 23-25.

13. Mechta, F. Proving pointer programs in higherorder logic [Текст]^. Mechta, T. Nipkow.-2003.-Vol. 2741.-P. 121-135.

УДК 004.658.6

И.В. Бутенко, С.М. Устинов

методика построения репозитория метаданных

для существующей информационной системы

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

В связи с этим при создании новых информационных систем разработчики используют аппарат, базирующийся на метаданных (МД). Он предоставляет возможности описания и манипулирования метаданными в рамках либо общей модели CWM (Common Warehouse Metamodel), сформированной группой OMG (Object Management Group), либо модели конкретной метасистемы (МС).

Этим вопросам посвящены многочисленные работы ученых как в нашей стране, так и за рубежом (Д. Марко, А. Танненбаум, Р. Кимбалл, Б. Инмон), а также такие программные продукты, как Oracle Data Integrator , IBM Information Server, SAP BusinessObjects Metadata Manager, CA ERwin Saphir Option, SAS® Metadata Server.

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

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

Особую потребность в МД испытывают быстро меняющиеся информационные системы. Например, такими системами являются банковские, бухгалтерского учета и аналитические.

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

Формализация задачи

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

Из внешних источников метаданные загружаются в МС. Наиболее эффективна данная система именно для разнородных информационных си-

i Надоели баннеры? Вы всегда можете отключить рекламу.