## ams_version=1.0

Model Main_PowerSystExp {
    Comment: {
        "Keywords:
        Linear Program, Stochastic Program, Two-Stage, Control-State Variables, What-If Analysis, Benders Decomposition."
    }
    Section Quantities_and_Units {
        DeclarationSection Declaration_Units {
            Quantity SI_Time_Duration {
                BaseUnit: hour;
                Comment: "Expresses the value for the duration of periods.";
            }
            Quantity SI_Power {
                BaseUnit: W;
                Conversions: GW -> W : # -> # * 1000000000;
                Comment: "Expresses the value for the amount of energy per time unit.";
            }
            Quantity Energy {
                BaseUnit: GWh = hour*GW;
            }
            Quantity Monetary {
                BaseUnit: $;
            }
        }
    }
    Section Common_Elements {
        DeclarationSection Declaration_Common {
            Set PlantTypes {
                Index: p;
                Definition: data { coal, hydro, nuclear};
            }
            Set DemandCateg {
                Index: k;
                Definition: data { base, peak };
            }
            Parameter ExistingCap {
                IndexDomain: p;
                Range: nonnegative;
                Unit: GW;
                Definition: data { coal : 1.75, hydro : 2, nuclear : 0 };
            }
            Parameter CapitalCosts {
                IndexDomain: (p);
                Range: nonnegative;
                Unit: 1000 * $/GW;
                Definition: data { coal : 200, hydro : 500, nuclear : 300 };
            }
            Parameter OperatingCosts {
                IndexDomain: (p);
                Range: nonnegative;
                Unit: 1000 * $/GWh;
                Definition: data { coal : 30, hydro : 10, nuclear : 20 };
            }
            Parameter ImportCosts {
                IndexDomain: k;
                Range: nonnegative;
                Unit: 1000 * $/GWh;
                Definition: data { base : 200, peak : 200 };
            }
            Parameter TotalCap {
                IndexDomain: (p);
                Unit: GW;
                Definition: ExistingCap(p) + NewCap(p);
            }
            Variable NewCap {
                IndexDomain: (p);
                Range: [0, 100];
                Unit: GW;
            }
            Variable TotalCapitalCosts {
                Range: nonnegative;
                Unit: 1000 * $;
                Definition: sum( p, CapitalCosts(p) * (ExistingCap(p) + NewCap(p)) );
            }
            ElementParameter ACase {
                Range: AllCases;
            }
        }
    }
    Section Deterministic_Model {
        DeclarationSection Declaration_Det {
            Parameter InstDemand {
                IndexDomain: (k);
                Range: nonnegative;
                Unit: GW;
                Property: Stochastic;
                InitialData: data { base : 8.25, peak : 10.75 };
            }
            Parameter DemandDuration {
                IndexDomain: (k);
                Range: [0, 24];
                Unit: hour;
                Property: Stochastic;
                InitialData: data { base : 24, peak : 6 };
            }
            Parameter RequiredElectr {
                IndexDomain: (k);
                Range: nonnegative;
                Unit: hour*GW;
                Property: Stochastic;
                Definition: {
                    if k = First(DemandCateg)
                       then InstDemand(k) * DemandDuration(k)
                       else (InstDemand(k) - InstDemand(k-1)) * DemandDuration(k)
                    endif
                }
            }
            Parameter CapImported {
                Range: nonnegative;
                Unit: GW;
                Property: Stochastic;
                Definition: sum(k, ImportCap(k) /$ DemandDuration(k));
            }
            Variable CapAllocation {
                IndexDomain: (p,k);
                Range: nonnegative;
                Unit: GW;
                Property: Stochastic;
                Stage: 2;
            }
            Variable ImportCap {
                IndexDomain: (k);
                Range: nonnegative;
                Unit: GWh;
                Property: Stochastic;
                Stage: 2;
            }
            Variable TotalImportCosts {
                Range: nonnegative;
                Unit: 1000 * $;
                Property: Stochastic;
                Stage: 2;
                Definition: sum (k, ImportCosts(k) * ImportCap(k) );
            }
            Variable TotalOperationCosts {
                Range: nonnegative;
                Unit: 1000 * $;
                Property: Stochastic;
                Stage: 2;
                Definition: sum( k, DemandDuration(k) *  sum( p, OperatingCosts(p) * CapAllocation(p,k)) );
            }
            Variable TotalCosts {
                Unit: 1000 * $;
                Definition: TotalCapitalCosts + TotalImportCosts + TotalOperationCosts;
            }
            Constraint MaxAllocation {
                IndexDomain: (p);
                Unit: GW;
                Definition: sum(k, CapAllocation(p,k)) <= ExistingCap(p) + NewCap(p);
            }
            Constraint SatisfyRequirements {
                IndexDomain: (k);
                Unit: hour*GW;
                Definition: ImportCap(k) + DemandDuration(k) * sum(p, CapAllocation(p,k)) = RequiredElectr(k);
            }
            Constraint NoNuclearForPeak {
                Unit: GW;
                Definition: {
                    CapAllocation('nuclear','peak') = 0 [GW];
                }
            }
            Set DetVariables {
                SubsetOf: AllVariables;
                Definition: {
                    {
                    'NewCap',
                    'CapAllocation',
                    'ImportCap',
                    'TotalCapitalCosts',
                    'TotalImportCosts',
                    'TotalOperationCosts',
                    'TotalCosts'
                    }
                }
                Comment: "TotalOperationCosts,";
            }
            Set DetConstraints {
                SubsetOf: AllConstraints;
                Definition: {
                    {
                    'MaxAllocation',
                    'SatisfyRequirements',
                    'NoNuclearForPeak',
                    'TotalCapitalCosts',
                    'TotalImportCosts',
                    'TotalOperationCosts',
                    'TotalCosts'
                    }
                }
                Comment: "TotalOperationCosts,";
            }
            MathematicalProgram PowerExpModel {
                Objective: TotalCosts;
                Direction: minimize;
                Constraints: DetConstraints;
                Variables: DetVariables;
                Type: LP;
            }
        }
    }
    Section Deterministic_Procedures {
        Procedure EmptyDetVariables {
            Body: {
                empty DetVariables;
            }
        }
        Procedure FixNewCapVariables {
            Body: {
                NewCap(p).Nonvar := 1;
                NewCapVarAreFixed := 1;
            }
        }
        Procedure UnfixNewCapVariables {
            Body: {
                NewCap(p).Nonvar := 0;
                NewCapVarAreFixed := 0;
            }
        }
        Procedure SolveDet_PowerExpModel {
            Body: {
                solve PowerExpModel;
            }
        }
        Procedure SetInstDemAsInCurrentScenario {
            Body: {
                InstDemand(k) := SPInstDemand(k,CurrentScenario);
            }
        }
        Procedure CopyCurrentScenSolInPlan {
            Body: {
                PlanNewCap(Plan(CurrentScenario),p) := NewCap(p);
                
                PlanTotalCap(Plan(CurrentScenario),p) := TotalCap(p);
                
                PlanCapAllocation(Plan(CurrentScenario),p,k) := CapAllocation(p,k);
                
                PlanTotalCosts(Plan(CurrentScenario)) := TotalCosts;
            }
        }
        Procedure SetNewCapAsInSelectedPlan {
            Body: {
                NewCap(p) := PlanNewCap(SelectedPlan,p);
                
                FixNewCapVariables;
            }
        }
        Procedure SetNewCapAsInCurrentPlan {
            Body: {
                NewCap(p) := PlanNewCap(CurrentPlan,p);
            }
        }
        Procedure CopyCurrentPlanSolInScenario {
            Body: {
                PlanCapImportedInScenario(CurrentPlan,CurrentScenario) := CapImported;
                
                PlanTotalCostsInScenario(CurrentPlan,CurrentScenario) := TotalCosts;
                
                !PlanShortageCapInScenario(CurrentPlan,p,CurrentScenario) :=
                !     sum[ k, max[ 0,SPRequiredElectr(k,CurrentScenario) / SPDemandDuration(k,CurrentScenario)
                !                     - sum[ p, CapAllocation(p,k,CurrentScenario) ] ] ];
            }
        }
        Procedure CopySelectedPlanSolInScenario {
            Body: {
                PlanCapImportedInScenario(SelectedPlan,CurrentScenario) := CapImported;
                
                PlanTotalCostsInScenario(SelectedPlan,CurrentScenario) := TotalCosts;
            }
        }
        Procedure SolveScenarioModels {
            Body: {
                for s do
                
                	CurrentScenario := s;
                	SetInstDemAsInCurrentScenario;
                	SolveDet_PowerExpModel;
                	CopyCurrentScenSolInPlan;
                
                endfor;
            }
        }
        Procedure PerformScenarioAnalysis {
            Body: {
                FixNewCapVariables;
                
                for spl do
                
                	CurrentPlan := spl;
                	SetNewCapAsInCurrentPlan;
                
                	for s do
                
                	CurrentScenario := s;
                	SetInstDemAsInCurrentScenario;
                	SolveDet_PowerExpModel;
                	CopyCurrentPlanSolInScenario;
                
                	endfor;
                
                endfor;
                
                UnfixNewcapVariables;
            }
        }
    }
    Section Stochastic_Model_Explicit {
        DeclarationSection Declaration_SP {
            Set SPScenarios {
                SubsetOf: ScenariosAndStoch;
                Index: s;
                Parameter: CurrentScenario;
                Definition: data{ s1, s2, s3, s4 };
            }
            Set ScenariosAndStoch {
                Index: sas;
                Definition: SPScenarios + { 'stoch' };
            }
            Parameter SPInstDemand {
                IndexDomain: (k,s);
                Range: nonnegative;
                Unit: GW;
                Definition: {
                    data {
                    (base,s1) :  8.25, (peak,s1) : 10.75,
                    (base,s2) : 10.00, (peak,s2) : 12.00,
                    (base,s3) :  7.50, (peak,s3) : 10.00,
                    (base,s4) :  9.00, (peak,s4) : 10.50
                    }
                }
            }
            Parameter AverageSPInstDemand {
                IndexDomain: (k);
                Unit: GW;
                Definition: (1/card(SPScenarios) ) * sum(s, SPInstDemand(k,s));
            }
            Parameter SPDemandDuration {
                IndexDomain: (k,s);
                Range: [0, 24];
                Unit: hour;
                Definition: {
                    data {
                    (base,s1) : 24, (peak,s1) : 6,
                    (base,s2) : 24, (peak,s2) : 6,
                    (base,s3) : 24, (peak,s3) : 6,
                    (base,s4) : 24, (peak,s4) : 6
                    }
                }
            }
            Parameter SPRequiredElectr {
                IndexDomain: (k,s);
                Range: nonnegative;
                Unit: hour*GW;
                Definition: (SPInstDemand(k,s) - SPInstDemand(k-1,s)) * SPDemandDuration(k,s);
                Comment: {
                    "if k=First(DemandCateg)
                       then SPInstDemand(k,s) * SPDemandDuration(k,s)
                       else (SPInstDemand(k,s) - SPInstDemand(k-1,s)) * SPDemandDuration(k,s)
                    endif"
                }
            }
            Parameter SPCapImported {
                IndexDomain: (s);
                Range: nonnegative;
                Unit: GW;
                Definition: sum(k, SPImportCap(k,s) / SPDemandDuration(k,s));
            }
            Parameter SPCapSurplus {
                IndexDomain: (s);
                Unit: GW;
                Definition: sum(p,PlanTotalCap(Plan('stoch'),p)) - sum((p,k), SPCapAllocation(p,k,s));
            }
            Parameter TotalCostsInScenarios {
                IndexDomain: (s);
                Unit: 1000 * $;
                Definition: TotalCapitalCosts + SPTotalImpOpCosts(s);
            }
            Parameter Probability {
                IndexDomain: (s);
                Range: [0, 1];
                Definition: data { s1 : 0.25, s2 : 0.25, s3 : 0.25, s4 : 0.25 };
            }
            Variable SPCapAllocation {
                IndexDomain: (p,k,s);
                Range: nonnegative;
                Unit: GW;
            }
            Variable SPImportCap {
                IndexDomain: (k,s);
                Range: nonnegative;
                Unit: hour*GW;
            }
            Variable SPTotalImportCosts {
                IndexDomain: s;
                Range: nonnegative;
                Unit: 1000 * $;
                Definition: sum ( k, ImportCosts(k) * SPImportCap(k,s) );
            }
            Variable SPTotalOperationCosts {
                IndexDomain: (s);
                Range: nonnegative;
                Unit: 1000 * $;
                Definition: sum( k, SPDemandDuration(k,s) *  Sum(p, OperatingCosts(p) * SPCapAllocation(p,k,s)) );
            }
            Variable SPTotalImpOpCosts {
                IndexDomain: (s);
                Range: nonnegative;
                Unit: 1000 * $;
                Definition: SPTotalImportCosts(s) + SPTotalOperationCosts(s);
            }
            Variable TotalExpectedCosts {
                Unit: 1000 * $;
                Definition: TotalCapitalCosts + sum(s, Probability(s)* SPTotalImpOpCosts(s) );
            }
            Constraint SPMaxAllocation {
                IndexDomain: (p,s);
                Unit: GW;
                Definition: sum(k, SPCapAllocation(p,k,s)) <= ExistingCap(p) + NewCap(p);
            }
            Constraint SPSatisfyRequirements {
                IndexDomain: (k,s);
                Unit: hour*GW;
                Definition: SPImportCap(k,s) + SPDemandDuration(k,s) * sum(p, SPCapAllocation(p,k,s)) = SPRequiredElectr(k,s);
            }
            Constraint SPNoNuclearForPeak {
                IndexDomain: (s);
                Unit: GW;
                Definition: {
                    SPCapAllocation('nuclear','peak',s) = 0 [GW];
                }
            }
            Set SPVariables {
                SubsetOf: AllVariables;
                Definition: {
                    data
                    {
                    NewCap,
                    SPCapAllocation,
                    SPImportCap,
                    TotalCapitalCosts,
                    SPTotalImportCosts,
                    SPTotalOperationCosts,
                    SPTotalImpOpCosts,
                    TotalExpectedCosts
                    }
                }
            }
            Set SPConstraints {
                SubsetOf: AllConstraints;
                Definition: {
                    {
                    'SPMaxAllocation',
                    'SPSatisfyRequirements',
                    'SPNoNuclearForPeak',
                    'TotalCapitalCosts',
                    'SPTotalImportCosts',
                    'SPTotalOperationCosts',
                    'SPTotalImpOpCosts',
                    'TotalExpectedCosts'
                    }
                }
            }
            MathematicalProgram SPPowerExpModel {
                Objective: TotalExpectedCosts;
                Direction: minimize;
                Constraints: SPConstraints;
                Variables: SPVariables;
                Type: LP;
            }
        }
    }
    Section SP_Explicit_Procedures {
        Procedure EmptySPVariables {
            Body: {
                empty SPVariables;
            }
        }
        Procedure SolveSP_PowerExpModel {
            Body: {
                solve SPPowerExpModel;
            }
        }
        Procedure CopyStochSolInPlan {
            Body: {
                PlanNewCap(Plan('stoch'),p) := NewCap(p);
                
                PlanTotalCap(Plan('stoch'),p) := TotalCap(p);
                
                PlanTotalCostsInScenario(Plan('stoch'),s) := TotalCapitalCosts + SPTotalImpOpCosts(s);
                
                PlanCapImportedInScenario(Plan('stoch'),s) := SPCapImported(s);
            }
        }
    }
    Section SP_Explicit_Results {
        Set ScenarioPlans {
            SubsetOf: AllPlans;
            Index: spl;
            Definition: data { 'Plan I', 'Plan II', 'Plan III', 'Plan IV' };
        }
        Set AllPlans {
            Index: pl;
            Parameter: CurrentPlan, SelectedPlan;
            Definition: ScenarioPlans + {'Plan V'};
        }
        ElementParameter Plan {
            IndexDomain: sas;
            Range: AllPlans;
            Default: '';
            Definition: {
                if Ord(sas) <= card(SPScenarios)
                   then First( pl | Ord(pl) = Ord(sas) )
                   else Last( AllPlans )
                endif
            }
        }
        ElementParameter ScenOrStoch {
            IndexDomain: (pl);
            Range: ScenariosAndStoch;
            Default: '';
            Definition: {
                if Ord(pl) < card(AllPlans)
                   then First( s | Ord(s) = Ord(pl) )
                   else 'stoch'
                endif
            }
        }
        Parameter NewCapVarAreFixed {
            Range: binary;
            Default: 0;
        }
        StringParameter NewCapVarFixedOrFree {
            Definition: {
                if NewCapVarAreFixed
                   then "New Capacity Variables Are Fixed"
                   else "New Capacity Variables Are Free"
                endif
            }
        }
        ElementParameter NewCapVarStatusColor {
            Range: AllColors;
            Definition: {
                if NewCapVarAreFixed
                   then 'red'
                   else 'green'
                endif
            }
        }
        Parameter PlanNewCap {
            IndexDomain: (pl,p);
            Range: nonnegative;
            Unit: GW;
        }
        Parameter PlanTotalCap {
            IndexDomain: (pl,p);
            Range: nonnegative;
            Unit: GW;
        }
        Parameter PlanCapAllocation {
            IndexDomain: (pl,p,k);
            Unit: GW;
        }
        Parameter PlanShortageCapInScenario {
            IndexDomain: (pl,p,s);
            Unit: GW;
        }
        Parameter PlanTotalCosts {
            IndexDomain: (spl);
            Unit: 1000 * $;
        }
        Parameter PlanCapImportedInScenario {
            IndexDomain: (pl,s);
            Range: nonnegative;
            Unit: GW;
        }
        Parameter PlanTotalCostsInScenario {
            IndexDomain: (pl,s);
            Range: nonnegative;
            Unit: 1000 * $;
        }
        Parameter PlanTotalExpectedCosts {
            IndexDomain: (pl);
            Range: nonnegative;
            Unit: 1000 * $;
            Definition: Sum(s, Probability(s) * PlanTotalCostsInScenario(pl,s));
        }
    }
    Section Stochastic_Model_GMP {
        DeclarationSection Declaration_SP_GMP {
            Set Stages {
                SubsetOf: Integers;
                Index: st;
                Definition: {
                    { 1, 2 }
                }
            }
            Set Scenarios {
                SubsetOf: AllStochasticScenarios;
                Index: sc;
            }
            ElementParameter ScenarioTreeMapping {
                IndexDomain: (sc,st);
                Range: Scenarios;
            }
            Parameter ScenarioProbability {
                IndexDomain: (sc);
            }
            Set StageBranches {
                Index: c;
                Definition: data { S1, S2, S3, S4 };
            }
            Parameter BranchChance {
                IndexDomain: (c);
                Definition: {
                    data
                    {
                    'S1' : 0.25,
                    'S2' : 0.25,
                    'S3' : 0.25,
                    'S4' : 0.25
                    }
                }
            }
            StringParameter SPRoot_Name {
                Definition: "DetOrExp";
            }
            ElementParameter SP_DetOrExp_AuxScen {
                Range: AllStochasticScenarios;
                Definition: StringToElement( AllStochasticScenarios, SPRoot_Name, 0);
            }
            ElementParameter SP_GMP_PowerExpModel {
                Range: AllGeneratedMathematicalPrograms;
            }
        }
    }
    Section SP_GMP_Procedures {
        Procedure CreateScenarioTree {
            Body: {
                empty AllStochasticScenarios;
                cleandependents AllStochasticScenarios;
                
                ScenGen::InitializeChildBranchesCallbackFunction   := 'InitializeBranchesCallback';
                ScenGen::InitializeStochasticDataCallbackFunction  := 'InitializeStochDataCallback';
                ScenGen::InitializeNewScenarioCallbackFunction     := 'InitializeNewScenarioCallback';
                
                option seed := 1234567;
                
                ScenGen::CreateScenarioTree( Stages, Scenarios, ScenarioProbability, ScenarioTreeMapping );
            }
        }
        Procedure SolveSP_GMPmodel {
            Body: {
                
                SP_GMP_PowerExpModel := GMP::Instance::GenerateStochasticProgram(
                                          PowerExpModel,
                                          AllStochasticParameters,
                                          AllStochasticVariables,
                                          Scenarios,
                                          ScenarioProbability,
                                          ScenarioTreeMapping,
                                          SPRoot_Name,
                                          GenerationMode : 'SubstituteStochasticVariables',
                                          Name : "StochasticGMP_PowerExpModel" );
                
                GMP::Instance::Solve( SP_GMP_PowerExpModel );
            }
        }
        Procedure SolveSP_GMPmodel_Benders {
            Body: {
                
                SP_GMP_PowerExpModel := GMP::Instance::GenerateStochasticProgram(
                                          PowerExpModel,
                                          AllStochasticParameters,
                                          AllStochasticVariables,
                                          Scenarios,
                                          ScenarioProbability,
                                          ScenarioTreeMapping,
                                          SPRoot_Name,
                                          GenerationMode : 'SubstituteStochasticVariables',
                                          Name : "StochasticGMP_PowerExpModel" );
                
                StochDecom::DoStochasticDecomposition( SP_GMP_PowerExpModel, Stages, Scenarios);
            }
        }
        Procedure EmptySP_GMPVariables {
            Body: {
                empty ScenarioTreeMapping;
                empty ScenarioProbability;
                empty NewCap.Stochastic;
                empty TotalCapitalCosts.Stochastic;
                empty CapAllocation.Stochastic;
                empty ImportCap.Stochastic;
                empty TotalImportCosts.Stochastic;
                empty TotalOperationCosts.Stochastic;
                empty TotalCosts.Stochastic;
                empty Scenarios;
            }
        }
    }
    Section SP_GMP_Results {
        Parameter TotalCap_GMP {
            IndexDomain: (p);
            Unit: GW;
            Definition: ExistingCap(p) + NewCap.Stochastic( SP_DetOrExp_AuxScen, p);
        }
    }
    Section Scenario_Generation_Callbacks {
        Procedure InitializeBranchesCallback {
            Arguments: (SomeStage,Scenario,ChildBranches,ChildBranchName);
            Body: {
                ChildBranches := { 1 .. card(StageBranches) };
                
                ChildBranchName(cb) := FormatString( "%e", Element( StageBranches, ord(cb) ) );
            }
            ElementParameter SomeStage {
                Range: Integers;
                Property: Input;
            }
            ElementParameter Scenario {
                Range: AllStochasticScenarios;
                Property: Input;
            }
            Set ChildBranches {
                SubsetOf: Integers;
                Index: cb;
                Property: Output;
            }
            StringParameter ChildBranchName {
                IndexDomain: (cb);
                Property: Output;
            }
        }
        Procedure InitializeStochDataCallback {
            Arguments: (CurrentStage,CurrentScenario,CurrentChildBranch, CurrentChildBranchName);
            Body: {
                
                CurrentChildBranchElem := StringToElement(StageBranches, CurrentChildBranchName, 0);
                
                if CurrentChildBranchElem <> ''
                       then
                          CurrentSPScenario := First( s | Ord(s) = Ord(CurrentChildBranchElem)  );
                          InstDemandValue(k) := SPInstDemand(k, CurrentSPScenario);
                       else
                          InstDemandValue(k) := AverageSPInstDemand(k);
                     endif;
                
                InstDemand.Stochastic( CurrentScenario, k) := InstDemandValue(k);
                
                DemandDuration.Stochastic ( CurrentScenario, k) := DemandDuration(k);
                
                !RequiredElectr.Stochastic( CurrentScenario, k):=
                !  if k = First(DemandCateg)
                !     then InstDemand.Stochastic( CurrentScenario, k)
                !          * DemandDuration.Stochastic( CurrentScenario, k)
                !     else (InstDemand.Stochastic( CurrentScenario, k) - InstDemand.Stochastic( CurrentScenario, k-1))
                !          * DemandDuration.Stochastic( CurrentScenario, k)
                !  endif;
                
                
                RelativeScenarioWeight := BranchChance(CurrentChildBranchElem);
                
                return /*relative weight*/ RelativeScenarioWeight;
            }
            ElementParameter CurrentStage {
                Range: Integers;
                Property: Input;
            }
            ElementParameter CurrentScenario {
                Range: AllStochasticScenarios;
                Property: Input;
            }
            ElementParameter CurrentChildBranch {
                Range: Integers;
                Property: Input;
            }
            StringParameter CurrentChildBranchName {
                Property: Input;
            }
            ElementParameter CurrentChildBranchElem {
                Range: StageBranches;
            }
            ElementParameter CurrentSPScenario {
                Range: SPScenarios;
            }
            Parameter InstDemandValue {
                IndexDomain: (k);
                Unit: GW;
            }
            Parameter RelativeScenarioWeight;
        }
        Procedure InitializeNewScenarioCallback {
            Arguments: (SomeStage,NewScenario,RepresentativeScenario);
            Body: {
                InstDemand.Stochastic( NewScenario, k) := InstDemand.Stochastic( RepresentativeScenario, k);
                
                DemandDuration.Stochastic ( NewScenario, k) := DemandDuration.Stochastic( RepresentativeScenario, k);
                
                !RequiredElectr.Stochastic( NewScenario, k):= RequiredElectr.Stochastic( RepresentativeScenario, k);
            }
            Comment: "(SomeStage,NewScenario,RepresentativeScenario)";
            ElementParameter SomeStage {
                Range: Integers;
                Property: Input;
            }
            ElementParameter NewScenario {
                Range: AllStochasticScenarios;
                Property: Input;
            }
            ElementParameter RepresentativeScenario {
                Range: AllStochasticScenarios;
                Property: Input;
            }
        }
    }
    Section GUI_Support_Section {
        DeclarationSection GUI_Declarations {
            StringParameter DescriptionFile {
                Definition: "Description.txt";
            }
        }
        Procedure Restart {
            Body: {
                EmptyDetVariables;
                EmptySPVariables;
                EmptySP_GMPVariables;
                EmptyResults;
                UnfixNewCapVariables;
            }
        }
        Procedure EmptyResults {
            Body: {
                empty PlanNewCap, PlanTotalCap, PlanTotalCosts, PlanCapImportedInScenario, PlanTotalCostsInScenario;
            }
        }
    }
    Procedure MainInitialization {
        Body: {
            CapAllocation('nuclear','peak')         := 0;
            CapAllocation.NonVar( 'nuclear','peak') := 1;
            
            SPCapAllocation('nuclear','peak',s)         := 0;
            SPCapAllocation.NonVar( 'nuclear','peak',s) := 1;
            
            SelectedPlan := First( AllPlans );
        }
    }
    Procedure MainExecution;
    Procedure MainTermination {
        Body: {
            return 1;
        }
    }
    Module Scenario_Generation_Module {
        SourceFile: "%AIMMSMODULES%\\ScenarioGeneration.ams";
    }
    Module Stochastic_Decomposition_Module {
        SourceFile: "%AIMMSMODULES%\\StochasticDecomposition.ams";
        Comment: {
            "This module contains an implementation of the Nested Benders algorithm using
            the functions from the GMP library. It can be used to solve linear stochastic
            models without integer/binary variables.
            
            The Nested Benders algorithm is based on a reformulation of the original model
            as a sequence of smaller models. The solution of the original model can be
            achieved by solving the sequence of models iteratively until a terminating
            condition is reached. A detailed discussion of the Nested Benders algorithm
            can be found in the AIMMS Language Reference, and in the following references:
            
            - F. Altenstedt, Memory consumption versus computational time in
              nested benders decompostion for stochastic linear programmings, Tech.
              report, Chalmers University of Technology, Goteborg, Sweden, 2003.
            
            - M. Dempster and R. Thompson, Parallelization and aggregation of
              nested benders decomposition, Annals of Operations Research 81
              (1998), pp. 163-187."
        }
    }
}