Skip to content

Commit bda0f1b

Browse files
committed
Do not use memory addresses for determining in which order duplicate variables are removed
1 parent c85453c commit bda0f1b

File tree

2 files changed

+57
-6
lines changed

2 files changed

+57
-6
lines changed

changelog.in

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,19 @@ Date: 2019-??-??
6868
[DESCRIPTION]
6969
Let's see.
7070

71+
[ENTRY]
72+
Module: kernel
73+
What: bug
74+
Rank: major
75+
[DESCRIPTION]
76+
For the combination of some constraints (min, max, nvalues, and
77+
some constraints over Boolean variables) with shared variable
78+
selection branching (that is, AFC, Action, and CHB) the behavior
79+
of Gecode was indeterminstic. The indeterminism was based on
80+
using memory addresses for determining the order of variables in
81+
some propagators which in turn affected which propagator might
82+
record failure first and hence influenced the branching decisions.
83+
7184
[ENTRY]
7285
Module: example
7386
What: new

gecode/kernel/data/array.hpp

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,24 @@
4545

4646
namespace Gecode { namespace Kernel {
4747

48+
/// Occurence information for a view
49+
template<class View>
50+
class ViewOcc {
51+
public:
52+
/// The view
53+
View x;
54+
/// The original index in the array
55+
int i;
56+
/// Sorting order
57+
bool operator <(const ViewOcc& y) const;
58+
};
59+
60+
template<class View>
61+
forceinline bool
62+
ViewOcc<View>::operator <(const ViewOcc& y) const {
63+
return x < y.x;
64+
}
65+
4866
/// Check whether \a p has duplicates among its \a n elements (changes \a p)
4967
GECODE_KERNEL_EXPORT
5068
bool duplicates(void** p, int n);
@@ -1399,12 +1417,32 @@ namespace Gecode {
13991417
ViewArray<View>::unique(void) {
14001418
if (n < 2)
14011419
return;
1402-
Support::quicksort<View>(x,n);
1403-
int j = 0;
1404-
for (int i=1; i<n; i++)
1405-
if (x[j] != x[i])
1406-
x[++j] = x[i];
1407-
n = j+1;
1420+
Region r;
1421+
Kernel::ViewOcc<View>* o = r.alloc<Kernel::ViewOcc<View>>(n);
1422+
for (int i=0; i<n; i++) {
1423+
o[i].x = x[i]; o[i].i = i;
1424+
}
1425+
Support::quicksort<Kernel::ViewOcc<View>>(o,n);
1426+
// Assign bucket numbers
1427+
int* bkt = r.alloc<int>(n);
1428+
int b = 0;
1429+
bkt[o[0].i] = b;
1430+
for (int i=1; i<n; i++) {
1431+
if (o[i-1].x != o[i].x)
1432+
b++;
1433+
bkt[o[i].i] = b;
1434+
}
1435+
// Eliminate duplicate elements
1436+
Support::BitSet<Region> seen(r,static_cast<unsigned int>(b+1));
1437+
int j=0;
1438+
for (int i=0; i<n; i++)
1439+
if (!seen.get(bkt[i])) {
1440+
x[j++]=x[i]; seen.set(bkt[i]);
1441+
} else {
1442+
x[j]=x[i];
1443+
}
1444+
assert(j == b+1);
1445+
n = j;
14081446
}
14091447

14101448
template<class View>

0 commit comments

Comments
 (0)