web-dev-qa-db-ja.com

インバリアントとは何ですか?それらはどのように使用できますか?プログラムで使用したことがありますか?

私はCoders at Workを読んでいますが、その中に不変条件についての多くの話があります。私が理解している限り、不変式は式の前と後の両方に成立する条件です。それらは、とりわけ、私のLogicコースを正しく覚えていれば、ループが正しいことを証明するのに役立ちます。

私の説明は正しいですか、それとも見逃していませんか?プログラムでそれらを使用したことがありますか?もしそうなら、彼らはどのように利益を得ましたか?

54
gablin

OOPでは、不変量は、プログラムが有効になるためにオブジェクトの存続期間中常に真でなければならない一連のアサーションです。オブジェクトが現在その状態を変更するメソッドを実行していないときはいつでも、コンストラクタの最後からデストラクタの最初までこの条件を満たしている必要があります。

不変の例としては、2つのメンバー変数の1つだけをnullにする必要があります。または、一方に特定の値がある場合、もう一方に許可される値のセットはこれまたはそれです...

オブジェクトのメンバー関数を使用して、不変条件が成立することを確認することがあります。そうでない場合、アサートが発生します。そして、メソッドは、オブジェクトを変更する各メソッドの開始時と終了時に呼び出されます(C++では、これは1行だけです...)

47
Xavier Nodet

さて、このスレッドで私が目にするものはすべて素晴らしいですが、私は仕事で非常に役立つ「不変条件」の定義を持っています。

不変条件とは、プログラムの実行全体を通じて従わなければならない、人間には伝達できるがコンパイラには伝達できない論理規則です。

この定義は、条件を2つのグループに分けるので役立ちます。コンパイラーは強制的に信頼できるものと、バグを導入せずにコードベースと対話するために文書化、議論、コメント、またはその他の方法で投稿者に通知する必要があるものです。 。

また、この定義は、「不変条件が悪い」という一般化を使用できるので役立ちます。

例として、マニュアルトランスミッション車のシフターは、不変条件を回避するように設計されています。必要に応じて、ギアごとに1つのレバーを備えたトランスミッションを構築できます。このレバーは、前方(「係合」)または後方(「非係合」)にすることができます。そのようなシステムでは、「不変条件」を作成しました。

「別のギアを使用する前に、現在使用しているギアを外すことが重要です。同時に2つのギアを使用すると、機械的ストレスが発生し、トランスミッションが切り離されます。別のギアを使用する前に、現在使用しているギアを必ず外してください。」

そして、だらしない運転で壊れたトランスミッションを非難するかもしれません。しかし、現代の車はギア間を回転する1本のスティックを使用しています。現代のスティックシフトカーでは、2つのギアを同時に入れることができないように設計されています。

このように、トランスミッションは「不変条件を削除する」ように設計されていると言えます。これは、トランスミッション自体が論理的なルールに違反する方法で機械的に構成されないためです。

コードから削除するこの種のすべての不変条件は、コードを操作する認知的負荷を軽減するため、改善されます。

15
Daniel Burbank

Coders At Workからの次の引用に基づいて...

しかし、それが維持している不変式を知ったら、ああ、その不変式を維持していると、ログのルックアップ時間を取得できることがわかります。

...「不変」=「希望の効果を確実にするために維持したい条件」だと思います。

インバリアントには微妙に異なる2つの感覚があるようです。

  1. 変わらないもの。
  2. 目標Xを達成するために同じことを維持しようとしているもの(上記の「ログ検索時間」など)。

つまり、1はアサーションのようなものです。 2は、正確さ、パフォーマンス、その他の特性を証明するツールのようなものだと思います。 2の例については Wikipediaの記事 を参照してください(MUパズルの解の正確性を証明します)。

実際、不変の3番目の意味は次のとおりです。

.3。プログラム(またはモジュールまたは関数)が行うことになっていること。つまり、その目的です。

同じCodes At Workインタビューから:

しかし、大きなソフトウェアを管理しやすくするのは、それが何をすべきか、何が真実であると想定されているかについて、いくつかのグローバルな不変条件または全体像を示すことです。

3
Jonathan Aquino

(一般的な意味での)不変とは、ある時点で、またはプログラムの実行中に常に真でなければならないいくつかの条件を意味します。例えばPreConditionsとPostConditionsを使用して、関数が呼び出されたときと関数が戻ったときに真でなければならないいくつかの条件を表明できます。オブジェクトの不変条件を使用すると、オブジェクトが存在している間、オブジェクトが有効な状態でなければならないことを表明できます。契約原理による設計です。
コードのチェックを使用して、不変条件を非公式に使用しました。しかし、最近では、不変式を直接サポートするコード 。Netの契約ライブラリ で遊んでいます。

3
softveda

インバリアントは、プログラムのロジックを決定するために使用できるルールまたは仮定のようなものです。

たとえば、ユーザーアカウントを追跡するソフトウェアアプリケーションがあるとします。また、ユーザーが複数のアカウントを持つことができると仮定しますが、何らかの理由でユーザーのメインアカウントと「エイリアス」アカウントを区別する必要があります。

これはDBレコードまたはその他の可能性がありますが、ここでは各ユーザーアカウントがクラスオブジェクトで表されていると仮定します。

class userAccount {private char * pUserName;プライベート文字* pParentAccountUserName;

...}

不変条件は、pParentAccountUserNameがNULLまたは空の場合、このオブジェクトが親アカウントであるという仮定です。この不変条件を使用して、さまざまなタイプのアカウントを区別できます。おそらく異なるタイプのユーザーアカウントを区別するためのより優れた方法があると考えられるため、これは不変条件の使用方法を示すための例にすぎないことに注意してください。

1
Pemdas

物理学の背景から来て、物理学には不変量があります。不変量は、基本的に、計算/シミュレーション全体を通じて変化しない量です。たとえば、物理学では、閉じたシステムの場合、総エネルギーが節約されます。また、物理学では、2つの粒子が衝突した場合、結果のフラグメントには、開始時のエネルギーと正確に同じ運動量(ベクトル量)が含まれている必要があります。通常、結果を完全に指定するのに十分な不変条件はありません。たとえば、2粒子衝突では、4つの不変量、3つの運動量成分、エネルギー成分がありますが、システムには6つの自由度があります(その状態を説明する6つの数値)。不変条件は丸め誤差内で保存されるべきですが、それらの保存は解が正しいことを証明しません。

したがって、通常、これらの事項はサニティチェックとして重要ですが、それだけでは正しさを証明できません。

1
Omega Centauri