From 85aecd38654c0bf7315c7a4eed1c9a55ba2fea4f Mon Sep 17 00:00:00 2001 From: Juliette-Gerbaux <130555142+Juliette-Gerbaux@users.noreply.github.com> Date: Tue, 10 Dec 2024 19:22:59 +0100 Subject: [PATCH] Clean code (#4) * Remove unused code * Clean tests * Clean src --------- Co-authored-by: Juliette-Gerbaux --- src/calculate_reward_and_bellman_values.py | 4 - src/display.py | 16 +- src/estimation.py | 11 +- src/functions_iterative.py | 3 +- src/hyperplane_interpolation.py | 7 - src/launch_calculation.py | 4 +- src/multi_stock_bellman_value_calculation.py | 192 ++----------------- src/optimization.py | 35 +--- src/read_antares_data.py | 12 +- src/requirements.txt | 6 - src/sddp.jl | 17 +- tests/test_basis.py | 4 +- tests/test_bellman_value_exact.py | 1 - tests/test_bellman_value_exact_two_stocks.py | 7 +- tests/test_fast_uv_two_stocks.py | 3 +- tests/test_iterative_two_stocks.py | 6 - tests/test_overflow.py | 6 +- 17 files changed, 44 insertions(+), 290 deletions(-) delete mode 100644 src/requirements.txt diff --git a/src/calculate_reward_and_bellman_values.py b/src/calculate_reward_and_bellman_values.py index a5aa2fe..3b6b32f 100644 --- a/src/calculate_reward_and_bellman_values.py +++ b/src/calculate_reward_and_bellman_values.py @@ -160,9 +160,6 @@ def get_disc( n_pts_below + n_pts_in + n_pts_above ) # Make sure total adds up if method == "lines": - # in_curve_pts = np.linspace(lbs, ubs, xNsteps-2) # Disc-2 * R - # all_pts = np.insert(in_curve_pts, 0, empty, axis=0) # (Disc-1) * R - # all_pts = np.insert(all_pts, all_pts.shape[0], full, axis=0) # Disc * R above_curve_pts = [ np.linspace(ubs[r], full[r], n_pts_above[r], endpoint=True) for r in range(n_reservoirs) @@ -183,7 +180,6 @@ def get_disc( for r in range(n_reservoirs) ] ).T - # all_pts = np.concatenate((below_curve_pts, in_curve_pts, above_curve_pts), axis=0) # Disc * R diffs_to_ref = all_pts[:, None] - reference_pt[None, :] # Disc * R diffs_to_ref = ( diffs_to_ref[:, :, None] * np.eye(n_reservoirs)[None, :, :] diff --git a/src/display.py b/src/display.py index ee60fa0..d2a2a4f 100644 --- a/src/display.py +++ b/src/display.py @@ -31,8 +31,6 @@ def draw_usage_values( closest_level ] - # z = np.maximum(np.zeros(reinterpolated_usage_values[area].T.shape), np.minimum(ub*np.ones(reinterpolated_usage_values[area].T.shape), reinterpolated_usage_values[area].T)) - # z = np.maximum(np.zeros(reinterpolated_usage_values[area].T.shape) - ub, np.minimum(ub*np.ones(reinterpolated_usage_values[area].T.shape), reinterpolated_usage_values[area].T)) usage_values_plot = go.Figure( data=[ go.Heatmap( @@ -64,9 +62,7 @@ def draw_usage_values( marker=dict(symbol="circle"), showlegend=True, ) - for i, (area, mng) in enumerate( - multi_stock_management.dict_reservoirs.items() - ) + for i, (_, _) in enumerate(multi_stock_management.dict_reservoirs.items()) ] + [ go.Scatter( @@ -78,9 +74,7 @@ def draw_usage_values( line=dict(dash="dash"), showlegend=True, ) - for i, (area, mng) in enumerate( - multi_stock_management.dict_reservoirs.items() - ) + for i, (_, mng) in enumerate(multi_stock_management.dict_reservoirs.items()) ] + [ go.Scatter( @@ -92,9 +86,7 @@ def draw_usage_values( line=dict(dash="dash"), showlegend=True, ) - for i, (area, mng) in enumerate( - multi_stock_management.dict_reservoirs.items() - ) + for i, (_, mng) in enumerate(multi_stock_management.dict_reservoirs.items()) ], layout=dict(title=f"Usage Values"), ) @@ -168,7 +160,7 @@ def draw_uvs_sddp( showlegend=True, visible=(r == 0), ) - for r, res in enumerate(reservoirs) + for r, _ in enumerate(reservoirs) ] + [ go.Scatter( diff --git a/src/estimation.py b/src/estimation.py index 06d2cc3..f1eef49 100644 --- a/src/estimation.py +++ b/src/estimation.py @@ -311,7 +311,6 @@ def __init__( costs: np.ndarray, duals: np.ndarray, correlations: Optional[np.ndarray] = None, - interp_mode: bool = False, ) -> None: """ Instanciates a LinearCostEstimator @@ -324,9 +323,6 @@ def __init__( costs:np.ndarray: Cost for every input, duals:np.ndarray: Duals for every input first dimension should be the same as inputs, """ - # self.true_controls=controls - # self.true_costs=costs - # self.true_duals=duals self.estimators = np.array( [ [ @@ -335,7 +331,6 @@ def __init__( costs=costs[week, scenario], duals=duals[week, scenario], correlations=correlations, - # interp_mode=interp_mode, ) for scenario in range(param.len_scenario) ] @@ -389,7 +384,6 @@ def update( inputs: np.ndarray, costs: np.ndarray, duals: np.ndarray, - interp_mode: bool = False, ) -> None: """ Updates the parameters of the Linear Interpolators @@ -409,10 +403,9 @@ def update( inputs=inputs, costs=costs, duals=duals, - # interp_mode=interp_mode, ) - def enrich_estimator(self, n_splits: int = 3) -> None: + def enrich_estimator(self) -> None: """ Adds 'mid_cuts' to our cost estimator to smoothen the curves and (hopefully) accelerate convergence @@ -441,8 +434,6 @@ def cleanup_approximations( for week_estimators in self.estimators: for estimator in week_estimators: estimator.remove_incoherence() - # controls=true_controls[week, scenario], - # real_costs=true_costs[week, scenario]) def remove_redundants( self, diff --git a/src/functions_iterative.py b/src/functions_iterative.py index 32969d3..6f9aca2 100644 --- a/src/functions_iterative.py +++ b/src/functions_iterative.py @@ -274,7 +274,7 @@ def itr_control( ) = init_iterative_calculation(param, reservoir_management, output_path, X, solver) i = 0 - while (gap >= tol_gap and gap >= 0) and i < N: # and (i<3): + while (gap >= tol_gap and gap >= 0) and i < N: debut = time() initial_x, controls = compute_x_multi_scenario( @@ -391,7 +391,6 @@ def init_iterative_calculation( stock_discretization=X, ) - i = 0 gap = 1e3 fin = time() tot_t.append(fin - debut) diff --git a/src/hyperplane_interpolation.py b/src/hyperplane_interpolation.py index 2201deb..21e3bfc 100644 --- a/src/hyperplane_interpolation.py +++ b/src/hyperplane_interpolation.py @@ -41,14 +41,11 @@ def BezierAv( if last_axify: p[:-1] = (p0[:-1] + p1[:-1]) / 2 p[-1] = p0[-1] * diff_rate + p1[-1] * (1 - diff_rate) - # v_sum = np.sum(v[:-1]) - # v[-1] /= v_sum v = v0 * (t) + v1 * (1 - t) v[-1] = v0[-1] * (t * (1 - partage) + partage * diff_rate) + v1[-1] * ( (1 - t) * (1 - partage) + partage * (1 - diff_rate) ) elif norm(v) > 1e-12: - # v = v / sum(v[:-1]) v = v / norm(v) * (n0 + n1) / 2 return np.array([p, v]) @@ -125,10 +122,6 @@ def interpolate_between( return mlr, data -mlrs: list = [] -datas: list = [] - - def enrich_by_interpolation( controls_init: np.ndarray, costs: np.ndarray, slopes: np.ndarray, n_splits: int = 3 ) -> tuple[np.ndarray, np.ndarray, np.ndarray]: diff --git a/src/launch_calculation.py b/src/launch_calculation.py index b0b7cfa..60b0431 100644 --- a/src/launch_calculation.py +++ b/src/launch_calculation.py @@ -50,7 +50,7 @@ def calculate_bellman_values( elif method == "precalculated": # or with precalulated reward - vb, G = calculate_bellman_value_with_precalculated_reward( + vb, _ = calculate_bellman_value_with_precalculated_reward( len_controls=len_controls, param=param, reservoir_management=reservoir_management, @@ -61,7 +61,7 @@ def calculate_bellman_values( elif method == "iterative": # or with iterative algorithm - vb, G, _, _, controls_upper, traj = itr_control( + vb, _, _, _, _, _ = itr_control( param=param, reservoir_management=reservoir_management, output_path=output_path, diff --git a/src/multi_stock_bellman_value_calculation.py b/src/multi_stock_bellman_value_calculation.py index f99b5ee..aa57ac0 100644 --- a/src/multi_stock_bellman_value_calculation.py +++ b/src/multi_stock_bellman_value_calculation.py @@ -11,7 +11,6 @@ from estimation import Estimator, LinearCostEstimator, LinearInterpolator from read_antares_data import TimeScenarioParameter, TimeScenarioIndex -# from julia_sddp import python_to_julia_data, manage_reservoirs_py from optimization import ( AntaresProblem, WeeklyBellmanProblem, @@ -19,12 +18,10 @@ solve_problem_with_multivariate_bellman_values, solve_for_optimal_trajectory, ) -from typing import Annotated, List, Literal, Dict, Optional, Any +from typing import Annotated, Literal, Dict, Optional, Any import numpy.typing as npt import numpy as np -# from scipy.interpolate import interp1d -# from functions_iterative import compute_upper_bound from display import ConvergenceProgressBar, draw_usage_values, draw_uvs_sddp from scipy.stats import random_correlation import pickle as pkl @@ -292,7 +289,6 @@ def get_bellman_values_from_costs( trajectory: np.ndarray, correlations: np.ndarray, divisor: dict[str, float] = {"euro": 1e8, "energy": 1e4}, - rounding: int = 6, verbose: bool = False, ) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, list[LinearInterpolator]]: """ @@ -325,7 +321,6 @@ def get_bellman_values_from_costs( name_solver=name_solver, divisor=divisor, ) - # problem.parameters.SetDoubleParam(problem.parameters.PRESOLVE, problem.parameters.PRESOLVE_ON) # Keeping in memory all future costs approximations future_costs_approx_l = [future_costs_approx] @@ -383,7 +378,6 @@ def get_bellman_values_from_costs( f"We were using the following future costs estimation: {[f'Cost(lvl) >= {cost} + (lvl_0 - {input[0]})*{duals[0]} + (lvl_1 - {input[1]})*{duals[1]}' for input, cost, duals in zip(future_costs_approx.inputs, future_costs_approx.costs, future_costs_approx.duals)]}" ) raise ValueError - # assert (np.min(np.abs(duals_wl))>.1 or np.random.rand()> .01) # Writing down results controls_w[lvl_id] = controls_wls @@ -410,10 +404,8 @@ def get_bellman_values_from_costs( def initialize_future_costs( - param: TimeScenarioParameter, starting_pt: np.ndarray, multi_stock_management: MultiStockManagement, - costs_approx: Estimator, mult: float = 0.0, ) -> LinearInterpolator: """ @@ -535,7 +527,6 @@ def get_all_costs( """ tot_iter = 0 times = [] - n_reservoirs = len(multi_stock_management.dict_reservoirs) if keep_intermed_res or already_init: assert saving_dir is not None filename = saving_dir + "/get_all_costs_run.pkl" @@ -566,10 +557,6 @@ def get_all_costs( controls_list=controls_list[week, scenario], ) except ValueError: - reservoirs = [ - mng.reservoir - for mng in multi_stock_management.dict_reservoirs.values() - ] print( f"Failed at week {week}, the conditions on control were: {controls_list[week, scenario]}" ) @@ -704,7 +691,6 @@ def generate_controls( for mng in multi_stock_management.dict_reservoirs.values() ] ) - mean_res = (max_res + min_res) / 2 # Points to start lines at start_pts = [ @@ -760,7 +746,7 @@ def generate_controls( manag.reservoir.max_generating, xNsteps, ) - for area, manag in multi_stock_management.dict_reservoirs.items() + for _, manag in multi_stock_management.dict_reservoirs.items() ] ) ] @@ -802,9 +788,6 @@ def precalculated_method( ------- Bellman Values:Dict[int, Dict[str, npt.NDArray[np.float32]]]: Bellman values """ - # __________________________________________________________________________________________ - # PRECALCULATION PART - # __________________________________________________________________________________________ # Initialize the problems list_models = initialize_antares_problems( @@ -834,15 +817,11 @@ def precalculated_method( verbose=verbose, ) - # print("=======================[ Reward approximation ]=======================") # Initialize cost functions costs_approx = LinearCostEstimator( param=param, controls=controls_list, costs=costs, duals=slopes ) - # __________________________________________________________________________________________ - # BELLMAN CALCULATION PART - # __________________________________________________________________________________________ print( "=======================[ Dynamic Programming ]=======================" ) @@ -855,9 +834,7 @@ def precalculated_method( ) future_costs_approx = initialize_future_costs( - param=param, multi_stock_management=multi_stock_management, - costs_approx=costs_approx, starting_pt=starting_pt, ) @@ -865,7 +842,6 @@ def precalculated_method( trajectory = np.swapaxes(trajectory, 1, 2) correlations = get_correlation_matrix( - param=param, multi_stock_management=multi_stock_management, corr_type="no_corrs", ) @@ -1025,7 +1001,6 @@ def select_controls_to_explore( * (2 * n_inputs + 1), size=(n_weeks, n_scenarios, n_reservoirs), ) - # pseudo_opt_controls += np.random.normal(scale=np.exp(-relative_proximity) * max_var[: ,None ,:]/10, size=(n_weeks, n_scenarios, n_reservoirs)) controls_to_explore[:, :, 0, :] = np.maximum( np.minimum(pseudo_opt_controls, max_gen[:, None, :]), max_pump[:, None, :] ) @@ -1033,7 +1008,6 @@ def select_controls_to_explore( def get_correlation_matrix( - param: TimeScenarioParameter, multi_stock_management: MultiStockManagement, adjacency_mat: Optional[np.ndarray] = None, corr_type: str = "no_corrs", @@ -1072,7 +1046,6 @@ def compute_usage_values_from_costs( nSteps_bellman: int, correlations: np.ndarray, divisor: dict[str, float] = {"euro": 1e8, "energy": 1e4}, - rounding: int = 6, verbose: bool = False, ) -> tuple[dict[str, np.ndarray], np.ndarray]: """For now we want this function to solve a lot of optimization problems for different initial values of stock @@ -1174,11 +1147,8 @@ def compute_usage_values_from_costs( for j, levels in enumerate(levels_to_test[week, :, i]): # Remove previous constraints / vars problem.reset_solver() - # problem.solver.SetSolverSpecificParametersAsString("presolve off") - try: # Rewrite problem - # print(levels, future_costs_approx_l[week].costs) problem.write_problem( week=week, level_init=levels, @@ -1229,13 +1199,10 @@ def get_opt_gap( ] ) # Computing the optimality gap - # pre_update_tot_costs = np.sum(pre_update_costs, axis=0) - # real_tot_costs = np.sum(costs, axis=0) costs = np.mean(costs, axis=-1) opt_gap = max( 1e-10, min(1, np.max(np.mean((costs - pre_update_costs), axis=1) / max_gap)) ) - # print(f"Gap {np.max(np.mean((costs - pre_update_costs),axis=1)/max_gap)}") return opt_gap @@ -1253,9 +1220,7 @@ def cutting_plane_method( saving_dir: str, maxiter: Optional[int] = None, precision: float = 5e-2, - interp_mode: bool = False, divisor: dict[str, float] = {"euro": 1e8, "energy": 1e4}, - rounding: int = 6, output_path: str = "", verbose: bool = False, ) -> tuple[ @@ -1285,12 +1250,6 @@ def cutting_plane_method( iter = 0 opt_gap = 1.0 maxiter = int(1e2) if maxiter is None else maxiter - inflows = np.array( - [ - mng.reservoir.inflow[: param.len_week, : param.len_scenario] - for mng in multi_stock_management.dict_reservoirs.values() - ] - ).T # Init trajectory trajectory = np.array([[starting_pt] * param.len_scenario] * param.len_week) trajectory = np.swapaxes(trajectory, 1, 2) @@ -1298,32 +1257,6 @@ def cutting_plane_method( max_gap = np.mean(np.max(costs, axis=2) - np.min(costs, axis=2), axis=1) rng = np.random.default_rng(1234115) - # hlpr = Caller( - # param=param, - # multi_stock_management=multi_stock_management, - # name_solver=name_solver, - # list_models=list_models, - # starting_pt=starting_pt, - # inflows=inflows, - # trajectory=trajectory, - # max_gap=max_gap, - # costs_approx=costs_approx, - # future_costs_approx=future_costs_approx, - # nSteps_bellman=nSteps_bellman, - # method=method, - # correlations=correlations, - # maxiter=maxiter, - # precision=precision, - # interp_mode=interp_mode, - # opt_gap=opt_gap, - # divisor=divisor, - # rounding=rounding, - # output_path=output_path, - # rng=rng, - # verbose=False, - # prefix="cut_plan") - # prefix="cut_plan" - # To display convergence: if verbose: pbar = ConvergenceProgressBar( @@ -1335,13 +1268,11 @@ def cutting_plane_method( if verbose: pbar.describe("Dynamic Programming") - # levels, bellman_costs, _, _, future_costs_approx_l = hlpr(get_bellman_values_from_costs,\ - # ("levels", "bellman_costs", "bellman_duals", "bellman_controls", "future_costs_approx_l", "usage_values")) ( levels, bellman_costs, - bellman_duals, - bellman_controls, + _, + _, future_costs_approx_l, ) = get_bellman_values_from_costs( param=param, @@ -1354,31 +1285,22 @@ def cutting_plane_method( trajectory=trajectory, correlations=correlations, divisor=divisor, - rounding=rounding, verbose=verbose, ) future_costs_approx = future_costs_approx_l[0] - # hlpr.update(future_costs_approx = future_costs_approx) # Evaluate optimal - # trajectory, _, _ = hlpr(solve_for_optimal_trajectory,\ - # ("trajectory", "pseudo_opt_controls", "pseudo_opt_costs")) - trajectory, pseudo_opt_controls, pseudo_opt_costs = ( - solve_for_optimal_trajectory( - param=param, - multi_stock_management=multi_stock_management, - costs_approx=costs_approx, - future_costs_approx_l=future_costs_approx_l, - inflows=inflows, - starting_pt=starting_pt, - name_solver=name_solver, - divisor=divisor, - verbose=verbose, - ) + trajectory, pseudo_opt_controls, _ = solve_for_optimal_trajectory( + param=param, + multi_stock_management=multi_stock_management, + costs_approx=costs_approx, + future_costs_approx_l=future_costs_approx_l, + starting_pt=starting_pt, + name_solver=name_solver, + divisor=divisor, ) # Beware, some trajectories seem to be overstep the bounds with values such as -2e-12 - # controls_list = hlpr(select_controls_to_explore, ("controls_list")) controls_list = select_controls_to_explore( param=param, multi_stock_management=multi_stock_management, @@ -1390,8 +1312,6 @@ def cutting_plane_method( pbar.describe("Simulation") # Evaluating this "optimal" trajectory - # hlpr.update(prefix=f"cut_plan_iter_{iter}_") - # controls_list, costs, slopes = hlpr(Lget_costs, ("controls_list", "costs", "slopes")) controls, costs, slopes = Lget_costs( param=param, multi_stock_management=multi_stock_management, @@ -1404,7 +1324,6 @@ def cutting_plane_method( prefix=f"cut_plan_iter_{iter}_", ) - # opt_gap = hlpr(get_opt_gap, "opt_gap") opt_gap = get_opt_gap( param=param, costs=costs, @@ -1414,15 +1333,12 @@ def cutting_plane_method( max_gap=max_gap, ) - costs_approx.update( - inputs=controls_list, costs=costs, duals=slopes, interp_mode=interp_mode - ) + costs_approx.update(inputs=controls_list, costs=costs, duals=slopes) costs_approx.remove_redundants(tolerance=1e-2) # If we want to look at the usage values evolution if verbose: pbar.describe("Drawing") - # hlpr.update(optimal_trajectory=trajectory, n_weeks=param.len_week) usage_values, levels_uv = compute_usage_values_from_costs( param=param, multi_stock_management=multi_stock_management, @@ -1433,9 +1349,7 @@ def cutting_plane_method( nSteps_bellman=nSteps_bellman, correlations=correlations, divisor=divisor, - rounding=rounding, ) - # hlpr(compute_usage_values_from_costs, ("usage_values", "levels_uv")) draw_usage_values( usage_values=usage_values, levels_uv=levels_uv, @@ -1445,7 +1359,6 @@ def cutting_plane_method( trajectory=trajectory, ub=500, ) - # hlpr(draw_usage_values) pbar.update(precision=opt_gap) if verbose: @@ -1464,14 +1377,9 @@ def iter_bell_vals( saving_dir: str, name_solver: str = "CLP", precision: float = 1e-2, - maxiter: int = 2, correlations: Optional[np.ndarray] = None, - interp_mode: bool = False, divisor: dict[str, float] = {"euro": 1e8, "energy": 1e4}, - rounding: int = 6, verbose: bool = False, - already_init: bool = False, - keep_intermed_res: bool = False, ) -> tuple[Any, Any, Any, Any, Any, Any]: """ In a similar fashion to Kelley's algorithm (1960), the idea is to approximate the (convex) cost function @@ -1512,40 +1420,14 @@ def iter_bell_vals( Returns: tuple[np.ndarray, Estimator, list[LinearInterpolator], np.ndarray]: Bellman costs, costs approximation, future costs approximation, levels """ - # Initialize the caller - # hlpr = Caller( - # param=param, - # multi_stock_management=multi_stock_management, - # output_path=output_path, - # n_controls_init=n_controls_init, - # starting_pt=starting_pt, - # nSteps_bellman=nSteps_bellman, - # method=method, - # name_solver=name_solver, - # precision=precision, - # maxiter=maxiter, - # correlations=correlations, - # interp_mode=interp_mode, - # divisor=divisor, - # rounding=rounding, - # verbose=verbose, - # already_init=already_init, - # keep_intermed_res=keep_intermed_res) - # Choose first controls to test - # controls = hlpr(initialize_controls, 'controls_list') controls_list = initialize_controls( param=param, multi_stock_management=multi_stock_management, n_controls_init=n_controls_init, ) - # #Initialize the Antares problems - # hlpr(initialize_antares_problems, 'list_models') - - # #Get hyperplanes resulting from initial controls - # _, duals = hlpr(get_all_costs, ('costs', 'slopes')) - # controls, costs, duals = hlpr(Lget_costs, ('controls_list', 'costs', 'slopes')) + # Get hyperplanes resulting from initial controls controls, costs, duals = Lget_costs( param=param, multi_stock_management=multi_stock_management, @@ -1556,34 +1438,24 @@ def iter_bell_vals( load_from_protos=True, verbose=verbose, ) - # hlpr.update(duals=duals, controls=controls) - # hlpr.update(list_models=[]) - # costs_approx = hlpr(LinearCostEstimator, "costs_approx") costs_approx = LinearCostEstimator( param=param, controls=controls, costs=costs, duals=duals ) # Initialize our approximation on future costs - # hlpr(initialize_future_costs, "future_costs_approx") future_costs_approx = initialize_future_costs( - param=param, starting_pt=starting_pt, multi_stock_management=multi_stock_management, - costs_approx=costs_approx, ) # Correlations matrix - # hlpr(get_correlation_matrix, "correlations") correlations = get_correlation_matrix( - param=param, multi_stock_management=multi_stock_management, corr_type="no_corrs", ) # Iterative part - # hlpr(cutting_plane_method, ("bellman_costs", "levels", "future_costs_approx_l", - # "costs_approx", "optimal_trajectory")) bellman_costs, levels, future_costs_approx_l, costs_approx, optimal_trajectory = ( cutting_plane_method( param=param, @@ -1598,18 +1470,14 @@ def iter_bell_vals( method=method, correlations=correlations, precision=precision, - interp_mode=interp_mode, divisor=divisor, - rounding=rounding, output_path=output_path, verbose=verbose, ) ) # Deducing usage values - # hlpr.update(nSteps_bellman=101) - # hlpr(compute_usage_values_from_costs, ('usage_values', 'levels_imposed')) - usage_values, levels_imposed = compute_usage_values_from_costs( + usage_values, _ = compute_usage_values_from_costs( param=param, multi_stock_management=multi_stock_management, name_solver=name_solver, @@ -1619,13 +1487,8 @@ def iter_bell_vals( nSteps_bellman=101, correlations=correlations, divisor=divisor, - rounding=rounding, ) - # returns = ("bellman_costs", "costs_approx", "future_costs_approx_l", "levels", "optimal_trajectory",\ - # "usage_values") - # bellman_costs, costs_approx, future_costs_approx_l,\ - # levels, optimal_trajectory, usage_values = hlpr.get(returns) return ( bellman_costs, costs_approx, @@ -1648,7 +1511,6 @@ def sddp_cutting_planes( normalization: Dict[str, float], maxiter: Optional[int] = None, precision: float = 1e-2, - interp_mode: bool = False, verbose: bool = False, ) -> tuple[np.ndarray, np.ndarray, LinearCostEstimator, list[np.ndarray]]: @@ -1769,9 +1631,7 @@ def sddp_cutting_planes( ) pbar.update(precision=opt_gap) - costs_approx.update( - inputs=controls, costs=costs, duals=slopes, interp_mode=interp_mode - ) + costs_approx.update(inputs=controls, costs=costs, duals=slopes) costs_approx.remove_redundants(tolerance=1e-2) usage_values, bellman_costs = jl_sddp.get_usage_values( param.len_week, param.len_scenario, jl_reservoirs, model, norms, 101 @@ -1790,7 +1650,6 @@ def iter_bell_vals_v2( name_solver: str = "CLP", precision: float = 1e-2, maxiter: int = 2, - interp_mode: bool = False, verbose: bool = False, ) -> Any: @@ -1801,24 +1660,6 @@ def iter_bell_vals_v2( n_controls_init=n_controls_init, ) - # #Initialize the Antares problems - # list_models = initialize_antares_problems( - # param=param, - # multi_stock_management=multi_stock_management, - # output_path=output_path, - # name_solver=name_solver, - # direct_bellman_calc=False, - # verbose=verbose, - # ) - - # Get hyperplanes resulting from initial - # costs, duals = get_all_costs( - # param=param, - # list_models=list_models, - # multi_stock_management=multi_stock_management, - # controls_list=controls_list, - # verbose=verbose, - # ) controls_list, costs, duals = Lget_costs( param=param, multi_stock_management=multi_stock_management, @@ -1846,7 +1687,6 @@ def iter_bell_vals_v2( precision=precision, normalization=normalization, maxiter=maxiter, - interp_mode=interp_mode, verbose=verbose, ) diff --git a/src/optimization.py b/src/optimization.py index f331b79..6ab6376 100644 --- a/src/optimization.py +++ b/src/optimization.py @@ -1,11 +1,11 @@ import re -from typing import Any, Optional +from typing import Optional from calculate_reward_and_bellman_values import ( BellmanValueCalculation, MultiStockBellmanValueCalculation, MultiStockManagement, ) -from estimation import Estimator, LinearInterpolator, LinearCostEstimator +from estimation import Estimator, LinearInterpolator from read_antares_data import TimeScenarioParameter import numpy as np from time import time @@ -444,7 +444,7 @@ def solve_with_predefined_controls( for area in self.range_reservoir: self.set_constraints_predefined_control(control[area], area) try: - beta, lamb, final_level, _, _, itr, computing_time = self.solve_problem( + beta, lamb, _, _, _, itr, computing_time = self.solve_problem( direct_bellman_mode=False ) # print(f"✔ for controls {control}") @@ -1384,34 +1384,8 @@ def get_control_cost( # 0 <= control_cost control_cost = self.solver.NumVar(0, inf, name=f"control_cost") - # - max_pump * eff - max_generating <= control_diff <= max_pump * eff + max_generating - # control_diffs = [ - # [ - # [ self.solver.NumVar( - # -mng.reservoir.max_pumping[week] * mng.reservoir.efficiency - mng.reservoir.max_generating[week], - # mng.reservoir.max_pumping[week] * mng.reservoir.efficiency + mng.reservoir.max_generating[week], - # name=f"control_diff_{area}_{s}_{c}" - # ) - # for c, _ in enumerate(self.week_costs_estimation[week,s].inputs)] - # for s in range(self.n_scenarios)] - # for area, mng in self.managements.items()] - # ========= Constraints ========== - # Control diffs definition - # control_diff_constraints = [ - # [ - # [ - # self.solver.Add( - # control_diffs[r][s][c] == controls[r,s] - input[r], - # name=f"control_diff_{r}_{s}_{c}" - # ) - # for c, input in enumerate(self.week_costs_estimation[week,s].inputs)] - # for s in range(self.n_scenarios)] - # for r, _ in enumerate(self.managements)] - - # Cuts on control costs - # control_cost_per_scenario >= cost + control_cost_constraints = [ [ self.solver.Add( @@ -1719,7 +1693,6 @@ def solve( # Removing unwanted parts of the cost cost -= self.future_cost.solution_value() * remove_future_costs cost -= self.penalty_cost.solution_value() * remove_penalties - # penalty = self.total_penalty.solution_value() penalty_duals = np.array( [cstr.dual_value() for cstr in self.initial_level_csts] ) @@ -1741,11 +1714,9 @@ def solve_for_optimal_trajectory( multi_stock_management: MultiStockManagement, costs_approx: Estimator, future_costs_approx_l: list[LinearInterpolator], - inflows: np.ndarray, starting_pt: np.ndarray, name_solver: str, divisor: dict[str, float], - verbose: bool = False, ) -> tuple[np.ndarray, np.ndarray, np.ndarray]: """Finds the optimal trajectory starting from starting_pts diff --git a/src/read_antares_data.py b/src/read_antares_data.py index cc574eb..b24d88c 100644 --- a/src/read_antares_data.py +++ b/src/read_antares_data.py @@ -96,9 +96,9 @@ def read_rule_curves(self, dir_study: str) -> None: )[:, [0, 2]] * self.capacity ) - # assert ( - # rule_curves[0, 0] == rule_curves[0, 1] - # ), "Initial level is not correctly defined by bottom and upper rule curves" + assert ( + rule_curves[0, 0] == rule_curves[0, 1] + ), "Initial level is not correctly defined by bottom and upper rule curves" self.initial_level = rule_curves[0, 0] bottom_rule_curve = rule_curves[6:365:7, 0] upper_rule_curve = rule_curves[6:365:7, 1] @@ -127,7 +127,7 @@ def read_efficiency(self, hydro_ini_file: ConfigParser) -> None: def generate_mps_file(study_path: str, antares_path: str) -> str: - # change_hydro_management_to_heuristic(dir_study=study_path) + change_hydro_management_to_heuristic(dir_study=study_path) name_solver = antares_path.split("/")[-1] assert "solver" in name_solver @@ -162,9 +162,5 @@ def change_hydro_management_to_heuristic(dir_study: str) -> None: if "use heuristic" in hydro_ini.keys(): hydro_ini["use heuristic"][area] = "true" - # Solve the weird mps occurence of limited hydro power: - # for area in hydro_ini["intra-daily-modulation"].keys(): - # hydro_ini["intra-daily-modulation"][area] = "999999.000000" - with open(dir_study + "/input/hydro/hydro.ini", "w") as configfile: # save hydro_ini.write(configfile) diff --git a/src/requirements.txt b/src/requirements.txt deleted file mode 100644 index 966cb43..0000000 --- a/src/requirements.txt +++ /dev/null @@ -1,6 +0,0 @@ -juliacall==0.9.22 -numpy==2.1.2 -ortools==9.9.9999 -plotly==5.23.0 -scipy==1.14.1 -tqdm==4.66.5 diff --git a/src/sddp.jl b/src/sddp.jl index 0db5407..0cc476b 100644 --- a/src/sddp.jl +++ b/src/sddp.jl @@ -74,9 +74,7 @@ function generate_model(n_weeks::Int, n_scenarios::Int, reservoirs::Vector{Main. stages = 3*n_weeks, sense = :Min, lower_bound = 0.0, - optimizer = Clp.Optimizer, - # optimizer = HiGHS.Optimizer, - # cut_oracle = SDDP.LevelOneCutOracle() + optimizer = Clp.Optimizer ) do subproblem, stage # Declaring the state variable @@ -121,10 +119,6 @@ function generate_model(n_weeks::Int, n_scenarios::Int, reservoirs::Vector{Main. end) # Define scenarios for inflows - # inflows = [ - # [reservoirs[r]["inflows"][stage][scenario] for r in 1:n_reservoirs] - # for scenario in 1:n_scenarios - # ] Ω = [ ( inflows = [reservoirs[r].inflows[modulo_stage, scenario] for r in 1:n_reservoirs], @@ -178,10 +172,6 @@ function manage_reservoirs(n_weeks::Int, n_scenarios::Int, reservoirs::Vector{Ma #Simulating simulation_results = get_trajectory(n_weeks, n_scenarios, reservoirs, model, norms) return simulation_results, model - # #Getting the usage values - # n_disc = 101 - # VU, costs = get_usage_values(n_weeks, n_scenarios, reservoirs, model, norms, n_disc) - # return VU, costs, simulation_results end function get_trajectory(n_weeks::Int, n_scenarios::Int, reservoirs::Vector{Main.Jl_SDDP.Reservoir}, model, norms::Normalizer) @@ -238,8 +228,3 @@ end export manage_reservoirs, get_usage_values, stability_report, reinit_cuts end -# Call the function -# results = manage_reservoirs(n_weeks, n_scenarios, reservoirs, costs_approx) - -# Print the results -# println(results) diff --git a/tests/test_basis.py b/tests/test_basis.py index d46fab2..260ce11 100644 --- a/tests/test_basis.py +++ b/tests/test_basis.py @@ -42,7 +42,7 @@ def test_basis_with_xpress() -> None: param=param, multi_stock_management=reservoir_management ) - beta_1, _, itr_without_basis, _ = problem.solve_with_predefined_controls( + beta_1, _, _, _ = problem.solve_with_predefined_controls( control={"area": 8400000}, prev_basis=Basis([], []) ) @@ -108,7 +108,7 @@ def test_basis_with_upper_bound() -> None: control={"area": 0}, prev_basis=Basis([], []) ) - upper_bound_1, _, itr_without_basis = compute_upper_bound( + upper_bound_1, _, _ = compute_upper_bound( bellman_value_calculation=bellman_value_calculation, list_models=list_models, V=V, diff --git a/tests/test_bellman_value_exact.py b/tests/test_bellman_value_exact.py index 7757670..4106b45 100644 --- a/tests/test_bellman_value_exact.py +++ b/tests/test_bellman_value_exact.py @@ -1,7 +1,6 @@ from functions_iterative import ( TimeScenarioParameter, ReservoirManagement, - TimeScenarioIndex, ) from simple_bellman_value_calculation import ( calculate_bellman_value_directly, diff --git a/tests/test_bellman_value_exact_two_stocks.py b/tests/test_bellman_value_exact_two_stocks.py index fa2436a..bb4e1a5 100644 --- a/tests/test_bellman_value_exact_two_stocks.py +++ b/tests/test_bellman_value_exact_two_stocks.py @@ -3,7 +3,12 @@ ReservoirManagement, TimeScenarioIndex, ) -from multi_stock_bellman_value_calculation import * +from multi_stock_bellman_value_calculation import ( + AntaresProblem, + Dict, + solve_problem_with_multivariate_bellman_values, + calculate_bellman_value_multi_stock, +) from calculate_reward_and_bellman_values import ( MultiStockManagement, BellmanValueCalculation, diff --git a/tests/test_fast_uv_two_stocks.py b/tests/test_fast_uv_two_stocks.py index 95a057b..5d94139 100644 --- a/tests/test_fast_uv_two_stocks.py +++ b/tests/test_fast_uv_two_stocks.py @@ -2,12 +2,13 @@ TimeScenarioParameter, ReservoirManagement, ) -from multi_stock_bellman_value_calculation import * +from multi_stock_bellman_value_calculation import generate_fast_uvs_v2 from calculate_reward_and_bellman_values import ( MultiStockManagement, ) from read_antares_data import Reservoir import pytest +import numpy as np def test_fast_usage_values_multi_stock() -> None: diff --git a/tests/test_iterative_two_stocks.py b/tests/test_iterative_two_stocks.py index 9611a0e..bf7e5cd 100644 --- a/tests/test_iterative_two_stocks.py +++ b/tests/test_iterative_two_stocks.py @@ -59,16 +59,11 @@ def test_bellman_value_iterative_method() -> None: for mng in multi_management.dict_reservoirs.values() ] ), - maxiter=10, precision=1e-3, method="lines", correlations=None, - interp_mode=False, divisor={"euro": 1e8, "energy": 1e4}, - rounding=6, verbose=False, - keep_intermed_res=False, - already_init=True, ) assert bell_costs == pytest.approx( @@ -262,7 +257,6 @@ def test_bellman_value_iterative_method_with_sddp() -> None: name_solver="CLP", maxiter=3, precision=1e-2, - interp_mode=False, verbose=False, ) diff --git a/tests/test_overflow.py b/tests/test_overflow.py index 69702ac..62820c6 100644 --- a/tests/test_overflow.py +++ b/tests/test_overflow.py @@ -1,13 +1,11 @@ from functions_iterative import ( TimeScenarioParameter, ReservoirManagement, - TimeScenarioIndex, ) from simple_bellman_value_calculation import ( calculate_bellman_value_with_precalculated_reward, ) from read_antares_data import Reservoir -import pytest import numpy as np from scipy.interpolate import interp1d @@ -28,7 +26,7 @@ def test_bellman_value_precalculated_reward_overflow() -> None: xNsteps = 20 X = np.linspace(0, reservoir.capacity, num=xNsteps) - vb, G = calculate_bellman_value_with_precalculated_reward( + vb, _ = calculate_bellman_value_with_precalculated_reward( len_controls=20, param=param, reservoir_management=reservoir_management, @@ -50,7 +48,7 @@ def test_bellman_value_precalculated_reward_overflow() -> None: overflow=False, ) - vb, G = calculate_bellman_value_with_precalculated_reward( + vb, _ = calculate_bellman_value_with_precalculated_reward( len_controls=20, param=param, reservoir_management=reservoir_management,