これは、問題の別の見方ですの列によって生成されたラティスがあります。Lenstra–Lenstra–Lovász(LLL)アルゴリズムを使用して、このラティスの基底を減らします。をLLLの出力によって形成される新しい行列で置き換える場合、の列は同じラティスを生成しますが、基底ベクトルは互いに直交し、エントリに近くなりますはより小さくなければなりません。MMMM− 1
そこから、各コンポーネントを個別にバインドすることも役立ちます。つまり、番目のコンポーネントをバインドできます。(ちなみに、バインドされたv私| v私|Σdj = 1| ( M− 1)私はj|∥ V ∥∞≤ ∥はM− 1∥は正しくありません。最大ではなく、各行の要素の合計を使用する必要があります。)
約30までの値の場合、LLLアルゴリズムは実質的に即座に終了します。漸近的に、それは取るので、非常に大きな場合は遅くなりますが、同時にチェックする必要があるポイントの数はで指数関数的に増加するため、LLLの実行時間は実際にはボトルネック。一方、チェックが必要なポイントの数を大幅に節約できます。ランダムな規則的(確率的)行列を生成し、以下のコンポーネントの境界を比較するために、GAPコードをいくつか作成しましたdO (d6)ddMv 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チェックポイント)
編集:この問題は、凸状ポリトープの格子点を列挙するという一般的な問題の特殊なケースであり、十分に研究された問題であり、上記のアルゴリズムよりも効率的なアルゴリズムがあります。調査については、このペーパーを参照してください。