pulpについて

  • pythonにおける数理最適化の有名なソルバー
    • 混合整数計画法を解くことができる
    • 混合整数計画法のなかに線形計画法や整数計画法が含まれる
    • つまり求めたい変数が実数だったり整数だったりする数理最適化問題と思えばよいだろう
  • PuLP の基本的な使い方
import pulp

prob = pulp.LpProblem('sample')

# 変数の定義
x = pulp.LpVariable('x', lowBound = 0)
y = pulp.LpVariable('y', lowBound = 0)

# 目的関数
prob += x + y + 1  

# 制約条件
prob += 3 * x + 5 * y <= 15
prob += 2 * x + y >= 4
prob += x - y == 1

print(prob)

# 実行
status = prob.solve(pulp.PULP_CBC_CMD(msg=0))
print("Status", pulp.LpStatus[status])

# 結果の表示
print("Result")
print("x", x.value())
print("y", y.value())
print("z", prob.objective.value())
  • 数理モデルオブジェクト prob = LpProblem(name='NoName', sense=LpMinimize)
    • name : 名前
    • sense : LpMinimize (最小値を求める), LpMaximize (最大値を求める)
  • 変数定義 var = LpVariable(name, lowBound=None, upBound=None, cat='Continuous')
    • name: 変数名
    • lowBound: 変数の下限値, None で -∞
    • upBound: 変数の上限値, None で ∞
    • cat: 変数の種類
      • Continuous, 実数
      • Integer, 整数
      • Binary, 0 または 1
  • 目的関数と制約条件の指定
    • prob += 式 でを指定する
    • 使用できる演算子は <=. ==, >= の 3 つだけ (それ以外の演算子は NG)
    • 演算子を含まない式が目的関数に自動でなる
  • 演算
    • status = prob.solve() で問題を解く (ソルバーを起動して解を求める)
    • 変数 var の値は var.value() で取得する
    • 目的関数の値は prob.objective.value() で取得する
  • 参考:

PuLP による数理最適化超入門

数理最適化について

  • ある目的関数を最大化または最小化するような解(パラメタ)を求めたい
    • 数理最適化がそんなとき使える
  • 複数の制約が課せられた条件下でのパラメタも求められる
    • 数理最適化すげえ
例題
材料AとBから合成できる化学製品XとYをたくさん作成したい。
Xを1kg作るのに、Aが1kg、Bが3kg必要である。
Yを1kg作るのに、Aが2kg、Bが1kg必要である。
また、XもYも1kg当りの価格は100円である。
材料Aは16kg、Bは18kgしかないときに、XとYの価格の合計が最大になるようにするには、
XとYをどれだけ作成すればよいか求めよ。
  • このときの目的関数は「XとYの価格の合計」
    • XとYの重量をxとyとすると目的関数は「100*(x +y)」
    • これを最大化させるxとyの組を求めたい
    • 制約条件がないならxとyを大きくすれば目的関数をいくらでも大きくできる
    • つまり実数解なし
  • 今回は材料AとBに対していくつか条件があり、xとyはどんな値でも取れるわけではない
    • 材料AとBの重量をaとbとする
    • 条件1:Xをxだけつくるには、Aがx、Bが3xの材料が必要
    • 条件2:Yをyだけつくるには、Aが2y、Bがyの材料が必要
    • 条件3:Aは16、Bは18の材料しかない
    • これらを数式にしてまとめると、xとyは以下の2つの制約式を満たさねばならない
      • x + 2y <= 16
      • 3x + y <= 18
  • よって、例題を数式で書き直すと
制約式 x + 2y <= 16と3x + y <= 18を満たすxとyのもとで、
目的関数100*(x +y)を最大化するxとyの組を求めよ
  • 高校数学でやったことあるよね
  • 線形計画法ってやつ
  • pythonだと pulp というソルバーを使って、この問題を解くことができる
from pulp import *
m = LpProblem(sense=LpMaximize) # 目的関数を最大化するよ~
x = LpVariable('x', lowBound=0) # 求めたいパラメタ1
y = LpVariable('y', lowBound=0) # 求めたいパラメタ2
m += 100 * x + 100 * y # 目的関数
m += x + 2 * y <= 16 # 材料Aの制約条件
m += 3 * x + y <= 18 # 材料Bの制約条件
m.solve() # ソルバーの実行
print(value(x), value(y)) # 4, 6

gitで直前のコミットを取り消したいとき

  • ゴミみたいなコミットメッセージでコミットしてもうた時
  • もうちょっと変更を加えてからコミットしたかった時
  • git reset --soft HEAD^
  • --soft :エディタ上のスクリプトの内容はそのままにして、コミットのみ取り消したい場合に使用
  • HEAD^:直前のコミットを意味する。
  • 参考:qiita.com/shuntaro_tamura/items/06281261d893acf049ed

gitで直前のコミットを取り消したいとき

  • ゴミみたいなコミットメッセージでコミットしてもうた時
  • もうちょっと変更を加えてからコミットしたかった時
  • git reset --soft HEAD^
  • --soft :エディタ上のスクリプトの内容はそのままにして、コミットのみ取り消したい場合に使用
  • 参考:qiita.com/shuntaro_tamura/items/06281261d893acf049ed

ggplotでy軸名を折り返したいとき

  • テストデータ
df <- tibble(
  label_grp = c("short", "Medium label",
                "a very long axis label that needs to be folded"),
  some_value = c(13633,20824,42000)
)
  • まずは普通にggplot
  • このままだと折り返してくれない
ggplot(data = df) +
  geom_col(aes(y = label_grp, 
               x = some_value,
               fill = label_grp))
  • str_wrapscale_y_discreteかますと折り返してくれる
ggplot(data = df) +
  geom_col(aes(y = label_grp, 
               x = some_value,
               fill = label_grp)) +
  scale_y_discrete(labels = function(x) str_wrap(x, width = 15))

googleドライブでファイルを深階層のフォルダに移動させたいとき

  • googleドライブでファイルを移動させる方法
    • 移動させたいファイルを右クリック→「指定の場所へ移動」→移動させたいフォルダを探す→移動
  • ただし、移動先のフォルダに深い階層のなかにあるとき、移動先のフォルダを探すのはしんどい
  • スター機能を使うと便利
    • 移動先のフォルダを右クリック→「スターを付ける」→移動させたいファイルを右クリック→「スター付きの場所へ移動」 dev.classmethod.jp