1717module ABCEfunctions
1818
1919using ArgParse, CPLEX,
20- Requires, SQLite, DataFrames, CSV, JuMP, GLPK, Cbc, Logging, Tables, HiGHS, Statistics
20+ Requires, SQLite, DataFrames, CSV, JuMP, GLPK, Cbc, Logging, Tables, HiGHS, Statistics, MathOptInterface
2121
2222include (" ./dispatch.jl" )
2323using . Dispatch
@@ -1351,10 +1351,13 @@ function add_constraint_shortage_protection(
13511351 transform! (agent_pf, [:num_units , :capacity , :capacity_factor ] => ((num, cap, cf) -> num .* cap .* cf) => :total_derated_cap )
13521352 agent_year_derated_cap = sum (agent_pf[! , :total_derated_cap ])
13531353
1354+ cname = string (" shortage_protection_y" , i)
1355+
13541356 @constraint (
13551357 m,
13561358 transpose (m[:u ] .* PA_summaries[:, :current ]) * marg_derated_cap[:, i] >=
1357- agent_year_derated_cap * margin
1359+ agent_year_derated_cap * margin,
1360+ base_name = cname,
13581361 )
13591362 end
13601363 end
@@ -1474,6 +1477,7 @@ function add_constraint_FM_floors(
14741477 )
14751478 for i= 1 : settings[" agent_opt" ][" fin_metric_horizon" ]
14761479 ) / settings[" agent_opt" ][" fin_metric_horizon" ] >= 0 ,
1480+ base_name = " FCDR_RCDR" ,
14771481 )
14781482
14791483 # Limit the average ICR value over the horizon to its floor
@@ -1483,7 +1487,8 @@ function add_constraint_FM_floors(
14831487 agent_fs[i, :FCF ] / 1e9 + sum (m[:u ] .* marg_FCF[:, i])
14841488 + (1 - ICR_solo_floor) * (- 1 ) * (agent_fs[i, :interest_payment ] / 1e9 + sum (m[:u ] .* marg_int[:, i]))
14851489 for i = 1 : settings[" agent_opt" ][" fin_metric_horizon" ]
1486- ) >= 0
1490+ ) >= 0 ,
1491+ base_name = " ICR" ,
14871492 )
14881493
14891494 return m
@@ -1502,11 +1507,13 @@ function add_constraint_max_new_capacity(
15021507
15031508 for i = 1 : size (PA_summaries)[1 ]
15041509 if PA_summaries[i, :project_type ] == " new_xtr"
1510+ cname = string (PA_summaries[i, :unit_type ], " _new_xtr_L" , PA_summaries[i, :lag ])
15051511 @constraint (
15061512 m,
15071513 m[:u ][i] .* exp_PA_summaries[i, :capacity ] .<=
15081514 convert (Int64, exp_PA_summaries[i, :allowed ]) .*
1509- max_type_newcap
1515+ max_type_newcap,
1516+ base_name = cname,
15101517 )
15111518 end
15121519 end
@@ -1530,21 +1537,27 @@ function add_constraint_max_retirements(
15301537 if PA_summaries[i, :project_type ] == " retirement"
15311538 unit_type = PA_summaries[i, :unit_type ]
15321539 ret_pd = PA_summaries[i, :ret_pd ]
1540+
15331541 asset_count = filter (
15341542 [:unit_type , :retirement_pd ] =>
15351543 (x, y) -> x == unit_type && y == ret_pd,
15361544 asset_counts,
1537- )[
1538- 1 ,
1539- :count ,
1540- ]
1545+ )[1 , :count ]
1546+
15411547 max_retirement = (
15421548 convert (Int64, PA_summaries[i, :allowed ]) .* min (
15431549 asset_count,
15441550 max_type_rets,
15451551 )
15461552 )
1547- @constraint (m, m[:u ][i] .<= max_retirement)
1553+
1554+ cname = string (unit_type, " _retlimit_" , ret_pd, " -" , PA_summaries[i, :lag ])
1555+
1556+ @constraint (
1557+ m,
1558+ m[:u ][i] .<= max_retirement,
1559+ base_name = cname,
1560+ )
15481561 end
15491562 end
15501563
@@ -1597,7 +1610,8 @@ function add_constraint_retireable_asset_limit(
15971610 @constraint (
15981611 m,
15991612 sum (ret_summation_matrix[i, :] .* m[:u ]) <=
1600- retireable_asset_counts[i, :count ]
1613+ retireable_asset_counts[i, :count ],
1614+ base_name = " retlimit_exist_$i "
16011615 )
16021616 end
16031617
@@ -1737,12 +1751,14 @@ function add_constraint_retirement_scheduling_limit(
17371751 for i = 1 : max_horizon
17381752 @constraint (
17391753 m,
1740- sum (transpose (m[:u ]) * type_PA_rets[:, i]) <= type_ops[i, :num_units ]
1754+ sum (transpose (m[:u ]) * type_PA_rets[:, i]) <= type_ops[i, :num_units ],
1755+ base_name = string (unit_type, " _retlimit_ops_y" , i),
17411756 )
17421757
17431758 @constraint (
17441759 m,
1745- sum (transpose (m[:u ]) * type_PA_rets[:, i]) <= settings[" agent_opt" ][" max_type_rets_per_pd" ]
1760+ sum (transpose (m[:u ]) * type_PA_rets[:, i]) <= settings[" agent_opt" ][" max_type_rets_per_pd" ],
1761+ base_name = string (unit_type, " _retlimit_global_y" , i),
17461762 )
17471763
17481764 # The following set of three constraints are collectively
@@ -1754,17 +1770,20 @@ function add_constraint_retirement_scheduling_limit(
17541770
17551771 @constraint (
17561772 m,
1757- m[:z ][z_count, i] >= type_rets[i, :num_units ]
1773+ m[:z ][z_count, i] >= type_rets[i, :num_units ],
1774+ base_name = string (" retlimit_z1_" , unit_type, i),
17581775 )
17591776
17601777 @constraint (
17611778 m,
1762- m[:z ][z_count, i] >= sum (transpose (m[:u ]) * type_PA_rets[:, i])
1779+ m[:z ][z_count, i] >= sum (transpose (m[:u ]) * type_PA_rets[:, i]),
1780+ base_name = string (" retlimit_z2_" , unit_type, i),
17631781 )
17641782
17651783 @constraint (
17661784 m,
1767- sum (m[:z ][z_count, j] for j= 1 : i) <= type_ops[1 , :num_units ]
1785+ sum (m[:z ][z_count, j] for j= 1 : i) <= type_ops[1 , :num_units ],
1786+ base_name = string (" retlimit_z3_" , unit_type, i),
17681787 )
17691788
17701789 end
@@ -1926,25 +1945,39 @@ function set_up_model(
19261945end
19271946
19281947
1929- function solve_model (m, verbosity, threshold= 1e-8 )
1930- optimize! (m)
1948+ function save_constraint_data (db, m, agent_id, pd)
1949+ cons_data = DataFrame (
1950+ agent_id = Int64[],
1951+ pd = Int64[],
1952+ name = String[],
1953+ equation = String[],
1954+ primal_value = Float64[],
1955+ dual_value = Float64[],
1956+ )
1957+
1958+ for (F, S) in list_of_constraint_types (m)
1959+ for con in all_constraints (m, F, S)
1960+ if (F != VariableRef)
1961+ # Get separate name and equation info
1962+ con_eq = JuMP. constraint_string (MIME (" text/plain" ), con)
1963+ if occursin (JuMP. name (con), con_eq)
1964+ lname = JuMP. name (con) * " : "
1965+ con_eq = replace (con_eq, lname => " " )
1966+ end
19311967
1932- if verbosity >= 3
1933- if string (termination_status .(m)) == " OPTIMAL"
1934- for (F, S) in list_of_constraint_types (m)
1935- for con in all_constraints (m, F, S)
1936- println (con)
1937- println (JuMP. value (con))
1938- end
1968+ con_data = [agent_id, pd, JuMP. name (con), con_eq, JuMP. value (con), JuMP. dual (con)]
1969+ DBInterface. execute (
1970+ db,
1971+ " INSERT INTO constraint_status VALUES (?, ?, ?, ?, ?, ?)" ,
1972+ con_data,
1973+ )
19391974 end
19401975 end
19411976 end
19421977
1943- return m
19441978end
19451979
19461980
1947-
19481981# ## Postprocessing
19491982function finalize_results_dataframe (m, mode, PA_summaries)
19501983 # Check solve status of model
@@ -2719,16 +2752,24 @@ function save_agent_fs!(fs, agent_id, db, mode)
27192752
27202753end
27212754
2722- function save_agent_decisions (db, current_pd, agent_id, decision_df)
2755+ function save_agent_decisions (db, current_pd, agent_id, decision_df; mode = " integral " )
27232756 decision_df[! , :agent_id ] .= agent_id
27242757 decision_df[! , :base_pd ] .= current_pd
2758+
2759+ if mode == " integral"
2760+ table = " agent_decisions"
2761+ else
2762+ table = " agent_decisions_relax"
2763+ end
2764+
27252765 cols_to_ignore = [:uid , :current ]
27262766 select! (decision_df, [:agent_id , :base_pd ], Not (vcat ([:agent_id ], cols_to_ignore)))
2767+
27272768 for row in Tuple .(eachrow (decision_df))
27282769 DBInterface. execute (
27292770 db,
27302771 string (
2731- " INSERT INTO agent_decisions " ,
2772+ " INSERT INTO $table " ,
27322773 " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" ,
27332774 ),
27342775 row,
0 commit comments