2016-11-23 3 views
1

私は変数の配列とそれらの間の線形制約のリストを持っています。各変数について、有効な値の開始リストを含むセットがあります。 Minizincを使用して、これらの開始値のセットを制約を満たすことができるものだけに減らすにはどうすればよいですか?各変数が取ることができるすべての値を特定します

私が達成しようとしているものを実証するための簡単な例:

array[1..2] of var int: xy; 
array[1..2] of set of int: xyvalid = [ {1, 5, 7}, 0..9 ]; 

constraint forall(i in 1..2)(xy[i] in xyvalid[i]); 
constraint xy[1] + xy[2] = 7; 

私はxyのためのすべてのソリューションsolve satisfyアイテムやプリントでこれを実行すると、私は(削除水平線で)取得する:

[1, 6] 
[5, 2] 
[4, 3] 
[3, 4] 

私はは何とかVARセットの配列を取得することですたい何、この場合には[ {1, 3, 4, 5}, {2, 3, 4, 6} ]に等しくなることを、xypossibleそれを呼び出します。 xypossible[1]の可能なすべての値に対して、有効な解を生成する値がxypossible[2]であり、その逆の場合、すべてのセットの合計カーディナリティを最大にするように解くという一連の制約を定義することができます。 xypossibleしかし、私の実際のデータは数百の変数のスケールで潜在的に数十の線形の制約があり、コードを書くのは面倒で実行するのが面倒です。

モデルとして使用する方法がない場合は、ソルバーが固有のジョブを実行する際に有効な値を特定した結果、情報を取得する方法がありますか?

+0

var int:xyのセットの配列[1..2]でモデリングしようとしましたか?あなたはセットを見つけようとしています。 – Kobbe

+0

私は最終的にそうするつもりだと思っていますが、適切な量のデータがあれば、アレイを効率的に作成するためのモデルの指定方法はわかりません。 – ConMan

答えて

1

xy [1]の可能な値は{1,5,7}であるため、結果は[{1,5,7}、{0,2,6} "xyvalid"配列で;そうでなければ、私は何かを逃しているに違いありません。...

あなたが望むように動作するかもしれないモデルはここにあります。最良のソリューションを選別するためには最大限の目的が必要ですが、

z = array1d(1..2 ,[{1,5,7}, {0,2,6}]); 
    ---------- 
    z = array1d(1..2 ,[{1,7}, {0,6}]); 
    ---------- 
    z = array1d(1..2 ,[{5,7}, {0,2}]); 
    ---------- 
    z = array1d(1..2 ,[7..7, 0..0]); 
    ---------- 
    z = array1d(1..2 ,[{1,5}, {2,6}]); 
    ---------- 
    z = array1d(1..2 ,[1..1, 6..6]); 
    ---------- 
    z = array1d(1..2 ,[5..5, 2..2]); 
    ---------- 
    z = array1d(1..2 ,[{}, {}]); 
    ---------- 
    ========== 

(これらのいくつかは、いくつかの追加の制約によって除去されている可能性)

% the domains of the two variables 
array[1..2] of set of int: xyvalid = [ {1, 5, 7}, 0..9 ]; 

% the result sets 
array[1..2] of var set of 0..9: z; 

% ensure that the largest solution is picked 
solve maximize card(z[1]) + card(z[2]); 

constraint 
    % get the domains of each variable set 
    forall(i in 1..2)(z[i] subset xyvalid[i]) /\ 
    % ensure that for all valid values in z[1] are in z[2] given 
    % that j + k = 7 
    forall(j in z[1]) (
     exists(k in z[2]) (j + k = 7) 
    ) 
    /\ 
    % and ensure that all valid values in z[2] are in z[1] 
    forall(k in z[2]) (
     exists(j in z[1]) (j + k = 7) 
    ) 
    ; 

結果が最大化目標がなければ、その後

z = array1d(1..2 ,[{1,5,7}, {0,2,6}]); 

で、8つのソリューションが存在することになります

私の個人的なアプローチはおそらくあなたのバリアントを使用して、いくつかの外部プログラムを介して値を返す。

注:一部のCPシステムでは、ラベル付けする前に(つまり、適切な有効な値を見つけるために)決定変数のドメインを印刷することができます。しかし、MiniZincにはこの機能がありません。そして、私はそれを逃す。

注2:決定変数のドメインを与えるdom()関数をテストしましたが、動作させることができませんでした。

+0

これをお探しいただきありがとうございます!私はこれまでのところあなたの答えを見逃しましたが、私ができる時にはそれをもっと徹底的に読んで、私がそれから何を集めることができるかを見ていきます。 – ConMan

関連する問題