좋은 코딩 습관

메가 슬롯 언어는 허용되는 코드의 구문 및 형식과 관련하여 매우 유연하여 사용자가 메가 슬롯 코드를 구성하고 형식화하는 방법에 대해 상당한 자유를 제공합니다. 대부분의 모델러는 메가 슬롯 시스템에 대한 경험을 쌓으면서 자신만의 스타일을 개발합니다. 이 튜토리얼은 Bruce A. McCarl(현재 텍사스 A&M 대학교 농업경제학 교수)의 코딩 선호도를 반영합니다. Bruce는 모델러이자 교육자로서 메가 슬롯에 대한 폭넓은 경험을 갖고 있으며 많은 메가 슬롯 사용자가 그의 작업을 알고, 사용하고, 그로부터 이익을 얻고 있습니다. 이 튜토리얼의 목표는 다음과 같습니다.아님임의로 따라야 하는 엄격한 규칙 세트를 제시하기보다는 사용자가 자신만의 코딩 선호도와 스타일을 개발하도록 돕습니다. 더 큰 목표는 현재 작업하는 개발자와 수개월 또는 수년에 걸쳐 모델을 사용하는 대규모 동료 및 컨설턴트 그룹 모두를 위해 쉽게 읽고 이해하고 편집하고 디버깅할 수 있는 자체 문서화 모델을 구축하는 것입니다.

우리는 다음 주제를 다룰 것입니다:

긴 이름과 설명 텍스트 사용

식별자에 대해 더 긴 자체 설명 이름(예: 집합 이름, 매개메가 슬롯, 메가 슬롯 등)을 사용하면 GAMS 코드의 가독성이 크게 향상될 수 있습니다. 프로덕션 및 인벤토리 모델에서 다음 코드 줄을 고려하세요.[로버트]:

p '제품' 설정 / 낮음, 중간, 높음 /
      r '원자재' / 스크랩, 새로운 /
      tt '긴 지평선' / 1*4 /
      t(tt) '짧은 지평선' / 1*3 /;

테이블 a(r,p) 입력 '계수'

          낮음 중간 높음
 스크랩 5 3 1
 새로운 1 2 3;

테이블 c(p,t) '기대 이익'

            1 2 3
 낮음 25 20 10
 중간 50 50 50
 높음 75 80 100;

메가 슬롯 x(p,tt) '생산 및 판매'
           s(r,tt) '주식 개시'
           이익;

 양의 메가 슬롯 x, s;

 방정식 cc(t) '용량 제약'
            sb(r,tt) '재고 잔액'
            pd '이익 정의' ;

 cc(t)..sum(p, x(p,t)) =l= m;

 sb(r,tt+1).. s(r,tt+1) =e= s(r,tt) - sum(p, a(r,p)*x(p,tt));

 pd.. 이익 =e= sum(t, sum(p, c(p,t)*x(p,t))
                        - sum(r, misc("storage-c",r)*s(r,t)))
                        + sum(r, misc("res-value",r)*s(r,"4"));

 s.up(r,"1") = misc("최대 재고",r);

이 줄은 다음과 같은 방법으로 다시 포맷할 수 있습니다(( 참조)good.gms)):

프로세스 '사용 가능한 생산 프로세스' 설정
       / low '신소재를 소량 사용합니다',
         Medium은 '중간 정도의 신소재를 사용한다',
         높음 '신소재를 다량 사용' /
     rawmateral '원자재의 원천' / 스크랩, 새것 /
     분기 '긴 지평선' / 봄, 여름, 가을, 겨울 /
     Quarter(쿼터스) '짧은 지평선' / 봄, 여름, 가을 /

 테이블 용도(원재료, 공정) '입력계수'
          낮음 중간 높음
 스크랩 5 3 1
 새로운 1 2 3

 테이블 Expectprof(process,quarters) '기대 이익'
         봄 여름 가을
 낮음 25 20 10
 중간 50 50 50
 높음 75 80 100;

 메가 슬롯 생산(공정,분기) '생산 및 판매'
            openstock(rawmateral,Quarters) '개시 주식'
            이익 ;

 양의 메가 슬롯 생산, 공개 재고;

 방정식 용량(분기) '용량 제약'
            stockbalan(rawmateral,Quarters) '재고 잔고'
            profitacct '이익 정의' ;

 용량(분기)..
        sum(프로세스, 생산(프로세스, 분기)) =l= mxcapacity;

 재고발란(rawmateral,Quarters+1)..
      openstock(rawmateral,Quarters+1) =e=
      오픈스톡(원자재,쿼터스)
      - 합계(프로세스, 사용량(원재료,프로세스)
                   *생산(프로세스,분기));

 이익계산.. 이익 =e=
   합계(분기,
       sum(프로세스, 기대prof(프로세스, 분기)
                    *생산(공정,분기))
     - sum(rawmateral, miscdata("store-cost",rawmateral)*
                       오픈스톡(원자재,분기)))
     + sum(rawmateral, miscdata("endinv-value",rawmateral)
                      *openstock(rawmateral,"겨울"));

 openstock.up(rawmateral,"spring") = miscdata("max-stock",rawmateral);

두 가지 공식은 그 효과가 동일하지만 두 번째 공식에서는 더 길고 더 설명적인 이름이 집합, 테이블, 메가 슬롯 및 방정식에 사용되었습니다. 또한 집합 요소와 집합 정의에 더 긴 이름이 사용되었습니다.프로세스세트 요소에는 추가 설명 텍스트가 있습니다. 두 번째 공식이 이해하기 더 쉽다는 것을 관찰하십시오. 이는 5년 후에 코드를 다시 검토할 때 특히 유용할 것입니다.

참고
  • 메가 슬롯는 다음에 대한 긴 이름을 허용한다는 점을 기억하십시오.식별자그리고라벨(요소 설정). 사용자는 이 기능을 활용하여 긴 설명 이름을 도입할 수 있습니다. 그러나 10자를 초과하는 레이블 이름은 다중 열 표시에서 제대로 작동하지 않습니다. 사용자 정의에 대한 단락을 참조하십시오.표시 너비자세한 내용은.
  • 식별자에 대한 설명 텍스트를 사용하여 단위, 출처, 설명 등을 나타냅니다. 그렇게 하는 것은 그리 어렵지 않으며 나중에 배당금을 지불합니다.
  • 마찬가지로, 적절하게 세트 요소에 대한 설명 텍스트를 사용하십시오.

예를 들어, 다음 코드 조각의 두 번째 줄에 있는 설명 텍스트는 첫 번째 줄의 텍스트보다 훨씬 더 많은 정보를 제공합니다:

매개메가 슬롯 vehsales(r) '지역 차량 판매';
매개메가 슬롯 vehsales(r) '지역 차량 판매량(백만 달러/년)';

해당 식별자가 표시될 때마다 설명 텍스트가 표시된다는 점에 유의하세요. 따라서 나중에 결과를 해석해야 하는 경우 텍스트에 단위를 포함하면 시간이 절약됩니다.

절차와 데이터의 성격 및 출처에 대한 설명 포함

코드 문서에서 다음 질문에 대한 답변을 제공하는 것이 좋습니다.

  • 메가 슬롯와 매개메가 슬롯의 단위는 무엇입니까?
  • 데이터는 어디서 왔습니까?
  • 단위, 적용 연도 등 데이터의 특징은 무엇입니까?
  • 구현 방식에 제약 조건이 설정된 이유는 무엇입니까?

또한 가정, 방정식 용어의 의도, 문서 이름, 페이지 번호, 표 번호, 적용 연도, 단위, URL 등을 포함한 데이터 소스를 설명하는 주석을 추가하는 것이 도움이 되는 경우가 많습니다.

다양한 형태의 주석이 설명된 다음 예를 고려하십시오:

* 이것은 데이터를 설명할 수 있는 한 줄 주석입니다.
$ontext
내 데이터는 이 여러 줄 주석으로 설명될 수 있습니다.
이게 두 번째 줄이에요
$offtext

* 다음 달러 제어 옵션은 줄 끝 주석을 활성화합니다.
* 줄 끝 주석 기호를 재정의합니다.
$eolCom #
x = 합(i, z(i)) ; # 이것은 줄 끝 주석입니다.

* 다음 달러 제어 옵션은 인라인 댓글을 활성화합니다.
* 인라인 주석의 기호를 재정의합니다.
$inLineCom (* *)
x = 합(i, z(i)) ; (* 인라인 주석입니다 *) r = sum(i, z(i)) ;

메가 슬롯의 댓글에 대한 자세한 내용은 섹션을 참조하세요.댓글.

계산된 데이터 대신 원시 데이터 선택

모델러는 종종 데이터 입력 방법을 선택할 수 있습니다. 원시 데이터를 사용하여 메가 슬롯 내부에서 필요한 정도로 변환하거나 외부에서 데이터를 처리하고 최종 결과를 메가 슬롯에 입력할 수 있습니다.

원시 데이터가 메가 슬롯에 도입되기 전에 조작할 수 있는 스프레드시트에서 사용할 수 있는 경우 두 번째 선택이 매력적일 수 있습니다. 그러나 시간이 지남에 따라 스프레드시트 및 기타 데이터 조작 프로그램이 변경되거나 손실되며 종종 이러한 프로그램이 제대로 문서화되지 않습니다. 따라서 실제 수집된 데이터와 최대한 가까운 형태로 메가 슬롯에 데이터를 입력한 후, 메가 슬롯로 데이터를 조작하여 원하는 형태를 얻는 것을 권장합니다. 이렇게 하면 나중에 모델을 업데이트하거나 암시적 가정을 해결하는 것이 훨씬 쉬워집니다.

데이터 입력 맥락에서 범용 집합 방지

메가 슬롯는 다음 사용을 허용하지만유니버설 세트 *매개메가 슬롯 또는 테이블 문의 색인으로, 대부분의 경우에 해당됩니다.아님그렇게 하는 것이 좋습니다. 생산 및 재고 모델의 다음 예를 고려하십시오.[로버트]:

r '원자재' 설정 / 스크랩, 새 / ;

Table misc(*,r) '기타 데이터'
            새것 폐기
 최대 재고 400 275
 스토리지-c .5 2
 res 값 15 25 ;
...

pd.. 이익 =e= sum(t, sum(p, c(p,t)*x(p,t))
              - sum(r, misc("storage-c",r)*s(r,t)))
              + sum(r, misc("res-value",r)*s(r,"4"));

테이블 정의에 유의하세요.기타은 첫 번째 인덱스 위치의 모든 항목이 허용됨을 나타냅니다. 없습니다도메인 확인. 결과적으로 라벨res-value다음과 같이 철자가 틀렸습니다.res-val방정식에서pd, 메가 슬롯는 오류 신호 없이 프로그램을 컴파일하고 실행하지만 예상 값 대신(예:misc(r,"res-value")), 값misc(r,"res-val")이 방정식에 사용됩니다. 이러한 0 값은 잘못된 결과로 이어지며 모델러는 이 사실을 알지 못합니다. 메가 슬롯 실행 결과를 신뢰할 수 있도록 하려면 테이블의 첫 번째 색인 위치에 있는 라벨에 대한 새로운 세트를 도입하여 도메인 확인을 사용하는 것이 좋습니다.기타:

r '원재료'를 설정합니다
         /스크랩, 새것 /
       miscite '기타 입력 항목'
         / 최대-재고, 저장-c, res-값/;

테이블 misc(miscitem,r) '기타 데이터'
            새것 폐기
 최대 재고 400 275
 스토리지-c .5 2
 res 값 15 25 ;

새로운 세트를 관찰하세요잘못 인용테이블의 행에 나타나는 라벨을 정확하게 포함합니다.기타. 따라서 세트잘못된 내용정의의 첫 번째 색인 위치에 사용될 수 있습니다.기타일반성을 잃지 않지만 도메인 확인의 이점이 있습니다.

집합과 부분집합을 현명하게 정의하기

일반적으로 집합의 요소들은 공통된 특징을 가지고 있거나 어떤 면에서 유사합니다. 이 섹션에서는 데이터의 레이블을 세트로 분할하는 방법에 대한 몇 가지 지침을 제공합니다. 또한 어떤 상황에서 하위 집합을 도입하는 것이 유용한지 논의할 것입니다. 메가 슬롯의 집합에 대한 소개는 장을 참조하세요.세트 정의.

예를 들어, 세 가지 등급의 석유와 이를 분해하는 세 가지 프로세스가 있다고 가정해 보겠습니다. 9개의 요소로 구성된 하나의 세트를 도입해야 하는지 아니면 3개의 요소와 2차원 세트로 구성된 두 개의 세트를 도입해야 하는지에 대한 의문이 생깁니다. 두 번째 대안을 권장합니다.

또 다른 예에서 우리는 농장 지출에 대한 예산을 고려합니다. 우리는 비료와 종자에 대한 연간(즉, 연간 누적) 지출이 있고 노동과 물에 대한 월간 지출도 있습니다. 예산에는 26개의 결정 또는 항목이 있습니다. 26개의 요소로 구성된 세트를 도입하거나 다음 공식을 사용할 수 있습니다.

자원 설정 / 비료, 종자, 노동, 물 /
     기간 / 1월, 2월, 3월, 4월, 5월, 6월, 7월, 8월, 9월, 10월, 11월, 12월, 연간 /
     사용(자원,기간)
                /(비료,종자).연간
                      (노동,물) .(jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec) /;

우리는 위의 공식을 권장하며 집합 정의로 더 광범위하거나 정확하다는 측면에서는 실수를 범합니다.

때때로 특정 목적을 위해 일부 라벨을 하나의 세트로 그룹화한 다음 다른 목적을 위해 일부 라벨을 골라내야 하는 경우가 있습니다.하위 집합그러한 경우의 모델링을 용이하게 합니다. 예를 들어 거리를 입력하고 관련 교통 비용을 계산하려면 모델의 모든 도시 집합이 필요할 수 있습니다. 또한 일부 방정식은 이러한 허브로 제한되어야 하므로 일부 활동의 허브인 도시를 지정하는 데 하위 집합을 사용할 수 있습니다.

가독성 향상을 위한 파일 구조화 및 형식 지정

이 섹션에서는 읽기 쉽게 메가 슬롯 코드를 구조화하고 형식화하는 방법에 대한 몇 가지 지침을 제공합니다.

메가 슬롯 코드를 구성하는 방법에는 여러 가지가 있습니다. 섹션에는 두 가지 스타일이 설명되어 있습니다.메가 슬롯 프로그램 구성. 고정된 순서로 코드 섹션을 입력하기 위한 다음 권장 사항은 첫 번째 스타일의 확장 버전입니다.

  1. 데이터와 관련된 세트에 대한 정의 세트
  2. 매개메가 슬롯, 스칼라 및 테이블 정의, 계산과 혼합될 수 있음
  3. 메가 슬롯 정의
  4. 수식 선언
  5. 방정식 정의(방정식의 대수적 사양)
  6. 문 모델링 및 해결
  7. 보고서 작성을 위한 세트 및 매개메가 슬롯 정의
  8. 보고서 작성을 위한 계산
  9. 보고서에 대한 표시 문

코드의 각 섹션에 한 가지 유형의 명령문만 포함되어 있으면 코드를 탐색하기가 가장 쉬울 것이라는 점에 유의하십시오. 예를 들어, 매개메가 슬롯 정의와 함께 집합 정의를 삽입하면 코드를 읽기가 불필요하게 어려워집니다.

고정된 구조를 따르는 것 외에도 코드 형식을 올바르게 지정하는 것도 중요합니다. 물론 형식 지정은 여러 측면에서 취향의 문제입니다. 다음 목록은 몇 가지 아이디어를 제공합니다.

  • 이 튜토리얼의 예와 일반적인 메가 슬롯 사용자 가이드에 설명된 대로 식별자 이름과 설명 텍스트를 정렬합니다.
  • 간격과 들여쓰기를 사용하세요.
  • 빈 줄을 사용하여 무언가를 강조하고 코드 섹션을 표시하십시오.
  • 메가 슬롯와 모든 인덱스 위치가 방정식 정의에서 한 줄에 있는지 확인하세요.
  • 합과 같은 색인 연산 및 프로그래밍 흐름 제어 구조에서 들여쓰기루프그리고if 문용어를 설명합니다. 길고 복잡한 문장의 구조는 조심스럽게 들여쓰기하고 닫는 괄호를 신중하게 배치하면 드러날 수 있습니다.

우리는 다음 두 가지 예를 통해 적절한 형식 지정의 효과를 보여줄 것입니다. 첫 번째 예에는 유효한 메가 슬롯 코드가 포함되어 있지만 의도적으로 형식이 잘못되었습니다.

제품 '사용 가능한 생산 공정' 설정 / 낮음 '낮은 신재료 사용'
Medium '중간 신소재 사용', High '고급 신소재 사용'/
rawmateral '원자재의 원천' / 스크랩, 새것 /
분기 '긴 지평선' / 봄, 여름, 가을, 겨울 /
Quarter(Quarters) '짧은 지평선' / 봄, 여름, 가을 / ;
메가 슬롯 생산(제품,분기) '생산 및 판매' ;
openstock(rawmateral,Quarters) '개시 주식', 이익 ;
양의 메가 슬롯 생산, 공개 재고;
방정식 용량(분기) '용량 제약',
stockbalan(rawmateral,Quarters) '재고 잔액',
이익acct 이익 정의 ;
이익acct.. 이익 =e= 합계(분기, 합계(제품, 기대prof(
제품,분기) *생산(제품,분기))-합계(
rawmateral,miscdata("저장 비용",rawmateral)*openstock(rawmateral
  ,quarter)))+ sum(rawmateral, miscdata("endinv-value",rawmateral) *openstock(rawmateral,"winter"));

두 번째 예는 첫 번째 예와 동일한 코드를 포함하지만 주의 깊게 형식이 지정되었습니다.

제품 '사용 가능한 생산 공정' 설정
       / low '신소재를 소량 사용합니다',
         Medium은 '중간 정도의 신소재를 사용한다',
         높음 '신소재를 다량 사용' /
     rawmateral '원자재의 원천' / 스크랩, 새것 /
     분기 '긴 지평선' / 봄, 여름, 가을, 겨울 /
     Quarter(Quarters) '짧은 지평선' / 봄, 여름, 가을 / ;

메가 슬롯 생산(제품,분기) '생산 및 판매'
           openstock(rawmateral,Quarters) '개시 주식'
           이익 ;
긍정적인 메가 슬롯 생산, openstock ;

방정식 용량(분기) '용량 제약'
           stockbalan(rawmateral,Quarters) '재고 잔고'
           profitacct '이익 정의' ;

이익 계산..
    이익 =e=
    합계(분기,
       sum(제품, 기대prof(제품,분기)
                    *생산(제품,분기)
           )
      - sum(rawmateral, miscdata("store-cost",rawmateral)*
                       오픈스톡(원재료,쿼터)
           )
       )
   + sum(rawmateral, miscdata("endinv-value",rawmateral)
                   *openstock(rawmateral,"겨울")
       )
  ;

빈 줄을 삽입하고, 식별자와 설명 텍스트의 이름을 정렬하고, 합계에서 닫는 괄호를 들여쓰고 서식을 지정하면 코드를 훨씬 더 쉽게 읽고 이해할 수 있으며(현재와 미래 모두) 메가 슬롯 코드를 작성할 때 표준 관행으로 채택할 가치가 있습니다.

기타 제안

모델러가 자신만의 규칙을 개발하는 데 도움이 될 수 있는 몇 가지 유용한 제안을 제공하여 이 튜토리얼을 완료하겠습니다.

GAMS가 대소문자를 구분하지 않더라도 대문자와 소문자 사용에 관한 규칙을 정하는 것이 좋습니다. 예를 들어 Paul N. Leiby(현재 Oak Ridge National Laboratory)는 텍스트와 설명에 소문자를 사용하고 GAMS 예약어와 메가 슬롯 및 매개메가 슬롯 이름에 대문자를 사용합니다. GAMS 프로그램에서 식별자나 라벨이 처음 발견될 때 사용되는 대소문자는 GAMS에 저장되어 목록 파일이나 GDX 파일과 같은 후속 출력에 사용됩니다. 모든 대소문자를 사용할 수 있습니다(그래서아니요어디다음과 동일함지금여기) 그러나 저장된 케이싱은 처음 사용할 때 결정됩니다.

라벨 인용에도 비슷한 상황이 있습니다. 저장된 인용문 유형(있는 경우)은 처음 사용할 때 결정됩니다.

달러 제어 옵션에 유의하세요$onSymList는 모든 식별자 이름 목록이 출력 파일의 컴파일 출력에 표시되도록 합니다. 이 목록은 출력 파일에 나타나는 식별자의 철자와 대소문자를 검토하는 데 사용될 수 있습니다. 마찬가지로 달러 제어 옵션$onUELL리스트모든 레이블의 정렬된 목록이 출력 파일의 컴파일 출력에 표시됩니다. 이는 메가 슬롯 프로그램에서 사용되는 라벨의 대소문자와 순서를 모두 확인하는 데 유용합니다. 라벨 주문과 관련된 문제에 대한 자세한 내용은 섹션을 참조하세요.정렬된 세트와 정렬되지 않은 세트.

식별자 이름의 데이터 유형을 추적하기 위해 일부 모델러는 항상 다음으로 세트 이름을 시작합니다.s_, 매개메가 슬롯 이름d_("데이터"의 경우), 메가 슬롯 이름은v_및 방정식 이름e_.

일부 숙련된 메가 슬롯 사용자는 항상 설명 텍스트를 따옴표로 묶습니다. 이렇게 하면 텍스트가 눈에 띄게 되고 레이블이나 식별자로 해석되는 것을 방지하며 다음과 같은 특수 문자를 사용할 수 있습니다.$, -그리고&사용됩니다.

파일이 여러 모델러에 의해 사용되며 가끔 업데이트되는 경우 파일 상단에 파일 수정 로그가 순서대로 표시됩니다. 여기에는 수정 날짜, 버전 번호, 수정 사항, 수정한 사람 등의 정보가 포함되어야 합니다. 예를 들어,버전입력 파일이 수정된 날짜를 추적하는 데 사용될 수 있습니다.

버전 설정(*,*,*,*);
. . .
version("my_file","5월","19","2016") = yes;
version("my_include_file","9월","30","2016") = 예;
. . .
디스플레이 버전;

display 문은 집합의 모든 요소를 표시합니다.버전, 각각 모델의 구성요소가 수정된 날짜를 나타냅니다.