Що таке інваріант?


130

Слово, здається, звикає в ряді контекстів. Найкраще, що я можу зрозуміти, це те, що вони означають змінну, яка не може змінитися. Хіба це не те, для чого потрібні константи / фінали (чорт ти Java!)?


Може, вони повинні були назвати це не варіантом?
johnny

Відповіді:


189

Інваріант є більш «концептуальним», ніж змінною. Взагалі, це властивість стану програми, що завжди відповідає дійсності. Функція або метод, який забезпечує, що інваріант має місце, як кажуть, підтримує інваріант.

Наприклад, бінарне дерево пошуку може бути інваріантним, що для кожного вузла ключ лівої дочірки вузла менше, ніж власний ключ вузла. Правильно написана функція вставки для цього дерева підтримуватиме цю інваріантність.

Як ви можете сказати, це не та річ, яку ви можете зберігати в змінній: це більше твердження про програму. З'ясувавши, який тип інваріантів має підтримувати ваша програма, переглянувши ваш код, щоб переконатися, що він фактично підтримує ці інваріанти, ви зможете уникнути логічних помилок у своєму коді.


1
Цей чудовий приклад був би кращим, якби він включив відповідь cero за посиланням на wikipedia.
ablarg

2
Вік батьків більший, ніж вік їх біологічних дітей. Навколишній контекст зміниться, але інваріант ніколи не зміниться. Наприклад, це може бути сім'я Сміта, яка має 2 дітей. Або це може бути в інших видів будь-якого ссавця. Контекст змінюється, але інваріант не змінюється.
truthadjustr

1
"... властивість програмного стану, яке завжди відповідає дійсності ..." - @jacob baskin - добре написано і за це дякую.
twknab

"... властивість програмного стану, яке завжди відповідає дійсності ..." - Я погоджуюся, що це добре написано, але це може ввести в оману. Спочатку я зрозумів це як булева правда, але я майже впевнений, що це означає "... завжди постійний" (але, можливо, це просто тому, що англійська мова не є моєю першою мовою)
dev-null

29

Це умова, за якою ви знаєте, що завжди є правдою в певному місці вашої логіки, і ви можете перевірити, коли налагоджувати, щоб дізнатися, що пішло не так.


17

Я зазвичай розглядаю їх більше з точки зору алгоритмів чи структур.

Наприклад, у вас може бути інваріант циклу, який можна стверджувати - завжди вірно на початку або в кінці кожної ітерації. Тобто, якщо ваш цикл повинен був обробити колекцію об'єктів з однієї стеки в іншу, ви можете сказати, що | stack1 | + | stack2 | = c, вгорі або внизу циклу.

Якщо інваріантна перевірка не вдалася, це вказувало б, що щось пішло не так. У цьому прикладі це може означати, що ви забули натиснути оброблений елемент на остаточний стек тощо.


17

Магія вікіпедії: Інваріант (інформатика)

В інформатиці присудок, який, якщо це правда, залишиться істинним протягом певної послідовності операцій, називається (ін) інваріантним для цієї послідовності.


2
Посилання? Технічний жаргон? ЧИТАННЯ? WTF ? ;) Якщо серйозно, то гарне посилання, але трохи резюме було б непогано.
Дастман

10

Як зазначено у цьому рядку:

В інформатиці присудок, який, якщо це правда, залишиться істинним протягом певної послідовності операцій, називається (ін) інваріантним для цієї послідовності.

Щоб краще зрозуміти цю надію, цей приклад на C ++ допомагає.

Розглянемо сценарій, коли потрібно отримати деякі значення та отримати їх загальну кількість у змінній, що називається як, countі додати їх у змінну, що називається якsum

Інваріант (знову ж це більше схоже на концепцію):

// invariant:
// we have read count grades so far, and
// sum is the sum of the first count grades

Код для вищезазначеного був би приблизно таким,

int count=0;
double sum=0,x=0;
while (cin >> x) {
++count;
sum+=x;
}

Що робить вищевказаний код?

1) Прочитає вхідні дані cinта додає їхx

2) Після одного успішного читання, збільшення countтаsum = sum + x

3) Повторюйте 1-2, поки читання не зупиниться (тобто ctrl + D)

Петля інваріантна:

Іваріант повинен бути ІСТИНИМ ЗАВЖДИ . Тож спочатку ви починаєте свій код саме з цього

while(cin>>x){
  }

Цей цикл зчитує дані зі стандартного введення та зберігає у x. Ну і добре. Але інваріант стає хибним, оскільки перша частина нашого інваріанта не дотримувалася (або зберігалася правдою).

// we have read count grades so far, and

Як зберегти правду інваріанта?

Просто! приріст кол.

Так ++count;би добре! Тепер наш код стає приблизно таким,

while(cin>>x){
 ++count; 
 }

Але

Навіть зараз наш інваріант (поняття, яке повинно бути ПРАВИЛЬНИМ) є помилковим, оскільки зараз ми не задовольнили другу частину нашого інваріанта.

// sum is the sum of the first count grades

То що тепер робити?

Додайте xдо sumі збережіть його у sum( sum+=x), і наступного разу cin>>xпрочитаєте нове значення у x.

Тепер наш код стає приблизно таким,

while(cin>>x){
 ++count; 
 sum+=x;
 }

Давайте перевіримо

Чи відповідає код нашому інваріанту

// invariant:
// we have read count grades so far, and
// sum is the sum of the first count grades

код:

while(cin>>x){
 ++count; 
 sum+=x;
 }

Ах !. Тепер цикл інваріантний "Істинний завжди" і код працює нормально.

Наведений вище приклад взяли та модифікували з книги « Прискорений C ++ » Ендрю-Конінг та Барбара-Е



2

Виходячи з того, що це таке, інваріанти досить корисні при написанні чистого коду, оскільки концептуально знання того, які інваріанти повинні бути присутніми у вашому коді, дозволяє вам легко вирішити, як організувати свій код для досягнення цих цілей. Як уже згадувалося, вони також корисні при налагодженні, оскільки перевірка того, чи підтримується інваріант, часто є хорошим способом побачити, чи будь-яка маніпуляція, яку ви намагаєтеся виконати, насправді робить те, що ви хочете.


2

Зазвичай це величина, яка не змінюється за певних математичних операцій. Прикладом є скаляром, який не змінюється при поворотах. Наприклад, у магнітно-резонансній томографії корисно характеризувати властивість тканини за допомогою обертального інваріанта, оскільки тоді її оцінка в ідеалі не залежить від орієнтації тіла в сканері.


2

Ця відповідь для моєї 5-річної дитини. Не думайте про інваріант як про постійне чи фіксоване числове значення. Але це може бути. Однак це більше того.

Швидше, інваріант - це щось на зразок фіксованих відносин між різними сутностями. Наприклад, ваш вік завжди буде меншим, ніж у порівнянні з вашими біологічними батьками. І ваш вік, і вік вашого батька змінюються з часом, але відносини, про які я згадував вище, інваріантні.

Інваріант також може бути числовою константою. Наприклад, значення pi- інваріантне відношення між окружністю кола над його діаметром. Незалежно від того, наскільки велике чи маленьке коло, це співвідношення завжди буде pi.


1

Інваріант ADT визначає зв'язки між полями даних (змінні екземпляра), які завжди повинні бути істинними до та після виконання будь-якого методу екземпляра.


0

Є чудовий приклад інваріанта і чому це має значення в книзі Java Concurrency in Practice .

Хоча орієнтований на Java, у прикладі описано деякий код, який відповідає за обчислення факторів поданого цілого числа. Приклад коду намагається кешувати останнє надане число та фактори, які були розраховані для підвищення продуктивності. У цьому сценарії є інваріант, який не враховувався в прикладі коду, який залишив код сприйнятливим до перегонових умов за паралельним сценарієм.

введіть тут опис зображення


0

Усі відповіді тут чудові, але я відчув, що я можу пролити більше світла на цю справу:

Інваріант з мовної точки зору означає щось, що ніколи не змінюється. Ця концепція походить насправді з математики, але це одна з популярних методик доказування в поєднанні з індукцією.

Ось як свідчить доказ: Якщо ви можете знайти інваріанта, який знаходиться в початковому стані, і що цей інваріант зберігається незалежно від будь-якої [правової] трансформації, застосованої до держави, то ви можете довести, що якщо певна держава не має цього інваріантний, то він ніколи не може відбутися, незалежно від того, яка послідовність перетворень застосовується до початкового стану.

Тепер попередній спосіб мислення (знову поєднаний з індукцією) дає можливість передбачити логіку комп'ютерного програмного забезпечення. Особливо важливо, коли виконання йде в циклі, в яких інваріант може бути використаний для доведення того, що певний цикл дасть певний результат або що він ніколи не змінить стан програми певним чином.

Коли інваріант використовується для предикації циклу циклу, його називають циклом інваріантом . Його можна використовувати зовнішні петлі, але для циклів це дійсно важливо, тому що у вас часто багато можливостей або нескінченна кількість можливостей.

Зауважте, що я використовую слово "предикат" логіку комп'ютерного програмного забезпечення, а не доказую. І це тому, що хоча математичний інваріант може бути використаний як доказ, він ніколи не може довести, що комп'ютерне програмне забезпечення при його виконанні дасть те, що очікується, через те, що програмне забезпечення виконується поверх багатьох абстракцій, що ніколи не може бути доведено що вони дадуть те, що очікується (подумайте, наприклад, про апаратну абстракцію).

Нарешті, хоча теоретично і жорстко прогнозувати логіку програмного забезпечення важливо лише для таких критично важливих програм, як Медична та Військова. Інваріант все ще може бути використаний для допомоги типовому програмісту при налагодженні. Її можна використовувати, щоб знати, де в певному місці. Програма не вдалася, оскільки вона не змогла підтримувати певний інваріант - багато хто з нас так чи інакше використовує її, не замислюючись про це.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.