23 : base_view(model, &cols_sizes_, &rows_sizes_, &cols_focus_, &rows_focus_),
25 ResetToIdentitySubModel();
30 const std::vector<FullSubsetIndex>& columns_focus)
31 : base_view(model, &cols_sizes_, &rows_sizes_, &cols_focus_, &rows_focus_),
33 rows_sizes_.resize(full_model_->num_elements(), 0);
34 for (ElementIndex i : full_model_->ElementRange()) {
35 rows_sizes_[i] = full_model_->rows()[i].size();
40void SubModelView::ResetToIdentitySubModel() {
46 cols_sizes_[j] = full_model_->
columns()[j].size();
47 cols_focus_.push_back(j);
50 rows_sizes_[i] = full_model_->
rows()[i].size();
51 rows_focus_.push_back(i);
53 fixed_columns_.clear();
58 const std::vector<SubsetIndex>& columns_to_fix) {
59 DCHECK(full_model_ !=
nullptr);
60 Cost old_fixed_cost = fixed_cost_;
61 if (columns_to_fix.empty()) {
62 return fixed_cost_ - old_fixed_cost;
65 for (SubsetIndex j : columns_to_fix) {
66 DCHECK(cols_sizes_[j] > 0);
67 fixed_cost_ += full_model_->subset_costs()[j];
68 fixed_columns_.push_back(
static_cast<FullSubsetIndex
>(j));
70 for (ElementIndex i : full_model_->columns()[j]) {
76 DCHECK(full_model_ !=
nullptr);
77 if (cols_sizes_[j] > 0) {
78 cols_sizes_[j] = absl::c_count_if(full_model_->columns()[j], [&](
auto i) {
79 return rows_sizes_[i] > 0;
82 return cols_sizes_[j] == 0;
85 &rows_focus_, [&](ElementIndex i) {
return !rows_sizes_[i]; });
88 return fixed_cost_ - old_fixed_cost;
92 const std::vector<FullSubsetIndex>& columns_to_fix,
const DualState&) {
93 ResetToIdentitySubModel();
94 std::vector<SubsetIndex> core_column_to_fix;
95 for (FullSubsetIndex full_j : columns_to_fix) {
96 core_column_to_fix.push_back(
static_cast<SubsetIndex
>(full_j));
102 DCHECK(full_model_ !=
nullptr);
103 DCHECK(!rows_sizes_.empty());
104 if (columns_focus.empty()) {
111 for (ElementIndex i : full_model_->ElementRange()) {
112 enabled_rows[i] = rows_sizes_[i] > 0;
114 cols_sizes_.assign(full_model_->num_subsets(), 0);
115 rows_sizes_.assign(full_model_->num_elements(), 0);
116 for (FullSubsetIndex full_j : columns_focus) {
117 SubsetIndex j =
static_cast<SubsetIndex
>(full_j);
118 for (ElementIndex i : full_model_->columns()[j]) {
119 if (enabled_rows[i] > 0) {
124 if (cols_sizes_[j] > 0) {
125 cols_focus_.push_back(j);
128 for (ElementIndex i : full_model_->ElementRange()) {
129 if (rows_sizes_[i] > 0) {
130 rows_focus_.push_back(i);
137 CHECK(ElementIndex(full_model_.num_elements()) < null_element_index)
138 <<
"Max element index is reserved.";
139 CHECK(SubsetIndex(full_model_.num_subsets()) < null_subset_index)
140 <<
"Max subset index is reserved.";
141 ResetToIdentitySubModel();
145 const std::vector<FullSubsetIndex>& columns_focus)
150 CHECK(ElementIndex(full_model_.num_elements()) < null_element_index)
151 <<
"Max element index is reserved.";
152 CHECK(SubsetIndex(full_model_.num_subsets()) < null_subset_index)
153 <<
"Max subset index is reserved.";
155 absl::c_iota(core2full_row_map_, FullElementIndex());
156 absl::c_iota(full2core_row_map_, ElementIndex());
160void CoreModel::ResetToIdentitySubModel() {
164 absl::c_iota(core2full_row_map_, FullElementIndex());
165 absl::c_iota(full2core_row_map_, ElementIndex());
166 absl::c_iota(core2full_col_map_, FullSubsetIndex());
168 fixed_columns_.clear();
177 if (columns_focus.empty()) {
184 core2full_col_map_.clear();
187 for (FullSubsetIndex full_j : columns_focus) {
188 bool first_row =
true;
189 for (FullElementIndex full_i : full_model_.columns()[full_j]) {
190 ElementIndex core_i = full2core_row_map_[full_i];
191 if (core_i != null_element_index) {
202 core2full_col_map_.push_back(full_j);
213void CoreModel::MarkNewFixingInMaps(
214 const std::vector<SubsetIndex>& columns_to_fix) {
215 for (SubsetIndex old_core_j : columns_to_fix) {
217 fixed_columns_.push_back(core2full_col_map_[old_core_j]);
219 core2full_col_map_[old_core_j] = null_full_subset_index;
220 for (ElementIndex old_core_i :
columns()[old_core_j]) {
221 core2full_row_map_[old_core_i] = null_full_element_index;
229 full2core_row_map_.
assign(full_model_.num_elements(), null_element_index);
232 FullElementIndex full_i = core2full_row_map_[old_core_i];
233 if (full_i != null_full_element_index) {
234 full2core_row_map_[full_i] = ElementIndex(new_c2f_row_map.size());
235 new_c2f_row_map.push_back(full_i);
238 return new_c2f_row_map;
246Model CoreModel::MakeNewCoreModel(
253 FullSubsetIndex full_j = core2full_col_map_[old_core_j];
254 if (full_j != null_full_subset_index) {
255 bool first_row =
true;
257 for (ElementIndex old_core_i :
columns()[old_core_j]) {
259 FullElementIndex full_i = core2full_row_map_[old_core_i];
260 if (full_i != null_full_element_index) {
264 new_submodel.AddEmptySubset(full_model_.subset_costs()[full_j]);
268 SubsetIndex new_j(new_core_j++);
269 core2full_col_map_[new_j] = full_j;
271 ElementIndex new_core_i = full2core_row_map_[full_i];
272 DCHECK(new_core_i != null_element_index);
273 new_submodel.AddElementToLastSubset(new_core_i);
279 core2full_col_map_.resize(new_core_j);
280 core2full_row_map_ = std::move(new_c2f_row_map);
281 new_submodel.CreateSparseRowView();
287 if (columns_to_fix.empty()) {
290 Cost old_fixed_cost = fixed_cost_;
293 MarkNewFixingInMaps(columns_to_fix);
299 static_cast<Model&
>(*this) = MakeNewCoreModel(new_c2f_row_map);
302 DCHECK(absl::c_is_sorted(core2full_col_map_));
303 DCHECK(absl::c_is_sorted(core2full_row_map_));
305 return fixed_cost_ - old_fixed_cost;
309 const std::vector<FullSubsetIndex>& columns_to_fix,
const DualState&) {
310 ResetToIdentitySubModel();
311 std::vector<SubsetIndex> core_column_to_fix;
312 for (FullSubsetIndex full_j : columns_to_fix) {
313 core_column_to_fix.push_back(
static_cast<SubsetIndex
>(full_j));
util_intops::StrongIntRange< ElementIndex > ElementRange() const
void AddElementToLastSubset(BaseInt element)
void AddEmptySubset(Cost cost)
const SparseRowView & rows() const
Row view of the set covering problem.
BaseInt num_elements() const
util_intops::StrongIntRange< SubsetIndex > SubsetRange() const
Access to the ranges of subsets and elements.
void CreateSparseRowView()
const SparseColumnView & columns() const
Column view of the set covering problem.
BaseInt num_subsets() const
BaseInt num_subsets() const
BaseInt num_elements() const
const SetCoverModel & base() const
virtual void ResetColumnFixing(const std::vector< FullSubsetIndex > &columns_to_fix, const DualState &state)
util_intops::StrongIntRange< ElementIndex > ElementRange() const
void SetFocus(const std::vector< FullSubsetIndex > &columns_focus)
CoreModel()=default
Empty initialization to facilitate delayed construction.
util_intops::StrongIntRange< SubsetIndex > SubsetRange() const
Access to the ranges of subsets and elements.
const SubsetCostVector & subset_costs() const
Vector of costs for each subset.
BaseInt num_elements() const
const SparseColumnView & columns() const
Member function relevant for the CFT inherited from Model.
virtual Cost FixMoreColumns(const std::vector< SubsetIndex > &columns_to_fix)
void SetFocus(const std::vector< FullSubsetIndex > &columns_focus)
SubModelView()=default
Empty initialization to facilitate delayed construction.
virtual void ResetColumnFixing(const std::vector< FullSubsetIndex > &columns_to_fix, const DualState &state)
virtual Cost FixMoreColumns(const std::vector< SubsetIndex > &columns_to_fix)
void assign(size_type n, const value_type &val)
void resize(size_type new_size)
void STLEraseAllFromSequenceIf(T *v, P pred)
Remove each element e in v satisfying pred(e).
bool ValidateSubModel(const SubModelT &model)
util_intops::StrongVector< ElementIndex, FullElementIndex > CoreToFullElementMapVector
util_intops::StrongVector< ElementIndex, bool > ElementBoolVector
double Cost
Basic non-strict type for cost. The speed penalty for using double is ~2%.