Optimization of checking the feasibility of transitions when verifying formal models

Transitions feasibility analysis becomes a significant part of operation time of verification tools for formal models of programs, which control flow is expressed implicitly. This paper describes a new method of model checking performance improvement. The main idea is a localization of a transition’...

Повний опис

Збережено в:
Бібліографічні деталі
Дата:2015
Автор: Kolchin, A.V.
Формат: Стаття
Мова:Ukrainian
Опубліковано: PROBLEMS IN PROGRAMMING 2015
Теми:
Онлайн доступ:https://pp.isofts.kiev.ua/index.php/ojs1/article/view/70
Теги: Додати тег
Немає тегів, Будьте першим, хто поставить тег для цього запису!
Назва журналу:Problems in programming
Завантажити файл: Pdf

Репозитарії

Problems in programming
id pp_isofts_kiev_ua-article-70
record_format ojs
resource_txt_mv ppisoftskievua/a6/dc58b8b87c09286b9834588f3a426aa6.pdf
spelling pp_isofts_kiev_ua-article-702018-09-18T13:32:44Z Optimization of checking the feasibility of transitions when verifying formal models Оптимизация проверки выполнимости переходов при верификации формальных моделей Оптимізація перевірки здійсненності переходів при верифікації формальних моделей Kolchin, A.V. UDC 519.686.2 Верификация УДК 519.686.2 УДК 519.686.2 Transitions feasibility analysis becomes a significant part of operation time of verification tools for formal models of programs, which control flow is expressed implicitly. This paper describes a new method of model checking performance improvement. The main idea is a localization of a transition’s unsatisfiability reason in some state and it’s usage for the satisfiability analysis in subsequent states. При проверке динамических свойств формальных моделей программ, в которых последовательность выполнения операторов выражена неявно, существенную часть операционного времени верификаторы тратят на анализ выполнимости переходов. В работе предложен метод повышения производительности проверки моделей, суть которого заключается в локализации причины невыполнимости перехода в некотором состоянии и ее использовании для анализа выполнимости в последующих состояниях. При перевірці динамічних властивостей формальних моделей програм, в яких послідовність виконання операторів виражена неявно, істотну частину операційного часу верифікатори витрачають на аналіз здійсненності переходів. В роботі запропонований метод підвищення продуктивності перевірки моделей, суть якого полягає в локалізації причини нездійсненності переходу в деякому стані і її використанні для аналізу здійсненності в наступних станах. PROBLEMS IN PROGRAMMING ПРОБЛЕМЫ ПРОГРАММИРОВАНИЯ ПРОБЛЕМИ ПРОГРАМУВАННЯ 2015-09-10 Article Article application/pdf https://pp.isofts.kiev.ua/index.php/ojs1/article/view/70 PROBLEMS IN PROGRAMMING; No 2-3 (2012) ПРОБЛЕМЫ ПРОГРАММИРОВАНИЯ; No 2-3 (2012) ПРОБЛЕМИ ПРОГРАМУВАННЯ; No 2-3 (2012) 1727-4907 uk https://pp.isofts.kiev.ua/index.php/ojs1/article/view/70/72 Copyright (c) 2015 ПРОБЛЕМИ ПРОГРАМУВАННЯ
institution Problems in programming
baseUrl_str https://pp.isofts.kiev.ua/index.php/ojs1/oai
datestamp_date 2018-09-18T13:32:44Z
collection OJS
language Ukrainian
topic
UDC 519.686.2
spellingShingle
UDC 519.686.2
Kolchin, A.V.
Optimization of checking the feasibility of transitions when verifying formal models
topic_facet
UDC 519.686.2
Верификация
УДК 519.686.2

УДК 519.686.2
format Article
author Kolchin, A.V.
author_facet Kolchin, A.V.
author_sort Kolchin, A.V.
title Optimization of checking the feasibility of transitions when verifying formal models
title_short Optimization of checking the feasibility of transitions when verifying formal models
title_full Optimization of checking the feasibility of transitions when verifying formal models
title_fullStr Optimization of checking the feasibility of transitions when verifying formal models
title_full_unstemmed Optimization of checking the feasibility of transitions when verifying formal models
title_sort optimization of checking the feasibility of transitions when verifying formal models
title_alt Оптимизация проверки выполнимости переходов при верификации формальных моделей
Оптимізація перевірки здійсненності переходів при верифікації формальних моделей
description Transitions feasibility analysis becomes a significant part of operation time of verification tools for formal models of programs, which control flow is expressed implicitly. This paper describes a new method of model checking performance improvement. The main idea is a localization of a transition’s unsatisfiability reason in some state and it’s usage for the satisfiability analysis in subsequent states.
publisher PROBLEMS IN PROGRAMMING
publishDate 2015
url https://pp.isofts.kiev.ua/index.php/ojs1/article/view/70
work_keys_str_mv AT kolchinav optimizationofcheckingthefeasibilityoftransitionswhenverifyingformalmodels
AT kolchinav optimizaciâproverkivypolnimostiperehodovpriverifikaciiformalʹnyhmodelej
AT kolchinav optimízacíâperevírkizdíjsnennostíperehodívpriverifíkacííformalʹnihmodelej
first_indexed 2025-07-17T09:47:56Z
last_indexed 2025-07-17T09:47:56Z
_version_ 1850410118864175104
fulltext Формальні методи програмування УДК 519.686.2 ОПТИМИЗАЦИЯ ПРОВЕРКИ ВЫПОЛНИМОСТИ ПЕРЕХОДОВ ПРИ ВЕРИФИКАЦИИ ФОРМАЛЬНЫХ МОДЕЛЕЙ А.В. Колчин Институт кибернетики им. В.М. Глушкова НАН Украины, 03680, Киев, проспект Академика Глушкова, 40. E-mail: kolchin_av@yahoo.com При проверке динамических свойств формальных моделей программ, в которых последовательность выполнения операторов выражена неявно, существенную часть операционного времени верификаторы тратят на анализ выполнимости переходов. В работе предложен метод повышения производительности проверки моделей, суть которого заключается в локализации причины невыполнимости перехода в некотором состоянии и ее использовании для анализа выполнимости в последующих состояниях. Transitions feasibility analysis becomes a significant part of operation time of verification tools for formal models of programs, which control flow is expressed implicitly. This paper describes a new method of model checking performance improvement. The main idea is a localization of a transition’s unsatisfiability reason in some state and it’s usage for the satisfiability analysis in subsequent states. Введение Актуальной задачей для проверки правильности программных систем является повышение производительности автоматических средств верификации. Алгоритмы современных инструментов проверки формальных моделей оперируют множеством выполнимых переходов на данном состоянии (часто такое множество обозначают «enabled», или «outgoing transitions» [1–4]). Выполнение процедуры установления такого множества требуется на каждом достигнутом состоянии модели; причем, как правило, количество выполнимых (из некоторого состояния) переходов значительно меньше общего количества переходов модели. Для большого множества состояний и переходов эффективность такой процедуры будет критичной: наивный перебор затратит время O(MS·MT), где MS – количество достигнутых состояний, MT – общее количество переходов модели. Типичные модели императивных программ состоят из параллельно работающих компонент, в каждой из которых явно выделен поток управления, определяющий последовательность выполнения операторов. Структура потока управления крайне важна для анализаторов моделей (например, [1, 5, 6]): его граф может быть построен статически, что дает возможность построения таблицы соответствия вида: значение потока управления множество переходов, → позволяющей эффективно осуществлять выбор подмножества потенциально выполнимых переходов модели, что существенно повышает производительность верификации, так как на практике множество выполнимых переходов (в некотором состоянии) в среднем состоит из 1–3 элементов, тогда как общее количество переходов модели может исчисляться тысячами. Рассмотрим пример программы 1 (рис. 1), выполнением которой является линейная последовательность операторов. Такая программа позволяет построить граф потока управления и таблицу соответствия для выбора переходов (см. рис. 2 и табл. 1) статически, что сделает процедуру установления выполнимых переходов эффективной. Однако последовательность выполнения операторов может быть задана неявно как, например, в моделях с неупорядоченным множеством переходов [7, 8]. Далее модель программы 1 приведена в виде такого множества переходов (табл. 2). Необходимо отметить, что порядок выполнения операторов operator<i> в программе 2 сохранен. Таблица 1. Таблица соответствия вида: значение потока управления множество переходов → Таблица 2. Переходы модели программы 2 Переход Предусловие Постусловие T1 control_flow1==1 control_flow1 = 0; control_flow2 = 1; Operator1 T2 control_flow2==1 control_flow2 = 0; control_flow3 = 1; Operator2 ... TN control_flowN==1 control_flowN = 0; OperatorN Программа 2 не содержит явно выделенного потока управления, и как следствие, статически построенная таблица соответствия будет неэффективна, так как потребует перебора всех переходов в каждом Operator1; … OperatorN; control_flow1: Operator1; … control_flowN: OperatorN; Значение потока управления Множество потенциально выполни- мых переходов (операторов) модели Рис. 1. Программа 1 Рис. 2. Программа 1 с явно обозначенными значениями потока управления control_flow1 Operator1 … … control_flowN OperatorN 201 ©А.В. Колчин, 2012 ISSN 1727-4907. Проблеми програмування. 2012. № 2-3. Спеціальний випуск Формальні методи програмування достигнутом состоянии. Например, процесс достижения оператора OperatorN для программы 2 будет осуществляться так (рис. 3). Начальное состояние: control_flow1 = 1, control_flow2 = 0,…, control_flowN = 0; if(control_flow1 == 1){control_flow1 = 0; control_flow2 = 1; Operator1;} if(control_flow1 == 1) -- не выполняется if(control_flow2 == 1){control_flow2 = 0; control_flow3 = 1; Operator2;} if(control_flow1 == 1) -- не выполняется if(control_flow2 == 1) -- не выполняется if(control_flow3 == 1){control_flow3 = 0; control_flow4 = 1; Operator3;} ... if(control_flow1 == 1) -- не выполняется if(control_flow2 == 1) -- не выполняется ... if(control_flowN == 1){control_flowN = 0; OperatorN;} Рис. 3. Процесс проверки модели c неявно заданной последовательностью выполнения операторов То есть количество проверок атрибутов control_flow<i> будет равным N·(N+1)/2, и как следствие, сложность проверки программы так же становится квадратичной. Причем количество проверок невыполнимых условий N·(N-1)/2, следовательно, большую часть времени процесс проверки модели был занят поиском очередного выполнимого перехода, неэффективно перебирая невыполнимые условия. Описание метода Рассмотрим пример пропозициональной формулы: ZYX ∨∧ . Непосредственно из ее таблицы истинности следует, что если значение атомарной формулы X ложно, то значение не влияет на результат, т. е. значение Y Y можно не вычислять; аналогично, можно не вычислять значение , если и Y истинны. Z X Относительно невыполнимости, эта таблица (см. табл. 3) позволяет сделать такие выводы: для случая 6 формула будет гарантированно невыполнима до тех пор, пока не изменится либо X, либо Z; для случая 7 – либо Y, либо Z. Случай 8 требует изменения атрибутов X, Y либо атрибута Z. Таблица 3. Пример таблицы истинности логической формулы X Y Z ZYX ∨∧# 1 T T T T На практике во многих языках программирования (например, в Cи), бинарные логические операции интерпретируются как некоммутативные, и, как правило, ассоциируются слева направо. Сначала всегда вычисляется первый операнд; если его значения достаточно для определения результата операции, то второй операнд не вычисляется. 2 F T T T 3 T F T T 4 F F T T Описываемый метод создает и поддерживает таблицу соответствия «причина невыполнимости множество переходов» динамически, в процессе проверки свойств модели. В случае, если переход невыполним, локализируются предикаты, явившиеся причиной невыполнения, и в таблицу соответствия добавляется элемент {атрибуты, входящие в предикаты имя перехода}. Далее переход будет гарантировано невыполнимым до тех пор, пока хотя бы один из этих атрибутов не изменит своего значения. 5 T T F T 6 F T F F 7 T F F F → 8 F F F F → Далее приведены основные формальные определения необходимые для описания алгоритмов. nvvvA ,...,, 21= Пусть задано конечное множество атрибутов и пусть также для каждого атрибута определена конечная область допустимых значений . Avi ∈ )( ivD Определение 1. Состоянием называется множество пар атрибутов и их значений вида . )}(,|)({ ||..0 iiiAi ii vDdAvdv ∈∈= =U Определение 2. Предусловием называется бескванторная формула (классической) логики предикатов над атрибутами множества A и констант множества . Ui ivDD )(= ),( ss ′β Определение 3. Постусловием называется конечное множество присваиваний вида , где атрибут состояния Aa∈ s′ expr D, – выражение над константами ),(: exprsFa = и атрибутами состояния s s– функция, вычисляющая значение выражения exprF, в состоянии . Не теряя общности, предполагается, что ни пред- ни постусловия: не допускают деления на ноль, выходов за пределы допустимых значений, переполнений и потерь значимости, а так же использования неинициализированных атрибутов. Анализ таких свойств потребует введения вспомогательных атрибутов и проверок; требуемая модификация не является критичной для доказательства основных свойств алгоритмов. Определение 4. Переходом называется тройка вида ),,( βα t , где α – предусловие, – метка (имя перехода), t β – постусловие. F В описании алгоритмов для интерпретации атомарных формул предусловий и функции будет использоваться функция interpret(<состояние>, <выражение>). 202 Формальні методи програмування =| Определение 5. Истинность формулы ϕ на состоянии s, записывается s ϕ, определяется индуктивно по структуре формулы ϕ: a ≡ interpret(s,a)= T – если атомарная формула a истинна в состоянии s; =|s =| ≠| ~ϕ ≡ ss ϕ – если формула ϕ не выполняется в s; s =| =| =|∧ ∧ – если в s выполняется формула ϕ ϕ1 ϕ2 ≡ s ϕ1 s ϕ 1 и ϕ22 ; s ∨ ∨ s=| =| =| – если в s выполняется формула ϕ ϕ1 ϕ2 ≡ s ϕ1 ϕ2 1 или ϕ2. Определение 6. Переход выполним из состояния t s ts α=| . тогда и только тогда когда Определение 7. Выполнением перехода из состояния t s s′ в состояние называется проверка его выполнимости из s s′ согласно определению 6 и модификация согласно определению 3. Для описания алгоритмов будет использоваться язык высокого уровня, состоящий из Упрощенного Алгола [9], и правил переписывания термов языка алгебраического программирования APLAN [10]. Из соображений простоты описания и доказательств, приведенные алгоритмы не претендуют на оптимальность. Далее описан алгоритм, определяющий множество атрибутов, необходимое для вычисления выполнимости перехода. Алгоритм интерпретации предусловий переходов Далее описан алгоритм, преобразующий логическую формулу в программу, интерпретирующую предусловия переходов с учетом некоммутативности логических операторов. Алгоритм 1. Интерпретация предусловий. Вход. Имя перехода t и формула предусловия Pre. Выход. Текст процедуры t], интерпретирующей предусловие Pre. precond[ interpret_pre := procedure(t, Pre) begin return ‘precond[’ t ‘] := procedure(S)local(R_ARR, result, r_idx, i1, i2) begin r_idx ← 0; ’ ! truth_table(Pre, T) ! ‘ return (result; {R_ARR[0..r_idx]}) end’ end Кавычки ‘’ используются для выделения строк, знак «!» обозначает операцию конкатенации. Оператор truth_table представляет собой систему переписывающих правил [10], которая сопоставляет левую часть (до знака «=») каждого правила входному терму сверху вниз до первого совпадения, и на выходе строит терм согласно правой части правила; T, F обозначают соответственно True, False; оператор push(x) означает заталкивание аргумента x в стек; оператор pop(x) означает выталкивание элемента из вершины стека и запись его значения в аргумент x; функция interpret вычисляет значение атомарных формул: truth_table := rewrite_system(a, b, p)begin ∨1. (a b, p) = 1a. ‘push(r_idx); 1b. ’ ! truth_table(a, p) ! ‘ 1c. if (result = ~(’ ! p ! ‘)) then 1d. begin 1e. push(r_idx); 1f. ’ ! truth_table(b, p) ! ‘ 1g. pop(i2); 1h. pop(i1); 1i. if (result =’ ! p ! ‘) then 1j. r_idx ← replace (i1, i2, r_idx) 1k. end 1l. else pop(i1);’, ∧2. (a b, p) = 2a. ‘push(r_idx); 2b. ’ ! truth_table(a, p) ! ‘ 2c. if (result = ’ ! p ! ‘) then 2d. begin 2e. push(r_idx); 2f. ’ ! truth_table(b, p) ! ‘ 2g. pop(i2); 2h. pop(i1); 2i. if (result = ~(’ ! p ! ‘)) then 2j. r_idx ← replace (i1, i2, r_idx) 203 Формальні методи програмування 2k. end 2l. else pop(i1);’, 3. (~(a), p) = truth_table(a, ~(p)), 4. (a, T) = read(a) ! ‘result interpret (S, ‘ ! a ! ’)’, ← 5. (a, F) = read(a) ! ‘result ~( interpret (S, ‘ ! a ! ’))’, ← end Процедура read строит операторы для добавления в массив R_ARR атрибутов, входящих в формулу: read := procedure(atomic_formula)local(r, attr)begin ← ‘’; r for attr ∈ atomic_formula begin r r ! ‘ R_ARR[r_idx] ’ ! attr; ← ← r r ! ‘ r_idx ← r_idx + 1;’ ← end return r end Процедура replace удаляет элементы с индексами idx1..idx2-1 из массива R_ARR путем сдвига элементов влево на (idx2-idx1) шагов начиная с позиции idx2. replace := procedure(idx1, idx2, idx)local(i) begin ← for(i idx2; i < idx; i ← i + 1) do R_ARR[i]; R_ARR[i – (idx2 - idx1)] ← return (idx - (idx2 - idx1)) end □ На рис. 4 и 5 показаны примеры построения процедуры для переходов t1 и t2. Вход: Вход: interpret_pre(t1, x=a+b y=0) ∧ interpret_pre(t2, x=0 ~(y=0 z=0)) ∨ ∨ Выход: Выход: precond[t1] := procedure(S) precond[t2] := procedure(S) local(R_ARR,result,r_idx,i1,i2) local(R_ARR,result,r_idx,i1,i2) begin begin r_idx 0; r_idx 0; ← ← push(r_idx); push(r_idx); R_ARR[r_idx] x; x; R_ARR[r_idx] ← ← r_idx r_idx + 1; ← r_idx r_idx + 1; ← ← R_ARR[r_idx] a; result interpret(S, x=0); ← if esult = ~(T)) then r_idx r_idx + 1; (r begin ← R_ARR[r_idx] b; ← r_idx r_idx + 1; push(r_idx); ← result interpret(S, x=a+b); y; R_ARR[r_idx] ← ← if (result = T) then r_idx r_idx + 1; ← begin pop(i2); push(r_idx); pop(i1); R_ARR[r_idx] y; ~(interpret(S, y=0)); result ← ← if(result = ~(F))then r_idx r_idx + 1; ← begin pop(i2); push(r_idx); pop(i1); ← R_ARR[r_idx] z; result ~(interpret(S, y=0)); ← if(result = ~(T))then r_idx r_idx + 1; ← r_idx replace(i1,i2,r_idx) pop(i2); ← end pop(i1); else op(i1); p return (result; {R_ARR[0..r_idx]}) result ~(interpret(S, z=0)); ← if(result = ~(F))then end r_idx replace(i1,i2,r_idx) ← else pop(i1); end end else op(i1); p return (result; {R_ARR[0..r_idx]}) end Рис. 4. Пример 1 работы алгоритма 1 Рис. 5. Пример 2 работы алгоритма 1 В табл. 4, 5 приведены примеры работы процедуры интерпретации предусловий переходов t1 и t2. 204 Формальні методи програмування Таблица 4. Примеры работы precond[t1] Таблица 5. Примеры работы precond[t2] Предусловие t1: x=a+b y=0 ∧ Предусловие t2: x=0 ~(y=0 z=0) ∨ ∨ Вход - состояние S Выход Вход - состояние S Выход a=0, b=0, x=0, y=0 (T, {x,a,b,y}) x=0,y=0,z=0 (T, {x}) a=0, b=0, x=1, y=0 (F, {x,a,b}) x=1,y=0,z=0 (F, {x,y}) a=0, b=0, x=0, y=1 (F, {y}) x=1,y=1,z=0 (F, {x,z}) Лемма 1. Алгоритм 1 строит процедуру precond, которая: а) интерпретирует согласно определению 5 логическую формулу Pre (удовлетворяющую определению 2), и имеет значение result на выходе T если формула истинна и F в противном случае; б) для бинарных операций не вычисляет второй операнд, если значения первого операнда достаточно для определения результата операции; в) множество элементов массива R_ARR[0..r_idx] после окончания работы процедуры содержит атрибуты, значений которых достаточно для интерпретации формулы Pre. Доказательство: а) преобразование пропозициональных связок (truth_table, правила 1–3) и вычисление результата интерпретации атомарных формул, т. е. вызов функции interpret (правила 4, 5) производятся с учетом полярности (атрибут p в правилах 1–3 и T, F – в 4,5) согласно таблицам истинности для логических выражений; б) согласно семантике операторов if-then (в строках 1c, 2c), вычисление второго операнда (строки 1f, 2f) осуществляется только в случае, когда значения первого операнда (вычисленного в строках 1b, 2b) не достаточно для определения результата операции; в) базис рекурсии (правила 4, 5) содержит вызов процедуры interpret, которая вычисляет результат атомарного выражения. А так как процедура read вызывается только перед вызовом interpret с тем же параметром, и только она добавляет элементы в массив R_ARR, то элементы R_ARR[0..r_idx] будут содержать только атрибуты, входящие в операнды, значения которых вычислялись; этих атрибутов, очевидно, достаточно для вычисления результата. Создаваемая процедура не имеет циклов и не содержит рекурсивных вызовов, следовательно, время ее работы имеет линейную зависимость от количества атомарных предикатов и атрибутов, входящих в формулу. Осталось показать, что все элементы R_ARR, удаленные процедурой replace, были добавлены в массив только в процессе избыточных вычислений (т. е. соответствующие вызовы процедуры read можно было бы не осуществлять). Рассмотрим вызовы процедуры replace. В момент вызова в строке 1j, элементы массива R_ARR[i1..i2-1] (согласно строкам 1a, 1b, 1e, 1g, 1h, 1l) содержат только атрибуты, необходимые для вычисления первого дизъюнкта (подформулы a), а элементы R_ARR[i2..r_idx] (согласно строкам 1e, 1f, 1g) для вычисления второго (подформулы b). Для определения результата a b оказалось (согласно строкам 1f, 1i) достаточно вычисления второго дизъюнкта, следовательно, достаточно значений атрибутов, входящих в подформулу b; вычисление подформулы a, согласно таблице истинности формулы a b, в этом случае можно считать избыточным, а значит, элементы R_ARR[i1..i2-1]можно удалить. ∨ ∨ Аналогично, в момент вызова в строке 2j, элементы R_ARR[i1..i2-1] (согласно строкам 2a, 2b, 2e, 2g, 2h, 2l) содержат только атрибуты, необходимые для вычисления первого конъюнкта (подформулы a), а элементы R_ARR[i2..r_idx] (согласно строкам 2e, 2f, 2g) для вычисления второго (подформулы b). Для определения результата a∧ b оказалось (согласно строкам 2f, 2i) достаточно вычисления второго конъюнкта, следовательно, достаточно значений атрибутов подформулы b; вычисление подформулы a, согласно таблице истинности a b, в этом случае можно считать избыточным, а элементы R_ARR[i1..i2-1]можно удалить. □ ∧ Следствие 1. Результат выполнения precond[t](S) соответствует определению 6: S result=T ⇔= tα| ⇔≠ tα| result=F. ∧ S Следствие 2. В случае невыполнимости перехода, никакое изменение состояния S, не включающее атрибутов из R_ARR[0..r_idx], не приведет к его выполнимости. Для краткости, элементы массива R_ARR[0..r_idx] будут называться R-атрибутами. В случае если переход невыполним, эти элементы представляют собой причину невыполнения. Необходимо отметить, что множество R-атрибутов будет содержать не обязательно все атрибуты, входящие в предусловие. Например, для вычисления f ∧ ∧f …f при истинных f ,…,f и ложном f1 2 n 1 n-1 n, результатом работы процедуры precond будут только атрибуты, входящие в f ; аналогично, только атрибуты, входящие в fn n, будут результатом для вычисления ~(f ∨ ∨f …f ) при ложных f ,…,f и истинном f . 1 2 n 1 n-1 n Алгоритм 1 будет использоваться для определения причины невыполнимости переходов. Его так же можно использовать для проверяемых свойств модели, выраженных согласно определению 2 (при этом вместо имени перехода первым параметром precond нужно указать идентификатор проверяемого свойства). Постусловие переходов интерпретируются процедурой postcond[t]. Она должна вычислять новое состояние модели, а так же формировать множество атрибутов, изменивших свое значение. 205 Формальні методи програмування Алгоритм 2. Интерпретация постусловий. Вход. Переход t, множество присваиваний постусловия Post, так же исходное состояние Src, и целевое Dst. Выход. Процедура postc для интерпретации присваиваний Pos , а так же множество W. ond[t] t interpret_post := procedure(t, Post)local(r, w, expr)begin 1. r ‘postcond[t] := procedure(Src, Dst)local(W) begin’; ← 2. r r ! ‘W ← ;’; ∅← 3. for (w := expr) ∈ Post do begin 4. r r ! ‘if(Dst->’! w ! ‘ ≠ interpret(Src, expr))then W W ’ ! w ! ‘;’; ∪← ← 5. r r ! ‘Dst->’! w ! ‘← interpret(Src, expr)’ ! ‘;’ ← end 6. r r ! ‘return (Dst; W) end’; ← 7. return r end □ Лемма 2. Алгоритм 2 строит процедуру postcond, которая: а) выполнит все присваивания Post(Src, Dst) согласно определению 3; б) формирует множество атрибутов W, которым осуществлялось присваивание новых значений. Доказательство: а) строка 3 предполагает выполнение строки 5 для каждого присваивания; в строке 5 присваивание значения, вычисляемого из (предыдущего) состояния Src, выполняется для атрибута (нового) состояния Dst; б) согласно строке 2, множество W изначально пустое; атрибуты добавляются во множество W только в строке 4 при условии, что присваиваемое значение новое; строка 3 предполагает выполнение строки 4 для каждого присваивания. □ Алгоритм 2 будет использоваться для определения атрибутов, изменивших свое значение (далее W- атрибутов), а так же для вычисления нового состояния модели. Далее описана процедура для выполнения переходов transit, удовлетворяющая определениям 4 и 7, которая на основании имени перехода Transition и состояния Src формирует множество R-атрибутов, и, если переход допустим, новое состояние Dst, а так же множество W-атрибутов. transit := procedure(Src, Transition, Dst) local(result, R, W) begin W ∅ ; ← (result; R) precond[Transition](Src); ← if(result = T) then (Dst; W) ← postcond[Transition](Src, Dst); return (result; Dst; R; W) end □ На рис. 6 показаны примеры работы процедуры transit. Предусловие перехода t1 : (x = a + b ∧ y = 0) Постусловие перехода t1 : (a := a - 1; x := 0) Вход: transit( (a=2,b=0,x=2,y=0), Вход: transit( (a=2,b=0,x=0,y=1), t1, t1, (a=2,b=0,x=2,y=0) ) (a=2,b=0,x=0,y=1) ) Выход: Выход: (T;(a=1,b=0,x=0,y=0); {x,a,b,y}; {a,x}) (F;(a=2,b=0,x=0,y=1); {y}; ∅ ) Рис. 6. Примеры работы процедуры transit Абстрактный алгоритм верификации Перед тем, как приступить к описанию алгоритма выбора подмножества потенциально выполнимых переходов, необходимо абстрактно определить алгоритм верификации, оперирующий множеством Enabled_Set. Допустим, он построен на алгоритме поиска в глубину (например, [2]). traverse := procedure(S)local(Enabled_Set, t, explored, S_new, res, R, W) begin a1. if (visited(S) = T) then return; else visited(S) T; ← a2. check_properties(S); a3. Enabled_Set Get_Enabled(S); ← a4. for t ∈ (Enabled_Set \ explored) do begin a5. explored explored ∪ t; ← a6. S_new copy(S); ← a7. (res, S_new, R, W) transit(S, t, S_new); ← a8. if (res = T) then traverse(S_new) end a9. return end □ 206 Формальні методи програмування Отношение visited:S→{T,F} используется для отметки пройденных состояний. Процедура check_properties(S) осуществляет проверку свойств на состоянии S. Процедура Get_Enabled(S) выполняет формирование множества выполнимых переходов из состояния S. Алгоритм выбора выполнимых переходов Далее описан алгоритм выбора подмножества потенциально выполнимых переходов. Данный алгоритм подразумевает такие модификации абстрактного алгоритма верификации traverse. - Вызов процедуры: 1) в начальном состоянии все переходы включаются в ENABLED, а множество DISABLED объявляется пустым; процедура traverse дополняется параметром для множества W-атрибутов (изначально пустого): ENABLED All transitions; ← DISABLED ∅ ; ← ∅new_traverse(initial, ). - Во вновь вычисленном новом состоянии S перед инициализацией множества Enabled_Set: 2) все переходы из множества DISABLED, причина невыполнения которых входит во множество W (т. е. атрибутов, изменивших свое значение), заносятся во множество ENABLED, так же все элементы с этим переходом (у одного перехода может быть более чем одна причина невыполнимости) удаляются из DISABLED. - В процессе работы с множеством Enabled_Set (при выполнении переходов): 3) если переход из множества Enabled_Set оказывается невыполнимым, то он удаляется из ENABLED, заносится во множество DISABLED с указанием причины невыполнимости. 4) для восстановления исходных значений множеств ENABLED, DISABLED используются множества tmp_enabled и tmp_disabled. Модификации алгоритма содержатся в строках m<i>, строки a<i> соответствуют исходной процедуре traverse. new_traverse := procedure(S, W)local(tmp_enabled, tmp_disabled, r, t, Enabled_Set, explored, S_new, res, R, W_new, x)begin a1. if (visited(S) = T) then return; else visited(S) T; ← a2. check_properties(S); m1. ∅ ∅tmp_enabled ← ; tmp_disabled ← ; m2. for r ∈ W do m3. while t|(r,t) ∈ DISABLED do begin ∃ ENABLED ∪ t; m4. ENABLED ← m6. while x|(x,t) ∈ DISABLED do begin ∃ m7. tmp_enabled tmp_enabled ∪ (r,t); ← m8. DISABLED DISABLED \ (r,t) ← end end m9. Enabled_Set ENABLED; ← a4. for t ∈ (Enabled_Set \ explored) do begin a5. explored explored ∪ t; ← a6. S_new copy(S); ← a7. (res, S_new, R, W_new) transit(S, t, S_new); ← a8. if T) then new_traverse(S_new, W_new); (res = else begin m10. ENABLED ENABLED \ t; ← m11. for r ∈ R do begin m12. tmp_disabled tmp_disabled ∪ (r,t); ← m13. DISABLED DISABLED ∪ (r,t) ← end end end m14. for (r,t) ∈ tmp_enabled do begin m15. DISABLED DISABLED ∪ (r,t); ← m16. ENABLED ENABLED \ t ← end m17. for (r,t) ∈ tmp_disabled do begin m18. ENABLED ENABLED ∪ t; ← m19. ISABLED DISABLED \ (r,t) D end ← a9. return end □ 207 Формальні методи програмування Вместо строки a3 множество Enabled_Set теперь формируется в строке m9. Лемма 3. Для любого вызова new_traverse(S,W), множество ENABLED (DISABLED) в начале работы процедуры равно множеству ENABLED (DISABLED) в конце ее работы. Доказательство. Можно показать индукцией по числу завершенных вызовов процедуры new_traverse(S,W), что каждое ее выполнение удовлетворяет утверждению леммы. Базис индукции. Рассмотрим первое завершение работы процедуры в строке a9, когда все переходы из множества Enabled_Set оказались, согласно строкам a4–a8, невыполнимы (случай завершения в строке a1 тривиален). До выполнения строки m14, множества ENABLED и DISABLED могли изменяться в строках m4, m8 и m10, m13. Рассмотрим строки m4, m8: множество tmp_enabled будет содержать, согласно строкам m3, m6, m7, все элементы, удаленные из DISABLED в строке m8, и переходы, добавленные во множество ENABLED строке m4, и только их, так как в строке m1 оно объявляется пустым. Рассмотрим строки m10, m13: множество tmp_disabled будет содержать, согласно строкам m11, m12, все элементы, добавленные во множество DISABLED в строке m13, а так же переход, удаленный из ENABLED в строке m10, и только их, так как в строке m1 оно объявляется пустым. Тогда после выполнения строк m14–m19, множества ENABLED и DISABLED вернутся в исходное состояние, так как, согласно строкам m14, m15, m16 все элементы из множества tmp_enabled будут добавлены в DISABLED и каждый переход удален из ENABLED, а согласно строкам m17, m18, m19 все элементы из множества tmp_disabled будут удалены из DISABLED, и каждый переход добавлен в ENABLED. Индукционный переход. Достаточно показать, что множества tmp_enabled и tmp_disabled после выполнения соответственно строк m7 и m12 не будут модифицированы где-либо еще до выполнения строк m12–m17. Это справедливо, так как множества tmp_enabled и tmp_disabled являются локальными для процедуры new_traverse, всякий ее рекурсивный вызов порождает новые экземпляры этих множеств, и следовательно, экземпляры любого вызова модифицируются только в указанных строках того же вызова. □ Лемма 4. Для любого вызова new_traverse(S,W) в строке m9 справедливо утверждение: для любого перехода, либо он является элементом множества ENABLED, либо он невыполним в состоянии S и множество DISABLED содержит непустое множество пар (причина, переход) таких, что никакое изменение атрибута, не являющегося причиной, не приведет к выполнимости этого перехода. Доказательство. Достаточно показать индукцией по числу вызовов процедуры new_traverse(S,W). Случай завершенных вызовов, согласно лемме 3, тривиален. Рассмотрим случай незавершенных вызовов. Базис индукции. Случай первого вызова тривиален, так как в начальном состоянии множество ENABLED содержит все переходы, а множество DISABLED пустое. Индукционный переход. По предположению индукции, утверждение леммы выполняется для S и требуется доказать справедливость утверждения в следующем рекурсивном вызове new_traverse(S_new,W_new). Вначале рассмотрим возможные изменения множества ENABLED. Необходимо рассмотреть такие варианты обработки очередного перехода t, выбранного из множества Enabled_Set в строке a4: 1) переход t выполним в состоянии S. Тогда, согласно строке a8, произойдет рекурсивный вызов процедуры new_traverse(S_new, W_new), до выполнения строки m9 которого никакие элементы из ENABLED не удаляются и в DISABLED не добавляются, т. е. истинность утверждения леммы сохраняется при следующем вызове; 2) переход t невыполним в состоянии S (тогда рекурсивный вызов new_traverse обеспечивается наличием во множестве Enabled_Set другого, выполнимого, перехода). Отметим, что это повлечет, согласно строке a8, удаление t из ENABLED (в строке m10) и добавление всего множества пар (r∈R, t) в DISABLED (в строках m11, m12, m13). Этот случай рассмотрен ниже в изменении множества DISABLED. Далее рассмотрим возможные изменения множества DISABLED. Условием для выполнимости любого перехода, содержащегося в DISABLED, по предположению индукции, может быть только изменение значения как минимум одного атрибута a, являющегося причиной невыполнения, т. е. множество DISABLED содержит пару (a, t). Тогда в следующем рекурсивном вызове new_traverse(S_new, W_new) переход t либо становится выполнимым (а значит, согласно строке a7 и лемме 2, существует a∈W_new), и, согласно строкам m4, m8 добавляется в ENABLED и удаляется из DISABLED, либо, в противном случае, согласно следствию 2 леммы 1, остается невыполнимым, и как следствие, не добавляется в ENABLED и не удаляется из DISABLED. В обоих случаях индукционный шаг сохраняет истинность утверждения леммы. □ Теорема 1 (о непротиворечивости абстрактному алгоритму верификации). Для любого вызова процедуры new_traverse(S,W), множество Enabled_Set будет содержать все выполнимые из состояния S переходы. 208 Формальні методи програмування Доказательство. Непосредственно из леммы 4 следует, что в строке m9 все выполнимые в состоянии S переходы принадлежат множеству ENABLED. Следовательно, множество Enabled_Set будет содержать все выполнимые в S переходы, так как оно формируется из множества ENABLED. □ Теорема 2 (об оптимизации абстрактного алгоритма верификации). Для любого рекурсивного вызова new_traverse(S_new, W_new), справедливо утверждение: если некоторый переход невыполним в предыдущем состоянии, и множество W_new не содержит атрибутов, являющихся причиной невыполнения перехода, то этот переход невыполним и в состоянии S_new, а множество Enabled_Set не будет его содержать. Доказательство. По индукции аналогично доказательству леммы 4: при обработке вызова new_traverse(S_new, W_new) переход t может стать выполнимым, согласно следствию 2 леммы 1, только если существует такое a∈W_new, что (a,t)∈DISABLED. В противном случае, переход не добавляется в ENABLED, и как следствие, не будет принадлежать множеству Enabled_Set. □ Следствие. Пусть E1 – множество переходов, возвращаемых функцией Get_Enabled(S) в абстрактном алгоритме верификации, E2 – множество переходов Enabled_Set в строке m9 процедуры new_traverse. Тогда E ⊆ E . 2 1 Оценка дополнительных затрат времени и памяти для построения множеств ENABLED и DISABLED существенным образом зависит от верифицируемой модели. Конечно, можно построить такую модель, в которой в предусловиях переходов будут громоздкие формулы, включающие все атрибуты модели, а постусловия будут так же изменять значения всех возможных атрибутов, тогда в худшем случае время дополнительных затрат будет О(M 2 · M ), где M – количество переходов модели, MA T T A – атрибутов, тогда как прямой перебор потребует время O(MT). Однако на практике переходы совсем не такие. Назовем модель реалистичной, если она удовлетворяет таким предположениям, наиболее приближенным к реальным моделям: 1) количество элементов множества W при каждом вызове new_traverse – маленькая константа, в реальных моделях в среднем переход изменяет значения 3–4 атрибутов, следовательно, W состоит из 3–4 элементов; 2) количество элементов множества R причин невыполнения переходов – маленькая константа. В реальных моделях в среднем это значение равно 1–2 элементам для каждого перехода; 3) количество переходов, соответствующих одному атрибуту–причине невыполнения – M /MT A. Чаще всего это значение распределения не превосходит 3. Однако в моделях с явно выделенным потоком управления ситуация иная; в случаях, когда можно статически выделить атрибут, являющийся потоком управления, его следует обрабатывать отдельно, используя его значение для дополнительной индексации соответствий {причина невыполнения → множество переходов}, что позволит многократно улучшить распределение. Теорема 3. Дополнительное время и память, затраченные на вычисление множества Enabled_Set при каждом вызове процедуры new_traverse для реалистичных моделей O(M /M ). T A Доказательство. Оценка следует из предположения о реалистичных моделях. Зависимость от распределения M /MT A порождается в строке m3, остальные затраты времени и памяти согласно предположению – маленькая константа. □ Можно показать, что метод пригоден и для поиска в ширину, однако недостатком будет неэффективное использование памяти: для каждого состояния нужно хранить различные экземпляры таблиц ENABLED и DISABLED. Выводы В лучшем случае метод позволит уменьшить сложность установления множества выполнимых переходов с O(M 2·M ·M /M ), где M – количество сгенерированных состояний, M) до O(MS T S T A S T – переходов модели, MA – атрибутов. На практике, безусловно, лучше применять описанный метод в комбинации со статическим анализом потока управления. Необходимо отметить, что алгоритм 1 не требует построения нормальных форм для предусловий переходов, а так же улучшает результаты [7], существенно сокращая множество атрибутов, достаточных для определения результата выполнения переходов и заданных свойств. Описанный метод может быть использован совместно с существующими оптимизациями и методами редукции [1–7] пространства поиска. Для эффективной работы с типами данных, которые имеют большой диапазон допустимых значений, процедура установления множества допустимых переходов может быть усовершенствована путем применения адаптированного метода абстракции предикатов. 1. Holzmann G. The model checker SPIN // IEEE transactions on software engineering. – 1997. – Vol. 23. – N 5. – P. 279–295. 2. Holzmann G., Peled D. An improvement in formal verification // FORTE 1994 Conference. – 1994. – P. 197–211. 3. Zhang Y., Rodriguez E., Zheng H., Myers C. A Behavioral Analysis Approach for Efficient Partial Order Reduction // In proc. of the 13th IEEE International Symposium on High-Assurance Systems Engineering. – 2011. – P. 49–56. 209 Формальні методи програмування 4. Jussila T. On Bounded Model Checking of Asynchronous Systems // Doctoral Thesis. Helsinki University of Technology, Laboratory for Theoretical Computer Science. Research report A97. – 2005. – P. 136. 5. Beyer D., Henzinger T., Jhala R., Majumdar R. The software model checker BLAST // International Journal Software Tools Technology Transfer. – 2007. – N 9. – P. 505–525. 6. Zheng H. Compositional reachability analysis for efficient modular verification of asynchronous designs // IEEE Trans. on CAD of Integrated Circuits and Systems. – 2010. – Vol. 29. – P. 329–340. 7. Колчин А.В. Автоматический метод динамического построения абстракций состояний формальной модели // Кибернетика и системный анализ. – 2010. – № 4. – С. 70–90. 8. Летичевский А., Капитонова Ю., Волков В. и др. Спецификация систем с помощью базовых протоколов // Кибернетика и системный анализ. – 2005. – № 4. – С. 3–21. 9. Ахо А., Хопкрофт Дж., Ульман Дж. Построение и анализ вычислительных алгоритмов. – М.: Мир, 1979. – С. 536. 10. Letichevsky A., Kapitonova J., Konozenko S. Computations in APS // Theoretical Computer Science. – 1993. – Vol. 119. – P. 145–171. 210