From d7714fe8e166e47b7259874f700fb0c010b5359e Mon Sep 17 00:00:00 2001 From: Mathieu Tanneau Date: Tue, 16 Oct 2018 11:21:10 -0400 Subject: [PATCH 01/13] Status fix --- src/status.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/status.jl b/src/status.jl index 6cb739a..d97ef33 100644 --- a/src/status.jl +++ b/src/status.jl @@ -21,8 +21,8 @@ These Status codes are based on those of MathOptInterface ) Status(::T) where T = Unknown -Status(s::Symbol) = Status(Val{s}) +Status(s::Symbol) = Status(Val(s)) -Status(::Type{Val{:Infeasible}}) = PrimalInfeasible -Status(::Type{Val{:Unbounded}}) = PrimalUnbounded -Status(::Type{Val{:Optimal}}) = Optimal \ No newline at end of file +Status(::Val{:Infeasible}) = PrimalInfeasible +Status(::Val{:Unbounded}) = PrimalUnbounded +Status(::Val{:Optimal}) = Optimal \ No newline at end of file From 183b1b0a0b5177b1cd96929897ce01c97f06c724 Mon Sep 17 00:00:00 2001 From: Mathieu Tanneau Date: Tue, 16 Oct 2018 11:23:27 -0400 Subject: [PATCH 02/13] MP constructor more flexible --- src/master.jl | 45 ++++++++++++++++++++++++++++++--------------- test/master.jl | 1 - 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/master.jl b/src/master.jl index d248105..4b771f7 100644 --- a/src/master.jl +++ b/src/master.jl @@ -24,6 +24,7 @@ mutable struct LindaMaster{RMP<:MPB.AbstractMathProgModel} column is added to / removed from the RMP =# + num_var_link::Int # Number of linking variables (including artificial ones) num_columns_rmp::Int # Number of columns currently in RMP active_columns::Vector{Column} # Active columns @@ -87,18 +88,21 @@ mutable struct LindaMaster{RMP<:MPB.AbstractMathProgModel} #=========================================================================== Constructor ===========================================================================# - + function LindaMaster( - rmp::RMP, num_constr_cvxty::Int, num_constr_link::Int, - rhs_constr_link::AbstractVector{Tv} + rhs_constr_link::AbstractVector{Tv}, + num_var_link::Int, + initial_columns::Vector{Column}, + rmp::RMP, ) where{RMP<:MPB.AbstractMathProgModel, Tv<:Real} # Dimension check n = MPB.numvar(rmp) - n == (2 * num_constr_link) || throw(ErrorException( - "RMP has $(n) variables instead of $(2*num_constr_link)" + ncols = length(initial_columns) + n == (num_var_link + ncols) || throw(ErrorException( + "RMP has $(n) variables instead of $(num_var_link + ncols)" )) m = MPB.numconstr(rmp) m == (num_constr_cvxty + num_constr_link) || throw(ErrorException( @@ -111,18 +115,23 @@ mutable struct LindaMaster{RMP<:MPB.AbstractMathProgModel} # Instanciate model mp = new{RMP}() - mp.num_columns_rmp = 0 - mp.active_columns = Vector{Column}(undef, 0) + # RMP columns + mp.num_var_link = num_var_link + mp.num_columns_rmp = ncols + mp.active_columns = initial_columns + # RMP constraints mp.num_constr_cvxty = num_constr_cvxty mp.num_constr_link = num_constr_link - mp.rhs_constr_link = rhs_constr_link + mp.rhs_constr_link = copy(rhs_constr_link) mp.π = Vector{Float64}(undef, num_constr_link) mp.σ = Vector{Float64}(undef, num_constr_cvxty) + # Other RMP info mp.rmp = rmp mp.rmp_status = Unknown + # Column-Generation info mp.mp_status = Unknown mp.primal_lp_bound = Inf mp.primal_ip_bound = Inf @@ -148,13 +157,13 @@ function LindaMaster( rmp = MPB.LinearQuadraticModel(lp_solver) # Add constraints for r in 1:num_constr_cvxty - MPB.addconstr!(rmp, Vector{Float64}(), Vector{Float64}(), 1.0, 1.0) + MPB.addconstr!(rmp, Float64[], Float64[], 1.0, 1.0) end for i in 1:num_constr_link MPB.addconstr!( rmp, - Vector{Float64}(), - Vector{Float64}(), + Float64[], + Float64[], rhs_constr_link[i], rhs_constr_link[i] ) @@ -162,29 +171,35 @@ function LindaMaster( end # Add artificial variables + num_var_link = 0 for i in 1:num_constr_link if senses[i] == '=' # Artificial slack and surplus MPB.addvar!(rmp, [num_constr_cvxty+i], [1.0], 0.0, 0.0, 10^4) # slack MPB.addvar!(rmp, [num_constr_cvxty+i], [-1.0], 0.0, 0.0, 10^4) # surplus + num_var_link += 2 elseif senses[i] == '<' # Regular slack ; artificial surplus MPB.addvar!(rmp, [num_constr_cvxty+i], [1.0], 0.0, Inf, 0.0) # slack MPB.addvar!(rmp, [num_constr_cvxty+i], [-1.0], 0.0, 0.0, 10^4) # surplus + num_var_link += 2 elseif senses[i] == '>' # Artificial slack ; regular surplus MPB.addvar!(rmp, [num_constr_cvxty+i], [1.0], 0.0, 0.0, 10^4) # slack MPB.addvar!(rmp, [num_constr_cvxty+i], [-1.0], 0.0, Inf, 0.0) # surplus + num_var_link += 2 else - error("Wrong input $(senses[i])") + error("Unknown sense for constraint $i: `$(senses[i])`") end end mp = LindaMaster( - rmp, num_constr_cvxty, num_constr_link, - rhs_constr_link + rhs_constr_link, + num_var_link, + Column[], + rmp ) return mp @@ -212,7 +227,7 @@ Solve Restricted Master Problem, and update current dual iterate. function solve_rmp!(master::LindaMaster) MPB.optimize!(master.rmp) - rmp_status = Status(Val{MPB.status(master.rmp)}) + rmp_status = Status(Val(MPB.status(master.rmp))) master.rmp_status = rmp_status # Update dual iterate diff --git a/test/master.jl b/test/master.jl index 8274d54..7933e1a 100644 --- a/test/master.jl +++ b/test/master.jl @@ -29,7 +29,6 @@ add_initial_columns!(mp, m, R) @test mp.num_columns_rmp == 2*R @test MPB.numvar(mp.rmp) == 2*m + 2*R - # Solve RMP to optimality Linda.solve_rmp!(mp) s = MPB.getreducedcosts(mp.rmp) From 00dff93300f46e1ca4c9b76e3f06f4d6eb4ebd81 Mon Sep 17 00:00:00 2001 From: Mathieu Tanneau Date: Tue, 16 Oct 2018 17:48:31 -0400 Subject: [PATCH 03/13] Copy initial set of columns --- src/master.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/master.jl b/src/master.jl index 4b771f7..46d6f85 100644 --- a/src/master.jl +++ b/src/master.jl @@ -118,7 +118,7 @@ mutable struct LindaMaster{RMP<:MPB.AbstractMathProgModel} # RMP columns mp.num_var_link = num_var_link mp.num_columns_rmp = ncols - mp.active_columns = initial_columns + mp.active_columns = deepcopy(initial_columns) # RMP constraints mp.num_constr_cvxty = num_constr_cvxty From bb8f069c214658544332061df4c41cbd38395413 Mon Sep 17 00:00:00 2001 From: Mathieu Tanneau Date: Tue, 16 Oct 2018 17:48:43 -0400 Subject: [PATCH 04/13] More detailed log --- src/colgen.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/colgen.jl b/src/colgen.jl index 55ea7b7..a36b972 100644 --- a/src/colgen.jl +++ b/src/colgen.jl @@ -65,7 +65,11 @@ function solve_colgen!( @printf("%+16.7e", mp.dual_bound) # RMP stats @printf("%10.0f", mp.num_columns_rmp) # number of columns in RMP - @printf("%9.2f", time_mp_total + time_sp_total) + @printf("%9.2f", time_mp_total) + @printf("%9.2f", time_sp_total) + @printf("%9.2f", time() - time_start) + @printf("%9d", MPB.getbarrieriter(mp.rmp)) + @printf("%9d", MPB.getsimplexiter(mp.rmp)) print("\n") end From 6155f55ee57a547e5724c7b31474140f012d0c1e Mon Sep 17 00:00:00 2001 From: Mathieu Tanneau Date: Mon, 29 Oct 2018 10:13:02 -0400 Subject: [PATCH 05/13] Change log header --- src/colgen.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/colgen.jl b/src/colgen.jl index a36b972..581953b 100644 --- a/src/colgen.jl +++ b/src/colgen.jl @@ -17,7 +17,7 @@ function solve_colgen!( time_cg_total::Float64 = 0.0 if env[Val{:verbose}] == 1 - println(" Itn Primal Obj Dual Obj NCols Time (s)") + println("Itn Primal Obj Dual Obj NCols MP(s) SP(s) Tot(s) BarIter SpxIter") end # Main CG loop From fcd2bd454bff0309f63c62544bf090977c24f070 Mon Sep 17 00:00:00 2001 From: Mathieu Tanneau Date: Thu, 8 Nov 2018 17:28:39 -0500 Subject: [PATCH 06/13] Add dimension check at instanciation --- src/Oracle/oracle_mip.jl | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Oracle/oracle_mip.jl b/src/Oracle/oracle_mip.jl index 35b7b1b..4f87b41 100644 --- a/src/Oracle/oracle_mip.jl +++ b/src/Oracle/oracle_mip.jl @@ -41,6 +41,26 @@ mutable struct LindaOracleMIP <: AbstractLindaOracle oracle.index = index + (m, n) = size(A_sub) + m == length(row_lb) || throw(DimensionMismatch( + "A has $m rows but $(length(row_lb)) row lower bounds" + )) + m == length(row_ub) || throw(DimensionMismatch( + "A has $m rows but $(length(row_lb)) row upper bounds" + )) + n == length(col_lb) || throw(DimensionMismatch( + "A has $n cols but $(length(col_lb)) col lower bounds" + )) + n == length(col_ub) || throw(DimensionMismatch( + "A has $n cols but $(length(col_ub)) col upper bounds" + )) + n == length(vartypes) || throw(DimensionMismatch( + "A has $n cols but $(length(vartypes)) var types" + )) + n == length(costs) || throw(DimensionMismatch( + "A has $n cols but $(length(costs)) objective terms" + )) + oracle.costs = costs oracle.A_link = A_link oracle.A_sub = A_sub From 62f06d1200350cf9ce667d223bf29dee425259f9 Mon Sep 17 00:00:00 2001 From: Mathieu Tanneau Date: Fri, 9 Nov 2018 11:41:37 -0500 Subject: [PATCH 07/13] Normalize farkas dual rays --- src/master.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/master.jl b/src/master.jl index 46d6f85..3ea715e 100644 --- a/src/master.jl +++ b/src/master.jl @@ -247,6 +247,12 @@ function solve_rmp!(master::LindaMaster) # update dual variables y = MPB.getinfeasibilityray(master.rmp) + # Normalize dual ray, for stability purposes + nrm = norm(y[(master.num_constr_cvxty+1):(master.num_constr_cvxty+master.num_constr_link)], 1) + if nrm > 1e-6 + y ./= nrm + end + master.σ .= y[1:master.num_constr_cvxty] master.π .= y[(master.num_constr_cvxty+1):(master.num_constr_cvxty+master.num_constr_link)] From b55c4842968829671dae536a7154f5c39e1a79b9 Mon Sep 17 00:00:00 2001 From: Mathieu Tanneau Date: Sat, 17 Nov 2018 12:56:46 -0500 Subject: [PATCH 08/13] Column-Generation logs --- src/Oracle/oracle_mip.jl | 3 +- src/Oracle/oracle_pool.jl | 12 +++---- src/colgen.jl | 70 ++++++++++++++++++++++----------------- test/colgen.jl | 5 +++ test/runtests.jl | 10 ++++-- 5 files changed, 57 insertions(+), 43 deletions(-) diff --git a/src/Oracle/oracle_mip.jl b/src/Oracle/oracle_mip.jl index 4f87b41..93db829 100644 --- a/src/Oracle/oracle_mip.jl +++ b/src/Oracle/oracle_mip.jl @@ -86,7 +86,8 @@ function query!( σ::Real; farkas::Bool=false, tol_reduced_cost::Float64=1.0e-6, - num_columns_max::Int=typemax(Int64) + num_columns_max::Int=typemax(Int64), + log=Dict() ) where{Tv<:Real} # Dimension checks diff --git a/src/Oracle/oracle_pool.jl b/src/Oracle/oracle_pool.jl index aacbb6d..bb42eaa 100644 --- a/src/Oracle/oracle_pool.jl +++ b/src/Oracle/oracle_pool.jl @@ -46,7 +46,8 @@ function query!( farkas::Bool=false, tol_reduced_cost::Float64=1.0e-6, num_columns_max::Int=typemax(Int64), - prop_sp_priced_max::Float64=1.0 + prop_sp_priced_max::Float64=1.0, + log::Dict=Dict() ) where{T1<:Real, T2<:Real} pool.new_columns = Set{Column}() @@ -61,7 +62,6 @@ function query!( # price each sub-problem # go through sub-problems in random order - nsp_priced = 0 perm = randperm(pool.n) for r in perm @@ -72,13 +72,13 @@ function query!( farkas=farkas, tol_reduced_cost=tol_reduced_cost ) - nsp_priced += 1 + log[:nsp_priced] += 1 # Check for infeasible sub-problem s = get_oracle_status(o) if s == PrimalInfeasible pool.status = PrimalInfeasible - @warn("Infeasible sub-problem") + @warn("Sub-problem $r is infeasible.") return pool.status end @@ -108,10 +108,6 @@ function query!( # Pricing ended because all sub-problems were solved to optimality pool.status = Optimal - # println("\tNCols: ", length(pool.new_columns)) - # println("\trc=: ", best_red_cost) - # println("\tPriced:", nsp_priced) - return pool.status end diff --git a/src/colgen.jl b/src/colgen.jl index 581953b..a5f80c5 100644 --- a/src/colgen.jl +++ b/src/colgen.jl @@ -6,15 +6,21 @@ Column-Generation algorithm. function solve_colgen!( env::LindaEnv, mp::LindaMaster{RMP}, - oracle::Oracle.AbstractLindaOracle + oracle::Oracle.AbstractLindaOracle; + cg_log::Dict=Dict() ) where{RMP<:MPB.AbstractMathProgModel} # Pre-optimization stuff n_cg_iter::Int = 0 time_start = time() - time_mp_total::Float64 = 0.0 - time_sp_total::Float64 = 0.0 - time_cg_total::Float64 = 0.0 + cg_log[:time_mp_total] = 0.0 + cg_log[:time_sp_total] = 0.0 + cg_log[:time_cg_total] = 0.0 + + cg_log[:num_iter_bar] = 0 # Total number of barrier inner iterations + cg_log[:num_iter_spx] = 0 # Total number of simplex inner iterations + + cg_log[:nsp_priced] = 0 # Number of calls to sub-problems if env[Val{:verbose}] == 1 println("Itn Primal Obj Dual Obj NCols MP(s) SP(s) Tot(s) BarIter SpxIter") @@ -25,18 +31,18 @@ function solve_colgen!( # Solve RMP, update dual variables t0 = time() solve_rmp!(mp) - time_mp_total += time() - t0 + cg_log[:time_mp_total] += time() - t0 if mp.rmp_status == Optimal farkas=false elseif mp.rmp_status == PrimalInfeasible farkas=true elseif mp.rmp_status == PrimalUnbounded - println("Master Problem is unbounded.") - return mp.mp_status + env[Val{:verbose}] == 1 && println("Master Problem is unbounded.") + break else - error("RMP status $(mp.rmp_status) not handled. Exiting.") - return mp.mp_status + @warn("RMP status $(mp.rmp_status) not handled.") + break end # Price @@ -45,9 +51,10 @@ function solve_colgen!( oracle, mp.π, mp.σ, farkas=farkas, tol_reduced_cost=env.tol_reduced_cost.val, - num_columns_max=env.num_columns_max.val + num_columns_max=env.num_columns_max.val, + log=cg_log ) - time_sp_total += time() - t0 + cg_log[:time_sp_total] += time() - t0 cols = Oracle.get_new_columns(oracle) lagrange_lb = ( @@ -56,6 +63,9 @@ function solve_colgen!( ) # Compute Lagrange lower bound mp.dual_bound = lagrange_lb > mp.dual_bound ? lagrange_lb : mp.dual_bound + cg_log[:num_iter_bar] += MPB.getbarrieriter(mp.rmp) + cg_log[:num_iter_spx] += MPB.getsimplexiter(mp.rmp) + # Log # Iteration count if env[Val{:verbose}] == 1 @@ -65,12 +75,13 @@ function solve_colgen!( @printf("%+16.7e", mp.dual_bound) # RMP stats @printf("%10.0f", mp.num_columns_rmp) # number of columns in RMP - @printf("%9.2f", time_mp_total) - @printf("%9.2f", time_sp_total) + @printf("%9.2f", cg_log[:time_mp_total]) + @printf("%9.2f", cg_log[:time_sp_total]) @printf("%9.2f", time() - time_start) - @printf("%9d", MPB.getbarrieriter(mp.rmp)) - @printf("%9d", MPB.getsimplexiter(mp.rmp)) + @printf("%9d", cg_log[:num_iter_bar]) + @printf("%9d", cg_log[:num_iter_spx]) print("\n") + flush(Base.stdout) end # Check duality gap @@ -81,28 +92,21 @@ function solve_colgen!( if mp_gap <= 10.0 ^-4 mp.mp_status = Optimal - time_cg_total += time() - time_start + # time_cg_total += time() - time_start if env[Val{:verbose}] == 1 println("Root relaxation solved.") - println("Total time / MP: ", time_mp_total) - println("Total time / SP: ", time_sp_total) - println("Total time / CG: ", time_cg_total) end - return mp.mp_status + break elseif farkas && length(cols) == 0 mp.mp_status = PrimalInfeasible - time_cg_total += time() - time_start + # time_cg_total += time() - time_start if env[Val{:verbose}] == 1 - println("Master is infeasible.") - println("Total time / MP: ", time_mp_total) - println("Total time / SP: ", time_sp_total) - println("Total time / CG: ", time_cg_total) + println("Problem is infeasible.") end - - return mp.mp_status + break else # add columns add_columns!(mp, cols) @@ -111,11 +115,15 @@ function solve_colgen!( n_cg_iter += 1 end - time_cg_total += time() - time_start + cg_log[:time_cg_total] = time() - time_start + if env[Val{:verbose}] == 1 - println("Total time / MP: ", time_mp_total) - println("Total time / SP: ", time_sp_total) - println("Total time / CG: ", time_cg_total) + @printf("Total time / MP: %.2fs\n", cg_log[:time_mp_total]) + @printf("Total time / SP: %.2fs\n", cg_log[:time_sp_total]) + @printf("Total time / CG: %.2fs\n", cg_log[:time_cg_total]) + @printf("Inner barrier iterations: %d\n", cg_log[:num_iter_bar]) + @printf("Inner simplex iterations: %d\n", cg_log[:num_iter_spx]) + @printf("Pricing calls: %d\n", cg_log[:nsp_priced]) end return mp.mp_status diff --git a/test/colgen.jl b/test/colgen.jl index 6833a61..60d2295 100644 --- a/test/colgen.jl +++ b/test/colgen.jl @@ -1,3 +1,8 @@ +import GLPK, GLPKMathProgInterface + +MPB.getbarrieriter(m::GLPKMathProgInterface.GLPKInterfaceLP.GLPKMathProgModelLP) = 0 +MPB.getsimplexiter(m::GLPKMathProgInterface.GLPKInterfaceLP.GLPKMathProgModelLP) = 0 + function add_initial_columns!(mp, m, R) # Add an initial set of columns diff --git a/test/runtests.jl b/test/runtests.jl index c9ceab3..ae98ea1 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,19 +2,23 @@ using Random using LinearAlgebra using Test + +import MathProgBase +const MPB = MathProgBase + import Linda import GLPKMathProgInterface: GLPKSolverLP, GLPKSolverMIP -import MathProgBase -const MPB = MathProgBase +import GLPK + const testdir = dirname(@__FILE__) const test_files = [ # include test file name here (without .jl extension) + "status", "env", "master", - "status", "oracle_mip", "colgen" ] From dfce9ff31fb2c1f028796fa54e24c91a43160136 Mon Sep 17 00:00:00 2001 From: Mathieu Tanneau Date: Mon, 26 Nov 2018 14:02:38 -0500 Subject: [PATCH 09/13] CG logs --- src/master.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/master.jl b/src/master.jl index 3ea715e..c1c0311 100644 --- a/src/master.jl +++ b/src/master.jl @@ -94,9 +94,9 @@ mutable struct LindaMaster{RMP<:MPB.AbstractMathProgModel} num_constr_link::Int, rhs_constr_link::AbstractVector{Tv}, num_var_link::Int, - initial_columns::Vector{Column}, + initial_columns::Vector{Tc}, rmp::RMP, - ) where{RMP<:MPB.AbstractMathProgModel, Tv<:Real} + ) where{RMP<:MPB.AbstractMathProgModel, Tv<:Real, Tc<:Column} # Dimension check n = MPB.numvar(rmp) From 46741c7f71cfc78edf0be39107e7fa1ddab7c323 Mon Sep 17 00:00:00 2001 From: Mathieu Tanneau Date: Mon, 26 Nov 2018 14:03:02 -0500 Subject: [PATCH 10/13] CG logs --- src/colgen.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/colgen.jl b/src/colgen.jl index a5f80c5..0b18bb3 100644 --- a/src/colgen.jl +++ b/src/colgen.jl @@ -115,9 +115,16 @@ function solve_colgen!( n_cg_iter += 1 end + # Logs cg_log[:time_cg_total] = time() - time_start + cg_log[:dual_bound] = mp.dual_bound + cg_log[:primal_bound] = mp.primal_lp_bound + cg_log[:n_cg_iter] = n_cg_iter + cg_log[:status] = mp.mp_status + cg_log[:num_cols_tot] = mp.num_columns_rmp if env[Val{:verbose}] == 1 + println() @printf("Total time / MP: %.2fs\n", cg_log[:time_mp_total]) @printf("Total time / SP: %.2fs\n", cg_log[:time_sp_total]) @printf("Total time / CG: %.2fs\n", cg_log[:time_cg_total]) From e603140c462cec59b65bf277c59d9c9390489bed Mon Sep 17 00:00:00 2001 From: Mathieu Tanneau Date: Mon, 26 Nov 2018 14:11:50 -0500 Subject: [PATCH 11/13] Add GLPK to test requirements --- test/REQUIRE | 1 + 1 file changed, 1 insertion(+) diff --git a/test/REQUIRE b/test/REQUIRE index 208f670..0e732ee 100644 --- a/test/REQUIRE +++ b/test/REQUIRE @@ -1 +1,2 @@ +GLPK GLPKMathProgInterface 0.4.3 \ No newline at end of file From 4eda08c171663315a9bd84a4f222c16b30fe964a Mon Sep 17 00:00:00 2001 From: Mathieu Tanneau Date: Tue, 27 Nov 2018 11:40:36 -0500 Subject: [PATCH 12/13] Enforce time limit --- src/colgen.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/colgen.jl b/src/colgen.jl index 0b18bb3..c80018c 100644 --- a/src/colgen.jl +++ b/src/colgen.jl @@ -28,6 +28,7 @@ function solve_colgen!( # Main CG loop while n_cg_iter < env[Val{:num_cgiter_max}] + # Solve RMP, update dual variables t0 = time() solve_rmp!(mp) @@ -45,6 +46,12 @@ function solve_colgen!( break end + # Check for time limit + if (time() - time_start) >= env[:time_limit] + env[Val{:verbose}] == 1 && println("Time limit reached.") + break + end + # Price t0 = time() Oracle.query!( From 8bef9800af99f8383f92b6dfbdcfc235ae30f3e0 Mon Sep 17 00:00:00 2001 From: Mathieu Tanneau Date: Wed, 28 Nov 2018 17:38:10 -0500 Subject: [PATCH 13/13] Check time limit at beginning of each iteration --- src/colgen.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/colgen.jl b/src/colgen.jl index c80018c..a58c044 100644 --- a/src/colgen.jl +++ b/src/colgen.jl @@ -29,6 +29,12 @@ function solve_colgen!( # Main CG loop while n_cg_iter < env[Val{:num_cgiter_max}] + # Check for time limit + if (time() - time_start) >= env[:time_limit] + env[Val{:verbose}] == 1 && println("Time limit reached.") + break + end + # Solve RMP, update dual variables t0 = time() solve_rmp!(mp) @@ -46,12 +52,6 @@ function solve_colgen!( break end - # Check for time limit - if (time() - time_start) >= env[:time_limit] - env[Val{:verbose}] == 1 && println("Time limit reached.") - break - end - # Price t0 = time() Oracle.query!(