例えば、フェーズオブジェクトを用いた制約系では、次のような解出力になります。3フェーズ/Day出力となります。
しかし、実際にユーザが管理しているのは、次のようなExcelフォーマットです。このフォーマットはユーザ毎に違います。SC3のExcel出力オプションでなんとかなるレベルではありません。
このGAPを埋めるのに、Excelマクロを使ったり、Openpyxl等を使った処理が必要になります。残念ながら、Openpyxlは、巨大すぎて実装できていないので、次善の策として、Pythonで整形したCSVファイルを出力することにしました。
Pythonソースは、以下です。
#post operation def get_day_index(day): return day-今月[0]+1 #名前項目分 def draw_row(person,day,row0,row1): phases=3 t0=task_solution[person][day*phases+0] t1=task_solution[person][day*phases+1] t2=task_solution[person][day*phases+2] d=get_day_index(day) #debug sc3.print(str(d)+' '+str(len(row0))+'\n') #勤務処理 if t0=='日T' and t1=='日T': if day in 休勤日今月: row0[d]='休勤' else : row0[d]='日勤' elif t0=='日T' and t1=='有給': row0[d]='後有' elif t1=='日T' and t0=='有給': row0[d]='前有' elif t0=='有給' and t1=='有給': row0[d]='有休' elif t0=='公休' and t1=='公休': row0[d]='休み' elif t0=='日T' and t1=='公休': row0[d]='午前' elif t1=='日T' and t0=='公休': row0[d]='午後' elif t0=='希望休み' and t1=='希望休み': row0[d]='希休' else: row0[d]='M休' #属性処理 if t2 !='公休': if day in 土: row1[d]='土拘' else : row1[d]='拘束' if shift_schedules[person][day]=='希望休み扱い': if row0[d] !='希休': row1[d]='希休' def post_main(): sc3.print('\n\n*********ポスト処理を実行中です。*************\n') sol_list=[] for person in 全スタッフ: row0=[] row1=[] row0.append(staffdef[person]) row1.append('') for day in 今月: row0.append('') #配列確保 row1.append('') #配列確保 draw_row(person,day,row0,row1) sol_list.append(row0) sol_list.append(row1) #Write csv file sc3.print('CSVファイルを生成中です。\n') os.chdir(project_file_path) file_path=project_file_path+'/this_month_solution.csv' with open(file_path, 'w', newline='') as file_path: writer = csv.writer(file_path) writer.writerows(sol_list) sc3.print('CSVファイルを生成しました。\n') sc3.print('********ポスト処理を終了します。*******************\n') #Main rountine 勤務日数設定OneShift() 有給日数設定OneShift() 週あたりの勤務日数設定OneShift()
このPythonソース中、def post_main(): がポスト処理で使用されるルーチンです。構文チェックは、
制約実行時に行われるので、構文エラーは、制約実行段階でチェックされます。制約実行時、解は未だありませんが、インタプリタの利点で、実行までその存在チェックはされないので、なくても問題ありません。
ポスト処理時は、制約実行のmain routineは、カットされます。このために、次のような記述構造としてください。
解は、shift_solution/task_solutionとして、2次元リストで得られます。これを解析してCSV出力しています。
処理内容としては、作業フォルダをプロジェクトファイルにした後、解をユーザフォーマットに変換して、CSV処理するだけです。ユーザは出力されたCSVをExcelで読み、そのシートを貼り付けるだけで済みます。
ポスト処理時のソースは、以下のソース全体(ポスト)で見ることが出来ます。(ReadOnlyです)
#staffdef staffdef=['スタッフ1','スタッフ2','スタッフ3','スタッフ4'] #daydef 制約開始日=6 制約終了日=35 表示開始日=0 daydef=['2020-05-26','2020-05-27','2020-05-28','2020-05-29','2020-05-30','2020-05-31','2020-06-01','2020-06-02','2020-06-03','2020-06-04','2020-06-05','2020-06-06','2020-06-07','2020-06-08','2020-06-09','2020-06-10','2020-06-11','2020-06-12','2020-06-13','2020-06-14','2020-06-15','2020-06-16','2020-06-17','2020-06-18','2020-06-19','2020-06-20','2020-06-21','2020-06-22','2020-06-23','2020-06-24','2020-06-25','2020-06-26','2020-06-27','2020-06-28','2020-06-29','2020-06-30'] #staffcollection 全スタッフ=[0,1,2,3] 正社員=[0,1] パート=[2,3] Work=[0,1,2,3] 日T=[0,1,2,3] 西拘束=[0,1,2,3] 拘束=[0,1,2,3] 有給=[0,1,2,3] 公休=[0,1,2,3] 希望休み=[0,1,2,3] NoTaskVar=[0,1,2,3] #daycollection 今月=[6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35] 日=[5,12,19,26,33] 月=[6,13,20,27,34] 火=[0,7,14,21,28,35] 水=[1,8,15,22,29] 木=[2,9,16,23,30] 金=[3,10,17,24,31] 土=[4,11,18,25,32] 全日=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35] 祝=[] 振=[] Dr1人木金=[9,16,24,31] 特別休業=[] パート給与計算1週目=[5,6,7,8,9,10,11] パート給与計算2週目=[12,13,14,15,16,17,18] パート給与計算3週目=[19,20,21,22,23,24,25] パート給与計算4週目=[26,27,28,29,30,31,32] パート給与計算5週目=[33,34,35] 増員火曜日=[7,35] 特別全員出勤日=[] 稼働日=[0,1,2,3,4,6,7,8,9,10,11,13,14,15,16,17,18,20,21,22,23,24,25,27,28,29,30,31,32,34,35] 制約開始日一日前=[5] 制約開始日二日前=[4] 制約開始日三日前=[3] 制約開始日四日前=[2] 制約開始日五日前=[1] 制約開始日六日前=[0] 制約開始日七日前=[] 制約開始日P1=[7] 制約開始日P2=[8] 制約開始日P3=[9] 制約開始日P4=[10] 制約開始日P5=[11] 制約開始日P6=[12] 第一週=[6,7,8,9,10,11,12] 第二週=[13,14,15,16,17,18,19] 第三週=[20,21,22,23,24,25,26] 第四週=[27,28,29,30,31,32,33] 第五週=[34,35] 第六週=[] 四週間=[6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33] 制約開始日1日前から=[5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35] 制約開始日2日前から=[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35] 制約開始日3日前から=[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35] 制約開始日4日前から=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35] 制約開始日5日前から=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35] 制約開始日6日前から=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35] 制約開始日7日前から=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35] 制約終了日六日前=[29] 制約終了日五日前=[30] 制約終了日四日前=[31] 制約終了日三日前=[32] 制約終了日二日前=[33] 制約終了日一日前=[34] 金土日=[3,4,5,10,11,12,17,18,19,24,25,26,31,32,33] 金土日月=[3,4,5,6,10,11,12,13,17,18,19,20,24,25,26,27,31,32,33,34] 休日でない月=[6,13,20,27,34] 休日でない火=[0,14,21,28] 休日でない水=[1,8,15,22,29] 休日でない木=[2,9,16,23,30] 休日でない金=[3,10,17,24,31] 休日でない土=[4,11,25] 実月水=[1,6,8,13,15,20,22,27,29,34] 実月火水=[0,1,6,7,8,13,14,15,20,21,22,27,28,29,34,35] 実火土=[0,4,11,14,21,25,28] 実土ではない=[0,1,2,3,5,6,7,8,9,10,12,13,14,15,16,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35] 実木金=[2,3,9,10,16,17,23,24,30,31] Dr2人の木=[2,23,30] Dr2人の金=[3,10,17] 今月月=[6,13,20,27,34] 今月火=[7,14,21,28,35] 今月水=[8,15,22,29] 今月木=[9,16,23,30] 今月金=[10,17,24,31] 今月土=[11,18,25,32] 実土=[4,11,18,25,32] 今月実土=[11,18,25,32] 実土でない=[0,1,2,3,5,6,7,8,9,10,12,13,14,15,16,17,19,20,21,22,23,24,26,27,28,29,30,31,33,34,35] 実土でない今月=[6,7,8,9,10,12,13,14,15,16,17,19,20,21,22,23,24,26,27,28,29,30,31,33,34,35] 土日=[4,11,18,19,25,32,33] 土日今月=[11,18,19,25,32,33] 休勤日=[5,12,19,26,33] 休勤日今月=[12,19,26,33] #shiftcollection #classcollection 全スタッフ属性=[全スタッフ] 雇用形態=[正社員,パート] #shiftdef shiftdef={'Work':Work} #taskdef taskdef={'日T':日T,'西拘束':西拘束,'拘束':拘束,'有給':有給,'公休':公休,'希望休み':希望休み,'NoTaskVar':NoTaskVar} #non_auto_tasks non_auto_tasks=['希望休み'] #phase_list 午前=0 午後=1 拘束=2 #task collections 休日集合={'有給':有給,'公休':公休,'希望休み':希望休み} 拘束集合={'拘束':拘束,'西拘束':西拘束} 働きカウント={'有給':有給,'日T':日T} 働きカウントしない={'公休':公休,'希望休み':希望休み} #phase_objects def phase_objects_def={'日勤','午前','午後','日勤拘束','日勤PV','公休PV','有休PV','希望PV','午前拘束PV','午前拘束西PV','午後拘束PV','午後拘束西PV','日勤拘束西PV','拘束ダメ','午前カウント','午後カウント','西の','拘束カウント','午前有休PV','午後有休PV','午前働','午後働','前後働'} #phase_object_aggregates phase_aggregate_object_def={'お休み','午前希望','午後希望','希望休み扱い','Any勤務','日勤扱い','午後扱い','有休集合','働集合'} #digited group 勤務日数最大={0:22,1:22,2:14.5,3:14.5} 勤務日数最小={0:22,1:22,2:13,3:13.5} 有給日数最大={0:2,1:2,2:1,3:1} 有給日数最小={0:0,1:2,2:0,3:0} 週あたりの勤務日数最大={2:4,3:4} 週あたりの勤務日数最小={2:3,3:3} 補助制約={'拘束タスクは、午前なし':B_拘束タスクは午前なし,'拘束タスクは、午後なし':C_拘束タスクは午後なし,'日タスクは、拘束フェーズなし':D_日タスクは拘束フェーズなし,'西野先生ではない休日':西野先生ではない休日,'西野先生休日':西野先生休日,'西野先生平日拘束':西野先生平日拘束,'西野先生ではない日(ひ)':E_西野先生ではない日ひ,'西野先生土曜日':西野先生土曜日} column_constraints={'列制約グループ1':列制約グループ1,'補助制約':補助制約} #shift schedules shift_schedules=[[('',0),('日勤',0),('日勤拘束',0),('日勤',0),('お休み',0),('お休み',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('希望休み扱い',0),('',0),('',0),('',0),('',0),('',0)] ,[('',0),('日勤拘束',0),('日勤',0),('お休み',0),('午前',0),('日勤拘束',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('拘束ダメ',0),('希望休み扱い',0),('希望休み扱い',0),('',0),('',0)] ,[('',0),('お休み',0),('有休PV',0),('午前',0),('午前拘束PV',0),('お休み',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('拘束ダメ',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)] ,[('',0),('日勤',0),('午前',0),('日勤拘束',0),('お休み',0),('お休み',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('午前希望',0),('',0),('希望休み扱い',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('希望休み扱い',0),('希望休み扱い',0),('',0),('',0)] ] task_schedules=[[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)] ,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)] ,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)] ,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)] ] project_file_path='C:/Users/sugaw/Documents/FA/sc3' shift_solution=[['Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work'] ,['Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work'] ,['Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work'] ,['Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work','Work'] ] task_solution=[['公休','日T','公休','日T','日T','公休','日T','日T','拘束','日T','日T','公休','公休','公休','公休','公休','公休','公休','日T','日T','拘束','日T','日T','公休','日T','日T','公休','日T','日T','拘束','公休','公休','公休','日T','公休','公休','日T','日T','拘束','公休','公休','公休','日T','日T','公休','日T','日T','公休','日T','日T','拘束','日T','日T','公休','公休','公休','公休','公休','公休','公休','日T','日T','拘束','日T','日T','公休','日T','日T','公休','有給','有給','公休','日T','日T','拘束','日T','公休','公休','公休','公休','公休','日T','日T','公休','日T','日T','拘束','日T','日T','公休','有給','有給','公休','日T','公休','公休','日T','公休','西拘束','公休','公休','公休','日T','日T','公休','日T','日T','公休'] ,['公休','日T','公休','日T','日T','拘束','日T','日T','公休','公休','公休','公休','日T','公休','公休','日T','日T','拘束','公休','公休','公休','有給','有給','公休','日T','日T','公休','日T','日T','公休','日T','日T','公休','日T','公休','拘束','公休','公休','公休','日T','日T','公休','日T','日T','公休','日T','日T','拘束','日T','日T','公休','有給','有給','公休','日T','公休','公休','日T','日T','西拘束','公休','公休','公休','日T','日T','公休','日T','日T','拘束','日T','日T','公休','日T','日T','公休','公休','公休','公休','日T','日T','拘束','公休','公休','公休','日T','日T','公休','日T','日T','公休','日T','日T','拘束','日T','日T','公休','公休','公休','公休','公休','公休','公休','日T','日T','公休','日T','日T','拘束'] ,['日T','公休','公休','公休','公休','公休','有給','有給','公休','日T','公休','公休','日T','公休','拘束','公休','公休','公休','日T','日T','公休','日T','日T','公休','日T','日T','拘束','公休','公休','公休','日T','公休','公休','公休','公休','公休','公休','公休','公休','日T','日T','拘束','公休','公休','公休','日T','日T','公休','公休','公休','公休','日T','日T','拘束','公休','公休','公休','公休','公休','公休','日T','日T','公休','公休','日T','拘束','有給','日T','公休','日T','公休','公休','公休','公休','公休','日T','公休','拘束','公休','公休','公休','日T','日T','公休','公休','公休','公休','日T','日T','拘束','日T','公休','公休','公休','公休','公休','日T','公休','公休','日T','日T','西拘束','公休','公休','公休','公休','日T','公休'] ,['日T','日T','公休','日T','日T','公休','日T','公休','公休','日T','日T','拘束','公休','公休','公休','公休','公休','公休','日T','日T','公休','日T','日T','拘束','公休','公休','公休','公休','公休','公休','日T','日T','拘束','公休','公休','公休','公休','公休','公休','日T','日T','公休','有給','日T','拘束','公休','公休','公休','公休','公休','公休','日T','公休','公休','日T','公休','西拘束','公休','公休','公休','日T','日T','公休','有給','公休','公休','日T','公休','公休','日T','日T','拘束','公休','公休','公休','公休','公休','公休','公休','公休','公休','日T','日T','拘束','公休','日T','公休','公休','公休','公休','日T','日T','公休','公休','日T','拘束','公休','公休','公休','公休','公休','公休','日T','日T','拘束','日T','公休','公休'] ] import sc3 import sys import os import csv def 勤務カウントOneShift(person,day,vlist): v=sc3.GetTaskVar(person,day,0,'日T');#AM vlist.append(v) v=sc3.GetTaskVar(person,day,1,'日T');#PM vlist.append(v) v=sc3.GetTaskVar(person,day,0,'有給');#AM vlist.append(v) v=sc3.GetTaskVar(person,day,1,'有給');#PM vlist.append(v) def 勤務日数設定OneShift(): for person in 全スタッフ: max=-1 min=0 st=staffdef[person]+' 勤務日数を制約' sc3.print(st+'します。\n') if person in 勤務日数最大: max=勤務日数最大[person]#float if person in 勤務日数最小: min=勤務日数最小[person]#float max *=2 min *=2 if isinstance(max, float) and not max.is_integer(): sc3.print('勤務日数設定でmaxが整数型ではありません。') continue if isinstance(min, float) and not min.is_integer(): sc3.print('勤務日数設定でminが整数型ではありません。') continue max =int(max) #float to int min =int(min) #float to int sc3.print('最大='+str(max)+' 最小='+str(min)+'\n') vlist=[] for day in 今月:#午前・午後の日勤と有給taskと有給シフトをカウントする 有給シフトは、2回分 勤務カウントOneShift(person,day,vlist) #sc3.AddSoft(sc3.SeqError(min,max,15,vlist),st,7)#許容2 ->8hours sc3.AddHard(sc3.SeqLE(min,max,vlist),st)#hard constraint def 有給日数設定OneShift(): min_sum=0; vlist_sum=[]; for person in 全スタッフ: max=-1 min=0 st=staffdef[person]+' 有給日数を制約' sc3.print(st+'します。\n') if person in 有給日数最大: max=有給日数最大[person]#float if person in 有給日数最小: min=有給日数最小[person]#float max *=2 min *=2 min_sum+=min; if isinstance(max, float) and not max.is_integer(): sc3.print('勤務日数設定でmaxが整数型ではありません。') continue if isinstance(min, float) and not min.is_integer(): sc3.print('勤務日数設定でminが整数型ではありません。') continue max =int(max) #float to int min =int(min) #float to int sc3.print('最大='+str(max)+' 最小='+str(min)+'\n') vlist=[] for day in 今月:#午前・午後の日勤と有給taskと有給シフトをカウントする 有給シフトは、2回分 v=sc3.GetTaskVar(person,day,0,'有給');#AM vlist.append(v) v=sc3.GetTaskVar(person,day,1,'有給');#PM vlist.append(v) sc3.AddSoft(sc3.SeqError(min,max,1,vlist),st,7) vlist_sum+=vlist; sc3.AddSoft(sc3.SeqError(min_sum,min_sum,10,vlist_sum),'Total有給の極小化',5)#重みは調整ください def 週あたりの勤務日数設定OneShift(): for person in 全スタッフ: max=14 min=0 st=staffdef[person]+' 週あたりの勤務日数を制約' sc3.print(st+'します。\n') if person in 週あたりの勤務日数最大: max=週あたりの勤務日数最大[person]#float if person in 週あたりの勤務日数最小: min=週あたりの勤務日数最小[person]#float if max==14 and min==0: continue max *=2 min *=2 if isinstance(max, float) and not max.is_integer(): sc3.print('週あたりの勤務日数設定でmaxが整数型ではありません。') continue if isinstance(min, float) and not min.is_integer(): sc3.print('週あたりの勤務日数設定でminが整数型ではありません。') continue max =int(max) #float to int min =int(min) #float to int sc3.print('最大='+str(max)+' 最小='+str(min)+'\n') week=0 for sun in 日:#日曜日を起点に1週間見る sc3.print('日曜日='+str(sun)+'\n') VList=[] days=0 for d in range(7): day=sun+d if day >制約終了日: break else: 勤務カウントOneShift(person,day,VList) days+=1 s="週あたりの勤務回数設定"+str(week)+' '+"person"+str(person) #Keyword+ space +variable word week+=1 if days==7: sc3.AddSoft(sc3.SeqError(min,max,2,VList),s,7) #level 3 許容エラー4 else: nmax=int( days*max/7);#7日に満たない場合は、リニア目標値設定 端数切捨て nmin=int( days*min/7);#7日に満たない場合は、リニア目標値設定 端数切捨て sc3.print(str(nmax)+"に目標値最大を設定しました。\n") sc3.print(str(nmin)+"に目標値最最小を設定しました。\n") sc3.AddSoft(sc3.SeqError(nmin,nmax,2,VList),s,7)#level 3 許容エラー4 #post operation def get_day_index(day): return day-今月[0]+1 #名前項目分 def draw_row(person,day,row0,row1): phases=3 t0=task_solution[person][day*phases+0] t1=task_solution[person][day*phases+1] t2=task_solution[person][day*phases+2] d=get_day_index(day) #debug sc3.print(str(d)+' '+str(len(row0))+'\n') #勤務処理 if t0=='日T' and t1=='日T': if day in 休勤日今月: row0[d]='休勤' else : row0[d]='日勤' elif t0=='日T' and t1=='有給': row0[d]='後有' elif t1=='日T' and t0=='有給': row0[d]='前有' elif t0=='有給' and t1=='有給': row0[d]='有休' elif t0=='公休' and t1=='公休': row0[d]='休み' elif t0=='日T' and t1=='公休': row0[d]='午前' elif t1=='日T' and t0=='公休': row0[d]='午後' elif t0=='希望休み' and t1=='希望休み': row0[d]='希休' else: row0[d]='M休' #属性処理 if t2 !='公休': if day in 土: row1[d]='土拘' else : row1[d]='拘束' if shift_schedules[person][day]=='希望休み扱い': if row0[d] !='希休': row1[d]='希休' def post_main(): sc3.print('\n\n*********ポスト処理を実行中です。*************\n') sol_list=[] for person in 全スタッフ: row0=[] row1=[] row0.append(staffdef[person]) row1.append('') for day in 今月: row0.append('') #配列確保 row1.append('') #配列確保 draw_row(person,day,row0,row1) sol_list.append(row0) sol_list.append(row1) #Write csv file sc3.print('CSVファイルを生成中です。\n') os.chdir(project_file_path) file_path=project_file_path+'/this_month_solution.csv' with open(file_path, 'w', newline='') as file_path: writer = csv.writer(file_path) writer.writerows(sol_list) sc3.print('CSVファイルを生成しました。\n') sc3.print('********ポスト処理を終了します。*******************\n') #Main rountine post_main()プリ・ポスト共GUI集合情報を元に記述できるので便利です。大半の情報は、既にGUIで記述済みですので、記述量が少なくて済みます。
実装では、pythonのソース解析が必要かなと一瞬思いましたが、Pythonの単純な文法構造のおかげで、Bisonを用いての真面目な処理は、行っていません。
以上の実装後の、ログは次のようになりました。
コンパイルの準備中ソルバを呼び出し中です。 Python ファイルを生成中です。 Python プロパティファイルの生成が終わりました。 制約をコンパイル中です。 スタッフ1 勤務日数を制約します。 最大=44 最小=44 スタッフ2 勤務日数を制約します。 最大=44 最小=44 スタッフ3 勤務日数を制約します。 最大=29 最小=26 スタッフ4 勤務日数を制約します。 最大=29 最小=27 スタッフ1 有給日数を制約します。 最大=4 最小=0 スタッフ2 有給日数を制約します。 最大=4 最小=4 スタッフ3 有給日数を制約します。 最大=2 最小=0 スタッフ4 有給日数を制約します。 最大=2 最小=0 スタッフ1 週あたりの勤務日数を制約します。 スタッフ2 週あたりの勤務日数を制約します。 スタッフ3 週あたりの勤務日数を制約します。 最大=8 最小=6 日曜日=5 日曜日=12 日曜日=19 日曜日=26 日曜日=33 3に目標値最大を設定しました。 2に目標値最最小を設定しました。 スタッフ4 週あたりの勤務日数を制約します。 最大=8 最小=6 日曜日=5 日曜日=12 日曜日=19 日曜日=26 日曜日=33 3に目標値最大を設定しました。 2に目標値最最小を設定しました。 Algorithm 1 Solving Process Started.. o 9920 0.964000(sec) o 8930 0.970000(sec) o 6780 0.987000(sec) o 5770 0.999000(sec) o 2780 1.010000(sec) o 1780 1.018000(sec) o 630 1.085000(sec) o 580 3.105000(sec) o 530 3.157000(sec) o 520 4.958000(sec) 充足解を書き込みました。 139612[KB] used. 5.729000(sec) Python ファイルを生成中です。 Python プロパティファイルの生成が終わりました。 _____________________________________ | | | | | Weight | Errors | Cost | |___________|___________|_____________| | | | | | 1000 | 0 | 0 | | 100 | 0 | 0 | | 50 | 9 | 450 | | 10 | 7 | 70 | |___________|___________|_____________| | | | | Total | 520 | |_______________________|_____________| o 520(0) *********ポスト処理を実行中です。************* CSVファイルを生成中です。 CSVファイルを生成しました。 ********ポスト処理を終了します。******************* 解探索が終了しました。 7 (秒) 解が得られました。
良くあるエラーは、次です、<string>
0 件のコメント:
コメントを投稿