new dynamic partition class
This commit is contained in:
@@ -293,4 +293,74 @@ std::string MergingPartition::DebugString() {
|
||||
return out;
|
||||
}
|
||||
|
||||
void SimpleDynamicPartition::Refine(
|
||||
absl::Span<const int> distinguished_subset) {
|
||||
// Compute the size of the non-empty intersection of each part with the
|
||||
// distinguished_subset.
|
||||
temp_to_clean_.clear();
|
||||
std::vector<int>& local_sizes = temp_data_by_part_;
|
||||
local_sizes.resize(size_of_part_.size(), 0);
|
||||
for (const int element : distinguished_subset) {
|
||||
const int part = part_of_[element];
|
||||
if (local_sizes[part] == 0) temp_to_clean_.push_back(part);
|
||||
local_sizes[part]++;
|
||||
}
|
||||
|
||||
// Reuse local_sizes to store new_part index or zero (no remapping).
|
||||
// Also update the size of each part.
|
||||
for (const int part : temp_to_clean_) {
|
||||
if (local_sizes[part] == size_of_part_[part]) {
|
||||
// No need to remap if the whole part is in distinguished_subset.
|
||||
local_sizes[part] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
const int new_part_index = size_of_part_.size();
|
||||
size_of_part_[part] -= local_sizes[part];
|
||||
size_of_part_.push_back(local_sizes[part]);
|
||||
local_sizes[part] = new_part_index;
|
||||
}
|
||||
|
||||
// For each part not completely included or excluded, split out the element
|
||||
// from distinguished_subset into a new part.
|
||||
for (const int element : distinguished_subset) {
|
||||
const int new_part = local_sizes[part_of_[element]];
|
||||
if (new_part != 0) part_of_[element] = new_part;
|
||||
}
|
||||
|
||||
// Sparse clean.
|
||||
for (const int part : temp_to_clean_) {
|
||||
local_sizes[part] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<absl::Span<const int>> SimpleDynamicPartition::GetParts(
|
||||
std::vector<int>* buffer) {
|
||||
const int num_elements = part_of_.size();
|
||||
const int num_parts = size_of_part_.size();
|
||||
buffer->resize(num_elements);
|
||||
|
||||
std::vector<absl::Span<const int>> result(num_parts);
|
||||
if (result.empty()) return result;
|
||||
|
||||
// Compute start of each part in buffer.
|
||||
std::vector<int>& starts = temp_data_by_part_;
|
||||
starts.resize(num_parts, 0);
|
||||
for (int i = 1; i < num_parts; ++i) {
|
||||
starts[i] = starts[i - 1] + size_of_part_[i - 1];
|
||||
}
|
||||
|
||||
// Fill result.
|
||||
for (int i = 0; i < num_parts; ++i) {
|
||||
result[i] = absl::MakeSpan(&(*buffer)[starts[i]], size_of_part_[i]);
|
||||
}
|
||||
|
||||
// Copy elements in order and at their place.
|
||||
for (int element = 0; element < num_elements; ++element) {
|
||||
(*buffer)[starts[part_of_[element]]++] = element;
|
||||
}
|
||||
starts.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace operations_research
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
|
||||
#include "ortools/base/logging.h"
|
||||
|
||||
#include "absl/types/span.h"
|
||||
|
||||
namespace operations_research {
|
||||
|
||||
// Partition class that supports incremental splitting, with backtracking.
|
||||
@@ -272,6 +274,35 @@ class MergingPartition {
|
||||
std::vector<bool> tmp_part_bit_;
|
||||
};
|
||||
|
||||
// A subset of the API of DynamicPartition without backtrack support. The
|
||||
// Refine() here is about twice as fast, but we have limited query support until
|
||||
// a batch ComputeElementsByPart() is called.
|
||||
class SimpleDynamicPartition {
|
||||
public:
|
||||
explicit SimpleDynamicPartition(int num_elements)
|
||||
: part_of_(num_elements, 0),
|
||||
size_of_part_(num_elements > 0 ? 1 : 0, num_elements) {}
|
||||
|
||||
int NumElements() const { return part_of_.size(); }
|
||||
const int NumParts() const { return size_of_part_.size(); }
|
||||
int PartOf(int element) const { return part_of_[element]; }
|
||||
int SizeOfPart(int part) const { return size_of_part_[part]; }
|
||||
|
||||
void Refine(absl::Span<const int> distinguished_subset);
|
||||
|
||||
// This is meant to be called once after a bunch of Refine().
|
||||
// The returned Span<> points into the given buffer which is re-initialized.
|
||||
std::vector<absl::Span<const int>> GetParts(std::vector<int>* buffer);
|
||||
|
||||
private:
|
||||
std::vector<int> part_of_;
|
||||
std::vector<int> size_of_part_;
|
||||
|
||||
// Temp data. Always empty or all zero.
|
||||
std::vector<int> temp_to_clean_;
|
||||
std::vector<int> temp_data_by_part_;
|
||||
};
|
||||
|
||||
// *** Implementation of inline methods of the above classes. ***
|
||||
|
||||
inline DynamicPartition::IterablePart DynamicPartition::ElementsInPart(
|
||||
|
||||
@@ -44,9 +44,10 @@
|
||||
%rename (setTimeLimit) operations_research::KnapsackSolver::set_time_limit; // untested
|
||||
|
||||
%unignore operations_research::KnapsackSolver::SolverType;
|
||||
%unignore operations_research::KnapsackSolver::KNAPSACK_BRUTE_FORCE_SOLVER; // untested
|
||||
%unignore operations_research::KnapsackSolver::KNAPSACK_64ITEMS_SOLVER; // untested
|
||||
%unignore operations_research::KnapsackSolver::KNAPSACK_DYNAMIC_PROGRAMMING_SOLVER; // untested
|
||||
%unignore operations_research::KnapsackSolver::KNAPSACK_BRUTE_FORCE_SOLVER;
|
||||
%unignore operations_research::KnapsackSolver::KNAPSACK_64ITEMS_SOLVER;
|
||||
%unignore operations_research::KnapsackSolver::KNAPSACK_DIVIDE_AND_CONQUER_SOLVER;
|
||||
%unignore operations_research::KnapsackSolver::KNAPSACK_DYNAMIC_PROGRAMMING_SOLVER;
|
||||
%unignore operations_research::KnapsackSolver::KNAPSACK_MULTIDIMENSION_CBC_MIP_SOLVER; // untested
|
||||
%unignore operations_research::KnapsackSolver::KNAPSACK_MULTIDIMENSION_GLPK_MIP_SOLVER; // untested
|
||||
%unignore operations_research::KnapsackSolver::KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER;
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/memory/memory.h"
|
||||
#include "ortools/base/basictypes.h"
|
||||
#include "ortools/base/integral_types.h"
|
||||
#include "ortools/base/logging.h"
|
||||
#include "ortools/base/macros.h"
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
KNAPSACK_MULTIDIMENSION_CBC_MIP_SOLVER;
|
||||
%unignore operations_research::KnapsackSolver::
|
||||
KNAPSACK_MULTIDIMENSION_SCIP_MIP_SOLVER;
|
||||
%unignore operations_research::KnapsackSolver::
|
||||
KNAPSACK_DIVIDE_AND_CONQUER_SOLVER;
|
||||
|
||||
%include "ortools/algorithms/knapsack_solver.h"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user