<jupyter_start><jupyter_text>model 1: planningmodA power system investment model to determine the optimal installed capacity for each generator. model 2 operationalModelA power system opteration model to determine the ouput of given generators to obtain the least overall operational cost. linking model 1 with model 21. run model 1, the capacities determined by planning model 1 will feed into operational model 2 as inputs2. run model 2, valiate the performance of proposed generator mix. if any violaton of operational constraint occurs, then the degree of violaton will feed back to planning model as addional inputs (formulated using Benders decomposition) for its next run.3. repeat step 1 and 2 until the two models convege.<jupyter_code># call planning model
planmod = MOD(lang='Julia')
planmod.newmodel(modelfile="planningmod.jl",jumpmod_name='rmp')
# call operation model
opermod = MOD(lang='AMPL')
opermod.newmodel(modelfile="OperationalModel.run")
# declare the indexing sets of exchange items
# index_set_opermod = ['Gcoal', 'Gocgt', 'Gccgt', 'Gnucl', 'Gdies']
# index_set_planmod =  ['coal', 'ocgt', 'ccgt', 'diesel', 'nuclear']

mapping_opermod2planmod = {'Gcoal': 'coal',
                             'Gocgt': 'ocgt',
                             'Gccgt': 'ccgt',
                             'Gnucl': 'nuclear',
                             'Gdies': 'diesel'}

mapping_planmod2opermod = {'coal': 'Gcoal',
                            'ocgt': 'Gocgt',
                            'ccgt': 'Gccgt',
                            'diesel': 'Gdies',
                            'nuclear': 'Gnucl'}
ϵ = .001 # set the stop threshold value for iteration
for i in list(range(30)):
    
    # solve planning model and get values of the exchange items
    planmod.solve()
    L = planmod.getObjectiveValue()
    x_fix = planmod.getValue('rmp[:x_inv][:]')

    # re-order the exchange items acording to the receiving model (operational model)
    # and pass over
    x_fix = CrossMapping(x_fix, mapping_planmod2opermod)
    opermod.getParam("pG_ub").setValues(x_fix)
    
    # solve operational mode and get values of the linking items
    opermod.solve()
    θ = opermod.getValue("oper")
#     θ = opermod.getObjectiveValue()
    λ = [c[1].dual() for c in opermod.getConstraint("lambda_pG")] #get constraint dual value into a list
    λ = CrossMapping(λ, mapping_opermod2planmod)

    # add addtional constraint (cut) into planning model
    # note: the bender algothrim is implemented in Julia, so involve some JuMP expression
    U = planmod.getValue('rmp[:cx]') + θ
    planmod.jumpworkspace.x_fix = x_fix # put this value back into Julia
    planmod.jumpworkspace.θ = θ
    planmod.jumpworkspace.λ = λ
    planmod.eval('@constraint(rmp,rmp[:θ] >= θ + sum(λ[i] * (rmp[:x_inv][i] - x_fix[i]) for i in 1:5))') # JuMP expression

    # check the gap, break if converge
    Δ = (U - L) / U * 100
    if Δ <= ϵ:
        break
# print the results
print(" ")
print("---------------------------------------------------------------------")
print("Investment Decisions")
print("coal    -> {} GW".format(round(x_fix[0] / 1000)))
print("ocgt    -> {} GW".format(round(x_fix[1] / 1000)))
print("ccgt    -> {} GW".format(round(x_fix[2] / 1000)))
print("diesel  -> {} GW".format(round(x_fix[3] / 1000)))
print("nuclear -> {} GW".format(round(x_fix[4] / 1000)))
print(" ")

print("Cost for investment -> {} m£".format(round(planmod.getValue('rmp[:cx]') / 1e6)))
print("Cost for operation  -> {} m£".format(round(θ / 1e6)))<jupyter_output>---------------------------------------------------------------------
Investment Decisions
coal    -> 0.0 GW
ocgt    -> 35.0 GW
ccgt    -> 12.0 GW
diesel  -> 5.0 GW
nuclear -> 0.0 GW
 
Cost for investment -> 1220 m£
Cost for operation  -> 6176 m£
{'fraction_non_alphanumeric': 0.15783898305084745, 'fraction_numerical': 0.020391949152542374, 'mean_word_length': 2.721182266009852, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '96653', 'license': 'MIT', 'n_tokens_mistral': 1254, 'n_tokens_neox': 1142, 'n_words': 361, 'path': 'examples/LinkMultiMods.ipynb', 'repo_name': 'sunedin/CESIAPI', 'size': '3776'}