スケジューリングソルバ ScNurse Software Development Kit for Socket Interface Technical View. 2016.Aug.5 菅原システムズ 評価開発環境 シリアライズ (problem.json) 制約クラス ソケットで送る GUI C#ソース 実行エンジン ソケットで解受け取り 1.スケジュールナースVer2相当のGUIソー ス(C# )が付いています。 2.制約クラスの使い方は、入力であるGUI ソースと、出力であるproblem.jsonを見る とよいでしょう。 3.ソースをコピペするとスケジュールナー スが出来てしまいます。(3rdParty GUI モ ジュールを除く) probelm.json と 解形式 { "SO": { "name": "Shift Objects", "members": [ { "use": true, "name": "ShiftDef", "def_name": "オンコール", "auto_schedule": true, "color": "Yellow", "label": "コ", "another_labels": [ "", "" ], "another_colors": [ "Gray", "Gray" ], SAT,7,36,2016,8 1日代休,オンコール,半日代 休,外来勤務,半日代休,訪問看 護,オンコール,外来勤務,訪問 看護,外来勤務,外来勤務,休み ,外来勤務,訪問看護,オンコ... シリアライズクラス singleA problem.json singleA ScNurse 解テキスト クラスsingleAをJSON.Netでシリアライライズしたものが、 problem.json(UTF-8) となりScNurseにソケットを通してとして渡さ れます。 ScNurseは、求解数分のテキストをとして生成します。(UTF-8) singleAの役割 スケジュールナースⅡの場合、プロジェクトファイルと役割を兼ねて いるので、ソルバへのシリアライズとしては、やや冗長な処理になっ ています。ソルバと無関係な部分は、privateにしているので、そちら は見る必要がありません。(private部はシリアライズされません。) singleAは、ソースファイルsc_nurse.csで記述されています。Doxgen を見るとファイル数も多いのですが、その殆どは、singleAにユーザ 記述を設定させるためのGUI処理です。solverの設定の仕方として は、最終的に何がsinlgeAにセットされたかが問題ですので、 sc_nurse.cs上 singleAのメンバーセット方法を見れば十分かと思いま す。 problem.json生成(solve_page.cs) public bool make_problem() { { //Aug.03.2016 problem_server_string = form1.serialize_all();//シリアライズ if (problem_server_string=="") return false;//Aug.03.2016 StreamWriter sw; string path = Application.StartupPath + "¥¥problem.json"; System.Text.Encoding enc = new System.Text.UTF8Encoding(false);//UTF8変換 sw = new StreamWriter(path, false, enc);//BOMなしでないとパースエラーになる sw.Write(problem_server_string);//Aug.03.2016 sw.Close(); } return true; } form1シリアライズ部 Newtonsoft.Json.JsonSerializerSettings get_json_setting() { Newtonsoft.Json.JsonSerializerSettings settings = new Newtonsoft.Json.JsonSerializerSettings { Converters = { new CustomDateTimeConverter() }, Formatting = Newtonsoft.Json.Formatting.Indented };//, TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All }; return settings; } public string serialize_all() { Newtonsoft.Json.JsonSerializerSettings settings = get_json_setting(); bool success=true; try { SingleA.set_projectname(most_recentfile);//プロジェクト名設定 SingleA.update_version(); success &=SingleA.eval_macro(rm);//マクロ評価 if (!success ) return ""; } catch (Exception ex){ MessageBox.Show(ex.Message); return ""; } string Serialized = Newtonsoft.Json.JsonConvert.SerializeObject(SingleA, settings);//Json.NETのシリアライズ return Serialized; } 解読み込み部(solve_page.cs) public string Read_Solution(int I) { string solution_filename = ""; solution_filename += Application.StartupPath; solution_filename += "¥¥solution"; solution_filename += (I + 1).ToString();// solutions.get_nof_solutions().ToString(); solution_filename += ".txt"; try { TextFieldParser parser = new TextFieldParser(solution_filename, System.Text.Encoding.GetEncoding("UTF-8")); using (parser) { parser.TextFieldType = FieldType.Delimited; parser.SetDelimiters(","); // 区切り文字はコンマ ..... SingleA.get_schedules().label_conversion(Solution.members);//Shiftが同じでAnotherLabelが 予定入力で使われていたら予定入力に合わせる Solution.save_as_history(SingleA); SingleA.get_solutions().members.Add(Solution);//singleAインスタンスに解追加 ソケット受信部 private void ReadCallback(object obj)//ソケット受信(非同期) { try { using ( TcpClient client = (TcpClient)obj) { using (NetworkStream stream = client.GetStream()) { const int BUFF_SIZE = 100000;//受信バッファ byte[] readbuf = new byte[BUFF_SIZE]; int len; int sol_counter=1; while (true) { len = stream.Read(readbuf, 0, BUFF_SIZE); if (len <= 0) break; }else if (readbuf[len-1]!=0){//Agu.23.2015 We have more data on stream while (true) { int len1 = stream.Read(readbuf,len, BUFF_SIZE - 1 - len); if (len1 <=0) goto exit_loop; else { len += len1; if (readbuf[len - 1]==0) break; } } } ソケット生成部・受信スレッド生成部 client = new TcpClient(); string[] ar = server_ip_address.ToArray(); if (ar.Length == 0) { richTextBox1.Focus(); richTextBox1.AppendText("計算サーバが見つかりません。内部エンジンに切 り替えます。¥n"); return false; } richTextBox1.Focus(); richTextBox1.AppendText("計算サーバが見つかりました。接続します。¥n"); client.Connect(ar[0], server_port); richTextBox1.Focus(); richTextBox1.AppendText("計算サーバと接続しました。¥n"); send_tcp(write_string);//problem.jsonの送出 // 受信スレッドを作成・実行 Thread thread = new Thread(new ParameterizedThreadStart(ReadCallback)); thread.Start(client); connect_state = ConnectState.CONNECTED; return true;; ソケット受信続き string s = Encoding.UTF8.GetString(readbuf, 0, len); string[] stArrayData = s.Split('¥0'); for (int i = 0; i < stArrayData.Length;i++ ) { string str = stArrayData[i]; if (str.Length < 1) continue; if (str.IndexOf("SAT") >= 0 || str.IndexOf("UNSAT") >= 0)//解の切り出し { int rows = SingleA.get_active_staffs(); string path = ""; path += Application.StartupPath + "¥¥solution"; path += sol_counter.ToString(); path += ".txt"; path += ""; StreamWriter sw = new StreamWriter(path); sw.WriteLine(str); sol_counter++; sw.Close(); } else {//解でなければ求解状況報告 AppendText(str); } } } exit_loop: //切断されるとここにくる connect_state = ConnectState.CONNECTED_EXIT; stream.Close(); client.Close(); } } } catch (Exception ex) { connect_state = ConnectState.CONNECTED_EXIT; MessageBox.Show(ex.Message); } ソケット送信部 //Socket送信 void send_tcp(string write_string) { if (client != null) { NetworkStream stream = client.GetStream(); string send_string = "TAKAYUKI write_string;//32bytes byte[] writebuf = Encoding.UTF8.GetBytes(send_string); Array.Resize(ref writebuf, writebuf.Length + 1); writebuf[writebuf.Length - 1] = 0;//Null Terminal stream.Write(writebuf, 0, writebuf.Length); stream.Flush(); } } "+ 求解中止処理 private void button2_Click(object sender, EventArgs e) { #if USE_EXTERNAL_SERVER try { send_tcp("Abrot"); return; } catch (Exception ex) { } #endif singleA 構造図 日 設定群 シフト schedules 制約群 求解パラメータ solving_ parameters スタッフ column_ constraints date_objects date_object date_aggregates date_aggregate_class shift_objects shift_object shift_aggregates shift_aggregate_class group_properties group_property group_aggregates group_aggregate staff_properties staff_property column_constraints_group column_constraint row_ constraints row_constraints_group row_constraint pair_ constraints pair_constraints_group pair_constraint singleA 最低限設定が必要なオブジェクト群 date_objects 日 設定群 シフト date_object 既定オブジェクト群 ,days,target_year,target_month shift_objects shift_object staff_properties staff_property スタッフ数、日数 schedules 制約群 求解パラメータ solving_ parameters スタッフ その他は、インスタンスとしては 必要ですが、ブランクでも支障あ りません。initialize部参照 solving_parametersクラス 求解パラメータ public Dictionary<string, int> parameters =new Dictionary<string,int>(); public void initialize(singleA SingleA, System.Resources.ResourceManager rm) { parameters["NofCpus"]=1; //CPU数 parameters["N_of_solutions"]=1;//求解数 parameters["not_repeat_planned_errors"]=1;//予定エラーの再掲を防ぐ parameters["BestEffots"]=1; //最小化有効 parameters["HardTimeout"]=30; //ハードタイムアウト(秒) parameters["ErrorAnalysis"]=1; // エラー原因解析 parameters["SoftTimeout"]=10; // ソフトタイムアウト(秒) parameters["BestEffotsTimeout"]=5;//default:5 parameters["UseExternalConstraint"]=0;//言語制約使用 } ソフト制約設定 ソフト制約レベル1-7 public Dictionary<int, Dictionary<string, sw_int> > solving_map=new Dictionary<int,Dictionary<string,sw_int>>(); "column" ➡列 "row" ➡行 "planned" ➡予定 "ext" ➡外部 bool use = solving_map[level][s].use; int per_errors = solving_map[level][s].value; int total_allowerable_errors = solving_map[level][s].total_max_errors; 詳細仕様 ・Doxygen生成文書・ソースコードをご参照ください。 ・GUI各データグリッド(表)とsingleA内クラスは、ほぼ 一対一対応しています。 ・スケジュールナースⅡチュートリアル・マニュアルも併 せてお読みください。 Visual Studioプロジェクト ファイル群には、Visual Studio2015update3プ ロジェクトファイル、実行ファイル、DLL等が含まれます。 これにより、ほぼスケジュールナースⅡGUIの開発環境が再 現できます。(C#デバッガが使えます。)これを出発点とし て、貴社アプリインタフェースの開発が可能になります。 スケジュールナースⅡ(C#) ソケット 貴アプリ(Java,C#,Javascript,Python..) C#ソースの必要箇所 を移植 ScNurse 評価用外部サーバ(V PS Linux) ソルバ性能、インタフェースの 評価で、目途がたったら、貴ア ププラットフォームのLinu x/Windows・(32/64ビット) 評価用エンジンを提供します。 Visual Studio Project インストール 圧縮ファイルを次のフォルダに展開します。 ScNurseSDKを起動します。 ダブルクリック schedule_nurse2 プロジェクト 下図のようになります。 起動の確認 起動の確認を行います。 サーバからのメッセージを ご確認ください。 ビルドの確認 WindowsFormsApplication1.exe Exeファイルが次のフォルダに生成されたら成功です。 オンラインサポート ご要望があればオンラインサポートが可能です。その日の午前 中にメールを頂ければ、その日中に対応可能です。SKYPE で画面を共有しながらお話しが可能です。インストールの必要 ないSKYPE MEETINGでもお打合せが可能です。 評価期間 • 1か月です。1か月を過ぎると起動できなくなります。 • お申し出があった場合に3か月まで更新が出来ます 。ただし、2か月目以降は有償となります。 以上
© Copyright 2024 ExpyDoc