Что такое инвариант?

Слово, похоже, используется в ряде контекстов. Лучшее, что я могу понять, это то, что они означают переменную, которая не может измениться. Разве это не то, что константы/финалы (чертовски вы Java!) Для?

Ответ 1

Инвариант более "концептуальен", чем переменная. В общем, это свойство состояния программы, которое всегда верно. Говорят, что функция или метод, обеспечивающий сохранение инварианта, сохраняет инвариант.

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

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

Ответ 2

Это условие, которое, как вы знаете, всегда должно быть истинным в определенном месте вашей логики и может проверять, когда отладка будет устранена, что пошло не так.

Ответ 3

Я обычно рассматриваю их больше с точки зрения алгоритмов или структур.

Например, у вас может быть инвариант цикла, который можно было бы утверждать - всегда true в начале или конце каждой итерации. То есть, если бы ваш цикл должен обрабатывать коллекцию объектов из одного стека в другой, вы могли бы сказать, что | stack1 | + | stack2 | = c, в верхней или нижней части цикла.

Если проверка инварианта не удалась, это означало бы, что что-то пошло не так. В этом примере это может означать, что вы забыли направить обработанный элемент в последний стек и т.д.

Ответ 4

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

В информатике предикат, который, если это правда, останется верным на протяжении всего определенной последовательности операций, является (an), инвариантный к Последовательность.

Ответ 5

Как говорится в этой строке:

В информатике предикат, который, если true, останется истинным во всей определенной последовательности операций, называется (an), инвариантным к этой последовательности.

Чтобы лучше понять эту надежду, этот пример на С++ помогает.

Рассмотрим сценарий, в котором вы должны получить некоторые значения и получить общее количество их в переменной, называемой 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

Как сохранить инвариант true?

Simple! счетчик приращений.

Итак ++count; будет делать добро!. Теперь наш код станет чем-то вроде этого,

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

Но

Даже теперь наш инвариант (понятие, которое должно быть TRUE) является False, потому что теперь мы не удовлетворили вторую часть нашего инварианта.

// 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;
 }

Ах!. Теперь инвариант цикла всегда True, и код работает нормально.

Вышеприведенный пример был взят и изменен из книги Ускоренный С++ по Andrew-koening и Barbara-E

Ответ 6

Что-то, что не меняется внутри блока кода

Ответ 7

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

Ответ 8

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

Ответ 9

Инвариант ADT определяет отношения среди полей данных (переменные экземпляра) это всегда должно быть правдой до и после выполнение любого метода экземпляра.

Ответ 10

Отличный пример инварианта и его значение в книге " Параллелизм Java на практике".

Хотя Java-ориентированный, пример описывает некоторый код, который отвечает за вычисление факторов предоставленного целого числа. Пример кода пытается кэшировать последнее предоставленное число и факторы, которые были рассчитаны для повышения производительности. В этом сценарии есть инвариант, который не был учтен в примере кода, который оставил код чувствительным к условиям гонки в параллельном сценарии.

enter image description here

Ответ 11

Все ответы здесь великолепны, но я чувствовал, что могу пролить больше света на этот вопрос:

Инвариант с языковой точки зрения означает то, что никогда не меняется. Хотя эта концепция на самом деле исходит из математики, она является одним из популярных методов доказательства в сочетании с индукцией.

Вот как идет доказательство: если вы можете найти инвариант, который находится в начальном состоянии, и что этот инвариант сохраняется независимо от какого-либо [юридического] преобразования, примененного к состоянию, то вы можете доказать, что если определенное состояние не имеет этого инвариант, то это никогда не может произойти, независимо от того, какая последовательность преобразований применяется к исходному состоянию.

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

Когда для определения логики цикла используется инвариант, он называется циклическим инвариантом. Его можно использовать вне циклов, но для циклов это действительно важно, потому что у вас часто есть много возможностей или бесконечное количество возможностей.

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

Наконец, хотя теоретически и строго предсказывать программную логику важно только для высококритических приложений, таких как медицинские и военные. Инвариант все еще может использоваться, чтобы помочь типичному программисту при отладке. С его помощью можно узнать, где находится определенное место. Программа потерпела неудачу, поскольку не смогла сохранить определенный инвариант - многие из нас все равно используют его, не задумываясь об этом.