From bda0f1b3b734ab6c9ace8c5b693ce0a07bf6bee3 Mon Sep 17 00:00:00 2001 From: Christian Schulte Date: Fri, 5 Apr 2019 14:42:44 +0200 Subject: [PATCH] Do not use memory addresses for determining in which order duplicate variables are removed --- changelog.in | 13 ++++++++++ gecode/kernel/data/array.hpp | 50 +++++++++++++++++++++++++++++++----- 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/changelog.in b/changelog.in index be0a937cfc..a2862df4a6 100755 --- a/changelog.in +++ b/changelog.in @@ -68,6 +68,19 @@ Date: 2019-??-?? [DESCRIPTION] Let's see. +[ENTRY] +Module: kernel +What: bug +Rank: major +[DESCRIPTION] +For the combination of some constraints (min, max, nvalues, and +some constraints over Boolean variables) with shared variable +selection branching (that is, AFC, Action, and CHB) the behavior +of Gecode was indeterminstic. The indeterminism was based on +using memory addresses for determining the order of variables in +some propagators which in turn affected which propagator might +record failure first and hence influenced the branching decisions. + [ENTRY] Module: example What: new diff --git a/gecode/kernel/data/array.hpp b/gecode/kernel/data/array.hpp index 6e871c469d..89cdbe0470 100755 --- a/gecode/kernel/data/array.hpp +++ b/gecode/kernel/data/array.hpp @@ -45,6 +45,24 @@ namespace Gecode { namespace Kernel { + /// Occurence information for a view + template + class ViewOcc { + public: + /// The view + View x; + /// The original index in the array + int i; + /// Sorting order + bool operator <(const ViewOcc& y) const; + }; + + template + forceinline bool + ViewOcc::operator <(const ViewOcc& y) const { + return x < y.x; + } + /// Check whether \a p has duplicates among its \a n elements (changes \a p) GECODE_KERNEL_EXPORT bool duplicates(void** p, int n); @@ -1399,12 +1417,32 @@ namespace Gecode { ViewArray::unique(void) { if (n < 2) return; - Support::quicksort(x,n); - int j = 0; - for (int i=1; i* o = r.alloc>(n); + for (int i=0; i>(o,n); + // Assign bucket numbers + int* bkt = r.alloc(n); + int b = 0; + bkt[o[0].i] = b; + for (int i=1; i seen(r,static_cast(b+1)); + int j=0; + for (int i=0; i