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

Algo interface in ColunaBase #306

Merged
merged 4 commits into from
Mar 23, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
13 changes: 6 additions & 7 deletions src/Algorithm/Algorithm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,11 @@ import MathOptInterface
import TimerOutputs

using ..Coluna
using ..Containers
using ..ColunaBase
using ..MathProg

# TO be deleted ???
import .MathProg: FeasibilityStatus, TerminationStatus, AbstractStorage, EmptyStorage, getstorage, setprimalbound!, setdualbound!
import .MathProg: OPTIMAL, TIME_LIMIT, NODE_LIMIT, OTHER_LIMIT, EMPTY_RESULT, NOT_YET_DETERMINED
import ..Coluna: AbstractSense

import .MathProg: getvalue
import .MathProg: AbstractStorage, EmptyStorage, getstorage, getvalue

using Logging
using Printf
Expand All @@ -31,11 +27,14 @@ import .MathProg: getfeasibilitystatus, getterminationstatus, setfeasibilitystat
update_lp_primal_bound!, update_lp_dual_bound!, set_ip_primal_bound!,
set_ip_dual_bound!, set_lp_primal_bound!, set_lp_dual_bound!, ip_gap

# Import to define run! method of algorithms
import .ColunaBase: run!

# Utilities to build algorithms
include("utilities/optimizationstate.jl")
include("utilities/record.jl")

# Abstract algorithm (interface should be moved in Containers)
# Abstract algorithm
include("interface.jl")

# Here include slave algorithms used by conquer algorithms
Expand Down
49 changes: 1 addition & 48 deletions src/Algorithm/interface.jl
Original file line number Diff line number Diff line change
@@ -1,35 +1,6 @@
"""
AbstractInput

Input of an algorithm.
"""
abstract type AbstractInput end

struct EmptyInput <: AbstractInput end

"""
AbstractOutput

Output of an algorithm.
"""
abstract type AbstractOutput end

struct EmptyOutput <: AbstractOutput end #Usefull ?


"""
AbstractAlgorithm

An algorithm is a procedure with a known interface (input and output) applied to a formulation.
An algorithm can use an additional storage to keep its computed data.
Input of an algorithm is put to its storage before running it.
The algorithm itself contains only its parameters.
Other data used by the algorithm is contained in its storage.
The same storage can be used by different algorithms
or different copies of the same algorithm (same algorithm with different parameters).
"""
abstract type AbstractAlgorithm end

"""
getstoragetype(AlgorithmType)::StorageType

Expand All @@ -47,16 +18,6 @@ getslavealgorithms!(
algo::AbstractAlgorithm, form::AbstractFormulation,
slaves::Vector{Tuple{AbstractFormulation, Type{<:AbstractAlgorithm}}}) = nothing

"""
run!(Algorithm, Formulation)::Output

Runs the algorithm. The storage of the algorithm can be obtained by asking
the formulation. Returns algorithm's output.
"""
function run!(algo::AbstractAlgorithm, form::AbstractFormulation, input::AbstractInput)::AbstractOutput
error("run! not defined for algorithm $(typeof(algo)), input $(typeof(input)).")
end

run!(algo::AbstractAlgorithm, form::AbstractFormulation, input::EmptyInput) = run!(algo, form) # good idea ?

"""
Expand Down Expand Up @@ -92,12 +53,4 @@ getresult(output::OptimizationOutput)::OptimizationState = output.result
The input of such algorithm should be of type Incumbents.
The output of such algorithm should be of type OptimizationState.
"""
abstract type AbstractOptimizationAlgorithm <: AbstractAlgorithm end

function run!(
algo::AbstractOptimizationAlgorithm, form::AbstractFormulation, input::NewOptimizationInput
)::OptimizationOutput
algotype = typeof(algo)
error("Method run! which takes formulation and Incumbents as input returns OldOutput
is not implemented for algorithm $algotype.")
end
abstract type AbstractOptimizationAlgorithm <: AbstractAlgorithm end
4 changes: 2 additions & 2 deletions src/Algorithm/utilities/optimizationstate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ end
_sort!(sols::Vector{PrimalSolution{F}}, f::Function) where {F} = sort!(sols, by = x -> f(PrimalBound(x.model, x.value)))
_sort!(sols::Vector{DualSolution{F}}, f::Function) where {F} = sort!(sols, by = x -> f(DualBound(x.model, x.value)))

function bestbound(solutions::Vector{Sol}, max_len::Int, new_sol::Sol) where {Sol<:Coluna.Containers.Solution}
function bestbound(solutions::Vector{Sol}, max_len::Int, new_sol::Sol) where {Sol<:Solution}
if length(solutions) < max_len
push!(solutions, new_sol)
else
Expand All @@ -26,7 +26,7 @@ function bestbound(solutions::Vector{Sol}, max_len::Int, new_sol::Sol) where {So
return
end

function pushfirst(solutions::Vector{Sol}, max_len::Int, new_sol::Sol) where {Sol<:Coluna.Containers.Solution}
function pushfirst(solutions::Vector{Sol}, max_len::Int, new_sol::Sol) where {Sol<:Solution}
pushfirst!(solutions, new_sol)
if length(solutions) > max_len
pop!(solutions)
Expand Down
8 changes: 3 additions & 5 deletions src/Coluna.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ global const MOIU = MathOptInterface.Utilities
global const TO = TimerOutputs

# submodules
export Containers, MathProg, Algorithm
export ColunaBase, MathProg, Algorithm

# parameters
export Parameters, DefaultOptimizer
Expand All @@ -29,16 +29,14 @@ include("interface.jl")
include("parameters.jl")
global const _params_ = Params()

include("Containers/Containers.jl")
using .Containers
include("ColunaBase/ColunaBase.jl")
using .ColunaBase

include("MathProg/MathProg.jl")
using .MathProg
const MP = MathProg

include("Algorithm/Algorithm.jl")
using .Algorithm
const AL = Algorithm

include("optimize.jl")

Expand Down
11 changes: 5 additions & 6 deletions src/Containers/Containers.jl → src/ColunaBase/ColunaBase.jl
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
module Containers
module ColunaBase

using DynamicSparseArrays

import ..Coluna

import Base
import Primes
import Printf

# interface.jl
export AbstractModel, AbstractProblem
export AbstractModel, AbstractProblem, AbstractSense, AbstractMinSense, AbstractMaxSense,
AbstractSpace, AbstractPrimalSpace, AbstractDualSpace, AbstractAlgorithm, AbstractInput,
AbstractOutput, run!

# nestedenum.jl
export NestedEnum, @nestedenum, @exported_nestedenum

# solsandbounds.jl
export Bound, Solution,
getvalue, isbetter, diff, gap, printbounds, getbound, getsol, setvalue!
export Bound, Solution, getvalue, isbetter, diff, gap, printbounds, getsol

# members.jl
export MembersMatrix
Expand Down
47 changes: 47 additions & 0 deletions src/ColunaBase/interface.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
abstract type AbstractModel end
abstract type AbstractProblem end

abstract type AbstractSense end
abstract type AbstractMinSense <: AbstractSense end
abstract type AbstractMaxSense <: AbstractSense end

abstract type AbstractSpace end
abstract type AbstractPrimalSpace <: AbstractSpace end
abstract type AbstractDualSpace <: AbstractSpace end

"""
AbstractInput

Input of an algorithm.
"""
abstract type AbstractInput end

"""
AbstractOutput

Output of an algorithm.
"""
abstract type AbstractOutput end

"""
AbstractAlgorithm

An algorithm is a procedure with a known interface (input and output) applied to a formulation.
An algorithm can use an additional storage to keep its computed data.
Input of an algorithm is put to its storage before running it.
The algorithm itself contains only its parameters.
Other data used by the algorithm is contained in its storage.
The same storage can be used by different algorithms
or different copies of the same algorithm (same algorithm with different parameters).
"""
abstract type AbstractAlgorithm end

"""
run!(algo::AbstractAlgorithm, model::AbstractModel, input::AbstractInput)::AbstractOutput

Runs the algorithm. The storage of the algorithm can be obtained by asking
the formulation. Returns algorithm's output.
"""
function run!(algo::AbstractAlgorithm, model::AbstractModel, input::AbstractInput)::AbstractOutput
error("run! not defined for algorithm $(typeof(algo)), model $(typeof(model)), and input $(typeof(input)).")
end
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ function _build_expression(names, values, export_symb::Bool = false)
# If the root name is a curly expression, the user must have defined the
# template type inheriting from NestedEnum in its code.
if root_name isa Symbol
push!(enum_expr.args, :(struct $root_name <: Coluna.Containers.NestedEnum value::UInt end))
push!(enum_expr.args, :(struct $root_name <: Coluna.ColunaBase.NestedEnum value::UInt end))
end
for i in 2:len
push!(enum_expr.args, :(const $(names[i]) = $(root_name)(UInt($(values[i])))))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
# alias only used in this file
const Primal = Coluna.AbstractPrimalSpace
const Dual = Coluna.AbstractDualSpace
const MinSense = Coluna.AbstractMinSense
const MaxSense = Coluna.AbstractMaxSense

const Primal = AbstractPrimalSpace
const Dual = AbstractDualSpace
const MinSense = AbstractMinSense
const MaxSense = AbstractMaxSense

# Bounds
struct Bound{Space<:Coluna.AbstractSpace,Sense<:Coluna.AbstractSense} <: Real
struct Bound{Space<:AbstractSpace,Sense<:AbstractSense} <: Real
value::Float64
Bound{Space,Sense}(x::Number) where {Space,Sense} = new(x === NaN ? _defaultboundvalue(Space, Sense) : x)
end
Expand All @@ -21,7 +20,7 @@ _defaultboundvalue(::Type{<:Dual}, ::Type{<:MaxSense}) = Inf

doc todo
"""
function Bound{Space,Sense}() where {Space<:Coluna.AbstractSpace,Sense<:Coluna.AbstractSense}
function Bound{Space,Sense}() where {Space<:AbstractSpace,Sense<:AbstractSense}
val = _defaultboundvalue(Space, Sense)
return Bound{Space,Sense}(val)
end
Expand Down Expand Up @@ -104,7 +103,7 @@ end
Base.promote_rule(B::Type{<:Bound}, ::Type{<:AbstractFloat}) = B
Base.promote_rule(B::Type{<:Bound}, ::Type{<:Integer}) = B
Base.promote_rule(B::Type{<:Bound}, ::Type{<:AbstractIrrational}) = B
Base.promote_rule(::Type{<:Bound{<:Primal,Se}}, ::Type{<:Bound{<:Dual,Se}}) where {Se<:Coluna.AbstractSense} = Float64
Base.promote_rule(::Type{<:Bound{<:Primal,Se}}, ::Type{<:Bound{<:Dual,Se}}) where {Se<:AbstractSense} = Float64

Base.convert(::Type{<:AbstractFloat}, b::Bound) = b.value
Base.convert(::Type{<:Integer}, b::Bound) = b.value
Expand Down
2 changes: 0 additions & 2 deletions src/Containers/interface.jl

This file was deleted.

10 changes: 5 additions & 5 deletions src/MOIcallbacks.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
function MOI.submit(
model::Optimizer,
cb::BD.PricingSolution{MP.PricingCallbackData},
cb::BD.PricingSolution{MathProg.PricingCallbackData},
cost::Float64,
variables::Vector{MOI.VariableIndex},
values::Vector{Float64}
Expand Down Expand Up @@ -28,31 +28,31 @@ function MOI.submit(
return
end

function MOI.get(model::Optimizer, spid::BD.PricingSubproblemId{MP.PricingCallbackData})
function MOI.get(model::Optimizer, spid::BD.PricingSubproblemId{MathProg.PricingCallbackData})
callback_data = spid.callback_data
uid = getuid(callback_data.form)
axis_index_value = model.annotations.ann_per_form[uid].axis_index_value
return axis_index_value
end

function MOI.get(
model::Optimizer, pvc::BD.PricingVariableCost{MP.PricingCallbackData},
model::Optimizer, pvc::BD.PricingVariableCost{MathProg.PricingCallbackData},
x::MOI.VariableIndex
)
form = pvc.callback_data.form
return getcurcost(form, _get_orig_varid(model, x))
end

function MOI.get(
model::Optimizer, pvlb::BD.PricingVariableLowerBound{MP.PricingCallbackData},
model::Optimizer, pvlb::BD.PricingVariableLowerBound{MathProg.PricingCallbackData},
x::MOI.VariableIndex
)
form = pvlb.callback_data.form
return getcurlb(form, _get_orig_varid(model, x))
end

function MOI.get(
model::Optimizer, pvub::BD.PricingVariableUpperBound{MP.PricingCallbackData},
model::Optimizer, pvub::BD.PricingVariableUpperBound{MathProg.PricingCallbackData},
x::MOI.VariableIndex
)
form = pvub.callback_data.form
Expand Down
Loading