🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

3625閲覧

長方形に円の詰め込み最適化について

KAZENOMACHI

総合スコア12

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/03/23 23:46

編集2021/03/24 00:30

前提・実現したいこと

過去にいくつかの質問があるようですが、解決までに至りません。
やりたいことは、以下の図9です。
http://www.orsj.or.jp/archive2/or63-12/or63_12_762.pdf
そのための前哨戦として以下の最適化問題をやろうとしています。線形ではなく、非線形でないと,,,,という話もありますが、

発生している問題・エラーメッセージ

エラーメッセージ

該当のソースコード

from

1m = LpProblem(sense=LpMinimize) 2import matplotlib.pyplot as plt 3import numpy as np 4 5#n:並べたい円の数,r:半径,W:横幅,UB高さ 6n=15 7r=0.2 8W=2.2 9UB=2.6 10 11x=[LpVariable('x%d' %i, lowBound=0) for i in range(n)] 12y=[LpVariable('y%d' %j, lowBound=0) for j in range(n)] 13 14u=[[LpVariable('u%d_%d' %(i,j),cat=LpBinary) for j in range(n)] for i in range(n)] 15v=[[LpVariable('v%d_%d' %(i,j),cat=LpBinary) for j in range(n)] for i in range(n)] 16 17H=LpVariable('H') 18 19#モデルプロジェクトm 20m += H 21for i in range(n): 22 for j in range(n): 23 m += x[i]+r*2 <= x[j]+W*(1-u[i][j]) 24 m += y[i]+r*2 <= y[j]+UB*(1-v[i][j]) 25 if i < j: 26 m += u[i][j]+u[j][i]+v[i][j]+v[j][i] >= 1 27 28for i in range(n): 29 m += x[i] <= W-r*2 30 m += y[i] <= H-r*2 31 m += r <= x[i] 32 m += r <= y[i] 33 34m.solve() 35 36# 37#for i in range(n): 38# print("x[i] value:", x[i].value()) 39# print("y[i] value:", y[i].value()) 40 41 42#描写 43fig = plt.figure() 44ax = fig.add_subplot(111,aspect='equal') 45ax.set_xlim([0,W]) 46ax.set_ylim([0,UB]) 47 48for i in range(n): 49 circle_n = plt.Circle((x[i].value(),y[i].value()),r) 50 ax.add_patch(circle_n) 51 52#グラフのタイトル 53plt.title("Sectional View") 54 55#x軸ラベル 56plt.xlabel("Hole diameter") 57 58#y軸ラベル 59plt.ylabel("depth") 60 61fig.savefig("test1.png") 62コード

試したこと

円の作画は中心点の設定、長方形のゼロ点は左下であるので、r*2で半径ではなく直径で円が重ならないようにしています。
この結果は、以下のようになります。ところが、n=15とするとプログラムが終了しません。5列3段になると思っているのですが(最終的には半径の異なる円を最適に詰め込みたいのですが)。
イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2021/03/24 00:14

このままではコードが読めないので、質問を編集し、<code>ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください
guest

回答1

0

ベストアンサー

過去の類似質問に回答していた者です。
https://teratail.com/questions/328071#reply-454147
https://teratail.com/questions/328308#reply-454344

・n=15とするとプログラムが終了しないのは、単に計算時間が掛かっているだけだと思われます。
・以下、回答例を提示します。円の重複判定には上下左右の関係しか見ていないため、隙間が生まれます。

python

1from pulp import * 2import matplotlib.pyplot as plt 3 4W = 20 5UB = 30 6 7n = 6 8r = [1, 2, 3, 4, 5, 6] 9 10H = LpVariable("H") 11x = [LpVariable(f'x{i}', lowBound=0) for i in range(n)] 12y = [LpVariable(f'y{i}', lowBound=0) for i in range(n)] 13u = [[LpVariable(f'u{i}{j}', cat=LpBinary) for j in range(n)] for i in range(n)] 14v = [[LpVariable(f'v{i}{j}', cat=LpBinary) for j in range(n)] for i in range(n)] 15 16m = LpProblem(sense=LpMinimize) 17m += H 18 19for i in range(n): 20 for j in range(n): 21 m += x[i] + r[i] <= x[j] - r[j] + W * (1 - u[i][j]) 22 m += y[i] + r[i] <= y[j] - r[j] + UB * (1 - v[i][j]) 23 if i < j: 24 m += u[i][j] + u[j][i] + v[i][j] + v[j][i] >= 1 25 26for i in range(n): 27 m += x[i] <= W - r[i] 28 m += y[i] <= H - r[i] 29 m += r[i] <= x[i] 30 m += r[i] <= y[i] 31 32m.solve() 33 34### 描画 ### 35 36fig = plt.figure() 37ax = fig.add_subplot(111,aspect='equal') 38ax.set_xlim([0,W]) 39ax.set_ylim([0,UB]) 40 41for i in range(n): 42 print(f'(x, y) = ({x[i].value()}, {y[i].value()}) r = {r[i]}') 43 circ = plt.Circle((x[i].value() ,y[i].value()), r[i]) 44 ax.add_patch(circ) 45 46plt.show() 47
(x, y) = (7.0, 21.0) r = 1 (x, y) = (2.0, 18.0) r = 2 (x, y) = (3.0, 13.0) r = 3 (x, y) = (16.0, 4.0) r = 4 (x, y) = (5.0, 5.0) r = 5 (x, y) = (14.0, 16.0) r = 6

出力画像

--- 追記(コメントへの回答) ---

枠で囲んでみると、これ以上Hを最小化できないことがわかる。
枠追加

投稿2021/03/24 01:31

編集2021/03/24 03:00
nanoseeing

総合スコア133

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KAZENOMACHI

2021/03/24 02:27

ありがとうございました。rをすべて2にして、n=10にすると、なかなか終了しません。n=7までは同じくらいの速度で終了するのですが。また、重複は上下で判定していますが、r=1は一番下でも配置できそうですし、r=6はもう少し下でも配置できそうですが、、、。完全に詰め込むことはできるのでしょうか?また、0.1の余裕を持たせ詰め込むことはできるのでしょうか?
nanoseeing

2021/03/24 02:59

>> rをすべて2にして、n=10にすると、なかなか終了しません。 計算が終了するまで待つしかありません。 >> r=1は一番下でも配置できそうですし、r=6はもう少し下でも配置できそう。 回答欄に円を枠で囲った画像を追記しました。Hは最小化されています。 >> 0.1の余裕を持たせ詰め込むことはできるのでしょうか? 元の半径から0.05を足せば良いと思います。
KAZENOMACHI

2021/03/24 03:58

参考にしたpdfのように正方形の枠線での詰込み配置ではなく、円周の重複を避けた詰込みができると思ったのですが、そういう意味ではなかったのですね。これは長方形の断面積を計算して、円の断面積を最大にして、かつ、Hを最小にするような最適化にするとよいのでしょうか?
KAZENOMACHI

2021/03/24 04:05

n = 16 r = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] にしても、同じ円が5列x3段+1個になると思ったのですが、以下のエラーとなります。どうしてなのか?正方形の枠でも十分に入ると思うのですが。 File "C:\Users\05896\Desktop\ダクト配列NEW.py", line 34, in <module> m.solve() File "C:\Users\05896\Anaconda3\lib\site-packages\pulp\pulp.py", line 1737, in solve status = solver.actualSolve(self, **kwargs) File "C:\Users\05896\Anaconda3\lib\site-packages\pulp\apis\coin_api.py", line 101, in actualSolve return self.solve_CBC(lp, **kwargs) File "C:\Users\05896\Anaconda3\lib\site-packages\pulp\apis\coin_api.py", line 159, in solve_CBC raise PulpSolverError("Pulp: Error while executing "+self.path) PulpSolverError: Pulp: Error while executing C:\Users\05896\Anaconda3\lib\site-packages\pulp\apis..\solverdir\cbc\win\64\cbc.exe
nanoseeing

2021/03/24 06:00

>> n = 16でエラーが起きる 変数名の重複が原因のようです。u{i}_{j} のように変数名を変更してください。 https://ja.stackoverflow.com/questions/55563/pulp%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6 >> 参考にしたpdfのように正方形の枠線での詰込み配置ではなく、円周の重複を避けた詰込みができると思ったのですが、そういう意味ではなかったのですね。 そのとおりです。結局のところ、正方形の詰込み問題を解いているに過ぎません。 >> これは長方形の断面積を計算して、円の断面積を最大にして、かつ、Hを最小にするような最適化にするとよいのでしょうか? 断面積が何を指すのかわかりませんが、いずれにしろ線形計画問題に落とし込めないと、pulpライブラリでは解けないかと思います。 私の思いついた解法としては、以下があります。 A. 非線形計画問題に対応したソルバーを使用する。 B. 円を正多角形で近似して、線形計画問題に落とし込む。厳密解は得られない。 C. 参考pdfのように、BL法による貪欲的な探索をする。厳密解は得られない。 私自身は数理最適化に詳しいわけではないので、参考までに。
KAZENOMACHI

2021/03/24 23:06

確かに正方形を詰め込んだことと同じですね。正方形の面積:その中にはいる円の面積は78.5%なので、余裕率として21.5%は見ておくという考えをすると実運用ではいいのかもしれませんが、ぎりぎりまで詰め込みたいときの可能性を知りたい場合には、使えませんね。非常に勉強になりました。もう一度、数理最適化から調べて再挑戦したいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問