3#ifndef LALA_POWER_SPLIT_STRATEGY_HPP
4#define LALA_POWER_SPLIT_STRATEGY_HPP
6#include "battery/vector.hpp"
7#include "battery/shared_ptr.hpp"
9#include "lala/logic/logic.hpp"
11#include "lala/abstract_deps.hpp"
37 default:
return "unknown";
41template <
class StringType>
43 if(str ==
"input_order") {
46 else if(str ==
"first_fail") {
49 else if(str ==
"anti_first_fail") {
52 else if(str ==
"smallest") {
55 else if(str ==
"largest") {
82 default:
return "unknown";
86template <
class StringType>
91 else if(str ==
"max") {
94 else if(str ==
"median") {
97 else if(str ==
"split") {
100 else if(str ==
"reverse_split") {
109template <
class Allocator>
116 battery::vector<AVar, Allocator>
vars;
132 return vars.get_allocator();
135 template <
class StrategyType2>
139 template <
class Alloc2>
143template <
class A,
class Allocator =
typename A::allocator_type>
154 constexpr static const bool sequential = sub_type::sequential;
164 constexpr static const char*
name =
"SplitStrategy";
166 template <
class Alloc>
183 template<
class SplitSnapshot>
191 template <
class Alloc2>
194 template <
class A2,
class Alloc2>
198 using universe_type =
typename A::universe_type;
199 using LB =
typename universe_type::LB;
200 using UB =
typename universe_type::UB;
205 battery::vector<StrategyType<allocator_type>,
allocator_type> strategies;
206 int current_strategy;
207 int next_unassigned_var;
209 CUDA const battery::vector<AVar, allocator_type>& current_vars()
const {
210 return strategies[current_strategy].vars;
213 CUDA NI void move_to_next_unassigned_var() {
214 while(current_strategy < strategies.size()) {
215 const auto& vars = current_vars();
216 int n = vars.empty() ? a->vars() : vars.size();
217 while(next_unassigned_var <
n) {
218 universe_type
v = (*a)[vars.empty() ? next_unassigned_var : vars[next_unassigned_var].vid()];
219 if(
v.lb().value() !=
v.ub().value()) {
222 next_unassigned_var++;
225 next_unassigned_var = 0;
229 template <
class MapFunction>
231 int i = next_unassigned_var;
233 auto best =
op((*a)[vars.empty() ?
i : vars[
i].
vid()]);
234 int n = vars.empty() ? a->vars() : vars.size();
235 for(++
i;
i <
n; ++
i) {
236 const auto&
u = (*a)[vars.empty() ?
i : vars[
i].vid()];
237 if(
u.lb().value() !=
u.ub().value()) {
238 if(best.meet(
op(
u))) {
247 const auto&
strat = strategies[current_strategy];
248 const auto& vars =
strat.vars;
249 switch(
strat.var_order) {
255 default:
printf(
"BUG: unsupported variable order strategy\n");
assert(
false);
return AVar{};
261 if((
u.is_top() && U::preserve_top) || (
u.is_bot() && U::preserve_bot)) {
263 printf(
"%% WARNING: Cannot currently branch on unbounded variables.\n");
268 using branch_vector = battery::vector<sub_tell_type, allocator_type>;
282 return make_branch(x,
LEQ,
GT,
u);
285 printf(
"%% WARNING: The subdomain does not support the underlying search strategy.\n");
296 atype(atype), var_aty(var_aty), a(a), current_strategy(0), next_unassigned_var(0), strategies(
alloc)
301 : atype(
other.atype),
302 var_aty(
other.var_aty),
305 current_strategy(
other.current_strategy),
306 next_unassigned_var(
other.next_unassigned_var)
314 return strategies.get_allocator();
317 template <
class Alloc2 = allocator_type>
322 template <
class Alloc2 = allocator_type>
324 while(strategies.size() >
snap.num_strategies) {
325 strategies.pop_back();
327 current_strategy =
snap.current_strategy;
328 next_unassigned_var =
snap.next_unassigned_var;
333 current_strategy = 0;
334 next_unassigned_var = 0;
338 template <
bool diagnose = false,
class F,
class Env,
class Alloc2>
341 &&
f.eseq().size() >= 2
342 &&
f.esig() ==
"search"
343 &&
f.eseq()[0].is(F::ESeq) &&
f.eseq()[0].eseq().size() == 0
344 &&
f.eseq()[1].is(F::ESeq) &&
f.eseq()[1].eseq().size() == 0))
346 RETURN_INTERPRETATION_ERROR(
"SplitStrategy can only interpret predicates of the form `search(input_order, indomain_min, x1, ..., xN)`.");
362 printf(
"WARNING: indomain_median is not supported since we use interval domain. It is replaced by SPLIT");
370 for(
int i = 2;
i <
f.eseq().size(); ++
i) {
371 if(
f.eseq(
i).is(F::LV)) {
377 else if(
f.eseq(
i).is(F::V)) {
378 strat.vars.push_back(
f.eseq(
i).v());
381 RETURN_INTERPRETATION_ERROR(
"The predicate `search` only supports variables or constants, but an expression containing a variable was passed to it.");
386 tell.push_back(std::move(
strat));
390 template <IKind kind,
bool diagnose = false,
class F,
class Env,
class I>
392 static_assert(
kind == IKind::TELL);
400 template <
class Alloc2>
403 for(
int i = 0;
i <
t.size(); ++
i) {
404 strategies.push_back(
t[
i]);
420 move_to_next_unassigned_var();
421 if(current_strategy < strategies.size()) {
422 AVar x = select_var();
424 switch(strategies[current_strategy].val_order) {
440 return strategies.size();
445 for(
int i = strategies.size() - 1;
i > 0; --
i) {
446 strategies[
i] = strategies[
i-1];
448 battery::vector<AVar, allocator_type> vars(strategies.get_allocator());
453 current_strategy = std::max(1, current_strategy);
454 next_unassigned_var = 0;
Definition split_strategy.hpp:144
static constexpr const bool is_abstract_universe
Definition split_strategy.hpp:153
static constexpr const bool sequential
Definition split_strategy.hpp:154
CUDA allocator_type get_allocator() const
Definition split_strategy.hpp:313
battery::vector< StrategyType< Alloc2 >, Alloc2 > tell_type
Definition split_strategy.hpp:192
CUDA SplitStrategy(const SplitStrategy< A2, Alloc2 > &other, AbstractDeps< Allocators... > &deps)
Definition split_strategy.hpp:300
Allocator allocator_type
Definition split_strategy.hpp:146
CUDA void push_eps_strategy(VariableOrder var_order, ValueOrder val_order)
Definition split_strategy.hpp:443
static constexpr const bool is_totally_ordered
Definition split_strategy.hpp:155
sub_type::template tell_type< allocator_type > sub_tell_type
Definition split_strategy.hpp:149
CUDA local::B deduce(const tell_type< Alloc2 > &t)
Definition split_strategy.hpp:401
A sub_type
Definition split_strategy.hpp:147
CUDA NI bool interpret_tell(const F &f, Env &env, tell_type< Alloc2 > &tell, IDiagnostics &diagnostics) const
Definition split_strategy.hpp:339
typename sub_type::allocator_type sub_allocator_type
Definition split_strategy.hpp:148
static constexpr const bool preserve_concrete_covers
Definition split_strategy.hpp:162
static constexpr const bool preserve_join
Definition split_strategy.hpp:159
CUDA void skip_eps_strategy()
Definition split_strategy.hpp:452
static constexpr const char * name
Definition split_strategy.hpp:164
static constexpr const bool preserve_bot
Definition split_strategy.hpp:156
Branch< sub_tell_type, allocator_type > branch_type
Definition split_strategy.hpp:150
CUDA snapshot_type< Alloc2 > snapshot(const Alloc2 &alloc=Alloc2()) const
Definition split_strategy.hpp:318
CUDA const auto & strategies_() const
Definition split_strategy.hpp:457
CUDA AType aty() const
Definition split_strategy.hpp:309
static constexpr const bool preserve_meet
Definition split_strategy.hpp:160
CUDA SplitStrategy(AType atype, AType var_aty, abstract_ptr< A > a, const allocator_type &alloc=allocator_type())
Definition split_strategy.hpp:295
CUDA void reset()
Definition split_strategy.hpp:332
CUDA bool interpret(const F &f, Env &env, I &intermediate, IDiagnostics &diagnostics) const
Definition split_strategy.hpp:391
CUDA void restore(const snapshot_type< Alloc2 > &snap)
Definition split_strategy.hpp:323
CUDA NI branch_type split()
Definition split_strategy.hpp:416
static constexpr const bool preserve_top
Definition split_strategy.hpp:157
CUDA size_t num_strategies() const
Definition split_strategy.hpp:439
static constexpr const bool injective_concretization
Definition split_strategy.hpp:161
const char * string_of_value_order(ValueOrder order)
Definition split_strategy.hpp:75
VariableOrder
Definition split_strategy.hpp:16
std::optional< ValueOrder > value_order_of_string(const StringType &str)
Definition split_strategy.hpp:87
std::optional< VariableOrder > variable_order_of_string(const StringType &str)
Definition split_strategy.hpp:42
ValueOrder
Definition split_strategy.hpp:63
const char * string_of_variable_order(VariableOrder order)
Definition split_strategy.hpp:30
Definition split_strategy.hpp:167
snapshot_type< Alloc > & operator=(const snapshot_type< Alloc > &)=default
snapshot_type< Alloc > & operator=(snapshot_type< Alloc > &&)=default
snapshot_type(snapshot_type< Alloc > &&)=default
int next_unassigned_var
Definition split_strategy.hpp:170
CUDA snapshot_type(const SplitSnapshot &other, const Alloc &)
Definition split_strategy.hpp:184
snapshot_type(const snapshot_type< Alloc > &)=default
size_t num_strategies
Definition split_strategy.hpp:168
CUDA snapshot_type(size_t num_strategies, int current_strategy, int next_unassigned_var)
Definition split_strategy.hpp:172
int current_strategy
Definition split_strategy.hpp:169
Definition split_strategy.hpp:110
StrategyType(const StrategyType< Allocator > &)=default
ValueOrder val_order
Definition split_strategy.hpp:114
CUDA StrategyType(const StrategyType2 &other, const Allocator &alloc=Allocator{})
Definition split_strategy.hpp:136
Allocator allocator_type
Definition split_strategy.hpp:111
StrategyType & operator=(StrategyType< Allocator > &&)=default
CUDA StrategyType(const Allocator &alloc=Allocator{})
Definition split_strategy.hpp:118
StrategyType(StrategyType< Allocator > &&)=default
VariableOrder var_order
Definition split_strategy.hpp:113
CUDA StrategyType(VariableOrder var_order, ValueOrder val_order, battery::vector< AVar, Allocator > &&vars)
Definition split_strategy.hpp:127
StrategyType & operator=(const StrategyType< Allocator > &)=default
battery::vector< AVar, Allocator > vars
Definition split_strategy.hpp:116
CUDA allocator_type get_allocator() const
Definition split_strategy.hpp:131