Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
model_utils.cc
Go to the documentation of this file.
1// Copyright 2010-2024 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 <string>
17#include <utility>
18
19#include "absl/container/flat_hash_set.h"
20#include "absl/log/check.h"
21#include "absl/status/statusor.h"
26
28
29namespace {
30
31absl::StatusOr<LpModel> ReorderVariables(
32 const LpModel& model,
34 const bool allow_skip_old) {
35 constexpr VariableIndex kBad(-1);
37 model.variables().end_index(), kBad);
38 for (const VariableIndex v_new : new_to_old.index_range()) {
39 const VariableIndex v_old = new_to_old[v_new];
40 if (v_old < VariableIndex(0) || v_old >= model.variables().end_index()) {
42 << "values of new_to_old be in [0," << model.variables().size()
43 << "), found: " << v_old;
44 }
45 if (old_to_new[v_old] != kBad) {
47 << "found value: " << v_old << " twice in new_to_old";
48 }
49 old_to_new[v_old] = v_new;
50 }
51 if (!allow_skip_old) {
52 for (const VariableIndex v_old : old_to_new.index_range()) {
53 if (old_to_new[v_old] == kBad) {
55 << "no new VariableIndex for old VariableIndex: " << v_old;
56 }
57 }
58 }
59 LpModel result;
60 for (const VariableIndex new_var : new_to_old.index_range()) {
62 result.AddVariable(model.variables()[new_to_old[new_var]]).status())
63 << "should be unreachable";
64 }
65 // We build the constraints in the new model by iterating over the constraints
66 // in the old model, copying each constraint and then modifying it in place.
67 for (Constraint c : model.constraints()) {
68 for (auto& [unused, var] : c.terms) {
69 if (old_to_new[var] == kBad) {
71 << "variable " << var
72 << " appears in a constraint but is not new_to_old";
73 }
74 var = old_to_new[var];
75 }
76 RETURN_IF_ERROR(result.AddConstraint(c).status())
77 << "should be unreachable";
78 }
79 return result;
80}
81
82} // namespace
83
86 model.variables().end_index());
87 for (const Constraint& c : model.constraints()) {
88 for (const auto& [unused, var] : c.terms) {
89 old_vars_used[var] = true;
90 }
91 }
93 for (VariableIndex v_old : old_vars_used.index_range()) {
94 if (old_vars_used[v_old]) {
95 new_to_old.push_back(v_old);
96 }
97 }
98 auto result = ReorderVariables(model, new_to_old, /*allow_skip_old=*/true);
99 CHECK_OK(result);
100 return *std::move(result);
101}
102
103absl::StatusOr<LpModel> PermuteVariables(
104 const LpModel& model,
106 new_index_to_old_index) {
107 return ReorderVariables(model, new_index_to_old_index,
108 /*allow_skip_old=*/false);
109}
110
111absl::StatusOr<LpModel> PermuteVariables(
112 const LpModel& model,
114 order_by_name) {
116 for (const std::string& name : order_by_name) {
117 auto it = model.variable_names().find(name);
118 if (it == model.variable_names().end()) {
120 << "no variable with name: " << name << " in model";
121 }
122 new_to_old.push_back(it->second);
123 }
124 return PermuteVariables(model, new_to_old);
125}
126
127} // namespace operations_research::lp_format
#define RETURN_IF_ERROR(expr)
void push_back(const value_type &val)
StrongIntRange< IntType > index_range() const
const std::string name
A name for logging purposes.
IntVar * var
GRBmodel * model
absl::StatusOr< LpModel > PermuteVariables(const LpModel &model, const util_intops::StrongVector< VariableIndex, VariableIndex > &new_index_to_old_index)
LpModel RemoveUnusedVariables(const LpModel &model)
StatusBuilder InvalidArgumentErrorBuilder()