60 lines
2.4 KiB
C++
60 lines
2.4 KiB
C++
// Copyright 2010-2017 Google
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "ortools/sat/util.h"
|
|
|
|
namespace operations_research {
|
|
namespace sat {
|
|
|
|
int MoveOneUnprocessedLiteralLast(const std::set<LiteralIndex>& processed,
|
|
int relevant_prefix_size,
|
|
std::vector<Literal>* literals) {
|
|
if (literals->empty()) return -1;
|
|
if (!gtl::ContainsKey(processed, literals->back().Index())) {
|
|
return std::min<int>(relevant_prefix_size, literals->size());
|
|
}
|
|
|
|
// To get O(n log n) size of suffixes, we will first process the last n/2
|
|
// literals, we then move all of them first and process the n/2 literals left.
|
|
// We use the same algorithm recursively. The sum of the suffixes' size S(n)
|
|
// is thus S(n/2) + n + S(n/2). That gives us the correct complexity. The code
|
|
// below simulates one step of this algorithm and is made to be "robust" when
|
|
// from one call to the next, some literals have been removed (but the order
|
|
// of literals is preserved).
|
|
int num_processed = 0;
|
|
int num_not_processed = 0;
|
|
int target_prefix_size = literals->size() - 1;
|
|
for (int i = literals->size() - 1; i >= 0; i--) {
|
|
if (gtl::ContainsKey(processed, (*literals)[i].Index())) {
|
|
++num_processed;
|
|
} else {
|
|
++num_not_processed;
|
|
target_prefix_size = i;
|
|
}
|
|
if (num_not_processed >= num_processed) break;
|
|
}
|
|
if (num_not_processed == 0) return -1;
|
|
target_prefix_size = std::min(target_prefix_size, relevant_prefix_size);
|
|
|
|
// Once a prefix size has been decided, it is always better to
|
|
// enqueue the literal already processed first.
|
|
std::stable_partition(literals->begin() + target_prefix_size, literals->end(),
|
|
[&processed](Literal l) {
|
|
return gtl::ContainsKey(processed, l.Index());
|
|
});
|
|
return target_prefix_size;
|
|
}
|
|
|
|
} // namespace sat
|
|
} // namespace operations_research
|