From beef545ede8f8ab5d577cf9ce00ac018320638dd Mon Sep 17 00:00:00 2001 From: raphasampaio Date: Mon, 25 Nov 2024 13:05:37 -0300 Subject: [PATCH 1/5] Project updates --- format/Project.toml | 5 +++++ format/format.bat | 5 +++++ format/format.jl | 6 ++++++ revise.bat | 2 +- 4 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 format/Project.toml create mode 100644 format/format.bat create mode 100644 format/format.jl diff --git a/format/Project.toml b/format/Project.toml new file mode 100644 index 0000000..71708c8 --- /dev/null +++ b/format/Project.toml @@ -0,0 +1,5 @@ +[deps] +JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899" + +[compat] +JuliaFormatter = "1" diff --git a/format/format.bat b/format/format.bat new file mode 100644 index 0000000..1ff9bfc --- /dev/null +++ b/format/format.bat @@ -0,0 +1,5 @@ +@echo off + +SET BASEPATH=%~dp0 + +CALL "%JULIA_194%" --project=%BASEPATH% %BASEPATH%\format.jl \ No newline at end of file diff --git a/format/format.jl b/format/format.jl new file mode 100644 index 0000000..f1393c8 --- /dev/null +++ b/format/format.jl @@ -0,0 +1,6 @@ +import Pkg +Pkg.instantiate() + +using JuliaFormatter + +format(dirname(@__DIR__)) diff --git a/revise.bat b/revise.bat index 626ca1b..e2c3520 100644 --- a/revise.bat +++ b/revise.bat @@ -3,4 +3,4 @@ SET BASEPATH=%~dp0 SET REVISE_PATH="%BASEPATH%\revise" -%JULIA_194% --project=%REVISE_PATH% --load=%REVISE_PATH%\revise_load_script.jl +CALL %JULIA_194% --project=%REVISE_PATH% --load=%REVISE_PATH%\revise_load_script.jl From bb12e19dacd6ae22cefd53dd2f210c044f4989e9 Mon Sep 17 00:00:00 2001 From: raphasampaio Date: Mon, 25 Nov 2024 13:06:57 -0300 Subject: [PATCH 2/5] Project updates --- .JuliaFormatter.toml | 24 ++++++++++++++++++ test/runtests.jl | 4 +-- test/script_newsvendor_benders_job_queue.jl | 23 ++++++++++-------- test/test_newsvendor_benders.jl | 27 +++++++++++---------- test/test_newsvendor_benders_job_queue.jl | 4 ++- 5 files changed, 56 insertions(+), 26 deletions(-) create mode 100644 .JuliaFormatter.toml diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml new file mode 100644 index 0000000..9c0570b --- /dev/null +++ b/.JuliaFormatter.toml @@ -0,0 +1,24 @@ +# Configuration file for JuliaFormatter.jl +# For more information, see: https://domluna.github.io/JuliaFormatter.jl/stable/config/ + +indent = 4 +margin = 146 +always_for_in = true +whitespace_typedefs = true +whitespace_ops_in_indices = false +remove_extra_newlines = true +import_to_using = false +pipe_to_function_call = false +short_to_long_function_def = false +long_to_short_function_def = false +whitespace_in_kwargs = true +annotate_untyped_fields_with_any = true +format_docstrings = true +conditional_to_if = false +normalize_line_endings = "auto" +trailing_comma = true +join_lines_based_on_source = true +indent_submodule = false +separate_kwargs_with_semicolon = false +surround_whereop_typeparameters = true +always_use_return = true \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index 2ac2b76..17fa99b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,7 +1,7 @@ using Test function test_modules(dir::AbstractString) - result = Dict{String, Vector{String}}() + result = Dict{String,Vector{String}}() for (root, dirs, files) in walkdir(dir) for file in joinpath.(root, filter(f -> occursin(r"test_(.)+\.jl", f), files)) main_case = splitpath(file)[end-2] @@ -24,4 +24,4 @@ end end end end -end \ No newline at end of file +end diff --git a/test/script_newsvendor_benders_job_queue.jl b/test/script_newsvendor_benders_job_queue.jl index 1129d13..0ed5574 100644 --- a/test/script_newsvendor_benders_job_queue.jl +++ b/test/script_newsvendor_benders_job_queue.jl @@ -39,7 +39,7 @@ function second_stage_builder(sp, inputs) @variable(sp, returned >= 0) @constraint(sp, sold_dem_con, sold <= dem) @constraint(sp, balance, sold + returned <= bought) - @objective(sp, Min, - sold * inputs.sell_price - returned * inputs.return_price) + @objective(sp, Min, -sold * inputs.sell_price - returned * inputs.return_price) return sp end @@ -49,16 +49,19 @@ function second_stage_modifier(sp, inputs, s) return nothing end -function newsvendor_benders(;cut_strategy = LightBenders.CutStrategy.MultiCut) +function newsvendor_benders(; cut_strategy = LightBenders.CutStrategy.MultiCut) inputs = Inputs(5, 10, 1, 100, [10, 20, 30]) num_scenarios = length(inputs.demand) policy_training_options = LightBenders.PolicyTrainingOptions(; - num_scenarios=num_scenarios, + num_scenarios = num_scenarios, lower_bound = -1e6, implementation_strategy = LightBenders.JobQueueTraining(), - stopping_rule = LightBenders.GapWithMinimumNumberOfIterations(;abstol = 1e-1, min_iterations = 2), - cut_strategy = cut_strategy + stopping_rule = LightBenders.GapWithMinimumNumberOfIterations(; + abstol = 1e-1, + min_iterations = 2, + ), + cut_strategy = cut_strategy, ) policy = LightBenders.train(; @@ -67,7 +70,7 @@ function newsvendor_benders(;cut_strategy = LightBenders.CutStrategy.MultiCut) second_stage_builder, second_stage_modifier, inputs = inputs, - policy_training_options + policy_training_options, ) if LightBenders.JQM.is_worker_process() @@ -87,7 +90,7 @@ function newsvendor_benders(;cut_strategy = LightBenders.CutStrategy.MultiCut) simulation_options = LightBenders.SimulationOptions( policy_training_options; implementation_strategy = LightBenders.BendersSerialSimulation(), - ) + ), ) @test results["objective", 0] ≈ -70 atol = 1e-2 @@ -95,10 +98,10 @@ end function test_newsvendor_benders() @testset "[Job Queue] Benders Newsvendor single cut" begin - newsvendor_benders(;cut_strategy = LightBenders.CutStrategy.SingleCut) + newsvendor_benders(; cut_strategy = LightBenders.CutStrategy.SingleCut) end @testset "[Job Queue] Benders Newsvendor multi cut" begin - newsvendor_benders(;cut_strategy = LightBenders.CutStrategy.MultiCut) + newsvendor_benders(; cut_strategy = LightBenders.CutStrategy.MultiCut) end end @@ -116,4 +119,4 @@ end TestNewsvendorBendersJobQueue.runtests() -end # module TestNewsvendorBendersJobQueue \ No newline at end of file +end # module TestNewsvendorBendersJobQueue diff --git a/test/test_newsvendor_benders.jl b/test/test_newsvendor_benders.jl index f042ef3..e9374ec 100644 --- a/test/test_newsvendor_benders.jl +++ b/test/test_newsvendor_benders.jl @@ -39,7 +39,7 @@ function second_stage_builder(sp, inputs) @variable(sp, returned >= 0) @constraint(sp, sold_dem_con, sold <= dem) @constraint(sp, balance, sold + returned <= bought) - @objective(sp, Min, - sold * inputs.sell_price - returned * inputs.return_price) + @objective(sp, Min, -sold * inputs.sell_price - returned * inputs.return_price) return sp end @@ -49,16 +49,19 @@ function second_stage_modifier(sp, inputs, s) return nothing end -function newsvendor_benders(;cut_strategy = LightBenders.CutStrategy.MultiCut) +function newsvendor_benders(; cut_strategy = LightBenders.CutStrategy.MultiCut) inputs = Inputs(5, 10, 1, 100, [10, 20, 30]) num_scenarios = length(inputs.demand) policy_training_options = LightBenders.PolicyTrainingOptions(; - num_scenarios=num_scenarios, + num_scenarios = num_scenarios, lower_bound = -1e6, implementation_strategy = LightBenders.SerialTraining(), - stopping_rule = LightBenders.GapWithMinimumNumberOfIterations(;abstol = 1e-1, min_iterations = 2), - cut_strategy = cut_strategy + stopping_rule = LightBenders.GapWithMinimumNumberOfIterations(; + abstol = 1e-1, + min_iterations = 2, + ), + cut_strategy = cut_strategy, ) policy = LightBenders.train(; @@ -67,7 +70,7 @@ function newsvendor_benders(;cut_strategy = LightBenders.CutStrategy.MultiCut) second_stage_builder, second_stage_modifier, inputs = inputs, - policy_training_options + policy_training_options, ) @test LightBenders.lower_bound(policy) ≈ -70 @@ -83,7 +86,7 @@ function newsvendor_benders(;cut_strategy = LightBenders.CutStrategy.MultiCut) simulation_options = LightBenders.SimulationOptions( policy_training_options; implementation_strategy = LightBenders.BendersSerialSimulation(), - ) + ), ) @test results["objective", 0] ≈ -70 atol = 1e-2 @@ -93,9 +96,7 @@ function newsvendor_deterministic() inputs = Inputs(5, 10, 1, 100, [10, 20, 30]) num_scenarios = length(inputs.demand) - options = LightBenders.DeterministicEquivalentOptions(; - num_scenarios = num_scenarios, - ) + options = LightBenders.DeterministicEquivalentOptions(; num_scenarios = num_scenarios) det_eq_results = LightBenders.deterministic_equivalent(; state_variables_builder, @@ -111,10 +112,10 @@ end function test_newsvendor_benders() @testset "Benders Newsvendor single cut" begin - newsvendor_benders(;cut_strategy = LightBenders.CutStrategy.SingleCut) + newsvendor_benders(; cut_strategy = LightBenders.CutStrategy.SingleCut) end @testset "Benders Newsvendor multi cut" begin - newsvendor_benders(;cut_strategy = LightBenders.CutStrategy.MultiCut) + newsvendor_benders(; cut_strategy = LightBenders.CutStrategy.MultiCut) end @testset "Deterministic equivalent Newsvendor" begin newsvendor_deterministic() @@ -176,4 +177,4 @@ end # module TestNewsvendorBenders # JuMP.optimize!(det) # @show JuMP.termination_status(det) # @show JuMP.objective_value(det) -# end \ No newline at end of file +# end diff --git a/test/test_newsvendor_benders_job_queue.jl b/test/test_newsvendor_benders_job_queue.jl index 26c616c..bdcc979 100644 --- a/test/test_newsvendor_benders_job_queue.jl +++ b/test/test_newsvendor_benders_job_queue.jl @@ -5,4 +5,6 @@ using JobQueueMPI.MPI project_dir = dirname(Base.active_project()) parallel_script = joinpath(@__DIR__, "script_newsvendor_benders_job_queue.jl") -mpiexec(exe -> run(`$exe -n 3 $(Base.julia_cmd()) --project=$(project_dir) $(parallel_script)`)) +mpiexec( + exe -> run(`$exe -n 3 $(Base.julia_cmd()) --project=$(project_dir) $(parallel_script)`), +) From 08cb97c5022f603a2f59c61cb2865250d5434e49 Mon Sep 17 00:00:00 2001 From: Raphael Sampaio Date: Mon, 25 Nov 2024 13:13:35 -0300 Subject: [PATCH 3/5] Update test_newsvendor_benders_job_queue.jl --- test/test_newsvendor_benders_job_queue.jl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/test_newsvendor_benders_job_queue.jl b/test/test_newsvendor_benders_job_queue.jl index bdcc979..26c616c 100644 --- a/test/test_newsvendor_benders_job_queue.jl +++ b/test/test_newsvendor_benders_job_queue.jl @@ -5,6 +5,4 @@ using JobQueueMPI.MPI project_dir = dirname(Base.active_project()) parallel_script = joinpath(@__DIR__, "script_newsvendor_benders_job_queue.jl") -mpiexec( - exe -> run(`$exe -n 3 $(Base.julia_cmd()) --project=$(project_dir) $(parallel_script)`), -) +mpiexec(exe -> run(`$exe -n 3 $(Base.julia_cmd()) --project=$(project_dir) $(parallel_script)`)) From 754da1118ef1c0cf7e6818da936349441b471beb Mon Sep 17 00:00:00 2001 From: raphasampaio Date: Mon, 25 Nov 2024 13:15:25 -0300 Subject: [PATCH 4/5] Project updates --- src/cut_strategies/cuts_base.jl | 6 ++--- src/cut_strategies/local_cuts.jl | 12 ++++----- src/cut_strategies/single_cut.jl | 26 +++++++++---------- src/debugging_options.jl | 2 +- .../deterministic_equivalent.jl | 8 +++--- src/optimize_helpers.jl | 2 +- src/progress_logs/abstractions.jl | 2 +- .../benders_training_iterations.jl | 9 ++++--- src/progress_logs/deterministic_equivalent.jl | 1 + src/simulate.jl | 7 +++-- src/simulation_strategies/benders_serial.jl | 2 +- src/states.jl | 2 +- src/stopping_rules.jl | 2 +- src/train.jl | 4 +-- src/training_strategies/benders_serial.jl | 15 ++++++----- test/runtests.jl | 2 +- 16 files changed, 53 insertions(+), 49 deletions(-) diff --git a/src/cut_strategies/cuts_base.jl b/src/cut_strategies/cuts_base.jl index 7792d55..8bc9d8a 100644 --- a/src/cut_strategies/cuts_base.jl +++ b/src/cut_strategies/cuts_base.jl @@ -15,7 +15,6 @@ Abstract type to hold various implementations of cut pools. A cut pool is a data """ abstract type AbstractCutPool end - """ initialize_cut_pool(options) @@ -29,6 +28,7 @@ function initialize_cut_pool(options) return [LightBenders.CutPoolMultiCut() for _ in 1:num_stages] end error("Not implemented.") + return nothing end """ @@ -64,9 +64,9 @@ end Add a cut to a Model and return the constraint reference. """ -function add_cut(model::JuMP.Model, epigraph_variable::JuMP.VariableRef, coefs::Vector{T}, rhs::T) where T <: Real +function add_cut(model::JuMP.Model, epigraph_variable::JuMP.VariableRef, coefs::Vector{T}, rhs::T) where {T <: Real} alpha = epigraph_variable cache = model.ext[:state]::StateCache cref = @constraint(model, alpha >= rhs + dot(coefs, cache.variables)) return cref -end \ No newline at end of file +end diff --git a/src/cut_strategies/local_cuts.jl b/src/cut_strategies/local_cuts.jl index 75361ff..377186c 100644 --- a/src/cut_strategies/local_cuts.jl +++ b/src/cut_strategies/local_cuts.jl @@ -16,15 +16,15 @@ function number_of_cuts(pool::LocalCutPool) end function store_cut!( - pool::LocalCutPool, - coefs::Vector{Float64}, - state::Vector{Float64}, - rhs::Float64, - obj::Float64 + pool::LocalCutPool, + coefs::Vector{Float64}, + state::Vector{Float64}, + rhs::Float64, + obj::Float64, ) push!(pool.coefs, coefs) push!(pool.state, state) push!(pool.rhs, rhs) push!(pool.obj, obj) return nothing -end \ No newline at end of file +end diff --git a/src/cut_strategies/single_cut.jl b/src/cut_strategies/single_cut.jl index 7980f44..8c32b96 100644 --- a/src/cut_strategies/single_cut.jl +++ b/src/cut_strategies/single_cut.jl @@ -19,11 +19,11 @@ function number_of_cuts(pool::CutPoolSingleCut) end function store_cut!( - pool::CutPoolSingleCut, - coefs::Vector{Float64}, - state::Vector{Float64}, - rhs::Float64, - obj::Float64 + pool::CutPoolSingleCut, + coefs::Vector{Float64}, + state::Vector{Float64}, + rhs::Float64, + obj::Float64, ) push!(pool.coefs, coefs) push!(pool.state, state) @@ -33,11 +33,11 @@ function store_cut!( end function store_cut!( - pool::Vector{CutPoolSingleCut}, + pool::Vector{CutPoolSingleCut}, local_cuts::LocalCutPool, state::Vector{Float64}, options, - t::Integer + t::Integer, ) if isa(options.risk_measure, RiskNeutral) return risk_neutral_single_cut!(pool, local_cuts, state, options, t) @@ -49,11 +49,11 @@ function store_cut!( end function risk_neutral_single_cut!( - pool::Vector{CutPoolSingleCut}, - local_cuts::LocalCutPool, + pool::Vector{CutPoolSingleCut}, + local_cuts::LocalCutPool, state::Vector{Float64}, options, - t::Integer + t::Integer, ) num_local_cuts = length(local_cuts.obj) obj = mean(local_cuts.obj) @@ -67,11 +67,11 @@ function risk_neutral_single_cut!( end function cvar_single_cut!( - pool::Vector{CutPoolSingleCut}, - local_cuts::LocalCutPool, + pool::Vector{CutPoolSingleCut}, + local_cuts::LocalCutPool, state::Vector{Float64}, options, - t::Int + t::Int, ) weights = build_cvar_weights(local_cuts.obj, options.risk_measure.alpha, options.risk_measure.lambda) obj = dot(weights, local_cuts.obj) diff --git a/src/debugging_options.jl b/src/debugging_options.jl index 3645078..1c4ae26 100644 --- a/src/debugging_options.jl +++ b/src/debugging_options.jl @@ -1,4 +1,4 @@ Base.@kwdef mutable struct DebuggingOptions logs_dir::String = "" write_lp::Bool = false -end \ No newline at end of file +end diff --git a/src/deterministic_equivalent/deterministic_equivalent.jl b/src/deterministic_equivalent/deterministic_equivalent.jl index 53039f0..2266dc7 100644 --- a/src/deterministic_equivalent/deterministic_equivalent.jl +++ b/src/deterministic_equivalent/deterministic_equivalent.jl @@ -8,7 +8,7 @@ function deterministic_equivalent(; first_stage_builder::Function, second_stage_builder::Function, second_stage_modifier::Function, - inputs=nothing, + inputs = nothing, options::DeterministicEquivalentOptions, ) num_scenarios = options.num_scenarios @@ -61,7 +61,7 @@ function copy_and_replace_variables( ) return JuMP.GenericAffExpr( src.constant, - Pair{VariableRef,Float64}[ + Pair{VariableRef, Float64}[ src_to_dest_variable[key] => val for (key, val) in src.terms ], ) @@ -73,7 +73,7 @@ function copy_and_replace_variables( ) return JuMP.GenericQuadExpr( copy_and_replace_variables(src.aff, src_to_dest_variable), - Pair{UnorderedPair{VariableRef},Float64}[ + Pair{UnorderedPair{VariableRef}, Float64}[ UnorderedPair{VariableRef}( src_to_dest_variable[pair.a], src_to_dest_variable[pair.b], @@ -104,7 +104,7 @@ function push_model!( model::JuMP.Model, subproblem::JuMP.Model, scenario::Int, - num_scenarios::Int + num_scenarios::Int, ) # push variables src_variables = all_variables_but_state(subproblem) diff --git a/src/optimize_helpers.jl b/src/optimize_helpers.jl index 348b4a2..7419f4d 100644 --- a/src/optimize_helpers.jl +++ b/src/optimize_helpers.jl @@ -14,7 +14,7 @@ function print_conflict_to_file(model::JuMP.Model, filename::String = "infeasibl write(io, "IIS found\n") for cref in all_constraints(model, include_variable_in_set_constraints = true) if MOI.get(model, MOI.ConstraintConflictStatus(), cref) == MOI.IN_CONFLICT - println(io, cref) + println(io, cref) end end end diff --git a/src/progress_logs/abstractions.jl b/src/progress_logs/abstractions.jl index 96a10fa..5c7a67e 100644 --- a/src/progress_logs/abstractions.jl +++ b/src/progress_logs/abstractions.jl @@ -3,4 +3,4 @@ Abstract type to hold progress logs for differnt algorithms. """ -abstract type AbstractProgressLog end \ No newline at end of file +abstract type AbstractProgressLog end diff --git a/src/progress_logs/benders_training_iterations.jl b/src/progress_logs/benders_training_iterations.jl index 2ee6e23..1de9bcd 100644 --- a/src/progress_logs/benders_training_iterations.jl +++ b/src/progress_logs/benders_training_iterations.jl @@ -55,20 +55,23 @@ function start_iteration!(progress::BendersTrainingIterationsLog) push!(progress.LB, 0.0) push!(progress.UB, 0.0) progress.current_iteration += 1 + return nothing end function report_current_bounds(progress::BendersTrainingIterationsLog) - next(progress.progress_table, + next(progress.progress_table, [ progress.current_iteration, current_lower_bound(progress), current_upper_bound(progress), current_gap(progress), time() - progress.start_time, - ] + ], ) + return nothing end function finish_training!(progress::BendersTrainingIterationsLog) finalize(progress.progress_table) -end \ No newline at end of file + return nothing +end diff --git a/src/progress_logs/deterministic_equivalent.jl b/src/progress_logs/deterministic_equivalent.jl index 87323a7..4d065e3 100644 --- a/src/progress_logs/deterministic_equivalent.jl +++ b/src/progress_logs/deterministic_equivalent.jl @@ -4,4 +4,5 @@ function DeterministicEquivalentLog(num_scenarios::Int) println(" ") println("Number of stages: 2") println("Number of scenarios: ", num_scenarios) + return nothing end diff --git a/src/simulate.jl b/src/simulate.jl index bbeddf2..13196ff 100644 --- a/src/simulate.jl +++ b/src/simulate.jl @@ -2,7 +2,7 @@ abstract type AbstractSimulationImplementation end struct BendersSerialSimulation <: AbstractSimulationImplementation end -""" +""" """ @enumx SimulationStateHandling begin # This is also known as commercial simulation @@ -24,7 +24,7 @@ end function SimulationOptions(policy_training_options::PolicyTrainingOptions; kwargs...) return SimulationOptions(; num_scenarios = policy_training_options.num_scenarios, - kwargs... + kwargs..., ) end @@ -37,7 +37,7 @@ function simulate(; second_stage_modifier::Function, inputs = nothing, policy::Policy, - simulation_options::SimulationOptions + simulation_options::SimulationOptions, ) if simulation_options.implementation_strategy isa BendersSerialSimulation return serial_benders_simulate(; @@ -53,4 +53,3 @@ function simulate(; error("Algorithm not implemented.") end end - diff --git a/src/simulation_strategies/benders_serial.jl b/src/simulation_strategies/benders_serial.jl index 6fde523..1c47647 100644 --- a/src/simulation_strategies/benders_serial.jl +++ b/src/simulation_strategies/benders_serial.jl @@ -3,7 +3,7 @@ function serial_benders_simulate(; first_stage_builder::Function, second_stage_builder::Function, second_stage_modifier::Function, - inputs=nothing, + inputs = nothing, policy::Policy, simulation_options::SimulationOptions, ) diff --git a/src/states.jl b/src/states.jl index 43507c0..84275c4 100644 --- a/src/states.jl +++ b/src/states.jl @@ -69,4 +69,4 @@ function set_state(model, state) JuMP.fix(cache.variables[i], state[i]; force = true) end return nothing -end \ No newline at end of file +end diff --git a/src/stopping_rules.jl b/src/stopping_rules.jl index 5f5a308..0afd993 100644 --- a/src/stopping_rules.jl +++ b/src/stopping_rules.jl @@ -63,4 +63,4 @@ function convergence_test( ) both_converged = progress.current_iteration >= rule.min_iterations && has_converged(convergence_test(progress, Gap(rule.abstol, rule.reltol))) return ConvergenceResult(both_converged, "converged with gap with minimum number of iterations") -end \ No newline at end of file +end diff --git a/src/train.jl b/src/train.jl index 5ca661a..7aec8cc 100644 --- a/src/train.jl +++ b/src/train.jl @@ -30,7 +30,7 @@ end Train a policy using the Benders algorithm. There are various ways of performing this training, which are controlled by the options argument. The `state_variables_builder`, `first_stage_builder`, `second_stage_builder` and `second_stage_modifier` -functions are used to construct and modify the models that are used in the training process. +functions are used to construct and modify the models that are used in the training process. The inputs argument contains the data that is used to build the models. """ function train(; @@ -39,7 +39,7 @@ function train(; second_stage_builder::Function, second_stage_modifier::Function, inputs = nothing, - policy_training_options::PolicyTrainingOptions + policy_training_options::PolicyTrainingOptions, ) if policy_training_options.implementation_strategy isa SerialTraining return serial_benders_train(; diff --git a/src/training_strategies/benders_serial.jl b/src/training_strategies/benders_serial.jl index 2f359fa..1a7b934 100644 --- a/src/training_strategies/benders_serial.jl +++ b/src/training_strategies/benders_serial.jl @@ -3,7 +3,7 @@ function serial_benders_train(; first_stage_builder::Function, second_stage_builder::Function, second_stage_modifier::Function, - inputs=nothing, + inputs = nothing, policy_training_options::PolicyTrainingOptions, ) validate_benders_training_options(policy_training_options) @@ -41,7 +41,8 @@ function serial_benders_train(; # Store the opening cut in a temporary cut pool store_cut!(local_pools, coefs, state, rhs, obj) future_cost = get_future_cost(second_stage_model, policy_training_options) - progress.UB[progress.current_iteration] += (JuMP.objective_value(second_stage_model) - future_cost) / policy_training_options.num_scenarios + progress.UB[progress.current_iteration] += + (JuMP.objective_value(second_stage_model) - future_cost) / policy_training_options.num_scenarios end # Store the (stage, scenario) cut(s) in a persitent pool. # Cuts here can be following the single cut strategy or @@ -59,10 +60,10 @@ function serial_benders_train(; end end return Policy( - progress=progress, - pool=pool, - states=state, - policy_training_options=policy_training_options + progress = progress, + pool = pool, + states = state, + policy_training_options = policy_training_options, ) end @@ -73,4 +74,4 @@ function validate_benders_training_options(policy_training_options::PolicyTraini error("Validation of policy training options failed.") end return nothing -end \ No newline at end of file +end diff --git a/test/runtests.jl b/test/runtests.jl index 17fa99b..f385b7c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,7 +1,7 @@ using Test function test_modules(dir::AbstractString) - result = Dict{String,Vector{String}}() + result = Dict{String, Vector{String}}() for (root, dirs, files) in walkdir(dir) for file in joinpath.(root, filter(f -> occursin(r"test_(.)+\.jl", f), files)) main_case = splitpath(file)[end-2] From c6f25ba55965b90d8f60285304c8a4ab6160509d Mon Sep 17 00:00:00 2001 From: raphasampaio Date: Mon, 25 Nov 2024 13:52:41 -0300 Subject: [PATCH 5/5] Project updates --- src/cut_strategies/multi_cut.jl | 50 ++++++++++---------- src/risk_measures.jl | 24 ++++++---- src/training_strategies/benders_job_queue.jl | 16 +++---- 3 files changed, 49 insertions(+), 41 deletions(-) diff --git a/src/cut_strategies/multi_cut.jl b/src/cut_strategies/multi_cut.jl index a9a2a86..2cac30f 100644 --- a/src/cut_strategies/multi_cut.jl +++ b/src/cut_strategies/multi_cut.jl @@ -14,21 +14,22 @@ function number_of_cuts(pool::CutPoolMultiCut) end function store_cut!( - pool_multicut::CutPoolMultiCut, - local_pool::LocalCutPool + pool_multicut::CutPoolMultiCut, + local_pool::LocalCutPool, ) push!(pool_multicut.cuts, local_pool) return nothing end function store_cut!( - pool::Vector{CutPoolMultiCut}, + pool::Vector{CutPoolMultiCut}, local_cuts::LocalCutPool, state::Vector{Float64}, options, - t::Integer + t::Integer, ) store_cut!(pool[t-1], local_cuts) + return nothing end function create_epigraph_multi_cut_variables!(model::JuMP.Model, policy_training_options) @@ -42,16 +43,16 @@ function create_epigraph_multi_cut_variables!(model::JuMP.Model, policy_training end function add_multi_cut_risk_neutral_cuts!( - model::JuMP.Model, + model::JuMP.Model, alphas::Vector{JuMP.VariableRef}, - pool::CutPoolMultiCut, - policy_training_options + pool::CutPoolMultiCut, + policy_training_options, ) for scen in 1:policy_training_options.num_scenarios JuMP.set_objective_coefficient( - model, - alphas[scen], - (1.0 - policy_training_options.discount_rate) / policy_training_options.num_scenarios + model, + alphas[scen], + (1.0 - policy_training_options.discount_rate) / policy_training_options.num_scenarios, ) for i in 1:length(pool.cuts) add_cut(model, alphas[scen], pool.cuts[i].coefs[scen], pool.cuts[i].rhs[scen]) @@ -61,33 +62,34 @@ function add_multi_cut_risk_neutral_cuts!( end function add_multi_cut_cvar_cuts!( - model::JuMP.Model, + model::JuMP.Model, alphas::Vector{JuMP.VariableRef}, - pool::CutPoolMultiCut, - policy_training_options + pool::CutPoolMultiCut, + policy_training_options, ) discount_rate_multiplier = (1.0 - policy_training_options.discount_rate) JuMP.@variable(model, z_explicit_cvar) # λ * z JuMP.set_objective_coefficient( - model, - z_explicit_cvar, - discount_rate_multiplier * (policy_training_options.risk_measure.lambda) + model, + z_explicit_cvar, + discount_rate_multiplier * (policy_training_options.risk_measure.lambda), ) JuMP.@variable(model, delta_explicit_cvar[scen = 1:policy_training_options.num_scenarios] >= 0) for scen in 1:policy_training_options.num_scenarios # (1 - λ)/L * sum(alphas) JuMP.set_objective_coefficient( - model, - alphas[scen], - discount_rate_multiplier * (1 - policy_training_options.risk_measure.lambda) / policy_training_options.num_scenarios + model, + alphas[scen], + discount_rate_multiplier * (1 - policy_training_options.risk_measure.lambda) / policy_training_options.num_scenarios, ) # λ / ((1 - CVaR_\alpha) * L) * sum(deltas) JuMP.set_objective_coefficient( - model, - delta_explicit_cvar[scen], - discount_rate_multiplier * - (policy_training_options.risk_measure.lambda) / ((1 - policy_training_options.risk_measure.alpha) * policy_training_options.num_scenarios) + model, + delta_explicit_cvar[scen], + discount_rate_multiplier * + (policy_training_options.risk_measure.lambda) / + ((1 - policy_training_options.risk_measure.alpha) * policy_training_options.num_scenarios), ) # Add delta constraint JuMP.@constraint(model, delta_explicit_cvar[scen] >= alphas[scen] - z_explicit_cvar) @@ -119,4 +121,4 @@ function get_multi_cut_future_cost(model::JuMP.Model)::Float64 end alphas = model[:epi_multi_cut]::Vector{JuMP.VariableRef} return mean(JuMP.value.(alphas)) -end \ No newline at end of file +end diff --git a/src/risk_measures.jl b/src/risk_measures.jl index 1545c77..230cda7 100644 --- a/src/risk_measures.jl +++ b/src/risk_measures.jl @@ -18,26 +18,32 @@ struct RiskNeutral <: AbstractRiskMeasure end CVaR risk measure, the risk measure is a convex combination of the expected value and the CVaR. # Fields -- `alpha::Float64`: The confidence level for the CVaR -- `lambda::Float64`: The weight of the CVaR in the convex combination + + - `alpha::Float64`: The confidence level for the CVaR + - `lambda::Float64`: The weight of the CVaR in the convex combination The convex combination is expressed as: + ```math \\begin{equation} (1 - \\lambda) \\text{Expected Value} + \\lambda \\text{CVaR}_{\\alpha} \\end{equation} ``` -Example: +Example: + ```julia -cvar_options = CVaROptions(alpha=0.95, lambda=0.5) +cvar_options = CVaROptions(alpha = 0.95, lambda = 0.5) ``` + will give a risk measure that is a convex combination of the expected value and the CVaR with a confidence level of 0.95 and a weight of 0.5. + ```math \\begin{equation} 0.5 \\text{Expected Value} + 0.5 \\text{CVaR}_{0.95} \\end{equation} ``` + Where the CVaR of 95% is approximatelly equal to the mean of the 5% worst cases. If we choose `lambda=0.0` the risk measure will be the expected value. If we choose `lambda=1.0` the risk measure will be the CVaR. @@ -46,7 +52,7 @@ If we choose `alpha=0.0` the CVaR will be equivalent to the expected value. If w mutable struct CVaR <: AbstractRiskMeasure alpha::Float64 lambda::Float64 - function CVaR(;alpha::Real=0.95, lambda::Real=0.5)::CVaR + function CVaR(; alpha::Real = 0.95, lambda::Real = 0.5)::CVaR num_errors = 0 if alpha < 0.0 || alpha > 1.0 @error("alpha must be between 0 and 1.") @@ -64,9 +70,9 @@ mutable struct CVaR <: AbstractRiskMeasure end function build_cvar_weights( - objectives::Vector{Float64}, - alpha::Real, - lambda::Real, + objectives::Vector{Float64}, + alpha::Real, + lambda::Real, )::Vector{Float64} N = length(objectives) κ = ceil(alpha * N) @@ -87,4 +93,4 @@ function build_cvar_weights( end end return weights -end \ No newline at end of file +end diff --git a/src/training_strategies/benders_job_queue.jl b/src/training_strategies/benders_job_queue.jl index 5b45b9f..d7ffb92 100644 --- a/src/training_strategies/benders_job_queue.jl +++ b/src/training_strategies/benders_job_queue.jl @@ -29,8 +29,8 @@ function job_queue_benders_train(; first_stage_builder::Function, second_stage_builder::Function, second_stage_modifier::Function, - inputs=nothing, - policy_training_options::PolicyTrainingOptions + inputs = nothing, + policy_training_options::PolicyTrainingOptions, ) JQM.mpi_init() JQM.mpi_barrier() @@ -123,20 +123,20 @@ function job_queue_benders_train(; end JQM.mpi_barrier() return Policy( - progress=progress, - pool=pool, - states=state, - policy_training_options=policy_training_options + progress = progress, + pool = pool, + states = state, + policy_training_options = policy_training_options, ) end -function workers_loop( +function workers_loop( state_variables_builder::Function, first_stage_builder::Function, second_stage_builder::Function, second_stage_modifier::Function, inputs, - policy_training_options::PolicyTrainingOptions + policy_training_options::PolicyTrainingOptions, ) worker = JQM.Worker() while true