Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Put back StaticVarConstrUnit and improving PresolveAlgorithm interface #1060

Merged
merged 3 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Algorithm/Algorithm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ export getterminationstatus, setterminationstatus!,

# Algorithms
export TreeSearchAlgorithm, ColCutGenConquer, ColumnGeneration, BendersConquer, BendersCutGeneration, SolveIpForm, RestrictedMasterIPHeuristic,
SolveLpForm, NoBranching, Branching, StrongBranching,
FirstFoundCriterion, MostFractionalCriterion, SingleVarBranchingRule
SolveLpForm, NoBranching, Branching, StrongBranching, PresolveAlgorithm, PresolveOutput,
FirstFoundCriterion, MostFractionalCriterion, LeastFractionalCriterion, ClosestToNonZeroIntegerCriterion, SingleVarBranchingRule

# Algorithm's types
export AbstractOptimizationAlgorithm,
Expand Down
155 changes: 79 additions & 76 deletions src/Algorithm/formstorages.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ end
function apply_state!(form::Formulation, var::Variable, var_state::VarState)
if isfixed(form, var)
println("var $(getname(form, var)) is fixed -- ", isfixed(form, var))
unfix!(form, var)
unfix!(form, var, false)
end
if getcurlb(form, var) != var_state.lb
setcurlb!(form, var, var_state.lb)
Expand All @@ -26,7 +26,7 @@ function apply_state!(form::Formulation, var::Variable, var_state::VarState)
end
if var_state.fixed
@assert var_state.lb == var_state.ub
fix!(form, var, var_state.lb)
fix!(form, var, var_state.lb, false)
end
return
end
Expand Down Expand Up @@ -132,8 +132,7 @@ ClB.storage_unit(::Type{MasterColumnsUnit}, _) = MasterColumnsUnit()
function ClB.record(::Type{MasterColumnsRecord}, id::Int, form::Formulation, unit::MasterColumnsUnit)
record = MasterColumnsRecord(Dict{VarId,ConstrState}())
for (id, var) in getvars(form)
if getduty(id) <= MasterCol &&
((iscuractive(form, var) && isexplicit(form, var) || isfixed(form, var)))
if getduty(id) <= MasterCol && isexplicit(form, var) && iscuractive(form, var) || isfixed(form, var)
varstate = VarState(
getcurcost(form, var),
getcurlb(form, var),
Expand Down Expand Up @@ -231,27 +230,30 @@ function ClB.restore_from_record!(
end
end

"""
StaticVarConstrUnit

Unit for static variables and constraints of a formulation.
Can be restored using a StaticVarConstrRecord.
"""

##### UNCOVERED CODE BELOW #####
struct StaticVarConstrUnit <: AbstractRecordUnit end

# """
# StaticVarConstrUnit
StaticVarConstrUnit(::Formulation) = StaticVarConstrUnit()

# Unit for static variables and constraints of a formulation.
# Can be restored using a StaticVarConstrRecord.
# """
mutable struct StaticVarConstrRecord <: AbstractRecord
constrs::Dict{ConstrId,ConstrState}
vars::Dict{VarId,VarState}
end

# struct StaticVarConstrUnit <: AbstractStorageUnit end
# TO DO: we need to keep here only the difference with the initial data

# StaticVarConstrUnit(::Formulation) = StaticVarConstrUnit()
struct StaticVarConstrKey <: AbstractStorageUnitKey end

# mutable struct StaticVarConstrRecord <: AbstractRecord
# constrs::Dict{ConstrId,ConstrState}
# vars::Dict{VarId,VarState}
# end
key_from_storage_unit_type(::Type{StaticVarConstrUnit}) = StaticVarConstrKey()
record_type_from_key(::StaticVarConstrKey) = StaticVarConstrRecord

# # TO DO: we need to keep here only the difference with the initial data
ClB.storage_unit(::Type{StaticVarConstrUnit}, _) = StaticVarConstrUnit()

# function Base.show(io::IO, record::StaticVarConstrRecord)
# print(io, "[vars:")
Expand All @@ -265,64 +267,65 @@ end
# print(io, "]")
# end

# function StaticVarConstrRecord(form::Formulation, unit::StaticVarConstrUnit)
# @logmsg LogLevel(-2) string("Storing static vars and consts")
# record = StaticVarConstrRecord(Dict{ConstrId,ConstrState}(), Dict{VarId,VarState}())
# for (id, constr) in getconstrs(form)
# if isaStaticDuty(getduty(id)) && iscuractive(form, constr) && isexplicit(form, constr)
# constrstate = ConstrState(getcurrhs(form, constr))
# record.constrs[id] = constrstate
# end
# end
# for (id, var) in getvars(form)
# if isaStaticDuty(getduty(id)) && iscuractive(form, var) && isexplicit(form, var)
# varstate = VarState(getcurcost(form, var), getcurlb(form, var), getcurub(form, var))
# record.vars[id] = varstate
# end
# end
# return record
# end
function ClB.record(::Type{StaticVarConstrRecord}, id::Int, form::Formulation, unit::StaticVarConstrUnit)
@logmsg LogLevel(-2) string("Storing static vars and consts")
record = StaticVarConstrRecord(Dict{ConstrId,ConstrState}(), Dict{VarId,VarState}())
for (id, constr) in getconstrs(form)
if isaStaticDuty(getduty(id)) && iscuractive(form, constr) && isexplicit(form, constr)
constrstate = ConstrState(getcurrhs(form, constr))
record.constrs[id] = constrstate
end
end
for (id, var) in getvars(form)
if isaStaticDuty(getduty(id)) && isexplicit(form, var) && iscuractive(form, var) || isfixed(form, var)
varstate = VarState(getcurcost(form, var), getcurlb(form, var), getcurub(form, var), isfixed(form, var))
record.vars[id] = varstate
end
end
return record
end

# function ColunaBase.restore_from_record!(
# form::Formulation, unit::StaticVarConstrUnit, record::StaticVarConstrRecord
# )
# @logmsg LogLevel(-2) "Restoring static vars and consts"
# for (id, constr) in getconstrs(form)
# if isaStaticDuty(getduty(id)) && isexplicit(form, constr)
# @logmsg LogLevel(-4) "Checking " getname(form, constr)
# if haskey(record.constrs, id)
# if !iscuractive(form, constr)
# @logmsg LogLevel(-2) string("Activating constraint", getname(form, constr))
# activate!(form, constr)
# end
# @logmsg LogLevel(-4) "Updating data"
# apply_data!(form, constr, record.constrs[id])
# else
# if iscuractive(form, constr)
# @logmsg LogLevel(-2) string("Deactivating constraint", getname(form, constr))
# deactivate!(form, constr)
# end
# end
# end
# end
# for (id, var) in getvars(form)
# if isaStaticDuty(getduty(id)) && isexplicit(form, var)
# @logmsg LogLevel(-4) "Checking " getname(form, var)
# if haskey(record.vars, id)
# if !iscuractive(form, var)
# @logmsg LogLevel(-4) string("Activating variable", getname(form, var))
# activate!(form, var)
# end
# @logmsg LogLevel(-4) "Updating data"
# apply_data!(form, var, record.vars[id])
# else
# if iscuractive(form, var)
# @logmsg LogLevel(-4) string("Deactivating variable", getname(form, var))
# deactivate!(form, var)
# end
# end
# end
# end
# end
ClB.record_type(::Type{StaticVarConstrUnit}) = StaticVarConstrRecord
ClB.storage_unit_type(::Type{StaticVarConstrRecord}) = StaticVarConstrUnit

# ColunaBase.record_type(::Type{StaticVarConstrUnit}) = StaticVarConstrRecord
function ClB.restore_from_record!(
form::Formulation, ::StaticVarConstrUnit, record::StaticVarConstrRecord
)
@logmsg LogLevel(-2) "Restoring static vars and consts"
for (id, constr) in getconstrs(form)
if isaStaticDuty(getduty(id)) && isexplicit(form, constr)
@logmsg LogLevel(-4) "Checking " getname(form, constr)
if haskey(record.constrs, id)
if !iscuractive(form, constr)
@logmsg LogLevel(-2) string("Activating constraint", getname(form, constr))
activate!(form, constr)
end
@logmsg LogLevel(-4) "Updating data"
apply_state!(form, constr, record.constrs[id])
else
if iscuractive(form, constr)
@logmsg LogLevel(-2) string("Deactivating constraint", getname(form, constr))
deactivate!(form, constr)
end
end
end
end
for (id, var) in getvars(form)
if isaStaticDuty(getduty(id)) && isexplicit(form, var)
@logmsg LogLevel(-4) "Checking " getname(form, var)
if haskey(record.vars, id)
if !iscuractive(form, var) && !isfixed(form, var)
@logmsg LogLevel(-4) string("Activating variable", getname(form, var))
activate!(form, var)
end
@logmsg LogLevel(-4) "Updating data"
apply_state!(form, var, record.vars[id])
else
if iscuractive(form, var)
@logmsg LogLevel(-4) string("Deactivating variable", getname(form, var))
deactivate!(form, var)
end
end
end
end
end
26 changes: 23 additions & 3 deletions src/Algorithm/presolve/interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -227,12 +227,32 @@ Presolve algorithm
"""
struct PresolveAlgorithm <: AlgoAPI.AbstractAlgorithm
ϵ::Float64
PresolveAlgorithm(;ϵ = 1e-6) = new(ϵ)
update_sp_var_bounds::Bool
PresolveAlgorithm(;ϵ = 1e-6, update_sp_var_bounds = false) = new(ϵ, update_sp_var_bounds)
end

function run!(algo::PresolveAlgorithm, ::Env, reform::Reformulation, _)
# PresolveAlgorithm does not have child algorithms, therefore get_child_algorithms() is not defined

function get_units_usage(algo::PresolveAlgorithm, reform::Reformulation)
units_usage = Tuple{AbstractModel, UnitType, UnitPermission}[]
master = getmaster(reform)
push!(units_usage, (master, StaticVarConstrUnit, READ_AND_WRITE))
push!(units_usage, (master, MasterBranchConstrsUnit, READ_AND_WRITE))
push!(units_usage, (master, MasterCutsUnit, READ_AND_WRITE))
push!(units_usage, (master, MasterColumnsUnit, READ_ONLY))
for (_, dw_sp) in get_dw_pricing_sps(reform)
push!(units_usage, (dw_sp, StaticVarConstrUnit, READ_AND_WRITE))
end
return units_usage
end

struct PresolveOutput
feasible::Bool
end

function run!(algo::PresolveAlgorithm, ::Env, reform::Reformulation, _)::PresolveOutput
treat!(algo, reform)
return
return PresolveOutput(true)
end

function treat!(algo::PresolveAlgorithm, reform::Reformulation{DwMaster})
Expand Down
2 changes: 1 addition & 1 deletion src/MathProg/duties.jl
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ function isaStaticDuty(duty::NestedEnum)
duty <= DwSpSetupVar ||
#duty <= DwSpPureVar ||
duty <= DwSpPrimalSol ||
duty <= DwSpDualSol ||
#duty <= DwSpDualSol ||
duty <= BendSpSepVar ||
#duty <= BendSpPureVar ||
duty <= BendSpSlackFirstStageVar ||
Expand Down
100 changes: 100 additions & 0 deletions test/unit/Algorithm/record_staticvarconstr.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
function unit_static_var_constr_record()
function test_var_record(state, cost, lb, ub, fixed)
@test state.cost == cost
@test state.lb == lb
@test state.ub == ub
@test state.fixed == fixed
end

function test_var(form, var, cost, lb, ub, fixed)
@test ClMP.getcurcost(form, var) == cost
@test ClMP.getcurlb(form, var) == lb
@test ClMP.getcurub(form, var) == ub
@test ClMP.isfixed(form, var) == fixed
end

function test_constr_record(state, rhs)
@test state.rhs == rhs
end

function test_constr(form, constr, rhs)
@test ClMP.getcurrhs(form, constr) == rhs
end

env = CL.Env{ClMP.VarId}(CL.Params())

# Create the following formulation:
# min 1*v1 + 2*v2 + 4*v3
# c1: 2*v1 + v3 >= 4
# c2: v1 + 2*v2 >= 5
# c3: v1 + v2 + v3 >= 3
# 0 <= v1 <= 10
# 0 <= v2 <= 20
# 0 <= v3 <= 30

form = ClMP.create_formulation!(env, ClMP.DwMaster())
vars = Dict{String,ClMP.Variable}()
constrs = Dict{String,ClMP.Constraint}()

rhs = [4,5,3]
for i in 1:3
c = ClMP.setconstr!(form, "c$i", ClMP.OriginalConstr; rhs = rhs[i], sense = ClMP.Less)
constrs["c$i"] = c
end

members = [
Dict(ClMP.getid(constrs["c1"]) => 2.0, ClMP.getid(constrs["c2"]) => 1.0, ClMP.getid(constrs["c3"]) => 1.0),
Dict(ClMP.getid(constrs["c2"]) => 2.0, ClMP.getid(constrs["c3"]) => 1.0),
Dict(ClMP.getid(constrs["c1"]) => 1.0, ClMP.getid(constrs["c3"]) => 1.0),
]
costs = [1,2,4]
ubounds = [10,20,30]
for i in 1:3
v = ClMP.setvar!(form, "v$i", ClMP.OriginalVar; cost = costs[i], members = members[i], lb = 0, ub = ubounds[i])
vars["v$i"] = v
end
DynamicSparseArrays.closefillmode!(ClMP.getcoefmatrix(form))

storage = ClB.getstorage(form)
r1 = ClB.create_record(storage, ClA.StaticVarConstrUnit)

@test isempty(setdiff(keys(r1.vars), ClMP.getid.(values(vars))))
@test isempty(setdiff(keys(r1.constrs), ClMP.getid.(values(constrs))))
test_var_record(r1.vars[ClMP.getid(vars["v1"])], 1, 0, 10, false)
test_var_record(r1.vars[ClMP.getid(vars["v2"])], 2, 0, 20, false)
test_var_record(r1.vars[ClMP.getid(vars["v3"])], 4, 0, 30, false)
test_constr_record(r1.constrs[ClMP.getid(constrs["c1"])], 4)
test_constr_record(r1.constrs[ClMP.getid(constrs["c2"])], 5)
test_constr_record(r1.constrs[ClMP.getid(constrs["c3"])], 3)

# make changes on the formulation
ClMP.setcurlb!(form, vars["v1"], 5.0)
ClMP.setcurub!(form, vars["v2"], 12.0)
ClMP.setcurcost!(form, vars["v3"], 4.6)
ClMP.fix!(form, vars["v3"], 3.5)
ClMP.setcurrhs!(form, constrs["c1"], 1.0)

guimarqu marked this conversation as resolved.
Show resolved Hide resolved
r2 = ClB.create_record(storage, ClA.StaticVarConstrUnit)

@test isempty(setdiff(keys(r2.vars), ClMP.getid.(values(vars))))
@test isempty(setdiff(keys(r2.constrs), ClMP.getid.(values(constrs))))
test_var_record(r2.vars[ClMP.getid(vars["v1"])], 1, 5, 10, false)
test_var_record(r2.vars[ClMP.getid(vars["v2"])], 2, 0, 12, false)
test_var_record(r2.vars[ClMP.getid(vars["v3"])], 4.6, 3.5, 3.5, true)
test_constr_record(r2.constrs[ClMP.getid(constrs["c1"])], 1)

ClB.restore_from_record!(storage, r1)

test_var(form, vars["v1"], 1, 0, 10, false)
test_var(form, vars["v2"], 2, 0, 20, false)
test_var(form, vars["v3"], 4, 0, 30, false)
test_constr(form, constrs["c1"], 4)

ClB.restore_from_record!(storage, r2)

test_var(form, vars["v1"], 1, 5, 10, false)
test_var(form, vars["v2"], 2, 0, 12, false)
test_var(form, vars["v3"], 4.6, 3.5, 3.5, true)
test_constr(form, constrs["c1"], 1)
end
register!(unit_tests, "master_columns_record", unit_static_var_constr_record)
Loading