Skip to content

Instantly share code, notes, and snippets.

@YSRKEN
Created October 30, 2018 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save YSRKEN/f9dd803ad02a5cfe5e99a51221e20bb5 to your computer and use it in GitHub Desktop.
Save YSRKEN/f9dd803ad02a5cfe5e99a51221e20bb5 to your computer and use it in GitHub Desktop.
少女前線(ドルフロ)の遠征を最適化するやつ(Pythonとpulpを使用)
# coding: UTF-8
import math
import pandas
import pulp
# 必要な資材量
want_supply = {
'人力': 10000,
'弾薬': 22000,
'配給': 0,
'パーツ': 0
}
# 遠征部隊数(最大:4)
unit_count = 4
# 更新間隔(hh:mm形式)
time_interval = '3:00'
def time_to_second(x: str) -> int:
"""hh:mm形式の文字列を、mmに変換する
:param x: str
hh:mm形式の時間
:return:
mm形式の時間
"""
temp = x.split(':')
return int(temp[0]) * 60 + int(temp[1])
def ceil(x: int, block: int):
"""xをblock単位で切り上げる
(参考:Python - 整数1桁5の切り上げのコードを短くしたい | teratail
https://teratail.com/questions/131512)
:param x:
整数
:param block:
切り上げ単位
:return:
切り上げ単位で切り上げられたx
"""
return int(math.floor((x + block - 1) / block)) * block
# 必要なデータを読み込む
exp_table = pandas.read_table('table.tsv')
exp_table['分'] = exp_table['時間'].map(lambda x: time_to_second(x))
time_interval_minute = time_to_second(time_interval)
exp_table['実質分'] = exp_table['分'].map(lambda x: ceil(x, time_interval_minute))
# 変数(各遠征の回数)を宣言
exp_table['回数'] = [
pulp.LpVariable(f'count_{i}', lowBound=0, cat=pulp.LpInteger)
for i in exp_table.index
]
# 問題の定義を始める
problem = pulp.LpProblem("Problem", pulp.LpMinimize)
result_time = pulp.LpVariable('result_time', lowBound=0, cat=pulp.LpContinuous)
problem += pulp.lpDot(exp_table.実質分, exp_table.回数) <= result_time * unit_count
problem += pulp.lpDot(exp_table.人力, exp_table.回数) >= want_supply['人力']
problem += pulp.lpDot(exp_table.弾薬, exp_table.回数) >= want_supply['弾薬']
problem += pulp.lpDot(exp_table.配給, exp_table.回数) >= want_supply['配給']
problem += pulp.lpDot(exp_table.パーツ, exp_table.回数) >= want_supply['パーツ']
for key, row in exp_table.iterrows():
problem += row.実質分 * row.回数 <= result_time
problem += result_time
# 問題を解く
problem.solve()
# 結果を表示する
exp_table['結果'] = exp_table['回数'].apply(lambda x: pulp.value(x)).astype('int64')
exp_table['総時間'] = exp_table.apply(lambda x: x['結果'] * x['実質分'] / 60.0, axis=1)
exp_table['人力'] = exp_table.apply(lambda x: x['結果'] * x['人力'], axis=1).astype('int64')
exp_table['弾薬'] = exp_table.apply(lambda x: x['結果'] * x['弾薬'], axis=1).astype('int64')
exp_table['配給'] = exp_table.apply(lambda x: x['結果'] * x['配給'], axis=1).astype('int64')
exp_table['パーツ'] = exp_table.apply(lambda x: x['結果'] * x['パーツ'], axis=1).astype('int64')
print(exp_table.query('結果 > 0.0')[['戦役', '名前', '結果', '総時間', '人力', '弾薬', '配給', 'パーツ']])
"""
# 変数(連続)を宣言
x = pulp.LpVariable("x", 0, 999, pulp.LpContinuous)
y = pulp.LpVariable("y", 0, sys.maxsize, pulp.LpContinuous)
# 目的関数を宣言
problem += ( x + y, "Objective" )
# かっこは不要だけど、わかりやすさのため記載
# 制約条件を宣言
problem += ( 2 * x + y <= 2 , "Constraint_1" )
problem += ( x + 2 * y <= 2 , "Constraint_2" )
# 問題の式全部を表示
print("問題の式")
print("--------")
print(problem)
print("--------")
# 計算
result_status = problem.solve()
# (解が得られていれば)目的関数値や解を表示
print("")
print("計算結果")
print("********")
print("最適性 = {}".format(pulp.LpStatus[result_status]))
print("目的関数値 = {}".format(pulp.value(problem.objective)))
print("解 x = {}".format(pulp.value(x)))
print("  y = {}".format(pulp.value(y)))
print("********")
"""
ID 戦役 名前 人力 弾薬 配給 パーツ Lv 時間
1 0 応援訓練 0 145 145 0 ? ? 0:50
2 0 合宿訓練 550 0 0 35 45 5 3:00
3 0 特殊支援 900 900 900 250 45 5 12:00
4 0 合同演習 0 1200 800 750 ? ? 24:00
5 1 準備運動 10 30 15 0 ? ? 0:15
6 1 巡回警備 0 40 60 0 ? ? 0:30
7 1 傷者搬送 30 0 30 10 ? ? 1:00
8 1 全域捜索 160 160 0 0 ? ? 2:00
9 2 前線調査 100 0 0 20 5 3 0:40
10 2 後方輸送 60 200 80 0 ? ? 1:30
11 2 工廠配達 10 10 10 230 ? ? 4:00
12 2 資料収集 0 250 600 60 15 5 6:00
13 3 掩体強化 50 0 75 0 ? ? 0:20
14 3 情報入手 0 120 70 30 ? ? 0:45
15 3 交通管制 0 300 0 0 15 4 1:30
16 3 間道封鎖 0 0 300 300 25 5 5:00
17 4 視界支援 0 185 185 0 ? ? 1:00
18 4 供給遮断 0 0 0 210 35 5 2:00
19 4 地図強奪 800 550 0 0 ? ? 6:00
20 4 座標特定 400 400 400 150 ? ? 8:00
21 5 定期検閲 0 0 100 45 ? ? 0:30
22 5 現場救助 0 600 300 0 35 5 2:30
23 5 経路追跡 800 400 400 0 40 5 4:00
24 5 維持工作 100 0 0 700 40 5 7:00
25 6 救援協力 300 300 0 100 35 5 2:00
26 6 遠隔捜査 0 200 550 100 40 5 3:00
27 6 技術抽出 0 0 200 500 45 5 5:00
28 6 戦場捜索 800 800 800 0 ? ? 12:00
29 7 拠点監視 650 0 650 0 ? ? 2:30
30 7 友軍支援 0 650 0 300 45 5 4:00
31 7 交通整理 900 600 600 0 ? ? 5:30
32 7 ダミー追跡 250 250 250 600 ? ? 8:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment