Google OR-Tools v9.12
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
model_parameters_validator.cc
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
15
16#include <cstdint>
17
18#include "absl/status/status.h"
19#include "absl/time/time.h"
20#include "google/protobuf/repeated_field.h"
26#include "ortools/math_opt/model_parameters.pb.h"
27#include "ortools/math_opt/sparse_containers.pb.h"
32
33namespace operations_research {
34namespace math_opt {
35namespace {
36
37absl::Status ValidateSolutionHint(const SolutionHintProto& solution_hint,
38 const ModelSummary& model_summary) {
40 MakeView(solution_hint.variable_values()),
41 {.allow_positive_infinity = false, .allow_negative_infinity = false}))
42 << "Invalid solution_hint.variable_values";
44 solution_hint.variable_values().ids(), model_summary.variables,
45 "solution_hint.variable_values ids", "model variable ids"));
46
48 MakeView(solution_hint.dual_values()),
49 {.allow_positive_infinity = false, .allow_negative_infinity = false}))
50 << "Invalid solution_hint.dual_values";
52 solution_hint.dual_values().ids(), model_summary.linear_constraints,
53 "solution_hint.dual_values ids", "model linear constraint ids"));
54
55 return absl::OkStatus();
56}
57
58absl::Status ValidateBranchingPriorities(
59 const SparseInt32VectorProto& branching_priorities,
60 const ModelSummary& model_summary) {
61 const auto vector_view = MakeView(branching_priorities);
63 << "Invalid branching_priorities";
64 RETURN_IF_ERROR(CheckIdsSubset(branching_priorities.ids(),
65 model_summary.variables,
66 "branching_priorities ids", "model IDs"));
67
68 return absl::OkStatus();
69}
70
71absl::Status ValidateObjectiveParameters(
72 const ObjectiveParametersProto& parameters) {
73 if (parameters.objective_degradation_absolute_tolerance() < 0) {
75 << "ObjectiveParametersProto.objective_degradation_absolute_"
76 "tolerance = "
77 << parameters.objective_degradation_absolute_tolerance() << " < 0";
78 }
79
80 if (parameters.objective_degradation_relative_tolerance() < 0) {
82 << "ObjectiveParametersProto.objective_degradation_relative_"
83 "tolerance = "
84 << parameters.objective_degradation_relative_tolerance() << " < 0";
85 }
86 {
88 const absl::Duration time_limit,
89 util_time::DecodeGoogleApiProto(parameters.time_limit()),
90 _ << "invalid ObjectiveParametersProto.time_limit");
91 if (time_limit < absl::ZeroDuration()) {
93 << "ObjectiveParametersProto.time_limit = " << time_limit
94 << " < 0";
95 }
96 }
97 return absl::OkStatus();
98}
99
100absl::Status ValidateLazyLinearConstraints(
101 const google::protobuf::RepeatedField<int64_t>& lazy_linear_constraint_ids,
102 const ModelSummary& model_summary) {
104 CheckIdsRangeAndStrictlyIncreasing(lazy_linear_constraint_ids));
106 lazy_linear_constraint_ids, model_summary.linear_constraints,
107 "lazy_linear_constraint ids", "model linear constraint IDs"));
108 return absl::OkStatus();
109}
110
111} // namespace
112
113absl::Status ValidateSparseVectorFilter(const SparseVectorFilterProto& v,
114 const IdNameBiMap& valid_ids) {
117 CheckIdsSubset(v.filtered_ids(), valid_ids, "filtered_ids", "model IDs"));
118 if (!v.filter_by_ids() && !v.filtered_ids().empty()) {
119 return absl::InvalidArgumentError(
120 "Invalid SparseVectorFilterProto.filter_by_id* specification. To "
121 "filter by "
122 "IDs you must set SparseVectorFilterProto.filter_by_ids to 'true'.");
123 }
124
125 return absl::OkStatus();
126}
127
129 const ModelSolveParametersProto& parameters,
130 const ModelSummary& model_summary) {
132 parameters.variable_values_filter(), model_summary.variables))
133 << "invalid variable_values_filter";
134 RETURN_IF_ERROR(ValidateSparseVectorFilter(parameters.reduced_costs_filter(),
135 model_summary.variables))
136 << "invalid reduced_costs_filter";
137 RETURN_IF_ERROR(ValidateSparseVectorFilter(parameters.dual_values_filter(),
138 model_summary.linear_constraints))
139 << "invalid dual_values_filter";
140 if (parameters.has_initial_basis()) {
141 RETURN_IF_ERROR(ValidateBasis(parameters.initial_basis(), model_summary,
142 /*check_dual_feasibility=*/false));
143 }
144 for (const SolutionHintProto& solution_hint : parameters.solution_hints()) {
145 RETURN_IF_ERROR(ValidateSolutionHint(solution_hint, model_summary));
146 }
147 RETURN_IF_ERROR(ValidateBranchingPriorities(parameters.branching_priorities(),
148 model_summary));
150 ValidateObjectiveParameters(parameters.primary_objective_parameters()))
151 << "invalid primary_objective_parameters";
152 for (const auto& [objective, params] :
153 parameters.auxiliary_objective_parameters()) {
154 if (!model_summary.auxiliary_objectives.HasId(objective)) {
156 << "Entry in auxiliary_objective_parameters for unknown "
157 "objective: "
158 << objective;
159 }
160 RETURN_IF_ERROR(ValidateObjectiveParameters(params))
161 << "invalid auxiliary_objective_parameters entry for objective: "
162 << objective;
163 }
164 RETURN_IF_ERROR(ValidateLazyLinearConstraints(
165 parameters.lazy_linear_constraint_ids(), model_summary))
166 << "invalid lazy_linear_constraint_ids";
167 return absl::OkStatus();
168}
169
170} // namespace math_opt
171} // namespace operations_research
#define RETURN_IF_ERROR(expr)
time_limit
Definition solve.cc:22
An object oriented wrapper for quadratic constraints in ModelStorage.
Definition gurobi_isv.cc:28
SparseVectorView< T > MakeView(absl::Span< const int64_t > ids, const Collection &values)
absl::Status CheckIdsAndValues(const SparseVectorView< T > &vector_view, absl::string_view value_name="values")
absl::Status CheckIdsSubset(absl::Span< const int64_t > ids, const IdNameBiMap &universe, std::optional< int64_t > upper_bound)
absl::Status ValidateBasis(const BasisProto &basis, const ModelSummary &model_summary, const bool check_dual_feasibility)
absl::Status ValidateSparseVectorFilter(const SparseVectorFilterProto &v, const IdNameBiMap &valid_ids)
absl::Status ValidateModelSolveParameters(const ModelSolveParametersProto &parameters, const ModelSummary &model_summary)
absl::Status CheckIdsRangeAndStrictlyIncreasing(absl::Span< const int64_t > ids)
In SWIG mode, we don't want anything besides these top-level includes.
inline ::absl::StatusOr< absl::Duration > DecodeGoogleApiProto(const google::protobuf::Duration &proto)
Definition protoutil.h:42
StatusBuilder InvalidArgumentErrorBuilder()
#define OR_ASSIGN_OR_RETURN3(lhs, rexpr, error_expression)