From 37f3abee4279d78e51720ece43c211fce513b794 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Fri, 8 Aug 2025 14:50:07 -0500 Subject: [PATCH] FisSal2011: Speed up hash calculation --- src/Cuts/tableau/gmi.jl | 29 ++++++++++++++++------------- src/Cuts/tableau/gmi_dual.jl | 12 +++++++----- src/Cuts/tableau/structs.jl | 1 + 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/Cuts/tableau/gmi.jl b/src/Cuts/tableau/gmi.jl index 86a17db..6b2351c 100644 --- a/src/Cuts/tableau/gmi.jl +++ b/src/Cuts/tableau/gmi.jl @@ -253,12 +253,13 @@ function compute_gmi(data::ProblemData, tableau::Tableau)::ConstraintSet end @timeit "Pre-allocation" begin - ub::Vector{Float64} = fill(Inf, nrows) - lb::Vector{Float64} = fill(0.999, nrows) + cut_ub::Vector{Float64} = fill(Inf, nrows) + cut_lb::Vector{Float64} = fill(0.999, nrows) nnz_tableau::Int = length(tableau_I) - lhs_I::Vector{Int} = Vector{Int}(undef, nnz_tableau) - lhs_J::Vector{Int} = Vector{Int}(undef, nnz_tableau) - lhs_V::Vector{Float64} = Vector{Float64}(undef, nnz_tableau) + cut_lhs_I::Vector{Int} = Vector{Int}(undef, nnz_tableau) + cut_lhs_J::Vector{Int} = Vector{Int}(undef, nnz_tableau) + cut_lhs_V::Vector{Float64} = Vector{Float64}(undef, nnz_tableau) + cut_hash::Vector{UInt64} = zeros(UInt64, nrows) nnz_count::Int = 0 end @@ -290,22 +291,24 @@ function compute_gmi(data::ProblemData, tableau::Tableau)::ConstraintSet # Store if significant if abs(v) > 1e-8 nnz_count += 1 - lhs_I[nnz_count] = i - lhs_J[nnz_count] = j - lhs_V[nnz_count] = v + cut_lhs_I[nnz_count] = i + cut_lhs_J[nnz_count] = j + cut_lhs_V[nnz_count] = v + cut_hash[i] = hash(j, cut_hash[i]) + cut_hash[i] = hash(v, cut_hash[i]) end end end @timeit "Resize arrays to actual size" begin - resize!(lhs_I, nnz_count) - resize!(lhs_J, nnz_count) - resize!(lhs_V, nnz_count) + resize!(cut_lhs_I, nnz_count) + resize!(cut_lhs_J, nnz_count) + resize!(cut_lhs_V, nnz_count) end @timeit "Convert to ConstraintSet" begin - lhs::SparseMatrixCSC = sparse(lhs_I, lhs_J, lhs_V, nrows, ncols) - cs::ConstraintSet = ConstraintSet(; lhs, ub, lb) + cut_lhs::SparseMatrixCSC = sparse(cut_lhs_I, cut_lhs_J, cut_lhs_V, nrows, ncols) + cs::ConstraintSet = ConstraintSet(; lhs=cut_lhs, ub=cut_ub, lb=cut_lb, hash=cut_hash) end return cs diff --git a/src/Cuts/tableau/gmi_dual.jl b/src/Cuts/tableau/gmi_dual.jl index ec7a55d..808fd9b 100644 --- a/src/Cuts/tableau/gmi_dual.jl +++ b/src/Cuts/tableau/gmi_dual.jl @@ -486,8 +486,7 @@ function collect_gmi_FisSal2011( @timeit "Compute cut hashses" begin unique_indices = Int[] for i in 1:ncuts - cut_data = (cuts_s.lhs[i, :], cuts_s.lb[i], cuts_s.ub[i]) - cut_hash = hash(cut_data) + cut_hash = cuts_s.hash[i] if !(cut_hash in pool_cut_hashes) push!(pool_cut_hashes, cut_hash) push!(unique_indices, i) @@ -499,7 +498,8 @@ function collect_gmi_FisSal2011( pool = ConstraintSet( lhs = sparse(cuts_s.lhs[unique_indices, :]'), lb = cuts_s.lb[unique_indices], - ub = cuts_s.ub[unique_indices] + ub = cuts_s.ub[unique_indices], + hash = cuts_s.hash[unique_indices], ) ncuts_unique = length(unique_indices) multipliers_curr = zeros(ncuts_unique) @@ -511,6 +511,7 @@ function collect_gmi_FisSal2011( pool.lhs = [pool.lhs sparse(cuts_s.lhs[unique_indices, :]')] pool.lb = [pool.lb; cuts_s.lb[unique_indices]] pool.ub = [pool.ub; cuts_s.ub[unique_indices]] + pool.hash = [pool.hash; cuts_s.hash[unique_indices]] multipliers_curr = [multipliers_curr; zeros(ncuts_unique)] multipliers_best = [multipliers_best; zeros(ncuts_unique)] pool_cut_age = [pool_cut_age; zeros(ncuts_unique)] @@ -531,14 +532,15 @@ function collect_gmi_FisSal2011( end @timeit "Update cut hashes" begin for idx in idx_remove - cut_data = (pool.lhs[:, idx], pool.lb[idx], pool.ub[idx]) - delete!(pool_cut_hashes, hash(cut_data)) + cut_hash = pool.hash[idx] + delete!(pool_cut_hashes, cut_hash) end end @timeit "Update cut pool" begin pool.lhs = pool.lhs[:, idx_keep] pool.ub = pool.ub[idx_keep] pool.lb = pool.lb[idx_keep] + pool.hash = pool.hash[idx_keep] multipliers_curr = multipliers_curr[idx_keep] multipliers_best = multipliers_best[idx_keep] pool_cut_age = pool_cut_age[idx_keep] diff --git a/src/Cuts/tableau/structs.jl b/src/Cuts/tableau/structs.jl index b6bca2e..fd754e6 100644 --- a/src/Cuts/tableau/structs.jl +++ b/src/Cuts/tableau/structs.jl @@ -35,6 +35,7 @@ Base.@kwdef mutable struct ConstraintSet lhs::SparseMatrixCSC ub::Vector{Float64} lb::Vector{Float64} + hash::Union{Nothing,Vector{UInt64}} = nothing end export ProblemData, Tableau, Basis, ConstraintSet