View Javadoc
1   package eu.simuline.relana.model;
2   
3   import eu.simuline.relana.expressions.Formula;
4   import eu.simuline.relana.expressions.Operation;
5   //import eu.simuline.relana.expressions.Operation;
6   //import eu.simuline.relana.expressions.Type;
7   
8   import java.math.BigDecimal;
9   
10  import java.util.Set;
11  import java.util.HashSet;
12  import java.util.Map;
13  //import java.util.HashMap;
14  import java.util.TreeMap;
15  import java.util.Iterator;
16  import java.util.List;
17  //import java.util.ArrayList;
18  import java.util.Comparator;
19  
20  
21  /**
22   * Instance of Component. 
23   *
24   *
25   * Created: Thu Apr 14 23:02:05 2005
26   *
27   * @author <a href="mailto:ernst.reissner@simuline.eu">Ernst Reissner</a>
28   * @version 1.0
29   */
30  public final class FlatCInstance {
31  
32      /* -------------------------------------------------------------------- *
33       * constants.                                                           *
34       * -------------------------------------------------------------------- */
35  
36      static final Comparator<List<String>> PATH_CMP = 
37      new Comparator<List<String>>() {
38  	    public int compare(List<String> list1, List<String> list2) {
39  		for (int i = 0; i < Math.min(list1.size(), list2.size()); i++) {
40  		    int res = list1.get(i).compareTo(list2.get(i));
41  		    if (res != 0) {
42  			return res;
43  		    }
44  		}
45  
46  		return list1.size() - list2.size();
47  	    }
48  	};
49  
50      /* -------------------------------------------------------------------- *
51       * attributes.                                                          *
52       * -------------------------------------------------------------------- */
53  
54      /**
55       * Maps the names of the effects to their instances. 
56       */
57      private final Map<List<String>, SInstance> effects;
58  
59      /* -------------------------------------------------------------------- *
60       * constructors.                                                        *
61       * -------------------------------------------------------------------- */
62  
63      public FlatCInstance(Map<List<String>, SInstance> effects) {
64  	this.effects = effects;
65      } // FlatCInstance constructor
66  
67      /* -------------------------------------------------------------------- *
68       * methods.                                                             *
69       * -------------------------------------------------------------------- */
70  
71      Map<List<String>, SInstance> getEffects() {
72  	return this.effects;
73      }
74  
75      public SInstance getEffect(InstanceLocator loc) {
76  	return getEffect(loc.getPath());
77      }
78  
79      public SInstance getEffect(List<String> path) {
80  	return this.effects.get(path);
81      }
82  
83  
84      /**
85       * Returns the <code>FlatCInstance</code> arising from this one 
86       * by assuming that <code>def</code> does not occur 
87       * within <code>serv</code>. 
88       *
89       * @param serv 
90       *    a <code>SInstance</code> with probability distribution. 
91       *    <code>serv.distr != null</code>. 
92       * @param def 
93       *    a <code>Deficiency</code> 
94       *    minimal within the type of <code>serv</code>. 
95       *    **** is this unique or not? **** 
96       * @return 
97       *    a <code>FlatCInstance</code> arising from this one by assuming 
98       *    that <code>def</code> does not occur within <code>serv</code>. 
99       */
100     public FlatCInstance remove(SInstance serv, Deficiency def) {
101 	SInstance newServ = serv.remove(def);
102 	if (newServ == null) {
103 	    // remove would cause empty set. 
104 	    return substitute(serv, Formula.EMPTY_EXPRESSION);
105 	}
106 
107 	Formula newVar = new Formula.Var(newServ, serv.getName());
108 	return substitute(serv, newVar);
109     }
110 
111     /**
112      * Returns the <code>FlatCInstance</code> arising from this one 
113      * by assuming that <code>def</code> occurs within <code>serv</code>. 
114      *
115      * @param serv 
116      *    a <code>SInstance</code> with probability distribution. 
117      *    <code>serv.distr != null</code>. 
118      * @param def 
119      *    a <code>Deficiency</code> 
120      *    minimal within the type of <code>serv</code>. 
121      *    **** is this unique or not? **** 
122      * @return 
123      *    a <code>FlatCInstance</code> arising from this one 
124      *    by assuming that <code>def</code> occurs within <code>serv</code>. 
125      */
126     public FlatCInstance add(SInstance serv, Deficiency def) {
127 	
128 	// create the set {def} with type serv.getType() 
129 	// This works, because def is minimal within serv.getType() 
130 	Set<Deficiency> defSet = 
131 	    new HashSet<Deficiency>();
132 	defSet.add(def);
133 	Formula newConst = new Formula.Const(defSet, serv.getType());
134 	assert serv.getType().isValid(defSet);
135 
136 	if (serv.getType().asSet().size() == 1) {
137 	    // def is the only remaining effect 
138 	    // and removing it implies removing the whole effect. 
139 	    return substitute(serv, newConst);
140 	}
141 	// Here, serv may assume more than one non-empty set. 
142 
143 	// replace formula "serv" by formula "|({def}, newServ)", 
144 	// where newServ evolves out of serv by changing the type: 
145 	// removing def and all deficiencies above. 
146 
147 	// newServ is the effect that occurs by REMOVING def 
148 	SInstance newServ = serv.add(def);
149 	Formula newVar = new Formula.Var(newServ, serv.getName());
150 	Set<Formula> args = new HashSet<Formula>();
151 	args.add(newConst);
152 	args.add(newVar);
153 	Formula newComp = Formula.
154 	    getFormula(Operation.getOperation(Operation.BaseOps.Union)
155 		       .getEval(null), args);
156 	
157 	return substitute(serv, newComp);
158     }
159 
160     /**
161      * Returns the <code>FlatCInstance</code> arising from this one 
162      * by substituting <code>serv</code> by <code>form</code> in all effects. 
163      *
164      * @param serv 
165      *    a <code>SInstance</code>. 
166      * @param form 
167      *    a <code>Formula</code> of appropriate type. 
168      *    **** 
169      * @return 
170      *    a <code>FlatCInstance</code> arising from this one 
171      *    by substituting <code>serv</code> by <code>form</code> 
172      *    in all effects using {@link SInstance#substitute}. 
173      */
174     FlatCInstance substitute(SInstance serv, Formula form) {
175 	Map<List<String>, SInstance> effects = 
176 	    new TreeMap<List<String>, SInstance>(PATH_CMP);
177 	for (Map.Entry<List<String>, SInstance> entry 
178 		 : this.effects.entrySet()) {
179 	    effects.put(entry.getKey(),
180 			 entry.getValue().substitute(serv, form));
181 	}
182 	
183 	return new FlatCInstance(effects);
184     }
185 
186     /**
187      * A container comprising an {@link SInstance} 
188      * and of one of its minimal {@link Deficiency}s. 
189      * This is needed for probability computations: 
190      * The variable of the {@link SInstance} is replaced by another one, 
191      * eliminating the given {@link Deficiency}. 
192      */
193     private static class InstDef {
194 	private final SInstance serv;
195 	private final Deficiency def;
196 	InstDef(SInstance serv, Deficiency def) {
197 	    this.serv = serv;
198 	    this.def = def;
199 	}
200     } // class InstDef 
201 
202     /**
203      * Maps the given effect which is given by a formula, 
204      * onto an {@link InstDef} 
205      * consisting of a variable with probability distribution 
206      * occuring in the formula and its minimal deficiency. 
207      * If no such variable exists, the variables within the formula 
208      * (which are then all associated with formulae) 
209      * are substituted within the root formula, 
210      * by their associated formulae. 
211      *
212      * @param serv 
213      *    an <code>SInstance</code> given by a formula. 
214      *    **** what if no formula is present? **** 
215      * @return 
216      *    an <code>InstDef</code> 
217      *    consisting of a variable occuring in the formula 
218      *    and its minimal deficiency. 
219      *    If this does not exist, <code>null</code> is returned. 
220      */
221     private InstDef instDefic(SInstance serv) {
222 //System.out.println("+serv: "+serv);
223 
224 	Formula form = serv.getFormula();
225 	assert form != null;
226 // **** no good: impossible to handle effects with distr given directly
227 	Set<SInstance> vars;
228 
229 	// in each loop variables with probability distributions are searched 
230 	// and if none are present, another variable is substituted 
231 	// by its formula. 
232 	// This may yield new aspects, unless alll effects are substituted. 
233 	// ***** the current algorithm which is NOT PERFORMANT **** 
234 	// loops up to <code>this.effects.keySet().size()</code> times. 
235 	for (int ind = 0; ind < this.effects.keySet().size(); ind++) {
236 	    vars = form.getVars();
237 //System.out.println("form: " + form);
238 //System.out.println("vars: " + vars);
239 	    // look for variables with probability distribution 
240 	    // and essentially return the first found. 
241 	    for (SInstance var: vars) {
242 		if (var.getDistr() != null) {
243 		    // Here, found variable var within formula form with distr. 
244 		    //System.out.println("var: "+var);
245 		    //System.out.println("var: "+var.getType());
246 
247 		    Set<Deficiency> minDefs = var.getType().getMin();
248 		    assert !minDefs.isEmpty();
249 		    Iterator<Deficiency> iter = minDefs.iterator();
250 		    //System.out.println("+form: "+form);
251 		    return new InstDef(var, iter.next());
252 		}
253 	    }
254 	    // found no variables with probability distribution. 
255 
256 	    // substitute all variables within form 
257 	    // (which are all associated with a formula) with their formulae 
258 	    Formula varForm;
259 	    for (SInstance var: vars) {
260 		varForm = var.getFormula();
261 		form = form.substitute(var, varForm);
262 	    }
263 	    serv.setFormula(form);
264 	}
265 	// Here, it is sure that form 
266 	// has no variables with probability distribution 
267 	// even if other variables are substituted recursively. 
268 	return null;
269     }
270 
271     /**
272      * Returns the probability 
273      * that the effect specified by <code>sPath</code> 
274      * is not the empty set. 
275      * It is intended to be applied primarily to Boolean effects, 
276      * i.e. to effects isomorphic to Boolean ones, 
277      * i.e. to one-point effects. 
278      * Then this method returns the probability for <code>true</code>. 
279      *
280      * @param sPath
281      *    identifies a effect. 
282      * @return 
283      *    the probability described above as a <code>BigDecimal</code> value. 
284      */
285     public BigDecimal getProb(List<String> sPath) {
286 	SInstance serv = getEffect(sPath);
287 	// Fetch a effect instance inst within the formula attached with serv 
288 	// such that s is associated with a probability distribution 
289 	// with a certain deficiency def. 
290 	// Then instDef comprises both, inst and def. 
291 	InstDef instDef = instDefic(serv);
292 	if (instDef == null) {
293 	    // the formula attached with serv is constant 
294 	    // (at least after substitution done by instDefic) 
295 	    Set<Deficiency> defs = serv.getFormula().getConst();
296 	    assert defs != null; // i.e. serv.getFormula() is a constant. 
297 	    return defs.isEmpty() ? BigDecimal.ZERO : BigDecimal.ONE;
298 	}
299 	// Here, instDef != null 
300 
301 	// cond is the probability that instDef.def occurs. 
302 	BigDecimal cond = instDef.serv.getDistr().getProb(instDef.def);
303 
304 	// create copies of this FlatCInstance 
305 	// by assuming that def occurs within serv 
306 	// and that it does not occur, respectively. 
307 	FlatCInstance cInstP = add   (instDef.serv, instDef.def);
308 	FlatCInstance cInstM = remove(instDef.serv, instDef.def);
309 //System.out.println("cInstP: " + cInstP);
310 //System.out.println("cInstM: " + cInstM);
311 //System.out.println("this: " + this);
312 //throw new IllegalStateException();
313 
314 	return                           cond .multiply(cInstP.getProb(sPath))
315 	    .add(BigDecimal.ONE.subtract(cond).multiply(cInstM.getProb(sPath)));
316     }
317 
318     public String toString() {
319 	StringBuffer res = new StringBuffer();
320 	res.append("\n<FlatCInstance><Effects>");
321 	res.append(this.effects);
322 	res.append("</Effects>\n</FlatCInstance>\n");
323 
324 	return res.toString();
325     }
326 
327 } // FlatCInstance