Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
А применяется формальная верификация, например, в ядре Windows и операционных системах беспилотников Darpa, для обеспечения максимального уровня защиты.
Мы будем использовать Z3Prover, очень мощный инструмент для автоматизированного доказательства теорем и решения уравнения.
создание программ с доказанной эффективностью обходится в 10 раз дороже
но это уже выходит за рамки таких методов
Формальная верификация является самым мощным средством поиска и устранения уязвимостей: она позволяет найти все существующие дыры и баги в программе, либо же доказать, что их нет.
Я эту же задачу делал на Майкрософтовском (MSR) пруфере TLA.
Там похоже, но чуть проще на мой взгляд и выглядит математичнее.
Опишу кратко здесь, полный код можно найти на
https://github.com/mentin/tla/blob/master/river2/mega_crossing.tla
В TLA /\ обозначает "или", а \/ — "и", они для красоты пишутся и вначале тоже.
(* описываем кто у нас есть *)
Things == { "Man", "Goat", "Wolf", "Cabbage" }
(* вначале никто не пересек реку *)
Init == locs = [x \in Things |-> FALSE]
(* условие безопасности: козел с человеком либо не там где волк или капуста *)
IsSafe == \/ locs'["Goat"] = locs'["Man"]
\/ (/\ locs'["Goat"] /= locs'["Wolf"]
/\ locs'["Goat"] /= locs'["Cabbage"])
(* следующее состояние после пересечения реки с "х" - "х" и человек меняют сторону реки *)
CrossWith(x) == /\ locs["Man"] = locs[x]
/\ locs' = [locs EXCEPT !["Man"] = ~locs[x], ![x] = ~locs[x]]
(* шаг это пересечение реки, можно с кем угодно из Things *)
Next == /\ (\E x \in Things : CrossWith(x))
/\ IsSafe
(* хотим чтобы все пересекли реку *)
IsDone == locs = [x \in Things |-> TRUE]# We know each queen must be in a different row.
# So, we represent each queen by a single integer: the column position
import json
from z3 import *
Q = [ Int('Q_%i' % (i + 1)) for i in range(30) ]
# Each queen is in a column {1, ... 30 }
val_c = [ And(1 <= Q[i], Q[i] <= 30) for i in range(30) ]
# At most one queen per column
col_c = [ Distinct(Q) ]
# Diagonal constraint
diag_c = [ If(i == j,
True,
And(Q[i] - Q[j] != i - j, Q[i] - Q[j] != j - i))
for i in range(30) for j in range(i) ]
solve(val_c + col_c + diag_c)[Q_13 = 4,
Q_5 = 7,
Q_16 = 3,
Q_17 = 25,
Q_3 = 30,
Q_4 = 9,
Q_7 = 18,
Q_1 = 13,
Q_18 = 10,
Q_19 = 2,
Q_24 = 20,
Q_27 = 21,
Q_14 = 15,
Q_23 = 12,
Q_29 = 17,
Q_8 = 8,
Q_12 = 22,
Q_22 = 29,
Q_2 = 28,
Q_15 = 24,
Q_28 = 26,
Q_26 = 19,
Q_10 = 14,
Q_25 = 11,
Q_20 = 23,
Q_30 = 1,
Q_6 = 5,
Q_11 = 27,
Q_9 = 6,
Q_21 = 16]
Формальная верификация на примере задачи о волке, козе и капусте