2020年12月29日火曜日

QMC1 Nurse Scheduling Benchmark

 Optimum 解に到達するまで8秒、Optimum証明まで23秒、Cplexは、5秒、Gurobiは、4秒でした。




2020年12月28日月曜日

GPost-B Nurse Scheduling Benchmark

 最適値に到達するまでの時間は、スケジュールナース7.7sec、Cplex 351sec、Gurobi 83secでした。



2020年12月27日日曜日

GPOST Nurse Scheduling Benchmark

 Cplex 206秒、Gurobi 30秒、スケジュールナース7秒でした。この例も、夜勤の4回連続を禁止した結果、2回から3回の連続となっています。欧米の殆どのベンチマークがほぼこのような形態となっています。




2020年12月23日水曜日

Azaiez Nurse Scheduling Benchmark

 SC3で6秒、Cplex9秒、Gurobi3秒でした。

下記の勤務パターンをみてお気づきかと思いますが、欧米の勤務パターンは、日本と全く異なります。基本的に、夜勤は12時間で、それが、2-3日続くパターンが一般的になっています。

クラッシックなベンチマークは、欧米の論文に由来しています。結果、殆どが下記のパターンと似通ったものになります。INRC1のパターンもそのようなパターンとなっています。

ベンチマークとしての問題は、欧米パターンに偏っていることです。もっと難しい問題は、色々ある、という風に力説したいと思います。




2020年12月18日金曜日

LLR Nurse Scheduling Benchmark

 Gurobi /Cplex共5秒程度、ScheduleNurse AL1では、19secでOptimum値(301)に達しますが、厳密解ではありません。AL4では、4secで厳密解となります。ちなみにGoogleORToolsで使われているCBCでは、Optimum値に到達するのが275秒、28000秒かけても、Optimum証明が出来ていません。一般的に、MIPソルバの世界では、商用ソルバとOpensource ソルバでは、相当な性能比となることは、よく知られており、100倍となることは、珍しくないというか普通に起こります。(それ故に商用ソルバの存在価値があるわけです。)



2020年12月14日月曜日

Millar-2Shift-DATA1.1 Nurse Scheduling Benchmark

 

Millar-2Shift-DATA1との違いは、よく分かっていません。どちらにしても1sec以内で解ける簡単なインスタンスです。

2020年12月13日日曜日

Millar-2Shift-DATA1 Nurse Scheduling Benchmark

 
このあたりから少し実用的なモデルになってきます。スケジュールナースでは、0.3秒、CPLEX/Gurobiでも同程度でした。



2020年12月12日土曜日

Musa Nurse Scheduling Benchmark

 これも古いです。シフトが2、2週間で小規模、パターンがほぼありません。ほぼ全体が基数制約です。こういったベンチは、MIPソルバが圧倒します。CPLEXで0.01secでOptimum証明完了です。

スケジュールナースⅢでは、Optimum値が出現するまで10sec,証明完了まで23secかかりました。






2020年12月11日金曜日

Ozkarahan nurse scheduling benchmark

1989年ということですので、最も古いNSP問題ということになりそうです。

現在では、0secで解ける問題です。

ptpmcrender.fcgi (europepmc.org)

驚くべきは、すでにこの時代から、個人毎のスタッフ契約体系になっていることで、土日働けない人の考慮がなされています。




import sc3

for person in [2]:
	clist=[]
	for day in AllDays:
		vlist=[]
		if day in Sat :
			if day +1 in AllDays :
				v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),sc3.GetShiftVar(person ,day+1,'Y'))
				vlist.append(v)
		if day in Sat :
			if day +1 in AllDays :
				v=sc3.And(sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y'))
				vlist.append(v)
		if day in Sat :
			if day +1 in AllDays :
				v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y'))
				vlist.append(v)
		if len(vlist) >= 1:
			clist.append(sc3.Or(vlist))
	sc3.AddSoft(sc3.SeqError(0,0,3, clist),'3_1',1)
for person in [3]:
	clist=[]
	for day in AllDays:
		vlist=[]
		if day in Sat :
			if day +1 in AllDays :
				v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),sc3.GetShiftVar(person ,day+1,'Y'))
				vlist.append(v)
		if day in Sat :
			if day +1 in AllDays :
				v=sc3.And(sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y'))
				vlist.append(v)
		if day in Sat :
			if day +1 in AllDays :
				v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y'))
				vlist.append(v)
		if len(vlist) >= 1:
			clist.append(sc3.Or(vlist))
	sc3.AddSoft(sc3.SeqError(0,0,3, clist),'4_1',1)
for person in [6]:
	clist=[]
	for day in AllDays:
		vlist=[]
		if day in Sat :
			if day +1 in AllDays :
				v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),sc3.GetShiftVar(person ,day+1,'Y'))
				vlist.append(v)
		if day in Sat :
			if day +1 in AllDays :
				v=sc3.And(sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y'))
				vlist.append(v)
		if day in Sat :
			if day +1 in AllDays :
				v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y'))
				vlist.append(v)
		if len(vlist) >= 1:
			clist.append(sc3.Or(vlist))
	sc3.AddSoft(sc3.SeqError(0,0,3, clist),'7_1',1)
for person in [7]:
	clist=[]
	for day in AllDays:
		vlist=[]
		if day in Sat :
			if day +1 in AllDays :
				v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),sc3.GetShiftVar(person ,day+1,'Y'))
				vlist.append(v)
		if day in Sat :
			if day +1 in AllDays :
				v=sc3.And(sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y'))
				vlist.append(v)
		if day in Sat :
			if day +1 in AllDays :
				v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y'))
				vlist.append(v)
		if len(vlist) >= 1:
			clist.append(sc3.Or(vlist))
	sc3.AddSoft(sc3.SeqError(0,0,3, clist),'8_1',1)
for person in [8]:
	clist=[]
	for day in AllDays:
		vlist=[]
		if day in Sat :
			if day +1 in AllDays :
				v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),sc3.GetShiftVar(person ,day+1,'Y'))
				vlist.append(v)
		if day in Sat :
			if day +1 in AllDays :
				v=sc3.And(sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y'))
				vlist.append(v)
		if day in Sat :
			if day +1 in AllDays :
				v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y'))
				vlist.append(v)
		if len(vlist) >= 1:
			clist.append(sc3.Or(vlist))
	sc3.AddSoft(sc3.SeqError(0,0,3, clist),'9_1',1)
for person in [12]:
	clist=[]
	for day in AllDays:
		vlist=[]
		if day in Sat :
			if day +1 in AllDays :
				v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),sc3.GetShiftVar(person ,day+1,'Y'))
				vlist.append(v)
		if day in Sat :
			if day +1 in AllDays :
				v=sc3.And(sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y'))
				vlist.append(v)
		if day in Sat :
			if day +1 in AllDays :
				v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y'))
				vlist.append(v)
		if len(vlist) >= 1:
			clist.append(sc3.Or(vlist))
	sc3.AddSoft(sc3.SeqError(0,0,3, clist),'13_1',1)


2020年12月10日木曜日

Real Nurse Scheduling Benchmarksの構想

 ベンチマーキングは、SchedulingBenchmarksとNurseSchedulingCompetitionⅡが現存しており、既に、結果についてはレポート済みです。

Benchmarks|What is Schedule NurseⅢ (nurse-scheduling-software.com)

後は、過去のOR関係の論文で言及があるものを集めたセットのみが残っています。これらをスケジュールナースで解いてみたいと思います。これらのプロジェクトとMPSファイルをGithubに集めてOneStopのベンチマーク集としたいと思います。MPSファイルを添付することで、MIPソルバー同士、あるいは、MIPソルバー対メタヒューリスティクスも論じ易くなるのではないかと思います。

また、日本の実際的なベンチもいくつか提供したいと思います。たとえば、シフト数が25を超えるものや、プリセプタ・プリセプテイ、等、これまでにない、しかし現場での実際的な問題を提供したいと思っています。

これらにより、Realなベンチマーキング集としたいと思います。(Githubなので、どなたでもForkしてPull Request出来ます。)

GitHub - sugawara-system/Schedule_Nurse3_Gallery





2020年12月9日水曜日

.htaccess のリダイレクトを廃止

 挙動不明な動きをするので、廃止しました。ブラウザのキャッシュをクリアすれば、リダイレクトすることはなくなります。

2020年12月8日火曜日

Date Aggregate Rep2/3/4/7/14とは?

 https://nurse-scheduling-software.com/knowledge_base/

に書きました。カレンダを見て頂いた方が早いです。私も使ったことはないのですが、例えば「特定の日基準の隔週」という集合を定義したいときに使うことを設計時意図していたと思います。GUIカレンダとSolver側に認識は、一致しているはずですが、確認したいときは、python で、

import sc3

だけ記述して、言語制約をオンして求めると、


とR2,R3,R4,R7,R14 Day集合を確認できます。Repは、132Dからのサポートになります。


2020年12月6日日曜日

SDK2のAWS ACOUNT ID Checkを廃止

 SDK2(Scheduling Solver Engine on Lambda function in AWS Development Kit 2)では、これまで、お客様固有のアカントしか動作できませんでしたが、この条件を緩和し、どのアカウントでも動作できるようにしました。ただし、期限は変わらず残ります。期限内に量産への移行をできればお願いいたします。

2020年12月5日土曜日

新しいシフトスケジューリング論文

保育士や、パートタイムについて論じています。

http://repository.nihon-u.ac.jp/xmlui/handle/11263/1659

未だあまり読み込んでいないのですが、具体データもあるので、スケジュールナースでモデル化したらどういう感じになるか、興味深いです。



2020年12月4日金曜日

ikegami benchmarkの評価

日本語サイトは、

スケジュールナース ホームページ 

に移動しました。


プロモーション用に最新のデータを採取しました。

Fast|What is Schedule NurseⅢ (nurse-scheduling-software.com)

GurobiとCplexのデータは、Optimumの値証明が完了するまでの時間です。GurobiとCplexは、結構差がついてしまいましたが、Gurobiの進歩が著しいということでしょう。

誤解のないようにお願いしたいのですが、このデータは、これらインスタンスに限ってのお話です。平均的な比較ではありません。

MIPソルバーの性能向上が著しくて、メタヒューリスティクスは、肩身が狭くなりつつはありますが、上記データが示すように全てMIPで済むという話には未だならないと思います。それぞれに得意不得意の領域があり、実務的・典型的ナーススケジューリング問題には、ScheduleNurseⅢ Algorithm1がMIPソルバーより良い結果を示すということであります。

それから、StateOfArtRosteringSolverとは、AutoRosterの4.34でこれは、多分昔とったデータと変わらないと思います。





2020年11月30日月曜日

英語サイト

 What is Schedule NurseⅢ (nurse-scheduling-software.com)

(日本語だとリダイレクトされます)

英語マニュアル


Video

英語マニュアルは、シフトは、プロの翻訳者の成果物をさらに、Grammerlyで書き直したものです。やはり、Passive構文の指摘が結構あり、正しい指摘に思えるものは直感的に直しました。
ユーザとPythonについては、プロの翻訳者に頼らず、DeepLとGrammerlyで作ったものです。以前にそういったツールなしにつくったものよりは良いような気がします。
また、日本の恥さらしになるかもしれないのですが、世界に問うてみたい気持ちの方が強いです。以前と違うのは、大手メーカの後追いではないということです。ニッチではあっても世界で唯一であることがささやかな誇りです。

2020年11月28日土曜日

インストール場所

 MSIXのインストール場所は、通常フォルダと異なり、書き込みをすることができません。

(作者である私自身もどこにインストールされたか分かりません。)

そうすると、problem.jsonの受け渡し、サンプルフォルダでのWriteが出来ないので、基点フォルダ別に設け

AppData→sugawara-systems→schedule_nurse→1.0.0.0

にしています。なので、インストール最初のフォルダは、ここになります。さらに、

英語版と日本語版でサンプルが異なりますので、上からさらに

Samples→Japanese→プロジェクトサンプル

でようやくサンプル場所に辿りつきます。

なお、AppDataは、通常隠しフォルダとなっているので、本来的に保存する場所ではないと思います。そのため、サンプルを保存する場合は、ドキュメントフォルダに移して保存してください。更新時に、名前を変えていても消去されるのではないかと思います。また、アンインストール時は、このフォルダは、消去されると思います。(未確認)




2020年11月27日金曜日

Hugoでサイトを構築

 https://www.wangchucheng.com/en/docs/eureka/

というテーマを拝借して構築しています。最初マークダウンをtyporaで記述するようなイメージを持っていたのですが、

hugo server

で、ローカルに起動中に、mdファイルを書き換えると、即差にupdateされることが分かりtyporaを使用する必要はありません。単純にテキストエディタで記述しながら、画面表示を確認できます。

製作中のSnapshotです。



2020年11月26日木曜日

.htaccessでリダイレクト

 日本語ブラウザを検出してリダイレクトするようにしました。

リダイレクトされないようにするには、ブラウザを日本語以外にするか、OSの言語設定を日本語以外にします。

以下で、切り替えています。



RewriteEngine On

  RewriteCond %{HTTP:Accept-Language} ^ja [NC]
  RewriteRule ^$ https://japanese.nurse-scheduling-software.com/ [L,R=301]



2020年11月25日水曜日

Githubで1MB以上のファイルが読み取れない

 1MBしか読み取れないのは、GetRawContentの仕様のようです。

blobsを使うと100MBまで出来るようになるよ、というご丁寧なエラーメッセージが出てきます。

.net core - How to retrieve and update a file > 1MB from/to master GitHub using Octokit.Net Git Data API within c# - Stack Overflow


131Cで問題を修正しました。


private Dictionary SHA_MAP = new Dictionary();
        
        public async void read_hiearachy()
        {
            try
            {
                SHA_MAP.Clear();
                var github = new Octokit.GitHubClient(new Octokit.ProductHeaderValue("IshisakaSample"));
                
                string owner = richTextBox1.Text.Trim();
                string repo = richTextBox2.Text.Trim();


               
                treeView1.Nodes.Clear();
                TreeNode rootNode = new TreeNode(repo);
                treeView1.Nodes.Add(rootNode); // ルート・ノードの追加

                
                string branch_str = richTextBox3.Text.Trim();
                var branch = await github.Repository.Branch.Get(owner, repo, branch_str);// "master");
                var contents = await github.Git.Tree.GetRecursive(owner, repo, branch.Commit.Sha);
                foreach (var v in contents.Tree)
                {
                    if (v.Path.Contains(".nurse3"))
                    {
                        if (v.Size >= 1024 * 1024)
                        {
                            SHA_MAP[v.Path] = v.Sha;
                        }
						if (Thread.CurrentThread.CurrentUICulture.DisplayName.Contains("日本語")){
                            if (v.Path.Contains("Japanese"))
                            {
                                rootNode.Nodes.Add(v.Path);
                            }
                        }else if (v.Path.Contains("English")){
                        	rootNode.Nodes.Add(v.Path);

                        }
                    }
                    Debug.WriteLine(v.Path, v.Type);
                }
                rootNode.Expand();
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }

        private void button1_Click(object sender, EventArgs e)
        {
            read_hiearachy();
        }

        
        private async void read(string filepath)
        {
            var github = new Octokit.GitHubClient(new Octokit.ProductHeaderValue("IshisakaSample"));
            string owner = richTextBox1.Text.Trim();
            string repo = richTextBox2.Text.Trim();
            if (SHA_MAP.ContainsKey(filepath))
            {
                string sha = SHA_MAP[filepath];
                var b64 = await github.Git.Blob.Get(owner, repo, sha);
                
                byte[] file=Convert.FromBase64String(b64.Content);
                
                form1.deserialize(file);

            }
            else
            {
                var file = await github.Repository.Content.GetRawContent(owner, repo, filepath);
                form1.deserialize(file);
            }

        }

2020年11月24日火曜日

appinstaller Webでの記載のしかた

そのまま、貼り付けるとXMLファイルとしてブラウザが認識してしまって上手くいきませんでした。

 https://docs.microsoft.com/en-us/windows/msix/app-installer/installing-windows10-apps-web

のようにすると、インストーラとして認識してくれるようです。downloadのページに貼り付けていますが、未だテスト中です。




2020年11月22日日曜日

英語プロジェクトと日本語プロジェクト

 日本語環境とそれ以外の環境で、作ったプロジェクト間では、互換がありません。プロジェクトが日本語由来かどうかは、作成時に決まります。その後、国を変更するということは想定していません。

これは、Date関係の定義を変えているために起きる現象です。例えば、日 →Sun、今月→ThisMonth と言った具体にDate表現が異なり、それをベースにDay集合を定義しているためで、基本的には、日本語環境で作ったプロジェクトを英語圏に持っていっても動きません。Pythonを使っていれば、確実にエラーとなるので、分りやすいですが、使っていなければ一見動いているように見えるプロジェクトも多いです。

無用なトラブルを避けるために、Githubサンプルも英語と日本語に分けて、参照できないようにしています。英語環境では、Englishフォルダ下しか見えません


日本語環境では、Japaneseフォルダ下しか見えません。


となります。



2020年11月21日土曜日

時間制約のVector化

 行制約時間制約についてVector化記述に対応しました。


時間制約は、ソフト制約がありません。ハード制約しかない唯一の制約になります。また、原因解析でも時間制約が原因とすることは、現状ありません。性能上も整数制約に比べれば、一概には言えないのですが、理屈的には、数倍以上遅くなることがありえます。

従い、

■出来る限り、整数制約を使って頂く

■ソフト制約化は、整数制約を併用する

といった対応が必要になります。

2020年11月20日金曜日

ZOOM MEETING 廃止

 諸事情によりZOOM MEETINGを廃止しました。また、購入ページをリニューアルしました。実質的には、何も変わっていませんが、有償・無償との違いを分かりやすくしました。

2020年11月19日木曜日

ConstraintEnableの改善

 例えば、月で制約を切り替えるとします。通常月は、


Special月は、

という制約にしたとします。この場合、OffDaysという名前がどちらにもありますが、一方のグループしかOnにしていないために、GUIには、一つの名前しか現れません。

<改善前>
Pythonで制約を切り替えた場合、GUIが把握しているOn/Offとは異なることがありえます。
その場合、GUIが把握しているOn/Offとソルバーのそれと齟齬が生じ赤マーキングになってしまうことがありました。

<改善後>
Pythonを使用した場合、Solverが認識しているOn/OffをGUIに返すようにして、SolverとGUIの認識を一致させるようにしました。その結果、赤マーキングはなくなりました。





2020年11月18日水曜日

数独問題の作成方法4x4 から100x100まで

 勤務表ソフトではありますが、数独を汎用的にプログラムできれば、GUIを拡張できる能力の強力な証明になるので、搭載pythonで汎用的に書き直してみました。100x100までは、動作を確認しました。GUIでは、100x100結果は、表示しきれないので、ExcelにExportさせた結果が以下です。簡易的ですが、一応各行列の和が各々5050になっていることを確認しました。

∵ n(n+1)/2=5050




Pythonソースは、以下が全ソースです。このソースは、数独サイズに依存しません。4x4でも、100x100でも同じソースでOKです。では、どうやってサイズを可変するかというと、GUI上で、スタッフ数、Day数、シフト数をGUIで定義しなおせばよいです。例えば、4x4の場合は、4人、4Days,4シフトを定義します。

<オリジナル問題の作り方>
1)ブランク状態(解が存在するなら適度な数字が入っていてもよい)で解を求めます。
2)解を予定に送ります。
3)適当な箇所をブランクにします。
4)解を求め2解目が存在しないことを確認します。
5)3)4)を気力が続く限り続け、2解目が存在するときに諦めて、その前の状態を問題として終了します。



数独の条件としては、1解しか存在しないことが条件となります。例えば、100x100で1ブランクでも作れば、1解しか存在しないので、超巨大ではあるけれども超簡単な数独問題となります。1解しか存在しない証明は難しいですが、スケジュールナースを活用すれば、簡単にチェック出来ます。

import sc3
import math

if math.sqrt(len(AllDays)) !=math.sqrt(len(shiftdef)):
    raise ValueError("AllDays and shiftdef are inconsistent")
blocks=int(math.sqrt(len(AllDays)))

for day in AllDays: #column
	for shift in shiftdef.keys():
		V=[]
		for person in A_Member_in_All:
			V.append(sc3.GetShiftVar(person,day,shift))
		sc3.AddHard(sc3.SeqLE(1,1,V),'')
for person in A_Member_in_All: #row
	for  shift in shiftdef.keys():
		V=[]
		for  day in AllDays:
			V.append(sc3.GetShiftVar(person,day,shift))
		sc3.AddHard(sc3.SeqLE(1,1,V),'')
for person in range(0,len(A_Member_in_All),blocks): #block
	for shift in shiftdef.keys():
		for  day in range(0,len(AllDays),blocks):
			V=[]
			for  i  in range(blocks):
				for  j in range(blocks):
					V.append(sc3.GetShiftVar(person+i,day+j,shift))
			sc3.AddHard(sc3.SeqLE(1,1,V),'')


2020年11月17日火曜日

年始年末の実装

 

今月が通常月の場合、今月の定義は以下になります。


このときSecondMonth(次月)は、空集合になります。


今月が年始を含む場合、今月の定義は、


このとき、SecondMonthは、


となります。thisyearsdatesは、上記に関わらず以下となり、


ThisYearsThisMonthを以下のように取得できます。



これを従来の制約上のThisMonthと置き換えれば、年末年始に依存しない期間とすることができ、メンテナンスフリーの実装とすることができます。Pythonによるコントロール切り替えも不要です。




2020年11月15日日曜日

Dr.Planning

 https://dmcommunity.org/challenge/challenge-apr-2020/

In a hospital, there has to be a doctor present at all times. In order to make sure this is the case, a planning is made for the next 7 days, starting on a monday. Each day consists of three shifts: an early shift, a late shift and a night shift.


Every shift needs to be assigned to a doctor. In total there are 5 doctors: every doctor has a list of available days, and some have special requirements. In general, the following rules apply:


■A doctor can only work one shift per day.

■A doctor should always be available for his shift (see table below)

■If a doctor has the night shift, they either get the next day off, or the night shift again.

■A doctor either works both days of the weekend, or none of the days.

■A planning should be made in which every requirement is fulfilled.


Name Available

Fleming Friday, Saturday, Sunday

Freud Every day early or late, never night

Heimlich Every day but neven the night shift on weekends

Eustachi Every day, every shift

Golgi Every day, every shift but at max 2 night shifts

という問題を解いてみます。

まずは、上の条件から、スタッフ数5人、シフト数 Early,Late,Night,PaidHolidayの4つ、

月曜から始まる1週間を考えればよいことが分かります。

■A doctor can only work one shift per day.

スケジュールナースは、Default状態でそうなっているので、何も記述する必要がありません。

■A doctor should always be available for his shift (see table below)

意味不明ですが、多分、Dr.毎、シフトは、条件があるのだと思います。テーブル参照。

■If a doctor has the night shift, they either get the next day off, or the night shift again.

Nightの後は、Nightかオフ(PaidHoliday)なので、その他のシフトを禁止すればよいことが分かります。他のシフトは、EarlyかLateしかないので、

Night→Early

Night→Late

を禁止すれば十分です。

■A doctor either works both days of the weekend, or none of the days.

週末の定義が不明ですが、土日と仮定すると、土日のうちの1日だけ働くことを禁止すればよいです。これは、排他的論理和(XOR)ですね。土曜日に働いたら日曜日禁止、日曜日に働いたら、土曜日禁止すれば、よいです。

■A planning should be made in which every requirement is fulfilled.

多分、全てのシフトで、1人以上(or 1人?)が必要だ、ということでしょう。列制約になります。

次にテーブル条件について考えます。

■Fleming Friday, Saturday, Sunday

金土日以外をPaidHolidayで予定を埋めてしまえばよいことが分かります。

■Freud Every day early or late, never night

夜勤以外というラベルを作って、全日予定を埋めます。

■Heimlich Every day but neven the night shift on weekends

夜勤以外というラベルを土日に埋め込みます。

■Golgi Every day, every shift but at max 2 night shifts

Nightシフト数を2以下に制限すればOKです。

非常に簡単なロジックで、実際的には、全然足りてないですが、スケジュールナースで行えば、多分世界最速で、モデル記述とグラフィック10解を得ることが出来ます。初見11分でした。(この文章を書いている時間の方が長い)


動画はこちら

https://youtu.be/pHYFd5IE0U0


2020年11月14日土曜日

競合調査

国際環境で、AWS LAMBDAで同じような機能を提供するVendorはいるのでしょうか?いるとすれば、競合になります。二つヒットしました。

https://www.optaplanner.org/

https://openrules.wordpress.com/2020/04/22/building-a-live-worker-scheduler/

OptaPlannerは、私が開発を始めたころからありました。100%JAVAで書かれているメタヒューリスティクスがベースになっています。ベルギーのGeoffrey De SmetさんがLeadであり論文や動画の投稿も沢山あります。オープンソースのビジネスモデルであり、RedHatがスポンサーのようです。

Openrulesは、毛色が変わっていますが、発想が面白いです。

2020年11月13日金曜日

言及されています

 日本の論文での言及は初めてではないかと思います。

https://www.jstage.jst.go.jp/article/pjsai/JSAI2020/0/JSAI2020_4Rin129/_pdf/-char/ja

スケジュールナースの目指している方向は、

1)求解速度

最適な解を求めるには、会話的に管理者の思いと、解の状況を見ながら、重みを調整します。そのためには、すぐに解が出ることが必要です。できれば、数秒、遅くても数十秒以内に実用的な解を提示できることが必要です。

2)超汎用性・柔軟性

 どのようなルールも記述できること。少なくとも、人間が作り出し運用しているルールを記述できない、ということがないこと。大体はGUIベースで、非常にレアな制約でもPythonで記述可能です。

3)ルール化・モデル化支援

Integer Programmingのリテラシーが有るならモデル化してMIPに落とせるでしょう。しかし、毎月制約は変化するのが常です。しかも、モデルをつくり運用するのは、IT技術者でもITリテラシーに通じた人でもありません。制約の世界では、モデル化とメンテナンスの時間の方が、解を求める時間よりはるかにかかります。本来は、生産性向上が目的なのですが、

■自動化コスト=モデル化(ルール記述・開発)+求解時間+メンテナンスコスト

■手書きコスト=求解時間(作成時間)

フェアな比較では、モデル化とメンテナンスコストを論ずるべきと思いますが、そのような論文は、見たことがありません。実際、SC3の開発においては、この部分に多くの時間を注きました。https://patents.google.com/patent/JP6364638B1/ja


4)アカデミックとのGapを埋めること

http://www.econ.upf.edu/~ramalhin/Referencias/Kellog_2007.pdf

5)ベンチマークでトップ性能を維持すること

https://www.nurse-scheduling-software.com/tutorial/benchmarks.htm

こちらプレスリリースをご覧ください。

開発から7年、上記の目的は、ほぼ達成できたと考えます。今後は、国際的にも主要な地位を目指すことを目標にしたいと思います。

そこで、次の二つの方向性を考えたいと思います。

1)デスクトップアプリのフリー化

 ソフト自体にコストはかかりません。勤務表作成と月々のメンテナンスのみ有償になります。

2)特定業務・形態に絞ったアプリ化

 企業向けにスケジューリングソルバ(AWS LAMBDA FUNCTION)を提供

国・分野を絞ることで、汎用性・柔軟性をなるべく維持しながら、より簡便なGUIを装備していただき自動最適化を実現。


2020年11月12日木曜日

年末年始対応の構想

年末年始は、次月にはなりますが、年始期間まで含んで休みを設定するところが多いと思います。

 年末年始をPythonを使ってダイナミックに記述するのは、良いアイデアですが、年始の期間を新たに定義しなければいけないのが、どうも美しくない、と思いました。そこで、次月(SecondMonth)というのをPredifineすることにしました。


こうすると、制約終了日が決まれば、「次月」は、自動的に決まります。(通常月は、空集合になります。)今月部であって AND 次月部でない 部分が通常月の制約に対応します。これは、ユーザ定義で、集合演算で求めます。

こうすると、

1)年末年始では、制約終了日がSpecial

2)年末年始期間を絶対定義

以上の2点だけが、通常月と変わる部分で、後は、PythonがDynamicに制約を切り替えるので、面倒な部分を隠蔽してくれます。



2020年11月10日火曜日

スタッフ名の空白

 は、今まで除去してきたのですが、英語環境では、さすがにまずいという結論となり、空白を許容することにしました。スタッフ名以外は、空白を除去しているのは従来通りです。



2020年11月8日日曜日

Hyper-Vでテスト

 Windows Sandboxを導入して拡張子msix/msibundleのテストを行いたかったのですが拡張子を認識してくれませんでした。仕方なく、Windows10 1903ISOを持ってきて(VisualStudio OS付ライセンス)Hyper-Vでテストすることにしましました。しかし、OSインストールが、動きませんでした。

同じ現象で、はまった方がおられましたので、その通りにしたら動きました。

https://qiita.com/saeki4n/items/b712cd5c9359f3b54dae

Hyper-Vの良いところは、Snapshotを取って、任意の時点に戻れることです。OS起動状態でスナップショットを取っておけば、何時でもCleanインストール状態から再現できます。


インストーラの拡張子は、見慣れないmsix/msibundleになります。Win10では、ダブルクリックするとインストーラが起動します。

下図は、Hyper-V上でのインストール時のスナップショットですが、デジタル著名が効いて、あの忌まわしいウィルスまがいのメッセージが出てきません。スケジュールナースでのサポートは、Windows10 x64のみVersion 1903以降になります。(現在は2004です。)


インストール後の起動は、デスクトップアイコンはありません。さ行のメニューからの起動となります。

英語化が11月一杯かかるので、リリースは、11月Endを予定しています。




2020年11月7日土曜日

Signing Tool Error 0x8007000B

対処方法 

https://docs.microsoft.com/en-us/windows/msix/package/signing-known-issues

  • Run Eventvwr.msc
  • Open the event log: Event Viewer (Local) -> Applications and Services Logs -> Microsoft -> Windows -> AppxPackagingOM -> Microsoft-Windows-AppxPackaging/Operational
  • Find the most recent error event


2020年11月6日金曜日

Code Signing Certificateを取得しました

 取得までの流れ

1)DUNS NUMBERの取得

2)代理店の選択

メールでいくつか英語を使う場面はありましたが、コールバックも日本語選択可能ですし、

英語メールに抵抗なければ、最安でも問題ないと思います。

3)Sectigoとのやり取り 日本語でした

法人番号を提示の依頼がありましたが、個人業者なのでない、と回答しました。

4)コールバック 日本語を選択

 コンピュータによる自動コールバックで、6桁の数字を記します。

5)ORDER #xxxx - Your Code Signing Certificate is ready!

 が着ます。リンクアドレスをインストールするPC上で、IEを起動します。

SHA128/256を選択します。期限は、下のように2年です。(26400円代理店で異なる)

How to Export Your Code Signing Certificate

に従ってExportします。

注意事項
1)ドメイン情報は結局使いませんでした。
2)Win10上でもIEが必要です。Edgeや、Cromeでは動作しません。IEは、WIN10の中に多分defaultでありました。
3)心配していたコールバックも、日本語を選択し、CallNowを選択すれば、すぐかかってきます。
4)DUNS NUMBERの取得で、東京商工リサーチで登録済みでも海外サイトに反映するには、2週間位かっかってしまうとのことで、直接海外にReflectしてくれるように指示(代理店)がありました。メールを送ると、すぐ登録したよ、とのReplyがありました。
5)更新の概念はないそうです。2年を選択したので、2年経つまえに再度取得する必要があります。
6)一番時間がかかった壁は、DUNS NUMBER取得と海外でのReflectです。DUNS NUMBER取得済みであるならば、1週間で可能と思いますが、取得していない場合は、1ヶ月見る必要があると思います。

以上、個人業者がコードサイニング証明書を取得する でした。






て、以下の手順で、pcxをExport

2020年11月5日木曜日

DeepLとGrammarly

 マニュアルの英文化を進めています。基本的には、DEEPLで日本文、DEEPL出力をGrammerlyに入力して校正していきます。全体で300ページ位あり、最初は、プロの翻訳者にお願いしていたのですが、上記方法に落ち着きました。DEEPL、翻訳者原稿どちらをGrammarlyに入力しても、受動態(PassiveVoice)の指摘が多いです。しっくりしないときは、自分で書き直して、再度Grammarlyにかけたり、元々の日本文から手直しします。Grammarlyは、有償版です。DeepLとGrammarlyの組み合わせが最強と実感しています。

以上の手順をもっと厳格に進めている方もおられました。

https://qiita.com/doikoji/items/d3b818dc2937bc34d579


2020年11月4日水曜日

Copt 1.43の評価

BarrirerSolver(内点法)を実装したとのことで評価してみました。

WSL1では、MACアドレスは、変わらなかったのですが、今回環境はWSL2になっており、前回のMAC ADDRESSとは見かけ上異なるものとなり、ライセンスで弾かれてしまいました。

しかたなくWindowsVersionでの評価です。WindowsVersionでは、コマンドラインで_Underbarがスキップされてしまうので、これも仕方なくファイル名を手動で変更しました。結果は、こちらです。

確かに、大規模インスタンスでは、顕著に速くなっていることが分かります。ただし、Defaultでマルチスレッドになるらしくスレッド数は、4です。また、内点法では、Simplexみたいに、Resolveで速くなることもないのでその辺は割り引いて考える必要があります。




2020年10月31日土曜日

ソフトウェアグローバリゼーション入門

 と アプリケーションをつくる英語

いう本を購入しました。また、アプリでは、

■Notepad++

■Typora

の実装を覗いてみました。Typoraは、イギリスの個人事業者だそうで、Open Sourceではありません。ちなみに、。Read.mdは、Typoraで書くことにしました。

2020年10月30日金曜日

サンプルプロジェクトの英語化

 チュートリアルサンプルを英語化しながらやっていますが、色々問題があり、C#をいじっています。訳語、スペース、フォント 等、なるべく日本語に影響しないように作業しています。



2020年10月29日木曜日

プロジェクトファイルのGithub化

 MSIX化で、そのサンプルフォルダをどこにしようか迷いました。ソフトが自由に書けるのは、恐らくAPPDATAですが、隠しフォルダとなっているために、あまりよろしくありませんし、そのような例も探したのですが見当たらず、やはりAppDataを主体にするのはよくない、という結論に達しました。

インストール初期には、あったほうが便利なので一応アタッチしておきますが、更新のしやすさ、ユーザ同士のプロジェクト交換等の便宜を考えると、ダウンロードを主体にしたほうがよさそうだ、という結論に達しました。

なので、プロジェクトの読み込みメニューを追加しました。

https://github.com/sugawara-system/Schedule_Nurse3_Gallery



Github固定ですが、Owner,Repository,Branchを指定するようにしたので、defaultレポジトリに限らず、Githubで公開されているレポジトリであれば、スケジュールナース3で開くことができます。

ダブルクリックすると、プロジェクトを開くことが出来ます。読み込んだ後、プロジェクトは、メモリにありますが、ファイルとしては、未だ存在しないので、名前をつけて適当な場所にプロジェクトを保存してから、求解してください。





2020年10月27日火曜日

ホームページ移転のお知らせ

 ホームページを移転します。新しいサイトは、https://japanese.nurse-scheduling-software.com/ になります。日本語版をサブドメイン、旧アドレスは英語として、Hugoで新しく作る予定です。

現在リンク部の改定作業中です。


2020年10月26日月曜日

C#ソースのDoxygen化

 problem.jsonに関わる部分のDoxygen化を行っています。英語と日本語です。この作業に2日位を見込んでいます。

方法としては、VisualStudioのエディタ上で、Intelisense →コメント挿入 で行っています。

2020年10月25日日曜日

MSIX化その2

<コマンドラインを使う>

 はまりました。VisualStudio上の「公開」を行うと、C#系は、DLL郡をきっちりアタッチしてくれるのですが、C++系プロジェクトについては、EXEだけで、読み込んでいるDLLをアタッチしてくれません。どうにも方法が分からなかったのですが、「公開」+コマンドラインで構築していくことで、必要なファイルをアタッチすることができました。

具体的には、makeappx コマンドとsigntool コマンドを次のようにコンソール上で動かします。最終的には、msixbundleというフォルダが出来ますが、これは、xx_bundleというフォルダに集められたサイニングしたmsixの集合体を指しているようです。最終的に、msibundleにもサイニングして完成になります。


makeappx pack /l /h sha256 /m "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\ForBundle\AppxManifest.xml" /f obj\x64\Release\main_map_tak.txt /o /p "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\WapProjTemplate1_1.0.30.0_x64.msix"
signtool.exe sign /fd sha256 /a "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\WapProjTemplate1_1.0.30.0_x64.msix"
makeappx pack /r /l /h sha256 /m "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\ForBundle\AppxManifest.xml" /f obj\x64\Release\split.scale-100.map.txt /o /p "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\WapProjTemplate1_1.0.30.0_scale-100.msix"  
signtool.exe sign /fd sha256 /a "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\ForBundle\AppxManifest.xml" /f obj\x64\Release\split.scale-100.map.txt /o /p "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\WapProjTemplate1_1.0.30.0_scale-100.msix"  
makeappx pack /r /l /h sha256 /m "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\ForBundle\AppxManifest.xml" /f obj\x64\Release\split.scale-125.map.txt /o /p "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\WapProjTemplate1_1.0.30.0_scale-125.msix"
signtool.exe sign /fd sha256 /a "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\ForBundle\AppxManifest.xml" /f obj\x64\Release\split.scale-125.map.txt /o /p "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\WapProjTemplate1_1.0.30.0_scale-125.msix"
makeappx pack /r /l /h sha256 /m "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\ForBundle\AppxManifest.xml" /f obj\x64\Release\split.scale-150.map.txt /o /p "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\WapProjTemplate1_1.0.30.0_scale-150.msix"  
signtool.exe sign /fd sha256 /a "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\ForBundle\AppxManifest.xml" /f obj\x64\Release\split.scale-150.map.txt /o /p "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\WapProjTemplate1_1.0.30.0_scale-150.msix"  
makeappx pack /r /l /h sha256 /m "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\ForBundle\AppxManifest.xml" /f obj\x64\Release\split.scale-400.map.txt /o /p "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\WapProjTemplate1_1.0.30.0_scale-400.msix"
signtool.exe sign /fd sha256 /a "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\ForBundle\AppxManifest.xml" /f obj\x64\Release\split.scale-400.map.txt /o /p "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\WapProjTemplate1_1.0.30.0_scale-400.msix"

copy "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\WapProjTemplate1_1.0.30.0_x64.msix" obj\x64\Release\WapProjTemplate1_1.0.30.0_Bundle\*.*
copy "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\WapProjTemplate1_1.0.30.0_scale-100.msix" obj\x64\Release\WapProjTemplate1_1.0.30.0_Bundle\*.*
copy "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\WapProjTemplate1_1.0.30.0_scale-125.msix" obj\x64\Release\WapProjTemplate1_1.0.30.0_Bundle\*.*
copy "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\WapProjTemplate1_1.0.30.0_scale-150.msix" obj\x64\Release\WapProjTemplate1_1.0.30.0_Bundle\*.*
copy "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\bin\x64\Release\WapProjTemplate1_1.0.30.0_scale-400.msix" obj\x64\Release\WapProjTemplate1_1.0.30.0_Bundle\*.*
 
makeappx bundle /d obj\x64\Release\WapProjTemplate1_1.0.30.0_Bundle\ /bv 1.0.30.0 /o /p "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\AppPackages\WapProjTemplate1_1.0.30.0_Test\WapProjTemplate1_1.0.30.0_x64.msixbundle"  
signtool.exe sign /fd sha256 /a "C:\Users\sugaw\Documents\Visual Studio 2019\Projects\schedule_nurse_ver3\WindowsFormsApplication1\WapProjTemplate1\WapProjTemplate1\AppPackages\WapProjTemplate1_1.0.30.0_Test\WapProjTemplate1_1.0.30.0_x64.msixbundle"  

最初のmakeappx で、/f obj\x64\Release\main_map_tak.txt を行っているのがミソで、オリジナルのmain_map.txtから変更しています。 https://stackoverflow.com/questions/47586254/what-are-mapping-files-for-building-against-uwp-centennial-projects-and-how-do


また、VisualStudio上のプロジェクトだけではなく、スケジュールナース上のサンプルフォルダについても、同様にmapping fileで記述することになります。サンプルフォルダは、いくつかの階層になっていて、ファイル数も多いし、今後のバージョンでも変わっていくので、プロジェクトフォルダ内のファイルをファイルに書き出すプログラムをつくりました。 

using System;
using System.IO;
using System.Text;

namespace ConsoleApp1
{
    class Program
    {
        private static void DirectoryDisplay(StreamWriter w,string sourceDirName,string subname="")
        {
            // Get the subdirectories for the specified directory.
            
            
            DirectoryInfo dir = new DirectoryInfo(sourceDirName);
            //Directory.SetCurrentDirectory(ss2);

            if (!dir.Exists)
            {
                throw new DirectoryNotFoundException(
                    "Source directory does not exist or could not be found: "
                    + sourceDirName);
            }

            DirectoryInfo[] dirs = dir.GetDirectories();

           

            // Get the files in the directory and copy them to the new location.
            FileInfo[] files = dir.GetFiles();
            foreach (FileInfo file in files)
            {
                string s = "\"" + file.FullName + "\" " + "\""+subname+"\\"+file.Name+"\"";
                w.WriteLine(s);
                
            }

            // If copying subdirectories, copy them and their contents to new location.
            
            {
                foreach (DirectoryInfo subdir in dirs)
                {
                    
                    DirectoryDisplay(w,subdir.FullName,subname+"\\"+subdir.Name);
                }
            }
        }


        static void Main(string[] args)
        {
            if (args.Length <= 0) return;
            string dir=args[0];
            var utf8_encoding = Encoding.GetEncoding("utf-8");

            StreamWriter w = new StreamWriter("test.txt",false,utf8_encoding);
            string ss = Directory.GetCurrentDirectory();
            string ss2 = Path.Combine(ss, "..\\");
            string ss3 = Path.Combine(ss2, dir);
            DirectoryDisplay(w,ss3, dir);
            Console.WriteLine("Hello World!");
        }

    }
}
 

スケジュールナースが起動したとき、defaultのインストールフォルダ内に、"プロジェクトサンプル"がないときは、プログラムの実行パスを基点としたプロジェクトサンプルフォルダの内容をコピーするようにしています。

以上で、証明書以外のMSIX化が可能になりました。

<TIPS> MSIX化したパッケージフォルダは、C:Program Files\WindowsApps内にありますが、アクセス権限が強いのか見ることができません。なので、丸ごとWindowsAppsの内容をコピーして、サンプルフォルダ等のアタッチするべきファイルがアタッチされているか、確認しています。

2020年10月24日土曜日

DUNS NUMBERを取得しました

東京商工リサーチの検索では、見つかるものの海外のDUNS NUMBERサーチでは、未だ反映されていないようです。(→海外で反映されるまで2週間程かかるようです。)

 ともあれ、DUNS NUMBER取得と、DomainTransfer作業が完了したので、コードサイニング申請を行いました。業者さんは、日本で一番安いところを選びました。


2020年10月23日金曜日

Cutoisさんの新しい論文

 http://www.schedulingbenchmarks.org/matsp/

で、新しい論文とベンチマークデータセットを見ました。SC3のタスクの概念そのものを使用していますが、残念ながらCoverを達成するための、Shiftを求める問題になっています。シフト時間帯そのものが変数になっているため、シフト時間帯が固定のSC3では、解くことができません。(正確には、そのようなモデリングを意図していないので効率よく解くことはできません。)

残念です。

いつも思うのですが、学術ベンチマークは、役に立たないものを多くてその多くは、人工的に作られています。実際の現場の勤務表ベースのベンチマークというのは、ほとんどないというのが実情です。が、唯一、池上先生が出されているベンチマークは、現場で実際に作られている勤務表がベースになっています。

https://www.nurse-scheduling-software.com/tutorial/benchmarks.htm

このベンチマークの特徴は、全てがソフト制約で記述されていることです。ソフト制約は、

探索空間を削減しません。ですから、ある意味特殊なベンチマークになっていて、実際、ここ数年においても格段の進歩を遂げているGurobi/Cplexでも解くのに、時間がかかる問題です。

2020年10月22日木曜日

DUNSナンバー登録申請2

 屋号を記した通帳コピーを提出したのですが、「スガワラシステムズ」 になっていて、申請の「菅原システムズ」 と違うという指摘をされました。青色申告書のコピーでもよい、と言われて、提出したのですが、「税務署の受領印がないと、駄目」ということでした。

電子申請の場合は、受信通知がはんこの代わりということで、e-Taxソフトにログインして、受信通知をスナショして、送ったら、それでOKということになりました。明日交付予定です。個人事業者で、コードサイニング取得の壁の第一は、DUNSナンバー取得と感じました。



2020年10月19日月曜日

DUNSナンバー登録申請

 個人事業者でも登録可能です。FAQを見ると、屋号の入った通帳があればよさそうです。また、登録申請のWEB画面でも、FAXのない方は、xxxを入れろと親切です。しかし、書類は、なぜかFAXで送る必要があります。コピー機にFAXはついていますが、電話線を引き込むのも面倒なので、秒速FAXを導入しました。送信Onlyでもよく、ポイントチャージ制で、200円からチャージできます。これで十分です。

2020年10月18日日曜日

コードサイニング

コードサイニングとは

 https://qiita.com/Chitama/items/915abc7b872b1e086800

認証局情報

https://www.nda.co.jp/memo/codesigning/index.html

ということで、申請の前にDUNS登録とDomain整備が必要になります。


Domainは、4つ所持しているのですが、名前が載っているドメインは、長年使っていたドメインであり、そのドメインの管理業者と連絡がつかなくなっていました。

消費者センタ、総務省等、手を尽くしましたが、結局届け出のTELにも出ないということで埒が明かず、カナダの上位管理会社(Registrar)と交渉し、ようやくAuthCodeを出してもらい、ドメインを移転することが出来ました。ドメインは移転したのですが、WEBデータ等整備していなかったので、コピーしメールサーバ設定その後DNSを切り替えてドメインの完全切り替え完了となります。従い、

1)DUNS登録

2)Domain整備 whois情報更新

(怪我の功名なのですが、最近は個人情報をさらさなくても独自ドメイン出来ますよ、と謳っている業者さんもあるのですが、名前をさらすことが証明につながる場合もあるということです。)

3)申請

コールバックは、夜中に英語で起こされるのはたまらないので、日本の代理店にしようと思います。

4)コールバック


を経て、ようやくコードサイニングが完了する予定です。その間に、MSIX用のコードに変更する作業を行います。

11月EndにMSIX版に移行を目指そうと思います。


2020年10月17日土曜日

MSIX

 今までインストール時の残念なメッセージが出るのを防止するには、ストアアプリ化するしかないと思っていたのですが、その認識は間違いであることが分かりました。MSIXという新し形式を使い、別にコードサイニングを取得すれば、ストアアプリ化する必要はないことが分かりました。今後の方針としては、

■インストーラをMSIXにする

■コードサイニングを取得維持する

■ソフト本体は無料とする (ライセンス期限を撤廃します)

■Win10 64bit版のみサポート(ビルド1903以降)

しようと思います。MSIX化後は、制約設定・メンテナンス・サポート・コンサルティングが必要な方のみ有償とする予定です。ストアアプリ化はキャンセルします。

MSIXについては、マイクロソフトのビデオを見ながら勉強しているのですが、出てくるエンジニアの方は、Nativeと思われる方はむしろ少なく、インド・フランスその他多様な人達が働いている、米国は本当に懐の深い国だと思いました。

この年にして、AWS LAMBDA, Docker, MSIX と次々に新しい技術を習得しています。最も役立っているのは、Qiitaですが、最後は、やはりStackOverflow 等の英語情報に行き着きます。  



2020年10月16日金曜日

国際祝日対応再び

前に書いた祝日ライブラリは、振り替え休日が定義されていないことが分かってドロップしました。そこで、下記で言及されているライブラリを採用することにしました。

ただし、javascriptなので、C#では、そのままでは、動作しません。そこで、
次のように、オフラインで、2035年までJSONを吐かせてそれをファイルとして搭載することにしました。
#!/usr/bin/env node

/**
 * draw tree of supported countries, states, regions
 */
function country_draw(stream,hd,country,country_name,state,state_name,region,region_name){
  hd.init(country)
    
    var holidays=hd.getHolidays(2015)
    for (y=2016;y< 2035 -="" 10="" 1="" :="" console.dir="" console.log="" const="" countries="" countrieslen="" country="" country_code="" country_name="" d="" date-holidays="" date="" draw="[" dt.getdate="" dt.getmonth="" dt="new" else="" for="" foreach="" function="" hd="new" holiday.substitute="" holiday.type="=" holiday="" holidays1="hd.getHolidays(y)" holidays="" i="" if="" m="" maxarraylength:="" maxarraylength="" msec="" n="" null="" object.keys="" of="" ountries:="" public="" public_holidays.push="" public_holidays="" region="" region_code="" region_name="" slice="" state="" state_code="" state_name="" str="" stream="" substitute_holidays.push="" substitute_holidays="" t="" tree="" util.inspect="" util="" var="" y="dt.getFullYear();"> {
    const d = (i === countriesLen ? draw[1] : draw[0])
    //console.log(d + country + ': ' + countries[country] + '\n')
    const hd = new Holidays()
    if (i!=0) console.log(",");
    country_draw(stream,hd,country,countries[country],"","","","")
    const states = Holidays().getStates(country)
    if (states) {
      const statesLen = Object.keys(states).length - 1
      Object.keys(states).forEach((state, j) => {
        let d = (i === countriesLen ? draw[3] : draw[2])
        d += (j === statesLen ? draw[1] : draw[0])
        //console.log(d + state + ': ' + states[state] + '\n')
        console.log(",");
   	country_draw(stream,hd,country,countries[country],state,states[state],"","")

        const regions = Holidays().getRegions(country, state)
        if (regions) {
          const regionsLen = Object.keys(regions).length - 1
          Object.keys(regions).forEach((region, k) => {
            let d = (i === countriesLen ? draw[3] : draw[2])
            d += (j === statesLen ? draw[3] : draw[2])
            d += (k === regionsLen ? draw[1] : draw[0])
            //console.log(d + region + ': ' + regions[region] + '\n')
	console.log(",");
   	country_draw(stream,hd,country,countries[country],state,states[state],region,regions[region])

          })
        }
      })
    }
  })
}
module.exports = tree

if (module === require.main) {
    console.log("{'members':[\n")
  tree(process.stdout)
  console.log("]\n")
  console.log("}\n")
}

定義済み曜日の祝をクリックするとComboboxが出現します。
国だけではなくて、米国のようにState、さらにRegionまで必要な場合もあるんですね。

2020年10月15日木曜日

UI Debug

 API Gateway呼び出しでは、慣れないawait/asyncを使っています。その際、UIでのデバッグでは、こちらを参考にしています。

https://qiita.com/ken_hamada/items/501b164374667319d270

A)背景の一番後ろが、DebugViewというツールで、C#のデバッグ出力です。
B)2番目が、UIをループされているプログラムで、上記サイトの電卓操作のプログラムを改造してスケジュールナース用の求解ボタンを叩いています。AWSのLambdaのコールドスタートタイミングに絡んでいそうなので、数分待って叩くループにしています。
C)3番目が、同作者のツールでAutomationIDを拾ってくれます。開発環境はリモートデスクトップでつながった、マイクもDisplayもないマシンでそのままでは、動かなかったので、音声入力のC#ソースは、カットしています。

なぜか、リモートデスクトップを最小化するとスリープに入るためか、B)がクラッシュしてしまいます。が、最小化しないで、画面の片隅に置いておけば大丈夫なようです。


2020年10月14日水曜日

Grammerly Premium を導入

 今まで無料版を使っていたのですが、Premiumに移行しました。DeepLとの併用で、かなり作業効率がよさそうです。楽しく英文を添削してくれます。






練習を兼ねてSDK2.1 Nurse Scheduling Solver AWS Lambda Engineの動画を作ってみました。

https://www.youtube.com/watch?v=UBkmB0LYVUc&feature=youtu.be