@@ -65,14 +65,25 @@ namespace Gecode { namespace Int { namespace Linear {
6565
6666 // / Sort linear terms by view
6767 template <class View >
68- class TermLess {
68+ class TermByView {
6969 public:
7070 forceinline bool
7171 operator ()(const Term<View>& a, const Term<View>& b) {
7272 return a.x < b.x ;
7373 }
7474 };
7575
76+ // / Sort linear terms by coefficient size and original position
77+ template <class View >
78+ class TermBySizePos {
79+ public:
80+ forceinline bool
81+ operator ()(const Term<View>& a, const Term<View>& b) {
82+ assert ((a.a > 0 ) && (b.a > 0 ));
83+ return (a.a > b.a ) || ((a.a == b.a ) && (a.p < b.p ));
84+ }
85+ };
86+
7687 // / Compute the greatest common divisor of \a a and \a b
7788 inline int
7889 gcd (int a, int b) {
@@ -116,28 +127,34 @@ namespace Gecode { namespace Int { namespace Linear {
116127 Term<View>* &t_p, int &n_p,
117128 Term<View>* &t_n, int &n_n,
118129 int & g) {
130+ // Number terms by position
131+ for (int i=0 ; i<n; i++)
132+ t[i].p = i;
133+
119134 /*
120135 * Join coefficients for aliased variables:
121136 *
122137 */
123138 {
124139 // Group same variables
125- TermLess <View> tl;
126- Support::quicksort<Term<View>,TermLess <View> >(t,n,tl);
140+ TermByView <View> tl;
141+ Support::quicksort<Term<View>,TermByView <View>>(t,n,tl);
127142
128143 // Join adjacent variables
129144 int i = 0 ;
130145 int j = 0 ;
131146 while (i < n) {
132147 Limits::check (t[i].a ," Int::linear" );
133148 long long int a = t[i].a ;
149+ int p = t[i].p ;
134150 View x = t[i].x ;
135151 while ((++i < n) && (t[i].x == x)) {
136152 a += t[i].a ;
153+ p = std::min (p,t[i].p );
137154 Limits::check (a," Int::linear" );
138155 }
139156 if (a != 0 ) {
140- t[j].a = static_cast <int >(a); t[j].x = x; j++;
157+ t[j].a = static_cast <int >(a); t[j].x = x; t[j]. p = p; j++;
141158 }
142159 }
143160 n = j;
@@ -170,6 +187,15 @@ namespace Gecode { namespace Int { namespace Linear {
170187 for (int i=0 ; i<n_n; i++)
171188 t_n[i].a = -t_n[i].a ;
172189
190+ /*
191+ * Sort terms into canonical order (to avoid indeterminstic order)
192+ */
193+ {
194+ TermBySizePos<View> tl;
195+ Support::quicksort<Term<View>,TermBySizePos<View>>(t_p,n_p,tl);
196+ Support::quicksort<Term<View>,TermBySizePos<View>>(t_n,n_n,tl);
197+ }
198+
173199 /*
174200 * Compute greatest common divisor
175201 *
0 commit comments