설명
일반 할당 슬롯 커뮤니티는 라그랑지안 이완을 통해 해결됩니다.
객관식 제약 조건을 이중화하고 해결함으로써
나머지 배낭 하위 슬롯 커뮤니티.
이 슬롯 커뮤니티에 대한 데이터는 Martello에서 가져왔습니다.
최적의 값은 223이고 최적의 솔루션은 다음과 같습니다.
1 1 4 2 3 5 1 4 3 5, 여기서
열 1과 2에서 첫 번째 행의 변수는 1과 같습니다.
3열에서 네 번째 행의 변수는 1과 같습니다...
소형 유형 모델 :MIP rmip
카테고리 : 슬롯 커뮤니티 모델 라이브러리
메인 파일 : gapmin.gms
$title 일반 할당을 위한 라그랑지안 완화(GAPMIN,SEQ=182)
$onText
일반적인 할당 문제는 Lagrangian Relaxation을 통해 해결됩니다.
객관식 제약 조건을 이중화하고 해결함으로써
나머지 배낭 하위 문제.
이 문제에 대한 데이터는 Martello에서 가져왔습니다.
최적의 값은 223이고 최적의 솔루션은 다음과 같습니다.
1 1 4 2 3 5 1 4 3 5, 여기서
열 1과 2에서 첫 번째 행의 변수는 1과 같습니다.
열 3에서 네 번째 행의 변수는 1과 같습니다.
Martello, S 및 Toth, P, 배낭 문제: 알고리즘 및 컴퓨터
구현. 존 와일리와 아들들, 치체스터, 1990.
Guignard, M 및 Rosenwein, M, 향상된 이중 기반 알고리즘
일반화된 할당 문제. 운영 연구 37(1989), 658-663.
--- 원래 모델 정의
키워드: 혼합 정수 선형 계획법, 완화된 혼합 정수 선형 계획법
프로그래밍, 일반 과제 문제, 라그랑지안 이완, 배낭
$offText
$eolCom //
$sTitle 원본 모델 정의
세트
나는 '자원'
j '항목';
변수
x(i,j) 'i를 j에 할당'
z '총 할당 비용';
이진변수 x;
방정식
용량(i) '자원 가용성'
choice(j) '할당 제약.. 항목당 하나의 자원'
defz '총 비용 정의';
매개변수
a(i,j) '항목 j에 의한 자원 i의 활용'
f(i,j) '자원 i에 항목 j를 할당하는 비용'
b(i) '사용 가능한 자원';
용량(i).. sum(j, a(i,j)*x(i,j)) =l= b(i);
선택(j)..sum(i, x(i,j)) =e= 1;
defz.. z =e= sum((i,j), f(i,j)*x(i,j));
모델 할당 '원래 할당 모델' / 용량, 선택, defz /;
* Martello 모델 데이터
세트
나는 '자원' / r1*r5 /
j '항목' / i1*i10 /
xopt(i,j) '최적 할당' / r1.(i1,i2,i7),r2.i4, r3.(i5,i9), r4.(i3,i8), r5.(i6,i10) /;
테이블 a(i,j) '항목 j에 의한 자원 i의 활용'
i1 i2 i3 i4 i5 i6 i7 i8 i9 i10
r1 12 8 25 17 19 22 6 22 20 25
r2 5 15 15 14 7 11 14 16 17 15
r3 21 24 13 24 12 16 23 20 15 5
r4 23 17 10 6 24 20 15 10 19 9
r5 17 20 15 16 5 13 7 16 8 5;
테이블 f(i,j) '자원 i에 항목 j를 할당하는 비용'
i1 i2 i3 i4 i5 i6 i7 i8 i9 i10
r1 16 26 30 47 18 19 33 37 42 31
r2 38 42 15 21 26 11 11 50 24 19
r3 48 17 14 22 14 18 47 32 17 42
r4 22 32 28 39 37 23 25 12 44 17
r5 31 42 31 40 16 15 29 31 44 41;
매개변수 b(i) '사용 가능한 자원' / r1 28, r2 20, r3 27, r4 24, r5 19 /;
$onText
* 데이터를 확인하고 싶다면
* MIP 문제를 해결하세요. 이것은 단지 확인일 뿐입니다.
할당.optCr = 0;
mip를 사용하여 z 최소화 할당을 해결합니다.
if(sum(xopt, x.l(xopt) <> 1),
abort '*** 이 솔루션에 문제가 있습니다.', x.l, xopt);
$offText
$sTitle 완화된 문제 정의 및 하위 기울기 최적화
* 라그랑주 하위 문제 정의
* 동적 집합을 사용하여 해결할 배낭을 정의합니다.
세트
id(i) 'i의 하위 집합을 정의하는 데 사용되는 i의 동적 버전'
iter '하위 경사 반복 인덱스' / iter1*iter20 /;
별칭(i,ii);
매개변수
w(j) '라그랑지 승수'
improv '이전 반복에 비해 라그랑지안 경계가 개선되었습니다.';
변수 zlrx '느슨한 목표';
방정식
knapsack(i) '동적 세트의 용량'
defzlrx 'zlrx의 정의';
배낭(id).. sum(j, a(id,j)*x(id,j)) =l= b(id);
defzlrx.. zlrx =e= sum((id,j), (f(id,j) - w(j))*x(id,j));
모델 pknap / 배낭, defzlrx /;
스칼라
target '목표 목적 함수 값'
알파 '단계 조절기' / 1 /
규범 '슬랙스의 규범'
step '하위 기울기의 단계 크기' / na /
zfeas '가장 잘 알려진 해에 대한 값 또는 유효한 상한'
zlr '라그랑주 목적값'
슬롯 커뮤니티 '라그랑주 목적값'
zlbest '현재 최적의 라그랑지안 하한'
count '개선 없는 반복 횟수'
'카운트 카운터 재설정' / 5 /
tol '종료 허용 범위' / 1e-5 /
상태 '외부 루프 상태' / 0 /;
매개변수
s(j) '여유 변수'
Report(iter,*) '반복 로그'
xrep(j,i,*) 'x 반복 보고서'
srep(iter,j) '슬랙 보고서'
wrep(iter,j) '반복 보고서';
* 초기 라그랑지 승수 계산
* 초기 승수를 찾는 방법에는 여러 가지가 있습니다.
* 초기 승수의 선택은 매우 중요합니다.
* 전반적인 성능. 완화된 문제의 한계
*는 승수를 초기화하는 데 자주 사용됩니다. 또 다른 선택
*는 단순히 승수 0으로 시작하는 것입니다.
* 'default'를 원하는 솔버로 바꾸세요.
옵션 mip = 기본값, rmip = 기본값;
파일 결과 '반복 보고서 작성' / 솔루션 /;
put results '사용된 솔버: RMIP = ' system.rmip /
' MIP = ' system.mip /;
* 초기 승수를 얻기 위해 완화된 문제를 해결
* 서로 다른 솔버는 서로 다른 이중 솔루션을 얻습니다.
* 이는 초기 승수 세트가 0인 것만큼 좋지 않습니다.
rmip를 사용하여 z를 최소화하는 할당을 해결합니다.
put / 'RMIP 목적값 = ', z.l:12:6 /;
if(할당.modelStat = %modelStat.optimal%,
status = %modelStat.optimal% // 모든 것이 정상입니다.
그렇지 않으면
'*** 완화된 MIP가 최적이 아님'을 중단하고,
' 하위 그라데이션 반복 없음', x.l;
);
xrep(j,i,'초기') = x.l(i,j);
xrep(j,i,'최적') = 1$xopt(i,j);
매개변수 wopt(j) '최적의 승수 세트'
/ i1 35, i2 40, i3 60, i4 69, i5 21
i6 49, i7 42, i8 47, i9 64, i10 46 /;
zlbest = z.l;
* RMIP 듀얼 사용
w(j) = 선택.m(j);
* 최적의 듀얼을 사용
* w(j) = wpt(j);
* 0 시작점 사용
* w(j) = 0;
* zlbest = 0;
put // 'zlbest 목적값 = ', zlbest:12:6;
put // "할당 제약 조건에 대한 이중 값"/ ;
loop(j, put / "w('",j.tl,"') = ", w(j):16:6 ";";);
* zfeas 값이 필요합니다.
* 다음과 같이 유효한 상한을 계산할 수 있습니다.
zfeas = sum(j, smax(i, f(i,j)));
put // 'zfeas 빠르고 더티 바운드 obj value = ', zfeas:12:6;
'선험적 상한'을 표시합니다, zfeas;
$onText
zfeas 값을 계산하는 또 다른 대안은 다음과 같습니다.
갑민을 B-B로 풀고 그만하자
처음에는 0-1개의 가능한 솔루션을 찾았습니다.
다음과 같이 gapmin.optCr = 1을 사용합니다.
할당.optCr = 1;
할당.solPrint = %solPrint.quiet%;
!!!
mip를 사용하여 z 최소화 할당을 해결합니다.
zfeas = min(zfeas,z.l);
'최종 zfeas' 표시, zfeas;
'B-B에 의한 휴리스틱 솔루션' 표시, x.l, z.l;
put / 'zfeas IP 솔루션 경계 목적 값 = ', zfeas.l:12:6;
$offText
put // / '반복 새 바운드 이전 바운드 규범 abs(슬롯 커뮤니티-zf)'/;
* 그런 다음 두 값 중 더 작은 값을 zfeas로 유지합니다.
pknap.optCr = 0; // 글로벌 솔루션 요청
pknap.solPrint = %solPrint.quiet%; // 모든 솔루션 출력을 끕니다.
*=========================================================================*
* *
* 하위 그라데이션 루프의 시작 *
* *
*=========================================================================*
id(i) = 아니오; // 처음에는 비어 있음
개수 = 1;
알파 = 1;
디스플레이 상태;
loop(iter$(status = 1), // 즉, 상태가 1인 동안 반복합니다.
* 겹치지 않는 배낭을 풀어 라그랑주 하위 문제를 해결합니다.
* 문제. 동적 집합 id(i)의 사용에 유의하세요.
* 현재 배낭 설명자를 포함합니다.
zlr = 0;
루프(ii,
아이디(ii) = 예; // ID가 비어 있다고 가정
zlrx를 최소화하는 mip를 사용하여 pknap을 해결합니다.
zlr = zlr + zlrx.l;
아이디(ii) = 아니요; // 세트를 다시 비워 둡니다.
);
개선 = 0;
슬롯 커뮤니티 = zlr + sum(j, w(j));
improv$(슬롯 커뮤니티 > zlbest) = 1; // 슬롯 커뮤니티이 zlbest보다 나은가요?
zlbest = 최대(zlbest,슬롯 커뮤니티);
s(j) = 1 - 합(i, x.l(i,j)); // 하위 그라데이션
노름 = 합(j, sqr(s(j)));
상태$(norm < tol) = 2;
상태$(abs(zlbest - zfeas) < 1e-4) = 3;
상태$(pknap.modelStat <> %modelStat.optimal%) = 4;
결과 넣기 / iter.tl, 슬롯 커뮤니티:16:6, zlbest:16:6, norm:16:6, abs(zlbest - zfeas):16:6;
if((상태 = 2),
put / /"subgr. 메소드가 수렴되었습니다. status = ",status:5:0/ /;
put / /"마지막으로 찾은 솔루션은 IP 문제에 최적입니다."/ /;
); //이면 종료
if((상태 = 3),
put / /"subgr. 메소드가 수렴되었습니다. status = ",status:5:0/ /;
put / /"이원성 격차가 없으며, 발견된 최상의 솔루션이 최적입니다."/ /;
); //이면 종료
if((상태 = 4),
put / /"마지막 Lag. 하위 문제에 문제가 있습니다."/ /;
put / /"status = ",status:5:0/ /;
); //이면 종료
보고서(iter,'zlr') = zlr;
보고서(iter,'슬롯 커뮤니티') = 슬롯 커뮤니티;
보고서(iter,'zlbest') = zlbest;
보고서(iter,'norm') = 규범;
보고서(iter,'단계') = 단계;
wrep(iter,j) = w(j);
srep(iter,j) = s(j);
xrep(j,i,iter) = x.l(i,j);
if(상태 = 1,
목표 = (zlbest + zfeas)/2;
단계 = (알파*(목표 - 슬롯 커뮤니티)/norm)$(norm > tol);
w(j) = w(j) + 단계*s(j);
if(count > Reset, // 개선 없이 너무 많은 반복을 수행함
알파 = 알파/2;
개수 = 1;
그렇지 않으면
if(improv, // 개선되면 카운트를 재설정합니다.
개수 = 1;
그렇지 않으면
개수 = 개수 + 1; // 개선이 없으면 업데이트 횟수
);
);
);
); // 루프 반복 종료
보고서 표시, wrep, srep, xrep;
결과 입력 / / "할당 제약 조건에 대한 이중 값" /;
loop(j, put / "w('",j.tl,"') = ", w(j):16:6 ";";);
put / /"최고의 라그랑지 경계 = ", zlbest:10:5;