インバリアントとは何ですか?


130

この言葉は多くの文脈で使われているようです。私が理解できる最高のことは、それらが変更できない変数を意味するということです。それは定数/ファイナル(Javaを宣言します!)の目的ではありませんか?


多分彼らはそれを非バリアントと呼ぶべきでしたか?
ジョニー

回答:


189

インバリアントは、変数よりも「概念的」です。一般に、それは常に真であるプログラム状態のプロパティです。不変式が保持されることを保証する関数またはメソッドは、不変式を維持すると言われています。

たとえば、二分探索木には、すべてのノードについて、ノードの左の子のキーがノード自体のキーよりも小さいという不変式がある場合があります。このツリーに対して正しく記述された挿入関数は、その不変を維持します。

あなたが言うことができるように、それはあなたが変数に格納できるものの一種ではありません:それはより多くの文の程度プログラム。プログラムがどのような不変条件を維持する必要があるかを把握し、コードを見直して、それらの不変条件が実際に維持されていることを確認することにより、コードの論理エラーを回避できます。


1
この素晴らしい例は、WikipediaのリンクにCeroの回答が含まれている場合に適しています。
ablarg 2016

2
親の年齢は、生物学的子供の年齢よりも高いです。周囲のコンテキストは変化しますが、不変条件は変化しません。たとえば、2人の子供がいるスミス家である可能性があります。または、哺乳類の他の種に存在する可能性もあります。コンテキストは変わりますが、不変条件は変わりません。
TruthAdjuster 2018年

1
「...常に真であるプログラム状態のプロパティ...」-@jacob baskin-よく書かれていて、これに感謝します。
twknab

「...常に真であるプログラム状態の特性...」-よく書かれていることに同意しますが、誤解を招く可能性があります。最初はブールの真として理解しましたが、「...は常に一定」を意味していると確信しています(しかし、おそらく英語が私の第一言語ではないためと思われます)
dev-null

29

これは、ロジックの特定の場所で常に真であることがわかっている状態であり、デバッグ時にチェックして、問題の原因を突き止めることができます。


17

私は通常、それらをアルゴリズムまたは構造の観点からより多く見ています。

たとえば、アサートできるループ不変式を使用できます。各反復の最初または最後で常にtrueです。つまり、ループがオブジェクトのコレクションをあるスタックから別のスタックに処理することになっている場合、| stack1 | + | stack2 | = cはループの最上部または最下部にあると言えます。

インバリアントチェックが失敗した場合は、何か問題があったことを示しています。この例では、処理済み要素を最終スタックにプッシュするのを忘れているなどの可能性があります。


17

ウィキペディアの魔法:不変(コンピューターサイエンス)

コンピュータサイエンスでは、trueの場合、特定の操作シーケンス全体を通してtrueのままであるという述語は、そのシーケンスに対して(不変)と呼ばれます。


2
リンク?専門用語?読む?WTF?;)真剣に、しかし良いリンクですが、少し要約がいいでしょう。
ダストマン

10

この行が述べるように:

コンピュータサイエンスでは、trueの場合、特定の操作シーケンス全体を通してtrueのままであるという述語は、そのシーケンスに対して(不変)と呼ばれます。

これをよりよく理解するには、C ++のこの例が役立ちます。

いくつかの値を取得し、as countと呼ばれる変数にそれらの合計数を取得し、それらをas と呼ばれる変数に追加する必要があるシナリオを考えます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)

ループ不変:

不変条件は常に Trueでなければなりません。したがって、最初はこれだけでコードを開始します

while(cin>>x){
  }

このループは、標準入力からデータを読み取り、xに格納します。まあ、良い。しかし、不変は、私たちの最初の部分ので偽となり不変が続く(または真の保持)されませんでした。

// we have read count grades so far, and

不変条件を真に保つ方法は?

シンプル!増分カウント。

だから++count;良いでしょう!コードは次のようになります。

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

だが

今でも、不変条件(TRUEでなければならない概念)はFalse です。これは不変条件の2番目の部分を満たさなかったためです。

// sum is the sum of the first count grades

それで、今何をすべきか?

()に追加xsumて保存すると、次回 は新しい値がxに読み込まれます。sumsum+=xcin>>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による書籍Accelerated C ++ から取得および変更されました。



2

それが何であるかに続いて、コードにどの不変条件が存在すべきかを概念的に知ること、目的を達成するためにコードを編成する方法を簡単に決定できるため、不変条件はクリーンなコードを書くのに非常に役立ちます。先に述べたように、不変条件が維持されているかどうかを確認することは、実行しようとしている操作が実際に望んでいることを実際に行っているかどうかを確認するのに適した方法であるため、デバッグにも役立ちます。


2

これは通常、特定の数学演算で変化しない量です。例では、回転下で変化しないスカラー、です。たとえば、磁気共鳴画像では、回転不変量によって組織の特性を特徴付けることが有用です。これは、その推定が理想的にはスキャナー内の身体の向きに依存しないためです。


2

この答えは私の5歳の子供向けです。不変量を定数または固定数値と考えないでください。しかし、それは可能です。しかし、それだけではありません。

むしろ、不変条件は、さまざまなエンティティ間の固定された関係のようなものです。たとえば、あなたの年齢は常にあなたの生物学的両親と比較してそれよりも低くなります。あなたの年齢とあなたの両親の年齢はどちらも時間の経過とともに変化しますが、上記の関係は不変です。

不変条件は、数値定数にすることもできます。たとえば、の値piは、直径に対する円の円周間の不変の比率です。円の大小に関係なく、その比率は常にになりますpi


1

ADTインバリアントは、データフィールド(インスタンス変数)間の関係を指定します。これは、インスタンスメソッドの実行の前後に常にtrueでなければなりません。


0

不変条件の優れた例と、それが重要な理由は、Java Concurrency in Practiceの本にあります

Java中心ですが、この例では、提供された整数の係数の計算を担当するいくつかのコードについて説明しています。サンプルコードは、提供された最後の数値と、パフォーマンスを改善するために計算された要因をキャッシュしようとします。このシナリオでは、コード例で考慮されなかった不変条件があり、コードが並行シナリオで競合状態の影響を受けやすくなっています。

ここに画像の説明を入力してください


0

ここでのすべての答えは素晴らしいですが、私はその問題にもっと光を当てることができると感じました:

言語の観点から不変とは、決して変わらないものを意味します。概念は実際には数学から来ていますが、誘導と組み合わせると、これは人気のある証明手法の1つです。

ここに証明があります。初期状態にある不変式を見つけることができ、この不変式が状態に適用された[法的]変換に関係なく持続する場合、特定の状態にこれがない場合に証明できます。したがって、初期状態に適用される変換のシーケンスに関係なく、不変になることはありません。

これで、以前の考え方(これも帰納法と組み合わせる)により、コンピューターソフトウェアのロジックを述語することが可能になります。実行がループで実行される場合に特に重要です。ループでは、不変条件を使用して、特定のループが特定の結果をもたらすか、またはプログラムの状態を特定の方法で変更しないことを証明できます。

ループロジックを述語するために不変が使用される場合、その呼び出されたループ不変です。ループの外側で使用できますが、多くの可能性や無限の可能性があるため、ループの場合は非常に重要です。

コンピューターソフトウェアのロジックである「述語」という言葉を使用していること、および証明していないことに注意してください。数学では不変量を証明として使用できますが、ソフトウェアを実行すると多くの抽象化の上で実行されるため、コンピュータソフトウェアを実行しても期待どおりの結果が得られるとは証明できないため、証明できません。期待される結果が得られることを確認します(たとえば、ハードウェアの抽象化を考えてください)。

最後に、ソフトウェアロジックを理論的かつ厳密に予測することは、医療や軍事などの重要度の高いアプリケーションでのみ重要です。インバリアントは、デバッグ時に一般的なプログラマを支援するために引き続き使用できます。これは、特定の場所のどこにあるかを知るために使用できます。プログラムは、特定の不変条件を維持できなかったために失敗しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.