View Javadoc

1   /*
2   * The contents of this file are subject to the BT "ZEUS" Open Source 
3   * Licence (L77741), Version 1.0 (the "Licence"); you may not use this file 
4   * except in compliance with the Licence. You may obtain a copy of the Licence
5   * from $ZEUS_INSTALL/licence.html or alternatively from
6   * http://www.labs.bt.com/projects/agents/zeus/licence.htm
7   * 
8   * Except as stated in Clause 7 of the Licence, software distributed under the
9   * Licence is distributed WITHOUT WARRANTY OF ANY KIND, either express or 
10  * implied. See the Licence for the specific language governing rights and 
11  * limitations under the Licence.
12  * 
13  * The Original Code is within the package zeus.*.
14  * The Initial Developer of the Original Code is British Telecommunications
15  * public limited company, whose registered office is at 81 Newgate Street, 
16  * London, EC1A 7AJ, England. Portions created by British Telecommunications 
17  * public limited company are Copyright 1996-9. All Rights Reserved.
18  * 
19  * THIS NOTICE MUST BE INCLUDED ON ANY COPY OF THIS FILE
20  */
21  
22  
23  
24  package zeus.concepts.fn;
25  
26  import java.util.*;
27  import zeus.util.*;
28  import zeus.concepts.*;
29  
30  public class ComparisonFn extends LogicalFn {
31     static final int EQ = 0;
32     static final int NE = 1;
33     static final int LE = 2;
34     static final int GE = 3;
35     static final int LT = 4;
36     static final int GT = 5;
37  
38     static final String[] comparators = {
39        "==", "!=", "<=", ">=", "<", ">"
40     };
41  
42     final static int[] illegal_operands = {
43        AND, OR, ELSE, IMPLY
44     };
45  
46     protected ValueFunction[] args = new ValueFunction[2];
47     protected int op = -1;
48  
49     public ComparisonFn(ValueFunction lhs, ValueFunction rhs, String op) {
50        super(COMP,4);
51        if ( (this.op = Misc.whichPosition(op,comparators)) == -1) 
52           throw new IllegalArgumentException("Unknown operator in \'" +
53              lhs + " " + op + " " + rhs + "\'");
54        int ltype = lhs.getID();
55        int rtype = rhs.getID();
56        if ( Misc.member(ltype,illegal_operands) ||
57             Misc.member(rtype,illegal_operands) ) {
58            throw new IllegalArgumentException("Illegal operands in " +
59               " function \'" + lhs + " " + op + " " + rhs + "\'");
60        }      
61        if ( lhs.isDeterminate() && rhs.isDeterminate() ) {
62           if ( lhs instanceof LogicalFn ) {
63              if ( !(rhs instanceof LogicalFn) && !(rhs instanceof DefinedFn) )
64                 throw new IllegalArgumentException("Illegal operands in " +
65                    " function \'" + lhs + " " + op + " " + rhs + "\'");
66           }
67           else if ( lhs instanceof NumericFn ) {
68              if ( !(rhs instanceof NumericFn) && !(rhs instanceof DefinedFn) )
69                 throw new IllegalArgumentException("Illegal operands in " +
70                    " function \'" + lhs + " " + op + " " + rhs + "\'");
71           }
72           else if ( ltype != rtype ) {
73              throw new IllegalArgumentException("Illegal operands in " +
74                 " function \'" + lhs + " " + op + " " + rhs + "\'");
75           }
76        }
77  
78        args[0] = lhs;
79        args[1] = rhs;
80     }
81     
82     
83     public ValueFunction mirror() {
84        return new ComparisonFn(args[0].mirror(),args[1].mirror(),comparators[op]);
85     }
86  
87  
88     public String toString() {
89        return "(" + args[0] + " " + comparators[op] + " " + args[1] + ")";
90     }
91     
92     
93     int getOperator() {
94        return op;
95     }
96     
97     
98     ValueFunction simplify() {
99        ValueFunction a, b;
100       a = args[0].simplify();
101       b = args[1].simplify();
102       return (a != args[0] || b != args[1])
103              ? new ComparisonFn(a,b,comparators[op]) : this;
104    }
105    
106    
107    Object getArg(int position) {
108       return args[position];
109    }
110    
111    
112    public boolean references(ValueFunction var) {
113       return args[0].references(var) || args[1].references(var);
114    }
115    
116    
117    public Vector variables() {
118       return Misc.union(args[0].variables(),args[1].variables());
119    }
120    
121    
122    public boolean isDeterminate() {
123     
124       return args[0].isDeterminate() && args[1].isDeterminate();
125    }
126    
127    
128    public ValueFunction resolve(ResolutionContext c, Bindings b) {
129       ValueFunction x = args[0].resolve(c,b);
130       ValueFunction y = args[1].resolve(c,b);
131       return (new ComparisonFn(x,y,comparators[op])).evaluationFn();
132    }
133    
134    
135    ValueFunction normalize() {
136       ValueFunction a, b;
137       a = args[0].normalize();
138       b = args[1].normalize();
139       return (a != args[0] || b != args[1] )
140              ? new ComparisonFn(a,b,comparators[op]) : this;
141    }
142 
143 
144    public int evaluate() {
145       ValueFunction fn = evaluationFn();
146       if ( fn == this ) return UNKNOWN;
147       else if ( fn == BoolFn.trueFn ) return TRUE;
148       else return FALSE;
149    }
150 
151 
152    public ValueFunction evaluationFn() {
153       if ( !isDeterminate() ) return this;
154 
155       ValueFunction a, b;
156       a = args[0];
157       b = args[1];
158 
159       if ( a instanceof LogicalFn )
160          a = ((LogicalFn)a).evaluationFn();
161       else if ( a instanceof ArithmeticFn)
162          a = ((ArithmeticFn)a).evaluationFn();
163 
164       if ( b instanceof LogicalFn )
165          b = ((LogicalFn)b).evaluationFn();
166       else if ( b instanceof ArithmeticFn)
167          b = ((ArithmeticFn)b).evaluationFn();
168 
169       if ( !(a instanceof PrimitiveFn) || !(b instanceof PrimitiveFn) )
170          throw new IllegalArgumentException(this.toString());
171 
172       PrimitiveFn x = (PrimitiveFn)a;
173       PrimitiveFn y = (PrimitiveFn)b;
174 
175       int xid = a.getID();
176       int yid = b.getID();
177 
178       if ( xid != yid ) {
179          if ( xid == INT  && yid == REAL )
180             ; // do-nothing
181          else if ( xid == REAL && yid == INT )
182             ; // do-nothing
183          else {
184             throw new IllegalArgumentException(this.toString());
185          }
186       }
187 
188 
189       switch( op ) {
190          case EQ:
191               return x.equals(y)
192                      ? BoolFn.trueFn : BoolFn.falseFn;
193          case LE:
194               return ( x.less(y) || x.equals(y) ) 
195                      ? BoolFn.trueFn : BoolFn.falseFn;
196 
197          case GE:
198               return !x.less(y)
199                      ? BoolFn.trueFn : BoolFn.falseFn;
200 
201          case NE:
202               return !x.equals(y)
203                      ? BoolFn.trueFn : BoolFn.falseFn;
204 
205          case GT:
206               return ( !x.less(y) && !x.equals(y) )
207                      ? BoolFn.trueFn : BoolFn.falseFn;
208               
209          case LT:
210               return x.less(y)
211                      ? BoolFn.trueFn : BoolFn.falseFn;
212  
213          default:
214               throw new IllegalArgumentException("Unknown operator in \'" +
215                  this + "\'");
216       }
217    }
218 
219    public ValueFunction duplicate(DuplicationTable table) {
220       return new ComparisonFn(args[0].duplicate(table),args[1].duplicate(table),
221                               comparators[op]);
222    }
223    public boolean equals(Object any) {
224       if ( !(any instanceof ComparisonFn) ) return false;
225       ComparisonFn fn = (ComparisonFn)any;
226       if ( op != fn.getOperator() ) return false;
227 
228       ValueFunction a = this.simplify();
229       ValueFunction b = fn.simplify();
230       return ((ValueFunction)a.getArg(0)).equals((ValueFunction)b.getArg(0)) &&
231              ((ValueFunction)a.getArg(1)).equals((ValueFunction)b.getArg(1));
232    }
233 }