2016-10-24 16 views
0

私はminizincで最初の制約プログラミングを試みています。私はnスロットとn人で、それぞれのスロットに別々の人が割り当てられたスケジュールを作成しようとしています。私はを使用して、alldifferent()を使用してスケジュールをモデル化し、各スロットに異なる人物を確保しています。 サイズnの別々のarray以下のように、namesは、自分の名前が含まれています:どのように私は名前から値によってschduleを制約することができます別の配列のMinizinc制約

% Pseudo enum 
set of int: NameIndex = 1..2; 
int: Forename = 1; 
int: Surname = 2; 

int: n = 4; % Number of slots and people 
set of int: slots = 1..n; 

array[slots, NameIndex] of string: names = [| "John", "Doe" 
              | "Ann", "Jones" 
              | "Fred", "Doe" 
              | "Barry", "Doe" |];     
% The schedule 
array[slots] of var slots: schedule; 

% Every person is scheduled: 
include "alldifferent.mzn"; 
constraint alldifferent(schedule); 

% How to constrain by a value from names, say alphabetic order by forename. 
% Want to compare each value in schedule to the next one. 
%constraint forall (i in 1..n-1) (names[schedule[i],Forename] < names[schedule[i+1],Forename]); 

solve satisfy; 

output [show(i) ++ ": " ++ show(names[schedule[i], Forename]) ++ " " ++ show(names[schedule[i], Surname]) ++ "\n" 
    | i in slots] 
% should be: 
% | i in schedule] 

?上記の私の(壊れた)の例ではforall制約がコメント解除されているとき、私は(Minizinc IDEを使用して)取得:

in call 'forall' 
in array comprehension expression 
    with i = 1 
in binary '<' operator expression 
in array access 
cannot find matching declaration 

私は宣言が見つからないことではない理解するまで、エラーに従ってください。出力ブロックshow()は、schdule値から配列にインデックスを付けると、非常にうれしい名前の値になります。

私には何が欠けていますか?名前をモデル化するより良い方法はありますか?私は人々の追加の属性に名前を拡張し、追加の制約を作成したいと考えています。私はモデルと私の全面的な制約の両方がかなり素朴であると確信しています!

答えて

0

問題は、MiniZincは文字列をあま​​りサポートしていないことです。あなたの例に特有のものです。文字列を比較するサポートはありません( "<")。

つまり、var文字列をサポートする計画がいくつかあります(つまり、文字列を決定変数として使用する)が、リリースされる時点の正確な状態はわかりません。

はここで非常に簡単な修正だが、それはいくつかの前処理が必要です。

1)それぞれの名前の(順序)インデックス含む新しい配列を作成します。

array[slots] of int: names_ix = [4, % John Doe 
            1, % Ann Jones 
            3, % Fred Doe 
            2, % Barry Doe 
            ];     

2)への発注制約を変更しますその後、[あなたが名前の各文字が(「VaRのINT」の行列に)整数に変換する必要があり、より複雑なバリエーションがあります。この新しい配列

constraint 
    forall (i in 1..n-1) (
     names_ix[schedule[i]] <= names_ix[schedule[i+1]] 
    ); 

を使用し、整数の集合としての単語が順序付けされていることを要求する。これは非常に乱雑な傾向があることに注意してください。例えば、異なる長さの文字列を扱うなどです。

+0

それはそれを説明します!前処理は問題ではない。私は、文字列をサポートするCPソルバーはほとんどないと推測しています(このような[検索結果]から)(https://arxiv.org/abs/1608.03650))? – aejh

+0

「MiniZinc with Strings」という論文では、従来のCPソルバのvar文字列の最初の実装について説明しています(Gecodeに関連する実験的実装がありますが、公式にはリリースされていません)。いくつかの専用の文字列ソルバーがありますが、文字列をサポートする傾向がありますが、従来のグローバル制約ではvar int:sではサポートされません。 – hakank