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  
25  package zeus.concepts.fn;
26  
27  import java.util.*;
28  import zeus.util.*;
29  import zeus.concepts.*;
30  
31  public class DefinedFn extends ValueFunction {
32     static final int ABS = 0;
33     static final int ACOS = 2;
34     static final int ASIN = 4;
35     static final int ATAN = 6;
36     static final int ATAN2 = 8;
37     static final int CEIL = 10;
38     static final int COS = 12;
39     static final int SIN = 14;
40     static final int TAN = 16;
41     static final int EXP = 18;
42     static final int FLOOR = 20;
43     static final int IEEE_REMAINDER = 22;
44     static final int LOG = 24;
45     static final int MAX = 26;
46     static final int MIN = 28;
47     static final int POW = 30;
48     static final int RANDOM = 32;
49     static final int RINT = 34;
50     static final int ROUND = 36;
51     static final int SQRT = 38;
52     static final int TO_DEGREES = 40;
53     static final int TO_RADIANS = 42;
54     static final int CONCAT = 44;
55     static final int NONVAR = 46;
56     static final int VAR = 48;
57  
58     static final String[] FUNCTIONS = {
59        "abs", "1",
60        "acos", "1",
61        "asin", "1",
62        "atan", "1",
63        "atan2", "2",
64        "ceil", "1",
65        "cos", "1",
66        "sin", "1",
67        "tan", "1",
68        "exp", "1",
69        "floor", "1",
70        "IEEEremainder", "2",
71        "log", "1",
72        "max", "2",
73        "min", "2",
74        "pow", "2",
75        "random", "0",
76        "rint", "1",
77        "round", "1",
78        "sqrt", "1",
79        "toDegrees", "1",
80        "toRadians", "1",
81        "concat", "2",
82        "nonvar", "1",
83        "var", "1"
84     };
85  
86     protected Object[] args = new Object[2];
87  
88     public DefinedFn(String lhs, Vector rhs) {
89        super(FUNC,3);
90        args[0] = lhs;
91        args[1] = rhs;
92  
93        int position = -1;
94        if ( (position = Misc.whichPosition(lhs,FUNCTIONS)) == -1 ||
95             ((position % 2) != 0) ) {
96           throw new IllegalArgumentException("Unknown function " + lhs +
97              " in expression.");
98        }
99  
100       int arity = Integer.parseInt(FUNCTIONS[position+1]);
101       if ( rhs == null || rhs.size() != arity ) {
102          throw new IllegalArgumentException(
103             "Wrong number of arguments used in function " +
104             lhs + "/" + arity + ".");
105       }
106    }
107    public ValueFunction mirror() {
108       Vector List = (Vector)args[1];
109       Vector otherList = new Vector();
110       ValueFunction fn;
111       for(int i = 0; i < List.size(); i++ ) {
112          fn = (ValueFunction)List.elementAt(i);
113          fn = fn.mirror();
114          otherList.addElement(fn);
115       }
116       return new DefinedFn((String)args[0],otherList);
117    }
118 
119    public String toString() {
120       String s = (String)args[0] + "(";
121       Vector List = (Vector)args[1];
122       ValueFunction fn;
123       for(int i = 0; i < List.size(); i++ ) {
124          fn = (ValueFunction)List.elementAt(i);
125          s += fn;
126          if ( i + 1 < List.size() )
127             s += ",";
128       }
129       s += ")";
130       return s;
131    }
132 
133    ValueFunction simplify() {
134       Vector List = (Vector)args[1];
135       Vector otherList = new Vector();
136       ValueFunction fn;
137       for(int i = 0; i < List.size(); i++ ) {
138          fn = (ValueFunction)List.elementAt(i);
139          fn = fn.simplify();
140          otherList.addElement(fn);
141       }
142       return new DefinedFn((String)args[0],otherList);
143    }
144    Object getArg(int position) {
145       return args[position];
146    }
147    public boolean references(ValueFunction var) {
148       Vector List = (Vector)args[1];
149       ValueFunction fn;
150       for(int i = 0; i < List.size(); i++ ) {
151          fn = (ValueFunction)List.elementAt(i);
152          if ( fn.references(var) )
153             return true;
154       }
155       return false;
156    }
157    public Vector variables() {
158       Vector List = (Vector)args[1];
159       Vector otherList = new Vector();
160       ValueFunction fn;
161       for(int i = 0; i < List.size(); i++ ) {
162          fn = (ValueFunction)List.elementAt(i);
163          otherList = Misc.union(otherList,fn.variables());
164       }
165       return otherList;
166    }
167    public boolean isDeterminate() {
168       Vector List = (Vector)args[1];
169       ValueFunction fn;
170       for(int i = 0; i < List.size(); i++ ) {
171          fn = (ValueFunction)List.elementAt(i);
172          if ( !fn.isDeterminate() ) return false;
173       }
174       return true;
175    }
176    ValueFunction normalize() {
177       Vector List = (Vector)args[1];
178       Vector otherList = new Vector();
179       ValueFunction fn;
180       for(int i = 0; i < List.size(); i++ ) {
181          fn = (ValueFunction)List.elementAt(i);
182          fn = fn.normalize();
183          otherList.addElement(fn);
184       }
185       return new DefinedFn((String)args[0],otherList);
186    }
187    public ValueFunction resolve(ResolutionContext c, Bindings b) {
188       Vector List = (Vector)args[1];
189       Vector otherList = new Vector();
190       ValueFunction fn;
191       for(int i = 0; i < List.size(); i++ ) {
192          fn = (ValueFunction)List.elementAt(i);
193          fn = fn.resolve(c,b);
194          otherList.addElement(fn);
195       }
196       return (new DefinedFn((String)args[0],otherList)).evaluationFn();
197    }
198 
199    public ValueFunction evaluationFn() {
200       if ( !args[0].equals("nonvar") && !args[0].equals("var") && !isDeterminate() ) return this;
201 
202       try {
203          PrimitiveNumericFn a, b;
204          IdFn c, d;
205          ValueFunction x;
206 
207          switch( Misc.whichPosition((String)args[0],FUNCTIONS) ) {
208             case ABS:
209                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
210                  switch( ((ValueFunction)a).getID() ) {
211                     case INT:
212                          return new IntFn(Math.abs(a.longValue()));
213                     case REAL:
214                          return new RealFn(Math.abs(a.doubleValue()));
215                  }
216                  break;
217 
218             case ACOS:
219                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
220                  return new RealFn(Math.acos(a.doubleValue()));
221 
222             case ASIN:
223                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
224                  return new RealFn(Math.asin(a.doubleValue()));
225 
226             case ATAN:
227                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
228                  return new RealFn(Math.atan(a.doubleValue()));
229 
230             case ATAN2:
231                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
232                  b = (PrimitiveNumericFn)((Vector)args[1]).elementAt(1);
233                  return new RealFn(Math.atan2(a.doubleValue(),b.doubleValue()));
234 
235             case CEIL:
236                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
237                  return new RealFn(Math.ceil(a.doubleValue()));
238 
239             case COS:
240                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
241                  return new RealFn(Math.cos(a.doubleValue()));
242 
243             case EXP:
244                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
245                  return new RealFn(Math.exp(a.doubleValue()));
246 
247             case FLOOR:
248                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
249                  return new RealFn(Math.floor(a.doubleValue()));
250 
251             case IEEE_REMAINDER:
252                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
253                  b = (PrimitiveNumericFn)((Vector)args[1]).elementAt(1);
254                  return new RealFn(Math.IEEEremainder(a.doubleValue(),b.doubleValue()));
255 
256             case LOG:
257                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
258                  return new RealFn(Math.log(a.doubleValue()));
259 
260             case MAX:
261                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
262                  b = (PrimitiveNumericFn)((Vector)args[1]).elementAt(1);
263                  if ( ((ValueFunction)a).getID() == INT && ((ValueFunction)b).getID() == INT )
264                     return new IntFn(Math.max(a.longValue(),b.longValue()));
265                  else
266                     return new RealFn(Math.max(a.doubleValue(),b.doubleValue()));
267 
268             case MIN:
269                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
270                  b = (PrimitiveNumericFn)((Vector)args[1]).elementAt(1);
271                  if ( ((ValueFunction)a).getID() == INT && ((ValueFunction)b).getID() == INT )
272                     return new IntFn(Math.min(a.longValue(),b.longValue()));
273                  else
274                     return new RealFn(Math.min(a.doubleValue(),b.doubleValue()));
275 
276             case POW:
277                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
278                  b = (PrimitiveNumericFn)((Vector)args[1]).elementAt(1);
279                  return new RealFn(Math.pow(a.doubleValue(),b.doubleValue()));
280 
281             case RANDOM:
282                  return new RealFn(Math.random());
283 
284             case RINT:
285                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
286                  return new RealFn(Math.rint(a.doubleValue()));
287 
288             case ROUND:
289                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
290                  return new IntFn(Math.round(a.doubleValue()));
291 
292             case SIN:
293                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
294                  return new RealFn(Math.sin(a.doubleValue()));
295 
296             case SQRT:
297                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
298                  return new RealFn(Math.sqrt(a.doubleValue()));
299 
300             case TAN:
301                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
302                  return new RealFn(Math.tan(a.doubleValue()));
303 
304             case TO_DEGREES:
305                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
306                  return new RealFn(Math.toDegrees(a.doubleValue()));
307 
308             case TO_RADIANS:
309                  a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
310                  return new RealFn(Math.toRadians(a.doubleValue()));
311 
312             case CONCAT:
313                  c = (IdFn)((Vector)args[1]).elementAt(0);
314                  d = (IdFn)((Vector)args[1]).elementAt(1);
315                  return new IdFn(c.getValue() + d.getValue());
316 
317             case NONVAR:
318                  x = (ValueFunction)((Vector)args[1]).elementAt(0);
319                  return BoolFn.newBoolFn(x.isDeterminate());
320 
321             case VAR:
322                  x = (ValueFunction)((Vector)args[1]).elementAt(0);
323                  return BoolFn.newBoolFn(!(x.isDeterminate()));
324 
325             default:
326                  throw new IllegalArgumentException(
327                     "Unknown function: \'" + args[0] + "\'");
328          }
329       }
330       catch(ClassCastException e) {
331          throw new IllegalArgumentException(
332             "Type mismatch in function \'" + this + "\'");
333       }
334       return null;
335    }
336 
337    public ValueFunction duplicate(DuplicationTable table) {
338       Vector List = (Vector)args[1];
339       Vector otherList = new Vector();
340       ValueFunction fn;
341       for(int i = 0; i < List.size(); i++ ) {
342          fn = (ValueFunction)List.elementAt(i);
343          fn = fn.duplicate(table);
344          otherList.addElement(fn);
345       }
346       return new DefinedFn((String)args[0],otherList);
347    }
348    public boolean equals(Object any) {
349       if ( !(any instanceof DefinedFn) ) return false;
350       DefinedFn fn = (DefinedFn)any;
351 
352       ValueFunction a = this.simplify();
353       ValueFunction b = fn.simplify();
354       return a.getArg(0).equals(b.getArg(0)) &&
355              Misc.sameVector((Vector)a.getArg(1),(Vector)b.getArg(1));
356 
357    }
358    ValueFunction unify(ValueFunction fn, Bindings b)  {
359       ValueFunction x = null;
360       if ( (x = evaluationFn()) == this )
361          return new AndFn(this,fn);
362       else
363          return x.unifiesWith(fn,b);
364    }
365 }