1/* BEGIN LICENSE BLOCK
2 * Version: CMPL 1.1
3 *
4 * The contents of this file are subject to the Cisco-style Mozilla Public
5 * License Version 1.1 (the "License"); you may not use this file except
6 * in compliance with the License.  You may obtain a copy of the License
7 * at www.eclipse-clp.org/license.
8 *
9 * Software distributed under the License is distributed on an "AS IS"
10 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
11 * the License for the specific language governing rights and limitations
12 * under the License.
13 *
14 * The Original Code is  The ECLiPSe Constraint Logic Programming System.
15 * The Initial Developer of the Original Code is  Cisco Systems, Inc.
16 * Portions created by the Initial Developer are
17 * Copyright (C) 2009 Cisco Systems, Inc.  All Rights Reserved.
18 *
19 * Contributor(s): Kish Shen
20 *
21 * END LICENSE BLOCK */
22
23#define SIZEOF_CHAR_P 4
24#define SIZEOF_INT 4
25#define SIZEOF_LONG 4
26
27#include <queue>
28#include "gfd.hpp"
29#include <eclipseclass.h>
30#include <sepia.h>
31
32#define EC_EXTERNAL_ERROR  -213  // from error.h
33
34// these must correspond to the gfd_space struct in gfd.ecl
35#define SPACE_HANDLE_POS   1
36#define SPACE_STAMP_POS    2
37
38inline EC_word
39EC_argument(EC_word t, int i)
40{
41  EC_word e;
42  int x = t.arg(i, e);
43  //assert(x == EC_succeed);
44  return e;
45}
46
47// Arg is an integer domain variable with index Idx (use EC_functor f)
48#define ArgIsVarIdx(Arg, Idx)			\
49    (EC_arg(Arg).functor(&f) == EC_succeed &&	\
50	strcmp(f.name(),"_ivar") ==0 && \
51	EC_argument(EC_arg(Arg),1).is_long(&Idx) == EC_succeed)
52
53// Arg is an integer domain variable with associated boolean with index BIdx (use EC_functor f)
54#define ArgIsVarBoolIdx(Arg, BIdx)		     \
55    (EC_arg(Arg).functor(&f) == EC_succeed &&	     \
56	strcmp(f.name(),"_ivar") ==0 && \
57	EC_argument(EC_arg(Arg),2).is_long(&BIdx) == EC_succeed)
58
59// report any exceptions from Gecode - must be preceeded by a try {...}
60#define CatchAndReportGecodeExceptions \
61    catch(Exception& err) {            \
62	p_fprintf(current_err_, "Gecode exception: %s\n", err.what()); \
63	return EC_EXTERNAL_ERROR; \
64    }
65
66#define THROW_ECEXCEPT throw Ec2gcException()
67#define RETURN_ECERR(Err) return Err
68
69#define Assign_Consistency_Level(atm, cl, Exception)		  \
70    dident ldid = atm.d;					  \
71    if (ldid == d_default) cl = ICL_DEF;                          \
72    else if (ldid == d_gac) cl = ICL_DOM;			  \
73    else if (ldid == d_bc) cl = ICL_BND;			  \
74    else if (ldid == d_vc) cl = ICL_VAL;			  \
75    else Exception					  	  \
76
77// get the interger consistency level cl from argument N
78#define Get_Consistency_Level(N, cl) {		\
79    EC_atom atm;   \
80    if (EC_arg(N).is_atom(&atm) != EC_succeed) return TYPE_ERROR; \
81    Assign_Consistency_Level(atm, cl, RETURN_ECERR(RANGE_ERROR)); \
82}
83
84// get IntRelType r from argument N
85#define Get_IntRelType(N, r) { \
86    EC_atom ecrel; \
87    if (EC_arg(N).is_atom(&ecrel) != EC_succeed) return TYPE_ERROR; \
88    dident rdid = ecrel.d;				    \
89    if (rdid == d_eq) r = IRT_EQ;				    \
90    else if (rdid == d_geq) r = IRT_GQ;				    \
91    else if (rdid == d_gt) r = IRT_GR;				    \
92    else if (rdid == d_leq) r = IRT_LQ;				    \
93    else if (rdid == d_lt) r = IRT_LE;				    \
94    else if (rdid == d_neq) r = IRT_NQ;				    \
95    else return TYPE_ERROR;				    \
96}
97
98#define Get_ReifType(N, r) { \
99   EC_atom rtype; \
100   if (EC_arg(N).is_atom(&rtype) != EC_succeed) return TYPE_ERROR; \
101   dident rtdid = rtype.d;                                         \
102   if (rtdid == d_equ) r = RM_EQV;                                  \
103   else if (rtdid == d_imp) r = RM_IMP;                             \
104   else if (rtdid == d_impby) r = RM_PMI;                           \
105   else return TYPE_ERROR;                                         \
106}
107
108// Assign IntVar var from argument N, var is assigned to either an existing
109// vInt[] variable if argN is a variable, or to an integer value if argN is
110// integer (use EC_functor f)
111#define Assign_IntVar(N, idx, var) { \
112    if (ArgIsVarIdx(N, idx)) {    \
113        if (idx < 1 || idx >= solver->vInt.size()) return RANGE_ERROR; \
114	var = solver->vInt[(int)idx]; \
115    } else if (EC_arg(N).is_long(&idx) == EC_succeed) { \
116	var = IntVar(*solver, (int)idx, (int)idx);      \
117    } else \
118        return TYPE_ERROR; \
119}
120
121// Assign the value of argument N to either IntVar var or int i, is_int is
122// set to true if i is assigned, false if var is assigned (use EC_functor f)
123#define Assign_IntVar_or_Int(N, i, var, is_int) { \
124    if (ArgIsVarIdx(N, i)) { \
125        if (i < 1 || i >= solver->vInt.size()) return RANGE_ERROR; \
126        var = solver->vInt[(int)i]; \
127        is_int = false; \
128    } else if (EC_arg(N).is_long(&i) == EC_succeed) { \
129        is_int = true; \
130    } else \
131        return TYPE_ERROR; \
132}
133
134extern "C" VisAtt stream_id log_output_, warning_output_, current_err_;
135
136extern "C" VisAtt void ec_trail_undo(void(*f)(pword*,word*,int,int), pword*, pword*, word*, int, int);
137
138extern "C" VisAtt int ec_flush(stream_id);
139
140extern "C" VisAtt int p_fprintf(stream_id, const char*, ...);
141
142#if defined(WIN32)
143
144extern "C" VisAtt stream_id Winapi ec_stream_id(int);
145# define log_output_ ec_stream_id(ec_stream_nr("log_output"))
146# define current_err_ ec_stream_id(ec_stream_nr("current_err"))
147
148#endif
149
150static dident d_max_wdeg2, d_min_wdeg2,
151    d_max_wdeg_per_val2, d_min_wdeg_per_val2,
152    d_max_wdeg1, d_min_wdeg1,
153    d_max_wdeg_per_val1, d_min_wdeg_per_val1,
154    d_max_wdeg, d_min_wdeg,
155    d_max_wdeg_per_val, d_min_wdeg_per_val,
156    d_ff, d_antiff,
157    d_occ, d_antiocc,
158    d_smallest, d_largest, d_smallest_upb, d_largest_lwb,
159    d_max_regret, d_max_regret_lwb,
160    d_min_regret_lwb, d_max_regret_upb, d_min_regret_upb,
161    d_most_constrained_per_val, d_least_constrained_per_val,
162    d_most_constrained, d_input_order, d_random, d_random1,
163    d_max_act2, d_max_act_per_val2, d_min_act2, d_min_act_per_val2,
164    d_max_act1, d_max_act_per_val1, d_min_act1, d_min_act_per_val1,
165    d_max_act, d_max_act_per_val, d_min_act, d_min_act_per_val,
166    d_fr_lg1, d_fr_sm1, d_fr_up1, d_fr_down1,
167    d_default, d_gac, d_bc, d_vc,
168    d_eq, d_neq, d_gt, d_lt, d_geq, d_leq, d_equ, d_imp, d_impby,
169    d_colon2, d_iv2, d_sum2, d_element2, d_plus2, d_minus2,
170    d_mult2, d_div2, d_rem2, d_min2, d_max2, d_pow2, d_inroot2,
171    d_minus1, d_abs1, d_sqr1, d_isqrt1, d_sum1, d_max1, d_min1,
172    d_eq2, d_gt2, d_geq2, d_lt2, d_leq2, d_neq2,
173    d_and2, d_or2, d_xor2, d_imp2, d_equ2, d_neg1,
174    d_geo2, d_luby1, d_rand4, d_con1, d_lin1;
175
176using namespace Gecode;
177
178
179int
180get_handle_from_arg(int arg, t_ext_type *method, void **obj)
181{
182    return EC_arg(arg).is_handle(method, obj);
183}
184
185static void _free_dfa_handle(DFA* dfap)
186{
187    delete dfap;
188}
189
190t_ext_type dfa_method = {
191    (void (*)(t_ext_ptr)) _free_dfa_handle, /* free */
192    NULL, /* copy */
193    NULL, /* mark_dids */
194    NULL, /* string_size */
195    NULL, /* to_string */
196    NULL, /* equal */
197    NULL, /* remote_copy */
198    NULL, /* get */
199    NULL, /* set */
200};
201
202static void _free_tupleset_handle(TupleSet* dtset)
203{
204    delete dtset;
205}
206
207t_ext_type tupleset_method = {
208    (void (*)(t_ext_ptr)) _free_tupleset_handle, /* free */
209    NULL, /* copy */
210    NULL, /* mark_dids */
211    NULL, /* string_size */
212    NULL, /* to_string */
213    NULL, /* equal */
214    NULL, /* remote_copy */
215    NULL, /* get */
216    NULL, /* set */
217};
218
219static void _free_space_handle(GecodeSpace** solverp)
220{
221    if (*solverp != NULL) delete *solverp;
222    delete solverp;
223}
224
225t_ext_type gfd_method = {
226    (void (*)(t_ext_ptr)) _free_space_handle, /* free */
227    NULL, /* copy */
228    NULL, /* mark_dids */
229    NULL, /* string_size */
230    NULL, /* to_string */
231    NULL, /* equal */
232    NULL, /* remote_copy */
233    NULL, /* get */
234    NULL, /* set */
235};
236
237static void _free_ldsbsyms_handle(LDSBSymsStore* sym_storep)
238{
239    if (sym_storep != NULL) delete sym_storep;
240    sym_storep = NULL;
241}
242
243t_ext_type ldsbsyms_method = {
244    (void (*)(t_ext_ptr)) _free_ldsbsyms_handle, /* free */
245    NULL, /* copy */
246    NULL, /* mark_dids */
247    NULL, /* string_size */
248    NULL, /* to_string */
249    NULL, /* equal */
250    NULL, /* remote_copy */
251    NULL, /* get */
252    NULL, /* set */
253};
254
255static void _free_search_handle(GecodeSearch* searchp)
256{
257    delete searchp;
258}
259
260t_ext_type gfdsearch_method = {
261    (void (*)(t_ext_ptr)) _free_search_handle, /* free */
262    NULL, /* copy */
263    NULL, /* mark_dids */
264    NULL, /* string_size */
265    NULL, /* to_string */
266    NULL, /* equal */
267    NULL, /* remote_copy */
268    NULL, /* get */
269    NULL, /* set */
270};
271
272/* Delete current space on backtracking as the space becomes invalid.
273   It is unsafe to obtain the space from phandle during GC as data
274   on the Prolog stacks can be marked. The space will instead be deleted
275   by _free_space_handle().
276   An alternative solution we looked at is to pass *solverp as the first
277   arg. As this is allocated by C++ and is not on the Prolog stack, this
278   undo function will not be called during GC, but this is also unafe as
279   *solverp might be deleted early by garbage collecting of the phandle.
280*/
281static void _g_delete_space(pword* phandle, word * dummy, int size, int context)
282{
283    GecodeSpace** solverp;
284
285    if (context == UNDO_GC) return; // Cannot safely get solverp during GC
286    ec_get_handle(phandle[SPACE_HANDLE_POS], &gfd_method, (void**)&solverp);
287    if (*solverp != NULL) {
288	delete *solverp;
289	*solverp = NULL;
290    }
291}
292
293static void _free_domain_handle(IntSet* domainp)
294{
295    if (domainp != NULL) delete domainp;
296}
297
298t_ext_type domain_method = {
299    (void (*)(t_ext_ptr)) _free_domain_handle, /* free */
300    NULL, /* copy */
301    NULL, /* mark_dids */
302    NULL, /* string_size */
303    NULL, /* to_string */
304    NULL, /* equal */
305    NULL, /* remote_copy */
306    NULL, /* get */
307    NULL, /* set */
308};
309
310static void _free_varselect_handle(VarSelectH* varselecthp)
311{
312    delete varselecthp;
313    varselecthp = NULL;
314}
315
316t_ext_type varselecth_method = {
317    (void (*)(t_ext_ptr)) _free_varselect_handle, /* free */
318    NULL, /* copy */
319    NULL, /* mark_dids */
320    NULL, /* string_size */
321    NULL, /* to_string */
322    NULL, /* equal */
323    NULL, /* remote_copy */
324    NULL, /* get */
325    NULL, /* set */
326};
327
328int get_domain_intervals_from_ec_array(int size, EC_word ecarr, int r[][2])
329{
330    EC_word arg;
331    long min, max;
332
333    for (int i=0; i<size; i++) {
334	arg = EC_argument(ecarr, i+1);
335	if (arg.arity() == 2) {
336	    if (EC_argument(arg, 1).is_long(&min) != EC_succeed) return TYPE_ERROR;
337	    if (EC_argument(arg, 2).is_long(&max) != EC_succeed) return TYPE_ERROR;
338
339	    r[i][0] = (int)min;
340	    r[i][1] = (int)max;
341	} else
342	    return TYPE_ERROR;
343    }
344    return EC_succeed;
345}
346
347int assign_IntVarArgs_and_collect_ints(GecodeSpace* solver, int size,
348				       EC_word ecarr, IntVarArgs& vargs,
349				       std::queue<IntVar*>* intsp)
350{
351    EC_functor f;
352    EC_word arg;
353    long l;
354
355    try {
356	for(int i=0; i<size; i++) {
357	    arg = EC_argument(ecarr, i+1);
358	    if (arg.functor(&f) == EC_succeed) {
359		if  (strcmp(f.name(), "_ivar") == 0
360		     && EC_argument(arg, 1).is_long(&l) == EC_succeed) {
361		    vargs[i] = solver->vInt[(int)l];
362		} else
363		    return RANGE_ERROR;
364	    } else if (arg.is_long(&l) == EC_succeed) {
365		vargs[i] = IntVar(*solver,(int)l,(int)l);
366		intsp->push(&vargs[i]);
367	    } else
368		return TYPE_ERROR;
369	}
370	return EC_succeed;
371    }
372    CatchAndReportGecodeExceptions
373}
374
375int assign_IntVarArgs_from_ec_array(GecodeSpace* solver, int size,
376				    EC_word ecarr, IntVarArgs& vargs)
377{
378    EC_functor f;
379    EC_word arg;
380    long l;
381
382    try {
383	for(int i=0; i<size; i++) {
384	    arg = EC_argument(ecarr, i+1);
385	    if (arg.functor(&f) == EC_succeed) {
386		if  (strcmp(f.name(), "_ivar") == 0
387		     && EC_argument(arg, 1).is_long(&l) == EC_succeed) {
388		    vargs[i] = solver->vInt[(int)l];
389		} else
390		    return RANGE_ERROR;
391	    } else if (arg.is_long(&l) == EC_succeed) {
392		vargs[i] = IntVar(*solver,(int)l,(int)l);
393	    } else
394		return TYPE_ERROR;
395	}
396	return EC_succeed;
397    }
398    CatchAndReportGecodeExceptions
399}
400
401int assign_IntArgs_from_ec_array(int size, EC_word ecarr, IntArgs& vargs)
402{
403    EC_word arg;
404    long l;
405
406    try {
407	for(int i=0; i<size; i++) {
408	    arg = EC_argument(ecarr, i+1);
409	    if (arg.is_long(&l) == EC_succeed) {
410		vargs[i] = (int)l;
411	    } else
412		return TYPE_ERROR;
413	}
414	return EC_succeed;
415    }
416    CatchAndReportGecodeExceptions
417}
418
419int assign_BoolVarArgs_from_ec_array(GecodeSpace* solver, int size,
420				    EC_word ecarr, BoolVarArgs& vargs)
421{
422    EC_functor f;
423    EC_word arg;
424    long l;
425
426    try {
427	for(int i=0; i<size; i++) {
428	    arg = EC_argument(ecarr, i+1);
429	    if (arg.functor(&f) == EC_succeed) {
430		if  (strcmp(f.name(), "_ivar") == 0
431		     && EC_argument(arg, 2).is_long(&l) == EC_succeed) {
432		    vargs[i] = solver->vBool[(int)l];
433		} else
434		    return RANGE_ERROR;
435	    } else if (arg.is_long(&l) == EC_succeed) {
436		if (l < 0 || l > 1) return RANGE_ERROR;
437 		vargs[i] = BoolVar(*solver,(int)l,(int)l);
438	    } else {
439		return TYPE_ERROR;
440	    }
441	}
442	return EC_succeed;
443    }
444    CatchAndReportGecodeExceptions
445}
446
447void cache_domain_sizes(GecodeSpace* solver) {
448    int snapshotsize = solver->dom_snapshot.size();
449    int varsize = solver->vInt.size();
450
451    if (varsize > snapshotsize) {
452	solver->dom_snapshot.reserve(varsize);
453    }
454    if (!solver->snapshot_valid()) {
455	for (int i=1; i < snapshotsize; i++) {
456	    solver->dom_snapshot[i] = solver->vInt[i].size();
457	}
458	solver->set_snapshot();
459    }
460    for (int i = snapshotsize; i<varsize; i++) {
461	    solver->dom_snapshot.push_back(solver->vInt[i].size());
462    }
463
464}
465
466// Initial initialisation, called when library is loaded
467extern "C" VisAtt
468int p_g_init()
469{
470    d_max_wdeg2 = ec_did("max_weighted_degree", 2);
471    d_min_wdeg2 = ec_did("min_weighted_degree", 2);
472    d_max_wdeg_per_val2 = ec_did("max_weighted_degree_per_value", 2);
473    d_min_wdeg_per_val2 = ec_did("min_weighted_degree_per_value", 2);
474    d_max_wdeg1 = ec_did("max_weighted_degree", 1);
475    d_min_wdeg1 = ec_did("min_weighted_degree", 1);
476    d_max_wdeg_per_val1 = ec_did("max_weighted_degree_per_value", 1);
477    d_min_wdeg_per_val1 = ec_did("min_weighted_degree_per_value", 1);
478    d_max_wdeg = ec_did("max_weighted_degree", 0);
479    d_min_wdeg = ec_did("min_weighted_degree", 0);
480    d_max_wdeg_per_val = ec_did("max_weighted_degree_per_value", 0);
481    d_min_wdeg_per_val = ec_did("min_weighted_degree_per_value", 0);
482    d_ff = ec_did("first_fail", 0);
483    d_antiff = ec_did("anti_first_fail", 0);
484    d_occ = ec_did("occurrence", 0);
485    d_antiocc = ec_did("anti_occurrence", 0);
486    d_smallest = ec_did("smallest", 0);
487    d_largest = ec_did("largest", 0);
488    d_smallest_upb = ec_did("smallest_upb", 0);
489    d_largest_lwb = ec_did("largest_lwb", 0);
490    d_max_regret = ec_did("max_regret", 0);
491    d_max_regret_lwb = ec_did("max_regret_lwb", 0);
492    d_max_regret_upb = ec_did("max_regret_upb", 0);
493    d_min_regret_lwb = ec_did("min_regret_lwb", 0);
494    d_min_regret_upb = ec_did("min_regret_upb", 0);
495    d_most_constrained_per_val = ec_did("most_constrained_per_value", 0);
496    d_most_constrained = ec_did("most_constrained", 0);
497    d_least_constrained_per_val = ec_did("least_constrained_per_value", 0);
498    d_input_order = ec_did("input_order", 0);
499    d_random = ec_did("random", 0);
500    d_random1 = ec_did("random", 1);
501    d_max_act2 = ec_did("max_activity", 2);
502    d_max_act_per_val2 = ec_did("max_activity_per_value", 2);
503    d_min_act2 = ec_did("min_activity", 2);
504    d_min_act_per_val2 = ec_did("min_activity_per_value", 2);
505    d_max_act1 = ec_did("max_activity", 1);
506    d_max_act_per_val1 = ec_did("max_activity_per_value", 1);
507    d_min_act1 = ec_did("min_activity", 1);
508    d_min_act_per_val1 = ec_did("min_activity_per_value", 1);
509    d_max_act = ec_did("max_activity", 0);
510    d_max_act_per_val = ec_did("max_activity_per_value", 0);
511    d_min_act = ec_did("min_activity", 0);
512    d_min_act_per_val = ec_did("min_activity_per_value", 0);
513    d_fr_sm1 = ec_did("from_smaller", 1);
514    d_fr_lg1 = ec_did("from_larger", 1);
515    d_fr_up1 = ec_did("from_up", 1);
516    d_fr_down1 = ec_did("from_down", 1);
517
518    d_default = ec_did("default", 0);
519    d_gac = ec_did("gfd_gac", 0);
520    d_bc = ec_did("gfd_bc", 0);
521    d_vc = ec_did("gfd_vc", 0);
522    d_colon2 = ec_did(":", 2);
523
524    d_eq = ec_did("#=", 0);
525    d_neq = ec_did("#\\=", 0);
526    d_gt = ec_did("#>", 0);
527    d_lt = ec_did("#<", 0);
528    d_geq = ec_did("#>=", 0);
529    d_leq = ec_did("#=<", 0);
530
531    d_eq2 = ec_did("#=", 2);
532    d_neq2 = ec_did("#\\=", 2);
533    d_gt2 = ec_did("#>", 2);
534    d_lt2 = ec_did("#<", 2);
535    d_geq2 = ec_did("#>=", 2);
536    d_leq2 = ec_did("#=<", 2);
537
538    d_sum2 = ec_did("sum", 2);
539    d_element2 = ec_did("element", 2);
540    d_max2 = ec_did("max", 2);
541    d_min2 = ec_did("min", 2);
542    d_rem2 = ec_did("rem", 2);
543    d_plus2 = ec_did("+", 2);
544    d_minus2 = ec_did("-", 2);
545    d_mult2 = ec_did("*", 2);
546    d_div2 = ec_did("//", 2);
547    d_minus1 = ec_did("-", 1);
548    d_abs1 = ec_did("abs", 1);
549    d_sqr1 = ec_did("sqr", 1);
550    d_isqrt1 = ec_did("isqrt", 1);
551    d_pow2 = ec_did("pow", 2);
552    d_inroot2 = ec_did("inroot", 2);
553    d_sum1 = ec_did("sum", 1);
554    d_max1 = ec_did("max", 1);
555    d_min1 = ec_did("min", 1);
556    d_and2 = ec_did("and", 2);
557    d_or2 = ec_did("or", 2);
558    d_xor2 = ec_did("xor", 2);
559    d_imp2 = ec_did("=>", 2);
560    d_equ2 = ec_did("<=>", 2);
561    d_neg1 = ec_did("neg", 1);
562    d_equ = ec_did("<=>", 0);
563    d_imp = ec_did("=>", 0);
564    d_impby = ec_did("<==", 0);
565
566    d_iv2 = ec_did("_ivar", 2);
567
568    d_geo2 = ec_did("geo", 2);
569    d_luby1 = ec_did("luby", 1);
570    d_rand4 = ec_did("rand", 4);
571    d_con1 = ec_did("con", 1);
572    d_lin1 = ec_did("lin", 1);
573
574    return EC_succeed;
575
576}
577
578// C++ level initialisation of space handle
579extern "C" VisAtt
580int p_g_init_space_handle_c()
581{
582    GecodeSpace** solverp = new GecodeSpace*;
583
584    *solverp = NULL;
585    return unify(EC_arg(1), handle(&gfd_method, solverp));
586}
587
588extern "C" VisAtt
589int p_g_trail_undo_for_event()
590{
591    GecodeSpace** solverp;
592    EC_functor f;
593    EC_word w;
594
595    if (EC_arg(1).functor(&f) != EC_succeed) return TYPE_ERROR;
596    if (strcmp(f.name(), "gfd_space") != 0) return TYPE_ERROR;
597    EC_arg(1).arg(SPACE_HANDLE_POS, w);
598    if (w.is_handle(&gfd_method, (void**)&solverp) != EC_succeed)
599	return TYPE_ERROR;
600
601    if (*solverp == NULL) return TYPE_ERROR; // should not happen!
602
603    ec_trail_undo(_g_delete_space, ec_arg(1).val.ptr, ec_arg(1).val.ptr+SPACE_STAMP_POS, NULL, 0, TRAILED_WORD32);
604
605    return EC_succeed;
606}
607
608extern "C" VisAtt
609int p_g_state_is_stable()
610{
611    GecodeSpace** solverp;
612    EC_functor f;
613    EC_word w;
614
615    if (EC_arg(1).functor(&f) != EC_succeed) return TYPE_ERROR;
616    EC_arg(1).arg(SPACE_HANDLE_POS, w);
617    if (w.is_handle(&gfd_method, (void**)&solverp) != EC_succeed)
618	return TYPE_ERROR;
619    try {
620	return ((*solverp)->stable() ? EC_succeed : EC_fail);
621    }
622    CatchAndReportGecodeExceptions
623
624}
625
626extern "C" VisAtt
627int p_g_check_handle()
628{
629    // trail_undo cannot be done here, because this space handle may be cloned
630    // and become an ancestor and not used for the current event
631    GecodeSpace** solverp;
632
633    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
634	return TYPE_ERROR;
635
636    if (*solverp == NULL) { // no valid current solver space, clone ancestor
637	if (EC_succeed == EC_arg(2).is_nil()) { // no ancestor, make new space
638	    *solverp = new GecodeSpace();
639	    (*solverp)->afc_decay(1.0);
640	} else { // clone ancestor
641	    GecodeSpace** ancestorp;
642	    EC_functor f;
643	    EC_word w;
644
645	    if (EC_arg(2).functor(&f) != EC_succeed) return TYPE_ERROR;
646	    if (strcmp(f.name(), "gfd_space") != 0) return TYPE_ERROR;
647	    EC_arg(2).arg(SPACE_HANDLE_POS, w);
648	    if (w.is_handle(&gfd_method, (void**)&ancestorp) != EC_succeed)
649		return TYPE_ERROR;
650	    *solverp = static_cast<GecodeSpace*>((*ancestorp)->clone());
651	}
652
653	// cloned -- instantiate arg(3) to []
654	return unify(EC_arg(3), nil());
655    } else {
656	// not cloned -- leave arg(3) uninstantiated
657	return EC_succeed;
658	}
659}
660
661
662extern "C" VisAtt
663int p_g_delete()
664{
665    GecodeSpace** solverp;
666
667    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
668	return TYPE_ERROR;
669
670    if (*solverp != NULL) delete *solverp;
671    *solverp = NULL;
672
673    return EC_succeed;
674}
675
676extern "C" VisAtt
677int p_g_get_var_value()
678{
679    long idx;
680    int val;
681    GecodeSpace** solverp;
682    GecodeSpace* solver;
683
684    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
685	return TYPE_ERROR;
686    solver = *solverp;
687    if (solver == NULL) return EC_fail;
688
689    if (EC_succeed != EC_arg(2).is_long(&idx)) return(TYPE_ERROR);
690
691    try {
692	val = solver->vInt[(int)idx].val();
693	return unify(EC_arg(3), EC_word((long)val));
694    }
695    catch(Int::ValOfUnassignedVar) {
696	return EC_fail;
697    }
698    CatchAndReportGecodeExceptions
699}
700
701extern "C" VisAtt
702int p_g_check_val_is_in_var_domain()
703{
704    long idx, val;
705    GecodeSpace** solverp;
706    GecodeSpace* solver;
707
708    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
709	return TYPE_ERROR;
710    solver = *solverp;
711    if (solver == NULL) return EC_fail;
712
713    if (EC_succeed != EC_arg(2).is_long(&idx)) return(TYPE_ERROR);
714
715    if (EC_succeed != EC_arg(3).is_long(&val)) return(TYPE_ERROR);
716
717    try {
718	if (solver->vInt[(int)idx].in((int)val))
719	    return EC_succeed;
720	else return EC_fail;
721    }
722    CatchAndReportGecodeExceptions
723
724}
725
726extern "C" VisAtt
727int p_g_get_var_bounds()
728{
729    long idx;
730    GecodeSpace** solverp;
731    GecodeSpace* solver;
732
733    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
734	return TYPE_ERROR;
735    solver = *solverp;
736    if (EC_succeed != EC_arg(2).is_long(&idx)) return(TYPE_ERROR);
737
738    /* idx outside current array size ==> idx is for new variable that
739       has not yet been added to the solver space. Normally the domain of
740       such variables cannot be accessed, but exceptions such as the tracer
741       tracing the ECLiPSe level code can occur internally. Just return []
742    */
743    if (solver == NULL || idx >= solver->vInt.size()) return RANGE_ERROR;
744    try {
745	int res;
746	res = unify(EC_arg(3), EC_word(solver->vInt[(int)idx].min()));
747	if (res != EC_succeed) return res;
748	return unify(EC_arg(4), EC_word(solver->vInt[(int)idx].max()));
749    }
750    CatchAndReportGecodeExceptions
751
752}
753
754extern "C" VisAtt
755int p_g_get_var_lwb()
756{
757    long idx;
758    GecodeSpace** solverp;
759    GecodeSpace* solver;
760
761    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
762	return TYPE_ERROR;
763    solver = *solverp;
764    if (EC_succeed != EC_arg(2).is_long(&idx)) return(TYPE_ERROR);
765
766    if (solver == NULL || idx >= solver->vInt.size()) return RANGE_ERROR;
767
768    try {
769	return unify(EC_arg(3), EC_word(solver->vInt[(int)idx].min()));
770    }
771    CatchAndReportGecodeExceptions
772}
773
774extern "C" VisAtt
775int p_g_update_and_get_var_bound()
776{
777    long idx;
778    EC_functor f;
779    EC_word w;
780    GecodeSpace** solverp;
781    GecodeSpace* solver;
782
783    if (EC_arg(1).functor(&f) != EC_succeed) return TYPE_ERROR;
784    if (strcmp(f.name(), "gfd_space") != 0) return TYPE_ERROR;
785    EC_arg(1).arg(SPACE_HANDLE_POS, w);
786    if (w.is_handle(&gfd_method, (void**)&solverp) != EC_succeed)
787	return TYPE_ERROR;
788
789    if (*solverp == NULL) return TYPE_ERROR;
790
791    solver = *solverp;
792    if (EC_succeed != EC_arg(2).is_long(&idx)) return(TYPE_ERROR);
793
794    if (solver == NULL || idx >= solver->vInt.size()) return RANGE_ERROR;
795    long val;
796    if (EC_succeed != EC_arg(3).is_long(&val)) return(TYPE_ERROR);
797
798    // update lower bound before getting it
799    long which;
800    if (EC_succeed != EC_arg(4).is_long(&which)) return(TYPE_ERROR);
801    IntRelType relop = (which == -1 ? IRT_GR : IRT_LE);
802
803    cache_domain_sizes(solver); // get snapshot
804
805    try {
806	rel(*solver, solver->vInt[(int)idx], relop, (int)val);
807
808	// we need to do trail undo here so that if failure occurs before
809	// an event is executed, the current space is correctly discarded
810	ec_trail_undo(_g_delete_space, ec_arg(1).val.ptr, ec_arg(1).val.ptr+SPACE_STAMP_POS, NULL, 0, TRAILED_WORD32);
811
812	if (!solver->status()) return EC_fail;
813
814	return (which == -1 ?
815		unify(EC_arg(5), EC_word(solver->vInt[(int)idx].min())) :
816		unify(EC_arg(5), EC_word(solver->vInt[(int)idx].max())));
817
818    }
819    CatchAndReportGecodeExceptions
820}
821
822extern "C" VisAtt
823int p_g_get_var_upb()
824{
825    long idx;
826    GecodeSpace** solverp;
827    GecodeSpace* solver;
828
829    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
830	return TYPE_ERROR;
831    solver = *solverp;
832    if (EC_succeed != EC_arg(2).is_long(&idx)) return(TYPE_ERROR);
833
834    if (solver == NULL || idx >= solver->vInt.size()) return RANGE_ERROR;
835
836    try {
837	return unify(EC_arg(3), EC_word(solver->vInt[(int)idx].max()));
838    }
839    CatchAndReportGecodeExceptions
840}
841
842extern "C" VisAtt
843int p_g_get_var_domain_size()
844{
845    long idx;
846    GecodeSpace** solverp;
847    GecodeSpace* solver;
848
849    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
850	return TYPE_ERROR;
851    solver = *solverp;
852    if (EC_succeed != EC_arg(2).is_long(&idx)) return(TYPE_ERROR);
853
854    if (solver == NULL || idx >= solver->vInt.size()) return RANGE_ERROR;
855
856    try {
857	return unify(EC_arg(3), EC_word((long)solver->vInt[(int)idx].size()));
858    }
859    CatchAndReportGecodeExceptions
860}
861
862extern "C" VisAtt
863int p_g_get_var_domain_width()
864{
865    long idx;
866    GecodeSpace** solverp;
867    GecodeSpace* solver;
868
869    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
870	return TYPE_ERROR;
871    solver = *solverp;
872    if (EC_succeed != EC_arg(2).is_long(&idx)) return(TYPE_ERROR);
873
874    if (solver == NULL || idx >= solver->vInt.size()) return RANGE_ERROR;
875
876    try {
877	return unify(EC_arg(3), EC_word((long)solver->vInt[(int)idx].width()));
878    }
879    CatchAndReportGecodeExceptions
880}
881
882extern "C" VisAtt
883int p_g_get_var_median()
884{
885    long idx;
886    GecodeSpace** solverp;
887    GecodeSpace* solver;
888
889    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
890	return TYPE_ERROR;
891    solver = *solverp;
892    if (EC_succeed != EC_arg(2).is_long(&idx)) return(TYPE_ERROR);
893
894    if (solver == NULL || idx >= solver->vInt.size()) return RANGE_ERROR;
895
896    try {
897	return unify(EC_arg(3), EC_word((long)solver->vInt[(int)idx].med()));
898    }
899    CatchAndReportGecodeExceptions
900}
901
902extern "C" VisAtt
903int p_g_get_var_degree()
904{
905    long idx;
906    GecodeSpace** solverp;
907    GecodeSpace* solver;
908
909    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
910	return TYPE_ERROR;
911    solver = *solverp;
912    if (EC_succeed != EC_arg(2).is_long(&idx)) return(TYPE_ERROR);
913
914    if (solver == NULL || idx >= solver->vInt.size()) return RANGE_ERROR;
915
916    try {
917	return unify(EC_arg(3), EC_word((long)solver->vInt[(int)idx].degree()));
918    }
919    CatchAndReportGecodeExceptions
920}
921
922extern "C" VisAtt
923int p_g_get_var_afc()
924{
925    long idx;
926    GecodeSpace** solverp;
927    GecodeSpace* solver;
928
929    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
930	return TYPE_ERROR;
931    solver = *solverp;
932    if (EC_succeed != EC_arg(2).is_long(&idx)) return(TYPE_ERROR);
933
934    if (solver == NULL || idx >= solver->vInt.size()) return RANGE_ERROR;
935
936    try {
937	return unify(EC_arg(3), EC_word(solver->vInt[(int)idx].afc(*solver)));
938    }
939    CatchAndReportGecodeExceptions
940}
941
942extern "C" VisAtt
943int p_g_get_var_regret_lwb()
944{
945    long idx;
946    GecodeSpace** solverp;
947    GecodeSpace* solver;
948
949    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
950	return TYPE_ERROR;
951    solver = *solverp;
952    if (EC_succeed != EC_arg(2).is_long(&idx)) return(TYPE_ERROR);
953
954    if (solver == NULL || idx >= solver->vInt.size()) return RANGE_ERROR;
955
956    try {
957	return unify(EC_arg(3), EC_word((long)solver->vInt[(int)idx].regret_min()));
958    }
959    CatchAndReportGecodeExceptions
960}
961
962extern "C" VisAtt
963int p_g_get_var_regret_upb()
964{
965    long idx;
966    GecodeSpace** solverp;
967    GecodeSpace* solver;
968
969    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
970	return TYPE_ERROR;
971    solver = *solverp;
972    if (EC_succeed != EC_arg(2).is_long(&idx)) return(TYPE_ERROR);
973
974    if (solver == NULL || idx >= solver->vInt.size()) return RANGE_ERROR;
975
976    try {
977	return unify(EC_arg(3), EC_word((long)solver->vInt[(int)idx].regret_max()));
978    }
979    CatchAndReportGecodeExceptions
980}
981
982extern "C" VisAtt
983int p_g_get_var_domain()
984{
985    long idx;
986    int min, max;
987    int first = 0;
988    EC_word l, tail, oldtail, domlist;
989    EC_functor dotdot((char*)"..", 2);
990    GecodeSpace** solverp;
991    GecodeSpace* solver;
992
993    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
994	return TYPE_ERROR;
995    solver = *solverp;
996    if (EC_succeed != EC_arg(2).is_long(&idx)) return(TYPE_ERROR);
997
998    /* idx outside current array size ==> idx is for new variable that
999       has not yet been added to the solver space. Normally the domain of
1000       such variables cannot be accessed, but exceptions such as the tracer
1001       tracing the ECLiPSe level code can occur internally. Just return []
1002       Also return [] if solver not defined -- state have not been recomputed
1003    */
1004    try {
1005	if (solver == NULL || idx >= solver->vInt.size()) return unify(EC_arg(3), nil());
1006
1007	for (IntVarRanges i(solver->vInt[idx]); i(); ++i) {
1008	    min = i.min();
1009	    max = i.max();
1010	    if (min == max) { // single number
1011		l = list(EC_word(max), tail = ec_newvar());
1012	    } else if (min == max - 1) { // 2 value interval
1013		l = list(EC_word(min), list(EC_word(max), tail = ec_newvar()));
1014	    } else {
1015		l = list(term(dotdot, EC_word(min), EC_word(max)), tail = ec_newvar());
1016	    }
1017	    if (first == 0) domlist = l;
1018	    else unify(oldtail, l);
1019	    first = 1;
1020	    oldtail = tail;
1021	}
1022    }
1023    CatchAndReportGecodeExceptions
1024
1025    unify(oldtail, nil());
1026
1027    return (unify(EC_arg(3), domlist));
1028}
1029
1030extern "C" VisAtt
1031int p_g_add_newvars_interval()
1032{
1033    GecodeSpace** solverp;
1034    GecodeSpace* solver;
1035    long newsize, min, max;
1036    int oldsize, snapshotsize;
1037
1038    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1039	return TYPE_ERROR;
1040    solver = *solverp;
1041    if (solver == NULL) return TYPE_ERROR;
1042    if (EC_succeed != EC_arg(2).is_long(&newsize)) return(TYPE_ERROR);
1043    if (EC_succeed != EC_arg(3).is_long(&min)) return(TYPE_ERROR);
1044    if (EC_succeed != EC_arg(4).is_long(&max)) return(TYPE_ERROR);
1045    oldsize = solver->vInt.size();
1046
1047    try {
1048      //	solver->vInt.resize(*solver, (int)++newsize); // ++ as we don't use 0
1049      for (int i=oldsize; i <= (int)newsize; i++) {
1050	  solver->vInt << IntVar(*solver, (int)min, (int)max);
1051      }
1052    }
1053    CatchAndReportGecodeExceptions
1054
1055    return EC_succeed;
1056}
1057
1058
1059extern "C" VisAtt
1060int p_g_add_newvars_as_bool()
1061{
1062    // add new vars as booleans to problem -- add new IntVars and link them
1063    // them with new BoolVars
1064    GecodeSpace** solverp;
1065    GecodeSpace* solver;
1066    long newsize;
1067    int oldsize, snapshotsize;
1068
1069    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1070	return TYPE_ERROR;
1071    solver = *solverp;
1072    if (solver == NULL) return TYPE_ERROR;
1073    if (EC_succeed != EC_arg(2).is_long(&newsize)) return(TYPE_ERROR);
1074    oldsize = solver->vInt.size();
1075    EC_word varr = EC_arg(3);
1076
1077    int varrsize = varr.arity();
1078    if (varrsize == 0) return TYPE_ERROR;
1079    // ++newsize as we don't use 0 for index
1080    if (varrsize != ++newsize - oldsize) return RANGE_ERROR;
1081
1082
1083    try {
1084	for (int i=oldsize,argi=1; i < (int)newsize; i++,argi++) {
1085	    solver->vInt << IntVar(*solver, 0, 1);
1086	    solver->vBool << BoolVar(*solver,0, 1);
1087	    int bidx = solver->vBool.size() - 1;
1088	    channel(*solver,  solver->vInt[i], solver->vBool[bidx]);
1089	    EC_word arg = EC_argument(varr, argi);
1090	    EC_functor f;
1091	    if (arg.functor(&f) == EC_succeed &&
1092		strcmp(f.name(), "_ivar") == 0 &&
1093		arg.arity() == 2) {
1094		int res = unify(EC_argument(arg, 2), EC_word((long)bidx));
1095		if (res != EC_succeed) return res;
1096
1097		res = unify(EC_argument(arg,1), EC_word((long)i));
1098		if (res != EC_succeed) return res;
1099
1100	    } else return TYPE_ERROR;
1101	}
1102    }
1103    CatchAndReportGecodeExceptions
1104
1105    return EC_succeed;
1106}
1107
1108extern "C" VisAtt
1109int p_g_add_newbool()
1110{
1111    GecodeSpace** solverp;
1112    GecodeSpace* solver;
1113
1114    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1115	return TYPE_ERROR;
1116    solver = *solverp;
1117    if (solver == NULL) return TYPE_ERROR;
1118
1119    // 2015-06-28 fix for bug#789  boolean may be linked to an existing
1120    // IntVar whose bounds could change (or even become singleton)
1121    if (solver->is_first()) cache_domain_sizes(solver);
1122
1123    try {
1124        solver->vBool << BoolVar(*solver,0,1);
1125	int bidx = solver->vBool.size()-1;
1126	long i;
1127
1128	if (EC_succeed != EC_arg(2).is_long(&i)) return TYPE_ERROR;
1129	channel(*solver, solver->vInt[(int)i], solver->vBool[bidx]);
1130	return unify(EC_arg(3), EC_word(bidx));
1131    }
1132    CatchAndReportGecodeExceptions
1133
1134}
1135
1136extern "C" VisAtt
1137int p_g_link_newbools()
1138{
1139    GecodeSpace** solverp;
1140    GecodeSpace* solver;
1141
1142    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1143	return TYPE_ERROR;
1144    solver = *solverp;
1145    if (solver == NULL) return TYPE_ERROR;
1146
1147    EC_word varr = EC_arg(2);
1148    int varrsize = varr.arity();
1149    if (varrsize == 0) return TYPE_ERROR;
1150
1151    // 2015-06-28 fix for bug#789  booleans are  linked to existing
1152    // IntVars whose bounds could change (or even become singleton)
1153    if (solver->is_first()) cache_domain_sizes(solver);
1154
1155    try {
1156	for (int i=1; i <= varrsize; i++) {
1157
1158	    EC_word arg = EC_argument(varr, i);
1159	    EC_functor f;
1160	    long vidx;
1161	    if (arg.functor(&f) == EC_succeed &&
1162		strcmp(f.name(), "_ivar") == 0 &&
1163		arg.arity() == 2 &&
1164		EC_argument(arg,1).is_long(&vidx) == EC_succeed) {
1165
1166		long bidx;
1167		if (EC_argument(arg, 2).is_long(&bidx) != EC_succeed) {
1168		    // not yet linked, create link to new BoolVar
1169		    solver->vBool << BoolVar(*solver,0,1);
1170		    bidx = (long) solver->vBool.size()-1;
1171		    channel(*solver,  solver->vInt[vidx], solver->vBool[(int)bidx]);
1172		    int res = unify(EC_argument(arg, 2), EC_word((long)bidx));
1173		    if (res != EC_succeed) return res;
1174		}
1175	    } else return TYPE_ERROR;
1176	}
1177
1178    }
1179    CatchAndReportGecodeExceptions
1180
1181    return EC_succeed;
1182}
1183
1184extern "C" VisAtt
1185int p_g_add_newvars_dom()
1186{
1187    GecodeSpace** solverp;
1188    GecodeSpace* solver;
1189    long newsize;
1190    int oldsize;
1191
1192    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1193	return TYPE_ERROR;
1194    solver = *solverp;
1195    if (solver == NULL) return TYPE_ERROR;
1196    if (EC_succeed != EC_arg(2).is_long(&newsize)) return(TYPE_ERROR);
1197    oldsize = solver->vInt.size();
1198
1199    EC_word darr = EC_arg(3);
1200    int dsize = darr.arity();
1201    int ranges[dsize][2];
1202    if (dsize == 0) return TYPE_ERROR;
1203
1204    int res = get_domain_intervals_from_ec_array(dsize, darr, ranges);
1205    if (res != EC_succeed) return res;
1206    IntSet domset(ranges, dsize);
1207
1208    try {
1209      //	solver->vInt.resize(*solver, (int)++newsize); // ++ to skip over idx 0
1210	for (int i=oldsize; i <= (int)newsize; i++)
1211	  solver->vInt << IntVar(*solver, domset);
1212    }
1213    CatchAndReportGecodeExceptions
1214
1215    return EC_succeed;
1216}
1217
1218extern "C" VisAtt
1219int p_g_add_newvars_dom_handle()
1220{
1221    GecodeSpace** solverp;
1222    GecodeSpace* solver;
1223    long newsize;
1224    int oldsize;
1225
1226    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1227	return TYPE_ERROR;
1228    solver = *solverp;
1229    if (solver == NULL) return TYPE_ERROR;
1230    if (EC_succeed != EC_arg(2).is_long(&newsize)) return(TYPE_ERROR);
1231    oldsize = solver->vInt.size();
1232
1233    IntSet* domp;
1234    if (EC_succeed != get_handle_from_arg(3, &domain_method, (void**)&domp))
1235	return TYPE_ERROR;
1236    if (domp == NULL) return TYPE_ERROR;
1237
1238    try {
1239      //	solver->vInt.resize(*solver, (int)++newsize); // ++ to skip over idx 0
1240	for (int i=oldsize; i <= (int)newsize; i++)
1241	  solver->vInt << IntVar(*solver, *domp);
1242    }
1243    CatchAndReportGecodeExceptions
1244
1245    return EC_succeed;
1246}
1247
1248#define Return_ExprListArg(e, minsize, solver, EXPR) {	\
1249     EC_word varr = EC_argument(e,1); \
1250     int size = varr.arity(); \
1251     if (size >= minsize) { \
1252	 IntVarArgs vars(size); \
1253	 if (assign_IntVarArgs_from_ec_array(solver, size, varr, vars) \
1254	     != EC_succeed) \
1255		throw Ec2gcException(); \
1256         return EXPR; \
1257     } \
1258}
1259
1260LinIntExpr
1261ec2intexpr(EC_word e, GecodeSpace* solver)
1262{
1263    long l;
1264    int i;
1265    EC_functor f;
1266    LinIntExpr arg1(BoolVar(*solver,1,1)), arg2(BoolVar(*solver,1,1));
1267
1268    if (e.functor(&f) == EC_succeed) {
1269	if (f.d == d_iv2 &&
1270	    //if (strcmp(f.name(), "_ivar") == 0 &&
1271	    EC_argument(e, 1).is_long(&l) == EC_succeed) {
1272	    i = (int)l;
1273	    return solver->vInt[i];
1274	} else {
1275	    switch (f.arity()) {
1276	    case 1: {
1277		if (f.d == d_sum1) {
1278		    Return_ExprListArg(e, 0, solver, sum(vars));
1279
1280		} else if (f.d == d_max1) {
1281		    Return_ExprListArg(e, 1, solver, max(vars));
1282
1283		} else if (f.d == d_min1) {
1284		    Return_ExprListArg(e, 1, solver, min(vars));
1285
1286
1287		} else {
1288		    arg2 = ec2intexpr(EC_argument(e, 1), solver);
1289
1290		    if (f.d == d_minus1) return -arg2;
1291		    else if (f.d == d_abs1) return abs(arg2);
1292		    else if (f.d == d_sqr1) return sqr(arg2);
1293		    else if (f.d == d_isqrt1) return sqrt(arg2);
1294		}
1295		break;
1296	    }
1297	    case 2: {
1298		if (f.d == d_sum2) {
1299		  EC_word carr = EC_argument(e,1);
1300		  EC_word varr = EC_argument(e,2);
1301		  int size = varr.arity();
1302
1303		  IntVarArgs vars(size);
1304		  if (assign_IntVarArgs_from_ec_array(solver, size, varr, vars) != EC_succeed)
1305		      throw Ec2gcException();
1306		  IntArgs cs(size);
1307		  if (assign_IntArgs_from_ec_array(size, carr, cs) == EC_succeed)
1308		      return sum(cs, vars);
1309
1310		} else if (f.d == d_pow2) {
1311		    arg1 = ec2intexpr(EC_argument(e, 1), solver);
1312		    if (EC_argument(e,2).is_long(&l) != EC_succeed)
1313			throw Ec2gcException();
1314		    return pow(arg1, (int)l);
1315
1316		} else if (f.d == d_inroot2) {
1317		    arg1 = ec2intexpr(EC_argument(e, 1), solver);
1318		    if (EC_argument(e,2).is_long(&l) != EC_succeed)
1319			throw Ec2gcException();
1320		    return nroot(arg1, (int)l);
1321
1322		} else if (f.d == d_colon2) {
1323		    EC_atom atm;
1324		    if (EC_argument(e,1).is_atom(&atm) != EC_succeed)
1325			throw Ec2gcException();
1326		    IntConLevel cl;
1327		    Assign_Consistency_Level(atm, cl, THROW_ECEXCEPT);
1328
1329		    return expr(*solver, ec2intexpr(EC_argument(e, 2), solver), cl);
1330
1331		} else if (f.d == d_element2) {
1332		    // element(<IdxExpr>, <Vars>)
1333		    EC_word varr = EC_argument(e,2);
1334		    int size = varr.arity();
1335		    IntVarArgs vars(size);
1336		    if (assign_IntVarArgs_from_ec_array(solver, size, varr, vars) == EC_succeed)
1337			return element(vars, ec2intexpr(EC_argument(e, 1), solver));
1338		} else {
1339
1340		    arg2 = ec2intexpr(EC_argument(e, 2), solver);
1341		    arg1 = ec2intexpr(EC_argument(e, 1), solver);
1342
1343		    if (f.d == d_plus2)       return (arg1 + arg2);
1344		    else if (f.d == d_minus2) return (arg1 - arg2);
1345		    else if (f.d == d_mult2)  return (arg1 * arg2);
1346		    else if (f.d == d_min2)   return  min(arg1, arg2);
1347		    else if (f.d == d_max2)   return max(arg1, arg2);
1348		    else if (f.d == d_rem2)   return (arg1 % arg2);
1349		    else if (f.d == d_div2)   return (arg1 / arg2);
1350
1351		}
1352		break;
1353	    }} /* switch */
1354	}
1355    } else if (e.is_long(&l) == EC_succeed) { // Integer
1356        return (int)l;
1357        //i = (int)l;
1358	//	return (solver->vInt[0] + i); // vInt[0] has value 0, needed as dummy
1359    }
1360
1361    // Unknown integer expression
1362    throw Ec2gcException();
1363}
1364
1365LinIntRel
1366ec2intrel(EC_word c, GecodeSpace* solver)
1367{
1368    EC_functor f;
1369
1370    if (c.functor(&f) == EC_succeed && f.arity() == 2) {
1371	LinIntExpr arg1 = ec2intexpr(EC_argument(c,1), solver);
1372	LinIntExpr arg2 = ec2intexpr(EC_argument(c,2), solver);
1373
1374	if (f.d == d_eq2) return (arg1 == arg2);
1375	else if (f.d == d_gt2) return (arg1 > arg2);
1376	else if (f.d == d_geq2) return (arg1 >= arg2);
1377	else if (f.d == d_lt2) return (arg1 < arg2);
1378	else if (f.d == d_leq2) return (arg1 <= arg2);
1379	else if (f.d == d_neq2) return (arg1 != arg2);
1380
1381	// Unknown binary constraint
1382	throw Ec2gcException();
1383    } else
1384	throw Ec2gcException();
1385}
1386
1387BoolExpr
1388ec2boolexpr(EC_word c, GecodeSpace*solver)
1389{
1390    EC_functor f;
1391    long l;
1392
1393    if (c.functor(&f) == EC_succeed) {
1394	if (f.d == d_iv2) {
1395	    if (EC_argument(c,2).is_long(&l) != EC_succeed)
1396		throw Ec2gcException();
1397	    return solver->vBool[(int)l];
1398
1399	} else if (f.d == d_and2) {
1400	    return (ec2boolexpr(EC_argument(c,1), solver) &&
1401		    ec2boolexpr(EC_argument(c,2), solver)
1402		    );
1403	} else if (f.d == d_or2) {
1404	    return (ec2boolexpr(EC_argument(c,1), solver) ||
1405		    ec2boolexpr(EC_argument(c,2), solver)
1406		    );
1407	} else if (f.d == d_xor2) {
1408	    return (ec2boolexpr(EC_argument(c,1), solver) ^
1409		    ec2boolexpr(EC_argument(c,2), solver)
1410		    );
1411	} else if (f.d == d_imp2) {
1412	    return (ec2boolexpr(EC_argument(c,1), solver) >>
1413		    ec2boolexpr(EC_argument(c,2), solver)
1414		    );
1415	} else if (f.d == d_equ2) {
1416	    return (ec2boolexpr(EC_argument(c,1), solver) ==
1417		    ec2boolexpr(EC_argument(c,2), solver)
1418		    );
1419
1420	} else if (f.d == d_neg1) {
1421	    return !ec2boolexpr(EC_argument(c,1), solver);
1422
1423	} else if (f.d == d_element2) {
1424	    EC_word barr = EC_argument(c,2);
1425	    int size = barr.arity();
1426
1427	    BoolVarArgs bools(size);
1428	    if (assign_BoolVarArgs_from_ec_array(solver, size, barr, bools) !=
1429		EC_succeed) throw Ec2gcException();
1430
1431	    return element(bools, ec2intexpr(EC_argument(c,1), solver) );
1432
1433	} else if (f.d == d_colon2) {
1434	    EC_atom atm;
1435	    if (EC_argument(c,1).is_atom(&atm) != EC_succeed)
1436		throw Ec2gcException();
1437	    IntConLevel cl;
1438	    Assign_Consistency_Level(atm, cl, THROW_ECEXCEPT);
1439
1440	    return expr(*solver, ec2boolexpr(EC_argument(c, 2), solver), cl);
1441
1442	}
1443	// otherwise, treat as linear relation
1444	return ec2intrel(c, solver);
1445    } else if (c.is_long(&l) == EC_succeed) {
1446	switch (l) {
1447	    case 0:
1448		return solver->boolfalse;
1449		break;
1450	    case 1:
1451		return solver->booltrue;
1452		break;
1453	    default:
1454		throw Ec2gcException();
1455		break;
1456	}
1457    }
1458
1459    // Unknown boolean expression
1460    throw Ec2gcException();
1461}
1462
1463REG
1464ec2reg(EC_word e)
1465{
1466  long l;
1467  EC_functor f, f2;
1468  EC_word e2;
1469  REG arg1, arg2;
1470
1471  if (e.functor(&f) == EC_succeed) {
1472    if (strcmp(f.name(), "[]") == 0) {
1473      int size =  f.arity();
1474      IntArgs alts(size);
1475
1476      if (assign_IntArgs_from_ec_array(size, e, alts) != EC_succeed)
1477	throw Ec2gcException();
1478      return REG(alts);
1479    }
1480
1481    switch (f.arity()) {
1482    case 1:
1483      if (strcmp(f.name(), "*") == 0) {
1484	arg1 = ec2reg(EC_argument(e, 1));
1485	return *arg1;
1486      } else
1487      if (strcmp(f.name(), "+") == 0) {
1488	arg1 = ec2reg(EC_argument(e, 1));
1489	return +arg1;
1490      } else
1491	throw Ec2gcException();
1492      break;
1493    case 2:
1494      if (strcmp(f.name(), "+") == 0) {
1495	arg1 = ec2reg(EC_argument(e, 1));
1496	arg2 = ec2reg(EC_argument(e, 2));
1497	return arg1 + arg2;
1498      } else
1499      if (strcmp(f.name(), "|") == 0) {
1500	arg1 = ec2reg(EC_argument(e, 1));
1501	arg2 = ec2reg(EC_argument(e, 2));
1502	return arg1 | arg2;
1503      } else
1504      if (strcmp(f.name(), ",") == 0) {
1505	arg1 = ec2reg(EC_argument(e, 1));
1506	e2 = EC_argument(e,2);
1507
1508	if (e2.functor(&f2) == EC_succeed) {
1509	  long n, m;
1510
1511	  switch (f2.arity()) {
1512	  case 1:
1513	    // assume f2 is {}/1: {n}
1514	    if (EC_argument(e2,1).is_long(&n) == EC_succeed) {
1515	      return arg1((unsigned int)n);
1516	    } else
1517	      throw Ec2gcException();
1518	    break;
1519	  case 2:
1520	    // assume f2 is r/2: r(n,m)
1521	    if (EC_argument(e2,1).is_long(&n) == EC_succeed &&
1522		EC_argument(e2,2).is_long(&m) == EC_succeed) {
1523	      return arg1((unsigned int)n,(unsigned int)m);
1524	    } else
1525	      throw Ec2gcException();
1526	    break;
1527	  default:
1528	    throw Ec2gcException();
1529	  }
1530	} else
1531	  throw Ec2gcException();
1532      } else
1533	throw Ec2gcException();
1534
1535    default:
1536      throw Ec2gcException();
1537    }
1538  } else if (e.is_long(&l) == EC_succeed) {
1539    return REG((int)l);
1540  } else
1541    throw Ec2gcException();
1542
1543}
1544
1545
1546extern "C" VisAtt
1547int p_g_post_bool_connectives()
1548{
1549    GecodeSpace** solverp;
1550    GecodeSpace* solver;
1551
1552    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1553	return TYPE_ERROR;
1554    solver = *solverp;
1555    if (solver == NULL) return TYPE_ERROR;
1556    IntConLevel cl;
1557    Get_Consistency_Level(3, cl);
1558
1559    try {
1560	BoolExpr c = ec2boolexpr(EC_arg(2), solver);
1561
1562	if (solver->is_first()) cache_domain_sizes(solver);
1563	rel(*solver, c, cl);
1564
1565	/* check for failure (without full propagation) */
1566	return (solver->failed() ? EC_fail : EC_succeed);
1567    }
1568    catch(Ec2gcException) {
1569	return TYPE_ERROR;
1570    }
1571    CatchAndReportGecodeExceptions
1572}
1573
1574
1575extern "C" VisAtt
1576int p_g_post_intrel_cstr()
1577{
1578    GecodeSpace** solverp;
1579    GecodeSpace* solver;
1580
1581    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1582	return TYPE_ERROR;
1583    solver = *solverp;
1584    if (solver == NULL) return TYPE_ERROR;
1585
1586    IntConLevel cl;
1587    Get_Consistency_Level(3, cl);
1588
1589    try {
1590	LinIntRel c = ec2intrel(EC_arg(2), solver);
1591
1592	if (solver->is_first()) cache_domain_sizes(solver);
1593	rel(*solver, c, cl);
1594
1595	/* check for failure (without full propagation) */
1596	return (solver->failed() ? EC_fail : EC_succeed);
1597    }
1598    catch(Ec2gcException) {
1599	return TYPE_ERROR;
1600    }
1601    CatchAndReportGecodeExceptions
1602}
1603
1604extern "C" VisAtt
1605int p_g_post_setvar()
1606{
1607    GecodeSpace** solverp;
1608    GecodeSpace* solver;
1609    long l;
1610    int idx, val;
1611
1612    if (EC_arg(2).is_long(&l) != EC_succeed) return TYPE_ERROR;
1613    idx = (int) l;
1614    if (idx < 0) return RANGE_ERROR;
1615    if (EC_arg(3).is_long(&l) != EC_succeed) return TYPE_ERROR;
1616    val = (int) l;
1617    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1618	return TYPE_ERROR;
1619    solver = *solverp;
1620    if (solver == NULL) return TYPE_ERROR;
1621    if (idx >= solver->vInt.size()) {
1622	return RANGE_ERROR;
1623    }
1624
1625    if (solver->is_first()) cache_domain_sizes(solver);
1626
1627    try {
1628	dom(*solver, solver->vInt[idx], (int)val);
1629//    rel(*solver, solver->vInt[idx], IRT_EQ, (int)val);
1630	if (solver->is_first()) solver->dom_snapshot[idx] = 1; // just assigned!
1631
1632	return (solver->failed() ? EC_fail : EC_succeed);
1633    }
1634    CatchAndReportGecodeExceptions
1635
1636}
1637
1638extern "C" VisAtt
1639int p_g_post_exclude_var_val()
1640{
1641    GecodeSpace** solverp;
1642    GecodeSpace* solver;
1643    long l;
1644    int idx, val;
1645
1646    if (EC_arg(2).is_long(&l) != EC_succeed) return TYPE_ERROR;
1647    idx = (int) l;
1648    if (idx < 0) return RANGE_ERROR;
1649    if (EC_arg(3).is_long(&l) != EC_succeed) return TYPE_ERROR;
1650    val = (int) l;
1651    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1652	return TYPE_ERROR;
1653    solver = *solverp;
1654    if (solver ==  NULL) return TYPE_ERROR;
1655    if (idx >= solver->vInt.size()) {
1656	return RANGE_ERROR;
1657    }
1658
1659    if (solver->is_first()) cache_domain_sizes(solver);
1660
1661    try {
1662	// Guido Tack suggests that this is the most efficient
1663	// way of excluding a value from a variable (2013-02-20)
1664	Int::IntView vv(solver->vInt[idx]);
1665	if (me_failed(vv.nq(*solver, (int)val))) solver->fail();
1666	return (solver->failed() ? EC_fail : EC_succeed);
1667    }
1668    CatchAndReportGecodeExceptions
1669
1670}
1671
1672#define CheckAndMakeChanged(snapshotsolver, tail, chgtail) \
1673{ \
1674    int dsize; \
1675    for (int i=1; i<snapshotsize; i++) { \
1676	dsize = solver->vInt[i].size();  \
1677	if (snapshotsolver->dom_snapshot[i] > dsize) { \
1678	    if (dsize == 1) { \
1679		tail = list(i,tail); \
1680	    } else { \
1681		chgtail = list(i,chgtail); \
1682	    } \
1683	} \
1684    } \
1685}
1686
1687extern "C" VisAtt
1688int p_g_stop_caching()
1689{
1690    GecodeSpace** solverp;
1691    GecodeSpace* solver;
1692
1693    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1694	return TYPE_ERROR;
1695    solver = *solverp;
1696    if (solver == NULL) return TYPE_ERROR;
1697
1698    solver->stop_caching();
1699    return EC_succeed;
1700
1701}
1702
1703extern "C" VisAtt
1704int p_g_start_caching()
1705{
1706    GecodeSpace** solverp;
1707    GecodeSpace* solver;
1708
1709    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1710	return TYPE_ERROR;
1711    solver = *solverp;
1712    if (solver == NULL) return TYPE_ERROR;
1713
1714    solver->start_caching();
1715    return EC_succeed;
1716
1717}
1718
1719extern "C" VisAtt
1720int p_g_propagate_recompute()
1721{
1722    GecodeSpace** solverp;
1723    GecodeSpace* solver;
1724
1725    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1726	return TYPE_ERROR;
1727    solver = *solverp;
1728    if (solver == NULL) return TYPE_ERROR;
1729
1730    try {
1731	if (!solver->status()) return EC_fail;
1732    }
1733    CatchAndReportGecodeExceptions
1734
1735    solver->start_caching();
1736    return EC_succeed;
1737
1738}
1739
1740extern "C" VisAtt
1741int p_g_propagate()
1742{
1743    GecodeSpace** solverp;
1744    GecodeSpace* solver;
1745
1746    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1747	return TYPE_ERROR;
1748    solver = *solverp;
1749    if (solver == NULL) return TYPE_ERROR;
1750
1751    try {
1752	if (!solver->status()) return EC_fail;
1753    }
1754    CatchAndReportGecodeExceptions
1755//    return EC_succeed;
1756
1757//    if (first == 0) return EC_succeed;
1758
1759
1760    EC_word tail = nil(), chgtail = nil();
1761
1762    if (solver->snapshot_valid()) {
1763//    int res;
1764	int snapshotsize = solver->dom_snapshot.size();
1765
1766//    printf("size: %d,%d\n",EC_arg(2).arity(), snapshotsize);
1767//    if (EC_arg(3).arity() < snapshotsize) return RANGE_ERROR;
1768
1769	CheckAndMakeChanged(solver, tail, chgtail);
1770    }
1771    solver->clear_snapshot();
1772
1773    if (unify(EC_arg(3), tail) != EC_succeed) {
1774	return EC_fail;
1775    } else {
1776	return unify(EC_arg(4), chgtail);
1777    }
1778
1779}
1780
1781extern "C" VisAtt
1782int p_g_post_interval()
1783{
1784    GecodeSpace** solverp;
1785    GecodeSpace* solver;
1786    long min, max;
1787
1788    if (EC_succeed != EC_arg(3).is_long(&min)) return(TYPE_ERROR);
1789    if (EC_succeed != EC_arg(4).is_long(&max)) return(TYPE_ERROR);
1790
1791    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1792	return TYPE_ERROR;
1793    solver = *solverp;
1794    if (solver == NULL) return TYPE_ERROR;
1795
1796    EC_word varr =  EC_arg(2);
1797    int size = varr.arity();
1798
1799    IntVarArgs vars(size);
1800    int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
1801    if (res != EC_succeed) return res;
1802
1803    if (solver->is_first()) cache_domain_sizes(solver);
1804
1805    try {
1806	dom(*solver, vars, min, max);
1807    }
1808    CatchAndReportGecodeExceptions
1809
1810    return (solver->failed() ? EC_fail : EC_succeed);
1811}
1812
1813extern "C" VisAtt
1814int p_g_post_var_interval_reif()
1815{
1816    GecodeSpace** solverp;
1817    GecodeSpace* solver;
1818    long min, max;
1819
1820    if (EC_succeed != EC_arg(3).is_long(&min)) return(TYPE_ERROR);
1821    if (EC_succeed != EC_arg(4).is_long(&max)) return(TYPE_ERROR);
1822//    if (min > max) return RANGE_ERROR;
1823
1824    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1825	return TYPE_ERROR;
1826    solver = *solverp;
1827    if (solver == NULL) return TYPE_ERROR;
1828
1829    long xidx;
1830    IntVar x;
1831    EC_functor f;
1832
1833    try {
1834        Assign_IntVar(2, xidx, x);
1835
1836	long b;
1837	BoolVar reifb;
1838
1839	if (ArgIsVarBoolIdx(5, b)) {
1840	    reifb = solver->vBool[(int)b];
1841	} else if (EC_arg(5).is_long(&b) == EC_succeed) {
1842	    if (b < 0 || b > 1) return RANGE_ERROR;
1843	    reifb = BoolVar(*solver, b, b);
1844	} else
1845	    return TYPE_ERROR;
1846
1847	ReifyMode rm;
1848	Get_ReifType(6, rm);
1849
1850	if (solver->is_first()) cache_domain_sizes(solver);
1851
1852	Reify reif(reifb, rm);
1853	dom(*solver, x, min, max, reif);
1854	return (solver->failed() ? EC_fail : EC_succeed);
1855    }
1856    CatchAndReportGecodeExceptions
1857
1858}
1859
1860extern "C" VisAtt
1861int p_g_post_dom()
1862{
1863    GecodeSpace** solverp;
1864    GecodeSpace* solver;
1865
1866    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1867	return TYPE_ERROR;
1868    solver = *solverp;
1869    if (solver == NULL) return TYPE_ERROR;
1870
1871    EC_word darr = EC_arg(3);
1872    int dsize = darr.arity();
1873    int ranges[dsize][2];
1874    if (dsize == 0) return TYPE_ERROR;
1875
1876    EC_word varr =  EC_arg(2);
1877    int size = varr.arity();
1878
1879    int res = get_domain_intervals_from_ec_array(dsize, darr, ranges);
1880    if (res != EC_succeed) return res;
1881    try {
1882	IntSet domset(ranges, dsize);
1883
1884	IntVarArgs vars(size);
1885	res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
1886	if (res != EC_succeed) return res;
1887
1888	if (solver->is_first()) cache_domain_sizes(solver);
1889
1890	dom(*solver, vars, domset);
1891
1892	return (solver->failed() ? EC_fail : EC_succeed);
1893    }
1894    CatchAndReportGecodeExceptions
1895}
1896
1897extern "C" VisAtt
1898int p_g_post_dom_handle()
1899{
1900    GecodeSpace** solverp;
1901    GecodeSpace* solver;
1902
1903    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1904	return TYPE_ERROR;
1905    solver = *solverp;
1906    if (solver == NULL) return TYPE_ERROR;
1907
1908    IntSet* domp;
1909    if (EC_succeed != get_handle_from_arg(3, &domain_method, (void**)&domp))
1910	return TYPE_ERROR;
1911    if (domp == NULL) return TYPE_ERROR;
1912
1913    EC_word varr =  EC_arg(2);
1914    int size = varr.arity();
1915
1916    try {
1917	IntVarArgs vars(size);
1918	int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
1919	if (res != EC_succeed) return res;
1920
1921	if (solver->is_first()) cache_domain_sizes(solver);
1922
1923	dom(*solver, vars, *domp);
1924
1925	return (solver->failed() ? EC_fail : EC_succeed);
1926    }
1927    CatchAndReportGecodeExceptions
1928}
1929
1930extern "C" VisAtt
1931int p_g_post_exclude_dom()
1932{
1933    GecodeSpace** solverp;
1934    GecodeSpace* solver;
1935
1936    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1937	return TYPE_ERROR;
1938    solver = *solverp;
1939    if (solver == NULL) return TYPE_ERROR;
1940
1941    EC_word darr = EC_arg(3);
1942    int dsize = darr.arity();
1943    int ranges[dsize][2];
1944    if (dsize == 0) return TYPE_ERROR;
1945
1946    int res = get_domain_intervals_from_ec_array(dsize, darr, ranges);
1947    if (res != EC_succeed) return res;
1948    if (solver->is_first()) cache_domain_sizes(solver);
1949
1950    EC_word varr =  EC_arg(2);
1951    int size = varr.arity();
1952
1953    try {
1954	IntSet domset(ranges, dsize);
1955
1956	BoolVar reif(*solver, 0, 0);
1957
1958	for (int i=1; i<=size; i++) {
1959	    EC_word arg = EC_argument(varr, i);
1960	    EC_functor f;
1961	    long l;
1962	    IntVar v;
1963
1964	    if (arg.functor(&f) == EC_succeed) {
1965		if  (strcmp(f.name(), "_ivar") == 0
1966		     && EC_argument(arg, 1).is_long(&l) == EC_succeed) {
1967		    v = solver->vInt[(int)l];
1968		} else
1969		    return RANGE_ERROR;
1970	    } else if (arg.is_long(&l) == EC_succeed) {
1971		v = IntVar(*solver,(int)l,(int)l);
1972	    } else
1973		return TYPE_ERROR;
1974
1975	    dom(*solver, v, domset, reif);
1976
1977	    if (solver->failed()) return EC_fail;
1978	}
1979	return EC_succeed;
1980    }
1981    CatchAndReportGecodeExceptions
1982}
1983
1984extern "C" VisAtt
1985int p_g_post_exclude_dom_handle()
1986{
1987    GecodeSpace** solverp;
1988    GecodeSpace* solver;
1989
1990    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
1991	return TYPE_ERROR;
1992    solver = *solverp;
1993    if (solver == NULL) return TYPE_ERROR;
1994
1995    IntSet* domp;
1996    if (EC_succeed != get_handle_from_arg(3, &domain_method, (void**)&domp))
1997	return TYPE_ERROR;
1998    if (domp == NULL) return TYPE_ERROR;
1999
2000    EC_word varr =  EC_arg(2);
2001    int size = varr.arity();
2002
2003    try {
2004	BoolVar reif(*solver, 0, 0);
2005
2006	for (int i=1; i<=size; i++) {
2007	    EC_word arg = EC_argument(varr, i);
2008	    EC_functor f;
2009	    long l;
2010	    IntVar v;
2011
2012	    if (arg.functor(&f) == EC_succeed) {
2013		if  (strcmp(f.name(), "_ivar") == 0
2014		     && EC_argument(arg, 1).is_long(&l) == EC_succeed) {
2015		    v = solver->vInt[(int)l];
2016		} else
2017		    return RANGE_ERROR;
2018	    } else if (arg.is_long(&l) == EC_succeed) {
2019		v = IntVar(*solver,(int)l,(int)l);
2020	    } else
2021		return TYPE_ERROR;
2022
2023	    dom(*solver, v, *domp, reif);
2024
2025	    if (solver->failed()) return EC_fail;
2026	}
2027	return EC_succeed;
2028    }
2029    CatchAndReportGecodeExceptions
2030}
2031
2032extern "C" VisAtt
2033int p_g_post_exclude_val()
2034{
2035    GecodeSpace** solverp;
2036    GecodeSpace* solver;
2037
2038    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2039	return TYPE_ERROR;
2040    solver = *solverp;
2041    if (solver == NULL) return TYPE_ERROR;
2042
2043    long val;
2044    if (EC_succeed != EC_arg(3).is_long(&val)) return(TYPE_ERROR);
2045
2046    EC_word varr =  EC_arg(2);
2047    int size = varr.arity();
2048
2049    try {
2050
2051	for (int i=1; i<=size; i++) {
2052	    EC_word arg = EC_argument(varr, i);
2053	    long l;
2054
2055	    if (arg.is_long(&l) != EC_succeed) return TYPE_ERROR;
2056
2057	    Int::IntView vv(solver->vInt[(int)l]);
2058	    if (me_failed(vv.nq(*solver, (int)val))) {
2059		solver->fail();
2060		return EC_fail;
2061	    }
2062
2063	}
2064	return EC_succeed;
2065    }
2066    CatchAndReportGecodeExceptions
2067}
2068
2069extern "C" VisAtt
2070int p_g_post_exclude_range()
2071{
2072    GecodeSpace** solverp;
2073    GecodeSpace* solver;
2074
2075    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2076	return TYPE_ERROR;
2077    solver = *solverp;
2078    if (solver == NULL) return TYPE_ERROR;
2079
2080    long lo, hi;
2081    if (EC_succeed != EC_arg(3).is_long(&lo)) return(TYPE_ERROR);
2082    if (EC_succeed != EC_arg(4).is_long(&hi)) return(TYPE_ERROR);
2083
2084    EC_word varr =  EC_arg(2);
2085    int size = varr.arity();
2086
2087    try {
2088	BoolVar reif(*solver, 0, 0);
2089
2090	for (int i=1; i<=size; i++) {
2091	    EC_word arg = EC_argument(varr, i);
2092	    EC_functor f;
2093	    long l;
2094	    IntVar v;
2095
2096	    if (arg.is_long(&l) == EC_succeed) {
2097		v = solver->vInt[(int)l];
2098	    } else
2099		return TYPE_ERROR;
2100
2101	    dom(*solver, v, (int)lo, (int)hi, reif);
2102
2103	    if (solver->failed()) return EC_fail;
2104	}
2105	return EC_succeed;
2106    }
2107    CatchAndReportGecodeExceptions
2108}
2109
2110extern "C" VisAtt
2111int p_g_post_var_dom_reif()
2112{
2113    GecodeSpace** solverp;
2114    GecodeSpace* solver;
2115
2116    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2117	return TYPE_ERROR;
2118    solver = *solverp;
2119    if (solver == NULL) return TYPE_ERROR;
2120
2121    try {
2122	long xidx;
2123	IntVar x;
2124	EC_functor f;
2125
2126	Assign_IntVar(2, xidx, x);
2127
2128	EC_word darr = EC_arg(3);
2129	int dsize = darr.arity();
2130	int ranges[dsize][2];
2131	if (dsize == 0) return TYPE_ERROR;
2132
2133	int res = get_domain_intervals_from_ec_array(dsize, darr, ranges);
2134	if (res != EC_succeed) return res;
2135	IntSet domset(ranges, dsize);
2136
2137	long b;
2138	BoolVar reifb;
2139
2140	if (ArgIsVarBoolIdx(4, b)) {
2141	    reifb = solver->vBool[(int)b];
2142	} else if (EC_arg(4).is_long(&b) == EC_succeed) {
2143	    if (b < 0 || b > 1) return RANGE_ERROR;
2144	    reifb = BoolVar(*solver, b, b);
2145	} else
2146	    return TYPE_ERROR;
2147
2148	ReifyMode rm;
2149	Get_ReifType(5, rm);
2150
2151	if (solver->is_first()) cache_domain_sizes(solver);
2152
2153	Reify reif(reifb, rm);
2154	dom(*solver, x, domset, reif);
2155	return (solver->failed() ? EC_fail : EC_succeed);
2156    }
2157    CatchAndReportGecodeExceptions
2158}
2159
2160extern "C" VisAtt
2161int p_g_post_var_val_reif()
2162{
2163    GecodeSpace** solverp;
2164    GecodeSpace* solver;
2165
2166    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2167	return TYPE_ERROR;
2168    solver = *solverp;
2169    if (solver == NULL) return TYPE_ERROR;
2170
2171    long xidx;
2172    IntVar x;
2173    EC_functor f;
2174
2175    try {
2176        Assign_IntVar(2, xidx, x);
2177
2178	long val;
2179
2180	if (EC_succeed != EC_arg(3).is_long(&val)) return(TYPE_ERROR);
2181
2182	long b;
2183	BoolVar reifb;
2184
2185	if (ArgIsVarBoolIdx(4, b)) {
2186	    reifb = solver->vBool[(int)b];
2187	} else if (EC_arg(4).is_long(&b) == EC_succeed) {
2188	    if (b < 0 || b > 1) return RANGE_ERROR;
2189		reifb = BoolVar(*solver, b, b);
2190	} else
2191	    return TYPE_ERROR;
2192
2193	ReifyMode rm;
2194	Get_ReifType(5, rm);
2195
2196	if (solver->is_first()) cache_domain_sizes(solver);
2197
2198	Reify reif(reifb, rm);
2199	dom(*solver, x, (int)val, reif);
2200	return (solver->failed() ? EC_fail : EC_succeed);
2201    }
2202    CatchAndReportGecodeExceptions
2203}
2204
2205extern "C" VisAtt
2206int p_g_post_dom_var()
2207{
2208    GecodeSpace** solverp;
2209    GecodeSpace* solver;
2210
2211    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2212	return TYPE_ERROR;
2213    solver = *solverp;
2214    if (solver == NULL) return TYPE_ERROR;
2215
2216    long i;
2217
2218    EC_functor f;
2219    IntVar x;
2220    Assign_IntVar(2, i, x);
2221
2222    IntVar y;
2223    Assign_IntVar(3, i, y);
2224
2225    try {
2226	dom(*solver, x,y);
2227	return (solver->failed() ? EC_fail : EC_succeed);
2228    }
2229    CatchAndReportGecodeExceptions
2230
2231}
2232
2233extern "C" VisAtt
2234int p_g_post_sum()
2235{
2236    GecodeSpace** solverp;
2237    GecodeSpace* solver;
2238
2239    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2240	return TYPE_ERROR;
2241    solver = *solverp;
2242    if (solver == NULL) return TYPE_ERROR;
2243
2244    EC_word varr = EC_arg(2);
2245    int size = varr.arity();
2246
2247    IntVarArgs vars(size);
2248    int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
2249    if (res != EC_succeed) return res;
2250
2251    IntRelType rel;
2252    Get_IntRelType(3, rel);
2253
2254    long c;
2255    IntVar cvar;
2256    EC_functor f;
2257    bool c_is_int;
2258    Assign_IntVar_or_Int(4, c, cvar, c_is_int);
2259
2260    IntConLevel cl;
2261    Get_Consistency_Level(5, cl);
2262
2263    if (solver->is_first()) cache_domain_sizes(solver);
2264
2265    try {
2266      if (c_is_int)
2267	  linear(*solver, vars, rel, (int)c, cl);
2268      else
2269	  linear(*solver, vars, rel, cvar, cl);
2270      return EC_succeed;
2271    }
2272    CatchAndReportGecodeExceptions
2273}
2274
2275extern "C" VisAtt
2276int p_g_post_sum_reif()
2277{
2278    GecodeSpace** solverp;
2279    GecodeSpace* solver;
2280
2281    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2282	return TYPE_ERROR;
2283    solver = *solverp;
2284    if (solver == NULL) return TYPE_ERROR;
2285
2286    EC_word varr = EC_arg(2);
2287    int size = varr.arity();
2288
2289    IntVarArgs vars(size);
2290    int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
2291    if (res != EC_succeed) return res;
2292
2293    IntRelType rel;
2294    Get_IntRelType(3, rel);
2295
2296    long c;
2297    IntVar cvar;
2298    EC_functor f;
2299    bool c_is_int;
2300    Assign_IntVar_or_Int(4, c, cvar, c_is_int);
2301
2302    IntConLevel cl;
2303    Get_Consistency_Level(7, cl);
2304
2305    long b;
2306    BoolVar reifb;
2307
2308    if (ArgIsVarBoolIdx(5, b)) {
2309        reifb = solver->vBool[(int)b];
2310    } else if (EC_arg(5).is_long(&b) == EC_succeed) {
2311        if (b < 0 || b > 1) return RANGE_ERROR;
2312	reifb = BoolVar(*solver, (int)b, (int)b);
2313    } else
2314        return TYPE_ERROR;
2315
2316    ReifyMode rm;
2317    Get_ReifType(6, rm);
2318
2319    if (solver->is_first()) cache_domain_sizes(solver);
2320
2321    try {
2322      Reify reif(reifb, rm);
2323      if (c_is_int)
2324	linear(*solver, vars, rel, (int)c, reif, cl);
2325      else
2326	linear(*solver, vars, rel, cvar, reif, cl);
2327      return EC_succeed;
2328    }
2329    CatchAndReportGecodeExceptions
2330}
2331
2332extern "C" VisAtt
2333int p_g_post_lin()
2334{
2335    GecodeSpace** solverp;
2336    GecodeSpace* solver;
2337
2338    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2339	return TYPE_ERROR;
2340    solver = *solverp;
2341    if (solver == NULL) return TYPE_ERROR;
2342
2343    EC_word varr = EC_arg(2);
2344    int size = varr.arity();
2345
2346    IntVarArgs vars(size);
2347    int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
2348    if (res != EC_succeed) return res;
2349
2350    EC_word carr = EC_arg(3);
2351    if (carr.arity() != size) return TYPE_ERROR;
2352
2353    IntArgs cs(size);
2354    res = assign_IntArgs_from_ec_array(size, carr, cs);
2355    if (res != EC_succeed) return res;
2356
2357    IntRelType rel;
2358    Get_IntRelType(4, rel);
2359
2360    long c;
2361    IntVar cvar;
2362    EC_functor f;
2363    bool c_is_int;
2364    Assign_IntVar_or_Int(5, c, cvar, c_is_int);
2365
2366    IntConLevel cl;
2367    Get_Consistency_Level(6, cl);
2368
2369    if (solver->is_first()) cache_domain_sizes(solver);
2370
2371    try {
2372      if (c_is_int)
2373	  linear(*solver, cs, vars, rel, (int)c, cl);
2374      else
2375	  linear(*solver, cs, vars, rel, cvar, cl);
2376      return EC_succeed;
2377    }
2378    CatchAndReportGecodeExceptions
2379}
2380
2381extern "C" VisAtt
2382int p_g_post_lin_reif()
2383{
2384    GecodeSpace** solverp;
2385    GecodeSpace* solver;
2386
2387    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2388	return TYPE_ERROR;
2389    solver = *solverp;
2390    if (solver == NULL) return TYPE_ERROR;
2391
2392    EC_word varr = EC_arg(2);
2393    int size = varr.arity();
2394
2395    IntVarArgs vars(size);
2396    int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
2397    if (res != EC_succeed) return res;
2398
2399    EC_word carr = EC_arg(3);
2400    if (carr.arity() != size) return TYPE_ERROR;
2401
2402    IntArgs cs(size);
2403    res = assign_IntArgs_from_ec_array(size, carr, cs);
2404    if (res != EC_succeed) return res;
2405
2406    IntRelType rel;
2407    Get_IntRelType(4, rel);
2408
2409    long c;
2410    IntVar cvar;
2411    EC_functor f;
2412    bool c_is_int;
2413    Assign_IntVar_or_Int(5, c, cvar, c_is_int);
2414
2415    IntConLevel cl;
2416    Get_Consistency_Level(8, cl);
2417
2418    long b;
2419    BoolVar reifb;
2420
2421    if (ArgIsVarBoolIdx(6, b)) {
2422        reifb = solver->vBool[(int)b];
2423    } else if (EC_arg(6).is_long(&b) == EC_succeed) {
2424        if (b < 0 || b > 1) return RANGE_ERROR;
2425	reifb = BoolVar(*solver, (int)b, (int)b);
2426    } else
2427        return TYPE_ERROR;
2428
2429    ReifyMode rm;
2430    Get_ReifType(7, rm);
2431
2432    if (solver->is_first()) cache_domain_sizes(solver);
2433
2434    try {
2435	Reify reif(reifb, rm);
2436	if (c_is_int)
2437	    linear(*solver, cs, vars, rel, (int)c, reif, cl);
2438	else
2439	    linear(*solver, cs, vars, rel, cvar, reif, cl);
2440	return EC_succeed;
2441    }
2442    CatchAndReportGecodeExceptions
2443}
2444
2445extern "C" VisAtt
2446int p_g_post_simple_reif_rc()
2447{
2448    GecodeSpace** solverp;
2449    GecodeSpace* solver;
2450
2451    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2452	return TYPE_ERROR;
2453    solver = *solverp;
2454    if (solver == NULL) return TYPE_ERROR;
2455
2456    long i;
2457
2458    EC_functor f;
2459    IntVar x;
2460    Assign_IntVar(2, i, x);
2461
2462    IntVar y;
2463    Assign_IntVar(4, i, y);
2464
2465    IntRelType relop;
2466    Get_IntRelType(3, relop);
2467
2468    long b;
2469    BoolVar reifb;
2470
2471    if (ArgIsVarBoolIdx(5, b)) {
2472	reifb = solver->vBool[(int)b];
2473    } else if (EC_arg(5).is_long(&b) == EC_succeed) {
2474	if (b < 0 || b > 1) return RANGE_ERROR;
2475	reifb = BoolVar(*solver, (int)b, (int)b);
2476    } else
2477	return TYPE_ERROR;
2478
2479    ReifyMode rm;
2480    Get_ReifType(6, rm);
2481
2482    IntConLevel cl;
2483    Get_Consistency_Level(7, cl);
2484
2485    if (solver->is_first()) cache_domain_sizes(solver);
2486
2487    try {
2488	Reify reif(reifb, rm);
2489	rel(*solver, x, relop, y, reif, cl);
2490    }
2491    CatchAndReportGecodeExceptions
2492    return EC_succeed;
2493}
2494
2495extern "C" VisAtt
2496int p_g_post_alldiff()
2497{
2498    GecodeSpace** solverp;
2499    GecodeSpace* solver;
2500
2501    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2502	return TYPE_ERROR;
2503    solver = *solverp;
2504    if (solver == NULL) return TYPE_ERROR;
2505
2506    EC_word varr = EC_arg(2);
2507    int size = varr.arity();
2508
2509    IntVarArgs alldiff(size);
2510    int res = assign_IntVarArgs_from_ec_array(solver, size, varr, alldiff);
2511    if (res != EC_succeed) return res;
2512
2513    IntConLevel cl;
2514    Get_Consistency_Level(3, cl);
2515
2516    if (solver->is_first()) cache_domain_sizes(solver);
2517
2518    try {
2519	distinct(*solver, alldiff, cl);
2520    }
2521    CatchAndReportGecodeExceptions
2522    return EC_succeed;
2523}
2524
2525extern "C" VisAtt
2526int p_g_post_alldiff_offsets()
2527{
2528    GecodeSpace** solverp;
2529    GecodeSpace* solver;
2530
2531    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2532	return TYPE_ERROR;
2533    solver = *solverp;
2534    if (solver == NULL) return TYPE_ERROR;
2535
2536    EC_word varr = EC_arg(2);
2537    int size = varr.arity();
2538
2539    IntVarArgs alldiff(size);
2540    int res = assign_IntVarArgs_from_ec_array(solver, size, varr, alldiff);
2541    if (res != EC_succeed) return res;
2542
2543    EC_word oarr = EC_arg(3);
2544    if (oarr.arity() != size) return TYPE_ERROR;
2545
2546    IntArgs offsets(size);
2547    res = assign_IntArgs_from_ec_array(size, oarr, offsets);
2548    if (res != EC_succeed) return res;
2549
2550
2551    IntConLevel cl;
2552    Get_Consistency_Level(4, cl);
2553
2554    if (solver->is_first()) cache_domain_sizes(solver);
2555
2556    try {
2557	distinct(*solver, offsets, alldiff, cl);
2558    }
2559    CatchAndReportGecodeExceptions
2560
2561    return EC_succeed;
2562}
2563
2564extern "C" VisAtt
2565int p_g_post_mem()
2566{
2567    GecodeSpace** solverp;
2568    GecodeSpace* solver;
2569
2570    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2571	return TYPE_ERROR;
2572    solver = *solverp;
2573    if (solver == NULL) return TYPE_ERROR;
2574
2575    EC_word varr = EC_arg(2);
2576    int size = varr.arity();
2577
2578    IntVarArgs vs(size);
2579    int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vs);
2580    if (res != EC_succeed) return res;
2581
2582    IntVar mvar;
2583    long m;
2584    EC_functor f;
2585    Assign_IntVar(3, m, mvar);
2586
2587    if (solver->is_first()) cache_domain_sizes(solver);
2588
2589    try {
2590      member(*solver, vs, mvar);
2591    }
2592    CatchAndReportGecodeExceptions
2593    return EC_succeed;
2594}
2595
2596extern "C" VisAtt
2597int p_g_post_mem_reif()
2598{
2599    GecodeSpace** solverp;
2600    GecodeSpace* solver;
2601
2602    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2603	return TYPE_ERROR;
2604    solver = *solverp;
2605    if (solver == NULL) return TYPE_ERROR;
2606
2607    EC_word varr = EC_arg(2);
2608    int size = varr.arity();
2609
2610    IntVarArgs vs(size);
2611    int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vs);
2612    if (res != EC_succeed) return res;
2613
2614    IntVar mvar;
2615    long m;
2616    EC_functor f;
2617    Assign_IntVar(3, m, mvar);
2618
2619    ReifyMode rm;
2620    Get_ReifType(5, rm);
2621
2622    long b;
2623    BoolVar reifb;
2624
2625    if (ArgIsVarBoolIdx(4, b)) {
2626        reifb = solver->vBool[(int)b];
2627	    } else if (EC_arg(4).is_long(&b) == EC_succeed) {
2628        if (b < 0 || b > 1) return RANGE_ERROR;
2629	reifb = BoolVar(*solver, (int)b, (int)b);
2630    } else
2631        return TYPE_ERROR;
2632
2633    if (solver->is_first()) cache_domain_sizes(solver);
2634
2635    try {
2636	Reify reif(reifb, rm);
2637	member(*solver, vs, mvar, reif);
2638    }
2639    CatchAndReportGecodeExceptions
2640    return EC_succeed;
2641}
2642
2643extern "C" VisAtt
2644int p_g_post_nvalues()
2645{
2646    GecodeSpace** solverp;
2647    GecodeSpace* solver;
2648
2649    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2650	return TYPE_ERROR;
2651    solver = *solverp;
2652    if (solver == NULL) return TYPE_ERROR;
2653
2654    EC_word varr = EC_arg(2);
2655    int size = varr.arity();
2656
2657    IntVarArgs vs(size);
2658    int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vs);
2659    if (res != EC_succeed) return res;
2660
2661    IntRelType rel;
2662    Get_IntRelType(3, rel);
2663
2664    IntVar valvar;
2665    long val;
2666    EC_functor f;
2667    Assign_IntVar(4, val, valvar);
2668
2669    if (solver->is_first()) cache_domain_sizes(solver);
2670
2671    try {
2672      nvalues(*solver, vs, rel, valvar);
2673    }
2674    CatchAndReportGecodeExceptions
2675    return EC_succeed;
2676}
2677
2678extern "C" VisAtt
2679int p_g_post_count()
2680{
2681    GecodeSpace** solverp;
2682    GecodeSpace* solver;
2683    IntVar val, n;
2684    long vidx, nidx;
2685
2686    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2687	return TYPE_ERROR;
2688    solver = *solverp;
2689    if (solver == NULL) return TYPE_ERROR;
2690
2691    EC_functor f;
2692    Assign_IntVar(2, vidx, val);
2693
2694    IntRelType rel;
2695    Get_IntRelType(4, rel);
2696
2697    Assign_IntVar(5, nidx, n);
2698
2699    EC_word varr = EC_arg(3);
2700    int size = varr.arity();
2701
2702    IntVarArgs vars(size);
2703    int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
2704    if (res != EC_succeed) return res;
2705
2706    IntConLevel cl;
2707    Get_Consistency_Level(6, cl);
2708
2709    if (solver->is_first()) cache_domain_sizes(solver);
2710
2711    try {
2712	count(*solver, vars, val, rel, n, cl);
2713    }
2714    CatchAndReportGecodeExceptions
2715
2716    return EC_succeed;
2717}
2718
2719extern "C" VisAtt
2720int p_g_post_among()
2721{
2722    GecodeSpace** solverp;
2723    GecodeSpace* solver;
2724    IntVar val, n;
2725    long vidx, nidx;
2726
2727    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2728	return TYPE_ERROR;
2729    solver = *solverp;
2730    if (solver == NULL) return TYPE_ERROR;
2731
2732    IntRelType rel;
2733    Get_IntRelType(4, rel);
2734
2735    EC_functor f;
2736    Assign_IntVar(5, nidx, n);
2737
2738    EC_word varr = EC_arg(3);
2739    int size = varr.arity();
2740
2741    IntVarArgs vars(size);
2742    int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
2743    if (res != EC_succeed) return res;
2744
2745    if (solver->is_first()) cache_domain_sizes(solver);
2746
2747    try {
2748	EC_word darr = EC_arg(2);
2749	int dsize = darr.arity();
2750	int ranges[dsize][2];
2751
2752	res = get_domain_intervals_from_ec_array(dsize, darr, ranges);
2753	if (res != EC_succeed) return res;
2754
2755	IntSet valset(ranges, dsize);
2756	count(*solver, vars, valset, rel, n);
2757    }
2758    CatchAndReportGecodeExceptions
2759
2760    return EC_succeed;
2761}
2762
2763extern "C" VisAtt
2764int p_g_post_count_matches()
2765{
2766    GecodeSpace** solverp;
2767    GecodeSpace* solver;
2768    IntVar val, n;
2769    long vidx, nidx;
2770
2771    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2772	return TYPE_ERROR;
2773    solver = *solverp;
2774    if (solver == NULL) return TYPE_ERROR;
2775
2776    IntRelType rel;
2777    Get_IntRelType(4, rel);
2778
2779    EC_functor f;
2780    Assign_IntVar(5, nidx, n);
2781
2782    EC_word varr = EC_arg(3);
2783    int size = varr.arity();
2784
2785    IntVarArgs vars(size);
2786    int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
2787    if (res != EC_succeed) return res;
2788
2789    if (solver->is_first()) cache_domain_sizes(solver);
2790
2791    try {
2792	EC_word valarr = EC_arg(2);
2793	if (valarr.arity() != size) return RANGE_ERROR;
2794
2795	IntArgs vals(size);
2796	res = assign_IntArgs_from_ec_array(size, valarr, vals);
2797	if (res != EC_succeed) return res;
2798
2799	count(*solver, vars, vals, rel, n);
2800    }
2801    CatchAndReportGecodeExceptions
2802
2803    return EC_succeed;
2804}
2805
2806extern "C" VisAtt
2807int p_g_post_gcc()
2808{
2809    GecodeSpace** solverp;
2810    GecodeSpace* solver;
2811    long val, n;
2812    bool n_is_int;
2813
2814    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2815	return TYPE_ERROR;
2816    solver = *solverp;
2817    if (solver == NULL) return TYPE_ERROR;
2818
2819    EC_word pvals = EC_arg(2);
2820    int specsize = pvals.arity();
2821
2822    IntArgs vals(specsize);
2823    int res = assign_IntArgs_from_ec_array(specsize, pvals, vals);
2824    if (res != EC_succeed) return res;
2825
2826    EC_word poccurs = EC_arg(3);
2827    if (specsize != poccurs.arity()) return RANGE_ERROR;
2828
2829    IntVarArgs occurs(specsize);
2830    res = assign_IntVarArgs_from_ec_array(solver, specsize, poccurs, occurs);
2831    if (res != EC_succeed) return res;
2832
2833    EC_word varr = EC_arg(4);
2834    int size = varr.arity();
2835
2836    IntVarArgs vars(size);
2837    res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
2838    if (res != EC_succeed) return res;
2839
2840    IntConLevel cl;
2841    Get_Consistency_Level(5, cl);
2842
2843    if (solver->is_first()) cache_domain_sizes(solver);
2844
2845    try {
2846	count(*solver, vars, occurs, vals, cl);
2847    }
2848    CatchAndReportGecodeExceptions
2849
2850    return EC_succeed;
2851}
2852
2853extern "C" VisAtt
2854int p_g_post_element()
2855{
2856    GecodeSpace** solverp;
2857    GecodeSpace* solver;
2858    long v, i;
2859    bool v_is_int;
2860    IntVar vvar, ivar;
2861
2862    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2863	return TYPE_ERROR;
2864    solver = *solverp;
2865    if (solver == NULL) return TYPE_ERROR;
2866
2867    try {
2868	EC_functor f;
2869
2870	Assign_IntVar_or_Int(4, v, vvar, v_is_int);
2871
2872	Assign_IntVar(2, i, ivar);
2873
2874	EC_word arr = EC_arg(3);
2875	int size = arr.arity();
2876
2877	IntVarArgs vals(size);
2878	int res = assign_IntVarArgs_from_ec_array(solver, size, arr, vals);
2879	if (res != EC_succeed) return res;
2880
2881	IntConLevel cl;
2882	Get_Consistency_Level(5, cl);
2883
2884	if (solver->is_first()) cache_domain_sizes(solver);
2885
2886	if (v_is_int)
2887	    element(*solver, vals, ivar, v, cl);
2888	else
2889	    element(*solver, vals, ivar, vvar, cl);
2890    }
2891    CatchAndReportGecodeExceptions
2892
2893    return EC_succeed;
2894}
2895
2896extern "C" VisAtt
2897int p_g_post_sequence()
2898{
2899    GecodeSpace** solverp;
2900    GecodeSpace* solver;
2901    long val, n;
2902    bool n_is_int;
2903
2904    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2905	return TYPE_ERROR;
2906    solver = *solverp;
2907    if (solver == NULL) return TYPE_ERROR;
2908
2909    EC_word pvals = EC_arg(6);
2910    int specsize = pvals.arity();
2911
2912    IntArgs vals(specsize);
2913    int res = assign_IntArgs_from_ec_array(specsize, pvals, vals);
2914    if (res != EC_succeed) return res;
2915    IntSet valset(vals);
2916
2917    EC_word varr = EC_arg(5);
2918    int size = varr.arity();
2919
2920    IntVarArgs vars(size);
2921    res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
2922    if (res != EC_succeed) return res;
2923
2924    long lo, hi, k;
2925    if (EC_succeed != EC_arg(2).is_long(&lo)) return TYPE_ERROR;
2926    if (EC_succeed != EC_arg(3).is_long(&hi)) return TYPE_ERROR;
2927    if (EC_succeed != EC_arg(4).is_long(&k)) return TYPE_ERROR;
2928
2929    IntConLevel cl;
2930    Get_Consistency_Level(7, cl);
2931
2932    if (solver->is_first()) cache_domain_sizes(solver);
2933
2934    try {
2935	sequence(*solver, vars, valset, k, lo, hi, cl);
2936    }
2937    CatchAndReportGecodeExceptions
2938
2939    return EC_succeed;
2940}
2941
2942extern "C" VisAtt
2943int p_g_post_sequence_01()
2944{
2945    GecodeSpace** solverp;
2946    GecodeSpace* solver;
2947    long val, n;
2948    bool n_is_int;
2949
2950    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2951	return TYPE_ERROR;
2952    solver = *solverp;
2953    if (solver == NULL) return TYPE_ERROR;
2954
2955    IntSet valset(1,1);
2956
2957    EC_word varr = EC_arg(5);
2958    int size = varr.arity();
2959
2960    BoolVarArgs vars(size);
2961    int res = assign_BoolVarArgs_from_ec_array(solver, size, varr, vars);
2962    if (res != EC_succeed) return res;
2963
2964    long lo, hi, k;
2965    if (EC_succeed != EC_arg(2).is_long(&lo)) return TYPE_ERROR;
2966    if (EC_succeed != EC_arg(3).is_long(&hi)) return TYPE_ERROR;
2967    if (EC_succeed != EC_arg(4).is_long(&k)) return TYPE_ERROR;
2968
2969    IntConLevel cl;
2970    Get_Consistency_Level(6, cl);
2971
2972    if (solver->is_first()) cache_domain_sizes(solver);
2973
2974    try {
2975	sequence(*solver, vars, valset, k, lo, hi, cl);
2976    }
2977    CatchAndReportGecodeExceptions
2978
2979    return EC_succeed;
2980}
2981
2982extern "C" VisAtt
2983int p_g_post_sorted2()
2984{
2985    GecodeSpace** solverp;
2986    GecodeSpace* solver;
2987
2988    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
2989	return TYPE_ERROR;
2990    solver = *solverp;
2991    if (solver == NULL) return TYPE_ERROR;
2992
2993    EC_word uarr = EC_arg(2);
2994    int size = uarr.arity();
2995
2996    IntVarArgs unsort(size);
2997    int res = assign_IntVarArgs_from_ec_array(solver, size, uarr, unsort);
2998    if (res != EC_succeed) return res;
2999
3000    EC_word sarr = EC_arg(3);
3001    if (sarr.arity() != size) return RANGE_ERROR;
3002
3003    IntVarArgs sort(size);
3004    res = assign_IntVarArgs_from_ec_array(solver, size, sarr, sort);
3005    if (res != EC_succeed) return res;
3006
3007    IntConLevel cl;
3008    Get_Consistency_Level(4, cl);
3009
3010    if (solver->is_first()) cache_domain_sizes(solver);
3011
3012    try {
3013	sorted(*solver, unsort, sort, cl);
3014    }
3015    CatchAndReportGecodeExceptions
3016
3017    return EC_succeed;
3018}
3019
3020extern "C" VisAtt
3021int p_g_post_sorted()
3022{
3023    GecodeSpace** solverp;
3024    GecodeSpace* solver;
3025
3026    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3027	return TYPE_ERROR;
3028    solver = *solverp;
3029    if (solver == NULL) return TYPE_ERROR;
3030
3031    EC_word uarr = EC_arg(2);
3032    int size = uarr.arity();
3033
3034    IntVarArgs unsort(size);
3035    int res = assign_IntVarArgs_from_ec_array(solver, size, uarr, unsort);
3036    if (res != EC_succeed) return res;
3037
3038    EC_word sarr = EC_arg(3);
3039    if (sarr.arity() != size) return RANGE_ERROR;
3040
3041    IntVarArgs sort(size);
3042    res = assign_IntVarArgs_from_ec_array(solver, size, sarr, sort);
3043    if (res != EC_succeed) return res;
3044
3045    EC_word parr = EC_arg(4);
3046    if (parr.arity() != size) return RANGE_ERROR;
3047
3048    IntVarArgs pos(size);
3049    res = assign_IntVarArgs_from_ec_array(solver, size, parr, pos);
3050    if (res != EC_succeed) return res;
3051
3052    IntConLevel cl;
3053    Get_Consistency_Level(5, cl);
3054
3055    if (solver->is_first()) cache_domain_sizes(solver);
3056
3057    try {
3058	sorted(*solver, unsort, sort, pos, cl);
3059    }
3060    CatchAndReportGecodeExceptions
3061
3062    return EC_succeed;
3063}
3064
3065
3066extern "C" VisAtt
3067int p_g_post_disj()
3068{
3069    GecodeSpace** solverp;
3070    GecodeSpace* solver;
3071
3072    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3073	return TYPE_ERROR;
3074    solver = *solverp;
3075    if (solver == NULL) return TYPE_ERROR;
3076
3077    EC_word sarr = EC_arg(2);
3078    int size = sarr.arity();
3079
3080    IntVarArgs starts(size);
3081    int res = assign_IntVarArgs_from_ec_array(solver, size, sarr, starts);
3082    if (res != EC_succeed) return res;
3083
3084    EC_word darr = EC_arg(3);
3085    if (darr.arity() != size) return RANGE_ERROR;
3086
3087    IntArgs durations(size);
3088    res = assign_IntArgs_from_ec_array(size, darr, durations);
3089    if (res != EC_succeed) return res;
3090
3091    EC_word barr = EC_arg(4);
3092    BoolVarArgs scheduled(size);
3093    bool has_optional = (barr.arity() != 0);
3094    if (has_optional) {
3095	if (size != barr.arity()) return TYPE_ERROR;
3096
3097	res = assign_BoolVarArgs_from_ec_array(solver, size, barr, scheduled);
3098	if (res != EC_succeed) return res;
3099    }
3100
3101    if (solver->is_first()) cache_domain_sizes(solver);
3102
3103    try {
3104	// consistency level not supported!
3105	if (has_optional) {
3106	    unary(*solver, starts, durations, scheduled);
3107	} else {
3108	    unary(*solver, starts, durations);
3109	}
3110    }
3111    CatchAndReportGecodeExceptions
3112
3113    return EC_succeed;
3114}
3115
3116extern "C" VisAtt
3117int p_g_post_disjflex()
3118{
3119    GecodeSpace** solverp;
3120    GecodeSpace* solver;
3121
3122    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3123	return TYPE_ERROR;
3124    solver = *solverp;
3125    if (solver == NULL) return TYPE_ERROR;
3126
3127    EC_word sarr = EC_arg(2);
3128    int size = sarr.arity();
3129
3130    IntVarArgs starts(size);
3131    int res = assign_IntVarArgs_from_ec_array(solver, size, sarr, starts);
3132    if (res != EC_succeed) return res;
3133
3134    EC_word darr = EC_arg(3);
3135    if (darr.arity() != size) return RANGE_ERROR;
3136
3137    IntVarArgs durations(size);
3138    res = assign_IntVarArgs_from_ec_array(solver, size, darr, durations);
3139    if (res != EC_succeed) return res;
3140
3141    EC_word earr = EC_arg(4);
3142    if (earr.arity() != size) return RANGE_ERROR;
3143
3144    IntVarArgs ends(size);
3145    res = assign_IntVarArgs_from_ec_array(solver, size, earr, ends);
3146    if (res != EC_succeed) return res;
3147
3148    EC_word barr = EC_arg(5);
3149    BoolVarArgs scheduled(size);
3150    bool has_optional = (barr.arity() != 0);
3151    if (has_optional) {
3152	if (size != barr.arity()) return TYPE_ERROR;
3153
3154	res = assign_BoolVarArgs_from_ec_array(solver, size, barr, scheduled);
3155	if (res != EC_succeed) return res;
3156    }
3157
3158    if (solver->is_first()) cache_domain_sizes(solver);
3159
3160    try {
3161	// consistency level not supported!
3162	if (has_optional) {
3163	  unary(*solver, starts, durations, ends, scheduled);
3164	} else {
3165	  unary(*solver, starts, ends, durations);
3166	}
3167    }
3168    CatchAndReportGecodeExceptions
3169
3170    return EC_succeed;
3171}
3172
3173extern "C" VisAtt
3174int p_g_post_cumulatives()
3175{
3176    GecodeSpace** solverp;
3177    GecodeSpace* solver;
3178
3179    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3180	return TYPE_ERROR;
3181    solver = *solverp;
3182    if (solver == NULL) return TYPE_ERROR;
3183
3184    EC_word sarr = EC_arg(2);
3185    int size = sarr.arity();
3186
3187    IntVarArgs starts(size);
3188    int res = assign_IntVarArgs_from_ec_array(solver, size, sarr, starts);
3189    if (res != EC_succeed) return res;
3190
3191    EC_word darr = EC_arg(3);
3192    if (darr.arity() != size) return RANGE_ERROR;
3193
3194    IntVarArgs durations(size);
3195    res = assign_IntVarArgs_from_ec_array(solver, size, darr, durations);
3196
3197    EC_word earr = EC_arg(4);
3198    if (earr.arity() != size) return RANGE_ERROR;
3199
3200    IntVarArgs ends(size);
3201    res = assign_IntVarArgs_from_ec_array(solver, size, earr, ends);
3202
3203    EC_word uarr = EC_arg(5);
3204    if (uarr.arity() != size) return RANGE_ERROR;
3205
3206    IntVarArgs usages(size);
3207    res = assign_IntVarArgs_from_ec_array(solver, size, uarr, usages);
3208
3209    EC_word usedarr = EC_arg(6);
3210    if (usedarr.arity() != size) return RANGE_ERROR;
3211
3212    IntVarArgs used(size);
3213    res = assign_IntVarArgs_from_ec_array(solver, size, usedarr, used);
3214
3215    EC_word larr = EC_arg(7);
3216    int nmachines = larr.arity();
3217
3218    IntArgs limits(nmachines);
3219    res = assign_IntArgs_from_ec_array(nmachines, larr, limits);
3220    if (res != EC_succeed) return res;
3221
3222    long ec_atmost;
3223    bool atmost;
3224    if (EC_succeed != EC_arg(8).is_long(&ec_atmost)) return TYPE_ERROR;
3225    atmost = (ec_atmost ? true : false);
3226
3227    if (solver->is_first()) cache_domain_sizes(solver);
3228
3229    try {
3230	cumulatives(*solver, used, starts, durations, ends, usages, limits, ec_atmost);
3231    }
3232    CatchAndReportGecodeExceptions
3233
3234    return EC_succeed;
3235}
3236
3237extern "C" VisAtt
3238int p_g_post_cumulative()
3239{
3240    GecodeSpace** solverp;
3241    GecodeSpace* solver;
3242
3243    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3244	return TYPE_ERROR;
3245    solver = *solverp;
3246    if (solver == NULL) return TYPE_ERROR;
3247
3248    EC_word sarr = EC_arg(2);
3249    int size = sarr.arity();
3250
3251    IntVarArgs starts(size);
3252    int res = assign_IntVarArgs_from_ec_array(solver, size, sarr, starts);
3253    if (res != EC_succeed) return res;
3254
3255    EC_word darr = EC_arg(3);
3256    if (darr.arity() != size) return RANGE_ERROR;
3257
3258    IntArgs durations(size);
3259    res = assign_IntArgs_from_ec_array(size, darr, durations);
3260
3261    EC_word uarr = EC_arg(4);
3262    if (uarr.arity() != size) return RANGE_ERROR;
3263
3264    IntArgs usages(size);
3265    res = assign_IntArgs_from_ec_array(size, uarr, usages);
3266
3267    long lidx;
3268    IntVar limit;
3269    EC_functor f;
3270    Assign_IntVar(5, lidx, limit);
3271
3272    if (solver->is_first()) cache_domain_sizes(solver);
3273
3274    EC_word barr = EC_arg(6);
3275    bool has_optional = (barr.arity() != 0);
3276    if (has_optional) {
3277	if (size != barr.arity()) return TYPE_ERROR;
3278
3279	BoolVarArgs scheduled(size);
3280	res = assign_BoolVarArgs_from_ec_array(solver, size, barr, scheduled);
3281	if (res != EC_succeed) return res;
3282	try {
3283	  cumulative(*solver, limit, starts, durations, usages, scheduled);
3284	}
3285	CatchAndReportGecodeExceptions
3286
3287    } else {
3288
3289      try {
3290	cumulative(*solver, limit, starts, durations, usages);
3291      }
3292      CatchAndReportGecodeExceptions
3293    }
3294
3295    return EC_succeed;
3296}
3297
3298extern "C" VisAtt
3299int p_g_post_cumulativeflex()
3300{
3301    GecodeSpace** solverp;
3302    GecodeSpace* solver;
3303
3304    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3305	return TYPE_ERROR;
3306    solver = *solverp;
3307    if (solver == NULL) return TYPE_ERROR;
3308
3309    EC_word sarr = EC_arg(2);
3310    int size = sarr.arity();
3311
3312    IntVarArgs starts(size);
3313    int res = assign_IntVarArgs_from_ec_array(solver, size, sarr, starts);
3314    if (res != EC_succeed) return res;
3315
3316    EC_word darr = EC_arg(3);
3317    if (darr.arity() != size) return RANGE_ERROR;
3318
3319    IntVarArgs durations(size);
3320    res = assign_IntVarArgs_from_ec_array(solver, size, darr, durations);
3321
3322    EC_word earr = EC_arg(4);
3323    if (earr.arity() != size) return RANGE_ERROR;
3324
3325    IntVarArgs ends(size);
3326    res = assign_IntVarArgs_from_ec_array(solver, size, earr, ends);
3327
3328    EC_word uarr = EC_arg(5);
3329    if (uarr.arity() != size) return RANGE_ERROR;
3330
3331    IntArgs usages(size);
3332    res = assign_IntArgs_from_ec_array(size, uarr, usages);
3333
3334    long lidx;
3335    IntVar limit;
3336    EC_functor f;
3337    Assign_IntVar(6, lidx, limit);
3338
3339    if (solver->is_first()) cache_domain_sizes(solver);
3340
3341    EC_word barr = EC_arg(7);
3342    bool has_optional = (barr.arity() != 0);
3343    if (has_optional) {
3344	if (size != barr.arity()) return TYPE_ERROR;
3345
3346	BoolVarArgs scheduled(size);
3347	res = assign_BoolVarArgs_from_ec_array(solver, size, barr, scheduled);
3348	if (res != EC_succeed) return res;
3349	try {
3350	  cumulative(*solver, limit, starts, durations, ends, usages, scheduled);
3351	}
3352	CatchAndReportGecodeExceptions
3353
3354    } else {
3355
3356      try {
3357	cumulative(*solver, limit, starts, durations, ends, usages);
3358      }
3359      CatchAndReportGecodeExceptions
3360    }
3361
3362    return EC_succeed;
3363}
3364
3365extern "C" VisAtt
3366int p_g_post_circuit()
3367{
3368    GecodeSpace** solverp;
3369    GecodeSpace* solver;
3370
3371    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3372	return TYPE_ERROR;
3373    solver = *solverp;
3374    if (solver == NULL) return TYPE_ERROR;
3375
3376    EC_word arr = EC_arg(2);
3377    int size = arr.arity();
3378
3379    IntVarArgs succ(size);
3380    int res = assign_IntVarArgs_from_ec_array(solver, size, arr, succ);
3381    if (res != EC_succeed) return res;
3382
3383    IntConLevel cl;
3384    Get_Consistency_Level(4, cl);
3385
3386    if (solver->is_first()) cache_domain_sizes(solver);
3387
3388    try {
3389	long offset;
3390	if (EC_arg(3).is_long(&offset) != EC_succeed) return TYPE_ERROR;
3391	if (offset == 0)
3392	    circuit(*solver, succ, cl);
3393	else
3394	    circuit(*solver, (int)offset, succ, cl);
3395    }
3396    CatchAndReportGecodeExceptions
3397
3398    return EC_succeed;
3399}
3400
3401extern "C" VisAtt
3402int p_g_post_circuit_cost()
3403{
3404    GecodeSpace** solverp;
3405    GecodeSpace* solver;
3406
3407    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3408	return TYPE_ERROR;
3409    solver = *solverp;
3410    if (solver == NULL) return TYPE_ERROR;
3411
3412    EC_word arr = EC_arg(2);
3413    int size = arr.arity();
3414
3415    IntVarArgs succ(size);
3416    int res = assign_IntVarArgs_from_ec_array(solver, size, arr, succ);
3417    if (res != EC_succeed) return res;
3418
3419    EC_word cmarr = EC_arg(3);
3420    int cmsize = cmarr.arity();
3421    if (cmsize != size*size) return RANGE_ERROR;
3422
3423    IntArgs cm(cmsize);
3424    res = assign_IntArgs_from_ec_array(cmsize, cmarr, cm);
3425    if (res != EC_succeed) return res;
3426
3427    EC_functor f;
3428    long cidx;
3429    IntVar c;
3430    Assign_IntVar(5, cidx, c);
3431
3432    long offset;
3433    if (EC_arg(6).is_long(&offset) != EC_succeed) return TYPE_ERROR;
3434
3435    IntConLevel cl;
3436    Get_Consistency_Level(7, cl);
3437
3438    if (solver->is_first()) cache_domain_sizes(solver);
3439
3440    try {
3441	if (EC_arg(4).is_nil() != EC_succeed) {
3442	    EC_word acarr = EC_arg(4);
3443	    if (size != acarr.arity()) return RANGE_ERROR;
3444	    IntVarArgs arccosts(size);
3445	    res = assign_IntVarArgs_from_ec_array(solver, size, acarr, arccosts);
3446	    if (res != EC_succeed) return res;
3447	    if (offset == 0)
3448		circuit(*solver, cm, succ, arccosts, c, cl);
3449	    else
3450	      circuit(*solver, cm, (int)offset, succ, arccosts, c, cl);
3451	} else {
3452	    if (offset == 0)
3453		circuit(*solver, cm, succ, c, cl);
3454	    else
3455	      circuit(*solver, cm, (int)offset, succ, c, cl);
3456	}
3457    }
3458    CatchAndReportGecodeExceptions
3459
3460    return EC_succeed;
3461}
3462
3463extern "C" VisAtt
3464int p_g_post_ham_path()
3465{
3466    GecodeSpace** solverp;
3467    GecodeSpace* solver;
3468
3469    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3470	return TYPE_ERROR;
3471    solver = *solverp;
3472    if (solver == NULL) return TYPE_ERROR;
3473
3474    long idx;
3475    EC_functor f;
3476    IntVar start;
3477    Assign_IntVar(2, idx, start);
3478
3479    IntVar end;
3480    Assign_IntVar(3, idx, end);
3481
3482    EC_word arr = EC_arg(4);
3483    int size = arr.arity();
3484
3485    IntVarArgs succ(size);
3486    int res = assign_IntVarArgs_from_ec_array(solver, size, arr, succ);
3487    if (res != EC_succeed) return res;
3488
3489    IntConLevel cl;
3490    Get_Consistency_Level(6, cl);
3491
3492    if (solver->is_first()) cache_domain_sizes(solver);
3493
3494    try {
3495	long offset;
3496	if (EC_arg(5).is_long(&offset) != EC_succeed) return TYPE_ERROR;
3497	if (offset == 0)
3498	  path(*solver, succ, start, end, cl);
3499	else
3500	  path(*solver, (int)offset, succ, start, end, cl);
3501    }
3502    CatchAndReportGecodeExceptions
3503
3504    return EC_succeed;
3505}
3506
3507extern "C" VisAtt
3508int p_g_post_ham_path_cost()
3509{
3510    GecodeSpace** solverp;
3511    GecodeSpace* solver;
3512
3513    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3514	return TYPE_ERROR;
3515    solver = *solverp;
3516    if (solver == NULL) return TYPE_ERROR;
3517
3518    long idx;
3519    EC_functor f;
3520    IntVar start;
3521    Assign_IntVar(2, idx, start);
3522
3523    IntVar end;
3524    Assign_IntVar(3, idx, end);
3525
3526    EC_word arr = EC_arg(4);
3527    int size = arr.arity();
3528
3529    IntVarArgs succ(size);
3530    int res = assign_IntVarArgs_from_ec_array(solver, size, arr, succ);
3531    if (res != EC_succeed) return res;
3532
3533    EC_word cmarr = EC_arg(5);
3534    int cmsize = cmarr.arity();
3535    if (cmsize != size*size) return RANGE_ERROR;
3536
3537    IntArgs cm(cmsize);
3538    res = assign_IntArgs_from_ec_array(cmsize, cmarr, cm);
3539    if (res != EC_succeed) return res;
3540
3541    long cidx;
3542    IntVar c;
3543    Assign_IntVar(7, cidx, c);
3544
3545    long offset;
3546    if (EC_arg(8).is_long(&offset) != EC_succeed) return TYPE_ERROR;
3547
3548    IntConLevel cl;
3549    Get_Consistency_Level(9, cl);
3550
3551    if (solver->is_first()) cache_domain_sizes(solver);
3552
3553    try {
3554	if (EC_arg(6).is_nil() != EC_succeed) {
3555	    EC_word acarr = EC_arg(6);
3556	    if (size != acarr.arity()) return RANGE_ERROR;
3557	    IntVarArgs arccosts(size);
3558	    res = assign_IntVarArgs_from_ec_array(solver, size, acarr, arccosts);
3559	    if (res != EC_succeed) return res;
3560	    if (offset == 0)
3561	       path(*solver, cm, succ, start, end, arccosts, c, cl);
3562	    else
3563	      path(*solver, cm, (int)offset, succ, start, end, arccosts, c, cl);
3564	} else {
3565	    if (offset == 0)
3566	      path(*solver, cm, succ, start, end, c, cl);
3567	    else
3568	      path(*solver, cm, (int)offset, succ, start, end, c, cl);
3569	}
3570    }
3571    CatchAndReportGecodeExceptions
3572
3573    return EC_succeed;
3574}
3575
3576extern "C" VisAtt
3577int p_g_post_precede()
3578{
3579    GecodeSpace** solverp;
3580    GecodeSpace* solver;
3581    long s, t;
3582
3583    if (EC_succeed != EC_arg(2).is_long(&s)) return(TYPE_ERROR);
3584    if (EC_succeed != EC_arg(3).is_long(&t)) return(TYPE_ERROR);
3585
3586    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3587	return TYPE_ERROR;
3588    solver = *solverp;
3589    if (solver == NULL) return TYPE_ERROR;
3590
3591    EC_word varr =  EC_arg(4);
3592    int size = varr.arity();
3593
3594    IntVarArgs vars(size);
3595    int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
3596    if (res != EC_succeed) return res;
3597
3598    if (solver->is_first()) cache_domain_sizes(solver);
3599
3600    try {
3601      precede(*solver, vars, (int)s, (int)t);
3602    }
3603    CatchAndReportGecodeExceptions
3604
3605    return EC_succeed;
3606}
3607
3608extern "C" VisAtt
3609int p_g_post_precede_chain()
3610{
3611    GecodeSpace** solverp;
3612    GecodeSpace* solver;
3613
3614    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3615	return TYPE_ERROR;
3616    solver = *solverp;
3617    if (solver == NULL) return TYPE_ERROR;
3618
3619    EC_word varr =  EC_arg(3);
3620    int size = varr.arity();
3621
3622    IntVarArgs vars(size);
3623    int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
3624    if (res != EC_succeed) return res;
3625
3626    EC_word valarr =  EC_arg(2);
3627    size = valarr.arity();
3628
3629    IntArgs vals(size);
3630    res = assign_IntArgs_from_ec_array(size, valarr, vals);
3631    if (res != EC_succeed) return res;
3632
3633    if (solver->is_first()) cache_domain_sizes(solver);
3634
3635    try {
3636	precede(*solver, vars, vals);
3637    }
3638    CatchAndReportGecodeExceptions
3639
3640    return EC_succeed;
3641}
3642
3643extern "C" VisAtt
3644int p_g_post_disjoint2()
3645{
3646    GecodeSpace** solverp;
3647    GecodeSpace* solver;
3648
3649    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3650	return TYPE_ERROR;
3651    solver = *solverp;
3652    if (solver == NULL) return TYPE_ERROR;
3653
3654    EC_word xarr =  EC_arg(2);
3655    int size = xarr.arity();
3656
3657    IntVarArgs xs(size);
3658    int res = assign_IntVarArgs_from_ec_array(solver, size, xarr, xs);
3659    if (res != EC_succeed) return res;
3660
3661    EC_word warr =  EC_arg(3);
3662    if (warr.arity() != size) return RANGE_ERROR;
3663
3664    IntArgs ws(size);
3665    res = assign_IntArgs_from_ec_array(size, warr, ws);
3666    if (res != EC_succeed) return res;
3667
3668    EC_word yarr =  EC_arg(4);
3669    if (yarr.arity() != size) return RANGE_ERROR;
3670
3671    IntVarArgs ys(size);
3672    res = assign_IntVarArgs_from_ec_array(solver, size, yarr, ys);
3673    if (res != EC_succeed) return res;
3674
3675    EC_word harr =  EC_arg(5);
3676    if (harr.arity() != size) return RANGE_ERROR;
3677
3678    IntArgs hs(size);
3679    res = assign_IntArgs_from_ec_array(size, harr, hs);
3680    if (res != EC_succeed) return res;
3681
3682    try {
3683	if (EC_arg(6).is_nil() != EC_succeed) {
3684	    EC_word oarr = EC_arg(6);
3685	    if (size != oarr.arity()) return RANGE_ERROR;
3686
3687	    BoolVarArgs os(size);
3688	    res = assign_BoolVarArgs_from_ec_array(solver, size, oarr, os);
3689
3690	    if (solver->is_first()) cache_domain_sizes(solver);
3691	    nooverlap(*solver, xs, ws, ys, hs, os);
3692	} else {
3693	    if (solver->is_first()) cache_domain_sizes(solver);
3694	    nooverlap(*solver, xs, ws, ys, hs);
3695	}
3696    }
3697    CatchAndReportGecodeExceptions
3698
3699    return EC_succeed;
3700}
3701
3702extern "C" VisAtt
3703int p_g_post_disjointflex2()
3704{
3705    GecodeSpace** solverp;
3706    GecodeSpace* solver;
3707
3708    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3709	return TYPE_ERROR;
3710    solver = *solverp;
3711    if (solver == NULL) return TYPE_ERROR;
3712
3713    EC_word x1arr =  EC_arg(2);
3714    int size = x1arr.arity();
3715
3716    IntVarArgs x1s(size);
3717    int res = assign_IntVarArgs_from_ec_array(solver, size, x1arr, x1s);
3718    if (res != EC_succeed) return res;
3719
3720    EC_word warr =  EC_arg(3);
3721    if (warr.arity() != size) return RANGE_ERROR;
3722
3723    IntVarArgs ws(size);
3724    res = assign_IntVarArgs_from_ec_array(solver, size, warr, ws);
3725    if (res != EC_succeed) return res;
3726
3727    EC_word y1arr =  EC_arg(4);
3728    if (y1arr.arity() != size) return RANGE_ERROR;
3729
3730    IntVarArgs y1s(size);
3731    res = assign_IntVarArgs_from_ec_array(solver, size, y1arr, y1s);
3732    if (res != EC_succeed) return res;
3733
3734    EC_word harr =  EC_arg(5);
3735    if (harr.arity() != size) return RANGE_ERROR;
3736
3737    IntVarArgs hs(size);
3738    res = assign_IntVarArgs_from_ec_array(solver, size, harr, hs);
3739    if (res != EC_succeed) return res;
3740
3741    EC_word x2arr =  EC_arg(7);
3742    if (x2arr.arity() != size) return RANGE_ERROR;
3743
3744    IntVarArgs x2s(size);
3745    res = assign_IntVarArgs_from_ec_array(solver, size, x2arr, x2s);
3746    if (res != EC_succeed) return res;
3747
3748    EC_word y2arr =  EC_arg(8);
3749    if (y2arr.arity() != size) return RANGE_ERROR;
3750
3751    IntVarArgs y2s(size);
3752    res = assign_IntVarArgs_from_ec_array(solver, size, y2arr, y2s);
3753    if (res != EC_succeed) return res;
3754
3755    try {
3756	if (EC_arg(6).is_nil() != EC_succeed) {
3757	    EC_word oarr = EC_arg(6);
3758	    if (size != oarr.arity()) return RANGE_ERROR;
3759
3760	    BoolVarArgs os(size);
3761	    res = assign_BoolVarArgs_from_ec_array(solver, size, oarr, os);
3762
3763	    if (solver->is_first()) cache_domain_sizes(solver);
3764	    nooverlap(*solver, x1s, ws, x2s, y1s, hs, y2s, os);
3765	} else {
3766	    if (solver->is_first()) cache_domain_sizes(solver);
3767	    nooverlap(*solver, x1s, ws, x2s, y1s, hs, y2s);
3768	}
3769    }
3770    CatchAndReportGecodeExceptions
3771
3772    return EC_succeed;
3773}
3774
3775extern "C" VisAtt
3776int p_g_post_sqrt()
3777{
3778    GecodeSpace** solverp;
3779    GecodeSpace* solver;
3780
3781    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3782	return TYPE_ERROR;
3783    solver = *solverp;
3784    if (solver == NULL) return TYPE_ERROR;
3785
3786    try {
3787	EC_functor f;
3788	long xidx, yidx;
3789	IntVar x, y;
3790	Assign_IntVar(2, xidx, x);
3791	Assign_IntVar(3, yidx, y);
3792
3793	IntConLevel cl;
3794	Get_Consistency_Level(4, cl);
3795
3796	if (solver->is_first()) cache_domain_sizes(solver);
3797
3798	sqrt(*solver, y, x, cl);
3799    }
3800    CatchAndReportGecodeExceptions
3801
3802    return EC_succeed;
3803}
3804
3805extern "C" VisAtt
3806int p_g_post_sq()
3807{
3808    GecodeSpace** solverp;
3809    GecodeSpace* solver;
3810
3811    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3812	return TYPE_ERROR;
3813    solver = *solverp;
3814    if (solver == NULL) return TYPE_ERROR;
3815
3816    try {
3817	EC_functor f;
3818	long xidx, yidx;
3819	IntVar x, y;
3820	Assign_IntVar(2, xidx, x);
3821	Assign_IntVar(3, yidx, y);
3822
3823	IntConLevel cl;
3824	Get_Consistency_Level(4, cl);
3825
3826	if (solver->is_first()) cache_domain_sizes(solver);
3827
3828	sqr(*solver, y, x, cl);
3829    }
3830    CatchAndReportGecodeExceptions
3831
3832    return EC_succeed;
3833}
3834
3835
3836extern "C" VisAtt
3837int p_g_post_abs()
3838{
3839    GecodeSpace** solverp;
3840    GecodeSpace* solver;
3841
3842    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3843	return TYPE_ERROR;
3844    solver = *solverp;
3845    if (solver == NULL) return TYPE_ERROR;
3846
3847    try {
3848	EC_functor f;
3849	long xidx, yidx;
3850	IntVar x, y;
3851	Assign_IntVar(2, xidx, x);
3852	Assign_IntVar(3, yidx, y);
3853
3854	if (solver->is_first()) cache_domain_sizes(solver);
3855
3856	abs(*solver, y, x);
3857    }
3858    CatchAndReportGecodeExceptions
3859
3860    return EC_succeed;
3861}
3862
3863
3864extern "C" VisAtt
3865int p_g_post_mult()
3866{
3867    GecodeSpace** solverp;
3868    GecodeSpace* solver;
3869
3870    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3871	return TYPE_ERROR;
3872    solver = *solverp;
3873    if (solver == NULL) return TYPE_ERROR;
3874
3875    try {
3876	EC_functor f;
3877	long xidx, yidx, zidx;
3878	IntVar x, y, z;
3879	Assign_IntVar(2, xidx, x);
3880	Assign_IntVar(3, yidx, y);
3881	Assign_IntVar(4, zidx, z);
3882
3883	IntConLevel cl;
3884	Get_Consistency_Level(5, cl);
3885
3886	if (solver->is_first()) cache_domain_sizes(solver);
3887
3888	mult(*solver, y, z, x, cl);
3889    }
3890    CatchAndReportGecodeExceptions
3891
3892    return EC_succeed;
3893}
3894
3895extern "C" VisAtt
3896int p_g_post_div()
3897{
3898    GecodeSpace** solverp;
3899    GecodeSpace* solver;
3900
3901    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3902	return TYPE_ERROR;
3903    solver = *solverp;
3904    if (solver == NULL) return TYPE_ERROR;
3905
3906    try {
3907	EC_functor f;
3908	long xidx, yidx, zidx;
3909	IntVar x, y, z;
3910	Assign_IntVar(2, xidx, x);
3911	Assign_IntVar(3, yidx, y);
3912	Assign_IntVar(4, zidx, z);
3913
3914	if (solver->is_first()) cache_domain_sizes(solver);
3915
3916	div(*solver, y, z, x);
3917    }
3918    CatchAndReportGecodeExceptions
3919
3920    return EC_succeed;
3921}
3922
3923extern "C" VisAtt
3924int p_g_post_mod()
3925{
3926    GecodeSpace** solverp;
3927    GecodeSpace* solver;
3928
3929    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3930	return TYPE_ERROR;
3931    solver = *solverp;
3932    if (solver == NULL) return TYPE_ERROR;
3933
3934    try {
3935	EC_functor f;
3936	long xidx, yidx, zidx;
3937	IntVar x, y, z;
3938	Assign_IntVar(2, xidx, x);
3939	Assign_IntVar(3, yidx, y);
3940	Assign_IntVar(4, zidx, z);
3941
3942	if (solver->is_first()) cache_domain_sizes(solver);
3943
3944	mod(*solver, y, z, x);
3945    }
3946    CatchAndReportGecodeExceptions
3947
3948    return EC_succeed;
3949}
3950
3951extern "C" VisAtt
3952int p_g_post_divmod()
3953{
3954    GecodeSpace** solverp;
3955    GecodeSpace* solver;
3956
3957    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3958	return TYPE_ERROR;
3959    solver = *solverp;
3960    if (solver == NULL) return TYPE_ERROR;
3961
3962    try {
3963	EC_functor f;
3964	long xidx, yidx, qidx, midx;
3965	IntVar x, y, q, m;
3966	Assign_IntVar(2, xidx, x);
3967	Assign_IntVar(3, yidx, y);
3968	Assign_IntVar(4, qidx, q);
3969	Assign_IntVar(5, midx, m);
3970
3971	if (solver->is_first()) cache_domain_sizes(solver);
3972
3973	divmod(*solver, x, y, q, m);
3974    }
3975    CatchAndReportGecodeExceptions
3976
3977    return EC_succeed;
3978}
3979
3980extern "C" VisAtt
3981int p_g_post_max2()
3982{
3983    GecodeSpace** solverp;
3984    GecodeSpace* solver;
3985
3986    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
3987	return TYPE_ERROR;
3988    solver = *solverp;
3989    if (solver == NULL) return TYPE_ERROR;
3990
3991    try {
3992	EC_functor f;
3993	long xidx, yidx, zidx;
3994	IntVar x, y, z;
3995	Assign_IntVar(2, xidx, x);
3996	Assign_IntVar(3, yidx, y);
3997	Assign_IntVar(4, zidx, z);
3998
3999	IntConLevel cl;
4000	Get_Consistency_Level(5, cl);
4001
4002	if (solver->is_first()) cache_domain_sizes(solver);
4003
4004	max(*solver, y, z, x, cl);
4005    }
4006    CatchAndReportGecodeExceptions
4007
4008    return EC_succeed;
4009}
4010
4011extern "C" VisAtt
4012int p_g_post_min2()
4013{
4014    GecodeSpace** solverp;
4015    GecodeSpace* solver;
4016
4017    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
4018	return TYPE_ERROR;
4019    solver = *solverp;
4020    if (solver == NULL) return TYPE_ERROR;
4021
4022    try {
4023	EC_functor f;
4024	long xidx, yidx, zidx;
4025	IntVar x, y, z;
4026	Assign_IntVar(2, xidx, x);
4027	Assign_IntVar(3, yidx, y);
4028	Assign_IntVar(4, zidx, z);
4029
4030	IntConLevel cl;
4031	Get_Consistency_Level(5, cl);
4032
4033	if (solver->is_first()) cache_domain_sizes(solver);
4034
4035	min(*solver, y, z, x, cl);
4036    }
4037    CatchAndReportGecodeExceptions
4038
4039    return EC_succeed;
4040}
4041
4042extern "C" VisAtt
4043int p_g_post_maxlist()
4044{
4045    GecodeSpace** solverp;
4046    GecodeSpace* solver;
4047
4048    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
4049	return TYPE_ERROR;
4050    solver = *solverp;
4051    if (solver == NULL) return TYPE_ERROR;
4052
4053    try {
4054	EC_functor f;
4055	long xidx;
4056	IntVar x;
4057	Assign_IntVar(2, xidx, x);
4058
4059	EC_word varr = EC_arg(3);
4060	int size = varr.arity();
4061
4062	IntVarArgs vars(size);
4063	int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
4064	if (res != EC_succeed) return res;
4065
4066	IntConLevel cl;
4067	Get_Consistency_Level(4, cl);
4068
4069	if (solver->is_first()) cache_domain_sizes(solver);
4070
4071	max(*solver, vars, x, cl);
4072    }
4073    CatchAndReportGecodeExceptions
4074
4075    return EC_succeed;
4076}
4077
4078extern "C" VisAtt
4079int p_g_post_minlist()
4080{
4081    GecodeSpace** solverp;
4082    GecodeSpace* solver;
4083
4084    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
4085	return TYPE_ERROR;
4086    solver = *solverp;
4087    if (solver == NULL) return TYPE_ERROR;
4088
4089    try {
4090	EC_functor f;
4091	long xidx;
4092	IntVar x;
4093	Assign_IntVar(2, xidx, x);
4094
4095	EC_word varr = EC_arg(3);
4096	int size = varr.arity();
4097
4098	IntVarArgs vars(size);
4099	int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
4100	if (res != EC_succeed) return res;
4101
4102	IntConLevel cl;
4103	Get_Consistency_Level(4, cl);
4104
4105	if (solver->is_first()) cache_domain_sizes(solver);
4106
4107	min(*solver, vars, x, cl);
4108    }
4109    CatchAndReportGecodeExceptions
4110
4111    return EC_succeed;
4112}
4113
4114extern "C" VisAtt
4115int p_g_post_minidx()
4116{
4117    GecodeSpace** solverp;
4118    GecodeSpace* solver;
4119
4120    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
4121	return TYPE_ERROR;
4122    solver = *solverp;
4123    if (solver == NULL) return TYPE_ERROR;
4124
4125    try {
4126	EC_functor f;
4127	long xidx;
4128	IntVar x;
4129	Assign_IntVar(2, xidx, x);
4130
4131	long tb;
4132	if (EC_arg(4).is_long(&tb) != EC_succeed) return TYPE_ERROR;
4133	bool tiebreak = (tb ? true : false);
4134
4135	EC_word varr = EC_arg(3);
4136	int size = varr.arity();
4137
4138	IntVarArgs vars(size);
4139	int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
4140	if (res != EC_succeed) return res;
4141
4142	IntConLevel cl;
4143	Get_Consistency_Level(5, cl);
4144
4145	if (solver->is_first()) cache_domain_sizes(solver);
4146
4147	argmin(*solver, vars, x, tiebreak, cl);
4148    }
4149    CatchAndReportGecodeExceptions
4150
4151    return EC_succeed;
4152}
4153
4154extern "C" VisAtt
4155int p_g_post_maxidx()
4156{
4157    GecodeSpace** solverp;
4158    GecodeSpace* solver;
4159
4160    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
4161	return TYPE_ERROR;
4162    solver = *solverp;
4163    if (solver == NULL) return TYPE_ERROR;
4164
4165    try {
4166	EC_functor f;
4167	long xidx;
4168	IntVar x;
4169	Assign_IntVar(2, xidx, x);
4170
4171	long tb;
4172	if (EC_arg(4).is_long(&tb) != EC_succeed) return TYPE_ERROR;
4173	bool tiebreak = (tb ? true : false);
4174
4175	EC_word varr = EC_arg(3);
4176	int size = varr.arity();
4177
4178	IntVarArgs vars(size);
4179	int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
4180	if (res != EC_succeed) return res;
4181
4182	IntConLevel cl;
4183	Get_Consistency_Level(5, cl);
4184
4185	if (solver->is_first()) cache_domain_sizes(solver);
4186
4187	argmax(*solver, vars, x, tiebreak, cl);
4188    }
4189    CatchAndReportGecodeExceptions
4190
4191    return EC_succeed;
4192}
4193
4194extern "C" VisAtt
4195int p_g_post_rel()
4196{
4197    GecodeSpace** solverp;
4198    GecodeSpace* solver;
4199
4200    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
4201	return TYPE_ERROR;
4202    solver = *solverp;
4203    if (solver == NULL) return TYPE_ERROR;
4204
4205    try {
4206	EC_functor f;
4207	long i;
4208	IntVar x, y;
4209	Assign_IntVar(2, i, x);
4210
4211        bool y_is_int = false;
4212	Assign_IntVar_or_Int(4, i, y, y_is_int);
4213
4214	IntRelType r;
4215	Get_IntRelType(3, r);
4216
4217	IntConLevel cl;
4218	Get_Consistency_Level(5, cl);
4219
4220	if (solver->is_first()) cache_domain_sizes(solver);
4221
4222	if (y_is_int)
4223	  rel(*solver, x, r, (int)i, cl);
4224	else
4225	    rel(*solver, x, r, y, cl);
4226    }
4227    CatchAndReportGecodeExceptions
4228
4229    return EC_succeed;
4230}
4231
4232extern "C" VisAtt
4233int p_g_post_collection_rel()
4234{
4235    GecodeSpace** solverp;
4236    GecodeSpace* solver;
4237
4238    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
4239	return TYPE_ERROR;
4240    solver = *solverp;
4241    if (solver == NULL) return TYPE_ERROR;
4242
4243    try {
4244	EC_word xarr = EC_arg(2);
4245	long i = xarr.arity();
4246	//if (i == 0) return TYPE_ERROR;
4247
4248	IntVarArgs xs(i);
4249	int res = assign_IntVarArgs_from_ec_array(solver, i, xarr, xs);
4250	if (res != EC_succeed) return res;
4251
4252	IntVar y;
4253        bool y_is_int = false;
4254	EC_functor f;
4255	Assign_IntVar_or_Int(4, i, y, y_is_int);
4256
4257	IntRelType r;
4258	Get_IntRelType(3, r);
4259
4260	IntConLevel cl;
4261	Get_Consistency_Level(5, cl);
4262
4263	if (solver->is_first()) cache_domain_sizes(solver);
4264
4265	if (y_is_int)
4266	    rel(*solver, xs, r, (int)i, cl);
4267	else
4268	    rel(*solver, xs, r, y, cl);
4269    }
4270    CatchAndReportGecodeExceptions
4271
4272    return EC_succeed;
4273}
4274
4275extern "C" VisAtt
4276int p_g_post_lwb()
4277{
4278    GecodeSpace** solverp;
4279    GecodeSpace* solver;
4280
4281    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
4282	return TYPE_ERROR;
4283    solver = *solverp;
4284    if (solver == NULL) return TYPE_ERROR;
4285
4286    try {
4287	EC_functor f;
4288	long xidx;
4289	IntVar x;
4290	Assign_IntVar(2, xidx, x);
4291
4292	long lwb;
4293	if (EC_arg(3).is_long(&lwb) != EC_succeed) return TYPE_ERROR;
4294
4295	if (solver->is_first()) cache_domain_sizes(solver);
4296
4297	rel(*solver, x, IRT_GQ, (int)lwb);
4298    }
4299    CatchAndReportGecodeExceptions
4300
4301    return EC_succeed;
4302}
4303
4304extern "C" VisAtt
4305int p_g_post_upb()
4306{
4307    GecodeSpace** solverp;
4308    GecodeSpace* solver;
4309
4310    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
4311	return TYPE_ERROR;
4312    solver = *solverp;
4313    if (solver == NULL) return TYPE_ERROR;
4314
4315    try {
4316	EC_functor f;
4317	long xidx;
4318	IntVar x;
4319	Assign_IntVar(2, xidx, x);
4320
4321	long upb;
4322	if (EC_arg(3).is_long(&upb) != EC_succeed) return TYPE_ERROR;
4323
4324	if (solver->is_first()) cache_domain_sizes(solver);
4325
4326	rel(*solver, x, IRT_LQ, (int)upb);
4327    }
4328    CatchAndReportGecodeExceptions
4329
4330    return EC_succeed;
4331}
4332
4333extern "C" VisAtt
4334int p_g_post_boolchannel()
4335{
4336    GecodeSpace** solverp;
4337    GecodeSpace* solver;
4338
4339    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
4340	return TYPE_ERROR;
4341    solver = *solverp;
4342    if (solver == NULL) return TYPE_ERROR;
4343
4344    try {
4345	EC_functor f;
4346	long xidx;
4347	IntVar x;
4348	Assign_IntVar(2, xidx, x);
4349
4350	EC_word barr = EC_arg(3);
4351	int size = barr.arity();
4352
4353	BoolVarArgs vars(size);
4354	int res = assign_BoolVarArgs_from_ec_array(solver, size, barr, vars);
4355	if (res != EC_succeed) return res;
4356
4357	long min;
4358	if (EC_succeed != EC_arg(4).is_long(&min)) return TYPE_ERROR;
4359
4360	IntConLevel cl;
4361	Get_Consistency_Level(5, cl);
4362
4363	if (solver->is_first()) cache_domain_sizes(solver);
4364
4365	channel(*solver, vars, x, min, cl);
4366    }
4367    CatchAndReportGecodeExceptions
4368
4369    return EC_succeed;
4370}
4371
4372extern "C" VisAtt
4373int p_g_post_inverse()
4374{
4375    GecodeSpace** solverp;
4376    GecodeSpace* solver;
4377
4378    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
4379	return TYPE_ERROR;
4380    solver = *solverp;
4381    if (solver == NULL) return TYPE_ERROR;
4382
4383    EC_word arr1 = EC_arg(2);
4384    int size = arr1.arity();
4385
4386    EC_word arr2 = EC_arg(3);
4387    if (size != arr2.arity()) return TYPE_ERROR;
4388
4389    IntVarArgs vars1(size);
4390    int res = assign_IntVarArgs_from_ec_array(solver, size, arr1, vars1);
4391    if (res != EC_succeed) return res;
4392
4393    IntVarArgs vars2(size);
4394    res = assign_IntVarArgs_from_ec_array(solver, size, arr2, vars2);
4395    if (res != EC_succeed) return res;
4396
4397    IntConLevel cl;
4398    Get_Consistency_Level(4, cl);
4399
4400    if (solver->is_first()) cache_domain_sizes(solver);
4401
4402    try {
4403	channel(*solver, vars1, vars2, cl);
4404    }
4405    CatchAndReportGecodeExceptions
4406
4407    return EC_succeed;
4408}
4409
4410extern "C" VisAtt
4411int p_g_post_inverse_offset()
4412{
4413    GecodeSpace** solverp;
4414    GecodeSpace* solver;
4415
4416    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
4417	return TYPE_ERROR;
4418    solver = *solverp;
4419    if (solver == NULL) return TYPE_ERROR;
4420
4421    long off1;
4422    if (EC_succeed != EC_arg(3).is_long(&off1)) return TYPE_ERROR;
4423
4424    long off2;
4425    if (EC_succeed != EC_arg(5).is_long(&off2)) return TYPE_ERROR;
4426
4427    EC_word arr1 = EC_arg(2);
4428    int size = arr1.arity();
4429
4430    EC_word arr2 = EC_arg(4);
4431    if (size != arr2.arity()) return TYPE_ERROR;
4432
4433    IntVarArgs vars1(size);
4434    int res = assign_IntVarArgs_from_ec_array(solver, size, arr1, vars1);
4435    if (res != EC_succeed) return res;
4436
4437    IntVarArgs vars2(size);
4438    res = assign_IntVarArgs_from_ec_array(solver, size, arr2, vars2);
4439    if (res != EC_succeed) return res;
4440
4441    IntConLevel cl;
4442    Get_Consistency_Level(6, cl);
4443
4444    if (solver->is_first()) cache_domain_sizes(solver);
4445
4446    try {
4447	channel(*solver, vars1, off1, vars2, off2, cl);
4448    }
4449    CatchAndReportGecodeExceptions
4450
4451    return EC_succeed;
4452}
4453
4454extern "C" VisAtt
4455int p_g_post_ordered()
4456{
4457    GecodeSpace** solverp;
4458    GecodeSpace* solver;
4459
4460    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
4461	return TYPE_ERROR;
4462    solver = *solverp;
4463    if (solver == NULL) return TYPE_ERROR;
4464
4465    IntRelType r;
4466    Get_IntRelType(3, r);
4467
4468    EC_word varr = EC_arg(2);
4469    int size = varr.arity();
4470
4471    IntVarArgs vars(size);
4472    int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vars);
4473    if (res != EC_succeed) return res;
4474
4475    IntConLevel cl;
4476    Get_Consistency_Level(4, cl);
4477
4478    if (solver->is_first()) cache_domain_sizes(solver);
4479
4480    try {
4481      rel(*solver, vars, r, cl);
4482    }
4483    CatchAndReportGecodeExceptions
4484
4485    return EC_succeed;
4486}
4487
4488extern "C" VisAtt
4489int p_g_post_lex_order()
4490{
4491    GecodeSpace** solverp;
4492    GecodeSpace* solver;
4493
4494    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
4495	return TYPE_ERROR;
4496    solver = *solverp;
4497    if (solver == NULL) return TYPE_ERROR;
4498
4499    IntRelType r;
4500    Get_IntRelType(3, r);
4501
4502    EC_word xarr = EC_arg(2);
4503    int size = xarr.arity(); // can be 0
4504
4505    IntVarArgs xvars(size);
4506    int res = assign_IntVarArgs_from_ec_array(solver, size, xarr, xvars);
4507    if (res != EC_succeed) return res;
4508
4509    EC_word yarr = EC_arg(4);
4510    size = yarr.arity(); // can be 0
4511
4512    IntVarArgs yvars(size);
4513    res = assign_IntVarArgs_from_ec_array(solver, size, yarr, yvars);
4514    if (res != EC_succeed) return res;
4515
4516    IntConLevel cl;
4517    Get_Consistency_Level(5, cl);
4518
4519    if (solver->is_first()) cache_domain_sizes(solver);
4520
4521    try {
4522      rel(*solver, xvars, r, yvars, cl);
4523    }
4524    CatchAndReportGecodeExceptions
4525
4526    return EC_succeed;
4527}
4528
4529extern "C" VisAtt
4530int p_g_post_bin_packing()
4531{
4532    GecodeSpace** solverp;
4533    GecodeSpace* solver;
4534
4535    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
4536	return TYPE_ERROR;
4537    solver = *solverp;
4538    if (solver == NULL) return TYPE_ERROR;
4539
4540    EC_word iarr = EC_arg(2);
4541    int size = iarr.arity();
4542
4543    IntVarArgs ivars(size);
4544    int res = assign_IntVarArgs_from_ec_array(solver, size, iarr, ivars);
4545    if (res != EC_succeed) return res;
4546
4547    EC_word sarr = EC_arg(3);
4548    if (size != sarr.arity()) return TYPE_ERROR;
4549
4550    IntArgs sizes(size);
4551    res = assign_IntArgs_from_ec_array(size, sarr, sizes);
4552    if (res != EC_succeed) return res;
4553
4554    EC_word larr = EC_arg(4);
4555    size = larr.arity();
4556
4557    IntVarArgs lvars(size);
4558    res = assign_IntVarArgs_from_ec_array(solver, size, larr, lvars);
4559    if (res != EC_succeed) return res;
4560
4561    if (solver->is_first()) cache_domain_sizes(solver);
4562
4563    try {
4564      binpacking(*solver, lvars, ivars, sizes);
4565    }
4566    CatchAndReportGecodeExceptions
4567
4568    return EC_succeed;
4569}
4570
4571extern "C" VisAtt
4572int p_g_post_bin_packing_md()
4573{
4574    GecodeSpace** solverp;
4575    GecodeSpace* solver;
4576
4577    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
4578	return TYPE_ERROR;
4579    solver = *solverp;
4580    if (solver == NULL) return TYPE_ERROR;
4581
4582    EC_word iarr = EC_arg(2);
4583    int size = iarr.arity();
4584
4585    IntVarArgs ivars(size);
4586    int res = assign_IntVarArgs_from_ec_array(solver, size, iarr, ivars);
4587    if (res != EC_succeed) return res;
4588
4589    // ec_ivars exclude the dummy item 0
4590    IntVarArgs ec_ivars(size-1);
4591    for (int i = 1; i < size; i++) ec_ivars[i-1] = ivars[i];
4592
4593    EC_word sarr = EC_arg(3);
4594    size = sarr.arity();
4595
4596    IntArgs sizes(size);
4597    res = assign_IntArgs_from_ec_array(size, sarr, sizes);
4598    if (res != EC_succeed) return res;
4599
4600    EC_word larr = EC_arg(4);
4601    size = larr.arity();
4602
4603    IntVarArgs lvars(size);
4604    res = assign_IntVarArgs_from_ec_array(solver, size, larr, lvars);
4605    if (res != EC_succeed) return res;
4606
4607    if (solver->is_first()) cache_domain_sizes(solver);
4608
4609    EC_word carr = EC_arg(5);
4610    int dim = carr.arity();
4611
4612    IntArgs caps(dim);
4613    res = assign_IntArgs_from_ec_array(dim, carr, caps);
4614    if (res != EC_succeed) return res;
4615
4616    try {
4617	// exclude allocating to item 0 for 0 sized items
4618	rel(*solver, ec_ivars, IRT_GQ, 1);  // always, no gecode indexing
4619	binpacking(*solver, dim, lvars, ivars, sizes, caps);
4620    }
4621    CatchAndReportGecodeExceptions
4622
4623    return EC_succeed;
4624}
4625
4626extern "C" VisAtt
4627int p_g_create_tupleset_handle()
4628{
4629    long size;
4630    if (EC_arg(2).is_long(&size) != EC_succeed) return TYPE_ERROR;
4631
4632      EC_word ts = EC_arg(1), tarr;
4633
4634      IntArgs tuple((int)size);
4635
4636    try {
4637	TupleSet* tsetp = new(TupleSet);
4638
4639	while (ts.is_nil() != EC_succeed) {
4640
4641	    if (ts.is_list(tarr, ts) != EC_succeed) return TYPE_ERROR;
4642	    if (tarr.arity() != size) return TYPE_ERROR;
4643	    int res = assign_IntArgs_from_ec_array(size, tarr, tuple);
4644	    if (res != EC_succeed) return res;
4645	    tsetp->add(tuple);
4646	}
4647	tsetp->finalize();
4648
4649	return unify(EC_arg(3), handle(&tupleset_method, tsetp));
4650
4651    }
4652    CatchAndReportGecodeExceptions
4653
4654}
4655
4656extern "C" VisAtt
4657int p_g_post_table()
4658{
4659    GecodeSpace** solverp;
4660    GecodeSpace* solver;
4661
4662    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
4663	return TYPE_ERROR;
4664    solver = *solverp;
4665    if (solver == NULL) return TYPE_ERROR;
4666
4667    long size;
4668    if (EC_arg(4).is_long(&size) != EC_succeed) return TYPE_ERROR;
4669
4670    EC_atom emph;
4671    ExtensionalPropKind epk;
4672    if (EC_arg(5).is_atom(&emph) != EC_succeed) return TYPE_ERROR;
4673    if (strcmp(emph.name(), "mem") == 0) epk = EPK_MEMORY;
4674    else if (strcmp(emph.name(), "speed") == 0) epk = EPK_SPEED;
4675    else epk = EPK_DEF;
4676
4677    TupleSet* tsetp;
4678    if (EC_succeed != get_handle_from_arg(3, &tupleset_method, (void**)&tsetp))
4679	    return TYPE_ERROR;
4680    if (tsetp == NULL) return TYPE_ERROR;
4681
4682    IntConLevel cl;
4683    Get_Consistency_Level(6, cl);
4684
4685    try {
4686
4687      if (solver->is_first()) cache_domain_sizes(solver);
4688
4689      EC_word varr,  vtail = EC_arg(2);
4690      IntVarArgs vvars(size);
4691
4692      do {
4693	if (vtail.is_list(varr, vtail) != EC_succeed) return TYPE_ERROR;
4694	if (varr.arity() != size) return TYPE_ERROR;
4695	int res = assign_IntVarArgs_from_ec_array(solver, size, varr, vvars);
4696	if (res != EC_succeed) return res;
4697
4698	extensional(*solver, vvars, *tsetp, epk, cl);
4699      } while (vtail.is_nil() != EC_succeed);
4700    }
4701    CatchAndReportGecodeExceptions
4702
4703    return EC_succeed;
4704}
4705
4706extern "C" VisAtt
4707int p_g_create_dfa_handle()
4708{
4709
4710    EC_word tarr = EC_arg(1), triple, item;
4711    int n = tarr.arity();
4712    DFA::Transition ts[n];
4713    long from, to, sym;
4714
4715    for (int i=0; i < n; i++) {
4716	if (tarr.arg(i+1, triple) != EC_succeed) return TYPE_ERROR;
4717	if (triple.arity() != 3) return TYPE_ERROR;
4718
4719	// these arg positon must correspond to that defined for
4720	// struct(dfa_transition(...) in gfd.ecl
4721	triple.arg(1,item);
4722	if (item.is_long(&from) != EC_succeed) return TYPE_ERROR;
4723	triple.arg(2, item);
4724	if (item.is_long(&sym) != EC_succeed) return TYPE_ERROR;
4725	triple.arg(3, item);
4726	if (item.is_long(&to) != EC_succeed) return TYPE_ERROR;
4727	ts[i].i_state = (int)from;
4728	ts[i].symbol = (int)sym;
4729	ts[i].o_state = (int)to;
4730    }
4731
4732    long start;
4733    if (EC_arg(2).is_long(&start) != EC_succeed) return TYPE_ERROR;
4734
4735    n = EC_arg(3).arity();
4736    if (n < 1) return TYPE_ERROR;
4737    int finals[n];
4738
4739    for (int i=0; i < n; i++) {
4740	EC_arg(3).arg(i+1, item);
4741	long j;
4742	if (item.is_long(&j) != EC_succeed) return TYPE_ERROR;
4743	finals[i] = (int) j;
4744    }
4745
4746    try {
4747
4748      DFA* dfap = new DFA((int)start, ts, finals);
4749      return unify(EC_arg(4), handle(&dfa_method, dfap));
4750
4751    }
4752    CatchAndReportGecodeExceptions
4753
4754}
4755
4756extern "C" VisAtt
4757int p_g_create_regdfa_handle()
4758{
4759    try {
4760
4761      REG r  = ec2reg(EC_arg(1));
4762      DFA* dfap = new DFA(r);
4763
4764      return unify(EC_arg(2), handle(&dfa_method, dfap));
4765    }
4766    catch(Ec2gcException) {
4767	return TYPE_ERROR;
4768    }
4769    CatchAndReportGecodeExceptions
4770
4771}
4772
4773extern "C" VisAtt
4774int p_g_post_extensional()
4775{
4776    GecodeSpace** solverp;
4777    GecodeSpace* solver;
4778
4779    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
4780	return TYPE_ERROR;
4781    solver = *solverp;
4782    if (solver == NULL) return TYPE_ERROR;
4783
4784
4785    IntConLevel cl;
4786    Get_Consistency_Level(4, cl);
4787
4788
4789    try {
4790
4791	DFA* dfap;
4792	if (EC_succeed != get_handle_from_arg(3, &dfa_method, (void**)&dfap))
4793	    return TYPE_ERROR;
4794	if (dfap == NULL) return TYPE_ERROR;
4795
4796	if (solver->is_first()) cache_domain_sizes(solver);
4797
4798	EC_word varr,  vtail = EC_arg(2);
4799	do {
4800	    if (vtail.is_list(varr, vtail) != EC_succeed) return TYPE_ERROR;
4801	    int n = varr.arity();
4802	    IntVarArgs vvars(n);
4803	    int res = assign_IntVarArgs_from_ec_array(solver, n, varr, vvars);
4804	    if (res != EC_succeed) return res;
4805
4806	    extensional(*solver, vvars, *dfap);
4807
4808	} while (vtail.is_nil() != EC_succeed);
4809    }
4810    catch(Ec2gcException) {
4811	return TYPE_ERROR;
4812    }
4813    CatchAndReportGecodeExceptions
4814
4815    return EC_succeed;
4816}
4817
4818
4819double set_actmerit_to_degree(const Space& solver, IntVar x, int idx)
4820{
4821    return (double)x.degree()*
4822	static_cast<const GecodeSpace&>(solver).get_d_args(0);
4823}
4824
4825double set_user_actmerit(const Space& solver, IntVar x, int idx)
4826{
4827
4828    return static_cast<const GecodeSpace&>(solver).get_d_args(idx);
4829}
4830
4831#define SetRestartCutoff(RestartMethodArg,CutoffArg) {	\
4832    long l; \
4833    EC_word cutoffspec = EC_argument(RestartMethodArg,CutoffArg); \
4834    if (cutoffspec.functor(&f) != EC_succeed) \
4835	return TYPE_ERROR; \
4836    dident cdid = f.d; \
4837    Search::Cutoff* cutoff; \
4838    if (cdid == d_geo2) { \
4839	if (EC_argument(cutoffspec,1).is_long(&l) != EC_succeed) \
4840	    return TYPE_ERROR; \
4841	double b; \
4842	if (EC_argument(cutoffspec,2).is_double(&b) != EC_succeed) \
4843	    return TYPE_ERROR; \
4844	cutoff = Search::Cutoff::geometric((unsigned long)l,b); \
4845    } else if (cdid == d_luby1) { \
4846	if (EC_argument(cutoffspec,1).is_long(&l) != EC_succeed) \
4847	    return TYPE_ERROR; \
4848	cutoff = Search::Cutoff::luby((unsigned long)l); \
4849    } else if (cdid == d_rand4) { \
4850	long min, max, seed; \
4851	if (EC_argument(cutoffspec,1).is_long(&min) != EC_succeed) \
4852	    return TYPE_ERROR; \
4853	if (EC_argument(cutoffspec,2).is_long(&max) != EC_succeed) \
4854	    return TYPE_ERROR; \
4855	if (EC_argument(cutoffspec,3).is_long(&l) != EC_succeed) \
4856	    return TYPE_ERROR; \
4857	if (EC_argument(cutoffspec,4).is_long(&seed) != EC_succeed) \
4858	    return TYPE_ERROR; \
4859	cutoff = Search::Cutoff::rnd(seed,min,max,l); \
4860    } else if (cdid == d_con1) { \
4861	if (EC_argument(cutoffspec,1).is_long(&l) != EC_succeed) \
4862	    return TYPE_ERROR; \
4863	cutoff = Search::Cutoff::constant((unsigned int)l);	\
4864    } else if (cdid == d_lin1) { \
4865	if (EC_argument(cutoffspec,1).is_long(&l) != EC_succeed) \
4866	    return TYPE_ERROR; \
4867	cutoff = Search::Cutoff::linear((unsigned int)l);	\
4868    } else return RANGE_ERROR; \
4869    o.cutoff = cutoff; \
4870}
4871
4872
4873#define Set_S2_VarSelect(Arg, Select) { \
4874	    EC_functor f; \
4875	    Arg.functor(&f); \
4876	    dident selectdid = f.d; \
4877	    if (selectdid == d_max_wdeg2 || \
4878		selectdid == d_min_wdeg2 || \
4879		selectdid == d_max_wdeg_per_val2 ||  \
4880		selectdid == d_min_wdeg_per_val2 ) { \
4881\
4882		double d; \
4883		if (EC_argument(Arg,1).is_double(&d) == EC_succeed) { \
4884		    if (d > 1) return RANGE_ERROR; \
4885		    /* -1.0 if not specified in params, get existing decay */ \
4886		    else if (d < 0) d = solver->afc_decay(); \
4887		} else \
4888		    return TYPE_ERROR; \
4889\
4890		IntAFC wdeg(*solver, vars, d);	 \
4891		if (selectdid == d_max_wdeg2 ) { \
4892		    Select = INT_VAR_AFC_MAX(wdeg); \
4893		} else if (selectdid == d_min_wdeg2 ) \
4894		    Select = INT_VAR_AFC_MIN(wdeg); \
4895		else if (selectdid == d_max_wdeg_per_val2 ) { \
4896		    Select = INT_VAR_AFC_SIZE_MAX(wdeg); \
4897		} else if (selectdid == d_min_wdeg_per_val2 ) { \
4898		    Select = INT_VAR_AFC_SIZE_MIN(wdeg); \
4899		} \
4900\
4901		if (EC_argument(Arg,2).is_double(&d) == EC_succeed) { \
4902		    /* -1.0 if not specified in params, do not change */ \
4903		    if (d >= 0)  solver->afc_set(d); \
4904		} else \
4905		    return TYPE_ERROR; \
4906\
4907	    } else if (selectdid == d_max_act2  ||  \
4908		       selectdid == d_max_act_per_val2 || \
4909		       selectdid == d_min_act2 || \
4910		       selectdid == d_min_act_per_val2 ) { \
4911\
4912		double actdecay; \
4913		IntBranchMerit actinitf = NULL; \
4914\
4915		GetActivityOptions(Arg, vsize, actdecay, actinitf); \
4916		IntActivity act(*solver, vars, actdecay, actinitf); \
4917\
4918		if (selectdid == d_max_act2)  \
4919		    Select = INT_VAR_ACTIVITY_MAX(act); \
4920		else if (selectdid == d_max_act_per_val2)\
4921		    Select = INT_VAR_ACTIVITY_SIZE_MAX(act); \
4922		else if (selectdid == d_min_act2) \
4923		    Select = INT_VAR_ACTIVITY_MIN(act);  \
4924		else if (selectdid == d_min_act_per_val2) \
4925		    Select = INT_VAR_ACTIVITY_SIZE_MIN(act); \
4926		else return RANGE_ERROR; /* should not happen */	\
4927	    } else \
4928		return RANGE_ERROR; \
4929}
4930
4931#define Set_Atm_VarSelect(varselect) { \
4932	    if (selectdid == d_input_order) varselect = INT_VAR_NONE(); \
4933	    else if (selectdid == d_ff) varselect = INT_VAR_SIZE_MIN(); \
4934	    else if (selectdid == d_antiff) varselect = INT_VAR_SIZE_MAX(); \
4935	    else if (selectdid == d_occ) varselect = INT_VAR_DEGREE_MAX(); \
4936	    else if (selectdid == d_antiocc) varselect = INT_VAR_DEGREE_MIN();\
4937	    else if (selectdid == d_largest) varselect = INT_VAR_MAX_MAX(); \
4938	    else if (selectdid == d_smallest) varselect = INT_VAR_MIN_MIN(); \
4939	    else if (selectdid == d_largest_lwb) varselect = INT_VAR_MAX_MIN();\
4940	    else if (selectdid == d_smallest_upb) varselect = INT_VAR_MIN_MAX();\
4941	    else if (selectdid == d_most_constrained_per_val) varselect = INT_VAR_DEGREE_SIZE_MAX();\
4942	    else if (selectdid == d_least_constrained_per_val) varselect = INT_VAR_DEGREE_SIZE_MIN();\
4943	    else if (selectdid == d_max_regret) varselect = INT_VAR_REGRET_MIN_MAX();\
4944	    else if (selectdid == d_max_regret_lwb) varselect = INT_VAR_REGRET_MIN_MAX();\
4945	    else if (selectdid == d_min_regret_lwb) varselect = INT_VAR_REGRET_MIN_MIN();\
4946	    else if (selectdid == d_max_regret_upb) varselect = INT_VAR_REGRET_MAX_MAX();\
4947	    else if (selectdid == d_min_regret_upb) varselect = INT_VAR_REGRET_MAX_MIN();\
4948	    else if (selectdid == d_random) { \
4949		Rnd r(0U);\
4950		r.time(); \
4951		varselect = INT_VAR_RND(r); \
4952	    } else return RANGE_ERROR; \
4953}
4954
4955#define GetActivityOptions(ActArg, vsize, actdecay, actinitf) {	    \
4956	EC_word w;						    \
4957	if (ActArg.arg(1, w) == EC_fail) return TYPE_ERROR;	    \
4958	if (w.is_double(&actdecay) == EC_succeed) {		    \
4959	    if (actdecay < 0) actdecay = 1.0;			    \
4960	    if (actdecay > 1) return RANGE_ERROR;		    \
4961	} else							    \
4962	    return TYPE_ERROR;					    \
4963	if (ActArg.arg(2, w) == EC_fail) return TYPE_ERROR;	    \
4964	EC_atom atm;						    \
4965	if (w.is_nil() == EC_succeed) {actinitf = NULL; }	    \
4966	else if (w.arity() == 1) {					\
4967	    EC_functor f;						\
4968	    w.functor(&f);						\
4969	    if (strcmp(f.name(), "vals") == 0) {			\
4970		actinitf = set_user_actmerit;				\
4971		/* set user merit array */				\
4972		w = EC_argument(w, 1);					\
4973		long size = w.arity();					\
4974		if (size != vsize) return RANGE_ERROR;                  \
4975		double* inits = new double[size], d;			\
4976		EC_word arg;						\
4977		for(int i=0; i<size; i++) {				\
4978		    arg = EC_argument(w, i+1);				\
4979		    if (arg.is_double(&d) == EC_succeed) {		\
4980			inits[i] = d;					\
4981		    } else return TYPE_ERROR;				\
4982		}							\
4983		solver->set_d_args(inits);				\
4984	    } else if (strcmp(f.name(),"degree") == 0) {		\
4985		double* f = new double[1];				\
4986		actinitf = set_actmerit_to_degree;			\
4987		if (EC_argument(w, 1).is_double(&f[0]) == EC_succeed) {	\
4988		    solver->set_d_args(f);			\
4989		} else return TYPE_ERROR;				\
4990	    } else return RANGE_ERROR;					\
4991	} else return RANGE_ERROR;					\
4992}
4993
4994#define GFDSTATSIZE    5
4995
4996extern "C" VisAtt
4997int p_g_setup_search()
4998{
4999    GecodeSpace** solverp;
5000    GecodeSpace* solver;
5001
5002    EC_functor f;
5003    EC_word w;
5004
5005    if (EC_arg(1).functor(&f) != EC_succeed) return TYPE_ERROR;
5006    if (strcmp(f.name(), "gfd_space") != 0) return TYPE_ERROR;
5007    EC_arg(1).arg(SPACE_HANDLE_POS, w);
5008    if (w.is_handle(&gfd_method, (void**)&solverp) != EC_succeed)
5009	return TYPE_ERROR;
5010    solver = *solverp;
5011
5012    try {
5013	EC_word varr = EC_arg(2);
5014	int res, vsize = varr.arity();
5015
5016	IntVarArgs vars(vsize);
5017	res = assign_IntVarArgs_from_ec_array(solver, vsize, varr, vars);
5018	if (res != EC_succeed) return res;
5019
5020	EC_atom atm;
5021	bool do_tiebreak = false;
5022	IntVarBranch varselect, tiebreakselect;
5023
5024	switch (EC_arg(6).arity()) {
5025	case 2:
5026	    do_tiebreak = true;
5027
5028	    Set_S2_VarSelect(EC_arg(6), tiebreakselect)
5029	    break;
5030
5031	case 1: {
5032	    do_tiebreak = true;
5033
5034	    EC_functor f;
5035	    EC_arg(6).functor(&f);
5036	    dident selectdid = f.d;
5037	    if (selectdid == d_random1) {
5038		long seed;
5039		if (EC_succeed == EC_argument(EC_arg(6), 1).is_long(&seed)) {
5040		    Rnd r((unsigned int)seed);
5041		    tiebreakselect = INT_VAR_RND(r);
5042		} else
5043		    return TYPE_ERROR;
5044	    } else
5045		return TYPE_ERROR;
5046	    break;
5047	}
5048	case 0:
5049	    if (EC_arg(6).is_atom(&atm) != EC_succeed) return TYPE_ERROR;
5050	    if (strcmp(atm.name(), "none") != 0) {
5051		do_tiebreak = true;
5052		dident selectdid = atm.d;
5053
5054		Set_Atm_VarSelect(tiebreakselect)
5055	    }
5056	    break;
5057
5058	default:
5059	    return TYPE_ERROR;
5060	}
5061
5062	switch (EC_arg(3).arity()) {
5063	case 2:
5064	    Set_S2_VarSelect(EC_arg(3), varselect)
5065	    break;
5066
5067	case 1: {
5068	    EC_functor f;
5069	    EC_arg(3).functor(&f);
5070	    dident selectdid = f.d;
5071	    if (selectdid == d_random1) {
5072		long seed;
5073		if (EC_succeed == EC_argument(EC_arg(3), 1).is_long(&seed)) {
5074		    Rnd r((unsigned int)seed);
5075		    varselect = INT_VAR_RND(r);
5076		} else
5077		    return TYPE_ERROR;
5078	    } else
5079		return TYPE_ERROR;
5080	    break;
5081	}
5082	case 0: {
5083	    if (EC_arg(3).is_atom(&atm) != EC_succeed) return TYPE_ERROR;
5084	    dident selectdid = atm.d;
5085	    if (selectdid == d_most_constrained) {
5086		varselect = INT_VAR_SIZE_MIN();
5087		do_tiebreak = true;
5088		tiebreakselect = INT_VAR_DEGREE_MAX();
5089	    } else
5090		Set_Atm_VarSelect(varselect)
5091	    break;
5092	}
5093	default:
5094	    return TYPE_ERROR;
5095	}
5096
5097	IntValBranch valchoice;
5098	switch (EC_arg(4).arity()) {
5099	case 1: {
5100	    EC_functor f;
5101	    EC_arg(4).functor(&f);
5102	    dident choicedid = f.d;
5103	    if (choicedid == d_random1) {
5104		long seed;
5105		if (EC_succeed == EC_argument(EC_arg(4),1).is_long(&seed)) {
5106		    Rnd r((unsigned int)seed);
5107		    valchoice = INT_VAL_RND(r);
5108		} else
5109		    return TYPE_ERROR;
5110	    } else if (choicedid == d_fr_sm1 ||
5111		       choicedid == d_fr_lg1 ||
5112		       choicedid == d_fr_up1 || choicedid == d_fr_down1) {
5113		EC_word valarr = EC_argument(EC_arg(4),1);
5114		int res, size = valarr.arity();
5115
5116		IntArgs vals(size);
5117		assign_IntArgs_from_ec_array(size, valarr, vals);
5118		if (choicedid == d_fr_sm1) valchoice = INT_VAL_NEAR_MIN(vals);
5119		else if (choicedid == d_fr_lg1) valchoice = INT_VAL_NEAR_MAX(vals);
5120		else if (choicedid == d_fr_down1) valchoice = INT_VAL_NEAR_DEC(vals);
5121		else if (choicedid == d_fr_up1) valchoice = INT_VAL_NEAR_INC(vals);
5122		else return TYPE_ERROR; // should not happen
5123	    } else
5124		return TYPE_ERROR;
5125	    break;
5126	}
5127	case 0:
5128	    if (EC_arg(4).is_atom(&atm) != EC_succeed) return TYPE_ERROR;
5129	    if (strcmp(atm.name(), "min") == 0) valchoice = INT_VAL_MIN();
5130	    else if (strcmp(atm.name(), "max") == 0) valchoice = INT_VAL_MAX();
5131	    else if (strcmp(atm.name(), "median") == 0) valchoice = INT_VAL_MED();
5132	    else if (strcmp(atm.name(), "random") == 0) {
5133		Rnd r(0U);
5134		r.time();
5135		valchoice = INT_VAL_RND(r);
5136	    } else if (strcmp(atm.name(), "split") == 0) valchoice = INT_VAL_SPLIT_MIN();
5137	    else if (strcmp(atm.name(), "reverse_split") == 0) valchoice = INT_VAL_SPLIT_MAX();
5138	    else if (strcmp(atm.name(), "indomain") == 0) valchoice = INT_VALUES_MIN();
5139	    else if (strcmp(atm.name(), "indomain_reverse_enum") == 0) valchoice = INT_VALUES_MAX();
5140	    else if (strcmp(atm.name(), "interval_min") == 0) valchoice = INT_VAL_RANGE_MIN();
5141	    else if (strcmp(atm.name(), "interval_max") == 0) valchoice = INT_VAL_RANGE_MAX();
5142	    else return RANGE_ERROR;
5143	    break;
5144
5145	default:
5146	    return TYPE_ERROR;
5147	}
5148
5149	EC_functor f;
5150	long oidx;
5151	SearchMethod method;
5152	Search::Options o;
5153
5154	switch (EC_arg(5).arity()) {
5155	case 0:
5156	    if (EC_arg(5).is_atom(&atm) == EC_succeed) {
5157		if (strcmp(atm.name(), "complete") == 0) {
5158		    method = METHOD_COMPLETE;
5159		} else return RANGE_ERROR;
5160	    } else return RANGE_ERROR;
5161	    break;
5162	case 1:
5163	    EC_arg(5).functor(&f); // must be compound -- arity 1
5164	    if (strcmp(f.name(),"bb_min") == 0) {
5165		if (EC_argument(EC_arg(5),1).is_long(&oidx) != EC_succeed)
5166		    return TYPE_ERROR;
5167		method = METHOD_CONTINUE_BAB;
5168	    } else if (strcmp(f.name(),"restart_min") == 0) {
5169		if (EC_argument(EC_arg(5),1).is_long(&oidx) != EC_succeed)
5170		    return TYPE_ERROR;
5171		o.cutoff = Search::Cutoff::constant(ULONG_MAX);
5172		o.nogoods_limit = 0;
5173		method = METHOD_RESTART_BAB;
5174	    } else if (strcmp(f.name(),"restart") == 0) {
5175		SetRestartCutoff(EC_arg(5),1);
5176		o.nogoods_limit = 0;
5177		method = METHOD_RESTART;
5178	    } else return RANGE_ERROR;
5179	    break;
5180	case 2:
5181	    EC_arg(5).functor(&f);
5182	    if (strcmp(f.name(), "restart_min") == 0) {
5183		if (EC_argument(EC_arg(5),1).is_long(&oidx) != EC_succeed)
5184		    return TYPE_ERROR;
5185		SetRestartCutoff(EC_arg(5),2);
5186		o.nogoods_limit = 0;
5187		method = METHOD_RESTART_RBAB;
5188	    } else if (strcmp(f.name(), "restart") == 0) {
5189		SetRestartCutoff(EC_arg(5),1);
5190		long ng_lim;
5191		if (EC_argument(EC_arg(5),2).is_long(&ng_lim) != EC_succeed)
5192		    return TYPE_ERROR;
5193		o.nogoods_limit = (unsigned int) ng_lim;
5194		method = METHOD_RESTART;
5195	    } else return RANGE_ERROR;
5196	    break;
5197	case 3:
5198	    EC_arg(5).functor(&f);
5199	    if (strcmp(f.name(), "restart_min") == 0) {
5200		if (EC_argument(EC_arg(5),1).is_long(&oidx) != EC_succeed)
5201		    return TYPE_ERROR;
5202		SetRestartCutoff(EC_arg(5),2);
5203		long ng_lim;
5204		if (EC_argument(EC_arg(5),3).is_long(&ng_lim) != EC_succeed)
5205		    return TYPE_ERROR;
5206		o.nogoods_limit = (unsigned int) ng_lim;
5207		method = METHOD_RESTART_RBAB;
5208	    } else return RANGE_ERROR;
5209	default:
5210	    return RANGE_ERROR;
5211	}
5212
5213	long timeout;
5214	if (EC_succeed != EC_arg(7).is_long(&timeout)) return TYPE_ERROR;
5215
5216	// these positions must correspond to gfd.ecl's struct:
5217	// struct(gfd_stats(prop,fail,node,depth,mem)).
5218	long fail_lim = 0, node_lim = 0, mem_lim = 0;
5219	if ((EC_arg(8).functor(&f) == EC_succeed) && (f.arity() == GFDSTATSIZE)
5220	    && (strcmp(f.name(), "gfd_stats") == 0)) {
5221	    if (EC_argument(EC_arg(8),2).is_long(&fail_lim) != EC_succeed)
5222		fail_lim = 0;
5223	    if (EC_argument(EC_arg(8),3).is_long(&node_lim) != EC_succeed)
5224		node_lim = 0;
5225	    if (EC_argument(EC_arg(8),5).is_long(&mem_lim) != EC_succeed)
5226		mem_lim = 0;
5227	}
5228
5229	long adaptived = 0, commitd = 0, ithreads;
5230	double threads = 1.0;
5231	if ((EC_arg(9).functor(&f) == EC_succeed)
5232	    && (strcmp(f.name(), "gfd_control") == 0)) {
5233	  // these positions must correspond to their definition in
5234	  // the struct(gdf_control(...)) in gfd.ecl
5235	    if (EC_argument(EC_arg(9),1).is_long(&commitd) != EC_succeed)
5236	        commitd = 0;  // commit_distance, arg 1
5237	    if (EC_argument(EC_arg(9),2).is_long(&adaptived) != EC_succeed)
5238	        adaptived = 0; // adaptive_distance, arg 2
5239	    if (EC_argument(EC_arg(9),3).is_long(&ithreads) == EC_succeed)
5240	        threads = (double) ithreads; // threads, arg 3 (set as int)
5241	    else if (EC_argument(EC_arg(9),3).is_double(&threads) != EC_succeed)
5242	        threads = 1.0;
5243	}
5244
5245	LDSBSymsStore* sym_storep = NULL;
5246	Symmetries syms;
5247	if (EC_arg(10).is_nil() != EC_succeed) {
5248	    if (EC_succeed != get_handle_from_arg(10, &ldsbsyms_method, (void**)&sym_storep))
5249		return TYPE_ERROR;
5250	    std::queue<SymmetryHandle>* symsp = sym_storep->symsp;
5251	    while (!symsp->empty()) {
5252		syms << symsp->front();
5253		symsp->pop();
5254	    }
5255	    std::queue<IntVar*>* intsp = sym_storep->intsp;
5256	    while (!intsp->empty()) {
5257		// work-around LDSB 'Variable in Symmetry not branched'
5258		// exception on dummy IntVars representing integers.
5259		// Add these to the search variables
5260		vars << *(intsp->front());
5261		intsp->pop();
5262	    }
5263	}
5264
5265	solver->clear_snapshot(); // make sure we do cache the current values!
5266	cache_domain_sizes(solver);
5267	if (!do_tiebreak) {
5268	    // time() sets the seeds for the random var/val methods
5269	    // setting user defined seed to be added later
5270	    if (sym_storep == NULL)
5271		branch(*solver, vars, varselect, valchoice);
5272	    else
5273		branch(*solver, vars, varselect, valchoice, syms);
5274	    //VarBranchOptions::time(), ValBranchOptions::time());
5275	} else {
5276	    if (sym_storep == NULL)
5277		branch(*solver, vars, tiebreak(varselect, tiebreakselect), valchoice);
5278	    else
5279		branch(*solver, vars, tiebreak(varselect, tiebreakselect), valchoice, syms);
5280
5281	    //		   VarBranchOptions::time(), ValBranchOptions::time());
5282	}
5283
5284	ec_trail_undo(_g_delete_space, ec_arg(1).val.ptr, ec_arg(1).val.ptr+SPACE_STAMP_POS, NULL, 0, TRAILED_WORD32);
5285
5286	Cutoff* cutoffp;
5287	if (timeout > 0 || fail_lim > 0 || node_lim > 0 || mem_lim > 0) {
5288	    cutoffp = new Cutoff((unsigned)node_lim,(unsigned)fail_lim,
5289				 (unsigned)timeout/*,(size_t)mem_lim*/);
5290	    o.stop = cutoffp;
5291	} else
5292	    cutoffp = NULL;
5293
5294	if (adaptived > 0) o.a_d = adaptived;
5295	if (commitd > 0) o.c_d = commitd;
5296	if (threads != 1.0) o.threads = threads;
5297
5298	GecodeSearch* searchp = new GecodeSearch(solver, o, (unsigned) oidx, cutoffp, method);
5299
5300	return unify(EC_arg(11), handle(&gfdsearch_method, searchp));
5301    }
5302    CatchAndReportGecodeExceptions
5303}
5304
5305
5306extern "C" VisAtt
5307int p_g_do_search()
5308{
5309    GecodeSpace** solverp;
5310    GecodeSpace* solver;
5311
5312    EC_functor f;
5313    EC_word w;
5314
5315    if (EC_arg(1).functor(&f) != EC_succeed) return TYPE_ERROR;
5316    if (strcmp(f.name(), "gfd_space") != 0) return TYPE_ERROR;
5317    EC_arg(1).arg(SPACE_HANDLE_POS, w);
5318    if (w.is_handle(&gfd_method, (void**)&solverp) != EC_succeed)
5319	return TYPE_ERROR;
5320    solver = *solverp;
5321    if (solver != NULL) {
5322	delete solver; // previous solution
5323	solver = NULL;
5324    }
5325
5326    GecodeSpace** presearchp;
5327    GecodeSpace* presearch;
5328
5329    if (EC_succeed != get_handle_from_arg(3, &gfd_method, (void**)&presearchp))
5330	return TYPE_ERROR;
5331    presearch = *presearchp;
5332
5333    unsigned long nprop, nfail, nnode, depth;
5334    size_t mem;
5335
5336    GecodeSearch* searchp;
5337    if (EC_succeed != get_handle_from_arg(2, &gfdsearch_method, (void**)&searchp))
5338	return TYPE_ERROR;
5339
5340    try {
5341	long status;
5342
5343	if (searchp->stopp != NULL) searchp->stopp->reset();
5344	switch (searchp->method) {
5345	case METHOD_COMPLETE:
5346	case METHOD_RESTART:
5347	    *solverp = searchp->next();
5348	    status = (*solverp == NULL ? 0 : 1);
5349	    break;
5350
5351	case METHOD_RESTART_RBAB:
5352	case METHOD_CONTINUE_BAB:
5353	case METHOD_RESTART_BAB: {
5354	    GecodeSpace* last_sol = NULL;
5355	    bool has_aborted = false;
5356	    do {
5357		solver = searchp->next();
5358		if (solver != NULL) {
5359		    if (solver->vCost.assigned()) {
5360			p_fprintf(log_output_,"Found a solution with cost %d\n", solver->vCost.val());
5361		    } else {
5362			p_fprintf(log_output_, "Cost variable not instantiated.\n");
5363			has_aborted = true;
5364			break;
5365		    }
5366		    ec_flush(log_output_);
5367		    last_sol = solver;
5368		} else
5369		    *solverp = last_sol;
5370	    } while (solver != NULL);
5371	    status =  (has_aborted ? 2/*1<<2*/ : (last_sol == NULL ? 0 : 1));
5372	    break;
5373	}
5374
5375	default:
5376	    return RANGE_ERROR;
5377	    break;
5378
5379	}
5380
5381	Search::Statistics stat = searchp->statistics();
5382	nprop = stat.propagate;
5383	nfail = stat.fail;
5384	nnode = stat.node;
5385	depth = stat.depth;
5386	//	mem = stat.memory;
5387
5388	// these must correspond to gfd_stats struct in gfd.ecl
5389	EC_functor sf("gfd_stats", GFDSTATSIZE);
5390	EC_word stats = term(sf, (long)nprop, (long)nfail, (long)nnode,
5391			     (long)depth, 0L);
5392	if (unify(EC_arg(6), stats) != EC_succeed) return EC_fail;
5393
5394	if (searchp->stopped()) {
5395	    status |=  searchp->stopp->reason();
5396	}
5397
5398	if (unify(EC_arg(7), EC_word(status)) != EC_succeed) return EC_fail;
5399
5400	if (*solverp != NULL) {// there is a solution
5401	    solver = *solverp;
5402	    // no need to trail the undo function here, as solverp would be
5403	    // deleted either in a new call to this procedure for the next
5404	    // solution, or by _free_space_handle() for the last solution
5405	    //ec_trail_undo(_g_delete_space, ec_arg(1).val.ptr, NULL, NULL, 0, TRAILED_WORD32);
5406
5407	    int snapshotsize = presearch->dom_snapshot.size();
5408	    int dsize;
5409	    EC_word tail = nil(),chgtail = nil();
5410
5411	    CheckAndMakeChanged(presearch, tail, chgtail);
5412
5413	    if (unify(EC_arg(4), tail) != EC_succeed) {
5414		return EC_fail;
5415	    } else {
5416		return unify(EC_arg(5), chgtail);
5417	    }
5418	} else {
5419	    return unify(EC_arg(4), nil());
5420	}
5421    }
5422    CatchAndReportGecodeExceptions
5423}
5424
5425extern "C" VisAtt
5426int p_g_create_ldsbsyms_handle()
5427{
5428
5429    LDSBSymsStore* sym_storep = new LDSBSymsStore();
5430    return unify(EC_arg(1), handle(&ldsbsyms_method, sym_storep));
5431
5432}
5433
5434extern "C" VisAtt
5435int p_g_add_ldsbsym_valueinter()
5436{
5437    LDSBSymsStore* sym_storep;
5438
5439    if (EC_succeed != get_handle_from_arg(1, &ldsbsyms_method, (void**)&sym_storep))
5440	return TYPE_ERROR;
5441
5442    EC_word varr = EC_arg(2);
5443    int res, size = varr.arity();
5444    IntArgs vals(size);
5445    res = assign_IntArgs_from_ec_array(size, varr, vals);
5446    if (res != EC_succeed) return res;
5447
5448    sym_storep->symsp->push(ValueSymmetry(vals));
5449
5450    return EC_succeed;
5451}
5452
5453extern "C" VisAtt
5454int p_g_add_ldsbsym_variableinter()
5455{
5456    LDSBSymsStore* sym_storep;
5457
5458    if (EC_succeed != get_handle_from_arg(1, &ldsbsyms_method, (void**)&sym_storep))
5459	return TYPE_ERROR;
5460
5461    GecodeSpace** solverp;
5462    GecodeSpace* solver;
5463
5464    if (EC_succeed != get_handle_from_arg(3, &gfd_method, (void**)&solverp))
5465	return TYPE_ERROR;
5466    solver = *solverp;
5467    if (solver == NULL) return TYPE_ERROR;
5468
5469    EC_word varr = EC_arg(2);
5470    int res, size = varr.arity();
5471    IntVarArgs vars(size);
5472    res = assign_IntVarArgs_and_collect_ints(solver, size, varr, vars, sym_storep->intsp);
5473    if (res != EC_succeed) return res;
5474
5475    sym_storep->symsp->push(VariableSymmetry(vars));
5476
5477    return EC_succeed;
5478}
5479
5480extern "C" VisAtt
5481int p_g_add_ldsbsym_parvalueinter()
5482{
5483    LDSBSymsStore* sym_storep;
5484
5485    if (EC_succeed != get_handle_from_arg(1, &ldsbsyms_method, (void**)&sym_storep))
5486	return TYPE_ERROR;
5487
5488    EC_word varr = EC_arg(2);
5489    int res, size = varr.arity();
5490    IntArgs vals(size);
5491    res = assign_IntArgs_from_ec_array(size, varr, vals);
5492    if (res != EC_succeed) return res;
5493
5494    long length;
5495    if (EC_arg(3).is_long(&length) == EC_succeed)
5496	sym_storep->symsp->push(ValueSequenceSymmetry(vals, length));
5497
5498    return EC_succeed;
5499}
5500
5501extern "C" VisAtt
5502int p_g_add_ldsbsym_parvariableinter()
5503{
5504    LDSBSymsStore* sym_storep;
5505
5506    if (EC_succeed != get_handle_from_arg(1, &ldsbsyms_method, (void**)&sym_storep))
5507	return TYPE_ERROR;
5508
5509    GecodeSpace** solverp;
5510    GecodeSpace* solver;
5511
5512    if (EC_succeed != get_handle_from_arg(4, &gfd_method, (void**)&solverp))
5513	return TYPE_ERROR;
5514    solver = *solverp;
5515    if (solver == NULL) return TYPE_ERROR;
5516
5517    EC_word varr = EC_arg(2);
5518    int res, size = varr.arity();
5519    IntVarArgs vars(size);
5520    res = assign_IntVarArgs_and_collect_ints(solver, size, varr, vars, sym_storep->intsp);
5521    if (res != EC_succeed) return res;
5522
5523    long length;
5524    if (EC_arg(3).is_long(&length) != EC_succeed) return TYPE_ERROR;
5525
5526    sym_storep->symsp->push(VariableSequenceSymmetry(vars, (int)length));
5527
5528    return EC_succeed;
5529}
5530
5531extern "C" VisAtt
5532int p_g_add_ldsbsym_valuesreflect()
5533{
5534    LDSBSymsStore* sym_storep;
5535
5536    if (EC_succeed != get_handle_from_arg(1, &ldsbsyms_method, (void**)&sym_storep))
5537	return TYPE_ERROR;
5538
5539    long lower, upper;
5540
5541    if (EC_arg(2).is_long(&lower) != EC_succeed) return TYPE_ERROR;
5542    if (EC_arg(3).is_long(&upper) != EC_succeed) return TYPE_ERROR;
5543
5544    sym_storep->symsp->push(values_reflect((int)lower, (int)upper));
5545
5546    return EC_succeed;
5547}
5548
5549
5550extern "C" VisAtt
5551int p_g_add_matrix_ldsbsym()
5552{
5553    LDSBSymsStore* sym_storep;
5554
5555    if (EC_succeed != get_handle_from_arg(1, &ldsbsyms_method, (void**)&sym_storep))
5556	return TYPE_ERROR;
5557
5558    GecodeSpace** solverp;
5559    GecodeSpace* solver;
5560
5561    if (EC_succeed != get_handle_from_arg(6, &gfd_method, (void**)&solverp))
5562	return TYPE_ERROR;
5563    solver = *solverp;
5564    if (solver == NULL) return TYPE_ERROR;
5565
5566    EC_word varr = EC_arg(2);
5567    int res, size = varr.arity();
5568    IntVarArgs vars(size);
5569    res = assign_IntVarArgs_and_collect_ints(solver, size, varr, vars, sym_storep->intsp);
5570    if (res != EC_succeed) return res;
5571
5572    long ncols, nrows;
5573    if (EC_arg(3).is_long(&nrows) != EC_succeed) return TYPE_ERROR;
5574    if (EC_arg(4).is_long(&ncols) != EC_succeed) return TYPE_ERROR;
5575
5576    // Gecode's Matrix rows/cols order are reverse of ECLiPSe/C++
5577    // but the matrix still uses row-major ordering
5578    Matrix<IntVarArgs>m(vars, ncols, nrows);
5579
5580    EC_atom f;
5581    if (EC_arg(5).is_atom(&f) != EC_succeed) return TYPE_ERROR;
5582    if (strcmp(f.name(), "r_int") == 0)
5583	sym_storep->symsp->push(rows_interchange(m));
5584    else if (strcmp(f.name(), "c_int") == 0)
5585	sym_storep->symsp->push(columns_interchange(m));
5586    else if (strcmp(f.name(), "c_ref") == 0)
5587	sym_storep->symsp->push(columns_reflect(m));
5588    else if (strcmp(f.name(), "r_ref") == 0)
5589	sym_storep->symsp->push(rows_reflect(m));
5590    else if (strcmp(f.name(), "d_ref") == 0)
5591	sym_storep->symsp->push(diagonal_reflect(m));
5592    else
5593	return TYPE_ERROR;
5594
5595    return EC_succeed;
5596}
5597
5598
5599extern "C" VisAtt
5600int p_g_get_gfd_maxint()
5601{
5602    return unify(EC_arg(1), EC_word(Int::Limits::max));
5603}
5604
5605extern "C" VisAtt
5606int p_g_get_gfd_minint()
5607{
5608    return unify(EC_arg(1), EC_word(Int::Limits::min));
5609}
5610
5611extern "C" VisAtt
5612int p_g_get_afc_decay()
5613{
5614    GecodeSpace** solverp;
5615
5616    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
5617	return TYPE_ERROR;
5618
5619    double d;
5620    try {
5621	d = (*solverp)->afc_decay();
5622    }
5623    CatchAndReportGecodeExceptions
5624
5625    return unify(EC_arg(2), EC_word(d));
5626}
5627
5628extern "C" VisAtt
5629int p_g_set_afc_decay()
5630{
5631    GecodeSpace** solverp;
5632
5633    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
5634	return TYPE_ERROR;
5635
5636    double d;
5637    if (EC_succeed != EC_arg(2).is_double(&d)) return TYPE_ERROR;
5638    try {
5639	(*solverp)->afc_decay(d);
5640    }
5641    CatchAndReportGecodeExceptions
5642
5643    return EC_succeed;
5644}
5645
5646extern "C" VisAtt
5647int p_g_reset_afc()
5648{
5649    GecodeSpace** solverp;
5650
5651    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
5652	return TYPE_ERROR;
5653
5654    double d;
5655    if (EC_succeed != EC_arg(2).is_double(&d)) return TYPE_ERROR;
5656    try {
5657	(*solverp)->afc_set(d);
5658    }
5659    CatchAndReportGecodeExceptions
5660    return EC_succeed;
5661}
5662
5663extern "C" VisAtt
5664int p_g_create_select_handle()
5665{
5666    EC_word idxs = EC_arg(2);
5667    long size = idxs.arity();
5668
5669    int* idxarr = new int[size+1];
5670    idxarr[0] = (int) size;
5671
5672    EC_word w;
5673    idxs.arg(1, w);
5674    long i;
5675    for (int j=1; j <= size; j++) {
5676	long i;
5677	EC_word w;
5678
5679	if (EC_fail == idxs.arg(j, w)) return RANGE_ERROR;
5680	if (EC_succeed == w.is_long(&i)) {
5681	    idxarr[j] = (int)i;
5682	} else return TYPE_ERROR;
5683    }
5684
5685
5686    GecodeSpace** solverp;
5687    GecodeSpace* solver;
5688
5689    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
5690	return TYPE_ERROR;
5691    solver = *solverp;
5692    if (solver == NULL) return TYPE_ERROR;
5693
5694    VarSelectH* selecth = new VarSelectH();
5695    selecth->idxs = idxarr;
5696    selecth->act_inited = false;
5697
5698    if (EC_arg(3).arity() == 2) {
5699	EC_functor f;
5700	EC_arg(3).functor(&f);
5701	dident selectdid = f.d;
5702
5703	if (selectdid == d_max_wdeg2 ||
5704	    selectdid == d_min_wdeg2 ||
5705	    selectdid == d_max_wdeg_per_val2 ||
5706	    selectdid == d_min_wdeg_per_val2 ) {
5707
5708	    double d;
5709	    if (EC_argument(EC_arg(3),1).is_double(&d) == EC_succeed) {
5710		if (d > 1) return RANGE_ERROR;
5711		/* -1.0 if not specified in params, do not change */
5712		else if (d >= 0) solver->afc_decay(d);
5713	    } else
5714		return TYPE_ERROR;
5715
5716	    if (EC_argument(EC_arg(3),2).is_double(&d) == EC_succeed) {
5717		/* -1.0 if not specified in params, do not change */
5718		if (d >= 0)  solver->afc_set(d);
5719	    } else
5720		return TYPE_ERROR;
5721
5722
5723	} else if (selectdid == d_max_act2  ||
5724		   selectdid == d_max_act_per_val2 ||
5725		   selectdid == d_min_act2 ||
5726		   selectdid == d_min_act_per_val2 ) {
5727
5728	    double actdecay;
5729	    IntBranchMerit actinitf = NULL;
5730
5731	    GetActivityOptions(EC_arg(3), size, actdecay, actinitf);
5732
5733	    IntVarArgs vars(size);
5734	    for(int i=1; i <= size; i++) vars[i-1] = solver->vInt[idxarr[i]];
5735
5736	    if (!solver->init_select_activity(vars, actdecay, actinitf)) return RANGE_ERROR;
5737	    selecth->act_inited = true;
5738
5739	} else
5740	    return RANGE_ERROR;
5741
5742
5743    }
5744
5745    return unify(EC_arg(4), handle(&varselecth_method, selecth));
5746
5747}
5748
5749#define Find_Best_IntVar_For(InitialVal, Best, Current, Checkbest) {	\
5750    Best = InitialVal;					\
5751    for (int j=1; j <= size; j++) {\
5752	int idx = (int) idxarr[j];\
5753	if ((dsize = solver->vInt[idx].size()) > 1) {	\
5754	    if Checkbest {\
5755		Best = Current;			\
5756		bestidx = idx;\
5757	    }\
5758	}\
5759    }\
5760}
5761
5762// check that an IntAct was initialised for this selecth
5763#define Check_Act_Inited(selecth) if (!selecth->act_inited) return RANGE_ERROR
5764
5765extern "C" VisAtt
5766int p_g_select()
5767{
5768    GecodeSpace** solverp;
5769    GecodeSpace* solver;
5770
5771    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
5772	return TYPE_ERROR;
5773    solver = *solverp;
5774    if (solver == NULL) return TYPE_ERROR;
5775
5776    VarSelectH* selecth;
5777    if (EC_succeed != get_handle_from_arg(2, &varselecth_method, (void **)&selecth))
5778	return TYPE_ERROR;
5779    int* idxarr = selecth->idxs;
5780
5781
5782    int size =  idxarr[0], bestidx = -1, best;
5783    unsigned int it, dsize;
5784    double ft, fbest;
5785
5786    try {
5787	switch (EC_arg(3).arity()) {
5788	case 0: {
5789	    EC_atom selectatm;
5790	    if (EC_arg(3).is_atom(&selectatm) != EC_succeed) return TYPE_ERROR;
5791	    dident selectdid = selectatm.d;
5792
5793	    if (selectdid == d_ff) {
5794		Find_Best_IntVar_For(Int::Limits::max, best, dsize,
5795				     ((int)dsize < best));
5796	    } else if (selectdid == d_max_wdeg) {
5797		Find_Best_IntVar_For(std::numeric_limits<double>::min(), fbest, ft,
5798				     ((ft=solver->vInt[idx].afc(*solver)) > fbest));
5799	    } else if (selectdid == d_min_wdeg) {
5800		Find_Best_IntVar_For(std::numeric_limits<double>::max(), fbest, ft,
5801				     ((ft=solver->vInt[idx].afc(*solver)) < fbest));
5802	    } else if (selectdid == d_occ) {
5803		Find_Best_IntVar_For(Int::Limits::min, best, it,
5804				     ((int)(it=solver->vInt[idx].degree()) > best));
5805	    } else if (selectdid == d_antiocc) {
5806		Find_Best_IntVar_For(Int::Limits::max, best, it,
5807				     ((int)(it=solver->vInt[idx].degree()) < best));
5808	    } else if (selectdid == d_input_order) {
5809		for (int j=1; j <= size; j++) {
5810		    int idx =  idxarr[j];
5811		    if (solver->vInt[idx].size() > 1) {
5812			bestidx = idx;
5813			break;
5814		    }
5815		}
5816	    } else if (selectdid == d_smallest) {
5817		Find_Best_IntVar_For(Int::Limits::max, best, it,
5818				     ((int)(it=solver->vInt[idx].min()) < best));
5819	    } else if (selectdid == d_largest) {
5820		Find_Best_IntVar_For(Int::Limits::min, best, it,
5821				     ((int)(it=solver->vInt[idx].max()) > best));
5822	    } else if (selectdid == d_smallest_upb) {
5823		Find_Best_IntVar_For(Int::Limits::max, best, it,
5824				     ((int)(it=solver->vInt[idx].max()) < best));
5825	    } else if (selectdid == d_largest) {
5826		Find_Best_IntVar_For(Int::Limits::min, best, it,
5827				     ((int)(it=solver->vInt[idx].min()) > best));
5828	    } else if (selectdid == d_max_wdeg_per_val) {
5829		Find_Best_IntVar_For(std::numeric_limits<double>::min(), fbest, ft,
5830				     ((ft=solver->vInt[idx].afc(*solver)/(double)dsize) > fbest));
5831	    } else if (selectdid == d_most_constrained) {
5832		int best2 = Int::Limits::min;
5833		best = Int::Limits::max;
5834		for (int j=1; j <= size; j++) {
5835		    int idx =  idxarr[j];
5836		    if ((dsize = (int)solver->vInt[idx].size()) > 1) {
5837			if ((int)dsize <= best &&
5838			    ((it=(int)solver->vInt[idx].degree()),(int)dsize < best || it > best2)) {
5839			    best = dsize;
5840			    best2 = it;
5841			    bestidx = idx;
5842			}
5843		    }
5844		}
5845	    } else if (selectdid == d_max_regret_lwb) {
5846		Find_Best_IntVar_For(Int::Limits::min, best, it,
5847				     ((int)(it=solver->vInt[idx].regret_min()) > best));
5848	    } else if (selectdid == d_max_regret_upb) {
5849		Find_Best_IntVar_For(Int::Limits::min, best, it,
5850				     ((int)(it=solver->vInt[idx].regret_max()) > best));
5851	    } else if (selectdid == d_min_regret_lwb) {
5852		Find_Best_IntVar_For(Int::Limits::max, best, it,
5853				     ((int)(it=solver->vInt[idx].regret_min()) < best));
5854	    } else if (selectdid == d_min_regret_upb) {
5855		Find_Best_IntVar_For(Int::Limits::max, best, it,
5856				     ((int)(it=solver->vInt[idx].regret_max()) < best));
5857	    } else if (selectdid == d_min_wdeg_per_val) {
5858		Find_Best_IntVar_For(std::numeric_limits<double>::max(), fbest, ft,
5859				     ((ft=solver->vInt[idx].afc(*solver)/(double)dsize) < fbest));
5860	    } else if (selectdid == d_most_constrained_per_val) {
5861		Find_Best_IntVar_For(Int::Limits::min, fbest, ft,
5862				     ((ft=solver->vInt[idx].degree()/(double)dsize) > fbest));
5863	    } else if (selectdid == d_least_constrained_per_val) {
5864		Find_Best_IntVar_For(Int::Limits::max, fbest, ft,
5865				     ((ft=solver->vInt[idx].degree()/(double)dsize) < fbest));
5866
5867	    } else if (selectdid == d_antiff) {
5868		Find_Best_IntVar_For(Int::Limits::min, best, dsize,
5869				     ((int)dsize > best));
5870	    } else if (selectdid == d_max_act) {
5871		Check_Act_Inited(selecth);
5872		Find_Best_IntVar_For(std::numeric_limits<double>::min(), fbest, ft,
5873				     ((ft=solver->get_select_activity(j-1)) > fbest));
5874	    } else if (selectdid == d_min_act) {
5875		Check_Act_Inited(selecth);
5876		Find_Best_IntVar_For(std::numeric_limits<double>::max(), fbest, ft,
5877				     ((ft=solver->get_select_activity(j-1)) < fbest));
5878	    } else if (selectdid == d_max_act_per_val) {
5879		Check_Act_Inited(selecth);
5880		Find_Best_IntVar_For(std::numeric_limits<double>::min(), fbest, ft,
5881				     ((ft=solver->get_select_activity(j-1))/dsize > fbest));
5882	    } else if (selectdid == d_min_act_per_val) {
5883		Check_Act_Inited(selecth);
5884		Find_Best_IntVar_For(std::numeric_limits<double>::max(), fbest, ft,
5885				     ((ft=solver->get_select_activity(j-1))/dsize < fbest));
5886	    } else
5887		return RANGE_ERROR;
5888
5889	    break;
5890	}
5891	case 1: {
5892	    EC_functor f;
5893	    EC_arg(3).functor(&f);
5894	    dident selectdid = f.d;
5895
5896	    /* parameters ignored */
5897	    if (selectdid == d_max_wdeg1) {
5898		Find_Best_IntVar_For(std::numeric_limits<double>::min(), fbest, ft,
5899				     ((ft=solver->vInt[idx].afc(*solver)) > fbest));
5900	    } else if (selectdid == d_min_wdeg1) {
5901		Find_Best_IntVar_For(std::numeric_limits<double>::max(), fbest, ft,
5902				     ((ft=solver->vInt[idx].afc(*solver)) < fbest));
5903	    } else if (selectdid == d_max_wdeg_per_val1) {
5904		Find_Best_IntVar_For(std::numeric_limits<double>::max(), fbest, ft,
5905				     ((ft=solver->vInt[idx].afc(*solver)/(double)dsize) < fbest));
5906	    } else if (selectdid == d_min_wdeg_per_val1) {
5907		Find_Best_IntVar_For(std::numeric_limits<double>::max(), fbest, ft,
5908				     ((ft=solver->vInt[idx].afc(*solver)/(double)dsize) < fbest));
5909	    } else if (selectdid == d_max_act1) {
5910		Check_Act_Inited(selecth);
5911		Find_Best_IntVar_For(std::numeric_limits<double>::min(), fbest, ft,
5912 				     ((ft=solver->get_select_activity(j-1)) > fbest));
5913 	    } else if (selectdid == d_min_act1) {
5914		Check_Act_Inited(selecth);
5915		Find_Best_IntVar_For(std::numeric_limits<double>::max(), fbest, ft,
5916				     ((ft=solver->get_select_activity(j-1)) < fbest));
5917	    } else if (selectdid == d_max_act_per_val1) {
5918		Check_Act_Inited(selecth);
5919		Find_Best_IntVar_For(std::numeric_limits<double>::min(), fbest, ft,
5920				     ((ft=solver->get_select_activity(j-1))/dsize > fbest));
5921	    } else if (selectdid == d_min_act_per_val1) {
5922		Check_Act_Inited(selecth);
5923		Find_Best_IntVar_For(std::numeric_limits<double>::max(), fbest, ft,
5924				     ((ft=solver->get_select_activity(j-1))/dsize < fbest));
5925	    } else
5926		return RANGE_ERROR;
5927
5928	    break;
5929	}
5930	default:
5931	    return RANGE_ERROR;
5932	}
5933    }
5934    CatchAndReportGecodeExceptions
5935
5936    if (bestidx > 0) return unify(EC_arg(4), EC_word((long)bestidx));
5937    else return EC_fail; // No var selected
5938
5939}
5940
5941extern "C" VisAtt
5942int p_g_get_var_domain_handle()
5943{
5944    GecodeSpace** solverp;
5945    GecodeSpace* solver;
5946
5947    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
5948	return TYPE_ERROR;
5949    solver = *solverp;
5950    if (solver == NULL) return TYPE_ERROR;
5951
5952    long xidx;
5953    if (EC_succeed != EC_arg(2).is_long(&xidx)) return(TYPE_ERROR);
5954
5955    IntVarRanges r(solver->vInt[(int)xidx]);
5956
5957    IntSet* setp = new IntSet(r);
5958
5959    return unify(EC_arg(3), handle(&domain_method, setp));
5960
5961}
5962
5963extern "C" VisAtt
5964int p_g_add_newvars_dom_union()
5965{
5966    GecodeSpace** solverp;
5967    GecodeSpace* solver;
5968    long newsize;
5969    int oldsize;
5970
5971    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
5972	return TYPE_ERROR;
5973    solver = *solverp;
5974    if (solver == NULL) return TYPE_ERROR;
5975    if (EC_succeed != EC_arg(2).is_long(&newsize)) return(TYPE_ERROR);
5976    oldsize = solver->vInt.size();
5977
5978    long xidx;
5979    IntVar x;
5980    EC_functor f;
5981    Assign_IntVar(3, xidx, x);
5982
5983    long yidx;
5984    IntVar y;
5985    Assign_IntVar(4, yidx, y);
5986
5987    try {
5988	IntVarRanges rx(x);
5989	IntVarRanges ry(y);
5990
5991	Iter::Ranges::Union<IntVarRanges, IntVarRanges> unioniter(rx, ry);
5992
5993	IntSet  newdom(unioniter);
5994
5995	//	solver->vInt.resize(*solver, (int)++newsize); // ++ to skip over idx 0
5996	for (int i=oldsize; i <= (int)newsize; i++)
5997	  solver->vInt << IntVar(*solver, newdom);
5998
5999	return EC_succeed;
6000    }
6001    CatchAndReportGecodeExceptions
6002}
6003
6004extern "C" VisAtt
6005int p_g_add_newvar_copy()
6006{
6007    GecodeSpace** solverp;
6008    GecodeSpace* solver;
6009    long newsize;
6010    int oldsize;
6011
6012    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
6013	return TYPE_ERROR;
6014    solver = *solverp;
6015    if (solver == NULL) return TYPE_ERROR;
6016    if (EC_succeed != EC_arg(2).is_long(&newsize)) return(TYPE_ERROR);
6017    oldsize = solver->vInt.size();
6018
6019    long oldidx;
6020
6021    if (EC_succeed != EC_arg(3).is_long(&oldidx)) return TYPE_ERROR;
6022
6023    try {
6024	IntVar y(*solver, Int::Limits::min, Int::Limits::max);
6025	Int::IntView yv(y);
6026	IntVarRanges iter(solver->vInt[(int)oldidx]);
6027	(void) yv.narrow_r(*solver, iter, false);
6028
6029	//	solver->vInt.resize(*solver, (int)++newsize); // ++ to skip over idx 0
6030	solver->vInt << y;
6031
6032	return EC_succeed;
6033    }
6034    CatchAndReportGecodeExceptions
6035}
6036
6037extern "C" VisAtt
6038int p_g_get_propagator_num()
6039{
6040    GecodeSpace** solverp;
6041    GecodeSpace* solver;
6042
6043    if (EC_succeed != get_handle_from_arg(1, &gfd_method, (void**)&solverp))
6044	return TYPE_ERROR;
6045
6046    try {
6047	long nprop = (*solverp)->propagators();
6048	return unify(EC_arg(2), EC_word(nprop));
6049    }
6050    CatchAndReportGecodeExceptions
6051
6052}
6053
6054extern "C" VisAtt
6055int p_g_gecode_version()
6056{
6057  return unify(EC_arg(1), EC_word(GECODE_VERSION));
6058}
6059
6060