Infrared
Loading...
Searching...
No Matches
assignment.hpp
1#ifndef INFRARED_ASSIGNMENT_HPP
2#define INFRARED_ASSIGNMENT_HPP
3
4/*
5 * InfraRed --- A generic engine for Boltzmann sampling over constraint networks
6 * (C) Sebastian Will, 2018
7 *
8 * This file is part of the InfraRed source code.
9 *
10 * InfraRed provides a generic framework for tree decomposition-based
11 * Boltzmann sampling over constraint networks
12 */
13
20#include <vector>
21#include <limits>
22#include <cassert>
23#include <iostream>
24#include <functional>
25
26
27#include "finite_domain.hpp"
28
29namespace ired {
30 template<class FeatureNetwork>
32
33 //@brief Vector type selector "no bit vector"
40 template<class T>
42 using type = std::vector<T>;
43 };
44
45 template<>
46 struct vector_nbv_sel<bool> {
47 using type = std::vector<char>;
48 };
49
50
76 class Assignment {
77 public:
78
81
83 using var_idx_t = int;
84
86 using var_value_t = int;
87
88 public:
97 explicit
99 :values_(domains.size()), domains_(domains)
100 {
101 for ( int i=0; i < values_.size(); ++i ) {
102 set_undet(i);
103 }
104 }
105
111 const auto &
112 operator [](var_idx_t i) const {return values_[i];}
113
119 auto &
120 operator [](var_idx_t i) {return values_[i];}
121
125 const auto &
126 values() const { return values_; }
127
131 auto
132 size() const { return values_.size(); }
133
138 auto
139 is_det(var_idx_t i) const {
140 return values_[i] != domains_[i].undet();
141 }
142
147 void
149 values_[i] = domains_[i].undet();
150 }
151
156 void
157 set_undet(const std::vector<var_idx_t> &xs) {
158 for (auto x: xs) {
159 set_undet(x);
160 }
161 }
162
167 void
169 domains_[i].inc( values_[i] );
170 }
171
181 template<class FeatureNetwork>
182 auto
183 make_iterator(const std::vector<var_idx_t> &vars,
184 const FeatureNetwork &cn,
185 const std::vector<const typename FeatureNetwork::constraint_t *> &
186 constraints,
187 const std::vector<const typename FeatureNetwork::function_t *> &
188 functions,
189 const typename FeatureNetwork::fun_value_t & initial_value
190 );
191
198 template<class Function, class EP>
199 auto
200 eval_determined(const std::vector<const Function *> &functions, const EP &) {
201 // for each function
202 auto x = EP::one();
203 for( const auto &f : functions ) {
204 if ( all_of( f->vars().begin(), f->vars().end(),
205 [&] (auto v) { return is_det(v); } ) )
206 {
207 // evaluate f
208 x = EP::mul( x, (*f)(*this) );
209 }
210 }
211 return x;
212 }
213
214 private:
219 std::vector<var_value_t> values_;
220 const FiniteDomainVector &domains_;
221 }; // end class Assignment
222
223
224
241 template<class FeatureNetwork>
243 public:
248 using fun_value_t = typename ep::fun_value_t;
249 using function_t = typename ep::function_t;
250 using constraint_t = typename ep::constraint_t;
251
273 const std::vector<var_idx_t> &vars,
274 const FeatureNetwork &cn,
275 const std::vector<const constraint_t *> &constraints,
276 const std::vector<const function_t *> &functions,
277 const fun_value_t &initial_value
278 )
279 : a_(a),
280 vars_(vars),
281 domains_(cn.domains()),
282 initial_value_(initial_value),
283 top_(0),
284 stage1_size_(-1) // init without staging
285 {
286 a_.set_undet( vars_ );
287
288 constraint_board_ = create_board<constraint_t>(constraints);
289 function_board_ = create_board<function_t>(functions);
290
291 this->reset();
292 }
293
297 void reset() {
298 a_.set_undet( vars_ );
299
300 // set up value stack
301 value_stack_.resize(vars_.size()+1);
302
303 value_stack_[0] = initial_value_;
304
305 if ( value_stack_[0]==ep::zero() ) {
306 top_=-1;
307 return;
308 }
309
310 if ( vars_.size() > 0 ) {
311 this -> operator ++();
312 }
313 }
314
322 auto
324 assert(top_>=0);
325 assert( ( top_==0 && vars_.size()==0 )
326 || top_ == static_cast<int>(vars_.size())-1 );
327 return value_stack_[vars_.size()];
328 }
329
341 void
342 register_finish_stage2_hook(int stage1_size, const std::function<void()> &hook) {
343 stage1_size_ = stage1_size;
344 finish_stage2_hook_ = hook;
345 }
346
347
352 const auto &
354 /*
355 * Invariants:
356 * top_ points to the next to be enumerated variable in vars_
357 * top_==-1 means termination
358 * otherwise a_[vars_[top_]] is valid,
359 * if a_[vars_[top_]] < domsize_[vars_[top_]],
360 *
361 * value_stack_[i] is the product of all function
362 * values, where the functions depend only on variables up
363 * to and including vars_[i-1], for 1<=i<=top_. If
364 * vars[top_] is undetermined, then value_stack_[top_+1] is undefined.
365 *
366 * value_stack_[0] is always ep::one()
367 */
368
369 //terminate if stack is empty
370 if ( top_ < 0 ) {
371 return *this;
372 }
373 while (top_ < static_cast<int>(vars_.size())) {
374 assert(top_>=0);
375
376 // determine the next valid candidate partial assignment
377 do {
378 a_.inc( vars_[top_] );
379
380 while ( a_[vars_[top_]] > domains_[vars_[top_]].ub() ) {
381
382 // call hook after each complete enum of stage2
383 // (i.e. at return to stage1)
384 if (top_ == stage1_size_) {
385 finish_stage2_hook_();
386 }
387
388 a_.set_undet( vars_[top_] );
389
390 top_ --;
391 if ( top_ < 0 ) {
392 // terminate if stack is empty
393 return *this;
394 }
395 a_.inc( vars_[top_] );
396 }
397
398 //repeat until the top variable has a valid value
399
400 if ( ! constraints_valid_at_top() )
401 continue;
402
403 if ( ! functions_valid_at_top() )
404 continue;
405
406 eval_at_top();
407 if ( value_stack_[top_+1] == ep::zero() )
408 continue;
409
410 break;
411 } while (true);
412 top_++;
413 }
414
415 // this test is required for the case where diff.size()==0
416 if (top_ == stage1_size_) {
417 finish_stage2_hook_();
418 }
419
420 top_--;
421 assert( top_ == static_cast<int>(vars_.size())-1 );
422
423 return *this;
424 }
425
428 bool finished() {
429 return top_ < 0;
430 }
431
432 private:
433 template<class Function>
434 struct board_t { using type = std::vector<std::vector<const Function *>>; };
435
436 assignment_t &a_;
437 const std::vector<var_idx_t> &vars_;
438 const FiniteDomainVector &domains_;
439 const fun_value_t initial_value_;
440 typename board_t<constraint_t>::type constraint_board_;
441 typename board_t<function_t>::type function_board_;
442 int top_;
443
444
445 using value_stack_t = typename vector_nbv_sel<fun_value_t>::type;
446 value_stack_t value_stack_;
447
448 int stage1_size_;
449 std::function<void()> finish_stage2_hook_;
450
451
453 bool
454 constraints_valid_at_top() const {
455 assert(top_ < (int)vars_.size());
456
457 //check all constraints at top_
458 const auto &constraints = constraint_board_[top_];
459 return all_of( constraints.begin(), constraints.end(),
460 [&](auto c) { return (*c)(a_); } );
461 }
462
468 bool
469 functions_valid_at_top() const {
470 assert(top_ < (int)vars_.size());
471
472 //check all constraints at top_
473 const auto &functions = function_board_[top_];
474 return all_of( functions.begin(), functions.end(),
475 [&](auto f) { return ! f->guaranteed_zero(a_); } );
476 }
477
480 void
481 eval_at_top() {
482 assert(top_>=0);
483 auto x = value_stack_[top_];
484 for ( const auto f: function_board_[top_] ) {
485 x = ep::mul( x, (*f)(a_) );
486 }
487
488 value_stack_[top_+1] = x;
489 }
490
503 template<class Function>
504 auto
505 create_board(const std::vector<const Function *> &functions) {
506
507 typename board_t<Function>::type board(vars_.size());
508
509 // for each function
510 for( const auto &f : functions ) {
511
512 // find 'last' undetermined variable of f
513 // by iterating over the variables of f
514 int last_idx = -1;
515 for ( auto var : f->vars() ) {
516 // skip determined variables of f
517 if ( a_.is_det(var) ) continue;
518
519 // determine maximum index of this variable (in the order of the variables
520 // of the assignment iterator)
521 // determine the index of the constraint variable in the iterator variables
522 auto idx = std::distance(vars_.begin(), find(vars_.begin(),vars_.end(),var));
523 // if the undetermined variable does not occur, then it will not be fixed during this enumeration --> we will not register f
524
525 // determine maximum as last_idx
526 last_idx = std::max(last_idx, static_cast<int>(idx));
527 }
528
529 // here, ignore f if either it does not have undetermined variables, or
530 // it has undetermined vars, but at least one is outside of the iterator vars
531 if ( 0 <= last_idx && last_idx < static_cast<int>(vars_.size()) ) {
532 // register f at last_idx
533 board[last_idx].push_back( f );
534 }
535 }
536 return board;
537 }
538 }; // end class AssignmentIterator
539
540 // const int Assignment::Undetermined;
541
542 template<class CN>
543 auto
544 Assignment::make_iterator(const std::vector<var_idx_t> &vars,
545 const CN &cn,
546 const std::vector<const typename CN::constraint_t *> &
547 constraints,
548 const std::vector<const typename CN::function_t *> &
549 functions,
550 const typename CN::fun_value_t & initial_value
551 ) {
552 return AssignmentIterator<CN>(*this,
553 vars,
554 cn,
555 constraints,
556 functions,
557 initial_value);
558 }
559
560}
561
562#endif
Iterate over the assignments of a subset of variables.
Definition assignment.hpp:242
auto value()
get evaluation according to functions
Definition assignment.hpp:323
typename ep::constraint_t constraint_t
Definition assignment.hpp:250
const auto & operator++()
Next valid partial assignment.
Definition assignment.hpp:353
assignment_t::var_idx_t var_idx_t
Definition assignment.hpp:245
AssignmentIterator(assignment_t &a, const std::vector< var_idx_t > &vars, const FeatureNetwork &cn, const std::vector< const constraint_t * > &constraints, const std::vector< const function_t * > &functions, const fun_value_t &initial_value)
constructor
Definition assignment.hpp:272
bool finished()
Check for termination.
Definition assignment.hpp:428
Assignment assignment_t
Definition assignment.hpp:244
typename ep::fun_value_t fun_value_t
Definition assignment.hpp:248
assignment_t::var_value_t var_value_t
Definition assignment.hpp:246
typename FeatureNetwork::evaluation_policy_t ep
Definition assignment.hpp:247
typename ep::function_t function_t
Definition assignment.hpp:249
void reset()
Reset iterator.
Definition assignment.hpp:297
void register_finish_stage2_hook(int stage1_size, const std::function< void()> &hook)
register hook to run after finishing stage 2 enumeration
Definition assignment.hpp:342
A (partial) assignment of variables to values.
Definition assignment.hpp:76
int var_value_t
variable value type
Definition assignment.hpp:86
auto eval_determined(const std::vector< const Function * > &functions, const EP &)
evaluate constraints/functions where all variables are already determined
Definition assignment.hpp:200
auto is_det(var_idx_t i) const
check whether variable is determined
Definition assignment.hpp:139
Assignment(const FiniteDomainVector &domains)
construct empty
Definition assignment.hpp:98
int var_idx_t
variable index type
Definition assignment.hpp:83
void set_undet(var_idx_t i)
set variables to undetermined
Definition assignment.hpp:148
auto make_iterator(const std::vector< var_idx_t > &vars, const FeatureNetwork &cn, const std::vector< const typename FeatureNetwork::constraint_t * > &constraints, const std::vector< const typename FeatureNetwork::function_t * > &functions, const typename FeatureNetwork::fun_value_t &initial_value)
make sub-assignment iterator
void inc(var_idx_t i)
increment value of variable
Definition assignment.hpp:168
void set_undet(const std::vector< var_idx_t > &xs)
set variables to undetermined
Definition assignment.hpp:157
auto size() const
get number of variables in assignment
Definition assignment.hpp:132
const auto & values() const
get values (read only)
Definition assignment.hpp:126
const auto & operator[](var_idx_t i) const
get value of a variable (read only)
Definition assignment.hpp:112
the feature network
Definition feature_network.hpp:208
FunValue fun_value_t
Definition feature_network.hpp:211
EvaluationPolicy evaluation_policy_t
Definition feature_network.hpp:217
Definition assignment.hpp:29
std::vector< FiniteDomain > FiniteDomainVector
Definition finite_domain.hpp:148
std::vector< char > type
Definition assignment.hpp:47
Definition assignment.hpp:41
std::vector< T > type
Definition assignment.hpp:42