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 ElseFn extends ValueFunction {
31     protected ValueFunction[] args = new ValueFunction[3];
32  
33     public ElseFn(ValueFunction lhsArg, ValueFunction rhsArg) {
34        super(ELSE,2);
35        if  ( !(lhsArg instanceof ImplyFn) )
36           throw new IllegalArgumentException("Illegal operand in \'" +
37              lhsArg + " else " + rhsArg + "\'");
38  
39        args[0] = (ValueFunction)lhsArg.getArg(0);
40        args[1] = (ValueFunction)lhsArg.getArg(1);
41        args[2] = rhsArg;
42     }
43     
44     
45     public ElseFn(ValueFunction arg0, ValueFunction arg1, ValueFunction arg2) {
46        super(ELSE,2);
47        if  ( !(arg0 instanceof LogicalFn) )
48           throw new IllegalArgumentException("Illegal operand \'" + arg0 +
49              " in \' + (if " + args[0] + " then " + args[1] + " else " +
50              args[2] + ")\'");
51        args[0] = arg0;
52        args[1] = arg1;
53        args[2] = arg2;
54     }
55  
56  
57      /*** 
58          *resolve is here to handle unification for the postcondition to precondition maps - 
59          *this will allow proper use of expressions when defining tasks. 
60          *@since 1.2.1
61          *@author Simon Thompson
62          */
63     public void resolve (String attrName, ValueFunction val) {
64      debug ("in resolve"); 
65      // recurse over lhs if this is a compound expression 
66      if (args[0] instanceof ArithmeticFn) {
67          debug ("recursing args[0]"); 
68          ArithmeticFn lhsFn = (ArithmeticFn) args[0];
69          lhsFn.resolve (attrName,val); 
70      }
71      // resolve when find a tangible
72      else if (args[0] instanceof VarFn) { 
73          debug ("resolving args[0]"); 
74          debug (" args[0] = " + args[0].toString() + " val = " +val.toString() +" attrName = " + attrName); 
75          if (args[0].toString().equals("?"+attrName)) {             
76              args[0] = val; }
77          debug (" args[0] = " + args[0].toString() + " val = " +val.toString() +" attrName = " + attrName); 
78      }
79      //recurse over rhs if this is a compound expression 
80     if (args[1] instanceof ArithmeticFn) {
81          debug ("recursing args[1]"); 
82          ArithmeticFn thenFn = (ArithmeticFn) args[1];
83          thenFn.resolve (attrName,val); 
84      }
85      // resolve when find a tangible
86      else if (args[1] instanceof VarFn) { 
87          debug ("resolving args[1]"); 
88          debug (" args[1] = " + args[1].toString() + " val = " +val.toString() +" attrName = " + attrName); 
89          if (args[1].toString().equals("?"+attrName)) {             
90              args[1] = val; }
91          debug (" args[1] = " + args[1].toString() + " val = " +val.toString() +" attrName = " + attrName); 
92      }
93     
94      if (args[2] instanceof ArithmeticFn) {
95          debug ("recursing args[2"); 
96          ArithmeticFn elseFn = (ArithmeticFn) args[2];
97          elseFn.resolve (attrName,val); 
98      }
99      // resolve when find a tangible
100     else if (args[2] instanceof VarFn) { 
101         debug ("resolving args[2]"); 
102         debug (" args[2] = " + args[2].toString() + " val = " +val.toString() +" attrName = " + attrName); 
103         if (args[2].toString().equals("?"+attrName)) {             
104             args[2] = val; }
105         debug (" args[2] = " + args[2].toString() + " val = " +val.toString() +" attrName = " + attrName); 
106     }
107 }
108 
109 
110    public String toString() {
111       return "(if " + args[0] + " then " + args[1] + " else " + args[2] + ")";
112    }
113    
114    
115    ValueFunction simplify() {
116       ValueFunction a, b, c;
117       a = args[0].simplify();
118       b = args[1].simplify();
119       c = args[2].simplify();
120       return (a != args[0] || b != args[1] || c != args[2] )
121              ? new ElseFn(a,b,c) : this;
122    }
123 
124    
125    Object getArg(int position) {
126       return args[position];
127    }
128 
129    
130    public boolean references(ValueFunction var) {
131       return args[0].references(var) || args[1].references(var) ||
132              args[2].references(var);
133    }
134    
135    
136    public Vector variables() {
137       Vector temp = Misc.union(args[0].variables(),args[1].variables());
138       return Misc.union(temp,args[2].variables());
139    }
140    
141    
142    public boolean isDeterminate() {
143       return args[0].isDeterminate() && args[1].isDeterminate() &&
144              args[2].isDeterminate();
145    }
146    
147    
148    ValueFunction normalize() {
149       ValueFunction a, b, c;
150       a = args[0].normalize();
151       b = args[1].normalize();
152       c = args[2].normalize();
153       return (a != args[0] || b != args[1] || c != args[2] )
154              ? new ElseFn(a,b,c) : this;
155    }
156    
157    
158    public ValueFunction mirror() {
159       return new ElseFn(args[0].mirror(),args[1].mirror(),args[2].mirror());
160    }
161   
162    
163    public ValueFunction resolve(ResolutionContext c, Bindings b) {
164       ValueFunction x = args[0].resolve(c,b);
165       switch( ((LogicalFn)x).evaluate() ) {
166          case LogicalFn.TRUE:
167               return args[1].resolve(c,b);
168          case LogicalFn.FALSE:
169               return args[2].resolve(c,b);
170          case LogicalFn.UNKNOWN:
171               if ( x.equals(args[0]) ) 
172                  return this;
173               else
174                  return new ElseFn(x,args[1],args[2]);
175       }
176       return null;
177    }
178    
179    
180    public ValueFunction evaluationFn() {
181       debug (args[0].getClass().toString()); 
182       switch( ((LogicalFn)args[0]).evaluate() ) {
183          case LogicalFn.TRUE:
184               return args[1];
185          case LogicalFn.FALSE:
186               return args[2];
187          case LogicalFn.UNKNOWN:
188               return this;
189       }
190       return this;
191    }
192    
193    
194    public ValueFunction duplicate(DuplicationTable table) {
195       return new ElseFn(args[0].duplicate(table),args[1].duplicate(table),
196                         args[2].duplicate(table));
197    }
198    
199    
200    public boolean equals(Object any) {
201       if ( !(any instanceof ElseFn) ) return false;
202       ElseFn fn = (ElseFn)any;
203       ValueFunction a = this.simplify();
204       ValueFunction b = fn.simplify();
205       return ((ValueFunction)a.getArg(0)).equals((ValueFunction)b.getArg(0)) &&
206              ((ValueFunction)a.getArg(1)).equals((ValueFunction)b.getArg(1)) &&
207              ((ValueFunction)a.getArg(2)).equals((ValueFunction)b.getArg(2));
208    }
209  
210    
211    ValueFunction unify(ValueFunction fn, Bindings b) {
212       ValueFunction x = null, y = null;
213 
214       if ( (x = evaluationFn()) == null )
215          return null;
216       else if ( x != this )
217          return x.unifiesWith(fn,b);
218 
219       switch( fn.getID() ) {
220          case IMPLY:
221               if ( (y = ((ImplyFn)fn).evaluationFn()) == null )
222                  return null;
223               else if ( y != fn )
224                  return this.unifiesWith(y,b);
225 
226               x = args[1].unifiesWith(fn,b);
227               y = args[2].unifiesWith(fn,b);
228 
229               if ( x == null && y == null )
230                  return null;
231               else if ( y == null )
232                  return new ImplyFn(args[0],x);
233               else if ( x == null )
234                  return new ImplyFn(new LogicalNotFn(args[0]),y);
235               else
236                  return new ElseFn(args[0],x,y);
237 
238          case ELSE:
239               if ( (y = ((ElseFn)fn).evaluationFn()) == null )
240                  return null;
241               else if ( y != fn )
242                  return this.unifiesWith(y,b);
243 
244               x = args[1].unifiesWith(fn,b);
245               y = args[2].unifiesWith(fn,b);
246 
247               if ( x == null && y == null )
248                  return null;
249               else if ( y == null )
250                  return new ImplyFn(args[0],x);
251               else if ( x == null ) 
252                  return new ImplyFn(new LogicalNotFn(args[0]),y);
253               else
254                  return new ElseFn(args[0],x,y);
255 
256          default:
257               x = args[1].unifiesWith(fn,b);
258               y = args[2].unifiesWith(fn,b);
259               if ( x == null && y == null )
260                  return null;
261               else if ( y == null )
262                  return new ImplyFn(args[0],x);
263               else if ( x == null )
264                  return new ImplyFn(new LogicalNotFn(args[0]),y);
265               else
266                  return new ElseFn(args[0],x,y);
267       }      
268    }
269 
270    
271    public int baseID() {
272       // must be called when Fn is known to be determinate
273       int x = args[1].baseID();
274       int y = args[2].baseID();
275       // perform type checking
276       if ( x != y )
277          throw new IllegalArgumentException("Incompatible types in " + this);
278       return x;
279    }
280    
281    
282    public void debug (String str) { 
283     //System.out.println("ArithmeticFn>>"+str);
284    }
285 
286 }