설명
이것은 일련의 여행하는 세일즈맨의 첫 번째 문제입니다.
문제. 이 문제에서는 먼저 과제를 해결합니다.
슬롯 게임의 완화로 인한 문제. 이 솔루션의 하위 둘러보기
감지되어 인쇄됩니다. 그런 다음 하위 투어는 다음을 통해 제거됩니다.
절단(하위 투어로 솔루션을 제거하는 제약 조건).
참고: 여기서는 비대칭 슬롯 게임를 다룹니다. 대칭인 경우
각 주기마다 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)) "너무 많은 컷이 필요함";