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) 2006 Cisco Systems, Inc. All Rights Reserved. 18 * 19 * Contributor(s): Pascal Brisset 20 * 21 * END LICENSE BLOCK */ 22// $Id: ilog.cc,v 1.1 2006/09/23 01:54:04 snovello Exp $ 23 24// External predicates for the ilog.pl module 25 26#include "classes.h" 27#include "ec2il.h" 28 29// Positions in the term attached to an Ilog Variable (object of EC_IlcIntVar) 30// Must be COHERENT with ilog_structure in ilog.cc 31#define VARIABLE_INDEX 2 32#define SUSPENSIONS_MIN_INDEX 3 33#define SUSPENSIONS_MAX_INDEX 4 34#define SUSPENSIONS_ANY_INDEX 5 35 36#define ILOG_ALREADY_INITIALIZED PERROR 37#define ILOG_NOT_INITIALIZED PERROR 38#define CheckInit() if (!ilog_initialized) {return ILOG_NOT_INITIALIZED;} 39 40static ilog_initialized = IlcFalse; 41 42 43t_ext_type ilog_method = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 44}; 45 46 47extern "C" 48int 49c_ilog_init() 50{ 51 if (ilog_initialized) { m.end();} 52 53 IlcInitFloat(); 54 m = IlcManager(IlcNoEdit); 55 m.useExceptions(); 56 zero = IlcIntVar(m, 0, 0); zero.setValue(0); 57 ilog_initialized = IlcTrue; 58 return unify(EC_arg(1), handle(&ilog_method, m.getImpl())); 59} 60 61int 62get_handle_from_arg(int arg, t_ext_type *method, void **obj) 63{ 64 return ((EC_succeed == EC_arg(arg).is_handle(method, obj))); 65} 66 67extern "C" 68c_ilog_is_intvar() 69{ 70 void **obj = NULL; 71 return EC_arg(1).is_handle(intvar_method, obj); 72} 73extern "C" 74int 75c_ilog_print_info() 76{ 77 CheckInit(); 78 m.printInformation(); 79 return(EC_succeed); 80} 81 82void 83instantiate_ecvar(EC_IlcIntVar v) 84{ 85 EC_word ec_term = *v.getEC_term(); 86 EC_word ec_var = EC_argument(ec_term, VARIABLE_INDEX); 87 88 if (unify(ec_var, EC_word(v.getValue())) != EC_succeed) { 89 throw IlcFailException(); 90 } 91} 92 93void 94wake_range_suspensions(EC_IlcIntVar v) 95{ 96 EC_word ec_term = *v.getEC_term(); 97 98 ec_term.schedule_suspensions(SUSPENSIONS_MIN_INDEX); 99 ec_term.schedule_suspensions(SUSPENSIONS_MAX_INDEX); 100 ec_term.schedule_suspensions(SUSPENSIONS_ANY_INDEX); 101} 102 103void 104wake_domain_suspensions(EC_IlcIntVar v) 105{ 106 EC_word ec_term = *v.getEC_term(); 107 108 ec_term.schedule_suspensions(SUSPENSIONS_ANY_INDEX); 109} 110 111int 112suspend_and_unify_intvar(EC_IlcIntVar v, int arg) 113{ 114 v.whenCondition(instantiate_ecvar, IlcWhenValue); 115 v.whenCondition(wake_range_suspensions, IlcWhenRange); 116 v.whenCondition(wake_domain_suspensions, IlcWhenDomain); 117 return unify(EC_arg(arg), handle(intvar_method, v.getImpl())); 118} 119 120extern "C" 121int 122c_ilog_intvar() // ilog_intvar(Term, Id, Min, Max) 123{ 124 CheckInit(); 125 IlcInt min = ec_arg(3).val.nint; 126 IlcInt max = ec_arg(4).val.nint; 127 128 EC_IlcIntVar v(m, min, max, EC_arg(1)); 129 return suspend_and_unify_intvar(v, 2); 130} 131 132extern "C" 133int 134c_ilog_enum_var() // ilog_intvar(Term, Id, Values) 135{ 136 CheckInit(); 137 try { 138 IlcIntArray values = int_array_of_list(EC_arg(3)); 139 140 EC_IlcIntVar v(m, values, EC_arg(1)); 141 142 return suspend_and_unify_intvar(v, 2); 143 } 144 catch (Ec2ilException) { 145 // It's not a list 146 return INSTANTIATION_FAULT; 147 } 148 catch (IsLongException) { 149 // It's not a list of integers 150 return INSTANTIATION_FAULT; 151 } 152} 153 154extern "C" 155int 156c_ilog_copy_var() // ilog_copy_var(Term, Copy, Original) 157{ 158 CheckInit(); 159 160 IlcIntVar original; 161 162 if (get_handle_from_arg(3, intvar_method, (void**)&original)) { 163 IlcIntVar copy = original.getCopy(m); 164 165 EC_IlcIntVar v(m, copy, EC_arg(1)); 166 167 return suspend_and_unify_intvar(v, 2); 168 } else { 169 return INSTANTIATION_FAULT; 170 } 171} 172 173extern "C" 174int 175c_ilog_get_range() // ilog_get_range(Var, Min, Max) 176{ 177 CheckInit(); 178 IlcIntVar v; 179 180 if (get_handle_from_arg(1, intvar_method, (void**)&v)) { 181 if (v.isBound()) {ec_panic("Bound variable", "ilog_get_range");} 182 183 return (unify(EC_arg(3), EC_word(v.getMax())) || 184 unify(EC_arg(2), EC_word(v.getMin()))); 185 } else { 186 Error(INSTANTIATION_FAULT); 187 } 188} 189 190 191extern "C" 192int 193c_ilog_get_size() // ilog_get_size(Var, Size) 194{ 195 CheckInit(); 196 IlcIntVar v; 197 198 if (get_handle_from_arg(1, intvar_method, (void**)&v)) { 199 return (unify(EC_arg(2), EC_word(v.getSize()))); 200 } else { 201 Error(INSTANTIATION_FAULT); 202 } 203} 204 205 206EC_word 207make_interval(IlcInt last, IlcInt max, EC_word l, EC_functor dotdot) 208{ 209 if (last == max) { // Single number 210 return list(EC_word(max), l); 211 } else if (last == max - 1) { // 2-value interval 212 return list(EC_word(max-1), list(EC_word(max), l)); 213 } else { // Interval 214 return list(term(dotdot, EC_word(last), EC_word(max)), l); 215 } 216 217} 218 219extern "C" 220c_ilog_get_domain() // ilog_get_domain(Var, List of integers and intervals) 221{ 222 CheckInit(); 223 IlcIntVar v; 224 225 if (get_handle_from_arg(1, intvar_method, (void**)&v)) { 226 if (v.isBound()) {ec_panic("Bound variable", "ilog_get_domain");} 227 228 IlcInt max = v.getMax(); 229 EC_word l = nil(); 230 EC_functor dotdot("..", 2); 231 232 if (max - v.getMin() > 100000) { 233 // Too long to return the actual domain 234 return unify(EC_arg(2), make_interval(v.getMin(), max, l, dotdot)); 235 } else { 236 // Let's fetch all the values starting from the max 237 IlcInt last = max; 238 239 while (v.getNextLower(last) != last) { 240 IlcInt lower = v.getNextLower(last); 241 if (lower == last - 1) { 242 last = lower; 243 } else { 244 l = make_interval(last, max, l, dotdot); 245 max = lower; last = lower; 246 } 247 } 248 l = make_interval(last, max, l, dotdot); 249 return (unify(EC_arg(2), l)); 250 } 251 } else { 252 Error(INSTANTIATION_FAULT); 253 } 254} 255 256 257int 258ilog_call(IlcConstraint g, pword *handle) 259{ 260 ReturnTryPushTrailCatchPop(m.add(g), handle); 261} 262 263extern "C" 264int 265c_ilog_set_value() // ilog_set_value(H, Var, IntValue) 266{ 267 CheckInit(); 268 IlcIntVar v; 269 270 if (get_handle_from_arg(2, intvar_method, (void**)&v)) { 271 if (v.isBound()) { 272 Assert(v.getValue() == ec_arg(3).val.nint, "c_ilog_set_value"); 273 return EC_succeed; 274 } else { 275 return ilog_call(v == ec_arg(3).val.nint, ec_arg(1).val.ptr); 276 } 277 } else { 278 Error(INSTANTIATION_FAULT); 279 } 280} 281 282 283extern "C" 284int 285c_ilog_eq_vars() // ilog_eq_vars(H, X, Y) 286{ 287 CheckInit(); 288 IlcIntVar x, y; 289 290 if (get_handle_from_arg(2, intvar_method, (void**)&x) 291 && get_handle_from_arg(3, intvar_method, (void**)&y)) { 292 return ilog_call(x == y, ec_arg(1).val.ptr); 293 } else { 294 Error(INSTANTIATION_FAULT); 295 } 296} 297 298 299extern "C" int 300c_ilog_add() // ilog_add(SolverHandle, Constraint) 301{ 302 CheckInit(); 303 try { 304 return ilog_call(ec2il_cstr(EC_arg(2)), ec_arg(1).val.ptr); 305 } 306 catch (Ec2ilException) { 307 Error(INSTANTIATION_FAULT); 308 } 309 catch(IlcFailException) { // ec2il_cstr may raise this exception (element/3) 310 return EC_fail; 311 } 312} 313 314 315extern "C" 316int 317c_ilog_setmin() 318{ 319 CheckInit(); 320 IlcIntVar v; 321 322 if (get_handle_from_arg(2, intvar_method, (void**)&v)) { 323 ReturnTryPushTrailCatchPop(v.setValue(v.getMin()), ec_arg(1).val.ptr); 324 } else { 325 Error(INSTANTIATION_FAULT); 326 } 327} 328 329extern "C" 330int 331c_ilog_removemin() 332{ 333 CheckInit(); 334 IlcIntVar v; 335 336 if (get_handle_from_arg(2, intvar_method, (void**)&v)) { 337 ReturnTryPushTrailCatchPop(v.setMin(v.getMin()+1), ec_arg(1).val.ptr); 338 } else { 339 Error(INSTANTIATION_FAULT); 340 } 341} 342