質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
最適化

最適化とはメソッドやデザインの最適な処理方法を選択することです。パフォーマンスの向上を目指す為に行われます。プログラミングにおける最適化は、アルゴリズムのスピードアップや、要求されるリソースを減らすことなどを指します。

Python

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

Q&A

解決済

1回答

6485閲覧

Pythonのpulpで作成したい制約条件をどうしても表現できません。

robocat

総合スコア4

最適化

最適化とはメソッドやデザインの最適な処理方法を選択することです。パフォーマンスの向上を目指す為に行われます。プログラミングにおける最適化は、アルゴリズムのスピードアップや、要求されるリソースを減らすことなどを指します。

Python

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

0グッド

0クリップ

投稿2021/11/05 07:49

編集2021/11/11 05:02

はじめに

Pythonのpulpを使用して“決定変数を用いたスイッチ(if構文)”を作成したいと考えております。
ここで、“決定変数を用いたスイッチ(if構文)”というのは、例えば「x(xは0以上の整数)とy(yは0,1のバイナリ変数)を決定変数としたとき、xが1以上の整数であればyは1を出力し、xが0であればyは0を出力する」ようなのを指します。

以下には、簡単な例題を用いて、“決定変数を用いたスイッチ(if構文)”の作成に向けて取り組んでみたこととその結果を記載させていただいております。

簡単な例題は、「入門オペレーションズ・リサーチ」(東海大学出版会)、「第1回:最近学んだ数理最適化の定式化のチップスたち 【ブレインパッドの数理最適化ブログ】」の例題を参考にさせていただき、作成しました。

本稿の大まかな流れとしましては、
①基本的な例題(アイス生産問題)を解きます。
②基本的な例題に、自作の“決定変数を用いスイッチ(if構文)”の機能を果たさない制約を導入する場合の説明をします。
③基本的な例題に、(本稿のテーマである)自作の“決定変数を用いたスイッチ(if構文)”の機能を果たす制約を導入する場合の説明をします。(3パターンございます。)

③を試したのですが現状、“決定変数を用いたスイッチ(if構文)”は作成できておりません。
作成できない原因といたしましても、そもそも不可能なことに挑戦しているのか、またはPython(pulp)初心者である私のプログラムの知識が足りないだけなのかもわかっておりません。
そのため、原因分析及び解決方法を見つけるのに、お力添えいただけますと幸いに存じます。

基本的な問題(アイス生産問題)

引用テキストアイス屋さんが、エスプレッソアイス、ラズベリーアイス、2種類のアイスの生産を計画しています。しかし、材料の牛乳は 8000 cc、作業時間は述べ 360 分という制限があり、好きな分量だけ作れるわけではありません。それぞれのアイスに使う牛乳とかかる手間がこのようになっているとき、儲けを最大にする増産計画はどの様になるでしょうか?

牛乳作業時間儲け
エスプレッソアイス100cc7分50円
ラズベリーアイス150cc5分10円

上記の問題設定を定式化しますと以下のように表すことができます。

イメージ説明

Pythonでプログラムにすると以下のように表すことができます。

Python

1import pulp 2 3problem = pulp.LpProblem('ice', pulp.LpMaximize) 4 5# 決定変数を定義 6x_e = pulp.LpVariable('x_e', lowBound=0, cat=pulp.LpInteger) 7x_r = pulp.LpVariable('x_r', lowBound=0, cat=pulp.LpInteger) 8 9# 目的関数を設定 10problem += 50*x_e +10*x_r 11 12# 制約を設定 13problem += 100*x_e + 150* x_r <= 8000 14problem += 7*x_e + 5* x_r <= 360 15 16# 最適化 17problem.solve() 18 19# 結果の表示 20print("エスプレッソ",x_e.value(),"個") 21print("ラズベリー",x_r.value(),"個") 22print("儲け",pulp.value(problem.objective),"円")

上記のプログラムを実行した結果は以下の通りです。

Python

1エスプレッソ 51.02ラズベリー 0.03儲け 2550.0

この結果より、儲けを最大にするにはラズベリーアイスを1つも生産しない方が良いことがわかります。

自作の“決定変数を用いスイッチ(if構文)”の機能を果たさない制約を導入する場合(アイス生産問題)

ここで、新たな制約条件を問題設定に加えます。
(新たに加えた制約条件を太文字にしてあります。)

引用テキストアイス屋さんが、エスプレッソアイス、ラズベリーアイス、2種類のアイスの生産を計画しています。しかし、材料の牛乳は 8000 cc、作業時間は述べ 360 分という制限があり、好きな分量だけ作れるわけではありません。それぞれのアイスに使う牛乳とかかる手間がこのようになっているとき、儲けを最大にする増産計画はどの様になるでしょうか?ただし本日、ラズベリーアイス1個分の量のラズベリー(素材)が消費期限を迎えます。よって、廃棄にならないよう少なくとも1個のラズベリーアイスを生産する必要があります。

牛乳作業時間儲け
エスプレッソアイス100cc7分50円
ラズベリーアイス150cc5分10円

上記の問題設定を定式化しますと以下のように表すことができます。

![イメイメージ説明

Pythonでプログラムにすると以下のように表すことができます。

Python

1import pulp 2 3problem = pulp.LpProblem('ice', pulp.LpMaximize) 4 5# 決定変数を定義 6x_e = pulp.LpVariable('x_e', lowBound=0, cat=pulp.LpInteger) 7x_r = pulp.LpVariable('x_r', lowBound=0, cat=pulp.LpInteger) 8 9# 目的関数を設定 10problem += 50*x_e +10*x_r 11 12# 制約を設定 13problem += 100*x_e + 150* x_r <= 8000 14problem += 7*x_e + 5* x_r <= 360 15 16###新たに加えた制約 17problem += x_r >= 1 18 19# 最適化 20problem.solve() 21 22# 結果の表示 23print("エスプレッソ",x_e.value(),"個") 24print("ラズベリー",x_r.value(),"個") 25print("儲け",pulp.value(problem.objective),"円")

上記のプログラムを実行した結果は以下の通りです。
儲けを最大にしつつ、消費期限が迫ったラズベリー(ラズベリーアイス1個分の量)を廃棄せずにすみました。

Python

1エスプレッソ 50.02ラズベリー 2.03儲け 2520.0

Challenge1:自作の“決定変数を用いたスイッチ(if構文)”の機能を果たす制約を導入後(アイス生産問題)

一つ前の章では以下のような制約を元の基本的な問題に加えました。

イメージ説明

Python

1#新たに加えた制約 2problem += x_r >= 1

今回の質問のテーマに沿わせるために、この制約を以下のような“決定変数を用いスイッチ(if構文)”の機能を果たす制約に書き換えます。

イメージ説明

Challenge1

1problem = pulp.LpProblem('ice', pulp.LpMaximize) 2 3# 決定変数を定義 4x_e = pulp.LpVariable('x_e', lowBound=0, cat=pulp.LpInteger) 5x_r = pulp.LpVariable('x_r', lowBound=0, cat=pulp.LpInteger) 6 7###新たに加えた決定変数 8y_r = pulp.LpVariable('y_r', lowBound=0, cat=pulp.LpBinary) 9 10# 目的関数を設定 11problem += 50*x_e +10*x_r 12 13# 制約を設定 14problem += 100*x_e + 150* x_r <= 8000 15problem += 7*x_e + 5* x_r <= 360 16 17###新たに加えた制約 18if x_r.value() >= 1: 19 y_r=1 20 problem += y_r == 1 21 22# 最適化 23problem.solve() 24 25# 結果の表示 26print("エスプレッソ",x_e.value(),"個") 27print("ラズベリー",x_r.value(),"個") 28print("儲け",pulp.value(problem.objective),"円") 29

結果は以下の通りでして、エラーが出ました。

Result1

1~省略~ 2 if x_r.value() >= 1: 3TypeError: '>=' not supported between instances of 'NoneType' and 'int'

Challenge2:自作の“決定変数を用いたスイッチ(if構文)”の機能を果たす制約を導入後(アイス生産問題)

Challenge1でエラーが出たのはプログラムでの制約の表現方法が悪いのかと考えました。
そのため、試しに“x_r.value”の“.value”を外してみることにしました。

Challenge2

1import pulp 2 3problem = pulp.LpProblem('ice', pulp.LpMaximize) 4 5# 決定変数を定義 6x_e = pulp.LpVariable('x_e', lowBound=0, cat=pulp.LpInteger) 7x_r = pulp.LpVariable('x_r', lowBound=0, cat=pulp.LpInteger) 8 9###新たに加えた決定変数 10y_r = pulp.LpVariable('y_r', lowBound=0, cat=pulp.LpBinary) 11 12# 目的関数を設定 13problem += 50*x_e +10*x_r 14 15# 制約を設定 16problem += 100*x_e + 150* x_r <= 8000 17problem += 7*x_e + 5* x_r <= 360 18 19###新たに加えた制約 20if x_r >= 1: 21 y_r=1 22 problem += y_r == 1 23 24 25# 最適化 26problem.solve() 27 28# 結果の表示 29print("エスプレッソ",x_e.value(),"個") 30print("ラズベリー",x_r.value(),"個") 31print("儲け",pulp.value(problem.objective),"円") 32

結果は以下の通りでして、エラーは出なかったもののラズベリーアイスが0個であることから導入した制約は制約として認識(反映)されていないことがわかります。

Result2

1エスプレッソ 51.0 個 2ラズベリー 0.0 個 3儲け 2550.0 円

Challenge3:自作の“決定変数を用いたスイッチ(if構文)”の機能を果たす制約を導入後(アイス生産問題)

次に、決定変数y_rを使用するのはいったん諦め、y_rを使用しない(別の決定変数で置き換えない)スイッチ機能のある制約およびプログラムをmax関数を用いて作成してみました。

Challenge3

1import pulp 2 3problem = pulp.LpProblem('ice', pulp.LpMaximize) 4 5# 決定変数を定義 6x_e = pulp.LpVariable('x_e', lowBound=0, cat=pulp.LpInteger) 7x_r = pulp.LpVariable('x_r', lowBound=0, cat=pulp.LpInteger) 8 9# 目的関数を設定 10problem += 50*x_e +10*x_r 11 12# 制約を設定 13problem += 100*x_e + 150* x_r <= 8000 14problem += 7*x_e + 5* x_r <= 360 15 16###新たに加えた制約 17problem += max(x_r,0) >= 1 18 19 20# 最適化 21problem.solve() 22 23# 結果の表示 24print("エスプレッソ",x_e.value(),"個") 25print("ラズベリー",x_r.value(),"個") 26print("儲け",pulp.value(problem.objective),"円") 27

結果は以下の通りでして、エラーが出ました。
このようなmax関数を使用した制約を作成することはできないようです。

Result3

1~省略~ 2 problem += max(x_r,0) >= 1 3TypeError: '>' not supported between instances of 'int' and 'LpVariable'

以上、3つの方法で取り組んでみましたが決定変数を用いてスイッチ(if構文)を作成することができませんでした。

そもそもpulpでこのような制約(=決定変数を用いてスイッチ(if構文))を作成し、解くことは不可能なのでしょうか。
(勉強不足で恐縮なのですが、もしや非線形問題になっていてpulpでは表現できないのでしょうか。)
それとも私のプログラムの書き方が悪いだけなのでしょうか。

よろしければ原因と解決方法をご教授いただけますと幸いに存じます。
(できたら慣れているpulpを使用したいのですが、仮にpulpを使用しなければプログラムを記述することができるのであれば挑戦したいと思いますので、ご教授下さりますと幸いに存じます。)

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

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

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

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

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

guest

回答1

0

自己解決

stackoverflowの方で解決策を回答いただくことができました。
以下にリンクと原文を再現したものを記載させていただきます。
回答者様に感謝申し上げます。

I was able to get the solution answered by stackoverflow.
Here is the link and the original text.
Thank you very much.

URL:https://stackoverflow.com/questions/69880590/how-to-create-a-program-for-constraints-based-on-decision-variables-when-using-p?answertab=votes#tab-top


You cannot add a constraint based on x_r.value()because this won't be available until the problem has been solved.

A better approach would be to connect x_r and y_r
through two additional constraints:

problem += M*y_r >= x_r problem += y_r <= x_r

Here Mis a big enough number, with your data setting M = min(8000/150, 360/5)would suffice.

投稿2021/11/11 04:59

robocat

総合スコア4

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問