2016-10-24 1 views
0

저는 minizinc로 첫 제약 프로그래밍을 시도하고 있습니다. 나는 n 개의 슬롯과 n 명의 사람들로 각 슬롯에 다른 사람을 할당하여 일정을 잡으려고합니다. 나는 array of var int을 사용하여 각 슬롯에 다른 사람을 보장하기 위해 alldifferent()을 사용하여 일정을 모델링했습니다. 크기 n의 별도의 array, names는 다음과 같이 자신의 이름이 포함되어 있습니다 :다른 배열의 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] 

가 어떻게 이름과 값으로 schdule을 제한 할 수 있습니까? 위 내 (깨진) 예는 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()의 값은 이름에서 꽤 행복하게 배열에 인덱스 할 때 값이됩니다.

무엇이 누락 되었습니까? 이름을 모델링하는 더 좋은 방법이 있습니까? 사람들의 추가 '속성'으로 이름을 확장하고 추가 제약 조건을 만들기를 희망합니다. 나는 모델과 나의 모든 제약이 아주 순진하다고 확신한다!

답변

0

문제는 MiniZinc이 문자열을 많이 지원하지 않는다는 것입니다. 귀하의 예와 관련이 있습니다. 문자열 비교를 지원하지 않습니다 ("<").

그렇다면 var 문자열 (예 : 결정 변수로 문자열 사용)을 지원할 계획이 있지만 출시 될 정확한 상태를 알 수는 없습니다.

여기 아주 간단한 수정입니다하지만 몇 가지 전처리가 필요합니다

1) 각 이름의 (순서) 인덱스를 포함하는 새로운 배열을 만듭니다

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

2)의 순서 제약 조건을 변경을 이 새로운 배열을 사용

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

[이 있습니다 ("var에 INT"의 매트릭스) 정수로 이름에서 각 문자를 변환해야 더 복잡한 변형, 그리고 다음 정수의 모음 인 단어를 주문해야합니다. 이것은 상당히 엉뚱한 경향이 있습니다. 예를 들어 길이가 다른 문자열을 처리하는 경우가 있습니다.]

+0

이렇게 설명 할 수 있습니다! 전처리는 문제가되지 않습니다. 나는 문자열을 지원하는 CP 해결사가 거의 없다고 생각합니다 ([검색 결과]와 같은) (https://arxiv.org/abs/1608.03650))? – aejh

+0

논문 "MiniZinc with Strings"는 전통적인 CP 솔버에서 var 문자열의 첫 번째 구현에 대해 설명합니다 (Gecode에서 관련 실험 구현이 있지만 공식 출시되지는 않았습니다). 일부 전용 문자열 해석기가 있지만 문자열을 지원하는 경향이 있지만 기존의 전역 제약 조건이있는 var int :가 아닙니다. – hakank