gams-math

Extract data to update model parameters and solve maximization problem in GAMS


I have several farmers and I would like to conduct optimization (profit maximization) for each of them in GAMS. I can do this for a single farmer, so my problem is how to iteratively make it works for multiple farmers.

I recorded the data in 3 different .csv files as follows (see code):

The following code does what I want for the single farmer case.

SETS
    resr                 resource of the farmer
    crop                 crops grown by the farmer
    ;

PARAMETERS
    resource_allocation  resource allocated by the farmer
    resEndow             resouce endowment of the farmer
    grosMarg             activities' gross margin of the farmer
    ;
    
$onEcho > resource_allocation.csv
resrs,Corn,    Bean,  Sorghum,  Peanut
Land,1,1,1,1
Labor,1.42,1.87,1.92,2.64
Mules,1.45,1.27,1.16,1.45
Market,0,0,0,0.98
$offEcho
$call csv2gdx resource_allocation.csv id=resource_allocation useHeader=y fieldSep=Comma index=1 values=2..lastCol trace=3 
$ifE errorLevel<>0 $abort Problems reading resource_allocation.csv!
$gdxIn resource_allocation.gdx
$load resr             = dim1
$load crop            = dim2
$load resource_allocation
$gdxIn
;

$onEcho > resource_endowment.csv
resr,resEndow
Labor,16.5
Land,5
Mules,10
Market,0.5
$offEcho
$call csv2gdx resource_endowment.csv id=resEndow useHeader=y fieldSep=Comma index=1 values=2 trace=3 
$ifE errorLevel<>0 $abort Problems reading resource_endowment.csv!
$gdxIn resource_endowment.gdx
$load resEndow
$gdxIn
;

$onEcho > activity_gross_margin.csv
crop,grosMarg
Corn,1372
Bean,1219
Sorghum,1523
Peanut,4874
$offEcho
$call csv2gdx activity_gross_margin.csv id=grosMarg useHeader=y fieldSep=Comma index=1 values=2 trace=3 
$ifE errorLevel<>0 $abort Problems reading activity_gross_margin.csv!

$gdxIn activity_gross_margin.gdx
$load grosMarg
$gdxIn
;

*DISPLAY resEndow, grosMarg, farmData;

VARIABLES

Prft Total gross margin
x(crop) activity levels
;

EQUATIONS

Profit definition of Z
RESCON ressouse constraint
NONNEG non-negativity condition;

Profit.. Prft =E= sum(crop, grosMarg (crop)*x(crop));
RESCON(resr).. sum(crop, resource_allocation(resr, crop)*x(crop)) =L= resEndow(resr);
NONNEG(crop).. x(crop) =G= 0;

model mayaland / Profit, RESCON, NONNEG /
;

SOLVE mayaland maximizing Prft using LP;
DISPLAY x.l, Prft.l;

My problem is how to make the above model work for multiple farmers and export the results in a comprehensive layout that clearly identify each farmer based on farmer's name, farmer's region, and farmer's practice (see data below). For this, I am only showing how the data look like on my end. I don't have much of ideas on the code to write (which is why I am asking this question). Note that, in the data below, I just replicated the same information from the single farmer datasets and add 3 additional columns to make the distinction between farmer 1 and farmer 2 clear. So, we expect the 2 solutions to be the same. I also would like to have the solution exported to a .csv file, so I can process it further.

*******************************************************************
* Here starts my problem: How can I run the above run over the 
* sets farmers, regions, and practices such that I get 1 solution 
* for each unique combination of(farmers, regions, practices)
*******************************************************************

SETS
    farmers
    regions
    practices
    resrs
    crops
;
PARAMETERS
    resource_allocations
    resource_endowments
    activity_gross_margins
    ;
    
SETS resrs, crops;

PARAMETERS
    farmDatas
    resEndows
    grosMargs
    ;
    
$onEcho > resource_allocations.csv
farmers,regions,practices,resrs,Corn,    Bean,  Sorghum,  Peanut
farmer 1,region 1,practice 1,Land,1,1,1,1
farmer 1,region 1,practice 1,Labor,1.42,1.87,1.92,2.64
farmer 1,region 1,practice 1,Mules,1.45,1.27,1.16,1.45
farmer 1,region 1,practice 1,Market,0,0,0,0.98
farmer 2,region 2,practice 2,Land,1,1,1,1
farmer 2,region 2,practice 2,Labor,1.42,1.87,1.92,2.64
farmer 2,region 2,practice 2,Mules,1.45,1.27,1.16,1.45
farmer 2,region 2,practice 2,Market,0,0,0,0.98
$offEcho
$call csv2gdx resource_allocations.csv id=resource_allocations useHeader=y fieldSep=Comma index=1..4 values=5..lastCol trace=3 
$ifE errorLevel<>0 $abort Problems reading resource_allocations.csv!
$gdxIn resource_allocations.gdx
$load farmers = dim1
$load regions = dim2
$load practices = dim3
$load resrs = dim4
$load crops = dim5
$load resource_allocations
$gdxIn
;

$onEcho > resource_endowments.csv
farmers,regions,practices,resrs,resEndows
farmer 1,region 1,practice 1,Labor,16.5
farmer 1,region 1,practice 1,Land,5
farmer 1,region 1,practice 1,Mules,10
farmer 1,region 1,practice 1,Market,0.5
farmer 2,region 2,practice 2,Labor,16.5
farmer 2,region 2,practice 2,Land,5
farmer 2,region 2,practice 2,Mules,10
farmer 2,region 2,practice 2,Market,0.5
$offEcho
$call csv2gdx resource_endowments.csv id=resEndows useHeader=y fieldSep=Comma index=1..4 values=5..lastCol trace=3 
$ifE errorLevel<>0 $abort Problems reading resource_endowments.csv!
$gdxIn resource_endowments.gdx
$load resEndows
$gdxIn
;

$onEcho > activity_gross_margins.csv
farmers,regions,practices,crops,grosMargs,
farmer 1,region 1,practice 1,Corn,1372,
farmer 1,region 1,practice 1,Bean,1219,
farmer 1,region 1,practice 1,Sorghum,1523,
farmer 1,region 1,practice 1,Peanut,4874,
farmer 2,region 2,practice 2,Corn,1372,
farmer 2,region 2,practice 2,Bean,1219,
farmer 2,region 2,practice 2,Sorghum,1523,
farmer 2,region 2,practice 2,Peanut,4874
$offEcho
$call csv2gdx activity_gross_margins.csv id=grosMargs useHeader=y fieldSep=Comma index=1..4 values=5..lastCol trace=3 
$ifE errorLevel<>0 $abort Problems reading activity_gross_margins.csv!

$gdxIn activity_gross_margins.gdx
$load grosMargs
$gdxIn
;

Please note that I have already asked this question here. However, I couldn't work out the suggestion I got from the answer. This is, I have a bit of an idea of the workflow as pseudo code but I could not translate it into actually code that GAMS understands. I know that I can update model parameters in a loop, but I couldn't extract the data for each farmer from the multiple farmer datasets. Note that after adding the 3 identifier columns (i.e. farmers, regions, practices), the dimensions of the data is no longer the same as in the model equations.

Based on the suggestion I received from the previous question, I tried to make up a set frp and loop through it to extract single farmer data and solve the model as in the code chunk below.

sets
    frp(farmers,regions,practices) the looping index
;

$onEcho > frp.csv
farmers,regions,practices,frp,
farmer 1,region 1,practice 1,1,
farmer 2,region 2,practice 2,2
$offEcho
$call csv2gdx frp.csv id=frp useHeader=y fieldSep=Comma index=1..3 values=4 trace=3 
$ifE errorLevel<>0 $abort Problems reading frp.csv!

$gdxIn frp.gdx
$load frp
$gdxIn
;

parameter results(farmers,regions,practices,*,*) 'collect results';

loop(frp(farmers,regions,practices),
* extract data for single case (I assume I need to update the following 3 parameters)
       resEndow(resr) =  resource_endowments(farmer,region,practice,resrs);
       grosMarg (crop) = activity_gross_margins (farmers,regions,practices,crops,grosMargs)
       resource_allocation(resr, crop) = resource_allocations(farmers,regions,practices,resrs)
* solve single case
       SOLVE mayaland maximizing Prft using LP;
* store results in parameter
       results(farmer,region,practice,'x',crops) = x.l(crops);
       results(farmer,region,practice,'profit','-') = Prft.l;
);
* export results to spreadsheet or csv file (have not even tried to export becuase I couldn't make the loop work).

I got a bunch of errors but the first one says:

**** 120 Unknown identifier entered as set **** 141 Symbol declared but no values have been assigned. Check for missing **** data definition, assignment, data loading or implicit assignment **** via a solve statement. **** A wild shot: You may have spurious commas in the explanatory **** text of a declaration. Check symbol reference list.


Solution

  • There is not really a one single general problem you have in the code you tried, but you mixed up the names of different symbols and also names of GDX files with names of symbols loaded from those files. However, it was pretty straight forward to go through your errors as pointed out by GAMS one by one to resolve them all. This is the new loop (I kept your code as comment and the fixed one just below):

    loop(frp(farmers,regions,practices),
    * extract data for single case (I assume I need to update the following 3 parameters)
    *old       resEndow(resr) =  resource_endowments(farmer,region,practice,resrs);
           resEndow(resr) =  resEndows(farmers,regions,practices,resr);
    *old       grosMarg (crop) = activity_gross_margins (farmers,regions,practices,crops,grosMargs)
           grosMarg (crop) = grosMargs (farmers,regions,practices,crop,'grosMargs');
    *old       resource_allocation(resr, crop) = resource_allocations(farmers,regions,practices,resrs)
           resource_allocation(resr, crop) = resource_allocations(farmers,regions,practices,resr,crop);
    * solve single case
           SOLVE mayaland maximizing Prft using LP;
    * store results in parameter
    *old       results(farmer,region,practice,'x',crops) = x.l(crops);
           results(farmers,regions,practices,'x',crop) = x.l(crop);
    *old       results(farmer,region,practice,'profit','-') = Prft.l;
           results(farmers,regions,practices,'profit','-') = Prft.l;
    );