Skip to content

Commit

Permalink
Merge pull request #1619 from robertpietzcker/2024-03-14_NashSolve
Browse files Browse the repository at this point in the history
Improve the handling of solve results of the solitr loop, and add a switch so that also non-optimal results are rerun.
  • Loading branch information
robertpietzcker authored Mar 19, 2024
2 parents e8f0566 + 02b7a16 commit f430976
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 48 deletions.
12 changes: 12 additions & 0 deletions main.gms
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,12 @@ $offdigit
*** turn profiling off (0) or on (1-3, different levels of detail)
option profile = 0;

file foo_msg; !! This creates a dummy output file with a well-defined output format:
foo_msg.nr = 1; !! namely F-format (decimal) (and not E-format = scientific notation)
*** The file can throughout the code be activated with `putclose foo_msg;` and used in the form `put_utility foo_msg "msg" / "xxxx"` to print out xxxx to full.lst
*** and be sure that the numeric format is F-format


*' @title{extrapage: "00_configuration"} Configuration
*' @code{extrapage: "00_configuration"}
*--------------------------------------------------------------------------
Expand Down Expand Up @@ -1644,6 +1650,12 @@ $setglobal c_testOneRegi_region EUR !! def = EUR !! regexp = [A-Z]{3}
*** cm_taxrc_RE "switch to define whether tax on (CO2 content of) energy imports is recycled to additional direct investments in renewables (wind, solar and storage)"
$setglobal cm_taxrc_RE none !! def = none !! regexp = none|REdirect

*' cm_repeatNonOpt "should nonoptimal regions be solved again?"
*'
*' * (off): no, only infeasable regions are repeated, standard setting
*' * (yes): also non-optimal regions are solved again, up to cm_solver_try_max
$setglobal cm_repeatNonOpt off

*' @stop

*-------------------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions modules/80_optimization/nash/declarations.gms
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ p80_handle(all_regi) "parallel mode handle parameter"
p80_repy(all_regi,solveinfo80) "summary report from solver "
p80_repy_iteration(all_regi,solveinfo80,iteration) "summary report from solver in iteration"
p80_repyLastOptim(all_regi,solveinfo80) "p80_repy from last iteration"
p80_repy_thisSolitr(all_regi,solveinfo80) "p80_repy from the current solitr - only shows results for regions that were run in this solItr"
p80_repy_nashitr_solitr(all_regi,solveinfo80,iteration,sol_itr) "summary report from solver in nash iteration and solver iteration"
p80_messageFailedMarket(tall,all_enty) "nash display helper"
p80_messageShow(convMessage80) "nash display helper"
Expand Down
43 changes: 22 additions & 21 deletions modules/80_optimization/nash/postsolve.gms
Original file line number Diff line number Diff line change
Expand Up @@ -274,31 +274,31 @@ loop(trade$(NOT tradeSe(trade)),
);
);

*** critertion "infes": and are all solutions optimal?
*** critertion "infes": is any region neither optimal nor intermediate non-optimal -> then it is infeasible
loop(regi,
if((p80_repy(regi,'modelstat') ne 2) and (p80_repy(regi,'modelstat') ne 7),
s80_bool = 0;
p80_messageShow("infes") = YES;
);
if( (p80_repy(regi,'modelstat') ne 2) and (p80_repy(regi,'modelstat') ne 7), !! 2 is optimal, 7 nonopt,
s80_bool = 0;
p80_messageShow("infes") = YES;
);
*** critertion "nonopt": The next lines are a workaround for the status 7
*** problem. If the objective value does not differ too much from the last known
*** optimal solution, accept this solution as if it were optimal.
p80_convNashObjVal_iter(iteration,regi) = p80_repy(regi,'objval') - p80_repyLastOptim(regi,'objval');
if (1 le iteration.val,
!! no last iteration if this is the first; NA value in p80_repyLastOptim is
!! sticky, so test this separately
if ( p80_repy(regi,'modelstat') eq 7
!! The 1E-4 are quite arbitrary. One should do more research on how
!! the solution differs over iteration when status 7 occurs.
AND p80_convNashObjVal_iter(iteration,regi) lt - 1e-4,
s80_bool = 0;
p80_messageShow("nonopt") = YES;
display "Not all regions were status 2 in the last iteration. The deviation of the objective function from the last optimal solution is too large to be accepted:";
s80_dummy = p80_repy(regi,'objval') - p80_repyLastOptim(regi,'objval');
display s80_dummy;
);
);
); !!regi
p80_convNashObjVal_iter(iteration,regi) = p80_repy(regi,'objval') - p80_repyLastOptim(regi,'objval');
if (1 le iteration.val,
!! no last iteration if this is the first; NA value in p80_repyLastOptim is
!! sticky, so test this separately
if ( p80_repy(regi,'modelstat') eq 7
!! The 1E-4 are quite arbitrary. One should do more research on how
!! the solution differs over iteration when status 7 occurs.
AND p80_convNashObjVal_iter(iteration,regi) lt - 1e-4,
s80_bool = 0;
p80_messageShow("nonopt") = YES;
display "Not all regions were status 2 in the last iteration. The deviation of the objective function from the last optimal solution is too large to be accepted:";
s80_dummy = p80_repy(regi,'objval') - p80_repyLastOptim(regi,'objval');
display s80_dummy;
);
);
); !! loop over regi

*** criterion only for checking, not applied anymore: are the anticipation terms sufficienctly small?
p80_fadeoutPriceAnticip_iter(iteration) = sm_fadeoutPriceAnticip;
Expand Down Expand Up @@ -406,6 +406,7 @@ display p80_repy;

display "trade convergence indicators";
display p80_surplusMaxTolerance, p80_surplusMax2100;
display p80_defic_trade, p80_defic_sum,p80_defic_sum_rel;

display "Reasons for non-convergence in this iteration (if not yet converged)";

Expand Down
84 changes: 57 additions & 27 deletions modules/80_optimization/nash/solve.gms
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ hybrid.solvelink = 0;
$endif.debug

loop (all_regi,
!! only solve for regions that do not have a valid solution for this nash
!! iteration
if ( sol_itr.val gt 1
AND ( p80_repy(all_regi,"modelstat") eq 2
OR p80_repy(all_regi,"modelstat") eq 7),

p80_repy(all_regi,solveinfo80) = 0;
!! only solve for regions that do not have a valid solution for this nash iteration
if ( sol_itr.val gt 1
AND ( p80_repy(all_regi,"modelstat") eq 2
$ifthen.repeatNonOpt "%cm_repeatNonOpt%" == "off"
OR p80_repy(all_regi,"modelstat") eq 7
$endif.repeatNonOpt
),

p80_repy_thisSolitr(all_regi,solveinfo80) = 0;
continue;
);

Expand Down Expand Up @@ -49,11 +51,11 @@ loop (all_regi,
solve hybrid using nlp maximizing vm_welfareGlob;

$ifthene.debug (sameas("%cm_nash_mode%","serial"))OR(sameas("%cm_nash_mode%","debug"))
p80_repy(all_regi,"solvestat") = hybrid.solvestat;
p80_repy(all_regi,"modelstat") = hybrid.modelstat;
p80_repy(all_regi,"resusd") = hybrid.resusd;
p80_repy(all_regi,"objval") = hybrid.objval;
if (p80_repy(all_regi,"modelstat") eq 2,
p80_repy_thisSolitr(all_regi,"solvestat") = hybrid.solvestat;
p80_repy_thisSolitr(all_regi,"modelstat") = hybrid.modelstat;
p80_repy_thisSolitr(all_regi,"resusd") = hybrid.resusd;
p80_repy_thisSolitr(all_regi,"objval") = hybrid.objval;
if (p80_repy_thisSolitr(all_regi,"modelstat") eq 2,
p80_repyLastOptim(all_regi,"objval") = p80_repy(all_regi,"objval");
);
$endif.debug
Expand All @@ -65,13 +67,15 @@ $endif.debug
$ifthen.parallel %cm_nash_mode% == "parallel"
repeat
loop (all_regi$handlecollect(p80_handle(all_regi)),
p80_repy(all_regi,"solvestat") = hybrid.solvestat;
p80_repy(all_regi,"modelstat") = hybrid.modelstat;
p80_repy(all_regi,"resusd") = hybrid.resusd;
p80_repy(all_regi,"objval") = hybrid.objval;
p80_repy_thisSolitr(all_regi,"solvestat") = hybrid.solvestat;
p80_repy_thisSolitr(all_regi,"modelstat") = hybrid.modelstat;
p80_repy_thisSolitr(all_regi,"resusd") = hybrid.resusd;
p80_repy_thisSolitr(all_regi,"objval") = hybrid.objval;

* p80_repyLatestSolve(all_regi,solveinfo80) = p80_repy(all_regi,solveinfo80);

if (p80_repy(all_regi,"modelstat") eq 2,
p80_repyLastOptim(all_regi,"objval") = p80_repy(all_regi,"objval");
if (p80_repy_thisSolitr(all_regi,"modelstat") eq 2,
p80_repyLastOptim(all_regi,"objval") = p80_repy_thisSolitr(all_regi,"objval");
);

display$handledelete(p80_handle(all_regi)) "trouble deleting handles" ;
Expand All @@ -83,19 +87,39 @@ $endif.parallel

regi(all_regi) = YES;


display p80_repy_thisSolitr;
display p80_repy;

*** internal nash helper paramter:
pm_SolNonInfes(regi) = 0;
p80_SolNonOpt(regi) = 0;

putclose foo_msg;
*** This putclose serves to make foo_msg the last "active" put file, and thus makes GAMS use the foo_msg formating (namely F-format, not scientific E-format)
*** Otherwise, the following put messages will try to write modelstat in scientif format, throwing errors because of insufficient space

loop (regi,
if( (p80_repy_thisSolitr(regi,"solvestat") > 0) ,
put_utility foo_msg "msg" / "Solitr:" sol_itr.tl:2:0 " " regi.tl:4:0 " updated. Modstat new " p80_repy_thisSolitr(regi,"modelstat"):2:0 ", old " p80_repy(regi,"modelstat"):2:0 "; Resusd new" p80_repy_thisSolitr(regi,"resusd"):5:0 ", old" p80_repy(regi,"resusd"):5:0 "; Obj new" p80_repy_thisSolitr(regi,"objval"):7:3 ", old" p80_repy(regi,"objval"):7:3 ;
p80_repy(regi,solveinfo80) = p80_repy_thisSolitr(regi,solveinfo80); !! copy info from this Solitr into p80_repy
else
put_utility foo_msg "msg" / "Solitr:" sol_itr.tl:2:0 " " regi.tl:4:0 " not updated. Modstat new " p80_repy_thisSolitr(regi,"modelstat"):2:0 ", old " p80_repy(regi,"modelstat"):2:0 "; Resusd new" p80_repy_thisSolitr(regi,"resusd"):5:0 ", old" p80_repy(regi,"resusd"):5:0 "; Obj new" p80_repy_thisSolitr(regi,"objval"):7:3 ", old" p80_repy(regi,"objval"):7:3 ;
);

if (p80_repy(regi,"modelstat") eq 2 OR p80_repy(regi,"modelstat") eq 7,
pm_SolNonInfes(regi) = 1;
);
if (p80_repy(regi,"modelstat") eq 7, p80_SolNonOpt(regi) = 1);
);

*** set o_modelstat to the highest value across all regions, ignoring status 7
*** set o_modelstat to the highest value across all regions
o_modelstat
= smax(regi, p80_repy(regi,"modelstat")$(p80_repy(regi,"modelstat") ne 7));
$ifthen.repeatNonOpt "%cm_repeatNonOpt%" == "off"
= smax(regi, p80_repy(regi,"modelstat")$(p80_repy(regi,"modelstat") ne 7)); !! ignoring status 7
$else.repeatNonOpt
= smax(regi, p80_repy(regi,"modelstat")); !! also taking into account status 7
$endif.repeatNonOpt

*** in cm_nash_mode=debug mode, enable solprint for next sol_itr when last
*** iteration was non-optimal:
Expand All @@ -105,16 +129,22 @@ if (o_modelstat ne 2,
);
$endif.solprint

p80_repy_iteration(all_regi,solveinfo80,iteration)$(
p80_repy(all_regi,solveinfo80) )
p80_repy_iteration(all_regi,solveinfo80,iteration)$( p80_repy_thisSolitr(all_regi,solveinfo80) ) !! add information if this region was solved in this iteration
!! store sum of resusd for all sol_itrs
= ( p80_repy_iteration(all_regi,solveinfo80,iteration)
+ p80_repy(all_regi,solveinfo80)
+ p80_repy_thisSolitr(all_regi,solveinfo80)
)$( sameas(solveinfo80,"resusd") )
+ p80_repy(all_regi,solveinfo80)$( NOT sameas(solveinfo80,"resusd") );
+ p80_repy_thisSolitr(all_regi,solveinfo80)$( NOT sameas(solveinfo80,"resusd") );

p80_repy_nashitr_solitr(all_regi,solveinfo80,iteration,sol_itr)$( p80_repy_thisSolitr(all_regi,solveinfo80) ) !! add information if this region was solved in this iteration
= p80_repy_thisSolitr(all_regi,solveinfo80);

put_utility "msg" / "Solve overview: The following are the results for iteration " iteration.tl:3:0 " , sol_itr " sol_itr.tl:3:0 ;
display o_modelstat;
display p80_repy;
display p80_repy_thisSolitr;
display p80_repy_iteration;
display p80_repy_nashitr_solitr;

p80_repy_nashitr_solitr(all_regi,solveinfo80,iteration,sol_itr)$(
p80_repy(all_regi,solveinfo80) )
= p80_repy(all_regi,solveinfo80);

*** EOF ./modules/80_optimization/nash/solve.gms

0 comments on commit f430976

Please sign in to comment.