spbenders4.gms : 확률론적 벤더 - 병렬 MPI

설명

이 예는 확률론적 Bender 구현을 보여줍니다.
간단한 운송 예.

이것은 확률론적 벤더 시퀀스의 네 번째 예입니다.
마스터 문제를 해결하기 위해 다양한 방법을 사용하여 구현
하위 문제.

이 네 번째 예는 다음을 사용하여 확률론적 벤더 알고리즘을 구현합니다.
MPI를 사용한 병렬 구현. 이 예에서는 모델이 시작됩니다.
다음과 같이 명령줄에서:

   mpiexec -n 4 게임 spbenders4 fileStemApFromEnv=PMI_RANK lo=2

다른 플랫폼에서는 이 명령이 약간 다르게 보일 수 있습니다. HPC에서
종종 Linux를 실행하고 특수 MPI를 사용하는 시스템의 경우 더 많을 수 있습니다.
Python 버전과 다른 Python 버전을 사용하는 것이 효율적(또는 필수)
슬롯가 함께 제공됩니다. /latest/docs/API_PY_GETTING_STARTED.html에 설명된 대로
이 Python에는 슬롯 Python API 패키지도 설치되어 있어야 합니다.
또한 PMI_RANK 변수가 다르게 호출될 수도 있습니다. 어쨌든 슬롯에는 다음이 필요합니다.
외부 Python 설치를 사용하도록 지시하려면
환경 변수 GMSPYTHONLIB를 외부 Python 라이브러리에 추가합니다.

   mpirun -n 4 GMSPYTHONLIB=/path/to/python/lib/libpython3.12.so 슬롯 spbenders4 fileStemApFromEnv=OMPI_COMM_WORLD_RANK lo=2

이 명령은 카드 + 1개(작은 예에서는 4개)의 복사본을 생성합니다.
spbenders4 모델과 환경 변수 PMI_RANK가 어느 부분을 결정했는지
특정 인스턴스가 재생됩니다. PMI_RANK=0인 슬롯 작업은 다음을 구현합니다.
master 및 슬롯 작업 PMI_RANK=1 ~ PMI_RANK=s는 하위 문제를 구현합니다.
수신된 마스터 변수와 컷 정보의 통신
Python 패키지 mpi4py 및 슬롯 임베디드 코드 기능을 통해 발생합니다.

키워드: 선형 계획법, 확률론적 벤더 알고리즘, 교통
          문제, 슬롯 임베디드 코드 기능, Python, 병렬 컴퓨팅,
          메시지 전달 인터페이스

소형 모델 유형 :LP


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


메인 파일 : spbenders4.gms

$title 확률론적 벤더 - 병렬 MPI (SPBENDERS4,SEQ=421)

$onText
이 예는 확률론적 Bender 구현을 보여줍니다.
간단한 운송 예.

이것은 확률론적 벤더 시퀀스의 네 번째 예입니다.
마스터 문제를 해결하기 위해 다양한 방법을 사용하여 구현
하위 문제.

이 네 번째 예는 다음을 사용하여 확률론적 벤더 알고리즘을 구현합니다.
MPI를 사용한 병렬 구현. 이 예에서는 모델이 시작됩니다.
다음과 같이 명령줄에서:

   mpiexec -n 4 게임 spbenders4 fileStemApFromEnv=PMI_RANK lo=2

다른 플랫폼에서는 이 명령이 약간 다르게 보일 수 있습니다. HPC에서
종종 Linux를 실행하고 특수 MPI를 사용하는 시스템의 경우 더 많을 수 있습니다.
Python 버전과 다른 Python 버전을 사용하는 것이 효율적(또는 필수)
슬롯가 함께 제공됩니다. /latest/docs/API_PY_GETTING_STARTED.html에 설명된 대로
이 Python에는 슬롯 Python API 패키지도 설치되어 있어야 합니다.
또한 PMI_RANK 변수가 다르게 호출될 수도 있습니다. 어쨌든 슬롯에는 다음이 필요합니다.
외부 Python 설치를 사용하도록 지시하려면 
환경 변수 GMSPYTHONLIB를 외부 Python 라이브러리에 추가합니다.

   mpirun -n 4 GMSPYTHONLIB=/path/to/python/lib/libpython3.12.so 슬롯 spbenders4 fileStemApFromEnv=OMPI_COMM_WORLD_RANK lo=2

이 명령은 카드 + 1개(작은 예에서는 4개)의 복사본을 생성합니다.
spbenders4 모델과 환경 변수 PMI_RANK가 어느 부분을 결정했는지
특정 인스턴스가 재생됩니다. PMI_RANK=0인 슬롯 작업은 다음을 구현합니다.
master 및 슬롯 작업 PMI_RANK=1 ~ PMI_RANK=s는 하위 문제를 구현합니다.
수신된 마스터 변수와 컷 정보의 통신
Python 패키지 mpi4py 및 슬롯 임베디드 코드 기능을 통해 발생합니다.

키워드: 선형 계획법, 확률론적 벤더 알고리즘, 교통
          문제, 슬롯 임베디드 코드 기능, Python, 병렬 컴퓨팅,
          메시지 전달 인터페이스
$offText

$set MPI_RANK notSet
$if setenv PMI_RANK $set MPI_RANK %sysEnv.PMI_RANK%
$if setenv OMPI_COMM_WORLD_RANK $set MPI_RANK %sysEnv.OMPI_COMM_WORLD_RANK%
$if %MPI_RANK%==notSet $abort.noError 이 모델은 mpiexec/mpirun으로 시작해야 합니다. 자세한 내용은 모델 소스의 서문을 참조하세요.

$set MPI_SIZE notSet
$if setenv PMI_SIZE $set MPI_SIZE %sysEnv.PMI_SIZE%
$if setenv OMPI_COMM_WORLD_RANK $set MPI_SIZE %sysEnv.OMPI_COMM_WORLD_SIZE%
$if %MPI_SIZE%==notSet $abort.noError 이 모델은 mpiexec/mpirun으로 시작해야 합니다. 자세한 내용은 모델 소스의 서문을 참조하세요.

$log --- Python 라이브러리 %sysEnv.GMSPYTHONLIB% 사용

세트
   나는 '공장' / f1*f3 /
   j '물류 센터' / d1*d5 /;

매개변수
   생산 능력(i) '공장의 단위 생산 능력'
               / f1 500, f2 450, f3 650 /
   수요(j) '유통센터의 단위수요'
               / d1 160, d2 120, d3 270, d4 325, d5 700 /
   prodcost '단위 생산 비용' / 14 /
   가격 '판매 가격' / 24 /
   wastecost '과잉 재고 제품 제거 비용' / 4 /;

테이블 transcost(i,j) '단위 운송 비용'
          d1 d2 d3 d4 d5
   f1 2.49 5.21 3.76 4.85 2.07
   f2 1.46 2.54 1.83 1.86 4.76
   f3 3.26 3.08 2.60 3.76 4.45;

$ifThen 설정되지 않음 useBig
   '시나리오' 설정 / lo, mid, hi /;

   테이블 ScenarioData(s,*) '수요와 확률에 대한 가능한 결과'
             d1 d2 d3 d4 d5 문제
      로우 150 100 250 300 600 0.25
      중반 160 120 270 325 700 0.50
      안녕 170 135 300 350 800 0.25;
$else
$ nrScen을 설정하지 않은 경우 $set nrScen 10
   s '시나리오' 설정 / s1*s%nrScen% /;
   Parameter ScenarioData(s,*) '수요 + 확률에 대한 가능한 결과';
   옵션 시드 = 1234;
   ScenarioData(s,'prob') = 1/카드;
   ScenarioData(s,j) = 수요(j)*uniform(0.6,1.4);
$endIf

$평가 카드S개 카드+1
$if not %cardS%==%MPI_SIZE% $abort MPI 크기는 %cardS%여야 합니다.

임베디드 코드 Python:
시도해 보세요:
  mpi4py 가져오기에서 *
제외:
  raise Exception("mpi4py 모듈을 찾을 수 없습니다")
comm = MPI.COMM_WORLD

def 기호2목록(*기호):
    반환 목록(map(lambda x: list(슬롯get(x)), 기호))
일시중지임베디드코드
abort$execerror 'mpy4py 설정에 문제가 있거나 다른 Python 오류가 발생했습니다. 로그를 확인하세요';

매개변수 osub(s), cconst(s), ccoeff(s,j);

$ifThen.MPI 0==%MPI_RANK%
* 벤더스 마스터 문제
$maxiter를 설정하지 않은 경우 $set maxiter 25
세트
   iter '최대 벤더 반복 횟수' / 1*%maxiter% /
   itActive(iter) '활성 벤더 컷';

매개변수
   cutconst(iter) '최적 컷의 상수' / #iter 0 /
   cutcoeff(iter,j) '최적 컷의 계수' / #iter.#j 0 /;

변수
   ship(i,j) '배송'
   제품(i) '생산'
   received(j) '시장에 보낸 수량'
   zmaster '마스터 문제의 목적 변수'
   세타 '미래 이익';

포지티브 가변 선박;

방정식
   masterobj '마스터 목적 함수'
   Production(i) '각 공장의 생산량을 계산합니다.'
   receive(j) '시장에 보낼 수량을 계산합니다'
   optcut(iter) '벤더 최적성 감소';

masterobj.. zmaster =e= theta - sum((i,j), transcost(i,j)*ship(i,j))
                              - sum(i, prodcost*product(i));

receive(j).. received(j) =e= sum(i, ship(i,j));

생산(i).. 제품(i) =e= sum(j, ship(i,j));

optcut(itActive)..
   theta =l= cutconst(itActive) + sum(j, cutcoeff(itActive,j)*received(j));

product.up(i) = 용량(i);

모델 마스터문제 / 모두 /;

스칼라
   rgap '상대적 간격' / 0 /
   lowerBound '전역 하한' / -inf /
   upperBound '전역 상한' / +inf /
   obj마스터 / 0 /
   objSub / 0 /;

옵션 limRow = 0, limCol = 0, solPrint = 자동, 솔버 = cplex,solveLink=%solveLink.loadLibrary%;
수신됨.l(j) = 0;
obj마스터 = 0;

$rtol을 설정하지 않은 경우 $set rtol 0.001
루프(반복,
   계속임베디드코드:
   comm.bcast([[0], list(슬롯get('received'))], 루트=0)
   cut = comm.gather(없음, 루트=0)[1:]
   슬롯set('osub', [c[0][0] for c in cut])
   슬롯set('cconst', [c[1][0] for c in cut])
   슬롯set('ccoeff', [rec for s in cut for rec in s[2]])
   PauseEmbeddedCode osub, cconst, ccoeff
   objSub = 합계(들, osub(들));
   cutconst(iter) = sum(s, cconst(s));
   cutcoeff(iter,j) = sum(s, ccoeff(s,j));

   if(lowerBound < objMaster + objSub, lowerBound = objMaster + objSub);
   rgap = (상한 - 하한)/(1 + abs(상한));
   break$(rgap < %rtol%);
   itActive(iter) = 예;
   lp를 사용하여 masterproblem max zmaster를 해결합니다.
   upperBound = zmaster.l;
   objMaster = zmaster.l - theta.l;
);

* 하위 작업 종료
계속임베디드코드:
comm.bcast([[1],[]], 루트=0)
endEmbeddedCode
abort$(rgap >= %rtol%) '추가 반복 필요', 하한, 상한;
'최적 솔루션' 표시, 하한, 상한;

$else.MPI
* 벤더스의 하위 문제
변수
   received(j) '시장으로 보낸 수량(마스터로부터)'
   sales(j) '판매량(실제 판매됨)'
   waste(j) '과잉 제품'
   zsub '하위 문제의 목적 변수';

긍정적인 변동판매, 낭비;

방정식
   subobj '하위 문제 목적 함수'
   Selling(j) '수취한 부분이 판매되었습니다'
   market(j) '매출 상한선';

subobj.. zsub =e= sum(j, 가격*판매(j)) - sum(j, wastecost*waste(j));

판매(j)..판매(j) + 폐기물(j) =e= 수신됨.l(j);

시장(j)..매출(j) =l= 수요(j);

모델 하위 문제 / 하위 개체, 판매, 시장 /;

* 무한 루프
싱글톤 세트 ss(s);
ss(들) = ord(들)=%MPI_RANK%;
수요(j) = 시나리오데이터(ss,j);

스칼라 완료;

옵션 limRow = 0, limCol = 0, solPrint = 자동, 솔버 = cplex,solveLink = %solveLink.loadLibrary%;
동안(1,
   계속임베디드코드:
   rx = comm.bcast(없음, 루트=0)
   슬롯set('완료', rx[0])
   슬롯set('수신', rx[1])
   PauseEmbeddedCode 완료, 수신됨
   abort.noerror$done '하위 프로세스 종료 중';
   lp를 사용하여 하위 문제 max zsub를 해결합니다.
   osub(ss) = eps + ScenarioData(ss,'prob')*zsub.l;
   cconst(ss) = eps + ScenarioData(ss,'prob')*sum(j, market.m(j)*demand(j));
   ccoeff(ss,j) = eps + ScenarioData(ss,'prob')*판매.m(j);
   계속임베디드코드:
   comm.gather(symbols2List('osub', 'cconst', 'ccoeff'), root=0 )
   일시중지임베디드코드
);
$endIf.MPI