2

背景情報:

私のプロジェクトでは、マリオ ドメインに強化学習 (RL) を適用しています。状態の表現には、カスタム オブジェクトをキーとして持つハッシュテーブルを使用することにしました。私のカスタム オブジェクトは不変で、(IntelliJ IDE によって生成された) .equals() と .hashcode() を上書きしました。

これは結果の .hashcode() です。追加情報としてコメントに可能な値を追加しました。

@Override
public int hashCode() {
    int result = (stuck ? 1 : 0);                // 2 possible values: 0, 1
    result = 31 * result + (facing ? 1 : 0);     // 2 possible values: 0, 1 
    result = 31 * result + marioMode;            // 3 possible values: 0, 1, 2
    result = 31 * result + (onGround ? 1 : 0);   // 2 possible values: 0, 1 
    result = 31 * result + (canJump ? 1 : 0);    // 2 possible values: 0, 1 
    result = 31 * result + (wallNear ? 1 : 0);   // 2 possible values: 0, 1 
    result = 31 * result + nearestEnemyX;        // 33 possible values: - 16 to 16
    result = 31 * result + nearestEnemyY;        // 33 possible values: - 16 to 16

    return result;
}

問題:

ここでの問題は、上記のコードの結果が を超える可能性があることInteger.MAX_VALUEです。これは問題である必要はないことをオンラインで読みましたが、私の場合はそうです。これは、Q ラーニング (RL メソッド) であるアルゴリズムが使用されているためであり、ハッシュテーブル内に格納されている正しい Q 値に依存しています。基本的に、値を取得するときに競合することはできません。実験を実行すると、結果がまったく良くないことがわかり、問題がハッシュテーブルからの Q 値の取得にあることは 95% 確信しています。(必要に応じて、これについて確信がある理由を詳しく説明できますが、これには、質問に関係のないプロジェクトに関する追加情報が必要です。)

質問:

整数オーバーフローを回避する方法はありますか?ここで何かを見落としている可能性がありますか? または、カスタムキーを指定して値を合理的に高速に取得する別の方法 (おそらく別のデータ構造) はありますか?

述べる:

いくつかのコメントを読んだ後、衝突を引き起こさない一意のキーが必要なため、HashTable を使用するための私の選択はおそらく最良のものではないことに気付きました。それでも HashTable を使用したい場合は、適切なエンコーディングが必要になるでしょう。

4

4 に答える 4

2

をマジック ナンバーとして使用する代わりに31、可能性の数 (0 に正規化) を使用する必要があります。

@Override
public int hashCode() {
    int result = (stuck ? 1 : 0);                // 2 possible values: 0, 1
    result = 2 * result + (facing ? 1 : 0);      // 2 possible values: 0, 1 
    result = 3 * result + marioMode;             // 3 possible values: 0, 1, 2
    result = 2 * result + (onGround ? 1 : 0);    // 2 possible values: 0, 1 
    result = 2 * result + (canJump ? 1 : 0);     // 2 possible values: 0, 1 
    result = 2 * result + (wallNear ? 1 : 0);    // 2 possible values: 0, 1 
    result = 33 * result + (16 + nearestEnemyX); // 33 possible values: - 16 to 16
    result = 33 * result + (16 + nearestEnemyY); // 33 possible values: - 16 to 16

    return result;
}

これにより、104544 の可能性のある hashCodes() が得られます。ところで、このプロセスを逆にして、一連の/およびを使用してコードから元の値を取得できます。%

于 2014-05-13T14:48:19.470 に答える
-1

Guava のhashCode()方法または JDK7 のObjects.hash(). 自分で書くよりずっといいです。自分でコードを繰り返さないでください (すぐに使えるソリューションを使用できる場合は他の人も):

于 2014-05-13T14:29:39.570 に答える