Skip to content

Commit eeb551a

Browse files
committed
julia: export from google3
1 parent c51007c commit eeb551a

2 files changed

Lines changed: 169 additions & 5 deletions

File tree

ortools/julia/ORTools.jl/src/moi_wrapper/MOI_wrapper.jl

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1924,3 +1924,164 @@ function MOI.optimize!(model::Optimizer)
19241924

19251925
return nothing
19261926
end
1927+
1928+
function MOI.get(model::Optimizer, ::MOI.RawStatusString)::String
1929+
if !isnothing(model) && !isnothing(model.solve_result)
1930+
return string(model.solve_result.termination.reason)
1931+
end
1932+
1933+
return ""
1934+
end
1935+
1936+
"""
1937+
Additional, typically solver-specific information about termination.
1938+
"""
1939+
struct ExtraTerminationDetailString <: MOI.AbstractOptimizerAttribute end
1940+
MOI.attribute_value_type(::ExtraTerminationDetailString) = String
1941+
1942+
function MOI.get(model::Optimizer, ::ExtraTerminationDetailString)::String
1943+
if !isnothing(model) && !isnothing(model.solve_result)
1944+
return model.solve_result.termination.detail
1945+
end
1946+
1947+
return ""
1948+
end
1949+
1950+
function MOI.get(model::Optimizer, ::MOI.TerminationStatus)::MOI.TerminationStatusCode
1951+
if isnothing(model) || isnothing(model.solve_result)
1952+
return MOI.OPTIMIZE_NOT_CALLED
1953+
end
1954+
1955+
if model.solve_result.termination.reason ==
1956+
TerminationReasonProto.TERMINATION_REASON_OPTIMAL
1957+
# It is expected that the LimitProto is LIMIT_UNSPECIFIED when the termination reason is OPTIMAL.
1958+
return MOI.OPTIMAL
1959+
elseif model.solve_result.termination.limit == LimitProto.LIMIT_ITERATION
1960+
return MOI.ITERATION_LIMIT
1961+
elseif model.solve_result.termination.limit == LimitProto.LIMIT_TIME
1962+
return MOI.TIME_LIMIT
1963+
elseif model.solve_result.termination.limit == LimitProto.LIMIT_NODE
1964+
return MOI.NODE_LIMIT
1965+
elseif model.solve_result.termination.limit == LimitProto.LIMIT_SOLUTION
1966+
return MOI.SOLUTION_LIMIT
1967+
elseif model.solve_result.termination.limit == LimitProto.LIMIT_MEMORY
1968+
return MOI.MEMORY_LIMIT
1969+
elseif model.solve_result.termination.limit == LimitProto.LIMIT_OBJECTIVE
1970+
return MOI.OBJECTIVE_LIMIT
1971+
elseif model.solve_result.termination.limit == LimitProto.LIMIT_NORM
1972+
return MOI.NORM_LIMIT
1973+
elseif model.solve_result.termination.limit == LimitProto.LIMIT_INTERRUPTED
1974+
return MOI.INTERRUPTED
1975+
elseif model.solve_result.termination.limit == LimitProto.LIMIT_SLOW_PROGRESS
1976+
return MOI.SLOW_PROGRESS
1977+
elseif model.solve_result.termination.limit == LimitProto.LIMIT_OTHER
1978+
return MOI.OTHER_LIMIT
1979+
elseif model.solve_result.termination.limit == LimitProto.LIMIT_UNDETERMINED
1980+
# TODO: b/411325865 Follow up on support for LIMIT_UNDETERMINED in MOI.jl
1981+
# A fallback as there's currently no associated MOI.LIMIT_* that can represent this.
1982+
@info "The underlying solver does not expose which limit was reached and the actual limit is LIMIT_UNDETERMINED " \
1983+
"However, LIMIT_UNDETERMINED is not associated with a MOI.LIMIT_* hence the returned LIMIT is MOI.OTHER_LIMIT."
1984+
return MOI.OTHER_LIMIT
1985+
elseif model.solve_result.termination.limit == LimitProto.LIMIT_CUTOFF
1986+
# TODO: b/411328356 Follow up on support for LIMIT_CUTOFF in MOI.jl
1987+
# A fallback as there's currently no associated MOI.LIMIT_* that can represent this.
1988+
@info "The solver was run with a cutoff on the objective, indicating that the user did not want any solution " \
1989+
"worse than the cutoff, and the solver concluded there were no solutions at least as good as the cutoff. " \
1990+
"Typically no further solution information is provided. The actual limit is LIMIT_CUTOFF. " \
1991+
"However, LIMIT_CUTOFF is not associated with a MOI.LIMIT_* hence the returned LIMIT is MOI.OTHER_LIMIT."
1992+
return MOI.OTHER_LIMIT
1993+
else
1994+
# TODO: b/411328207 Add attribute to capture more information about the limit when LIMIT_UNSPECIFIED is the returned limit.
1995+
# The else bit falls back to MOI.LIMIT_UNSPECIFIED if the termination reason wasn't TERMINATION_REASON_OPTIMAL
1996+
@info "The solver terminated but not from a limit and the actual limit is LIMIT_UNSPECIFIED, which is used as a null. " \
1997+
"However, LIMIT_UNSPECIFIED is not associated with a MOI.LIMIT_* hence the returned LIMIT is MOI.OTHER_LIMIT."
1998+
return MOI.OTHER_LIMIT
1999+
end
2000+
end
2001+
2002+
function MOI.get(model::Optimizer, attr::MOI.PrimalStatus)
2003+
if isnothing(model) || isnothing(model.solve_result)
2004+
return MOI.NO_SOLUTION
2005+
end
2006+
2007+
if attr.result_index != 1
2008+
return MOI.NO_SOLUTION
2009+
elseif model.solve_result.termination.problem_status.primal_status ==
2010+
FeasibilityStatusProto.FEASIBILITY_STATUS_UNDETERMINED
2011+
return MOI.UNKNOWN_RESULT_STATUS
2012+
elseif model.solve_result.termination.problem_status.primal_status ==
2013+
FeasibilityStatusProto.FEASIBILITY_STATUS_FEASIBLE
2014+
return MOI.FEASIBLE_POINT
2015+
elseif model.solve_result.termination.problem_status.primal_status ==
2016+
FeasibilityStatusProto.FEASIBILITY_STATUS_INFEASIBLE
2017+
return MOI.INFEASIBLE_POINT
2018+
else
2019+
# For FEASIBILITY_STATUS_UNSPECIFIED which is a guard value representing no status
2020+
return MOI.NO_SOLUTION
2021+
end
2022+
end
2023+
2024+
function MOI.get(model::Optimizer, attr::MOI.DualStatus)
2025+
if isnothing(model) || isnothing(model.solve_result)
2026+
return MOI.NO_SOLUTION
2027+
end
2028+
2029+
if attr.result_index != 1
2030+
return MOI.NO_SOLUTION
2031+
elseif model.solve_result.termination.problem_status.dual_status ==
2032+
FeasibilityStatusProto.FEASIBILITY_STATUS_UNDETERMINED
2033+
return MOI.UNKNOWN_RESULT_STATUS
2034+
elseif model.solve_result.termination.problem_status.dual_status ==
2035+
FeasibilityStatusProto.FEASIBILITY_STATUS_FEASIBLE
2036+
return MOI.FEASIBLE_SOLUTION
2037+
elseif model.solve_result.termination.problem_status.dual_status ==
2038+
FeasibilityStatusProto.FEASIBILITY_STATUS_INFEASIBLE
2039+
return MOI.INFEASIBLE_SOLUTION
2040+
else
2041+
# For FEASIBILITY_STATUS_UNSPECIFIED which is a guard value representing no status
2042+
return MOI.NO_SOLUTION
2043+
end
2044+
end
2045+
2046+
"""
2047+
When the solver claims the the primal or dual problem is infeasible, but
2048+
it does not know which (or if both are infeasible), this attribute returns `true`.
2049+
It can be true only when primal_status = dual_status = FEASIBILITY_STATUS_UNDETERMINED
2050+
(mapped to MOI.UNKNOWN_RESULT_STATUS). This extra information is often needed when
2051+
preprocessing determines there is no optimal solution to the problem
2052+
(but can't determine if it is due to infeasibility, unboundedness, or both).
2053+
"""
2054+
struct PrimalOrDualInfeasible <: MOI.AbstractOptimizerAttribute end
2055+
MOI.attribute_value_type(::PrimalOrDualInfeasible) = Bool
2056+
2057+
function MOI.get(model::Optimizer, ::PrimalOrDualInfeasible)::Bool
2058+
if isnothing(model) || isnothing(model.solve_result)
2059+
return false
2060+
end
2061+
2062+
return model.solve_result.termination.problem_status.primal_status.primal_or_dual_infeasible
2063+
end
2064+
2065+
function MOI.get(model::Optimizer, attr::MOI.ObjectiveBound)
2066+
if isnothing(model) || isnothing(model.solve_result)
2067+
throw(MOI.GetAttributeNotAllowed(attr))
2068+
end
2069+
2070+
return model.solve_result.termination.objective_bounds.primal_bound
2071+
end
2072+
2073+
"""
2074+
When the solver claims there exists a dual solution that is numerically feasible
2075+
(i.e. feasible up to the solvers tolerance), and whose objective value is
2076+
dual_bound, this attribute returns the dual bound.
2077+
"""
2078+
struct DualObjectiveBound <: MOI.AbstractOptimizerAttribute end
2079+
MOI.attribute_value_type(::DualObjectiveBound) = Float64
2080+
2081+
function MOI.get(model::Optimizer, attr::DualObjectiveBound)
2082+
if isnothing(model) || isnothing(model.solve_result)
2083+
throw(MOI.GetAttributeNotAllowed(attr))
2084+
end
2085+
2086+
return model.solve_result.termination.objective_bounds.dual_bound
2087+
end

ortools/julia/ORTools.jl/src/moi_wrapper/Type_wrappers.jl

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ const OperationsResearch = ORToolsGenerated.Proto.operations_research
33
const MathOpt = OperationsResearch.math_opt
44
const SolverType = MathOpt.SolverTypeProto
55
const SolveResultProto = MathOpt.SolveResultProto
6+
const TerminationReasonProto = MathOpt.TerminationReasonProto
7+
const LimitProto = MathOpt.LimitProto
8+
const FeasibilityStatusProto = MathOpt.FeasibilityStatusProto
69
const PB = MathOpt.PB
710

811
"""
@@ -933,7 +936,7 @@ mutable struct SatParameters <: AbstractSatParameters
933936
exploit_objective::Bool
934937
probing_period_at_root::Int64
935938
use_probing_search::Bool
936-
shaving_deterministic_time_in_probing_search::Float64
939+
use_shaving_in_probing_search::Bool
937940
shaving_search_deterministic_time::Float64
938941
use_objective_lb_search::Bool
939942
use_objective_shaving_search::Bool
@@ -1154,8 +1157,8 @@ mutable struct SatParameters <: AbstractSatParameters
11541157
exploit_objective = true,
11551158
probing_period_at_root = Int64(0),
11561159
use_probing_search = false,
1157-
shaving_deterministic_time_in_probing_search = Float64(0.001),
1158-
shaving_search_deterministic_time = Float64(0.1),
1160+
use_shaving_in_probing_search = true,
1161+
shaving_search_deterministic_time = Float64(0.001),
11591162
use_objective_lb_search = false,
11601163
use_objective_shaving_search = false,
11611164
pseudo_cost_reliability_threshold = Int64(100),
@@ -1375,7 +1378,7 @@ mutable struct SatParameters <: AbstractSatParameters
13751378
exploit_objective,
13761379
probing_period_at_root,
13771380
use_probing_search,
1378-
shaving_deterministic_time_in_probing_search,
1381+
use_shaving_in_probing_search,
13791382
shaving_search_deterministic_time,
13801383
use_objective_lb_search,
13811384
use_objective_shaving_search,
@@ -1603,7 +1606,7 @@ function to_proto_struct(
16031606
sat_parameters.exploit_objective,
16041607
sat_parameters.probing_period_at_root,
16051608
sat_parameters.use_probing_search,
1606-
sat_parameters.shaving_deterministic_time_in_probing_search,
1609+
sat_parameters.use_shaving_in_probing_search,
16071610
sat_parameters.shaving_search_deterministic_time,
16081611
sat_parameters.use_objective_lb_search,
16091612
sat_parameters.use_objective_shaving_search,

0 commit comments

Comments
 (0)