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

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

詳細はこちら
Matplotlib

MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

Python

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

Q&A

解決済

1回答

3144閲覧

Pythonによる円(2次元)の詰め込み問題

yoshih

総合スコア5

Matplotlib

MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

Python

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

0グッド

0クリップ

投稿2021/03/17 03:18

前提・実現したいこと

pythonのmatpoltlibを用いて、容器の中に円をしたから詰め込み、高さが最も低くなるように詰め込んでいきたいと考えております。

プログラムはエラーが起こらずにコンパイルできましたが、円の数を変更しても1つしか出力されずに困っております。
また、その円も下から詰め込まれずに宙に浮いております。
何かアドバイスを頂けると助かります。
イメージ説明

下記の文献を参考に取り組んでおります。
http://www.orsj.or.jp/archive2/or63-12/or63_12_762.pd

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

エラーメッセージはでません。

エラーメッセージ

該当のソースコード

Python

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

試したこと

パラメーターを少しずつ変更しながら原因を探しておりますが、まだわかっておりません。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答1

0

ベストアンサー

原因がわからない場合は、printを使ったデバッグを覚えましょう。

円が1つしか表示されない → 座標(x,y)や半径rがおかしいのでは?
と考え、x,y,rなどの変数を表示してみましょう。

下記のようにprintを追記してみました。

python

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

出力結果

x : [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9] x type : <class 'list'> x[0] : x0 x[0] type : <class 'pulp.pulp.LpVariable'> x[0] value: None

これを見れば、xはリストで、
xの中身は「LpVariable」であることがわかります。

また、value()を使ってxの中身を取り出すと、
「None」になってしまっていることがわかります。

なぜ、「None」になっているか考えれば、
m.solve()を書き忘れていることにも気付けるはずです。

投稿2021/03/17 04:03

nanoseeing

総合スコア133

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

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

yoshih

2021/03/17 06:47

printでデバックするテクニックは非常に勉強になりました。 数式を解き終わったと宣言してあげないといけないという理解でよろしいでしょうか。 また、m.solve()を追加してみましたが変わらず1つしか円が生成されませんでした。 forの変数が間違っているのでしょうか。 お忙しいところ恐縮ですが何卒宜しくお願い致します。
nanoseeing

2021/03/17 07:57

m.solve()を実行することで、制約条件に従って問題を解いてくれます。 forの変数が間違っているかというご質問に関しては、その通りなのですが、ご自身で確認してみましたか? forの文の中でx、yをprintしてみて想定どおりの数値になっているか確認してみてください。 いきなり複雑な問題に挑戦するのは難しいです。とりあえず、シンプルな問題を考え、想定どおりの答えになっているか確認してみてください。 例えば、幅が2の長方形に、半径1の円を2つ、詰め込むことを考えます。答えは、中心座標が(1, 1)と(1, 3)になるはずですよね。
nanoseeing

2021/03/17 08:16 編集

なお、pulpは線形計画問題を解くためのライブラリだと思うのですが、円の詰め込みは、線形な制約条件で表すことができるのでしょうか。円の重複判定には中心間の距離が必要で、2乗が出てきませんか? そのあたりの数学に関しては詳しくないので間違っていたら申し訳ないのですが。
yoshih

2021/03/18 03:05

printで値を見て、僕も円の詰め込みは線形な制約条件では表せないと思いました。そもそもuとvは上下左右の位置しかみておらず、最密充填に詰め込むことができないので、もう一度作り直す必要がありそうです。。。 重複判定は使用せずに、円と接する距離でプログラムしてみようと考えてます。 次はprintを活かしながら実行していきたいと思います。また質問することがあると思いますので、そのときは宜しくお願い致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問