MODEL Oil_Problem

/*----------------------------------------------------------------------------*/
/* Data Creare     : 18 Mai       1997                                        */
/* Data Modificare : 25 Octombrie 1997                                        */
/*----------------------------------------------------------------------------*/
/* Sursa  : "Oil-Refinery Modeling with the GAMS Language" by David Kendrick, */
/* Alexander Meeraus and Jung Sun Suh.                                        */
/*                                                                            */
/* Modelul unei companii ce prelucreaza petrol brut cumparat.                 */
/*    O companie cumpara petrol brut si anumite produse intermediare pentru a */
/* produce diverse produse finale pentru a fi vindute pe piata.  Compania are */
/* mai multe unitati de prelucrare.  In procesul de amestec intrebuinteaza si */
/* alte  materii  prime.Problema companiei este de a produce in asa fel incit */
/* sa maximizeze venitul net rezultat din vinzarile de produse finale din care*/
/* se scad  toate costurile implicate pe intreg procesul de productie.        */
/*----------------------------------------------------------------------------*/

  FILE fd="oil.dat"

  INTEGER

    nrcrude  READ fd IS nrcrude  >=1; /* Numar tipuri petrol brut */

    nrmraw   READ fd IS nrmraw   >=1; /* Numar materii prime */

    nrinter  READ fd IS nrinter  >=1; /* Numar produse intermediare */

    nrpurch  READ fd IS {nrpurch >=1; nrpurch <=nrinter};

        /* Numar produse intermediare cumparate */

    nrfinal READ fd IS nrfinal >=1;  /* Numar produse finale */

    nrproc  READ fd IS nrproc  >=1;  /* Numar procese */

    nrunit  READ fd IS nrunit  >=1;  /* Numar unitati productive */

    nrqual  READ fd IS nrqual  >=1;  /* Numar calitati */

    nrblend READ fd IS {nrblend >=1; nrblend<=nrfinal*nrinter};

        /* Number elemente multime BLEND,configuratii de intermediare */
        /* ce pot participa  in amestec pentru un anumit produs final */

    nrmrint = nrmraw+nrinter

        /* Numar materii prime plus produse intermediare */
 

    RANGE

      crude  = [1,nrcrude ]; /* Coduri  interne  petrol  brut */

      mraw   = [1,nrmraw  ]; /* Coduri interne  materii prime */

      inter  = [1,nrinter];  /* Coduri  produse  intermediare */

      purch  = [1,nrpurch];  /* Coduri intermediare cumparate */

      final  = [1,nrfinal];  /* Coduri produse finale */

      proc   = [1,nrproc ];  /* Coduri procese tehnologice */

      unit   = [1,nrunit ];  /* Coduri unitati  productive */

      qual   = [1,nrqual ];  /* Coduri calitati produse */

      blend  = [1,nrblend];  /* Coduri elemente multime asociata */

      mrint  = [1,nrmrint]  /* Coduri materii prime si intermediare  */
 

    INTEGER

      spurch[purch] READ fd IS /* Coduri prod. interm. cumparate */

             FOR[k IN purch] {spurch[k]>0; spurch[k]<=nrinter};

        /* Multimea amestec este formata din vectorii: BLENDPF si BLENDPI */
        /* blendpi(b) poate participa prin amestec la produsul blendpf(b) */

      blendpf[blend] READ fd IS  /* Componenta 1 a multimii amestec */

             FOR[b IN blend]  {blendpf[b]>=1; blendpf[b]<=nrfinal};

      blendpi[blend] READ fd IS  /* Componenta 2 a multimii amestec */

             FOR[b IN blend]  {blendpi[b]>=1; blendpi[b]<=nrinter};

      blendl[blend] IS /* Indici liniarizati pentru multimea amestec */

            FOR[b IN blend] blendl[b]=(blendpf[b]-1)*nrinter + blendpi[b]

    REAL io[crude,mrint,proc] READ fd

        /* io[c,m,p] este intrare (daca < 0.0) sau iesire (daca >=0.0) */
        /* a materialului m, prin folosire tip de petrol c, pe unitate */
        /* de nivel a operatiei procesului p */

    INTEGER

      util [unit,proc] READ fd IS FOR[u IN unit,p IN proc]

          util[u,p]=ifs(util[u,p],1,0)

        /* util[u,p] = 1 daca procesul p utilizeaza unitatea u,0 altfel */
 

    REAL

      cap [unit] READ fd IS FOR[u IN unit] cap[u] >= 0.0;

 /* cap[u] este capacitatea initiala a unitatii u */

      pricec [crude] READ fd IS FOR[c IN crude] pricec[c] > 0.0;

        /* pricec[c] este pretul de cumparare pe baril al petrolului c */

      pricep [purch] READ fd IS FOR[p IN purch] pricep[p] > 0.0;

        /* pricep[p] pretul pe baril al intermediarului cumparat spurch[p] */

      pricef [final] READ fd IS FOR[f IN final] pricef[f] > 0.0;

        /* pricef[f] este pretul de vinzare baril pentru produsul final f */

      cost [proc] READ fd IS FOR[k IN proc] cost[k] > 0.0;

        /* cost[k] este $ pe baril in procesul k */

      qmin [final,qual] READ fd IS

             FOR[f IN final,q IN qual] qmin[f,q] >= 0.0;

        /* Limita inferioara pe calitate la produse finale */

      qmax [final,qual] READ fd IS

             FOR[f IN final,q IN qual] qmax[f,q] >= 0.0;

        /* Limita superioara pe calitate produsele finale */

      qboth[inter,qual] READ fd IS

             FOR[i IN inter,q IN qual] qboth[i,q] >= 0.0;

      qcrude [crude,inter,qual] READ fd IS

       FOR[c IN crude,i IN inter, q IN qual] {qcrude[c,i,q] >= 0.0;

                lor(ifp(qcrude[c,i,q],0,1,0),ifp(qboth[i,q],0,1,0))=1};
 

      attr [crude,inter,qual] IS FOR[c IN crude,i IN inter,q IN qual]

         attr[c,i,q]= ifp(qcrude[c,i,q],qboth[i,q],

                           qboth[i,q],qcrude[c,i,q]);

        /* attr[c,i,q] este marimea atributului q ce contribuie la amestec */

        /* prin intermediarul i derivat din tipul de petrol c */

     cpmax [crude] READ fd IS FOR[c IN crude] cpmax[c] > 0.0

        /* Margine superioara a petrolului cumparat */

     INTEGER

       nrqminnz= SUM[f IN final,q IN qual](ifp(qmin[f,q],1,0,1));

        /* Numarul elementelor qmin[f,q] <>0 */

       nrqmaxnz= SUM[f IN final,q IN qual](ifp(qmax[f,q],1,0,1));

        /* Numarul elementelor qmax[f,q] <>0 */

       find=0;  /* Variabila necesara in actiuni SEARCH */
 

       l=1; l1=0; m=1; m1=0 /* Variabile de lucru */
 

    RANGE

        /* Domenii necesare mai departe in calcul vectori */

      qminnz=[1,nrqminnz];

      qminnz1=[1,nrqminnz+1];

      qmaxnz=[1,nrqmaxnz];

      qmaxnz1=[1,nrqmaxnz+1]
 

    INTEGER

      qminnzl[qminnz1] IS FOR[f IN final,q IN qual]

      qminnzl[l]=(f-1)*nrqual+q+atr(ifp(qmin[f,q],1,0,1)+l,l);

        /* Indici lineari ai perechilor (f,q) unde qmin[f,q]<>0 */

      qmaxnzl[qmaxnz1] IS FOR[f IN final,q IN qual]

      qmaxnzl[m]=(f-1)*nrqual+q+atr(ifp(qmax[f,q],1,0,1)+m,m)

        /* Indici lineari ai perechilor (f,q) unde qmax[f,q]<>0 */

  VARIABLES

    InCr [crude]  IS FOR[c IN crude] InCr[c] <= cpmax[c];

        /* Cantitatea de petrol cumparata. Nu trebuie sa depaseasca limita */

    InInt[purch,crude]; /* InInt[p,c] este cantitatea cumparata pentru */
                        /* derivatul spurch[p] din petrolul de tip c */

    LevPr [proc,crude]; /* LevPr[p,c] este nivel proces p cu petrol tip c */

    LevBl [blend,crude];/* LevBl[f,i,c] este nivel intermediar i, derivat */
                        /* din petrol tip c, amestecat in produsul final f*/

    Out [final];        /* Out[f] este cantitatea rezultata din produsul f*/

    Revenue;            /* Venit pe toate produsele finale vindute */

    PurchC;             /* Costul tuturor materialelor achizitionate */

    OperC               /* Costul tuturor operatiilor */
 

  OBJECTIVES

    net IS net:=  Revenue - PurchC - OperC

        /* Venitul net rezultat din vinzari minus costuri */

    MAXIMIZE net
 

  CONSTRAINTS

    balcr [mraw,crude] IS FOR [r IN mraw, c IN crude]

    balcr[r,c]:=SUM [p IN proc](io[c,r,p] * LevPr[p,c]) + InCr[c] >= 0.0;

        /* Inputul pentru fiecare tip petrol din toate procesele */
        /* (negativ prin conventie) trebuie sa fie acoperit din achizitii */

    balin [inter,crude] IS FOR [i IN inter, c IN crude]

    balin[i,c]:=SUM [p IN proc] (io[c,i+nrmraw,p] * LevPr[p,c]) +

                 search(i, spurch[1],find)* InInt[find,c] >=

                 SUM[f IN final]( atr( (f-1)*nrinter +i,m) +

                 search(m,blendl[1],find)*LevBl[find,c]);

        /* Cantitatea fiecarui intermediar produs si cumparat trebuie */
        /* sa acopere cantitatea necesara in amestec */

    balfin[final] IS FOR [f IN final]

       balfin[f]:= Out[f] = SUM[i IN inter,c IN crude]

       (atr((f-1)*nrinter +i,m) + search(m,blendl[1],find)*LevBl[find,c]);

        /* Volumul fiecarui produs final este egal cu volumul */
        /* tuturor intermediarelor amestecate pentru producerea sa */

    rqmin[qminnz] IS FOR[k IN qminnz] rqmin[k]:=

      atr(qminnzl[k],l)+  atr((l-1)/nrqual+1,m) + /* f=m,q=l1 */

      atr(l-(m-1)*nrqual,l1) + SUM[i IN inter,c IN crude]

       ( atr((m-1)*nrinter+i,m1) +  search(m1,blendl[1],find)*

         attr[c,i,l1]*LevBl[find,c]) >= qmin[m,l1] * Out[m];

        /* Calitatile produselor finale nu trebuie sa scada sub minim */

    rqmax[qmaxnz] IS FOR [k IN qmaxnz] rqmax[k]:=

      atr(qmaxnzl[k],l)+ atr((l-1)/nrqual+1,m) + /* f=m,q=l1 */

      atr(l-(m-1)*nrqual,l1) + SUM[i IN inter,c IN crude]

      ( atr((m-1)*nrinter+i,m1) + search(m1,blendl[1],find)*

        attr[c,i,l1]*LevBl[find,c]) <= qmax[m,l1] * Out[m];

        /* Calitatile produselor finale nu trebuie sa scada sub minim */

    rcap[unit] IS FOR[u IN unit] rcap[u]:= SUM[p IN proc]

           (util[u,p] * SUM[c IN crude] (LevPr[p,c])) <= cap[u];

        /* Utilizarea unei unitati de catre toate procesele */
        /* nu poate sa depaseasca capacitatea specifica a ei*/

    dRev IS dRev :=

      Revenue = SUM[f IN final] (pricef[f] * Out[f]);

        /* Venitul este suma rezultata din valoarea produselor finale */

    dPurchC IS dPurchC:= PurchC = SUM[c IN crude](pricec[c] * InCr[c]) +

         SUM[p IN purch, c IN crude] (pricep[p]* InInt[p,c]);

       /* Total cost al achizitiilor este costul pe achizitia de petrol */
       /* plus  costul produselor intermediare care sunt cumparate */

    dOperC IS dOperC:= OperC = SUM[p IN proc] (cost[p] * SUM[c IN crude] (LevPr[p,c]))

        /* Costul total de operare este suma costurilor pentru toate */
        /* nivelele de proces ale tipurilor de petrol */

END


Return la Tabela Modele