1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package zeus.concepts.fn;
25
26 import java.util.*;
27 import zeus.util.*;
28 import zeus.concepts.*;
29
30 /***
31 note: changed some accesses for 1.2.1 so that I could infer contents for
32 precondition unification bug fixes
33 */
34 public class ConstraintFn extends ValueFunction {
35 static final int LE = 0;
36 static final int LT = 1;
37 static final int GE = 2;
38 static final int GT = 3;
39 static final int UN = 4;
40 static final int NE = 5;
41
42 public static final String[] operators = {
43 "<=", "<", ">=", ">", "~", "!="
44 };
45
46 public ValueFunction arg = null;
47 protected int op = -1;
48
49 public ConstraintFn(String operator, ValueFunction arg) {
50 super(CONS,7);
51 op = Misc.whichPosition(operator,operators);
52 if ( op == -1 )
53 throw new IllegalArgumentException("Unknown operator \'" + operator +
54 "\' in constraint expression");
55
56 this.arg = arg;
57 switch(op) {
58 case LE:
59 case GE:
60 case LT:
61 case GT:
62 switch(arg.getID()) {
63 case ID:
64 case LVAR:
65 case FIELD:
66 case ARITH:
67 case FUNC:
68 case INT:
69 case REAL:
70 case DATE:
71 case TIME:
72 case METH:
73 break;
74
75 default:
76 throw new IllegalArgumentException("Illegal operand in \'" +
77 this + "\'");
78 }
79 break;
80
81 case UN:
82 case NE:
83 break;
84
85 default:
86 throw new IllegalArgumentException("Illegal operand in \'" +
87 this + "\'");
88 }
89 }
90
91
92 public String toString() {
93 String out = operators[op] + arg;
94 return out;
95 }
96
97
98 public int getOperator() {
99 return op;
100 }
101
102
103 Object getArg(int position) {
104 if ( position != 0 )
105 throw new ArrayIndexOutOfBoundsException(position);
106 return arg;
107 }
108
109
110 public boolean references(ValueFunction var) {
111 return arg.references(var);
112 }
113
114
115 public Vector variables() {
116 return arg.variables();
117 }
118
119
120 public boolean isDeterminate() {
121 return arg.isDeterminate();
122 }
123
124
125 public ValueFunction resolve(ResolutionContext c, Bindings b) {
126 ValueFunction x = arg.resolve(c,b);
127 return (new ConstraintFn(operators[op],x)).evaluationFn();
128 }
129
130
131 public ValueFunction duplicate(DuplicationTable table) {
132 return new ConstraintFn(operators[op],arg.duplicate(table));
133 }
134
135
136 public ValueFunction mirror() {
137 return new ConstraintFn(operators[op],arg.mirror());
138 }
139
140
141 ValueFunction normalize() {
142 ValueFunction a = arg.normalize();
143 switch(op) {
144 case LE:
145 case GE:
146 case LT:
147 case GT:
148 switch(a.getID()) {
149 case ID:
150 case LVAR:
151 case FIELD:
152 case ARITH:
153 case FUNC:
154 case INT:
155 case REAL:
156 case DATE:
157 case TIME:
158 case METH:
159 return new ConstraintFn(operators[op],a);
160
161 default:
162 throw new IllegalArgumentException("Illegal operand in \'" + this + "\'");
163 }
164
165 case UN:
166 case NE:
167 switch(a.getID()) {
168 case ID:
169 case TYPE:
170 case FIELD:
171 case FUNC:
172 case IMPLY:
173 case ELSE:
174 case LOR:
175 case LAND:
176 case COMP:
177 case BOOL:
178 case INT:
179 case REAL:
180 case DATE:
181 case TIME:
182 case ARITH:
183 case METH:
184 return new ConstraintFn(operators[op],a);
185
186 case LNOT:
187 return (ValueFunction)a.getArg();
188
189 case CONS:
190 switch(((ConstraintFn)a).getOperator()) {
191 case LE:
192 return new ConstraintFn(operators[GT],
193 (ValueFunction)a.getArg());
194 case GE:
195 return new ConstraintFn(operators[LT],
196 (ValueFunction)a.getArg());
197 case LT:
198 return new ConstraintFn(operators[GE],
199 (ValueFunction)a.getArg());
200 case GT:
201 return new ConstraintFn(operators[LE],
202 (ValueFunction)a.getArg());
203
204 case NE:
205 case UN:
206 return (ValueFunction)a.getArg();
207
208 default:
209 throw new IllegalArgumentException("Illegal operand in \'" + this + "\'");
210
211 }
212
213 case OR:
214 ValueFunction x = (ValueFunction)a.getArg(0);
215 ValueFunction y = (ValueFunction)a.getArg(1);
216 x = (new ConstraintFn(operators[NE],x)).normalize();
217 y = (new ConstraintFn(operators[NE],y)).normalize();
218 return new AndFn(x,y);
219 case AND:
220 return new ConstraintFn(operators[op],a);
221
222 case LVAR:
223 return new ConstraintFn(operators[op],a);
224
225 default:
226 throw new IllegalArgumentException("Illegal operand in \'" + this + "\'");
227
228 }
229
230 default:
231 throw new IllegalArgumentException("Illegal operand in \'" + this + "\'");
232
233 }
234 }
235
236
237 public boolean equals(Object any) {
238 if ( !(any instanceof ConstraintFn) ) return false;
239 ConstraintFn fn = (ConstraintFn)any;
240 return arg.equals(fn.getArg());
241 }
242
243
244 ValueFunction unify(ValueFunction fn, Bindings b) {
245
246 if ( !isDeterminate() || !fn.isDeterminate() )
247 return new AndFn(this,fn);
248
249 ValueFunction u = evaluationFn();
250 ValueFunction v = fn.evaluationFn();
251 int x = u.baseID();
252 int y = v.baseID();
253
254 if ( x == INT || x == REAL ) {
255 if ( y != INT && y != REAL )
256 throw new IllegalArgumentException("Illegal operand in \'" +
257 this + "\'");
258 }
259 else if ( x != y ) {
260 throw new IllegalArgumentException("Illegal operand in \'" +
261 this + "\'");
262 }
263
264 switch(op) {
265 case LE:
266 case GE:
267 case LT:
268 case GT:
269 switch(v.getID()) {
270 case ID:
271 case DATE:
272 case TIME:
273 case INT:
274 case REAL:
275 return compare((ConstraintFn)u,(PrimitiveFn)v);
276
277 case CONS:
278 return checkRange((ConstraintFn)u,(ConstraintFn)v);
279
280 default:
281 throw new IllegalArgumentException("Illegal operand in \'" +
282 this + "\'");
283 }
284
285 case UN:
286 case NE:
287 switch(v.getID()) {
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302 case ID:
303 case TYPE:
304 case AND:
305 case OR:
306 case DATE:
307 case TIME:
308 case BOOL:
309 case INT:
310 case REAL:
311 case VECT:
312 if (((ValueFunction)u.getArg()).unifiesWith(v,b) == null)
313 return v;
314 else
315 return null;
316
317 case CONS:
318 switch(((ConstraintFn)v).getOperator()) {
319 case UN:
320 case NE:
321 if ( u.equals(v) )
322 return u;
323 else
324 return new AndFn(u,v);
325
326 default:
327 return checkRange((ConstraintFn)u,(ConstraintFn)v);
328 }
329 }
330 break;
331
332 default:
333 throw new IllegalArgumentException("Illegal operand in \'" +
334 this + "\'");
335 }
336 return null;
337 }
338
339
340 public int baseID() {
341
342 return arg.baseID();
343 }
344
345
346
347 static ValueFunction compare(ConstraintFn a, PrimitiveFn b) {
348 PrimitiveFn x = (PrimitiveFn)a.getArg();
349 switch(a.getOperator()) {
350 case LE:
351
352 if ( b.less(x) || b.equals(x) )
353 return (ValueFunction)b;
354 else
355 return null;
356
357 case GE:
358
359 if ( x.less(b) || x.equals(b) )
360 return (ValueFunction)b;
361 else
362 return null;
363
364 case LT:
365
366 if ( b.less(x) )
367 return (ValueFunction)b;
368 else
369 return null;
370 case GT:
371
372 if ( x.less(b) )
373 return (ValueFunction)b;
374 else
375 return null;
376 default:
377
378 Assert.notNull(null);
379 return null;
380 }
381 }
382
383
384 static ValueFunction checkRange(ConstraintFn a, ConstraintFn b) {
385
386 if ( a.getOperator() > b.getOperator() )
387 return checkRange(b,a);
388
389 PrimitiveFn x = (PrimitiveFn) a.getArg();
390 PrimitiveFn y = (PrimitiveFn) b.getArg();
391
392 switch( a.getOperator() ) {
393 case LE:
394
395 switch( b.getOperator() ) {
396 case LE:
397 return ( x.less(y) ? a : b );
398
399 case LT:
400 if ( x.equals(y) )
401 return null;
402 else if ( x.less(y) )
403 return a;
404 else
405 return b;
406
407 case GE:
408 if ( x.equals(y) )
409 return (ValueFunction)x;
410 else if ( y.less(x) )
411 return new AndFn(a,b);
412 else
413 return null;
414
415 case GT:
416 if ( y.less(x) )
417 return new AndFn(a,b);
418 else
419 return null;
420
421 case UN:
422 case NE:
423 if ( x.equals(y) )
424 return new ConstraintFn(operators[LT],(ValueFunction)x);
425 else if ( x.less(y) )
426 return a;
427 else
428 return new AndFn(a,b);
429 }
430 break;
431
432 case LT:
433
434 switch( b.getOperator() ) {
435
436 case LT:
437 return ( x.less(y) ? a : b );
438
439 case GE:
440 case GT:
441 if ( y.less(x) )
442 return new AndFn(a,b);
443 else
444 return null;
445
446 case UN:
447 case NE:
448 if ( y.less(x) )
449 return new AndFn(a,b);
450 else
451 return a;
452 }
453 break;
454
455 case GE:
456
457 switch( b.getOperator() ) {
458
459
460 case GE:
461 return (x.less(y) ? (ValueFunction)y : (ValueFunction)x);
462
463 case GT:
464 if ( x.equals(y) )
465 return null;
466 else if ( x.less(y) )
467 return b;
468 else
469 return a;
470
471 case UN:
472 case NE:
473 if ( x.equals(y) )
474 return new ConstraintFn(operators[GT],(ValueFunction)x);
475 else if ( x.less(y) )
476 return new AndFn(a,b);
477 else
478 return a;
479 }
480 break;
481
482 case GT:
483
484 switch( b.getOperator() ) {
485
486
487
488 case GT:
489 return ( x.less(y) ? b : a );
490
491 case UN:
492 case NE:
493 if ( x.less(y) )
494 return new AndFn(a,b);
495 else
496 return a;
497 }
498 break;
499
500 case UN:
501 case NE:
502
503 switch( b.getOperator() ) {
504
505
506
507
508 case UN:
509 case NE:
510 return ( x.equals(y) ? (ValueFunction)a
511 : (ValueFunction)(new AndFn(a,b)) );
512 }
513 break;
514 }
515 Assert.notNull(null);
516 return null;
517 }
518
519 }