Почему защита недопустима в этом инварианте цикла

#verification #frama-c #formal-verification #acsl

Вопрос:

Я пытаюсь создать инвариант цикла, чтобы проверить, имеют ли все элементы массива с четным индексом число 2 на них (программа для поиска простых чисел, на этом шаге она генерирует SPF).

Однако, когда я попробую это:

 /*@ loop invariant (forall integer j; (4<=j<i amp;amp; j%2==0 ==> prime[j]==2));
  */
  for (int i = 4; i <= n; i  = 2) {
    prime[i] = 2;
  }
 

Я получаю следующую ошибку:

 Warning: 
  invalid E-ACSL construct
  `invalid guard 4 ≤ j < i_0 ∧ j % 2 ≡ 0 in quantification
  ∀ ℤ j; 4 ≤ j < i_0 ∧ j % 2 ≡ 0 ⇒ *(prime   j) ≡ 2'.
  Ignoring annotation.

 

Я действительно не могу понять, что здесь происходит, но я очень ценю любую помощь

Ответ №1:

Проблема здесь в том, что E-ACSL не использует произвольные количественные формулы, а только те, которые он умеет переводить в виде for цикла. В основном это означает, что он синтаксически ищет явные границы для количественной переменной ( j в данном случае). Для этого он будет смотреть, имеет ли формула форму forall integer j; lower_bound <= j <= higher_bound ==> some_formula . Поскольку ваша гипотеза j добавляет ограничение по модулю, она не соответствует этому шаблону, следовательно, ее отклоняет E-ACSL. Чтобы избежать этой проблемы, вы можете переписать его как:

 forall integer j; (4<=j<i ==> j%2==0 ==> primes[j]==2)
 

это логически эквивалентно (в обоих случаях j должно находиться между 4 и i и быть четным primes[j] , чтобы быть равным 2 ), но теперь соответствует шаблону, который ищет E-ACSL.