ブールラスターがあります。
ラスターの灰色の領域で、特定のサイズのポリゴンを連続した範囲内に収めたいと思います。
基本的に、不規則なポリゴンがあります。可能な限り、不規則なポリゴンの範囲内で既知のポリゴンを「適合」させたいと思います。
多角形の方向は重要ではなく、正方形でもかまいません。グラフィカルにフィットするようにしたいのですが、ポリゴンに数字を付けるだけで(フィットする#)、同様に機能します。
ArcGIS Desktop 10を使用しています。
ブールラスターがあります。
ラスターの灰色の領域で、特定のサイズのポリゴンを連続した範囲内に収めたいと思います。
基本的に、不規則なポリゴンがあります。可能な限り、不規則なポリゴンの範囲内で既知のポリゴンを「適合」させたいと思います。
多角形の方向は重要ではなく、正方形でもかまいません。グラフィカルにフィットするようにしたいのですが、ポリゴンに数字を付けるだけで(フィットする#)、同様に機能します。
ArcGIS Desktop 10を使用しています。
回答:
この問題に取り組むには多くの方法があります。 データのラスター形式は、ラスターベースのアプローチを示唆しています。これらのアプローチを検討する際、2進整数線形プログラムとしての問題の定式化は有望に見えます。これは、多くのGISサイト選択分析の精神に非常に合致しており、それらに容易に適応できるためです。
この定式化では、塗りつぶしポリゴンのすべての可能な位置と方向を列挙します。これを「タイル」と呼びます。各タイルに関連付けられているのは、その「良さ」の尺度です。目的は、全体の良さが可能な限り大きい非重複タイルのコレクションを見つけることです。ここでは、各タイルの長所をカバーする領域とすることができます。(よりデータが豊富で洗練された決定環境では、各タイルに含まれるセルのプロパティ、おそらく可視性に関連するプロパティ、他のものへの近接性などの組み合わせとして、良さを計算している可能性があります。)
この問題に対する制約は、ソリューション内の2つのタイルが重ならないことです。
これは、多角形のセル(「領域」)1、2、...、Mを列挙することにより、効率的に計算できるように、もう少し抽象的にフレーム化できます。タイルの配置は、0と1のインジケーターベクトルでエンコードすることができ、1をタイルで覆われたセルと他の場所の0に対応させます。このエンコーディングでは、タイルのコレクションに必要なすべての情報は、それらのインジケーターベクトル(通常はコンポーネントごと)を合計することで見つけることができます:合計は、少なくとも1つのタイルがセルをカバーし、合計が大きくなるゼロ以外の値になります2つ以上のタイルが重なる場所はどこでもありません。(合計は、重複の量を効果的にカウントします。)
もう1つの小さな抽象化:考えられるタイル配置のセット自体を列挙できます(1、2、...、Nなど)。タイル配置のセット自体の選択は、配置するタイルを指定するインジケーターベクトルに対応します。
ここにアイデアを修正するための小さなイラストがあります。計算の実行に使用されるMathematicaコードが付随しているため、プログラミングの難しさ(またはその欠如)が明らかになります。
まず、タイル化する領域を示します。
region = {{0, 0, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};
セルを左から右へ、上から順に番号付けすると、領域のインジケーターベクトルには16個のエントリがあります。
Flatten[region]
{0、0、1、1、1、1、1、1、1、1、1、1、1、1、1、1、1}
90度の倍数のすべての回転とともに、次のタイルを使用してみましょう。
tileSet = {{{1, 1}, {1, 0}}};
回転(および反射)を生成するコード:
apply[s_List, alpha] := Reverse /@ s;
apply[s_List, beta] := Transpose[s];
apply[s_List, g_List] := Fold[apply, s, g];
group = FoldList[Append, {}, Riffle[ConstantArray[alpha, 4], beta]];
tiles = Union[Flatten[Outer[apply[#1, #2] &, tileSet, group, 1], 1]];
(このやや不透明な計算は、 /math//a/159159のます。これは、タイルの可能なすべての回転と反射を生成し、重複する結果を削除することを示しています。)
ここに示すようにタイルを配置するとします。
セル3、6、および7は、この配置でカバーされています。それは指標ベクトルによって指定されます
{0、0、1、0、0、1、1、0、0、0、0、0、0、0、0、0、0}
このタイルを1列右にシフトすると、そのインジケーターベクトルは代わりに
{0、0、0、1、0、0、1、1、0、0、0、0、0、0、0、0、0}
両方にタイルを配置しようとする組み合わせこれらのの位置に同時に、これらのインジケータの合計によって決まります。
{0、0、1、1、0、1、2、1、0、0、0、0、0、0、0、0、0}
7番目の位置の2は、1つのセルでこれらのオーバーラップを示しています(下から2行目、左から3列目)。重複したくないので、、有効なソリューションのベクトルの合計に1を超えるエントリが含まれないようにする必要があります。
この問題では、タイルの方向と位置の29の組み合わせが可能です。(これは徹底的な検索を含む簡単なコーディングで発見されました。)29の可能性すべてを、列ベクトルとしてインジケーターを描画することで表現できます。(行の代わりに列を使用するのが一般的です。)結果の配列の画像を次に示します。これは16行(長方形の各セルに1行)と29列になります。
makeAllTiles[tile_, {n_Integer, m_Integer}] :=
With[{ m0 = Length[tile], n0 = Length[First[tile]]},
Flatten[
Table[ArrayPad[tile, {{i, m - m0 - i}, {j, n - n0 - j}}], {i, 0, m - m0}, {j, 0, n - n0}], 1]];
allTiles = Flatten[ParallelMap[makeAllTiles[#, ImageDimensions[regionImage]] & , tiles], 1];
allTiles = Parallelize[
Select[allTiles, (regionVector . Flatten[#]) >= (Plus @@ (Flatten[#])) &]];
options = Transpose[Flatten /@ allTiles];
(前の2つのインジケーターベクトルは、左の最初の2列として表示されます。)鋭い目をした読者は、並列処理のいくつかの機会に気付いたかもしれません。これらの計算には数秒かかることがあります。
前述のすべては、マトリックス表記を使用してコンパクトに言い換えることができます。
Fは、M行N列のこのオプションの配列です。
Xは、長さNの一連のタイル配置のインジケータです。
bは1のNベクトルです。
Rは地域の指標です。それはMの -ベクトル。
FXはXでカバーされるセルのインジケーターであり、Rの積はこれらの値を合計するため、考えられるソリューションXに関連付けられた合計「良さ」はRFXに等しくなります。(ソリューションが地域内の特定の領域を優先または回避することを希望する場合、Rに重みを付けることができます。) これは最大化されます。 (RF)と書くことができるからです。Xは、それがある線形の関数X:これは重要です。(以下のコードでは、変数にRFが含まれています。)c
制約があること
Xのすべての要素は非負でなければなりません。
Xのすべての要素は1(bの対応するエントリ)未満でなければなりません。
Xのすべての要素は整数でなければなりません。
制約(1)と(2)はこれを線形プログラムにしますが、3番目の要件はこれを整数線形プログラムに変えます。
まさにこの形式で表現された整数線形プログラムを解くための多くのパッケージが存在します。MおよびNの値を数十または数十万にまで処理できます。実際のアプリケーションでは、おそらくこれで十分です。
最初の例として、Mathematica 8のLinearProgramming
コマンドを使用して前の例の解を計算しました。(これがします最小限に抑える。線形目的関数を最小化が容易に目的関数を否定することで最大化になっている。)それは0.011秒で(タイルとその位置のリストとして)ソリューションを返しました:
b = ConstantArray[-1, Length[options]];
c = -Flatten[region].options;
lu = ConstantArray[{0, 1}, Length[First[options]]];
x = LinearProgramming[c, -options, b, lu, Integers, Tolerance -> 0.05];
If[! ListQ[x] || Max[options.x] > 1, x = {}];
solution = allTiles[[Select[x Range[Length[x]], # > 0 &]]];
灰色のセルは領域にまったくありません。白血球はこの溶液で覆われていませんでした。
これと同じくらい良い他の多くのタイルを(手で)解決できますが、より良いタイルを見つけることはできません。これは、このアプローチの潜在的な制限です。複数のソリューションがある場合でも、1つの最適なソリューションを提供します。(いくつかの回避策があります:Xの列を並べ替える場合と、問題は変わりませんが、ソフトウェアは結果として異なるソリューションを選択することがよくあります。ただし、この動作は予測できません。)
2番目の図として、より現実的にするために、問題の地域を考えてみましょう。画像をインポートしてリサンプリングすることで、69 x 81のグリッドで表現しました。
領域は、このグリッドの2156個のセルで構成されています。
物事を面白くし、線形計画法の一般性を説明するために、この領域を可能な限り2種類の長方形でカバーしてみましょう。
1つは17 x 9(153セル)で、もう1つは15 x 11(165セル)です。2番目のほうが大きいので、2番目のほうを使用することをお勧めしますが、最初のほうがより細く、狭い場所に収まります。どれどれ!
このプログラムには、N = 5589のタイル配置が含まれます。かなり大きい!6.3秒の計算の後、Mathematicaはこの10タイルのソリューションを思い付きました。
いくつかのたるみがあるため(たとえば、左下のタイルを最大で4列左にシフトできます)、明らかにこれとは少し異なる他のソリューションがいくつかあります。
多角形のパッキングのための遺伝的アルゴリズムについてへのリンクは、最小間隔で制約エリア内に最大数のポイントを配置するアルゴリズムを探すでの同様の質問への私の答えで提供されていますか?、役に立つかもしれません。メソッドは、長方形だけでなく、任意のコンテナ形状で機能するように一般化できるようです。
あなたが言及した高度に制約されたサブセット(ポットホール内の正方形/三角形のタイル)について、上記の明示的な最適化を仮定すると、この疑似コードは、高解像度で問題をブルートフォースする可能性を単に通して、おおよその答えに到達するはずです。長方形のタイルや非常に不規則なコンテナーなど、個々のタイルの回転がゲインを見ることができる状況では、正しく機能しません。これは100万回の反復であり、必要に応じてさらに試行できます。
長さLの辺を持つ正方形を仮定します
少なくともコンテナの範囲の寸法に加えて、各方向に少なくとも1Lの正方形の市松模様を作成します。
N = 0
DX = 0
DY = 0
DR = 0
チェッカーボードの位置を元の重心にリセット
(R = 1:100)
(Y = 1:100)
(X = 1:100)
M =コンテナ内の正方形の数を完全に数える
If(M> N)
DR = R
DY = Y
DX = X
N = M
チェッカーボードをL / 100だけ東に移動する
チェッカーボードの東をリセット
チェッカーボードをL / 100だけ北に移動する
チェッカーボードの北をリセット
チェッカーボードをその重心を中心にCW 3.6度回転させます
DY = DY * L
DX = DX * L
チェッカーボードを元の位置と回転にリセット
印刷DR& "、"&DX& "、および"&DY& "は最終的な変換/回転マトリックスです
DRによるチェッカーボードの回転
DX、DYによるチェッカーボードの翻訳
完全にコンテナ内にある正方形を選択します
正方形をエクスポート