Skip to content

Commit 51f8b46

Browse files
authored
Add support for VariablePrimalStart (#128)
1 parent ccd56e2 commit 51f8b46

File tree

1 file changed

+73
-3
lines changed

1 file changed

+73
-3
lines changed

src/MOI_wrapper.jl

+73-3
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,22 @@ mutable struct _VariableInfo
6161
upper::Float64
6262
# Track integrality
6363
type::_TypeEnum
64+
start::Union{Nothing,Float64}
6465
function _VariableInfo(
6566
index::MOI.VariableIndex,
6667
column::HighsInt,
6768
bound::_BoundEnum = _BOUND_NONE,
6869
)
69-
return new(index, "", column, bound, -Inf, Inf, _TYPE_CONTINUOUS)
70+
return new(
71+
index,
72+
"",
73+
column,
74+
bound,
75+
-Inf,
76+
Inf,
77+
_TYPE_CONTINUOUS,
78+
nothing,
79+
)
7080
end
7181
end
7282

@@ -363,8 +373,12 @@ end
363373

364374
MOI.get(model::Optimizer, ::MOI.RawSolver) = model
365375

366-
function MOI.get(::Optimizer, ::MOI.ListOfVariableAttributesSet)
367-
return MOI.AbstractVariableAttribute[MOI.VariableName()]
376+
function MOI.get(model::Optimizer, ::MOI.ListOfVariableAttributesSet)
377+
ret = MOI.AbstractVariableAttribute[MOI.VariableName()]
378+
if any(info -> info.start !== nothing, values(model.variable_info))
379+
push!(ret, MOI.VariablePrimalStart())
380+
end
381+
return ret
368382
end
369383

370384
function MOI.get(model::Optimizer, ::MOI.ListOfModelAttributesSet)
@@ -720,6 +734,37 @@ function _rebuild_name_to_variable(model::Optimizer)
720734
return
721735
end
722736

737+
#
738+
# MOI.VariablePrimalStart
739+
#
740+
741+
function MOI.supports(
742+
::Optimizer,
743+
::MOI.VariablePrimalStart,
744+
::Type{MOI.VariableIndex},
745+
)
746+
return true
747+
end
748+
749+
function MOI.set(
750+
model::Optimizer,
751+
::MOI.VariablePrimalStart,
752+
x::MOI.VariableIndex,
753+
start::Union{Nothing,Float64},
754+
)
755+
info = _info(model, x)
756+
info.start = start
757+
return
758+
end
759+
760+
function MOI.get(
761+
model::Optimizer,
762+
::MOI.VariablePrimalStart,
763+
x::MOI.VariableIndex,
764+
)
765+
return _info(model, x).start
766+
end
767+
723768
###
724769
### Objectives
725770
###
@@ -1616,6 +1661,22 @@ function _store_solution(model::Optimizer, ret::HighsInt)
16161661
return
16171662
end
16181663

1664+
function _set_variable_primal_start(model::Optimizer)
1665+
if all(info -> info.start === nothing, values(model.variable_info))
1666+
return
1667+
end
1668+
start = zeros(Cdouble, length(model.variable_info))
1669+
for (x, info) in model.variable_info
1670+
# For the default start, pick the lower bound if it exists, otherwise
1671+
# the minimum of the upper bound and zero.
1672+
default = isfinite(info.lower) ? info.lower : min(info.upper, 0.0)
1673+
start[info.column+1] = something(info.start, default)
1674+
end
1675+
ret = Highs_setSolution(model, start, C_NULL, C_NULL, C_NULL)
1676+
_check_ret(ret)
1677+
return
1678+
end
1679+
16191680
function MOI.optimize!(model::Optimizer)
16201681
for info in model.binaries
16211682
Highs_changeColBounds(
@@ -1625,6 +1686,7 @@ function MOI.optimize!(model::Optimizer)
16251686
min(1.0, info.upper),
16261687
)
16271688
end
1689+
_set_variable_primal_start(model)
16281690
ret = Highs_run(model)
16291691
_store_solution(model, ret)
16301692
# TODO(odow): resetting the bounds here invalidates previously stored
@@ -2366,6 +2428,14 @@ function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike)
23662428
MOI.ObjectiveFunction{F}(),
23672429
MOI.Utilities.map_indices(mapping, f_obj),
23682430
)
2431+
# VariablePrimalStart
2432+
start_attr = MOI.VariablePrimalStart()
2433+
if start_attr in MOI.get(src, MOI.ListOfVariableAttributesSet())
2434+
for x in MOI.get(src, MOI.ListOfVariableIndices())
2435+
start = MOI.get(src, start_attr, x)
2436+
MOI.set(dest, start_attr, mapping[x], start)
2437+
end
2438+
end
23692439
return mapping
23702440
end
23712441

0 commit comments

Comments
 (0)