提取数据以更新模型参数并解决 GAMS 中的最大化问题

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

我有几个农民,我想在 GAMS 中对他们每个人进行优化(利润最大化)。我可以为一个农民做这件事,所以我的问题是如何迭代地让它适用于多个农民。

我将数据记录在 3 个不同的 .csv 文件中,如下(见代码):

下面的代码可以满足我对单个农民案例的要求。

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;

我的问题是如何使上述模型适用于多个农民,并以全面的布局导出结果,根据农民的姓名、农民所在地区和农民的做法(参见下面的数据)清楚地识别每个农民。为此,我只展示了数据在我这边的样子。我对要编写的代码没有太多想法(这就是我问这个问题的原因)。请注意,在下面的数据中,我只是从单个农民数据集中复制了相同的信息,并添加了 3 个额外的列以明确 farmer 1farmer 2 之间的区别。因此,我们希望这两个解决方案是相同的。我还想将解决方案导出到 .csv 文件,以便我可以进一步处理它。

*******************************************************************
* 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
;

请注意我已经问过这个问题here。但是,我无法弄清楚从答案中得到的建议。也就是说,我对作为伪代码的工作流有一些想法,但我无法将其转化为 GAMS 理解的实际代码。我知道我可以在 loop 中更新模型参数,但我无法从多个农民数据集中提取每个农民的数据。请注意,在添加 3 个标识符列(即农民、地区、实践)后,数据的维度不再与模型方程中的维度相同。

根据我从上一个问题中收到的建议,我尝试组成一个集合 frp 并循环遍历它以提取单个农民数据并求解模型,如下面的代码块所示。

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).

我遇到了一堆错误,但第一个说:

**** 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.

在您尝试的代码中并没有真正的单一一般问题,但是您混淆了不同符号的名称以及 GDX 文件的名称与从这些文件加载​​的符号的名称。然而,正如 GAMS 指出的那样,一个一个地解决你的错误是非常直接的。这是新循环(我将您的代码保留为注释,固定的代码就在下面):

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;
);