MiniZinc 제약 해결사 사용하여 매우 쉽게 cardinality constraints을 표현할 수 내장 sum()
기능 : 카디널리티 제약 조건이 충족카디널리티 제약
% This predicate is true, iff 2 of the array
% elements are true
predicate exactly_two_sum(array[int] of var bool: x) =
(sum(x) == 2);
경우에만, 수 경우 배열의 진정한 요소 부울 변수의 값은 지정된대로입니다. 부울은 합계를 계산하기 위해 정수 값 0
및 1
에 자동으로 매핑됩니다.
% This predicate is true, iff 2 of the array
% elements are true
predicate exactly_two_parallel(array[int] of var bool: x) =
let
{
int: lb = min(index_set(x));
int: ub = max(index_set(x));
int: len = length(x);
}
in
if len < 2 then
false
else if len == 2 then
x[lb] /\ x[ub]
else
(
let
{
% counter is modelled as a set of slices
% with 2 outputs each
% Encoding:
% 0 0 : 0 x true
% 0 1 : 1 x true
% 1 0 : 2 x true
% 1 1 : more than 2 x true
array[lb+1..ub] of var bool: t0;
array[lb+1..ub] of var bool: t1;
}
in
% first two slices are hard-coded
(t1[lb+1] == (x[lb] /\ x[lb+1])) /\
(t0[lb+1] == not t1[lb+1]) /\
% remaining slices are regular
forall(i in lb+2..ub)
(
(t0[i] == (t0[i-1] != x[i]) \/ (t0[i-1] /\ t1[i-1])) /\
(t1[i] == t1[i-1] \/ (t0[i-1] /\ x[i]))
) /\
% output of final slice must be 1 0 to fulfil predicate
(t1[ub] /\ not t0[ub])
)
endif endif;
질문 :
% This predicate is true, iff 2 of the array
% elements are true
predicate exactly_two_serial(array[int] of var bool: x) =
let
{
int: lb = min(index_set(x));
int: ub = max(index_set(x));
int: len = length(x);
}
in
if len < 2 then
false
else if len == 2 then
x[lb] /\ x[ub]
else
(
let
{
% 1-of-3 counter is modelled as a set of slices
% with 3 outputs each
array[lb+1..ub-1] of var bool: t0;
array[lb+1..ub-1] of var bool: t1;
array[lb+1..ub-1] of var bool: t2;
}
in
% first two slices are hard-coded
(t0[lb+1] == not(x[lb] \/ x[lb+1])) /\
(t1[lb+1] == (x[lb] != x[lb+1])) /\
(t2[lb+1] == (x[lb] /\ x[lb+1])) /\
% remaining slices are regular
forall(i in lb+2..ub-1)
(
(t0[i] == t0[i-1] /\ not x[i]) /\
(t1[i] == (t0[i-1] /\ x[i]) \/ (t1[i-1] /\ not x[i])) /\
(t2[i] == (t1[i-1] /\ x[i]) \/ (t2[i-1] /\ not x[i]))
) /\
% output 2 of final slice must be true to fulfil predicate
((t1[ub-1] /\ x[ub]) \/ (t2[ub-1] /\ not x[ub]))
)
endif endif;
이 구현은 조각 사이의 적은 라인/변수로 병렬 인코딩을 사용하고 있습니다 : 카운터 조각 세트로
나는 내 자신의 카디널리티 제약 조건을 구현 :h ome-grown 카디널리티 술어? 아니면 솔루션 속도면에서 의문의 여지없이 MiniZinc 구현이
sum()
입니까?
업데이트 : Gecode로 해석 백엔드를 사용하고
.
힌트를 보내 주셔서 감사합니다. 저는 주로 정수가 아닌 Boolean 변수를 다루고 있습니다. 링크는 정수 제약 조건을 참조합니다. –
@AxelKemper MiniZinc은 자동 강제 변환 기능을 사용합니다. 즉, 부울은 술어 나 함수에서 필요로하는 경우 부동 소수로 정수 및 정수로 사용할 수 있습니다. 귀하의 경우에 술어가 부울 인수로만 구성 될 때, 우리는 일반적으로 컴파일러가 부울 논리 형식으로 다시 제약 조건을 단순화하는 것을 신뢰합니다. Gecode에서 글로벌 제약 조건은 특수한 전파 자로 인해 더 잘 수행 될 수 있지만 생성 된 조건자는 (큰) 수의 전파자로 구성된다는 점에 유의하십시오. – Dekker