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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

1回答

900閲覧

作成したプログラムについての質問

K.takita

総合スコア14

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2020/12/02 04:54

前提・実現したいこと

現在、シフトの作成を行おうとしています。
これまで質問した内容に関する回答をもとに、以下のプログラムを作成しました。

該当のソースコード

python

1import numpy as np 2import pandas as pd 3from pulp import LpBinary, LpMinimize, LpProblem, LpVariable, lpSum, value 4 5#アルバイトの集合 6n_member = 5 7member = pd.Series(f"member{m+1}" for m in range(n_member)) 8 9#日にちの集合 10n_day = 2 11day = pd.Series(f"day{d+1}" for d in range(n_day)) 12 13#時刻の集合 14n_time = 9 15time = pd.Series(f"{t+12}時" for t in range(n_time)) 16#t時 : t時~t+1時 17 18#シフト番号 19n_shiftnumber = 6 20shiftnumber = pd.Series(f"shift{sn+1}" for sn in range(n_shiftnumber)) 21 22#シフトの一覧 23shift = pd.read_csv('exshift.csv', header=None) 24shift.index = shiftnumber 25shift.columns = time 26 27shiftdaycount = [int(sum(x) > 0) for x in shift.values] 28 29#各シフトの労働時間 30wtime = pd.read_csv('wtime.csv', header=None) 31wtime.index = shiftnumber 32wtime.columns = day 33 34#必要人数 35need = pd.DataFrame([[2, 2, 2, 2, 2, 2, 2, 2, 2]], index=day, columns=time) 36 37#希望出勤日 38kibou = pd.DataFrame([[1, 1], 39 [1, 1], 40 [1, 1], 41 [1, 1], 42 [1, 1]], index=member, columns=day) 43 44#各メンバーの時給 45jikyu = pd.DataFrame([[900, 900], 46 [900, 900], 47 [900, 900], 48 [900, 900], 49 [900, 900]], index=member, columns=day) 50 51#1日の人件費 52jinkenhi = pd.DataFrame([[16200], 53 [16200]], index=day) 54 55 56#モデルの作成 57prob = LpProblem(sense=LpMinimize) 58 59#変数 60X = LpVariable.dicts('X', ([m for m in range(member.size)], [d for d in range(day.size)], [s for s in range(n_shiftnumber)]), 0, 1, 'Integer') 61 62#目的関数 63prob += kibou.values.sum() - lpSum(shiftdaycount[s] * X[m][d][s] for s in range(n_shiftnumber) for d in range(day.size) for m in range(member.size)) 64 65for m in range(member.size): 66 #希望出勤日数 67 ks = kibou.iloc[m].sum() 68 #実際に働いた日数 69 actual = lpSum(shiftdaycount[s] * X[m][d][s] for s in range(n_shiftnumber) for d in range(day.size)) 70 #(制約1)実際に働いた日数が希望出勤日数を超えない制約 71 prob += actual <= ks 72 73 74#制約条件 75#(制約2)必要最低人数を満たす制約 76for d in range(day.size): 77 for t in range(time.size): 78 prob += lpSum(shift.values[s][t] * X[m][d][s] for s in range(n_shiftnumber) for m in range(member.size)) == need.iloc[d, t] 79 80#(制約4)各メンバーが1日に取りうるシフトは必ず1つ 81for m in range(member.size): 82 for d in range(day.size): 83 prob += lpSum(X[m][d][s] for s in range(n_shiftnumber)) == 1 84 85#(制約5)人件費を超えない 86for s in range(n_shiftnumber): 87 for d in range(day.size): 88 prob += lpSum(jikyu.iloc[m, d] * wtime.iloc[s, d] * X[m][d][s] for m in range(member.size)) <= jinkenhi.iloc[d] 89 90#(制約6)6日以上の連続勤務を禁止する 91for m in range(member.size): 92 for s in range(n_shiftnumber): 93 prob += lpSum(X[m][d][s] for d in range(day.size)) <= 6 94 95prob.solve() 96 97 98scheduling = pd.DataFrame(index=member, columns=day) 99for m in range(member.size): 100 for d in range(day.size): 101 for s in range(n_shiftnumber): 102 if X[m][d][s].value() == 1: 103 scheduling.iloc[m, d] = shiftnumber[s] 104 105scheduling.to_csv("scheduling.csv") 106 107

各csvファイルのデータ内容

shift 12時 13時 14時 15時 16時 17時 18時 19時 20時 shift1 0 0 0 0 0 0 0 0 0 shift2 1 1 1 1 1 1 1 1 1 shift3 1 1 1 0 0 0 0 0 0 shift4 0 0 0 1 1 1 0 0 0 shift5 0 0 0 0 0 0 1 1 1 shift6 1 1 1 0 0 0 1 1 1
wtime day1 day2 shift1 0 0 shift2 9 9 shift3 3 3 shift4 3 3 shift5 3 3 shift6 6 6

上記のプログラムでは日ごとに各memberが出勤可能かどうか(上記の希望出勤日)をもとに実行してきました。
この日ごとで出勤可能かどうかを判別していたものを、時間ごとに判別しシフトを組むものを作成したいと考えています。(〇日は出勤できます→〇日の×時は出勤できますというように変更したい)
そこで上記の希望出勤日の部分を以下の希望出勤時間のように変更してみました。

試したこと

python

1#希望出勤時間 2kibou = pd.DataFrame([[0, 0, 0, 1, 1, 1, 0, 0, 0], 3 [0, 0, 0, 1, 1, 1, 0, 0, 0], 4 [1, 1, 1, 0, 0, 0, 1, 1, 1], 5 [1, 1, 1, 0, 0, 0, 1, 1, 1], 6 [0, 0, 0, 0, 0, 0, 0, 0, 0]], index=member, columns=time) 7#0 : 出勤不可の時間 8#1 : 出勤可能な時間 9 10kiboutimecount = [int(sum(y) > 0) for y in kibou.values]

変更後、エラーは発生せず、以下のような結果が得られました。

実行結果

python

1 day1 day2 2member1 shift3 shift4 3member2 shift5 shift4 4member3 shift4 shift6 5member4 shift2 shift6 6member5 shift1 shift1

実行結果のday2は問題ないのですが、day1のように出勤不可の時間帯に出勤するようなシフトを選択してしまいます。
これはプログラムに問題があるのか、希望出勤時間のデータの書き方に問題があるのか、判断ができないため質問させていただきました。
一方的な質問になってしまい申し訳ありません。よろしくお願いします。

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

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

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

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

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

guest

回答1

0

すみません。かなり分かりづらいと思いますので、今回行いたかったこと、また、少し試してみたことがあるので、それらを踏まえ改めて投稿させていただきます。
大変申し訳ありませんが、そちらに回答をいただけると幸いです。

投稿2020/12/03 05:11

K.takita

総合スコア14

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問