From dce68d173bd86b03727faf2128a0c10c357727b9 Mon Sep 17 00:00:00 2001 From: jkhamphousone Date: Thu, 1 Aug 2024 23:18:18 +0200 Subject: [PATCH 1/3] Nodes coordinates support --- README.md | 19 ++- ...1-3.0_benders_Poly()__F=0.0_UB=903.0).pdf" | Bin 10389 -> 10389 bytes ...61-3.0_benders_LP()__F=0.0_UB=1278.0).pdf" | Bin 12240 -> 12241 bytes src/instance.jl | 76 ++++++++- src/main.jl | 159 +++++++++++++++++- test/runtests.jl | 21 +++ 6 files changed, 267 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 30d30d8..4e508d9 100755 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ julia> pars = RSP.SolverParameters( s_ij = RSP.Euclidian(), # star costs r_ij = RSP.Euclidian(), # ring costs backup_factor = 0.01, # backup_factor c'=0.01c and d'=0.01c - alpha = 3, # See [`Labbé et al., 2004`](ttps://doi.org/10.1002/net.10114) + alpha = 3, # See [`Labbé et al., 2004`](ttps://doi.org/10.1002/net.10114) tildeV = 100, # uncertain nodes set writeresults = RSP.WHTML(), # output results locally, WLocal(), WHTML() or no output false plotting = false, # plot results to subfolder src/plots/results/ @@ -74,6 +74,23 @@ julia> symbolinstance = :berlin52 julia> RSP.rspoptimize(pars, symbolinstance, Gurobi.Optimizer) ``` +## Solving with nodes coordinates + +Either: +```julia +julia> x = 1:10 +julia> y = rand(1:10, 10) +julia> RSP.rspoptimize(pars, x, y, Gurobi.Optimizer) +``` + +Or: +```julia +julia> xycoors = tuple.(1:10, rand(1:10, 10)) +julia> RSP.rspoptimize(pars, xycoors, Gurobi.Optimizer) +``` + + + ## Plotting To plot the solutions in the folder ext/results diff --git "a/ext/results/TinyInstance_12_2____\316\261-3.0_benders_Poly()/TinyInstance_12_2____\316\261-3.0_benders_Poly()__F=0.0_UB=903.0).pdf" "b/ext/results/TinyInstance_12_2____\316\261-3.0_benders_Poly()/TinyInstance_12_2____\316\261-3.0_benders_Poly()__F=0.0_UB=903.0).pdf" index 3fcd96ee239312974052934bf07a6d8550b15263..cdb1419483fd2c55576a6a544fc052c7c561a2f0 100644 GIT binary patch delta 304 zcmV-00nh%GQI%1!RVIJIYQr!PMDPBJxs)ap?3FD$N-#Mjflx{zB)yd$gd!Y6v5X{_ z=I<*xbxP4`A3K^EmVpvhp`;`SD_O!8D1=Dr8rj>m*T@dC(Jldyy|ibCcjO=(@iC&U z89EP^tkb*5XkGhUSoNtaJozN*zD?8UmXLX(MGrS%2G;PDyPJgvZANQLG zLxaeV+L^&B?NA@wJx@WX{H=%!H~Cj~E4}g|3m%-c*Ed{CpTj3xz?)qFIQcNW(bzkt=VT&K!y)$)4~vOOI= zbPYUjrBSmM(m)@wd7hn6*jo|fZt|~e#V!9*{k^NZ$Gxgs`USmJakZ1tArrHOClCRe CHICZ= diff --git "a/ext/results/eil51________________\316\261-3.0_benders_LP()/eil51________________\316\261-3.0_benders_LP()__F=0.0_UB=1278.0).pdf" "b/ext/results/eil51________________\316\261-3.0_benders_LP()/eil51________________\316\261-3.0_benders_LP()__F=0.0_UB=1278.0).pdf" index f05b2834d87cdc91250b7cf38c6961bdb9b65976..be8486f0f9730a8c81b2800f8f633e624baf015c 100644 GIT binary patch delta 327 zcmV-N0l5CqU(sK%mMwo@Yr`NE#ozrD_hl?$kf`}nS3)0}KpA5Y+P#fEh>=tnF{l~q zx1T0Wx8jTU$332NkN`%cgaRW9q#%fFAY%+w6{PQ%Q9|1CURneI>8t82d;kRuNBEpk zt*5~OLA%|oXpQbBAq_-=E2DuVge4fFvvZ@}rs+(3!^g7{Hqn2kkK^STBe_$0Xtd6RcA-j2=yigjrrHJ)^a#yzIj(_R?+SUKZwW?qG1;plYy_2mjAOSR!&MwUj9RP~y ZU1wkb0IsnK1CyvPAP6xEB_%~qMhfN&n^*t< delta 326 zcmV-M0lEIsU(jE$mMwolYlJWmh421~xs)meO`@x^$R1W5J22RBfRB(Ze= zeG^@`Eg_Kkn3p$?p+Ewf!;S% z*z6f$87WxKXy)z{VUL7Fo5}B3@ZhYyzU3PI9DcF|ykal;QGL5{i94)J<1Ej1dGYtT zMHsCU8_4eJlUDNtRpkp`uZ|1d(AiPVM>Bb6aozAUSUuxb)vl|-FDbA)9X)gjJnzt` zSqn6f-aXGwDC`*;#JHXO3tMx`Khh^Jq>Y9E4zgBU$lddix0W*`&F3k ceil_labbe( + distance( + [x_coors[e[1]], y_coors[e[1]]], + [x_coors[e[2]], y_coors[e[2]]], + ) * (α), + ) for e in E + ) + + + for i ∈ 2:n + c[i, n+1] = c[1, i] + end + c[1, n+1] = 0 + + + d = Dict( + (a[1], a[2]) => ceil_labbe( + distance( + [x_coors[a[1]], y_coors[a[1]]], + [x_coors[a[2]], y_coors[a[2]]], + ) * (10 - α), + ) for a in A + ) + + c′ = Dict{Tuple{Int,Int},Float64}() + d′ = Dict{Tuple{Int,Int},Float64}() + for kv in c + c′[kv[1]] = c[kv[1]] * pars.backup_factor + end + for kv in d + d′[kv[1]] = d[kv[1]] * pars.backup_factor + end + return RRSPInstance(n, V, tildeV, pars.F, o, α, c, c′, d, d′, x_coors, y_coors) +end + + + + + + """ readcoordinates(data) + first line and column of data contains the number of nodes and is ignored Return two vectors of coordinates read from data """ function readcoordinates(data) diff --git a/src/main.jl b/src/main.jl index 072cbf1..9933c3b 100755 --- a/src/main.jl +++ b/src/main.jl @@ -4,7 +4,7 @@ """ rspoptimize(pars::SolverParameters, symbolinstance::Symbol, optimizer, solutionchecker = false) -Return exit code 0 +Return exit succesful code 0 """ function rspoptimize( pars::SolverParameters, @@ -39,6 +39,146 @@ function rspoptimize( end + + +""" + rspoptimize(pars::SolverParameters, xycoordinates::Vector{Tuple{Int,Int}}, optimizer, solutionchecker = false) + + Return exit succesful code 0 +""" +function rspoptimize( + pars::SolverParameters, + xycoordinates::Vector{Tuple{Int,Int}}, + optimizer, + solutionchecker = false, +) + + + + if pars.redirect_stdio + # redirect terminal outputs/stdio to file + now_file = Dates.format(Dates.now(), "yyyy-mm-dd_HHhMM") + now_folder = Dates.format(Dates.now(), "yyyy-mm-dd") + output_path = joinpath(@__DIR__, "debug", "stdio", "$now_folder") + mkpath(output_path) + redirect_stdio( + stdout = "$output_path/stdout_$(symbolinstance)_$now_file.txt", + stderr = "$output_path/stderr_$(symbolinstance)_$now_file.txt", + ) do + main(pars, xycoordinates, optimizer, solutionchecker) + GC.gc() + end + end + main(pars, xycoordinates, optimizer, solutionchecker) + GC.gc() + return 0 +end + + +function main(pars::SolverParameters, xycoordinates::Vector{Tuple{Int,Int}}, optimizer, solutionchecker = false) + + + + output_folder = joinpath(@__DIR__, "results", "solutions/") + extension = ".txt" + if pars.writeresults == HTML() + output_folder = joinpath(@__DIR__, "results", "html", "solutions", "experiments/") + extension = ".html" + end + + α = pars.alpha + for rand_inst_id ∈ pars.nb_runrand[1]:pars.nb_runrand[2] + benders_table = BDtable() + ilp_table = ILPtable() + α + nstr_random = pars.nrand > 0 ? "_" * "$(pars.nrand)" : "" + + + + + inst = createinstance_rrsp(xycoordinates, α, pars) + + instdataname = Symbol("xy_$(length(xycoordinates))") + + println("\nInstance: ", "$(length(xycoordinates))-nodes with coordinates instance") + pars.log_level > 0 && @info "α=$α" + + + printinst(inst, pars) + + if pars.solve_mod == gF() || + pars.solve_mod in [gFexploreonlyILP(), gFexploreonlyben()] + rrsp_plot_gF( + instdatame, + inst, + pars, + pars.F_interval[1], + pars.F_interval[2], + ) + end + + if pars.solve_mod == BranchBendersCut() + benders_table = round!( + rrspcreatebenders_modellazy(instdataname, inst, pars; optimizer), + ) + + end + + input_filepath = get_input_filepath( + output_folder, + instdataname, + extension, + inst, + pars, + nstr_random, + rand_inst_id, + ) + if pars.solve_mod == ILP() + + ilp_table = round!( + rrspcreate_ilplazy( + instdataname, + inst, + pars, + optimizer, + solutionchecker, + ), + ) + + + elseif pars.solve_mod == NoOptimize() + @show input_filepath + ilp_table = read_ilp_table(input_filepath, pars.plot_id) + end + + if pars.plotting && pars.writeresults != "" + if pars.solve_mod == ILP() + perform_plot(pars, inst, instdataname, ilp_table, true) + end + if pars.solve_mod == BranchBendersCut() + perform_plot(pars, inst, instdataname, benders_table, false) + end + end + if pars.writeresults != "" + write_solution_to_file( + input_filepath, + instdataname, + inst, + pars, + nstr_random, + rand_inst_id, + inst.n, + benders_table, + ilp_table, + ) + end + end + GC.gc() + return 0 +end + + + function main(pars::SolverParameters, instdataname, optimizer, solutionchecker = false) @@ -143,3 +283,20 @@ function main(pars::SolverParameters, instdataname, optimizer, solutionchecker = GC.gc() return 0 end + +""" + rspoptimize(pars::SolverParameters, x::Vector{Int}, y::Vector{Int}, optimizer, solutionchecker = false) + + Return exit succesful code 0 +""" +rspoptimize( + pars::SolverParameters, + x, y, + optimizer, + solutionchecker, +) = rspoptimize( + pars, + tuple.(x, y), + optimizer, + solutionchecker, +) \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index 8d4c6ec..84411b9 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -36,6 +36,27 @@ include("aqua.jl") include("solutionchecker.jl") + xycoordinates = tuple.(1:10, rand(1:10, 10)) + + + @test rspoptimize( + pars, + xycoordinates, + optimizer_with_attributes(GLPK.Optimizer, "msg_lev" => 2), + true, + ) == 0 + + + x = 1:10 + y = rand(1:10, 10) + @test rspoptimize( + pars, + x, + y, + optimizer_with_attributes(GLPK.Optimizer, "msg_lev" => 2), + true, + ) == 0 + @test rspoptimize( pars, :TinyInstance_10_3, From bd9c7c006fbd041e6418bacbd40a31d47b663ad3 Mon Sep 17 00:00:00 2001 From: jkhamphousone Date: Fri, 2 Aug 2024 00:09:33 +0200 Subject: [PATCH 2/3] Passing tests for nodes coordinates --- Project.toml | 2 +- README.md | 4 +- ...1-3.0_benders_Poly()__F=0.0_UB=903.0).pdf" | Bin 10389 -> 10388 bytes ...61-3.0_benders_LP()__F=0.0_UB=1278.0).pdf" | Bin 12241 -> 12240 bytes src/benders_rrsp.jl | 8 +- src/instance.jl | 10 +- src/main.jl | 117 ++---------------- test/runtests.jl | 17 +-- 8 files changed, 29 insertions(+), 129 deletions(-) diff --git a/Project.toml b/Project.toml index 5c52909..d31c5db 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "RingStarProblems" uuid = "bed4ad48-c7de-4cc5-bbc0-d98473e6c0f4" authors = ["jkhamphousone "] -version = "0.1.10" +version = "0.2.0" [deps] Cairo = "159f3aea-2a34-519c-b102-8c37f9878175" diff --git a/README.md b/README.md index 4e508d9..9988a10 100755 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ The references: Introduce the Resilient Ring Star Problem (called 1-R-RSP). The package can solve 1-R-RSP thanks to: - - A Branch-and-Benders-cut algorithm (refered to as B&BC) + - A Branch-and-Benders-cut algorithm (referred to as B&BC) - An Integer Linear Programming model (ILP) ## Ring Star Problem @@ -26,7 +26,7 @@ When setting `backup_factor=0` or `tildeV=0`, 1-R-RSP reduces to RSP # Requirements -[JuMP.jl](https://github.com/jump-dev/JuMP.jl) must be installed. You can use CPLEX, GLPK, Gurobi, Xpress or any [solver that MOI.supports Lazy Constraints callback in JuMP](https://jump.dev/JuMP.jl/stable/manual/callbacks/#Available-solvers). +[JuMP.jl](https://github.com/jump-dev/JuMP.jl) must be installed. You can use CPLEX, GLPK, Gurobi, Xpress or any [solver that supports Lazy Constraints callback in JuMP](https://jump.dev/JuMP.jl/stable/manual/callbacks/#Available-solvers). # Installation ```julia diff --git "a/ext/results/TinyInstance_12_2____\316\261-3.0_benders_Poly()/TinyInstance_12_2____\316\261-3.0_benders_Poly()__F=0.0_UB=903.0).pdf" "b/ext/results/TinyInstance_12_2____\316\261-3.0_benders_Poly()/TinyInstance_12_2____\316\261-3.0_benders_Poly()__F=0.0_UB=903.0).pdf" index cdb1419483fd2c55576a6a544fc052c7c561a2f0..860154b7134df0bec71459af1035a62bd292d826 100644 GIT binary patch delta 344 zcmV-e0jK_zQIt`zRVIH?YlAQph2Q-Z_hqay(3==-R-_MAC}Rx7?rrQLq`?ZqND{~T z@0V!p7PT2?m(%1fM;R7fjwD38j zN>76W67Bc1qA~hBNo8OoMQ=2agzyAmb8&98yEL6?XT*5vrA>dd>Ed|##wg)>J=DS} z*wj0Ulp#loh@2HqNFNd7)#NW0Jb3G%Z-h}HM@Tk0*HuIS{c5rZ9rv%IeO1)Q1GI#qtFR^Po;?eP$x zZxDE^te%Wi7P20@=gAADTZ&kJlYeC^;l!8jZe9I7ZdLu#FSn0zu#?dt6Am~aFd%PY qY6>7AATl^OlanXS4L1YD)Mqg;004wX3|y0KC?E(p3MC~)Peuw}MxiVK delta 332 zcmV-S0ki&;QI%1!RVIJIYQr!PMDPBJxs)ap?3FD$N-#Mjflx{zB)yd$gd!Y6v5X{_ z=I<*xbxP4`A3K^EmVpvhp`;`SD_O!8D1=Dr8rj>m*T@dC(Jldyy|ibCcjO=(@iC&U z89EP^tkb*5XkGhUSoNtaJozN*zD?8UmXLX(MGrS%2G;PDyPJgvZANQLG zLxaeV+L^&B?NA@wJx@WX{H=%!H~Cj~E4};rMrJHT%OUA+g=Sdw-SPS z%aEm5AVb7wWKYN*5yREwFBUvFYp-v(mOh71HiI|W_I$5?TwHXA6-kulX_jyPU)KtQ zbz%eQO?}X68lf!x;OE70rYkx*s`+3>?<_7WegUf|xlWbas^xbtQ=gA3$U5XbN_a}E{D{lFh>aJbge_X4&rC+o5ajuiDE+7Fjlg}>A4ebYt>0M)B W006G02?3L-FCYjo3MC~)Peuyo%9jlQ delta 325 zcmV-L0lNOsU(sK%m@R+9AQZ*l{S^0QEMbtS`BPUyADTcJV-VWCjXj8wR2VU+8SA&7 zCQY~Ei}%Mpo^y}@Mx=xSBMPJ-h-@HZ3{@4R@0U?R+VWmn1OVx)>MVQ!1q?^{oKdZ( z!2vHgZ)|HrkeU-|{a=5f7~tu7z|G?UIQ%?%v@is@Zv XU;qHFu?Yi{s4pN0F$yImMNdWw<#C#h diff --git a/src/benders_rrsp.jl b/src/benders_rrsp.jl index 423f722..9a1861c 100755 --- a/src/benders_rrsp.jl +++ b/src/benders_rrsp.jl @@ -123,10 +123,10 @@ function rrspcreatebenders_modellazy(filename, inst, pars; optimizer) function f(x, y) - sum(sum(c[i, j] * x[i, j] for j in V if i < j; init = 0) for i in V) + - sum(c[1, i] * x[i, n+1] for i ∈ 2:n) + - sum(sum(d[i, j] * y[i, j] for j in V if i != j) for i in V) + - sum(o[i] * y[i, i] for i in V) + sum(sum(c[i, j] * x[i, j] for j in V if i < j; init = 0) for i in V; init = 0) + + sum(c[1, i] * x[i, n+1] for i ∈ 2:n ; init = 0) + + sum(sum(d[i, j] * y[i, j] for j in V if i != j; init = 0) for i in V; init = 0) + + sum(o[i] * y[i, i] for i in V; init = 0) end bestsol, bestobjval = three(inst.n, inst.o, inst.c, inst.d, tildeV) diff --git a/src/instance.jl b/src/instance.jl index 292ad46..2eeabe0 100755 --- a/src/instance.jl +++ b/src/instance.jl @@ -127,8 +127,9 @@ function printinst(inst::RRSPInstance, pars) end function createinstance_rrsp(filename, α, pars) + random_filepath = - eval(@__DIR__) * "/instances/Instances_journal_article/RAND/$(filename[1]).dat" + eval(@__DIR__) * "/instances/Instances_journal_article/RAND/$(filename[2]).dat" if pars.nrand > 0 && !isfile(random_filepath) n = pars.nrand data = [1:1000 rand(1:1000, 1000) rand(1:1000, 1000)] @@ -211,7 +212,6 @@ function createinstance_rrsp(filename, α, pars) data = readdlm(filename[1]) n = filename[2] - V = 1:n tildeV = 2:Int(ceil(n * pars.tildeV / 100)) E = [(i, j) for i in V, j in V if i < j] @@ -350,10 +350,10 @@ end Return an RRSPInstance """ -function createinstance_rrsp(xycoordinates::Vector{Tuple{Int, Int}}, α, pars) - n = length(xycoordinates) +function createinstance_rrsp(instdataname::Tuple{Vector{Tuple{Int, Int}},Int}, α, pars) + n = length(instdataname[2]) - x_coors, y_coors = first.(xycoordinates), last.(xycoordinates) + x_coors, y_coors = first.(instdataname[1]), last.(instdataname[1]) V = 1:n tildeV = 2:Int(ceil(n * pars.tildeV / 100)) diff --git a/src/main.jl b/src/main.jl index 9933c3b..ddd7f0a 100755 --- a/src/main.jl +++ b/src/main.jl @@ -53,10 +53,10 @@ function rspoptimize( solutionchecker = false, ) - + instdataname = "xycoordinates_$(length(xycoordinates))", (xycoordinates, length(xycoordinates)) if pars.redirect_stdio - # redirect terminal outputs/stdio to file + # redirect terminal outputs/stdio txycoordinateso file now_file = Dates.format(Dates.now(), "yyyy-mm-dd_HHhMM") now_folder = Dates.format(Dates.now(), "yyyy-mm-dd") output_path = joinpath(@__DIR__, "debug", "stdio", "$now_folder") @@ -65,114 +65,11 @@ function rspoptimize( stdout = "$output_path/stdout_$(symbolinstance)_$now_file.txt", stderr = "$output_path/stderr_$(symbolinstance)_$now_file.txt", ) do - main(pars, xycoordinates, optimizer, solutionchecker) + main(pars, instdataname, optimizer, solutionchecker) GC.gc() end end - main(pars, xycoordinates, optimizer, solutionchecker) - GC.gc() - return 0 -end - - -function main(pars::SolverParameters, xycoordinates::Vector{Tuple{Int,Int}}, optimizer, solutionchecker = false) - - - - output_folder = joinpath(@__DIR__, "results", "solutions/") - extension = ".txt" - if pars.writeresults == HTML() - output_folder = joinpath(@__DIR__, "results", "html", "solutions", "experiments/") - extension = ".html" - end - - α = pars.alpha - for rand_inst_id ∈ pars.nb_runrand[1]:pars.nb_runrand[2] - benders_table = BDtable() - ilp_table = ILPtable() - α - nstr_random = pars.nrand > 0 ? "_" * "$(pars.nrand)" : "" - - - - - inst = createinstance_rrsp(xycoordinates, α, pars) - - instdataname = Symbol("xy_$(length(xycoordinates))") - - println("\nInstance: ", "$(length(xycoordinates))-nodes with coordinates instance") - pars.log_level > 0 && @info "α=$α" - - - printinst(inst, pars) - - if pars.solve_mod == gF() || - pars.solve_mod in [gFexploreonlyILP(), gFexploreonlyben()] - rrsp_plot_gF( - instdatame, - inst, - pars, - pars.F_interval[1], - pars.F_interval[2], - ) - end - - if pars.solve_mod == BranchBendersCut() - benders_table = round!( - rrspcreatebenders_modellazy(instdataname, inst, pars; optimizer), - ) - - end - - input_filepath = get_input_filepath( - output_folder, - instdataname, - extension, - inst, - pars, - nstr_random, - rand_inst_id, - ) - if pars.solve_mod == ILP() - - ilp_table = round!( - rrspcreate_ilplazy( - instdataname, - inst, - pars, - optimizer, - solutionchecker, - ), - ) - - - elseif pars.solve_mod == NoOptimize() - @show input_filepath - ilp_table = read_ilp_table(input_filepath, pars.plot_id) - end - - if pars.plotting && pars.writeresults != "" - if pars.solve_mod == ILP() - perform_plot(pars, inst, instdataname, ilp_table, true) - end - if pars.solve_mod == BranchBendersCut() - perform_plot(pars, inst, instdataname, benders_table, false) - end - end - if pars.writeresults != "" - write_solution_to_file( - input_filepath, - instdataname, - inst, - pars, - nstr_random, - rand_inst_id, - inst.n, - benders_table, - ilp_table, - ) - end - end + main(pars, instdataname, optimizer, solutionchecker) GC.gc() return 0 end @@ -198,13 +95,13 @@ function main(pars::SolverParameters, instdataname, optimizer, solutionchecker = nstr_random = pars.nrand > 0 ? "_" * "$(pars.nrand)" : "" if instdataname[1] == :RandomInstance - instdataname[2] = "$(instdataname[1])$(nstr_random)_o=$(replace(pars.o_i,":"=>"-"))_$(pars.r_ij)_s($(pars.s_ij))_ID$(rand_inst_id)" + instdataname[2][1] = "$(instdataname[1])$(nstr_random)_o=$(replace(pars.o_i,":"=>"-"))_$(pars.r_ij)_s($(pars.s_ij))_ID$(rand_inst_id)" if pars.r_ij == pars.s_ij - instdataname[2] = "$(instdataname[1])$(nstr_random)_o$(replace(pars.o_i,":"=>"-"))_rs=l_ij_ID$(rand_inst_id)" + instdataname[2][1] = "$(instdataname[1])$(nstr_random)_o$(replace(pars.o_i,":"=>"-"))_rs=l_ij_ID$(rand_inst_id)" end end - + inst = createinstance_rrsp(instdataname[2], α, pars) println("\nInstance: ", "$(instdataname[1])") diff --git a/test/runtests.jl b/test/runtests.jl index 84411b9..dc8c155 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -19,7 +19,7 @@ include("aqua.jl") solve_mod = BranchBendersCut(), # ILP, or BranchBendersCut F = 7, # total failing time F in days per year, see [`PhD manuscript`](https://theses.hal.science/tel-04319443) sp_solve = Poly(), - o_i = 0, # opening costs + o_i = 1, # opening costs s_ij = Euclidian(), # star costs r_ij = Euclidian(), # ring costs alpha = 3, # See [Labbé et al., 2004](ttps://doi.org/10.1002/net.10114) @@ -63,12 +63,14 @@ include("aqua.jl") optimizer_with_attributes(GLPK.Optimizer, "msg_lev" => 2), true, ) == 0 + @test rspoptimize( pars, :Instance_15_1_0_3_1, - optimizer_with_attributes(GLPK.Optimizer, "msg_lev" => 2), - true, + optimizer_with_attributes(GLPK.Optimizer, "msg_lev" => 2), + true, ) == 0 + @test rspoptimize( pars, :eil51, @@ -81,16 +83,16 @@ include("aqua.jl") @test rspoptimize( pars, - :TinyInstance_12_2, - optimizer_with_attributes(GLPK.Optimizer, "msg_lev" => 2), + :TinyInstance_12_2, + optimizer_with_attributes(GLPK.Optimizer, "msg_lev" => 2), true, ) == 0 pars.sp_solve = LP() pars.redirect_stdio = true @test rspoptimize( pars, - :eil51, - optimizer_with_attributes(GLPK.Optimizer, "msg_lev" => 2, "tm_lim" => 15_000), + :eil51, + optimizer_with_attributes(GLPK.Optimizer, "msg_lev" => 2, "tm_lim" => 15_000), true, ) == 0 @@ -103,6 +105,7 @@ include("aqua.jl") ) == 0 pars.tildeV = 0 + pars.o_i = 0 @test rspoptimize( pars, :TinyInstance_10_3, From a01ad48df0a187549f978cf7dbd62defdc91ace2 Mon Sep 17 00:00:00 2001 From: jkhamphousone Date: Fri, 2 Aug 2024 00:34:29 +0200 Subject: [PATCH 3/3] Improving code coverage on solve_mod=ILP() --- ...1-3.0_benders_Poly()__F=0.0_UB=903.0).pdf" | Bin 10388 -> 10388 bytes ...61-3.0_benders_LP()__F=0.0_UB=1278.0).pdf" | Bin 12240 -> 12240 bytes src/instance.jl | 138 ++++++++++-------- src/main.jl | 14 +- test/runtests.jl | 10 +- 5 files changed, 94 insertions(+), 68 deletions(-) diff --git "a/ext/results/TinyInstance_12_2____\316\261-3.0_benders_Poly()/TinyInstance_12_2____\316\261-3.0_benders_Poly()__F=0.0_UB=903.0).pdf" "b/ext/results/TinyInstance_12_2____\316\261-3.0_benders_Poly()/TinyInstance_12_2____\316\261-3.0_benders_Poly()__F=0.0_UB=903.0).pdf" index 860154b7134df0bec71459af1035a62bd292d826..70ab9f2dc9e82f3dc8f4753febf1f095c2c71c66 100644 GIT binary patch delta 299 zcmV+`0o4AKQIt`zRVIJIYQr!PMDPBJxs)ap?3FA#ZZJ6{flx{zB)yd$gd!Y6v5X{_ z=I<*xaZ1r?A3K^EmVpvhqM(F>6)a&3k+AK)My@HwK5 z89EP^tX899Z_Q~?+G3_;YYkY+s+2H0d*8cdmW{NrvOl-VrN)0Y^ZE4~tEF#Ex0POF zwq0`Kf-2%foC$g&{zx>RO#WiwAy`NKURoV<#AG9Q)2CLh%}E)McZe7DYZdJq5FRMLqrL%D-BLN|>j|%_* delta 299 zcmV+`0o4AKQIt`zRVIH?YlAQph2Q-Z_hqay(3==-R-_MAC}Rx7?rrQLq`?ZqND{~T z@0V!p7PT2?m(%1fM;R7fjwD38j zN>76W67Bc1qA~hBNo8OoMQ=2agzyAmb8&98yEL6?XT*5vrA>dd>Ed|##wg)>J=DS} z*wj0Ulp#loh@2HqNFNd7)#NW0Jb3G%Z-h}HM@Tk0*HuIS{c5rZ9rv%IeO1)Q1GI#qtFR^Po;?eP$x xZxDE^te%Wi7P20@=gAADTZ&kJlYeC^;l!8jZe9I7ZdLu#FSn0zu(NR|BLVy0l~4cx diff --git "a/ext/results/eil51________________\316\261-3.0_benders_LP()/eil51________________\316\261-3.0_benders_LP()__F=0.0_UB=1278.0).pdf" "b/ext/results/eil51________________\316\261-3.0_benders_LP()/eil51________________\316\261-3.0_benders_LP()__F=0.0_UB=1278.0).pdf" index 6ae6d6b261a1bcf412994f82039ff5c44ea26c96..bbbf95615c7bf6c435a193d055060fada42b1d9c 100644 GIT binary patch delta 294 zcmV+>0onf0U(jE$mMwqHYJ@Nph4*=iyD3!)dJ}&}2ARbu45bvr>8^AUVsM0FB#EW- z_Dyu0wq%q0aZk=UgaQ(pLxzL_%_yNeNQ#1#CB$#nNkZK4UK#=b@ypN|cn1auEqpAf zQuAnmlEYz9G+K4DkQxHP2d#icw1^Obi?x&4$MHgY&8N#COr(EwABO8QT5>z6vF27n zQ12PC6bodCjAq3XvPZ;lGx?1L56;@_8?L3#;gc=kRdxeEs&5w;-C;!%rFoj=yT8}1 z!f2h?Kzdi7w3;Ut6n#nth>xQ4f>RE16<+f`1H3-?Bjvl%Op10Dd sSqo_(xqF_SP}mu@h;e`NuWZFF|5W|0tNV{zRk!p5xrcGHv#l;80s3>05&!@I delta 294 zcmV+>0onf0U(jE$mMwo@YlAQp#ozNO?#q}m(3|+Du1FuMP{tTYySK525Q7zlktB}w z+b_}Dt>h*5$2~dc5DG|W4jB>#G^2!WASnt`mJq*RMhS7lJ81|2#IJp8-~$*S9N}|D zm6`?%l ceil_labbe( - distance([x_coors[e[1]], y_coors[e[1]]], [x_coors[e[2]], y_coors[e[2]]]), - ) for e in E - ) - - - d = Dict( - (a[1], a[2]) => - a[1] == a[2] ? 0 : round(1 / rand(Uniform(n / 2, 3n / 2)), digits = 5) - for a in A - ) - if pars.s_ij isa Euclidian - d = Dict( - (a[1], a[2]) => ceil_labbe( - distance( - [x_coors[a[1]], y_coors[a[1]]], - [x_coors[a[2]], y_coors[a[2]]], - ), - ) for a in A - ) - end - for i ∈ 2:n - c[i, n+1] = c[1, i] - end - c[1, n+1] = 0 + xs = data[1:n, 2] + ys = data[1:n, 3] + c, d = createweights(xs, ys, A, pars.r_ij, pars.s_ij) o = zeros(Float64, n) if pars.o_i == RandomInterval @@ -183,7 +157,7 @@ function createinstance_rrsp(filename, α, pars) open(random_filepath, "w") do f println(f, "$n 0.0 $α") for i ∈ 1:n - println(f, "$i $(x_coors[i]) $(y_coors[i])") + println(f, "$i $(xs[i]) $(ys[i])") end println(f, "opening costs") for i ∈ 1:n @@ -206,7 +180,7 @@ function createinstance_rrsp(filename, α, pars) for kv in d d′[kv[1]] = d[kv[1]] * pars.backup_factor end - return RRSPInstance(n, V, tildeV, pars.F, o, α, c, c′, d, d′, x_coors, y_coors) + return RRSPInstance(n, V, tildeV, pars.F, o, α, c, c′, d, d′, xs, ys) elseif pars.nrand == 0 @@ -270,13 +244,13 @@ function createinstance_rrsp(filename, α, pars) shift_n = 414 - 7 end - x_coors, y_coors = readcoordinates(data) + xs, ys = readcoordinates(data) c = Dict( (e[1], e[2]) => ceil_labbe( distance( - [x_coors[e[1]], y_coors[e[1]]], - [x_coors[e[2]], y_coors[e[2]]], + [xs[e[1]], ys[e[1]]], + [xs[e[2]], ys[e[2]]], ) * (α), ) for e in E ) @@ -291,8 +265,8 @@ function createinstance_rrsp(filename, α, pars) d = Dict( (a[1], a[2]) => ceil_labbe( distance( - [x_coors[a[1]], y_coors[a[1]]], - [x_coors[a[2]], y_coors[a[2]]], + [xs[a[1]], ys[a[1]]], + [xs[a[2]], ys[a[2]]], ) * (10 - α), ) for a in A ) @@ -305,7 +279,7 @@ function createinstance_rrsp(filename, α, pars) for kv in d d′[kv[1]] = d[kv[1]] * pars.backup_factor end - return RRSPInstance(n, V, tildeV, pars.F, o, α, c, c′, d, d′, x_coors, y_coors) + return RRSPInstance(n, V, tildeV, pars.F, o, α, c, c′, d, d′, xs, ys) end else @@ -316,19 +290,11 @@ function createinstance_rrsp(filename, α, pars) E = [(i, j) for i in V, j in V if i < j] A = [(i, j) for i in V, j in V] Ac = [(i, j) for i in V, j in V if i != j] - x_coors, y_coors = readcoordinates(data) + xs, ys = readcoordinates(data) o = data[n+3, 1:n] - @assert pars.r_ij isa Euclidian - c = Dict( - (e[1], e[2]) => ceil_labbe( - distance([x_coors[e[1]], y_coors[e[1]]], [x_coors[e[2]], y_coors[e[2]]]), - ) for e in E - ) - for i ∈ 2:n - c[i, n+1] = c[1, i] - end - c[1, n+1] = 0 + c, d = createweights(xs, ys, A, pars.r_ij, pars.s_ij) + d_data = data[n+5:2n+4, 1:n] d = Dict((a[1], a[2]) => d_data[a[1], a[2]] for a in A) c′ = Dict{Tuple{Int,Int},Float64}() @@ -340,7 +306,7 @@ function createinstance_rrsp(filename, α, pars) d′[kv[1]] = d[kv[1]] * pars.backup_factor end - return RRSPInstance(n, V, tildeV, pars.F, o, α, c, c′, d, d′, x_coors, y_coors) + return RRSPInstance(n, V, tildeV, pars.F, o, α, c, c′, d, d′, xs, ys) end end @@ -353,7 +319,7 @@ end function createinstance_rrsp(instdataname::Tuple{Vector{Tuple{Int, Int}},Int}, α, pars) n = length(instdataname[2]) - x_coors, y_coors = first.(instdataname[1]), last.(instdataname[1]) + xs, ys = first.(instdataname[1]), last.(instdataname[1]) V = 1:n tildeV = 2:Int(ceil(n * pars.tildeV / 100)) @@ -371,8 +337,8 @@ function createinstance_rrsp(instdataname::Tuple{Vector{Tuple{Int, Int}},Int}, c = Dict( (e[1], e[2]) => ceil_labbe( distance( - [x_coors[e[1]], y_coors[e[1]]], - [x_coors[e[2]], y_coors[e[2]]], + [xs[e[1]], ys[e[1]]], + [xs[e[2]], ys[e[2]]], ) * (α), ) for e in E ) @@ -387,8 +353,8 @@ function createinstance_rrsp(instdataname::Tuple{Vector{Tuple{Int, Int}},Int}, d = Dict( (a[1], a[2]) => ceil_labbe( distance( - [x_coors[a[1]], y_coors[a[1]]], - [x_coors[a[2]], y_coors[a[2]]], + [xs[a[1]], ys[a[1]]], + [xs[a[2]], ys[a[2]]], ) * (10 - α), ) for a in A ) @@ -401,7 +367,7 @@ function createinstance_rrsp(instdataname::Tuple{Vector{Tuple{Int, Int}},Int}, for kv in d d′[kv[1]] = d[kv[1]] * pars.backup_factor end - return RRSPInstance(n, V, tildeV, pars.F, o, α, c, c′, d, d′, x_coors, y_coors) + return RRSPInstance(n, V, tildeV, pars.F, o, α, c, c′, d, d′, xs, ys) end @@ -418,30 +384,74 @@ end function readcoordinates(data) n_start = 2 - x_coors = Float64[] - y_coors = Float64[] - while length(x_coors) == 0 + xs = Float64[] + ys = Float64[] + while length(xs) == 0 try if data[end, 2] == "" - x_coors = Float64.(data[n_start:end-1, 2]) + xs = Float64.(data[n_start:end-1, 2]) else - x_coors = Float64.(data[n_start:end, 2]) + xs = Float64.(data[n_start:end, 2]) end catch n_start += 1 end end n_start = 2 - while length(y_coors) == 0 + while length(ys) == 0 try if data[end, 2] == "" - y_coors = Float64.(data[n_start:end-1, 3]) + ys = Float64.(data[n_start:end-1, 3]) else - y_coors = Float64.(data[n_start:end, 3]) + ys = Float64.(data[n_start:end, 3]) end catch n_start += 1 end end - return x_coors, y_coors + return xs, ys end + + +function createweights(xs, ys, A, r_ij, s_ij) + if r_ij isa RandomInterval + c = Dict( + (a[1], a[2]) => + a[1] == a[2] ? 0 : rand(pars.r_ij[1]:pars.r_ij[2]) + for a in A + ) + end + if r_ij isa Euclidian + c = Dict( + (e[1], e[2]) => ceil_labbe( + distance([xs[e[1]], ys[e[1]]], [xs[e[2]], ys[e[2]]]), + ) for e in E + ) + end + + if s_ij isa RandomInterval + d = Dict( + (a[1], a[2]) => + a[1] == a[2] ? 0 : rand(pars.r_ij[1]:pars.r_ij[2]) + for a in A + ) + end + if s_ij isa Euclidian + d = Dict( + (a[1], a[2]) => ceil_labbe( + distance( + [xs[a[1]], ys[a[1]]], + [xs[a[2]], ys[a[2]]], + ), + ) for a in A + ) + end + + for i ∈ 2:n + c[i, n+1] = c[1, i] + end + c[1, n+1] = 0 + + + return c, d +end \ No newline at end of file diff --git a/src/main.jl b/src/main.jl index ddd7f0a..aa3534b 100755 --- a/src/main.jl +++ b/src/main.jl @@ -155,12 +155,20 @@ function main(pars::SolverParameters, instdataname, optimizer, solutionchecker = ilp_table = read_ilp_table(input_filepath, pars.plot_id) end - if pars.plotting && pars.writeresults != "" + if pars.plotting && pars.writeresults if pars.solve_mod == ILP() - perform_plot(pars, inst, instdataname[1], ilp_table, true) + if ilp_table.sol.n != 0 + perform_plot(pars, inst, instdataname[1], ilp_table, true) + else + @info "No feasible solution has been found by ILP within the solving time, can not perform plotting" + end end if pars.solve_mod == BranchBendersCut() - perform_plot(pars, inst, instdataname[1], benders_table, false) + if benders_table.sol.n != 0 + perform_plot(pars, inst, instdataname[1], benders_table, false) + else + @info "No feasible solution has been found by B&BC within the solving time, can not perform plotting" + end end end if pars.writeresults != "" diff --git a/test/runtests.jl b/test/runtests.jl index dc8c155..da9f1d2 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -16,7 +16,7 @@ include("aqua.jl") pars = SolverParameters( - solve_mod = BranchBendersCut(), # ILP, or BranchBendersCut + solve_mod = BranchBendersCut(), # ILP(), or BranchBendersCut() F = 7, # total failing time F in days per year, see [`PhD manuscript`](https://theses.hal.science/tel-04319443) sp_solve = Poly(), o_i = 1, # opening costs @@ -112,4 +112,12 @@ include("aqua.jl") optimizer_with_attributes(GLPK.Optimizer, "msg_lev" => 2, "tm_lim" => 1_000), true, ) == 0 + + pars.solve_mod = ILP() + @test rspoptimize( + pars, + :TinyInstance_10_3, + optimizer_with_attributes(GLPK.Optimizer, "msg_lev" => 2, "tm_lim" => 1_000), + true, + ) == 0 end