Blame view

src/constraints/poly-eq.c 9.88 KB
eef94371   Vasco Pedro   Update to PaCCS v...
1
2
3
4
/* poly-eq(C, X, y) == sum(C . X) = y */

// caveat: may not work correctly when there are more than one
// occurrences of some variable
965dadaa   Salvador Abreu   initial commit fr...
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

static int fd_poly_eq_filter(fd_constraint this)
{
  int ub, lb;
  int min, max;
  int terms = this->nconstants;
  int *mins, *maxs;
  int i;
#ifdef CONSTRAINT_TEMPS
  int *base;

  assert(!fd__constraint_data_valid(this));

  if (!constraint_memory[this->index])
    constraint_memory[this->index] = malloc((2 * terms + 4) * sizeof(int));

  base = constraint_memory[this->index];

  mins = base + 4;
  maxs = mins + terms;
#else
  mins = alloca(terms * sizeof(*mins));
  maxs = alloca(terms * sizeof(*maxs));
#endif

  lb = _fd_var_min(VAR(this, this->nvariables - 1));	// lower bound
  ub = _fd_var_max(VAR(this, this->nvariables - 1));	// upper bound

  // sum the minima and the maxima of the terms
  min = max = 0;

  for (i = 0; i < terms; ++i)
    {
      int vl, vh;

      if (this->constants[i] > 0)
	{
	  vl = mins[i] = _fd_var_min(VAR(this, i));
	  vh = maxs[i] = _fd_var_max(VAR(this, i));
	}
      else
	{
	  vl = maxs[i] = _fd_var_max(VAR(this, i));
	  vh = mins[i] = _fd_var_min(VAR(this, i));
	}

      min += this->constants[i] * vl;
      max += this->constants[i] * vh;
    }

  if (min > ub || max < lb)
    return FD_NOSOLUTION;

eef94371   Vasco Pedro   Update to PaCCS v...
58
  if (min > lb)
965dadaa   Salvador Abreu   initial commit fr...
59
    {
eef94371   Vasco Pedro   Update to PaCCS v...
60
61
62
63
64
65
66
67
      fd_update_domain_and_check(del_lt, min, VAR(this, this->nvariables - 1));

      lb = min;
    }

  if (max < ub)
    {
      fd_update_domain_and_check(del_gt, max, VAR(this, this->nvariables - 1));
965dadaa   Salvador Abreu   initial commit fr...
68

eef94371   Vasco Pedro   Update to PaCCS v...
69
      ub = max;
965dadaa   Salvador Abreu   initial commit fr...
70
71
72
    }

  if (min == max)
eef94371   Vasco Pedro   Update to PaCCS v...
73
74
75
76
77
78
79
    {
      fd__constraint_set_entailed(this);
    }
  else
    {
      // bounds domain filtering
      // XXX: number of iterations depends on the size of the domains
965dadaa   Salvador Abreu   initial commit fr...
80

eef94371   Vasco Pedro   Update to PaCCS v...
81
      int omin, omax;
965dadaa   Salvador Abreu   initial commit fr...
82

eef94371   Vasco Pedro   Update to PaCCS v...
83
84
85
86
87
      do {
	omin = min;
	omax = max;

	if (max > ub)
965dadaa   Salvador Abreu   initial commit fr...
88
	  {
eef94371   Vasco Pedro   Update to PaCCS v...
89
	    for (i = 0; i < terms; ++i)
965dadaa   Salvador Abreu   initial commit fr...
90
	      {
eef94371   Vasco Pedro   Update to PaCCS v...
91
92
93
		int c = this->constants[i];
		int imin = mins[i];
		int imax = maxs[i];
965dadaa   Salvador Abreu   initial commit fr...
94

eef94371   Vasco Pedro   Update to PaCCS v...
95
		if (c == 0 || imin == imax)  continue;
965dadaa   Salvador Abreu   initial commit fr...
96

eef94371   Vasco Pedro   Update to PaCCS v...
97
98
99
		if (c > 0)
		  {
		    // enforce min(sum{j!=i}(c[j] * x[j])) + c[i] * max[i] <= max[y]
965dadaa   Salvador Abreu   initial commit fr...
100

eef94371   Vasco Pedro   Update to PaCCS v...
101
102
103
104
		    if (min + (imax - imin) * c > ub)
		      {
			// imax = floor((ub - min) / c) + imin
			imax = (ub - min) / c + imin;
965dadaa   Salvador Abreu   initial commit fr...
105

eef94371   Vasco Pedro   Update to PaCCS v...
106
			fd_update_domain_and_check(del_gt, imax, VAR(this, i));
965dadaa   Salvador Abreu   initial commit fr...
107

eef94371   Vasco Pedro   Update to PaCCS v...
108
			max -= (maxs[i] - imax) * c;
965dadaa   Salvador Abreu   initial commit fr...
109

eef94371   Vasco Pedro   Update to PaCCS v...
110
111
112
113
114
115
			maxs[i] = imax;
		      }
		  }
		else
		  {
		    // enforce min(sum{j!=i}(c[j] * x[j])) + c[i] * min[i] <= max[y]
965dadaa   Salvador Abreu   initial commit fr...
116

eef94371   Vasco Pedro   Update to PaCCS v...
117
118
119
120
121
122
		    if (min + (imin - imax) * c > ub)
		      {
			// imin = ceil((ub - min) / c) + imax
			imin = (ub - min) / c + imax;

			fd_update_domain_and_check(del_lt, imin, VAR(this, i));
965dadaa   Salvador Abreu   initial commit fr...
123

eef94371   Vasco Pedro   Update to PaCCS v...
124
			max -= (mins[i] - imin) * c;
965dadaa   Salvador Abreu   initial commit fr...
125

eef94371   Vasco Pedro   Update to PaCCS v...
126
127
128
			mins[i] = imin;
		      }
		  }
965dadaa   Salvador Abreu   initial commit fr...
129
	      }
eef94371   Vasco Pedro   Update to PaCCS v...
130
131
132

	    if (max < lb)
	      return FD_NOSOLUTION;
965dadaa   Salvador Abreu   initial commit fr...
133
	  }
965dadaa   Salvador Abreu   initial commit fr...
134

eef94371   Vasco Pedro   Update to PaCCS v...
135
136
137
	if (min < lb)
	  {
	    for (i = 0; i < terms; ++i)
965dadaa   Salvador Abreu   initial commit fr...
138
	      {
eef94371   Vasco Pedro   Update to PaCCS v...
139
140
141
142
143
144
145
		int c = this->constants[i];
		int imin = mins[i];
		int imax = maxs[i];

		if (c == 0 || imin == imax)  continue;

		if (c > 0)
965dadaa   Salvador Abreu   initial commit fr...
146
		  {
eef94371   Vasco Pedro   Update to PaCCS v...
147
148
149
150
151
152
		    // enforce max(sum{j!=i}(c[j] * x[j])) + c[i] * min[i] >= min[y]

		    if (max + (imin - imax) * c < lb)
		      {
			// imin = ceil((lb - max) / c) + imax
			imin = (lb - max) / c + imax;
965dadaa   Salvador Abreu   initial commit fr...
153

eef94371   Vasco Pedro   Update to PaCCS v...
154
			fd_update_domain_and_check(del_lt, imin, VAR(this, i));
965dadaa   Salvador Abreu   initial commit fr...
155

eef94371   Vasco Pedro   Update to PaCCS v...
156
			min += (imin - mins[i]) * c;
965dadaa   Salvador Abreu   initial commit fr...
157

eef94371   Vasco Pedro   Update to PaCCS v...
158
159
			mins[i] = imin;
		      }
965dadaa   Salvador Abreu   initial commit fr...
160
		  }
eef94371   Vasco Pedro   Update to PaCCS v...
161
		else
965dadaa   Salvador Abreu   initial commit fr...
162
		  {
eef94371   Vasco Pedro   Update to PaCCS v...
163
164
165
166
167
168
		    // enforce max(sum{j!=i}(c[j] * x[j])) + c[i] * max[i] >= min[y]

		    if (max + (imax - imin) * c < lb)
		      {
			// imax = floor((lb - max) / c) + imin
			imax = (lb - max) / c + imin;
965dadaa   Salvador Abreu   initial commit fr...
169

eef94371   Vasco Pedro   Update to PaCCS v...
170
			fd_update_domain_and_check(del_gt, imax, VAR(this, i));
965dadaa   Salvador Abreu   initial commit fr...
171

eef94371   Vasco Pedro   Update to PaCCS v...
172
			min += (imax - maxs[i]) * c;
965dadaa   Salvador Abreu   initial commit fr...
173

eef94371   Vasco Pedro   Update to PaCCS v...
174
175
			maxs[i] = imax;
		      }
965dadaa   Salvador Abreu   initial commit fr...
176
177
		  }
	      }
eef94371   Vasco Pedro   Update to PaCCS v...
178
179
180

	    if (min > ub)
	      return FD_NOSOLUTION;
965dadaa   Salvador Abreu   initial commit fr...
181
182
	  }

eef94371   Vasco Pedro   Update to PaCCS v...
183
	if (min > lb && _fd_var_del_lt(min, VAR(this, this->nvariables - 1)))
965dadaa   Salvador Abreu   initial commit fr...
184
	  {
eef94371   Vasco Pedro   Update to PaCCS v...
185
186
	    if (fd_domain_empty(VAR(this, this->nvariables - 1)))
	      return FD_NOSOLUTION;
965dadaa   Salvador Abreu   initial commit fr...
187

eef94371   Vasco Pedro   Update to PaCCS v...
188
	    _fd_revise_connected(this, VAR(this, this->nvariables - 1));
965dadaa   Salvador Abreu   initial commit fr...
189

eef94371   Vasco Pedro   Update to PaCCS v...
190
191
	    lb = min;
	  }
965dadaa   Salvador Abreu   initial commit fr...
192

eef94371   Vasco Pedro   Update to PaCCS v...
193
194
195
196
	if (max < ub && _fd_var_del_gt(max, VAR(this, this->nvariables - 1)))
	  {
	    if (fd_domain_empty(VAR(this, this->nvariables - 1)))
	      return FD_NOSOLUTION;
965dadaa   Salvador Abreu   initial commit fr...
197

eef94371   Vasco Pedro   Update to PaCCS v...
198
	    _fd_revise_connected(this, VAR(this, this->nvariables - 1));
965dadaa   Salvador Abreu   initial commit fr...
199

eef94371   Vasco Pedro   Update to PaCCS v...
200
201
	    ub = max;
	  }
965dadaa   Salvador Abreu   initial commit fr...
202

eef94371   Vasco Pedro   Update to PaCCS v...
203
      } while (min != max && (min != omin || max != omax));
965dadaa   Salvador Abreu   initial commit fr...
204

eef94371   Vasco Pedro   Update to PaCCS v...
205
206
      if (min == max)
	fd__constraint_set_entailed(this);
965dadaa   Salvador Abreu   initial commit fr...
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
    }

#ifdef CONSTRAINT_TEMPS
  // save values
  *base = lb;
  *(base + 1) = ub;
  *(base + 2) = min;
  *(base + 3) = max;

  fd__constraint_remember(this);
#endif

  return FD_OK;
}

static int fd_poly_eq_propagate2(fd_constraint this, fd_int culprit)
{
#ifdef CONSTRAINT_TEMPS
  int ub, lb;
  int min, max;
  int terms = this->nconstants;
  int *mins, *maxs;
  int i;
  int *base;
  int x, c;
  int nmin, nmin_x, nmax, nmax_x;
eef94371   Vasco Pedro   Update to PaCCS v...
233
  int nlb, nub;
965dadaa   Salvador Abreu   initial commit fr...
234
235
236
237
238
239
240
241
242
243
244

  if (!fd__constraint_data_valid(this))
    return fd_poly_eq_filter(this);	// ignores culprit

  // bounds filtering

  base = constraint_memory[this->index];

  mins = base + 4;
  maxs = mins + terms;

eef94371   Vasco Pedro   Update to PaCCS v...
245
246
  nlb = lb = *base;
  nub = ub = *(base + 1);
965dadaa   Salvador Abreu   initial commit fr...
247

eef94371   Vasco Pedro   Update to PaCCS v...
248
249
  nmin = min = *(base + 2);
  nmax = max = *(base + 3);
965dadaa   Salvador Abreu   initial commit fr...
250
251
252
253

  if (culprit == VAR(this, this->nvariables - 1))
    {
      // the culprit is the sum variable
965dadaa   Salvador Abreu   initial commit fr...
254
255
256
257
258
259
260

      nlb = _fd_var_min(culprit);
      nub = _fd_var_max(culprit);

      if (nlb == lb && nub == ub)
	return FD_OK;

eef94371   Vasco Pedro   Update to PaCCS v...
261
262
263
264
265
266
267
268
      if (min > nub || max < nlb)
	return FD_NOSOLUTION;
    }
  else
    {
      // the culprit appears in one of the terms, find out which one(s)
      for (x = 0; culprit != VAR(this, x); ++x)
	;
965dadaa   Salvador Abreu   initial commit fr...
269

eef94371   Vasco Pedro   Update to PaCCS v...
270
271
      nmin_x = _fd_var_min(VAR(this, x));
      nmax_x = _fd_var_max(VAR(this, x));
965dadaa   Salvador Abreu   initial commit fr...
272

eef94371   Vasco Pedro   Update to PaCCS v...
273
274
      if (nmin_x == mins[x] && nmax_x == maxs[x])
	return FD_OK;
965dadaa   Salvador Abreu   initial commit fr...
275

eef94371   Vasco Pedro   Update to PaCCS v...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
      do
	{
	  c = this->constants[x];

	  if (c > 0)
	    {
	      nmin = nmin + (nmin_x - mins[x]) * c;
	      nmax = nmax - (maxs[x] - nmax_x) * c;
	    }
	  else if (c < 0)
	    {
	      nmin = nmin - (maxs[x] - nmax_x) * c;
	      nmax = nmax + (nmin_x - mins[x]) * c;
	    }

	  if (nmin > ub || nmax < lb)
	    return FD_NOSOLUTION;
965dadaa   Salvador Abreu   initial commit fr...
293

eef94371   Vasco Pedro   Update to PaCCS v...
294
295
	  mins[x] = nmin_x;
	  maxs[x] = nmax_x;
965dadaa   Salvador Abreu   initial commit fr...
296

eef94371   Vasco Pedro   Update to PaCCS v...
297
298
299
300
	  while (++x < terms && culprit != VAR(this, x))
	    ;
	}
      while (x < terms);
965dadaa   Salvador Abreu   initial commit fr...
301

eef94371   Vasco Pedro   Update to PaCCS v...
302
303
      if (nmin == min && nmax == max)
	return FD_OK;
965dadaa   Salvador Abreu   initial commit fr...
304

eef94371   Vasco Pedro   Update to PaCCS v...
305
306
307
      if (nmin > lb)
	{
	  fd_update_domain_and_check(del_lt, nmin, VAR(this, this->nvariables - 1));
965dadaa   Salvador Abreu   initial commit fr...
308

eef94371   Vasco Pedro   Update to PaCCS v...
309
310
	  nlb = nmin;
	}
965dadaa   Salvador Abreu   initial commit fr...
311

eef94371   Vasco Pedro   Update to PaCCS v...
312
313
314
      if (nmax < ub)
	{
	  fd_update_domain_and_check(del_gt, nmax, VAR(this, this->nvariables - 1));
965dadaa   Salvador Abreu   initial commit fr...
315

eef94371   Vasco Pedro   Update to PaCCS v...
316
317
318
	  nub = nmax;
	}
    }
965dadaa   Salvador Abreu   initial commit fr...
319

eef94371   Vasco Pedro   Update to PaCCS v...
320
  // (nmin, nlb, nub, nmax) != (min, lb, ub, max)
965dadaa   Salvador Abreu   initial commit fr...
321

eef94371   Vasco Pedro   Update to PaCCS v...
322
323
324
325
326
327
328
329
  if (nmin == nmax)
    {
      fd__constraint_set_entailed(this);
    }
  else
    {
      // bounds domain propagation
      // XXX: number of iterations depends on the size of the domains
965dadaa   Salvador Abreu   initial commit fr...
330

eef94371   Vasco Pedro   Update to PaCCS v...
331
      int onmin, onmax;
965dadaa   Salvador Abreu   initial commit fr...
332

eef94371   Vasco Pedro   Update to PaCCS v...
333
334
335
336
337
338
      do {
	onmin = nmin;
	onmax = nmax;

	if (nmin < nlb)
	  {
965dadaa   Salvador Abreu   initial commit fr...
339
340
	    for (i = 0; i < terms; ++i)
	      {
eef94371   Vasco Pedro   Update to PaCCS v...
341
342
343
344
345
346
347
		int c = this->constants[i];
		int imin = mins[i];
		int imax = maxs[i];

		if (c == 0 || imin == imax)  continue;

		if (c > 0)
965dadaa   Salvador Abreu   initial commit fr...
348
		  {
eef94371   Vasco Pedro   Update to PaCCS v...
349
350
351
		    // enforce max(sum{j!=i}(c[j] * x[j])) + c[i] * min[i] >= min[y]

		    if (nmax + (imin - imax) * c < nlb)
965dadaa   Salvador Abreu   initial commit fr...
352
		      {
eef94371   Vasco Pedro   Update to PaCCS v...
353
354
355
356
357
358
			// imin = ceil((nlb - nmax) / c) + imax
			imin = (nlb - nmax) / c + imax;

			fd_update_domain_and_check(del_lt, imin, VAR(this, i));

			nmin += (imin - mins[i]) * c;
965dadaa   Salvador Abreu   initial commit fr...
359

eef94371   Vasco Pedro   Update to PaCCS v...
360
			mins[i] = imin;
965dadaa   Salvador Abreu   initial commit fr...
361
362
		      }
		  }
eef94371   Vasco Pedro   Update to PaCCS v...
363
		else
965dadaa   Salvador Abreu   initial commit fr...
364
		  {
eef94371   Vasco Pedro   Update to PaCCS v...
365
366
367
		    // enforce max(sum{j!=i}(c[j] * x[j])) + c[i] * max[i] >= min[y]

		    if (nmax + (imax - imin) * c < nlb)
965dadaa   Salvador Abreu   initial commit fr...
368
		      {
eef94371   Vasco Pedro   Update to PaCCS v...
369
370
371
372
			// imax = floor((nlb - nmax) / c) + imin
			imax = (nlb - nmax) / c + imin;

			fd_update_domain_and_check(del_gt, imax, VAR(this, i));
965dadaa   Salvador Abreu   initial commit fr...
373

eef94371   Vasco Pedro   Update to PaCCS v...
374
375
376
			nmin += (imax - maxs[i]) * c;

			maxs[i] = imax;
965dadaa   Salvador Abreu   initial commit fr...
377
378
379
380
		      }
		  }
	      }

eef94371   Vasco Pedro   Update to PaCCS v...
381
382
383
	    if (nmin > nub)
	      return FD_NOSOLUTION;
	  }
965dadaa   Salvador Abreu   initial commit fr...
384

eef94371   Vasco Pedro   Update to PaCCS v...
385
386
387
	if (nmax > nub)
	  {
	    for (i = 0; i < terms; ++i)
965dadaa   Salvador Abreu   initial commit fr...
388
	      {
eef94371   Vasco Pedro   Update to PaCCS v...
389
390
391
392
393
394
395
		int c = this->constants[i];
		int imin = mins[i];
		int imax = maxs[i];

		if (c == 0 || imin == imax)  continue;

		if (c > 0)
965dadaa   Salvador Abreu   initial commit fr...
396
		  {
eef94371   Vasco Pedro   Update to PaCCS v...
397
		    // enforce min(sum{j!=i}(c[j] * x[j])) + c[i] * max[i] <= max[y]
965dadaa   Salvador Abreu   initial commit fr...
398

eef94371   Vasco Pedro   Update to PaCCS v...
399
		    if (nmin + (imax - imin) * c > nub)
965dadaa   Salvador Abreu   initial commit fr...
400
		      {
eef94371   Vasco Pedro   Update to PaCCS v...
401
402
			// imax = floor((nub - nmin) / c) + imin
			imax = (nub - nmin) / c + imin;
965dadaa   Salvador Abreu   initial commit fr...
403

eef94371   Vasco Pedro   Update to PaCCS v...
404
405
406
407
408
			fd_update_domain_and_check(del_gt, imax, VAR(this, i));

			nmax -= (maxs[i] - imax) * c;

			maxs[i] = imax;
965dadaa   Salvador Abreu   initial commit fr...
409
410
		      }
		  }
eef94371   Vasco Pedro   Update to PaCCS v...
411
		else
965dadaa   Salvador Abreu   initial commit fr...
412
		  {
eef94371   Vasco Pedro   Update to PaCCS v...
413
		    // enforce min(sum{j!=i}(c[j] * x[j])) + c[i] * min[i] <= max[y]
965dadaa   Salvador Abreu   initial commit fr...
414

eef94371   Vasco Pedro   Update to PaCCS v...
415
		    if (nmin + (imin - imax) * c > nub)
965dadaa   Salvador Abreu   initial commit fr...
416
		      {
eef94371   Vasco Pedro   Update to PaCCS v...
417
418
419
420
			// imin = ceil((nub - nmin) / c) + imax
			imin = (nub - nmin) / c + imax;

			fd_update_domain_and_check(del_lt, imin, VAR(this, i));
965dadaa   Salvador Abreu   initial commit fr...
421

eef94371   Vasco Pedro   Update to PaCCS v...
422
423
424
			nmax -= (mins[i] - imin) * c;

			mins[i] = imin;
965dadaa   Salvador Abreu   initial commit fr...
425
426
427
		      }
		  }
	      }
965dadaa   Salvador Abreu   initial commit fr...
428

eef94371   Vasco Pedro   Update to PaCCS v...
429
430
431
	    if (nmax < nlb)
	      return FD_NOSOLUTION;
	  }
965dadaa   Salvador Abreu   initial commit fr...
432

eef94371   Vasco Pedro   Update to PaCCS v...
433
434
435
436
	if (nmin > nlb && _fd_var_del_lt(nmin, VAR(this, this->nvariables - 1)))
	  {
	    if (fd_domain_empty(VAR(this, this->nvariables - 1)))
	      return FD_NOSOLUTION;
965dadaa   Salvador Abreu   initial commit fr...
437

eef94371   Vasco Pedro   Update to PaCCS v...
438
	    _fd_revise_connected(this, VAR(this, this->nvariables - 1));
965dadaa   Salvador Abreu   initial commit fr...
439

eef94371   Vasco Pedro   Update to PaCCS v...
440
441
	    nlb = nmin;
	  }
965dadaa   Salvador Abreu   initial commit fr...
442

eef94371   Vasco Pedro   Update to PaCCS v...
443
444
445
446
	if (nmax < nub && _fd_var_del_gt(nmax, VAR(this, this->nvariables - 1)))
	  {
	    if (fd_domain_empty(VAR(this, this->nvariables - 1)))
	      return FD_NOSOLUTION;
965dadaa   Salvador Abreu   initial commit fr...
447

eef94371   Vasco Pedro   Update to PaCCS v...
448
	    _fd_revise_connected(this, VAR(this, this->nvariables - 1));
965dadaa   Salvador Abreu   initial commit fr...
449

eef94371   Vasco Pedro   Update to PaCCS v...
450
451
452
	    nub = nmax;
	  }
      } while (nmin != nmax && (nmin != onmin || nmax != onmax));
965dadaa   Salvador Abreu   initial commit fr...
453

eef94371   Vasco Pedro   Update to PaCCS v...
454
455
      if (nmin == nmax)
	fd__constraint_set_entailed(this);
965dadaa   Salvador Abreu   initial commit fr...
456
457
    }

eef94371   Vasco Pedro   Update to PaCCS v...
458
459
  *(base + 0) = nlb;
  *(base + 1) = nub;
965dadaa   Salvador Abreu   initial commit fr...
460
461
462
463
464
465
466
467
468
469
470
  *(base + 2) = nmin;
  *(base + 3) = nmax;

  return FD_OK;
#else /* CONSTRAINT_TEMPS */
  return fd_poly_eq_filter(this);	// ignores culprit
#endif /* CONSTRAINT_TEMPS */
}

fd_constraint fd_poly_eq(int cs[], fd_int xs[], int nterms, fd_int y)
{
eef94371   Vasco Pedro   Update to PaCCS v...
471
472
473
474
475
476
477
478
479
  fd_constraint fd_poly_eq_k(int[], fd_int[], int, int);
  fd_constraint c;
  int i, k;

  // specialise when y is a singleton
  if (fd_var_single(y, &k))
    return fd_poly_eq_k(cs, xs, nterms, k);

  c = fd__constraint_new(nterms + 1, nterms);
965dadaa   Salvador Abreu   initial commit fr...
480
481
482
483
484
485
486
487

  if (c)
    {
      for (i = 0; i < nterms; ++i)
	c->variables[i] = FD_INT2C_VAR(xs[i]);
      c->variables[nterms] = FD_INT2C_VAR(y);
      for (i = 0; i < nterms; ++i)
	c->constants[i] = cs[i];
eef94371   Vasco Pedro   Update to PaCCS v...
488

965dadaa   Salvador Abreu   initial commit fr...
489
      c->kind = FD_CONSTR_POLY_EQ;
965dadaa   Salvador Abreu   initial commit fr...
490
491
492
493
494
495
496
497
498

      for (i = 0; i < c->nvariables; ++i)
	_fd_var_add_constraint(VAR(c, i), c);

      _fd_add_constraint(c);
    }

  return c;
}