A set of benchmarks to compare a new prototype MiniZinc implementation
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
3/*
4 * Main authors:
5 * Guido Tack <guido.tack@monash.edu>
6 */
7
8/* This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11
12#ifndef __MINIZINC_ITER_HH__
13#define __MINIZINC_ITER_HH__
14
15#include <minizinc/values.hh>
16
17#include <cmath>
18
19#ifdef _MSC_VER
20#define _CRT_SECURE_NO_WARNINGS
21#undef ERROR // MICROsoft.
22#undef min
23#undef max
24#endif
25
26namespace MiniZinc {
27namespace Ranges {
28
29/**
30 * \brief Base for range iterators with explicit min and max
31 *
32 * The iterator provides members \a mi and \a ma for storing the
33 * limits of the currently iterated range. The iterator
34 * continues until \a mi becomes greater than \a ma. The member function
35 * finish does exactly that.
36 *
37 * \ingroup FuncIterRanges
38 */
39
40template <class Val>
41class MinMax {
42protected:
43 /// Minimum of current range
44 Val mi;
45 /// Maximum of current range
46 Val ma;
47 /// %Set range such that iteration stops
48 void finish(void);
49
50public:
51 /// \name Constructors and initialization
52 //@{
53 /// Default constructor
54 MinMax(void);
55 /// Initialize with range \a min to \a max
56 MinMax(Val min, Val max);
57 //@}
58
59 /// \name Iteration control
60 //@{
61 /// Test whether iterator is still at a range or done
62 bool operator()(void) const;
63 //@}
64
65 /// \name Range access
66 //@{
67 /// Return smallest value of range
68 Val min(void) const;
69 /// Return largest value of range
70 Val max(void) const;
71 /// Return width of range (distance between minimum and maximum)
72 Val width(void) const;
73 //@}
74};
75
76template <class Val>
77inline void MinMax<Val>::finish(void) {
78 mi = 1;
79 ma = 0;
80}
81
82template <class Val>
83inline MinMax<Val>::MinMax(void) {}
84
85template <class Val>
86inline MinMax<Val>::MinMax(Val min, Val max) : mi(min), ma(max) {}
87
88template <class Val>
89inline bool MinMax<Val>::operator()(void) const {
90 return mi <= ma;
91}
92
93template <class Val>
94inline Val MinMax<Val>::min(void) const {
95 return mi;
96}
97template <class Val>
98inline Val MinMax<Val>::max(void) const {
99 return ma;
100}
101template <class Val>
102inline Val MinMax<Val>::width(void) const {
103 if (mi > ma) return 0;
104 if (mi.isFinite() && ma.isFinite()) return ma - mi + 1;
105 return Val::infinity();
106}
107
108template <class Val, class I>
109class Bounded {
110protected:
111 I i;
112 Val _min;
113 bool use_min;
114 Val _max;
115 bool use_max;
116 Bounded(I& i, Val min0, bool umin0, Val max0, bool umax0);
117
118public:
119 static Bounded miniter(I& i, Val min);
120 static Bounded maxiter(I& i, Val max);
121 static Bounded minmaxiter(I& i, Val min, Val max);
122
123 /// \name Iteration control
124 //@{
125 /// Test whether iterator is still at a range or done
126 bool operator()(void) const;
127 /// Move iterator to next range (if possible)
128 void operator++(void);
129 //@}
130
131 /// \name Range access
132 //@{
133 /// Return smallest value of range
134 Val min(void) const;
135 /// Return largest value of range
136 Val max(void) const;
137 /// Return width of range (distance between minimum and maximum)
138 Val width(void) const;
139 //@}
140};
141
142template <class Val, class I>
143inline Bounded<Val, I>::Bounded(I& i0, Val min0, bool umin0, Val max0, bool umax0)
144 : i(i0), _min(min0), use_min(umin0), _max(max0), use_max(umax0) {
145 while (i() && use_min && i.max() < _min) ++i;
146}
147template <class Val, class I>
148inline Bounded<Val, I> Bounded<Val, I>::miniter(I& i, Val min) {
149 return Bounded(i, min, true, 0, false);
150}
151template <class Val, class I>
152inline Bounded<Val, I> Bounded<Val, I>::maxiter(I& i, Val max) {
153 return Bounded(i, 0, false, max, true);
154}
155template <class Val, class I>
156inline Bounded<Val, I> Bounded<Val, I>::minmaxiter(I& i, Val min, Val max) {
157 return Bounded(i, min, true, max, true);
158}
159
160template <class Val, class I>
161inline bool Bounded<Val, I>::operator()(void) const {
162 return i() && (!use_max || i.min() <= _max);
163}
164template <class Val, class I>
165inline void Bounded<Val, I>::operator++(void) {
166 ++i;
167 while (i() && use_min && i.max() < _min) ++i;
168}
169template <class Val, class I>
170inline Val Bounded<Val, I>::min(void) const {
171 return use_min ? std::max(_min, i.min()) : i.min();
172}
173template <class Val, class I>
174inline Val Bounded<Val, I>::max(void) const {
175 return use_max ? std::min(_max, i.max()) : i.max();
176}
177template <class Val, class I>
178inline Val Bounded<Val, I>::width(void) const {
179 if (min() > max()) return 0;
180 if (min().isFinite() && max().isFinite()) return max() - min() + 1;
181 return Val::infinity();
182}
183
184template <class Val>
185class Const {
186protected:
187 Val _min;
188 Val _max;
189 bool done;
190
191public:
192 Const(Val min0, Val max0);
193
194 /// \name Iteration control
195 //@{
196 /// Test whether iterator is still at a range or done
197 bool operator()(void) const;
198 /// Move iterator to next range (if possible)
199 void operator++(void);
200 //@}
201
202 /// \name Range access
203 //@{
204 /// Return smallest value of range
205 Val min(void) const;
206 /// Return largest value of range
207 Val max(void) const;
208 /// Return width of range (distance between minimum and maximum)
209 Val width(void) const;
210 //@}
211};
212
213template <class Val>
214inline Const<Val>::Const(Val min0, Val max0) : _min(min0), _max(max0), done(min0 > max0) {}
215template <class Val>
216inline bool Const<Val>::operator()(void) const {
217 return !done;
218}
219template <class Val>
220inline void Const<Val>::operator++(void) {
221 done = true;
222}
223template <class Val>
224inline Val Const<Val>::min(void) const {
225 return _min;
226}
227template <class Val>
228inline Val Const<Val>::max(void) const {
229 return _max;
230}
231template <class Val>
232inline Val Const<Val>::width(void) const {
233 if (min() > max()) return 0;
234 if (min().isFinite() && max().isFinite()) return max() - min() + 1;
235 return Val::infinity();
236}
237
238/**
239 * \brief Range iterator for computing union (binary)
240 *
241 * \ingroup FuncIterRanges
242 */
243template <class Val, class I, class J>
244class Union : public MinMax<Val> {
245protected:
246 /// First iterator
247 I i;
248 /// Second iterator
249 J j;
250
251public:
252 /// \name Constructors and initialization
253 //@{
254 /// Default constructor
255 Union(void);
256 /// Initialize with iterator \a i and \a j
257 Union(I& i, J& j);
258 /// Initialize with iterator \a i and \a j
259 void init(I& i, J& j);
260 //@}
261
262 /// \name Iteration control
263 //@{
264 /// Move iterator to next range (if possible)
265 void operator++(void);
266 //@}
267};
268
269/// Return whether an interval ending with \a x overlaps with an interval starting at \a y
270inline bool overlaps(const IntVal& x, const IntVal& y) { return x.plus(1) >= y; }
271/// Return whether an interval ending with \a x overlaps with an interval starting at \a y
272inline bool overlaps(const FloatVal& x, const FloatVal& y) {
273 if (x.isPlusInfinity()) return true;
274 if (y.isMinusInfinity()) return true;
275 if (x.isFinite() && y.isFinite()) {
276 return std::nextafter(x.toDouble(), INFINITY) >= y.toDouble();
277 }
278 return x >= y;
279}
280inline IntVal nextHigher(const IntVal& x) { return x.plus(1); }
281inline IntVal nextLower(const IntVal& x) { return x.minus(1); }
282inline FloatVal nextHigher(const FloatVal& x) {
283 if (x.isFinite()) return std::nextafter(x.toDouble(), INFINITY);
284 return x;
285}
286inline FloatVal nextLower(const FloatVal& x) {
287 if (x.isFinite()) return std::nextafter(x.toDouble(), -INFINITY);
288 return x;
289}
290
291/*
292 * Binary union
293 *
294 */
295
296template <class Val, class I, class J>
297inline void Union<Val, I, J>::operator++(void) {
298 if (!i() && !j()) {
299 MinMax<Val>::finish();
300 return;
301 }
302
303 if (!i() || (j() && (!overlaps(j.max(), i.min())))) {
304 MinMax<Val>::mi = j.min();
305 MinMax<Val>::ma = j.max();
306 ++j;
307 return;
308 }
309 if (!j() || (i() && (!overlaps(i.max(), j.min())))) {
310 MinMax<Val>::mi = i.min();
311 MinMax<Val>::ma = i.max();
312 ++i;
313 return;
314 }
315
316 MinMax<Val>::mi = std::min(i.min(), j.min());
317 MinMax<Val>::ma = std::max(i.max(), j.max());
318
319 ++i;
320 ++j;
321
322next:
323 if (i() && (overlaps(MinMax<Val>::ma, i.min()))) {
324 MinMax<Val>::ma = std::max(MinMax<Val>::ma, i.max());
325 ++i;
326 goto next;
327 }
328 if (j() && (overlaps(MinMax<Val>::ma, j.min()))) {
329 MinMax<Val>::ma = std::max(MinMax<Val>::ma, j.max());
330 ++j;
331 goto next;
332 }
333}
334
335template <class Val, class I, class J>
336inline Union<Val, I, J>::Union(void) {}
337
338template <class Val, class I, class J>
339inline Union<Val, I, J>::Union(I& i0, J& j0) : i(i0), j(j0) {
340 operator++();
341}
342
343template <class Val, class I, class J>
344inline void Union<Val, I, J>::init(I& i0, J& j0) {
345 i = i0;
346 j = j0;
347 operator++();
348}
349
350/**
351 * \brief Range iterator for computing intersection (binary)
352 *
353 * \ingroup FuncIterRanges
354 */
355template <class Val, class I, class J>
356class Inter : public MinMax<Val> {
357protected:
358 /// First iterator
359 I i;
360 /// Second iterator
361 J j;
362
363public:
364 /// \name Constructors and initialization
365 //@{
366 /// Default constructor
367 Inter(void);
368 /// Initialize with iterator \a i and \a j
369 Inter(I& i, J& j);
370 /// Initialize with iterator \a i and \a j
371 void init(I& i, J& j);
372 //@}
373
374 /// \name Iteration control
375 //@{
376 /// Move iterator to next range (if possible)
377 void operator++(void);
378 //@}
379};
380
381/*
382 * Binary intersection
383 *
384 */
385
386template <class Val, class I, class J>
387inline void Inter<Val, I, J>::operator++(void) {
388 if (!i() || !j()) goto done;
389 do {
390 while (i() && (i.max() < j.min())) ++i;
391 if (!i()) goto done;
392 while (j() && (j.max() < i.min())) ++j;
393 if (!j()) goto done;
394 } while (i.max() < j.min());
395 // Now the intervals overlap: consume the smaller interval
396 MinMax<Val>::ma = std::min(i.max(), j.max());
397 MinMax<Val>::mi = std::max(i.min(), j.min());
398 if (i.max() < j.max())
399 ++i;
400 else
401 ++j;
402 return;
403done:
404 MinMax<Val>::finish();
405}
406
407template <class Val, class I, class J>
408inline Inter<Val, I, J>::Inter(void) {}
409
410template <class Val, class I, class J>
411inline Inter<Val, I, J>::Inter(I& i0, J& j0) : i(i0), j(j0) {
412 operator++();
413}
414
415template <class Val, class I, class J>
416inline void Inter<Val, I, J>::init(I& i0, J& j0) {
417 i = i0;
418 j = j0;
419 operator++();
420}
421
422/**
423 * \brief Range iterator for computing set difference
424 *
425 * \ingroup FuncIterRanges
426 */
427
428template <class Val, class I, class J>
429class Diff : public MinMax<Val> {
430protected:
431 /// Iterator from which to subtract
432 I i;
433 /// Iterator to be subtracted
434 J j;
435
436public:
437 /// \name Constructors and initialization
438 //@{
439 /// Default constructor
440 Diff(void);
441 /// Initialize with iterator \a i and \a j
442 Diff(I& i, J& j);
443 /// Initialize with iterator \a i and \a j
444 void init(I& i, J& j);
445 //@}
446
447 /// \name Iteration control
448 //@{
449 /// Move iterator to next range (if possible)
450 void operator++(void);
451 //@}
452};
453
454template <class Val, class I, class J>
455inline void Diff<Val, I, J>::operator++(void) {
456 // Precondition: mi <= ma
457 // Task: find next mi greater than ma
458 while (true) {
459 if (!i()) break;
460 bool isInfinite = (!MinMax<Val>::ma.isFinite() && MinMax<Val>::ma > 0);
461 MinMax<Val>::mi = nextHigher(MinMax<Val>::ma);
462 MinMax<Val>::ma = i.max();
463 if (isInfinite || MinMax<Val>::mi > i.max()) {
464 ++i;
465 if (!i()) break;
466 MinMax<Val>::mi = i.min();
467 MinMax<Val>::ma = i.max();
468 }
469 while (j() && (j.max() < MinMax<Val>::mi)) ++j;
470 if (j() && (j.min() <= MinMax<Val>::ma)) {
471 // Now the interval [mi ... ma] must be shrunken
472 // Is [mi ... ma] completely consumed?
473 if ((MinMax<Val>::mi >= j.min()) && (MinMax<Val>::ma <= j.max())) continue;
474 // Does [mi ... ma] overlap on the left?
475 if (j.min() <= MinMax<Val>::mi) {
476 MinMax<Val>::mi = nextHigher(j.max());
477 // Search for max!
478 ++j;
479 if (j() && (j.min() <= MinMax<Val>::ma)) MinMax<Val>::ma = nextLower(j.min());
480 } else {
481 MinMax<Val>::ma = nextLower(j.min());
482 }
483 }
484 return;
485 }
486 MinMax<Val>::finish();
487}
488
489template <class Val, class I, class J>
490inline Diff<Val, I, J>::Diff(void) {}
491
492template <class Val, class I, class J>
493inline Diff<Val, I, J>::Diff(I& i0, J& j0) : i(i0), j(j0) {
494 if (!i()) {
495 MinMax<Val>::finish();
496 } else {
497 MinMax<Val>::mi = nextLower(i.min());
498 MinMax<Val>::ma = MinMax<Val>::mi;
499 operator++();
500 }
501}
502
503template <class Val, class I, class J>
504inline void Diff<Val, I, J>::init(I& i0, J& j0) {
505 i = i0;
506 j = j0;
507 if (!i()) {
508 MinMax<Val>::finish();
509 } else {
510 MinMax<Val>::mi = nextLower(i.min());
511 MinMax<Val>::ma = MinMax<Val>::mi;
512 operator++();
513 }
514}
515
516/**
517 * \brief Value iterator from range iterator
518 *
519 * \ingroup FuncIterValues
520 */
521template <class I>
522class ToValues {
523protected:
524 /// Range iterator used
525 I i;
526 /// Current value
527 IntVal cur;
528 /// End of current range
529 IntVal max;
530 /// Initialize iterator
531 void start(void);
532
533public:
534 /// \name Constructors and initialization
535 //@{
536 /// Default constructor
537 ToValues(void);
538 /// Initialize with values from range iterator \a i
539 ToValues(I& i);
540 /// Initialize with values from range iterator \a i
541 void init(I& i);
542 //@}
543
544 /// \name Iteration control
545 //@{
546 /// Test whether iterator is still at a value or done
547 bool operator()(void) const;
548 /// Move iterator to next value (if possible)
549 void operator++(void);
550 //@}
551
552 /// \name Value access
553 //@{
554 /// Return current value
555 IntVal val(void) const;
556 //@}
557};
558
559template <class I>
560inline ToValues<I>::ToValues(void) {}
561
562template <class I>
563inline void ToValues<I>::start(void) {
564 if (i()) {
565 cur = i.min();
566 max = i.max();
567 } else {
568 cur = 1;
569 max = 0;
570 }
571}
572
573template <class I>
574inline ToValues<I>::ToValues(I& i0) : i(i0) {
575 start();
576}
577
578template <class I>
579inline void ToValues<I>::init(I& i0) {
580 i = i0;
581 start();
582}
583
584template <class I>
585inline bool ToValues<I>::operator()(void) const {
586 return (cur <= max);
587}
588
589template <class I>
590inline void ToValues<I>::operator++(void) {
591 ++cur;
592 if (cur > max) {
593 ++i;
594 if (i()) {
595 cur = i.min();
596 max = i.max();
597 }
598 }
599}
600
601template <class I>
602inline IntVal ToValues<I>::val(void) const {
603 return cur;
604}
605
606/**
607 * \defgroup FuncIterRangesOp Operations on range iterators
608 *
609 * \ingroup FuncIterRanges
610 */
611
612//@{
613/// Cardinality of the set represented by range iterator \a i
614template <class I>
615IntVal cardinality(I& i);
616
617/// Check whether range iterators \a i and \a j are equal
618template <class I, class J>
619bool equal(I& i, J& j);
620
621/// Check whether range iterator \a i is subset of range iterator \a j
622template <class I, class J>
623bool subset(I& i, J& j);
624
625/// Check whether range iterators \a i and \a j are disjoint
626template <class I, class J>
627bool disjoint(I& i, J& j);
628
629/// Comapre two iterators with each other
630enum CompareStatus {
631 CS_SUBSET, ///< First is subset of second iterator
632 CS_DISJOINT, ///< Intersection is empty
633 CS_NONE ///< Neither of the above
634};
635
636/// Check whether range iterator \a i is a subset of \a j, or whether they are disjoint
637template <class I, class J>
638CompareStatus compare(I& i, J& j);
639//@}
640
641template <class I>
642inline IntVal cardinality(I& i) {
643 IntVal s = 0;
644 while (i()) {
645 if (i.width().isFinite()) {
646 s += i.width();
647 ++i;
648 } else {
649 return IntVal::infinity();
650 }
651 }
652 return s;
653}
654
655template <class I, class J>
656inline bool equal(I& i, J& j) {
657 // Are i and j equal?
658 while (i() && j())
659 if ((i.min() == j.min()) && (i.max() == j.max())) {
660 ++i;
661 ++j;
662 } else {
663 return false;
664 }
665 return !i() && !j();
666}
667
668template <class I, class J>
669inline bool subset(I& i, J& j) {
670 // Is i subset of j?
671 while (i() && j())
672 if (j.max() < i.min()) {
673 ++j;
674 } else if ((i.min() >= j.min()) && (i.max() <= j.max())) {
675 ++i;
676 } else {
677 return false;
678 }
679 return !i();
680}
681
682template <class I, class J>
683inline bool disjoint(I& i, J& j) {
684 // Are i and j disjoint?
685 while (i() && j())
686 if (j.max() < i.min()) {
687 ++j;
688 } else if (i.max() < j.min()) {
689 ++i;
690 } else {
691 return false;
692 }
693 return true;
694}
695
696template <class I, class J>
697inline CompareStatus compare(I& i, J& j) {
698 bool subset = true;
699 bool disjoint = true;
700 while (i() && j()) {
701 if (j.max() < i.min()) {
702 ++j;
703 } else if (i.max() < j.min()) {
704 ++i;
705 subset = false;
706 } else if ((i.min() >= j.min()) && (i.max() <= j.max())) {
707 ++i;
708 disjoint = false;
709 } else if (i.max() <= j.max()) {
710 ++i;
711 disjoint = false;
712 subset = false;
713 } else if (j.max() <= i.max()) {
714 ++j;
715 disjoint = false;
716 subset = false;
717 }
718 }
719 if (i()) subset = false;
720 if (subset) return CS_SUBSET;
721 return disjoint ? CS_DISJOINT : CS_NONE;
722}
723
724template <class I, class J>
725inline bool less(I& i, J& j) {
726 while (i()) {
727 if (!j()) return false;
728 if (i.min() < j.min()) return true;
729 if (i.min() > j.min()) return false;
730 if (i.max() < j.max()) return true;
731 if (i.max() > j.max()) return false;
732 ++i;
733 ++j;
734 }
735 if (j()) return true;
736 return false;
737}
738
739template <class I, class J>
740inline bool lessEq(I& i, J& j) {
741 while (i()) {
742 if (!j()) return false;
743 if (i.min() < j.min()) return true;
744 if (i.min() > j.min()) return false;
745 if (i.max() < j.max()) return true;
746 if (i.max() > j.max()) return false;
747 ++i;
748 ++j;
749 }
750 return true;
751}
752
753} // namespace Ranges
754} // namespace MiniZinc
755
756#endif