ハイパーキューブ内のすべてのグリッドポイントをアルゴリズム的に生成する


8

問題は計算数学から直接生じ、次のように述べた:

正則行列所与の、すべてのベクトルが効果的に見つけるよう、\ N {MVは}の最大成分であります係数のベクトル。MRd×dvZdMv1Mv

以下にアルゴリズムを示しますが、グリッドポイントの数よりもはるかに多くのステップがあるため、非常に非効率的です。私の場合はd = 5でも耐えられd=5ますが、d=6では完全に失敗します。時間はあまりありません。また、高次元にも対応したいです。


私の現在のアルゴリズムは以下に基づいています(免責事項:より多くの数学が含まれています):最初に、\ n {M ^ {-1}}を計算しM1ます。次に、\ n {v} \ leq \ n {M ^ {-1}} \ n {Mv} \ leq \ n {M ^ {-1}}が観察されvM1MvM1ます。つまり、L=M1を計算してから、すべてのベクトルv \ in \ lbrace-L、-L + 1、\ dots、L-1、L \を試すことができます。} ^ dv{LL+1L1L}d ; ちょうど2L+1dあります。(そしてここに問題があります:d=6およびL=18場合、2.5E9回の反復が得られます。これは、私が存在すると思う点の数よりも桁違いに大きいです。)


1
問題を整数線形プログラムとして定式化し、解を数えることを検討しましたか?これを行うためにIPソルバー(CPLEXなど)で利用できる方法はあると思いますが、実際にどれほど高速かわかりません。そのための1つの方法は、Barvinokのアルゴリズムとして知られています。
Corneliusブランド、

@C。ブランドありがとうございます。詳しく調べます(ただし、LP / IPを最後に見たのは久しぶりです)。たまたま、これがSageMathにあるかどうかはわかりましたか?
yo '

あなたの懸念に関しては、問題の元の定式化はすでに(ほぼ)整数プログラムです。注意すべき唯一のことは、(非線形) -normの使用です。しかし、IPソリューションをカウントするアルゴリズムがSageMathで使用できるかどうかはわかりません。
Corneliusブランド

回答:


3

これは、問題の別の見方ですの列によって生成されたラティスがあります。Lenstra–Lenstra–Lovász(LLL)アルゴリズムを使用して、このラティスの基底を減らします。をLLLの出力によって形成される新しい行列で置き換える場合、の列は同じラティスを生成しますが、基底ベクトルは互いに直交し、エントリに近くなりますはより小さくなければなりません。MMMM1

そこから、各コンポーネントを個別にバインドすることも役立ちます。つまり、番目のコンポーネントをバインドできます。(ちなみに、バインドされたv|v|Σj=1d|M1j|vM1は正しくありません。最大ではなく、各行の要素の合計を使用する必要があります。)

約30までの値の場合、LLLアルゴリズムは実質的に即座に終了します。漸近的に、それは取るので、非常に大きな場合は遅くなりますが、同時にチェックする必要があるポイントの数はで指数関数的に増加するため、LLLの実行時間は実際にはボトルネック。一方、チェックが必要なポイントの数を大幅に節約できます。ランダムな規則的(確率的)行列を生成し、以下のコンポーネントの境界を比較するために、GAPコードをいくつか作成しましたdOd6ddMv LLL-reduced基底と比較して、元の基底を使用して取得します(ちなみに、行列が規則的であると想定する必要はありません。この制限を適用したのは、これがアプリケーションに当てはまったためです)。

d:= 8;
M:= IdentityMat(d);
[1..d]のiの場合
  [1..d]のjに対して
    M [i] [j]:=ランダム([-10 ^ 8..10 ^ 8]);
  od;
  M [i]:= M [i] / Sum(M [i]);
od;
L:= LLLReducedBasis(M).basis;
MM:= M ^ -1 * 1.0;
LL:= L ^ -1 * 1.0;
[1..d]のiの場合
  [1..d]のjに対して
    MM [i] [j]:= MM [i] [j] * SignFloat(MM [i] [j]);
    LL [i] [j]:= LL [i] [j] * SignFloat(LL [i] [j]);
  od;
od;

Print( "元のベースの境界:");
ones:= [1..d] * 0 + 1;
v:= MM * ones;
[1..d]のiの場合
  v [i]:= Int(Floor(v [i]));
  Print(v [i]);
  Print( "");
od;
Print( "\ n(");
Print(Product(v * 2 + 1));
Print( "チェックするポイント)\ n");

Print( "LLLベースの境界:");
v:= LL * ones;
[1..d]のiの場合
  v [i]:= Int(Floor(v [i]));
  Print(v [i]);
  Print( "");
od;
Print( "\ n(");
Print(Product(v * 2 + 1));
Print( "チェックするポイント)\ n");

次の出力(デフォルトのランダムシードに基づく、)は、異常ではありません。d=8

元の基準の境界:9 23 24 4 23 16 23 4 
(258370076349チェックポイント)
LLLベースの境界:3 3 2 2 3 4 2 3 
(2701125チェックポイント)

編集:この問題は、凸状ポリトープの格子点を列挙するという一般的な問題の特殊なケースであり、十分に研究された問題であり、上記のアルゴリズムよりも効率的なアルゴリズムがあります。調査については、このペーパーを参照してください。


最初にグリッドの良いベースを取得することを考えましたが、高次元でどれほど効率的かわかりませんか?(注:完全に回避できたので、この問題は現在私には興味深いものではありませんが、この質問には引き続き注意
yo '

LLLの効率に関するいくつかの情報と、サンプルコードおよび出力を使用して、さらに回答を追加しました。
ブレントカービー2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.