dither 0.1.5 → 0.2.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,451 @@
1
+ /*
2
+ *
3
+ * Copyright (C) 2015 Jason Gowan
4
+ * All rights reserved.
5
+ *
6
+ * This software may be modified and distributed under the terms
7
+ * of the BSD license. See the LICENSE file for details.
8
+ */
9
+
10
+ #include "ipog.h"
11
+ #include <forward_list>
12
+ #include <iterator>
13
+ #include <utility>
14
+ #include <tuple>
15
+ #include <limits.h>
16
+
17
+ namespace dither {
18
+
19
+ Ipog::~Ipog() {
20
+ if(constraint_handler != NULL) {
21
+ delete constraint_handler;
22
+ }
23
+ }
24
+
25
+ Ipog::Ipog() {
26
+ t_ = 2;
27
+ }
28
+
29
+ Ipog::Ipog(const unsigned int t) {
30
+ t_ = t;
31
+ }
32
+
33
+ void Ipog::init_bound() {
34
+ using dither::product;
35
+ dtest_case tmp;
36
+
37
+ product(bound_, tmp, input_params_.begin(), input_params_.begin() + t_);
38
+ auto size = param_cache_.size();
39
+ for (auto it = bound_.begin(); it != bound_.end(); ++it) {
40
+ (*it).resize(size, -1);
41
+ (*it).shrink_to_fit();
42
+ }
43
+ bound_.remove_if([this](dtest_case& a) { return has_previously_tested(a); });
44
+
45
+ merge_scratch_.resize(param_cache_.size(), -1);
46
+
47
+ if(constraints.size() > 0) {
48
+ for(auto it = param_cache_.cbegin(); it != param_cache_.cend(); ++it) {
49
+ const dval tmp = (*it).size() - 1;
50
+ ranges.push_back(tmp);
51
+ }
52
+ constraint_handler = new SimpleConstraintHandler(ranges, constraints);
53
+ } else {
54
+ constraint_handler = new BaseConstraintHandler();
55
+ }
56
+ }
57
+
58
+ std::forward_list<std::vector<param>> Ipog::cover(const int k) {
59
+ std::vector<int> input(k);
60
+ for (std::size_t i = 0; i < k; i++) {
61
+ input[i] = i;
62
+ }
63
+
64
+ std::forward_list<std::vector<int>> output;
65
+ combinations(t_ - 1, input, output);
66
+ std::forward_list<std::vector<std::vector<param>>> product_input;
67
+ const std::vector<param> k_param = param_cache_[k];
68
+ for (auto it = output.begin(); it != output.end(); ++it) {
69
+ std::vector<std::vector<param>> param_tuple;
70
+ (*it).push_back(k);
71
+ for (auto iit = (*it).begin(); iit != (*it).end(); ++iit) {
72
+ auto vals = param_cache_[*iit];
73
+ param_tuple.push_back(vals);
74
+ }
75
+ product_input.push_front(param_tuple);
76
+ }
77
+
78
+ std::forward_list<std::vector<param>> coverage;
79
+ for (auto it = product_input.begin(); it != product_input.end(); ++it) {
80
+ std::vector<param> tmp;
81
+ std::vector<std::vector<param>> x = *it;
82
+ product2(coverage, tmp, (*it).cbegin(), (*it).cend());
83
+ }
84
+ coverage.remove_if([this](std::vector<param>& a) { return has_previously_tested(a); });
85
+ return coverage;
86
+ }
87
+
88
+ void Ipog::run() {
89
+ init_bound();
90
+ for (auto k = t_; k < input_params_.size(); k++) {
91
+ std::forward_list<std::vector<param>> pi = cover(k);
92
+
93
+ {
94
+ auto prev = bound_.cbefore_begin();
95
+ auto next = bound_.begin();
96
+ auto end = bound_.cend();
97
+ while (next != end) {
98
+ if (maximize_coverage(k, *next, pi) == -1) {
99
+ next = bound_.erase_after(prev);
100
+ } else {
101
+ ++prev;
102
+ ++next;
103
+ }
104
+ }
105
+ }
106
+
107
+ /* vertical extension */
108
+ for (auto pairs = pi.cbegin(); pairs != pi.cend(); ++pairs) {
109
+ const std::vector<param> &test_case = *pairs;
110
+ bool case_covered = constraint_handler->violate_constraints(test_case);
111
+
112
+ if (!case_covered) {
113
+ bool is_merged = false;
114
+ auto prev = unbound_.before_begin();
115
+ auto next = unbound_.begin();
116
+ auto end = unbound_.end();
117
+ while (next != end) {
118
+ const int merge_result = merge(k, *next, test_case);
119
+ if (merge_result == 0) {
120
+ bound_.push_front(*next);
121
+ unbound_.erase_after(prev);
122
+ is_merged = true;
123
+ break;
124
+ } else if (merge_result == 1) {
125
+ is_merged = true;
126
+ break;
127
+ }
128
+ ++prev;
129
+ ++next;
130
+ }
131
+
132
+ if (!is_merged) {
133
+ dtest_case unbound_test_case(param_cache_.size(), -1);
134
+ for (auto it = test_case.cbegin(); it != test_case.cend(); ++it) {
135
+ unbound_test_case[(*it).first] = (*it).second;
136
+ }
137
+ if (!constraint_handler->violate_constraints(unbound_test_case)) {
138
+ unbound_.push_front(unbound_test_case);
139
+ }
140
+ }
141
+ }
142
+
143
+ }
144
+ }
145
+ ground_solutions();
146
+ }
147
+
148
+ /* -1 no merge, 0 perfect merge (no unbound), 1 partial merge */
149
+ inline const int Ipog::merge(const int k, dtest_case &test_case,
150
+ const std::vector<param> &pairs) {
151
+ for (auto it = pairs.cbegin(); it != pairs.cend(); ++it) {
152
+ auto value = test_case[(*it).first];
153
+ if (!(value == -1 || value == (*it).second)) {
154
+ return -1;
155
+ }
156
+ }
157
+
158
+ std::copy(test_case.cbegin(), test_case.cend(), merge_scratch_.begin());
159
+
160
+ for (auto it = pairs.cbegin(); it != pairs.cend(); ++it) {
161
+ merge_scratch_[(*it).first] = (*it).second;
162
+ }
163
+
164
+ if (constraint_handler->violate_constraints(merge_scratch_)) {
165
+ return -1;
166
+ }
167
+
168
+ for (auto it = pairs.cbegin(); it != pairs.cend(); ++it) {
169
+ test_case[(*it).first] = (*it).second;
170
+ }
171
+
172
+ for (auto i = 0; i < k; i++) {
173
+ if (test_case[i] == -1) {
174
+ return 1;
175
+ }
176
+ }
177
+
178
+ return 0;
179
+ }
180
+
181
+ inline bool Ipog::is_covered(const dtest_case &test_case,
182
+ const std::vector<param> &params) {
183
+ for (auto param = params.cbegin(); param != params.cend(); ++param) {
184
+ if (test_case[(*param).first] != (*param).second) {
185
+ return false;
186
+ }
187
+ }
188
+ return true;
189
+ }
190
+
191
+ const int Ipog::maximize_coverage(const int k, dtest_case &test_case,
192
+ std::forward_list<std::vector<param>> &pi) {
193
+ const std::vector<param> &param_range = param_cache_[k];
194
+ int current_max = -1;
195
+ param max_param = param_range[0];
196
+ std::forward_list<std::forward_list<std::vector<param>>::iterator> covered;
197
+
198
+ for (auto it = param_range.cbegin(); it != param_range.cend(); ++it) {
199
+ std::forward_list<std::forward_list<std::vector<param>>::iterator>
200
+ tmp_covered;
201
+ const param current_param = *it;
202
+
203
+ test_case[current_param.first] = current_param.second;
204
+ if (!constraint_handler->violate_constraints(test_case)) {
205
+ int count = 0;
206
+ auto prev = pi.before_begin();
207
+ for (auto params = pi.cbegin(); params != pi.cend(); ++params) {
208
+ if (is_covered(test_case, *params)) {
209
+ tmp_covered.push_front(prev);
210
+ count++;
211
+ }
212
+ ++prev;
213
+ }
214
+
215
+ if (count > current_max) {
216
+ current_max = count;
217
+ max_param = current_param;
218
+ covered = tmp_covered;
219
+ }
220
+ }
221
+ test_case[current_param.first] = -1;
222
+ }
223
+
224
+ if (current_max == -1) {
225
+ return -1;
226
+ }
227
+
228
+ /* remove covered */
229
+ for (auto it = covered.begin(); it != covered.end(); ++it) {
230
+ pi.erase_after(*it);
231
+ }
232
+
233
+ test_case[max_param.first] = max_param.second;
234
+ return current_max;
235
+ }
236
+
237
+ void Ipog::display_raw_solution() {
238
+ /* display_header(); */
239
+ for (auto it = bound_.cbegin(); it != bound_.cend(); ++it) {
240
+ display_test_case(*it);
241
+ }
242
+ }
243
+
244
+ void Ipog::add_parameter(const std::string name, const int *terms,
245
+ const unsigned int terms_length) {
246
+ std::vector<int> tmp(terms, terms + terms_length);
247
+ std::pair<std::string, std::vector<int>> key_value(name, tmp);
248
+ int_params_.insert(key_value);
249
+ ordered_param_names_.push_back(name);
250
+ }
251
+
252
+ void Ipog::add_parameter(const std::string name, const std::string *terms,
253
+ const unsigned int terms_length) {
254
+ std::vector<std::string> tmp(terms, terms + terms_length);
255
+ std::pair<std::string, std::vector<std::string>> key_value(name, tmp);
256
+ str_params_.insert(key_value);
257
+ ordered_param_names_.push_back(name);
258
+ }
259
+
260
+ void Ipog::add_parameter(const std::string name) {
261
+ const bool arr[] = {true, false};
262
+ std::vector<bool> tmp(arr, arr + 2);
263
+ std::pair<std::string, std::vector<bool>> key_value(name, tmp);
264
+ bool_params_.insert(key_value);
265
+ ordered_param_names_.push_back(name);
266
+ }
267
+
268
+ void Ipog::init_param_cache() {
269
+ std::vector<std::tuple<std::string, int, int>> tmp;
270
+ for (auto it = int_params_.cbegin(); it != int_params_.cend(); ++it) {
271
+ if ((*it).second.size() < 1) {
272
+ continue;
273
+ }
274
+ tmp.push_back(
275
+ std::make_tuple((*it).first, DITHER_INT_T, (*it).second.size()));
276
+ }
277
+
278
+ for (auto it = str_params_.cbegin(); it != str_params_.cend(); ++it) {
279
+ if ((*it).second.size() < 1) {
280
+ continue;
281
+ }
282
+ tmp.push_back(
283
+ std::make_tuple((*it).first, DITHER_STRING_T, (*it).second.size()));
284
+ }
285
+
286
+ for (auto it = bool_params_.cbegin(); it != bool_params_.cend(); ++it) {
287
+ if ((*it).second.size() < 1) {
288
+ continue;
289
+ }
290
+ tmp.push_back(
291
+ std::make_tuple((*it).first, DITHER_BOOL_T, (*it).second.size()));
292
+ }
293
+
294
+ std::sort(tmp.begin(), tmp.end(), [](std::tuple<std::string, int, int> a,
295
+ std::tuple<std::string, int, int> b) {
296
+ return std::get<2>(a) > std::get<2>(b);
297
+ });
298
+
299
+ std::unordered_map<std::string, int> original_name_to_index;
300
+ int count = 0;
301
+ for(auto it = ordered_param_names_.cbegin(); it != ordered_param_names_.cend(); ++it, count++) {
302
+ original_name_to_index.insert({{*it, count}});
303
+ }
304
+ ordered_param_index_.resize(tmp.size());
305
+ reverse_ordered_param_index_.resize(tmp.size());
306
+
307
+ count = 0;
308
+ for (auto it = tmp.cbegin(); it != tmp.cend(); ++it, count++) {
309
+ std::vector<param> params;
310
+ std::vector<dval> dvals;
311
+ auto name = std::get<0>(*it);
312
+ auto type = std::get<1>(*it);
313
+ reverse_param_index_.insert({{count, name}});
314
+ ordered_param_index_[count] = original_name_to_index.find(name)->second;
315
+ reverse_ordered_param_index_[original_name_to_index.find(name)->second] = count;
316
+
317
+ for (dval i = 0; i < SCHAR_MAX && i < std::get<2>(*it); i++) {
318
+ param my_param;
319
+ my_param.first = count;
320
+ my_param.second = i;
321
+ my_param.name = name;
322
+ my_param.type = type;
323
+
324
+ params.push_back(my_param);
325
+ dvals.push_back(i);
326
+ }
327
+ param_cache_.push_back(params);
328
+ input_params_.push_back(dvals);
329
+ }
330
+
331
+ std::vector<dval> scratch(param_cache_.size());
332
+ for(auto it = original_previously_tested_.cbegin(); it != original_previously_tested_.cend(); ++it) {
333
+ for(std::size_t i = 0; i < scratch.size(); i++) {
334
+ scratch[reverse_ordered_param_index_[i]] = (*it)[i];
335
+ }
336
+ previously_tested_.push_back(scratch);
337
+ }
338
+
339
+ // transform constraints
340
+ for(std::size_t j = 0; j < constraints.size(); j++) {
341
+ for(std::size_t i = 0; i < scratch.size(); i++) {
342
+ scratch[reverse_ordered_param_index_[i]] = constraints[j][i];
343
+ }
344
+ std::copy(scratch.begin(), scratch.end(), constraints[j].begin());
345
+ }
346
+ }
347
+
348
+ int Ipog::size() {
349
+ return solution_size;
350
+ }
351
+
352
+ std::string *Ipog::header() {
353
+ std::string *result = new std::string[param_cache_.size()];
354
+ for (std::size_t i = 0; i < param_cache_.size(); i++) {
355
+ result[i] = reverse_param_index_[i];
356
+ }
357
+ return result;
358
+ }
359
+
360
+ void Ipog::add_constraint(const int* constraint, const unsigned int length) {
361
+ std::vector<dval> tmp(length);
362
+ std::copy(constraint, constraint+length, tmp.begin());
363
+ for(auto it = tmp.cbegin(); it != tmp.cend(); ++it) {
364
+ if((*it) > SCHAR_MAX) {
365
+ std::cerr << "WARNING: constraint value > " << SCHAR_MAX << " behavior undefined" << std::endl;
366
+ }
367
+ }
368
+ constraints.push_back(tmp);
369
+ }
370
+
371
+ void Ipog::ground_solutions() {
372
+ std::size_t solution_count = 0;
373
+ std::vector<dval> transform_scratch(param_cache_.size(), 0);
374
+
375
+ auto prev = bound_.cbefore_begin();
376
+ auto next = bound_.begin();
377
+ auto end = bound_.cend();
378
+ while (next != end) {
379
+ if (constraint_handler->violate_constraints(*next) || has_previously_tested(*next)) {
380
+ next = bound_.erase_after(prev);
381
+ } else {
382
+ transform(transform_scratch, *next);
383
+ solution_count++;
384
+ ++prev;
385
+ ++next;
386
+ }
387
+ }
388
+
389
+ while(!unbound_.empty()) {
390
+ dtest_case first = unbound_.front();
391
+ if(constraint_handler->ground(first)) {
392
+ if(!has_previously_tested(first)) {
393
+ transform(transform_scratch, first);
394
+ solution_count++;
395
+ bound_.push_front(first);
396
+ }
397
+ }
398
+ unbound_.pop_front();
399
+ }
400
+ solution_size = solution_count;
401
+ }
402
+
403
+ void Ipog::fill(int *solution) {
404
+ std::size_t i = 0;
405
+ for(auto it = bound_.cbegin(); it != bound_.cend(); ++it) {
406
+ for(auto iit = (*it).cbegin(); iit != (*it).cend(); ++iit, i++) {
407
+ solution[i] = *iit;
408
+ }
409
+ }
410
+ }
411
+
412
+ void Ipog::add_previously_tested(const int values[], const std::size_t length) {
413
+ std::vector<dval> tmp(length);
414
+ std::copy(values, values+length, tmp.begin());
415
+ original_previously_tested_.push_back(tmp);
416
+ }
417
+
418
+ inline bool Ipog::has_previously_tested(std::vector<param>& test_case) {
419
+ for(auto it = previously_tested_.cbegin(); it != previously_tested_.cend(); ++it) {
420
+ bool flag = true;
421
+ for(auto iit = test_case.cbegin(); iit != test_case.cend(); ++iit) {
422
+ if((*it)[(*iit).first] != (*iit).second) {
423
+ flag = false;
424
+ break;
425
+ }
426
+ }
427
+ if(flag) {
428
+ return true;
429
+ }
430
+ }
431
+ return false;
432
+ }
433
+
434
+ inline bool Ipog::has_previously_tested(dtest_case& test_case) {
435
+ for(auto it = previously_tested_.cbegin(); it != previously_tested_.cend(); ++it) {
436
+ if(std::equal(test_case.cbegin(), test_case.cend(), (*it).cbegin())) {
437
+ return true;
438
+ }
439
+ }
440
+ return false;
441
+ }
442
+
443
+ inline bool Ipog::has_previously_tested(const int k, dtest_case& test_case) {
444
+ for(auto it = previously_tested_.cbegin(); it != previously_tested_.cend(); ++it) {
445
+ if(std::equal(test_case.cbegin(), test_case.cbegin()+k, (*it).cbegin())) {
446
+ return true;
447
+ }
448
+ }
449
+ return false;
450
+ }
451
+ }
data/ext/dither/ipog.h ADDED
@@ -0,0 +1,128 @@
1
+ /*
2
+ *
3
+ * Copyright (C) 2015 Jason Gowan
4
+ * All rights reserved.
5
+ *
6
+ * This software may be modified and distributed under the terms
7
+ * of the BSD license. See the LICENSE file for details.
8
+ */
9
+
10
+ #ifndef IPOG_H_
11
+ #define IPOG_H_
12
+
13
+ #include <vector>
14
+ #include <iostream>
15
+ #include <forward_list>
16
+ #include <algorithm>
17
+ #include <string>
18
+ #include <unordered_map>
19
+ #include "combinations.h"
20
+ #include "dither_types.h"
21
+ #include "base_constraint_handler.h"
22
+ #include "simple_constraint_handler.h"
23
+
24
+ namespace dither {
25
+
26
+ class Ipog {
27
+ std::size_t t_;
28
+ std::vector<std::vector<dval>> input_params_;
29
+ std::vector<std::vector<param>> param_cache_;
30
+ std::forward_list<dtest_case> bound_;
31
+ std::forward_list<dtest_case> unbound_;
32
+ std::unordered_map<std::string, std::vector<int>> int_params_;
33
+ std::unordered_map<std::string, std::vector<std::string>> str_params_;
34
+ std::unordered_map<std::string, std::vector<bool>> bool_params_;
35
+ std::vector<std::string> ordered_param_names_;
36
+ std::vector<int> ordered_param_index_;
37
+ std::vector<int> reverse_ordered_param_index_;
38
+ std::unordered_map<std::string, int> param_index_;
39
+ std::unordered_map<int, std::string> reverse_param_index_;
40
+ dtest_case merge_scratch_;
41
+ BaseConstraintHandler* constraint_handler;
42
+ std::vector<std::vector<dval>> constraints;
43
+ std::vector<dval> ranges;
44
+ std::size_t solution_size;
45
+ std::vector<std::vector<dval>> original_previously_tested_;
46
+ std::vector<std::vector<dval>> previously_tested_;
47
+
48
+ inline void transform(std::vector<dval>& scratch, std::vector<dval>& test_case) {
49
+ for(std::size_t i = 0; i < test_case.size(); i++) {
50
+ scratch[ordered_param_index_[i]] = test_case[i];
51
+ }
52
+ std::copy(scratch.cbegin(), scratch.cend(), test_case.begin());
53
+ }
54
+
55
+ inline bool has_previously_tested(std::vector<param>& test_case);
56
+ inline bool has_previously_tested(dtest_case& test_case);
57
+ inline bool has_previously_tested(const int, dtest_case& test_case);
58
+
59
+ public:
60
+ Ipog();
61
+ ~Ipog();
62
+ Ipog(const unsigned int);
63
+ void set_t(const unsigned int t) { t_ = t; }
64
+ void add_parameter(const std::string, const int[], const unsigned int);
65
+ void add_parameter(const std::string, const std::string[], const unsigned int);
66
+ void add_parameter(const std::string);
67
+ void init_bound();
68
+ void init_param_cache();
69
+ void run();
70
+ int size();
71
+ std::string *header();
72
+ void ground_solutions();
73
+ inline bool is_valid() { return t_ <= param_cache_.size(); }
74
+ std::forward_list<std::vector<param>> cover(int);
75
+ const int maximize_coverage(const int, dtest_case &,
76
+ std::forward_list<std::vector<param>> &);
77
+ void add_constraint(const int[], const unsigned int);
78
+ void add_previously_tested(const int[], const std::size_t);
79
+ inline bool is_covered(const dtest_case &test_case,
80
+ const std::vector<param> &params);
81
+ inline bool is_covered(const std::vector<param> &params);
82
+ inline const int merge(const int, dtest_case &, const std::vector<param> &);
83
+ void display_raw_solution();
84
+ void fill(int[]);
85
+ inline void display_header() {
86
+ for (std::size_t i = 0; i < param_cache_.size();) {
87
+ std::cout << reverse_param_index_[i];
88
+ if (++i < param_cache_.size()) {
89
+ std::cout << ',';
90
+ }
91
+ }
92
+ std::cout << std::endl;
93
+ }
94
+
95
+ inline void display_test_case(const dtest_case &test_case) {
96
+ for (std::size_t i = 0; i < test_case.size();) {
97
+ const dval value = test_case[i];
98
+ if (value == -1) {
99
+ std::cout << '-';
100
+ if (++i < test_case.size()) {
101
+ std::cout << ',';
102
+ }
103
+ continue;
104
+ }
105
+ const param my_param = param_cache_[reverse_ordered_param_index_[i]][value];
106
+ switch (my_param.type) {
107
+ case DITHER_INT_T:
108
+ std::cout << int_params_[my_param.name][my_param.second];
109
+ break;
110
+ case DITHER_BOOL_T:
111
+ std::cout << std::boolalpha
112
+ << bool_params_[my_param.name][my_param.second];
113
+ break;
114
+ case DITHER_STRING_T:
115
+ std::cout << str_params_[my_param.name][my_param.second];
116
+ break;
117
+ }
118
+ if (++i < test_case.size()) {
119
+ std::cout << ',';
120
+ }
121
+ }
122
+ std::cout << std::endl;
123
+ }
124
+ };
125
+
126
+ }
127
+
128
+ #endif
@@ -0,0 +1,119 @@
1
+ /*
2
+ *
3
+ * Copyright (C) 2015 Jason Gowan
4
+ * All rights reserved.
5
+ *
6
+ * This software may be modified and distributed under the terms
7
+ * of the BSD license. See the LICENSE file for details.
8
+ */
9
+
10
+ #include "simple_constraint_handler.h"
11
+
12
+ namespace dither {
13
+
14
+ SimpleConstraintHandler::SimpleConstraintHandler(std::vector<dval>& ranges, std::vector<std::vector<dval>>& pconstraints) : params(ranges) {
15
+ for(auto it = pconstraints.cbegin(); it != pconstraints.cend(); ++it) {
16
+ std::vector<std::pair<std::size_t, dval>> constraint;
17
+ int i = 0;
18
+ for(auto iit = (*it).cbegin(); iit != (*it).cend(); ++iit, i++) {
19
+ if((*iit) != -1) {
20
+ constraint.push_back(std::make_pair(i, *iit));
21
+ }
22
+ }
23
+ constraints.push_back(constraint);
24
+ }
25
+ std::sort(constraints.begin(), constraints.end(), [](std::vector<std::pair<std::size_t, dval>>& a, std::vector<std::pair<std::size_t, dval>>& b) { return a.size() < b.size(); });
26
+ }
27
+
28
+ bool SimpleConstraintHandler::violate_constraints(const dtest_case &test_case) {
29
+ for(auto constraint = constraints.cbegin(); constraint != constraints.cend(); ++constraint) {
30
+ if(violate_constraint(test_case, *constraint)) {
31
+ return true;
32
+ }
33
+ }
34
+ return false;
35
+ }
36
+
37
+ inline bool SimpleConstraintHandler::violate_constraint(const dtest_case& test_case, const std::vector<std::pair<std::size_t, dval>>& constraint) {
38
+ for(auto it = constraint.cbegin(); it != constraint.cend(); ++it) {
39
+ auto value = test_case[(*it).first];
40
+ if(value == -1 || value != (*it).second) {
41
+ return false;
42
+ }
43
+ }
44
+ return true;
45
+ }
46
+
47
+ bool SimpleConstraintHandler::violate_constraints(const std::vector<param> &test_case) {
48
+ for(auto constraint = constraints.cbegin(); constraint != constraints.cend(); ++constraint) {
49
+ if(violate_constraint(test_case, *constraint)) {
50
+ return true;
51
+ }
52
+ }
53
+ return false;
54
+ }
55
+
56
+ inline bool SimpleConstraintHandler::violate_constraint(const std::vector<param>& test_case, const std::vector<std::pair<std::size_t, dval>>& constraint) {
57
+ if(test_case.size() < constraint.size()) {
58
+ return false;
59
+ }
60
+
61
+ std::size_t count = 0;
62
+ for(auto it = constraint.cbegin(); it != constraint.cend(); ++it) {
63
+ for(auto iit = test_case.cbegin(); iit != test_case.cend(); ++iit) {
64
+ if((*iit).first == (*it).first && (*iit).second == (*it).second) {
65
+ count++;
66
+ break;
67
+ }
68
+ }
69
+ }
70
+ if(count == constraint.size()) {
71
+ return true;
72
+ }
73
+ return false;
74
+ }
75
+
76
+ bool SimpleConstraintHandler::ground(dtest_case &test_case) {
77
+ std::vector<std::size_t> indexes;
78
+
79
+ // find unbound indexes
80
+ std::size_t i = 0;
81
+ for (auto it = test_case.begin(); it != test_case.end(); ++it, i++) {
82
+ if ((*it) == -1) {
83
+ indexes.push_back(i);
84
+ }
85
+ }
86
+ if(indexes.size() == 0) {
87
+ return true;
88
+ }
89
+ std::vector<dval> bound_values(indexes.size(), 0);
90
+ i = 0;
91
+
92
+ LOOP:{
93
+ do {
94
+ test_case[indexes[i]] = bound_values[i];
95
+ if(violate_constraints(test_case)) {
96
+ // try to bump a bound value... return false if no valid value
97
+ const std::size_t upper_bound = i + 1;
98
+ for(std::size_t j = 0; j < upper_bound; j++) {
99
+ auto bump_value = bound_values[i] + 1;
100
+ if(bump_value < params[indexes[i]]) {
101
+ bound_values[i] = bump_value;
102
+ goto LOOP;
103
+ }
104
+
105
+ // unwind
106
+ bound_values[i] = 0;
107
+ test_case[indexes[i]] = -1;
108
+ i--;
109
+ }
110
+
111
+ return false;
112
+ }
113
+ i++;
114
+ }while(i < indexes.size());
115
+ }
116
+
117
+ return true;
118
+ }
119
+ }