18 #ifndef QBPP_EASY_SOLVER_HPP
19 #define QBPP_EASY_SOLVER_HPP
21 #include <tbb/blocked_range.h>
22 #include <tbb/parallel_for.h>
24 #include <boost/circular_buffer.hpp>
36 namespace easy_solver {
65 throw std::runtime_error(
THROW_MESSAGE(
"RandomSet: Insert variable (",
66 index,
") already in set"));
73 if (pos1 == pos2)
return;
81 throw std::runtime_error(
82 THROW_MESSAGE(
"RandomSet: Erase variable (", index,
") not in set"));
95 void print(
const std::string &prefix =
"")
const {
96 std::cout << prefix <<
" Size = " <<
var_count() <<
" : ";
100 std::cout << std::endl;
115 auto tuple_val = std::make_pair(delta, index);
116 auto result =
set_.insert(tuple_val);
117 if (!result.second) {
118 throw std::runtime_error(
THROW_MESSAGE(
"MinSet: Insert variable (", index,
119 ") already in set"));
124 auto pair_val = std::make_pair(delta, index);
125 auto result =
set_.erase(pair_val);
127 throw std::runtime_error(
128 THROW_MESSAGE(
"MinSet: Erase variable (", index,
") not in set"));
134 void print(
const std::string &prefix)
const {
136 for (
auto &[val, i] :
set_) {
137 std::cout <<
"(" << i <<
"," << val <<
")";
139 std::cout << std::endl;
170 void print(
const std::string &prefix)
const {
205 }
while (
has(index));
210 std::cout <<
"Tabu list:";
212 std::cout <<
" " << i;
214 std::cout << std::endl;
237 std::optional<double>
set_if_better(
const std::string &solver_name);
246 [[maybe_unused]]
vindex_t flip_index,
247 [[maybe_unused]]
vindex_t update_delta_index) {}
250 [[maybe_unused]]
vindex_t flip_index,
251 [[maybe_unused]]
vindex_t update_delta_index) {}
308 void search(
size_t iteration);
312 std::cout <<
"(" << i <<
"," <<
delta_[i] <<
")";
314 std::cout << std::endl;
328 : std::thread::hardware_concurrency()};
347 std::shared_ptr<qbpp::SolHolder> sol_holder_ptr =
nullptr)
389 std::cout <<
"TTS = " << std::fixed << std::setprecision(3)
390 << std::setfill(
'0') << tts
391 <<
"s Energy = " << sol.
get_energy() << std::endl;
403 :
Sol(easy_solver.get_quad_model()),
404 easy_solver_(easy_solver),
406 neg_set_(var_count()),
407 sol_holder_ptr_(easy_solver.get_sol_holder_ptr()) {
415 throw std::out_of_range(
428 static_cast<energy_t>((2 *
get(index) - 1) * (2 *
get(k) - 1) * coeff);
467 for (
vindex_t i = 0; i < iteration; ++i) {
477 if (
get(i) != destination.
get(i)) {
485 if (
get(pair.first) != destination.
get(pair.first)) {
486 to_be_flipped.
erase(pair.first,
delta_[pair.first]);
493 if (
get(pair.first) != destination.
get(pair.first))
501 const std::string &solver_name) {
502 std::optional<double> tts =
504 if (tts.has_value()) {
513 std::min(easy_solver.get_quad_model().var_count() / 2,
518 }
else if (
delta_[i] > 0) {
526 for (
vindex_t i = 0; i < iteration; ++i) {
527 std::optional<vindex_t> flip_index = std::nullopt;
531 flip_index = min_index;
543 throw std::runtime_error(
THROW_MESSAGE(
"Unexpected error."));
546 flip_index = candidate;
550 if (!flip_index.has_value()) {
554 flip(flip_index.value());
565 const size_t min_flip_count = 100;
567 size_t max_flip_count = (
var_count() / 2);
569 double k = std::pow(
static_cast<double>(max_flip_count) / min_flip_count,
572 static_cast<size_t>(min_flip_count * std::pow(k, thread_id));
573 if (max_flip_count < min_flip_count) max_flip_count = min_flip_count;
576 size_t random_flip_count = 1;
581 pos_min_sol_delta.
search(max_flip_count);
586 random_flip_count = (random_flip_count + 1) % (max_flip_count / 2);
587 if (random_flip_count == 0) random_flip_count = 1;
589 random_flip_count = 1;
598 tbb::parallel_for(
size_t(0),
static_cast<size_t>(
thread_count_),
vindex_t var_count() const
size_t term_count(vindex_t deg) const
const std::vector< std::vector< std::pair< vindex_t, coeff_t > > > & get_quadratic() const
const std::vector< coeff_t > & get_linear() const
const std::vector< vindex_t > & get_degree() const
vindex_t var_count() const
const QuadModel quad_model_
energy_t get_energy() const
std::optional< energy_t > energy_
energy_t comp_energy() const
impl::BitVector bit_vector_
var_val_t get(vindex_t index) const
const std::optional< energy_t > get_target_energy() const
const std::shared_ptr< qbpp::SolHolder > sol_holder_ptr_
const qbpp::QuadModel quad_model_
EasySolver(const qbpp::QuadModel &quad_model, std::shared_ptr< qbpp::SolHolder > sol_holder_ptr=nullptr)
const std::shared_ptr< qbpp::SolHolder > get_sol_holder_ptr() const
void single_search(size_t thread_id)
std::optional< energy_t > target_energy_
vindex_t var_count() const
virtual ~EasySolver()=default
std::mutex callback_mutex_
std::optional< energy_t > prev_energy_
const qbpp::QuadModel & get_quad_model() const
void set_thread_count(unsigned int count)
std::optional< uint32_t > time_limit_
void set_target_energy(energy_t energy)
void enable_default_callback()
const std::optional< uint32_t > get_time_limit() const
virtual void callback(const qbpp::Sol &sol, double tts) const
size_t get_thread_count()
void set_time_limit(uint32_t limit)
bool enable_default_callback_
qbpp::Sol get_sol() const
vindex_t var_count() const
std::set< std::pair< energy_t, vindex_t > > ValIndexMap
vindex_t get_first() const
void erase(vindex_t index, energy_t delta)
void insert(vindex_t index, energy_t delta)
void print(const std::string &prefix) const
void before_delta_updated(vindex_t, vindex_t k) override
void after_delta_updated(vindex_t, vindex_t k) override
vindex_t pos_count() const
PosMinSolDelta(const EasySolver &easy_solver)
virtual ~PosMinSolDelta()=default
void search(size_t iteration)
vindex_t select_at_random() const
void erase(vindex_t index, energy_t delta)
void print(const std::string &prefix) const
void insert(vindex_t index, energy_t delta)
vindex_t var_count() const
RandomMinSet(vindex_t size)
vindex_t get_first() const
bool has(vindex_t index) const
void insert(vindex_t index)
std::vector< vindex_t > position_
void print(const std::string &prefix="") const
vindex_t select_at_random() const
std::vector< vindex_t > variables_
void swap(vindex_t pos1, vindex_t pos2)
void erase(vindex_t index)
vindex_t var_count() const
bool has(vindex_t index) const
std::shared_ptr< qbpp::SolHolder > sol_holder_ptr_
SolDelta(const EasySolver &easy_solver)
energy_t get_delta(vindex_t i) const
const EasySolver & easy_solver_
vindex_t neg_count() const
virtual void after_delta_updated([[maybe_unused]] vindex_t flip_index, [[maybe_unused]] vindex_t update_delta_index)
virtual ~SolDelta()=default
virtual void flip(vindex_t index)
std::vector< energy_t > delta_
virtual void before_delta_updated([[maybe_unused]] vindex_t flip_index, [[maybe_unused]] vindex_t update_delta_index)
std::optional< double > set_if_better(const std::string &solver_name)
void random_flip(size_t iteration)
void move_to(qbpp::Sol destination)
const vindex_t tabu_size_
virtual ~TabuSolDelta()=default
bool tabu_has(vindex_t index) const
vindex_t non_tabu_random()
void flip(vindex_t index) override
TabuSolDelta(const EasySolver &easy_solver, vindex_t tabu_size)
void insert(vindex_t index)
Tabu(vindex_t size, vindex_t tabu_size)
vindex_t tabu_size() const
bool has(vindex_t index) const
boost::circular_buffer< vindex_t > tabu_list
impl::BitVector variables_
vindex_t non_tabu_random()
bool get(vindex_t index) const
void flip(vindex_t index)
void set(vindex_t index, bool value)
Generates a QUBO Expression for the Graph Coloring Problem using QUBO++ library.
const vindex_t vindex_limit
QUBO++, a C++ library for generating expressions for binary and spin variables.
#define THROW_MESSAGE(...)
A miscellaneous library used for sample programs of the QUBO++ library.