2017-09-17 4 views
1

Minizinc 구문과 관련하여 간단한 질문이 있습니다.Minizinc,지도 또는 사전 데이터 구조를 만드는 방법

rates_index_0 = array2d(1..3, 1..501, [ 15, 20, 23, .... 
rates_index_12 = array2d(1..3, 1..501, [ 21, 24, 27, .... 
... 

참고 : -

인덱스 번호는 그 격차 (> 20 예, 12)가 다음과 같이 파일 .dzn 내 입력, 2 개 dimentional 배열 (약 최대 30 배열)의 집합을 포함 선언

내 모델에서는 변수의 값에 따라 이러한 배열 중 하나를 사용해야합니다. 공통 프로그래밍 언어에서는지도 또는 사전 데이터 구조를 사용하여이를 해결할 것입니다. 그러나 Minizinc에서 나는 다음과 같은 방법으로이 하드 코딩 오전 :

function var int: get_rate(int: index, var int: load, int: dc_size) = 

     if index == 0 then 
      rates_index_0[dc_size, load] 
     else if index == 12 then 
      rates_index_12[dc_size, load] 
     else if index == 16 then 
      rates_index_16[dc_size, load] 
     else if index == 20 then 
      rates_index_20[dc_size, load] 
     else 
      assert(false, "unknown index", 0) 
     endif endif endif endif; 

이 코드를 가진 하나의 명백한 문제는 내가 모델에게 내가 입력을 변경할 때마다 변경해야한다는 것입니다. 이 코드를 일반적인 방식으로 코딩하는 더 좋은 방법이 있습니까?

감사합니다.

답변

3

map-structure는 더 추상적 인 방식으로 특정 유형의 입력을 배열에 매핑하는 기능에 지나지 않습니다. 따라서 맵은 배열과 함수로 대체 될 수 있습니다. (차이점은 직접 함수를 정의해야한다는 것입니다)

나머지를 시작하기 전에 모델이 일반적으로 빠르게 컴파일되면 함수없이 트리플 배열을 사용해보십시오. rates_index = array3d(0..60, 1..3, 1..501, [ 15, 20, 23, ..... 이렇게하면 더 많은 메모리가 소모되지만 모델을보다 유연하게 만들 수 있습니다.

지도 구조를 사용하는 일반적인 방법은 입력 (이 경우 정수)을 배열의 색인 및 정수에 매핑하는 함수 map_index을 정의하는 것입니다. 즉, 오른쪽 레벨 배열을 정의하여 rates_index = array3d(0..nr_arrays, 1..3, 1..501, ....을 지정할 수 있습니다. 즉, get_rates의 내용은 rates_index[map_index(index), dc_size, load]이 될 수 있습니다. 퍼팅

function int: map_index(int: index) = 
    if index == 0 then 
     0 
    else if index == 12 then 
     1 
    else if index == 16 then 
     2 
    else if index == 20 then 
     3 
    else 
     assert(false, "unknown index", 0) 
    endif endif endif endif; 

각 인덱스에 대한 배열 번호를 포함하는 별도의 배열을 생성하여 동적으로 만들 수 있습니다 그러나, -1 :

당신의 if-then-else 문의 다른 버전을 포함하는 것이 가장 간단한 형태의 기능 map_index 자체 사용할 수없는 모든 배열에 대해 예를 들어 매핑은 다음과 같습니다 : array[0..20] of int: mapping = [0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 2, -1, -1, -1, 3];. map_index 함수는 다음과 같이 동적으로 정의 될 수 있습니다.

function int: map_index(int: index) = 
    mapping[index]; 
+0

좋아요. 컴파일 시간과 메모리 사용에 대한 진술을 명확히 해 주시겠습니까? array3d (0..60, 1..3, 1..501)는 60 array2d (1..3, 1..501)보다 많은 계산/메모리 리소스를 사용합니까? 당신의 솔루션을 이해했습니다. 기본적으로 배열 2ds를 하나의 3d로 병합 한 다음 인덱스를 매핑합니다. 유일한 단점은 데이터가 인간에게 더 이해하기 어렵다는 것입니다. 그러나 당연히 모델을 바꾸지 않아도됩니다. 감사! – kirbo

+2

나는 당신에게 요점이 있다고 생각한다! 메모리 소비에 관해서는 컴파일 된 3d 배열보다 2 차원 배열이 더 많은 메모리를 차지하지 않습니다. 그러나 변환 단계를 수행하고 싶지 않고 3d 배열에서 2 차원 배열이 아닌 여분의 (빈) 배열을 추가하도록 선택하면 큰 메모리 오버 헤드가 발생할 수 있습니다. – Dekker

+0

, 감사합니다! – kirbo