tsp1.gms : 여행하는 세일즈맨 문제 - 1

설명

이것은 일련의 여행하는 세일즈맨의 첫 번째 문제입니다.
문제. 이 문제에서는 먼저 과제를 해결합니다.
슬롯 게임의 완화로 인한 문제. 이 솔루션의 하위 둘러보기
감지되어 인쇄됩니다. 그런 다음 하위 투어는 다음을 통해 제거됩니다.
절단(하위 투어로 솔루션을 제거하는 제약 조건).

참고: 여기서는 비대칭 슬롯 게임를 다룹니다. 대칭인 경우
      각 주기마다 2개의 컷을 추가할 수 있습니다.
      뒤로.

추가 정보는 다음에서 확인할 수 있습니다.

/modlib/adddocs/tsp1doc.htm

소형 모델 유형 :MIP


카테고리 : 슬롯 게임 모델 라이브러리


메인 파일 : tsp1.gms   다음을 포함합니다: br17.inc

$title 여행하는 외판원 문제 - 1개(TSP1,SEQ=177)

$onText
이것은 여행하는 세일즈맨 시리즈의 첫 번째 문제입니다.
문제. 이 문제에서는 먼저 과제를 해결합니다.
슬롯 게임의 완화로 인한 문제. 이 솔루션의 하위 둘러보기
감지되어 인쇄됩니다. 그런 다음 하위 투어는 다음을 통해 제거됩니다.
절단(하위 투어로 솔루션을 제거하는 제약 조건).

참고: 여기서는 비대칭 슬롯 게임를 다룹니다. 대칭인 경우
      각 주기마다 2개의 컷을 추가할 수 있습니다.
      뒤로.

추가 정보는 다음에서 확인할 수 있습니다.

/modlib/adddocs/tsp1doc.htm

Kalvelagen, E, GAMS를 사용한 모델 구축. 곧

de Wetering, AV, 개인 통신.

키워드: 혼합 정수 선형 계획법, 여행하는 외판원 문제, 반복
          서브투어 제거, 컷 생성
$offText

$eolCom //

$include br17.inc

* 이 간단한 알고리즘의 경우 문제가 너무 어렵습니다.
* 따라서 처음 6개 도시만 고려합니다.
i(ii) / i1*i6 /를 설정합니다.

* 옵션. MIP 솔버가 전역 최적값을 찾는지 확인하세요.
옵션 optCr = 0;

모델 할당/목적, rowsum, colsum/;

z를 최소화하는 mip를 사용하여 할당을 해결합니다.

* 투어 찾기 및 표시
t '투어' / t1*t17 /를 설정합니다.
abort$(card(t) < 카드(i)) "세트 t가 너무 작을 수 있습니다.";

매개변수 투어(i,j,t) '하위 투어';

싱글톤 세트
   from(i) '항상 하나의 요소, 즉 from city를 포함합니다.'
   next(j) '항상 하나의 요소, 즉 to city를 포함합니다.'
   tt(t) '항상 하나의 요소, 즉 현재 하위 투어를 포함합니다.';

Visited(i) '도시를 이미 방문했는지 여부에 대한 플래그'를 설정합니다.

* 초기화
from(i)$(ord(i) = 1) = 예;    // 첫 번째 요소를 켭니다.
tt(t)$( ord(t) = 1) = 예;    // 첫 번째 요소를 켭니다.

루프(나,
   next(j)$(x.l(from,j) > 0.5) = 예;    // x.l(from,j) = 1인지 확인하면 위험합니다.
   투어(from,next,tt) = 예;             // 테이블에 저장
   방문(from) = 예;                  // 'from' 도시를 방문한 것으로 표시
   from(j) = next(j);
   if(sum(visited(next),1) > 0, // 이미 방문한 경우...
      tt(t) = tt(t-1);
      loop(k$(not Visited(k)), // 새로운 하위 투어의 시작점을 찾습니다.
         from(k) = 예;
      );
   );
);

전시 투어;

* 컷을 추가하여 하위 투어 제거
* 하위 투어가 있는지 감지하는 논리는 유사합니다.
* 위 코드에
cc / c1*c100 / 설정;  // 최대 100컷까지 허용

별칭(cc,ccc);

세트
   curcut(cc) '현재 컷은 항상 하나의 요소'
   allcuts(cc) '총 컷수';

매개변수 cutcoeff(cc, i, j);

방정식 절단(cc) '동적 절단';

cut(allcuts).. sum((i,j), cutcoeff(allcuts,i,j)*x(i,j)) =l= 카드(i) - 1;

모델 tspcut / 목표, rowsum, colsum, cut /;

curcut(cc)$(ord(cc) = 1) = 예;

스칼라 괜찮습니다.

루프(ccc,
   from(i) = ord(i) = 1;      // 첫 번째 도시부터 초기화
   방문(i) = 아니오;
   알았어 = 1;
   loop(i$((ord(i) < 카드(i)) and ok), // 마지막 도시는 무시될 수 있습니다.
      next(j) = x.l(from,j) > 0.5;           //다음 도시 찾기
      방문(from) = 예;
      from(j) = next(j);
      ok$sum(방문함(다음),1) = 0;           // 하위 투어를 감지했습니다.
   );
   break$(ok = 1); // 완료: 하위 투어 없음

   // 컷 소개
   cutcoeff(curcut, i, j)$(x.l(i,j) > 0.5) = 1;
   // 다음은 일반적인 경우에 필요하지만 슬롯 게임에는 필요하지 않습니다.
   // cutcoeff(curcut, i, j)$(x.l(i,j) < 0.5) = -1;
   allcuts(curcut) = 예;      // 이 컷을 세트에 포함
   커컷(cc) = 커컷(cc-1);  //다음 요소를 얻는다
   z를 최소화하는 mip를 사용하여 tspcut을 해결합니다.
   tspcut.solPrint = %solPrint.quiet%;
);

* 올바른 순서로 솔루션 인쇄
xtour '순서된 투어'를 설정합니다.
from(i) = ord(i) = 1;      // 첫 번째 도시부터 초기화
방문(i) = 아니오;
알았어 = 1;

루프(t$확인,
   next(j) = x.l(from,j) > 0.5;     //다음 도시 찾기
   xtour(t,from,next) = 예;
   방문(from) = 예;
   from(j) = next(j);
   ok$sum(방문함(다음),1) = 0;     // 하위 투어를 감지했습니다.
);

옵션 xtour:0:0:1;
xtour,x.l을 표시합니다.

abort$(card(allcuts) = 카드(cc)) "너무 많은 컷이 필요함";