From bc20f1f943c5ceb599eedfd9a96e8e700e1afc32 Mon Sep 17 00:00:00 2001 From: Ruslan Sadykov <41117501+rrsadykov@users.noreply.github.com> Date: Fri, 19 Jan 2024 09:50:48 +0100 Subject: [PATCH] Remove Heuristic module (#1120) --- src/Algorithm/Algorithm.jl | 2 +- src/Algorithm/conquer.jl | 18 ++++++++---- src/Algorithm/heuristic/restricted_master.jl | 24 ++++++++-------- src/Coluna.jl | 3 -- src/Heuristic/Heuristic.jl | 29 -------------------- 5 files changed, 26 insertions(+), 50 deletions(-) delete mode 100644 src/Heuristic/Heuristic.jl diff --git a/src/Algorithm/Algorithm.jl b/src/Algorithm/Algorithm.jl index 05ea001e3..032beea15 100644 --- a/src/Algorithm/Algorithm.jl +++ b/src/Algorithm/Algorithm.jl @@ -4,7 +4,7 @@ using DataStructures import MathOptInterface import TimerOutputs -using ..Coluna, ..ColunaBase, ..MathProg, ..MustImplement, ..ColGen, ..Benders, ..AlgoAPI, ..TreeSearch, ..Branching, ..Heuristic +using ..Coluna, ..ColunaBase, ..MathProg, ..MustImplement, ..ColGen, ..Benders, ..AlgoAPI, ..TreeSearch, ..Branching using Crayons, DynamicSparseArrays, Logging, Parameters, Printf, Random, Statistics, SparseArrays, LinearAlgebra diff --git a/src/Algorithm/conquer.jl b/src/Algorithm/conquer.jl index 18fced3a4..f4601f8a9 100644 --- a/src/Algorithm/conquer.jl +++ b/src/Algorithm/conquer.jl @@ -2,7 +2,7 @@ # ParameterizedHeuristic #################################################################### -struct ParameterizedHeuristic{A <: AlgoAPI.AbstractAlgorithm} +struct ParameterizedHeuristic{A <: AbstractOptimizationAlgorithm} algorithm::A root_priority::Float64 nonroot_priority::Float64 @@ -261,14 +261,20 @@ function run_heuristics!(ctx::ColCutGenContext, heuristics, env, reform, input, records = create_records(reform) end - output = Heuristic.run(heuristic.algorithm, env, reform, conquer_output) - for sol in Heuristic.get_primal_sols(output) - store_ip_primal_sol!(get_global_primal_handler(input), sol) - end - + heuristic_output = run!(heuristic.algorithm, env, reform, conquer_output) + update!(conquer_output, heuristic_output) + # for sol in Heuristic.get_primal_sols(output) + # store_ip_primal_sol!(get_global_primal_handler(input), sol) + # end + if ismanager(heuristic.algorithm) restore_from_records!(input.units_to_restore, records) end + + if getterminationstatus(conquer_output) == TIME_LIMIT || + ip_gap_closed(conquer_output, atol = ctx.params.opt_atol, rtol = ctx.params.opt_rtol) + return false + end end return true end diff --git a/src/Algorithm/heuristic/restricted_master.jl b/src/Algorithm/heuristic/restricted_master.jl index 9becfa8e6..07eb5b9b5 100644 --- a/src/Algorithm/heuristic/restricted_master.jl +++ b/src/Algorithm/heuristic/restricted_master.jl @@ -4,7 +4,7 @@ optimizes the master problem restricted to active master column variables using If the heuristic finds a solution, it checks that this solution does not violate any essential cut. """ -struct RestrictedMasterHeuristic <: Heuristic.AbstractHeuristic +struct RestrictedMasterHeuristic <: AbstractOptimizationAlgorithm solve_ip_form_alg::SolveIpForm RestrictedMasterHeuristic(; @@ -21,27 +21,29 @@ function get_child_algorithms(algo::RestrictedMasterHeuristic, reform::Reformula return child_algs end -struct RestrictedMasterHeuristicOutput <: Heuristic.AbstractHeuristicOutput - ip_primal_sols::Vector{PrimalSolution} -end +# struct RestrictedMasterHeuristicOutput <: Heuristic.AbstractHeuristicOutput +# ip_primal_sols::Vector{PrimalSolution} +# end -Heuristic.get_primal_sols(o::RestrictedMasterHeuristicOutput) = o.ip_primal_sols +# Heuristic.get_primal_sols(o::RestrictedMasterHeuristicOutput) = o.ip_primal_sols -function Heuristic.run(algo::RestrictedMasterHeuristic, env, reform, opt_state::OptimizationState) - ip_form_output = run!(algo.solve_ip_form_alg, env, getmaster(reform), opt_state) +function run!(algo::RestrictedMasterHeuristic, env, reform, input::OptimizationState) + master = getmaster(reform) + ip_form_output = run!(algo.solve_ip_form_alg, env, master, input) ip_primal_sols = get_ip_primal_sols(ip_form_output) + output = OptimizationState(master) + # We need to make sure that the solution is feasible by separating essential cuts and then # project the solution on master. - feasible_ip_primal_sols = PrimalSolution[] if length(ip_primal_sols) > 0 for sol in sort(ip_primal_sols) # we start with worst solution to add all improving solutions cutgen = CutCallbacks(call_robust_facultative = false) - cutcb_output = run!(cutgen, env, getmaster(reform), CutCallbacksInput(sol)) + cutcb_output = run!(cutgen, env, master, CutCallbacksInput(sol)) if cutcb_output.nb_cuts_added == 0 - push!(feasible_ip_primal_sols, sol) + add_ip_primal_sol!(output, sol) end end end - return RestrictedMasterHeuristicOutput(feasible_ip_primal_sols) + return output end diff --git a/src/Coluna.jl b/src/Coluna.jl index 9d5f4f446..c816b7e20 100644 --- a/src/Coluna.jl +++ b/src/Coluna.jl @@ -60,9 +60,6 @@ using .ColGen include("Benders/Benders.jl") using .Benders -include("Heuristic/Heuristic.jl") -using .Heuristic - include("Algorithm/Algorithm.jl") using .Algorithm diff --git a/src/Heuristic/Heuristic.jl b/src/Heuristic/Heuristic.jl deleted file mode 100644 index a2f13e96b..000000000 --- a/src/Heuristic/Heuristic.jl +++ /dev/null @@ -1,29 +0,0 @@ -module Heuristic - -!true && include("../MustImplement/MustImplement.jl") # linter -using ..MustImplement - -!true && include("../interface.jl") # linter -using ..AlgoAPI - -"Supertype for heuristic." -abstract type AbstractHeuristic <: AlgoAPI.AbstractAlgorithm end - -""" -Output of a heuristic algorithm. -""" -abstract type AbstractHeuristicOutput end - -"Returns a collection of primal solutions found by the heuristic." -@mustimplement "HeuristicOutput" get_primal_sols(::AbstractHeuristicOutput) = nothing - -""" -run the heuristic using following arguments: -- `form`: a formulation (or any representation) of the problem -- `optstate`: current optimization state - -and returns an `AbstractHeuristicOutput` object. -""" -@mustimplement "Heuristic" run(::AbstractHeuristic, env, form, optstate) = nothing - -end \ No newline at end of file