gikoha’s blog

個人的メモがわり

Optaplannerでシフト作成 - 5

結局DRLで「あるdayのemployeeがworkDayであった場合、他のemployeeのassign scoreを-1する」と表現するのがわからなかったので、employee workDayを読み込んだときに他のemployeeにそのdayを使わないようにフラグをつけることとした

 

うまく動くようになってご満悦

GitHub - vascarpenter/ShiftSolver

あとIntelliJ IDECSV pluginを使うと余計なスペースを入れられて、openCSVで読み込むときゴミが入ってしまうのでプラグインを削除した。

 

Optaplannerでシフト作成 - 4

Employeeに HashMapを持たせ、Assetsを解析させることで DRLから参照できるようにして、ついに拘束日と休日を実装できた

GitHub - vascarpenter/ShiftSolver

f:id:gikoha:20180915211528j:plain

だが、DRLではどうやったら拘束日の実装をすればいいのかわからん

一番の理想:拘束日の医師は決定しており optaplannerを使うまでもない

理想:ある日がだれかの拘束日に当たっていて、その担当以外の医師だったらスコアを下げる

→ある日が誰かの拘束日であるか逆算できる必要がある

現実:その医師の拘束日だったらスコアをあげる。本当は上げたくないんだが。

DRL:

when WorkDayAssignment(employee != null, employee.isWorkDay(day) == true) then scoreHolder.addHardConstraintMatch(kcontext, new BigDecimal(1));

うーんむずかしい

でもプログラムとしてはこれでほとんど完成なんだな..

 

Optaplannerでシフト作成 - 3

GitHub - vascarpenter/ShiftSolver

GUIを拡張し、テーブルにして、拘束日と休日を","で区切って入力できるようにした

そのリストはCSVでの読み込みと保存できる

出力もテーブルにした

出力はCSVで結果を保存できるようにした

Optaplanner 7.0に対応し、deprecatedなものは削除

こんなふうになった

 

f:id:gikoha:20180914230416j:plain

まだ拘束日と休日の検索に対応していないけれどな!

 

jarで書き出した場合、DRLはリソースにしないと読めず、リソースにするとJARファイル内にDRLが入ってしまってこれはgetResourceで読めないから解析がなされなくなってしまう

DRLをlistにしてbuilderに読ませる方法がわからん。

Optaplannerでシフト作成 - 2

GUIを作成しました

GUIの問題点は「ボタンを押して計算を始めるとGUIに処理がいかずに計算中はハングしてしまう」こと

SwingWorkerを使うとよさそうで、実際optaplannerのサンプルもSwingWorkerを使っているので、とりあえず入れてみた

GitHub - vascarpenter/ShiftSolver

 

f:id:gikoha:20180913221806j:plain

Optaplannerでシフト作成 - 1

www.ogis-ri.co.jp

を参考に、以前に作ったシフト割り振りをoptaplannerを使ってヒューリスティック法で探索するプログラムを作る。

GitHub - vascarpenter/ShiftSolver: shift solver sample application using optaplanner

とりあえず doctorA,B,Cの3人を Employeeに

日付を Dayに

拘束割り付けモデルを WorkDayAssignmentにする

solutionParameterを使ったあまり美しくないやりかたも継承

とりあえずdrlは

rule "countLeveling"
  when
    $solutionParameter : SolutionParameter()
    $employee : Employee()
    $workCountPerPeople : Number() from accumulate( $workDayAssignment : WorkDayAssignment( employee == $employee ), count( $workDayAssignment ) )
  then
    scoreHolder.addSoftConstraintMatch(kcontext, new BigDecimal((int)(-10000D * Math.pow($solutionParameter.getCountAverage() - $workCountPerPeople.doubleValue(), 2) )));
end

のみとした (均等割り付けモデルのみ)

実際走らせてみると

    Day	People
1	Doctor A
2	Doctor C
3	Doctor B
4	Doctor A
5	Doctor C
...
<secondsSpentLimit>10</secondsSpentLimit>

で10秒間だけ探索するよう指定したけれど上記のようにうまくいってそうな感じ 

あとは休み希望や専門の縛り、土日拘束回数の均一化、

非同期探索、swingやkotlin/TornadeFXのガワもかぶせないとな..

cmd.exe

Windowsは cmd.exe上で

pushd "¥¥ServerIP¥hoge¥oge"      (cdだとUNCが使えないため)

java -jar hogehoge.jar

popd

とバッチファイルでいままでやっていたが jarならstartまんまでいけるとのことであり

start "¥¥Server¥hoge¥oge¥hogehoge.jar"

だけでよかったらしい

 

eclipse to IntelliJ IDEA (Java 1.3-6 Project)

ターゲットのJVMバージョン1.5-1.6で動作するプログラムを作るとき、これまでは eclipse+ WindowBuilderが定番だったが、 IntelliJ IDEAでは formを読ませることで WindowBuilderの代わりをするらしい(IDEが$$$setup$$$とかをソースで埋め込むかバイナリで埋め込むかをPreferences>Editor>GUI Designerから選んでおくこと)

まず New Projectから Javaを選択しProjectを作る

Project structure画面からsrcを右クリックし packageを作る

f:id:gikoha:20180910214355j:plain

main view classは extends JFrameとする

main view classから右クリックし、同じ名前のGUI Formを作る

bind classを新規に作らない場合には必ずbindしておくこと

まっさらなJPanelができる

f:id:gikoha:20180910214417j:plain

コンポーネントをつめこむ  GridLayoutManager (IntelliJ)はコンポーネントを長くしたい場合横方向や縦方向にRow/Columnをつなげることで長くできる

f:id:gikoha:20180910214531j:plain

ロジックを書き込んで pack()等を忘れずにコンストラクタに記述する

f:id:gikoha:20180910214612j:plain

そんでもってうまくいきました

f:id:gikoha:20180910214702j:plain

apache poi使った。

こりゃ本格的にeclipse不要になってきたな..