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  /*** 
32      ArithmeticFn is used to store arthimetic over some condition 
33      - made some alterations for 1.2.1  so that the precondition unification 
34      bugs could be properly sorted (well, for the time being at least!) 
35          Si.
36     */
37  public class ArithmeticFn extends ValueFunction implements NumericFn {
38     public static final int PLUS = 0;
39     public static final int MINUS = 1;
40     public static final int TIMES = 2;
41     public static final int DIVIDE = 3;
42     public static final int REM = 4;
43     public static final String[] operators = {
44        "+", "-", "*", "/", "%" };
45  
46     public final static String[] legal_operands = {
47        "zeus.concepts.fn.MethodCallFn",
48        "zeus.concepts.fn.DefinedFn",
49        "zeus.concepts.fn.ArithmeticFn",
50        "zeus.concepts.fn.IntFn",
51        "zeus.concepts.fn.RealFn",
52        "zeus.concepts.fn.VarFn",
53        "zeus.concepts.fn.FieldFn",
54        "zeus.concepts.fn.ElseFn"
55     };
56     public final static String[] legal_unifiers = {
57        "zeus.concepts.fn.MethodCallFn",
58        "zeus.concepts.fn.DefinedFn",
59        "zeus.concepts.fn.ArithmeticFn",
60        "zeus.concepts.fn.IntFn",
61        "zeus.concepts.fn.RealFn",
62        "zeus.concepts.fn.VarFn",
63        "zeus.concepts.fn.FieldFn",
64  
65        "zeus.concepts.fn.AndFn",
66        "zeus.concepts.fn.OrFn",
67        "zeus.concepts.fn.NotFn",
68        "zeus.concepts.fn.ImplyFn",
69        "zeus.concepts.fn.ElseFn"
70     };
71  
72  
73     protected ValueFunction[] args = new ValueFunction[2];
74     protected int op = -1;
75  
76  
77      /*** 
78          *resolve is here to handle unification for the postcondition to precondition maps - 
79          *this will allow proper use of expressions when defining tasks. 
80          *@since 1.2.1
81          *@author Simon Thompson
82          */
83     public void resolve (String attrName, ValueFunction val) { 
84      ValueFunction lhs = args[0]; 
85      ValueFunction rhs = args[1]; 
86      debug ("in resolve"); 
87      // recurse over lhs if this is a compound expression 
88      if (lhs instanceof ArithmeticFn) {
89          debug ("recursing lhs"); 
90          ArithmeticFn lhsFn = (ArithmeticFn) lhs;
91          lhsFn.resolve (attrName,val); 
92      }
93      // resolve when find a tangible
94      else if (lhs instanceof VarFn) { 
95          debug ("resolving lhs"); 
96          debug (" lhs = " + lhs.toString() + " val = " +val.toString() +" attrName = " + attrName); 
97          if (lhs.toString().equals("?"+attrName)) {             
98              lhs = val;
99              args[0] = lhs; }
100         debug (" lhs = " + lhs.toString() + " val = " +val.toString() +" attrName = " + attrName); 
101     }
102     //recurse over rhs if this is a compound expression 
103     if (rhs instanceof ArithmeticFn) { 
104         debug ("recursing rhs"); 
105         ArithmeticFn rhsFn = (ArithmeticFn) rhs; 
106         rhsFn.resolve (attrName,val); 
107     }    
108     // resolve when find rhs tangible.
109     else if (rhs instanceof VarFn) { 
110        debug ("resolving rhs"); 
111        if (rhs.toString().equals("?"+attrName)){
112               rhs = val;
113               args[1] = rhs; 
114        }
115     }
116    }
117    
118 
119    public ArithmeticFn(ValueFunction lhs, ValueFunction rhs, String op) {
120       super(ARITH,3);
121       args[0] = lhs;
122       args[1] = rhs;
123 
124       if ( (this.op = Misc.whichPosition(op,operators)) == -1 )
125          throw new IllegalArgumentException("Illegal operator " + 
126             " in arithmetic function \'" + lhs + op + rhs + "\'");
127 
128       String lname = lhs.getClass().getName();
129       String rname = rhs.getClass().getName();
130       if ( !Misc.member(lname,legal_operands) ||
131            !Misc.member(rname,legal_operands) )
132          throw new IllegalArgumentException("Illegal operands "  +
133             " in arithmetic function \'" + lhs + op + rhs + "\'");
134    }
135    
136    
137    public ValueFunction getLHS () { 
138     return args[0]; 
139    }
140    
141    public ValueFunction getRHS () { 
142     return args[1]; 
143    }
144    
145    
146   
147    
148    public ValueFunction mirror() {
149       return new ArithmeticFn(args[0].mirror(),args[1].mirror(),operators[op]);
150    }
151 
152    public String toString() {
153       return "(" + args[0] + " " + operators[op] + " " + args[1] + ")";
154    }
155    
156    public int getOperator() {
157       return op;
158    }
159    
160    
161    ValueFunction simplify() {
162       ValueFunction a, b;
163       a = args[0].simplify();
164       b = args[1].simplify();
165       return (a != args[0] || b != args[1])
166              ? new ArithmeticFn(a,b,operators[op]) : this;
167    }
168    
169    Object getArg(int position) {
170       return args[position];
171    }
172   
173    
174   
175    
176    public boolean references(ValueFunction var) {
177       return args[0].references(var) || args[1].references(var);
178    }
179    
180    
181    public Vector variables() {
182       return Misc.union(args[0].variables(),args[1].variables());
183    }
184    
185    public boolean isDeterminate() {
186       return args[0].isDeterminate() && args[1].isDeterminate();
187    }
188    
189    
190    ValueFunction normalize() {
191       ValueFunction a, b;
192       a = args[0].normalize();
193       b = args[1].normalize();
194       return (a != args[0] || b != args[1] )
195              ? new ArithmeticFn(a,b,operators[op]) : this;
196    }
197    
198    
199    public ValueFunction resolve(ResolutionContext c, Bindings b) {
200       ValueFunction x = args[0].resolve(c,b);
201       ValueFunction y = args[1].resolve(c,b);
202       return (new ArithmeticFn(x,y,operators[op])).evaluationFn();
203    }
204 
205 
206    public ValueFunction evaluationFn() {
207       if ( !isDeterminate() ) return this;
208       ValueFunction a, b;
209       double x = 0, y = 0, z = 0;
210       int left_type = REAL;
211       int right_type = REAL;
212       int return_type = REAL;
213       try {
214          a = args[0].evaluationFn();
215          b = args[1].evaluationFn();
216 
217          if ( a instanceof IntFn ) {
218             x = (double) ((IntFn)a).getValue();
219             left_type = INT;
220          }
221          else
222             x = ((RealFn)a).getValue();
223 
224          if ( b instanceof IntFn ) {
225             y = (double) ((IntFn)b).getValue();
226             right_type = INT;
227          }
228          else
229             y = ((RealFn)b).getValue();
230        
231          if ( left_type == REAL || right_type == REAL )
232             return_type = REAL;
233          else
234             return_type = INT;
235       }
236       catch(Exception e) {
237          throw new IllegalArgumentException("Unknown operand type in " +
238             " arithmetic function \'" + this + "\'");
239       }
240 
241       switch( op ) {
242          case PLUS:
243               z = x+y;
244               break;
245          case MINUS:
246               z = x-y;
247               break; 
248          case TIMES:
249               z = x*y;
250               break;
251          case DIVIDE:
252               z = x/y;
253               break;
254          case REM:
255               z = (double) (((int)x) % ((int)y));
256               break;              
257          default:
258               throw new IllegalArgumentException("Unknown operator in " +
259                  " arithmetic function \'" + this + "\'");
260       }
261       if (op == REM || return_type == INT ) 
262          return new IntFn((int)z);
263       else
264          return new RealFn(z);
265    }
266 
267 
268    public ValueFunction duplicate(DuplicationTable table) {
269       return new ArithmeticFn(args[0].duplicate(table),args[1].duplicate(table),
270                               operators[op]);
271    }
272    
273    
274    public boolean equals(Object any) {
275       if ( !(any instanceof ArithmeticFn) ) return false;
276       ArithmeticFn fn = (ArithmeticFn)any;
277 
278       if ( op != ((ArithmeticFn)fn).getOperator() ) return false;
279 
280       ValueFunction a = this.simplify();
281       ValueFunction b = fn.simplify();
282       return ((ValueFunction)a.getArg(0)).equals((ValueFunction)b.getArg(0)) &&
283              ((ValueFunction)a.getArg(1)).equals((ValueFunction)b.getArg(1));
284    }
285    
286    
287    ValueFunction unify(ValueFunction fn, Bindings b)  {
288       String name = fn.getClass().getName();
289       if ( !Misc.member(name,legal_unifiers) ) {
290          throw new IllegalArgumentException("Illegal unification attempted: " +
291             this + " and " + fn );
292       }      
293 
294       ValueFunction x = null;
295 
296       if ( (x = evaluationFn()) == this )
297          return new AndFn(this,fn);
298       else
299          return x.unifiesWith(fn,b);
300    }
301    
302    
303    public void debug (String str) { 
304    // System.out.println("ArithmeticFn>>"+str);
305    }
306 
307 
308 }