1 | package PIANOS.generator; |
2 | |
3 | import PIANOS.datastructures.*; |
4 | import PIANOS.exceptions.*; |
5 | import PIANOS.io.*; |
6 | |
7 | import java.util.*; |
8 | import java.io.*; |
9 | |
10 | /** |
11 | * Generates calculations needed when generating the Fortarn module "main". |
12 | */ |
13 | public class Acceptation { |
14 | |
15 | private static ArrayList<Variable> topologicalList; |
16 | |
17 | /** |
18 | * Sets the topological variable list that is used when calculating the correct |
19 | * new-value-generation order for functional parameters. This method must be called before any |
20 | * other methods of this class are called. |
21 | * |
22 | * @param list A list of all variables in the current model in topolocial order. |
23 | */ |
24 | public static void setTopologicalList(ArrayList<Variable> list) { |
25 | // This method has to be called before any other methods! |
26 | topologicalList = new ArrayList<Variable>(list); |
27 | } |
28 | |
29 | |
30 | /** |
31 | * Generates code that fetches a proposed new value for a parameter from its buffer or if the buffer |
32 | * is empty, calls the subroutine "generate". |
33 | * |
34 | * @param variable A parameter for which the new value code is generated.We assume that it |
35 | * is indexed by "one_dim(1)" if it is global, by "one_dim(i)" if it is one-dimensional and by |
36 | * "two_dim(i, j)" if it is two-dimensional. |
37 | */ |
38 | public static ArrayList<String> generateNewValueCode(Variable variable) { |
39 | ArrayList<String> result=new ArrayList<String>(); |
40 | |
41 | assert variable.isFunctional() == false; |
42 | assert variable.isData() == false || variable.getMissingValueCount() > 0; |
43 | |
44 | String name = variable.getName(); |
45 | result.add("IF (" + name + " % buffer_index > SIZE(" + name + " % buffer) .OR. " + name + " % buffer_index < 1) THEN"); |
46 | result.add("CALL generate('" + name + "', " + name + " % buffer)"); |
47 | result.add(name + " % buffer_index = 1"); |
48 | result.add("END IF"); |
49 | result.add(""); |
50 | |
51 | String indexing=""; |
52 | if (variable.getEntity() == null) { |
53 | indexing = "one_dim(1)"; |
54 | } else if (variable.getEntity().isMatrix() == false) { |
55 | indexing = "one_dim(i)"; |
56 | } else { |
57 | indexing = "two_dim(i, j)"; |
58 | } |
59 | |
60 | assert variable.getStrategy() != null; |
61 | if (variable.getStrategy().equals("random walk")) { |
62 | result.add(name + " % " + indexing + " % new_value = " + name + " % " + indexing + " % value + " |
63 | + name + " % buffer(" + name + " % buffer_index)"); |
64 | } else { |
65 | result.add(name + " % " + indexing + " % new_value = " + name + " % buffer(" + name + " % buffer_index)"); |
66 | } |
67 | |
68 | result.add(name + " % buffer_index = " + name +" % buffer_index + 1"); |
69 | |
70 | return result; |
71 | } |
72 | |
73 | |
74 | /** |
75 | * Generates code that decides whether the new value is accepted and makes the necessary |
76 | * changes: updates the value of the current parameter and all functional parameters depending |
77 | * on it. |
78 | * |
79 | * @param variable A parameter for which the acceptation code is generated. We assume that it |
80 | * is indexed by "one_dim(1)" if it is global, by "one_dim(i)" if it is one-dimensional and by |
81 | * "two_dim(i, j)" if it is two-dimensional. |
82 | */ |
83 | public static ArrayList<String> generateAcceptationCode(Variable variable, String strategy) throws InvalidModelException{ |
84 | |
85 | assert variable.isFunctional() == false; |
86 | assert variable.isData() == false || variable.getMissingValueCount() > 0; |
87 | |
88 | ArrayList<String> result=new ArrayList<String>(); |
89 | |
90 | String name = variable.getName(); |
91 | |
92 | String indexing=""; |
93 | if (variable.getEntity() == null) { |
94 | indexing = "one_dim(1)"; |
95 | } else if (variable.getEntity().isMatrix() == false) { |
96 | indexing = "one_dim(i)"; |
97 | } else { |
98 | indexing = "two_dim(i, j)"; |
99 | } |
100 | |
101 | result.add("IF (p_acc > prob(prob_index)) THEN"); |
102 | result.add(name + " % " + indexing + " % value = " + name + " % " + indexing + " % new_value"); |
103 | result.add(name + " % " + indexing + " % successful_changes = " + name +" % " + indexing + |
104 | " % successful_changes + 1"); |
105 | result.add(""); |
106 | if (strategy.equals("random")){ |
107 | result.add("IF ("+ name +" % "+ indexing +" % successful_changes == "+ |
108 | name +" % "+ indexing +" % update_count) THEN"); |
109 | result.add("parameters_achieved = parameters_achieved + 1"); |
110 | result.add("END IF"); |
111 | } |
112 | // here we must update all the functionals depending on variable |
113 | // like blah % value = blah % new value |
114 | // problem: spatial case! (we need to _calculate_ the new value) |
115 | |
116 | // 1) functional, non-spatial |
117 | ArrayList<Variable> allAffected = new ArrayList<Variable>(variable.getAffectsList()); |
118 | for (int i=0; i<allAffected.size(); i++) { |
119 | Variable depending = allAffected.get(i); |
120 | |
121 | if (!depending.isFunctional()) |
122 | continue; |
123 | if(depending.isSpatial()) |
124 | continue; |
125 | |
126 | allAffected.addAll(depending.getAffectsList()); |
127 | |
128 | LinkedList<Variable> depdeps = depending.getDependsList(); |
129 | |
130 | boolean spatialDependencies = false; |
131 | for (Variable depdep : depdeps){ |
132 | if (depdep.isSpatial() && allAffected.contains(depdep)) |
133 | spatialDependencies = true; |
134 | } |
135 | |
136 | // code for depending... |
137 | if (spatialDependencies == false) { |
138 | result.addAll(acceptationAffectedOf(variable, depending)); |
139 | } |
140 | |
141 | } |
142 | |
143 | // 2) functional, spatial |
144 | // Here we update the spatial parameters of _neighbour_squares_ by using the new value of |
145 | // the current variable of the current square. |
146 | |
147 | allAffected = new ArrayList<Variable>(variable.getAffectsList()); |
148 | for (int i=0; i<allAffected.size(); i++) { |
149 | Variable depending = allAffected.get(i); |
150 | |
151 | if (!depending.isFunctional()) |
152 | continue; |
153 | LinkedList<Variable> depdeps = depending.getDependsList(); |
154 | |
155 | boolean spatialDependencies = false; |
156 | for (Variable depdep : depdeps){ |
157 | if (depdep.isSpatial() && allAffected.contains(depdep)) |
158 | spatialDependencies = true; |
159 | } |
160 | |
161 | /* now, if this variable (depending) has spatial dependencies: |
162 | * 1. depending is not spatial. (spatial variables have only one non-spatial dep) |
163 | * 2. depending has not been updated yet in the previous loop. |
164 | * 3. the spatial dependencies of depending have their new values calculated |
165 | * previously in this loop. |
166 | * So we can safely update it as we did before |
167 | * (and the path of other functionals leading from it) |
168 | * TROUBLE. If this depending is affected by a global, we must add loops and |
169 | * we shouldn't even be doing this neighbour-thing. |
170 | * How to recognize that the new value for depending has been already calculated |
171 | * while considering this global? ... Maybe we should look at the dependsList of depending. |
172 | * not really. Just checking that variable.getEntity() == null should suffice. |
173 | * IS IT ALWAYS like this? can we always skip the neighbouring process with variables |
174 | * that are global? |
175 | */ |
176 | |
177 | |
178 | if (spatialDependencies){ |
179 | if (variable.getEntity() == null){ |
180 | result.addAll(acceptationAffectedOf(variable, depending)); |
181 | } else{ |
182 | boolean spatialY; |
183 | if (depending.getEntity().isMatrix() == false){ |
184 | indexing = " % one_dim(neighbour)"; |
185 | spatialY = true; |
186 | } else{ |
187 | if (depending.getEntity().getXCoordinate().isSpatial()){ |
188 | indexing = " % two_dim(i, neighbour)"; |
189 | spatialY = false; |
190 | } else{ |
191 | indexing = " % two_dim(neighbour, j)"; |
192 | spatialY = true; |
193 | } |
194 | } |
195 | |
196 | if (spatialY){ |
197 | result.add("DO k = 1, spatial(i, 1)"); |
198 | result.add("neighbour = spatial(i, k +1)"); |
199 | } else{ |
200 | result.add("DO k = 1, spatial(j, 1)"); |
201 | result.add("neighbour = spatial(j, k +1)"); |
202 | } |
203 | |
204 | result.addAll(generateSpatialDeps(depending, indexing, spatialY)); |
205 | result.add("END DO"); |
206 | |
207 | |
208 | |
209 | } // end of not global variable |
210 | } // end of spatial deps |
211 | if(!depending.isSpatial()) // updated already |
212 | continue; |
213 | |
214 | for (Variable affected: depending.getAffectsList()){ |
215 | if (!allAffected.contains(affected)) |
216 | allAffected.add(affected); |
217 | } |
218 | |
219 | // adding further forks... |
220 | // Spatial variables are direct, but the functionals |
221 | // that depend on them have not been updated yet. |
222 | |
223 | /* ok, now update the spatial variable. |
224 | * it's either COUNT(&variable) |
225 | * or SUM(&variable) |
226 | * (since it depends on variable) |
227 | */ |
228 | String depname = depending.getName(); |
229 | |
230 | String[] depEquation = depending.getEquation().getEquation(); |
231 | boolean sum = false; |
232 | if (depEquation[0].startsWith("SUM")) |
233 | sum = true; |
234 | else |
235 | continue; |
236 | // count stays the same, squares don't get shot even if birds do :-) |
237 | |
238 | if (variable.getEntity().isMatrix() == false && |
239 | depending.getEntity().isMatrix() == false) { |
240 | // one-dim affecting an one-dim spatial, possible |
241 | |
242 | |
243 | result.add("! 1 to number of neighbours"); |
244 | result.add("DO k = 1, spatial(i, 1)"); |
245 | if (variable.isInteger()) |
246 | result.add("sum_int = 0"); |
247 | else |
248 | result.add("sum_real = 0"); |
249 | result.add("neighbour = spatial(i, k + 1)"); |
250 | result.add("! updating " + depname + " % one_dim(spatial(i, k + 1))"); |
251 | result.add("DO h = 1, spatial(neighbour, 1)"); // neighbours of neighbour |
252 | if (variable.isInteger()) |
253 | result.add("sum_int = sum_int + "+ name +" % one_dim(spatial(neighbour, h + 1)) % value"); |
254 | else |
255 | result.add("sum_real = sum_real + "+ name +" % one_dim(spatial(neighbour, h + 1)) % value"); |
256 | |
257 | result.add("END DO"); |
258 | if (variable.isInteger()) |
259 | result.add(depname + " % one_dim(neighbour) % value = sum_int"); |
260 | else |
261 | result.add(depname + " % one_dim(neighbour) % value = sum_real"); |
262 | result.add("END DO"); |
263 | |
264 | } else if (variable.getEntity().isMatrix() == false && |
265 | depending.getEntity().isMatrix() == true) { |
266 | // one-dim affecting a two-dim spatial, impossible? |
267 | throw new InvalidModelException("Acceptation: A one-dim variable is affecting a two-dim spatial!"); |
268 | |
269 | } else { |
270 | |
271 | // both 2-dimensional, possible (the same entity) |
272 | // two dimensional sum case... |
273 | // when variable and dep have the same number of dimensions |
274 | |
275 | String correct_sum = ""; |
276 | if (variable.isInteger()) { |
277 | correct_sum = "sum_int"; |
278 | } else correct_sum = "sum_real"; |
279 | if (variable.getEntity().getYCoordinate().isSpatial()){ |
280 | result.add("! 1 to number of neighbours"); |
281 | result.add("DO k = 1, spatial(i, 1)"); |
282 | result.add(correct_sum + " = 0"); |
283 | result.add("neighbour = spatial(i, k + 1)"); |
284 | result.add("! updating " + depname + " % two_dim(spatial(i, k + 1), j)"); |
285 | result.add("DO h = 1, spatial(neighbour, 1)"); // neighbours of neighbour |
286 | result.add(correct_sum + " = " + correct_sum + " + " + name + " % two_dim(spatial(neighbour, h + 1), j) % value"); |
287 | result.add("END DO"); |
288 | result.add(depname + " % two_dim(neighbour, j) % value = " + correct_sum); |
289 | result.add("END DO"); |
290 | } else{ |
291 | result.add("! 1 to number of neighbours"); |
292 | result.add("DO k = 1, spatial(j, 1)"); |
293 | result.add(correct_sum + " = 0"); |
294 | result.add("neighbour = spatial(j, k + 1)"); |
295 | result.add("! updating " + depname + " % two_dim(i, spatial(j, k + 1))"); |
296 | result.add("DO h = 1, spatial(neighbour, 1)"); // neighbours of neighbour |
297 | result.add(correct_sum + " = " + correct_sum + " + " + name + " % two_dim(i, spatial(neighbour, h + 1)) % value"); |
298 | result.add("END DO"); |
299 | result.add(depname + " % two_dim(i, neighbour) % value = " + correct_sum); |
300 | result.add("END DO"); |
301 | |
302 | } |
303 | } |
304 | } |
305 | |
306 | |
307 | |
308 | |
309 | result.add("END IF"); |
310 | result.add("prob_index = prob_index + 1"); |
311 | result.add("IF (prob_index > SIZE(prob) .OR. prob_index < 1) THEN"); |
312 | result.add("CALL G05FAF(0.0_dp, 1.0_dp, SIZE(prob), prob)"); |
313 | result.add("prob_index = 1"); |
314 | result.add("END IF"); |
315 | |
316 | return result; |
317 | } |
318 | |
319 | /** |
320 | * Sets correct indexing for functional variables with |
321 | * spatial dependencies. Used for updating neighbouring square functional properties after |
322 | * the spatial functional variable target has been updated. |
323 | * For example: q = sum(&x) and p = q/2.0. |
324 | * When x is updated (the spatial target) |
325 | * first q is calculated for all neighbours of x, |
326 | * then all neighbours of x get a new p to match their new q values. |
327 | */ |
328 | |
329 | private static ArrayList<String> generateSpatialDeps(Variable functional, String indexing, boolean spatialY){ |
330 | ArrayList<String> result = new ArrayList<String>(); |
331 | String[] equation = functional.getEquation().getEquation(); |
332 | |
333 | |
334 | Variable[] parameters = functional.getEquation().getParameters(); |
335 | |
336 | |
337 | // DEBUG |
338 | /* |
339 | System.out.println("GENERATOR DEBUG: generateSpatialDeps for " + functional.getName()); |
340 | System.out.print("newToBeUsed contains:"); |
341 | for (Variable n : newToBeUsed){ |
342 | System.out.print(n.getName() + " "); |
343 | } |
344 | System.out.println(); |
345 | */ |
346 | |
347 | // check the equation of depending |
348 | for (int i=0; i<parameters.length; i++) { |
349 | // dealing with Variable parameters[i] |
350 | |
351 | //System.out.println("GENERATOR DEBUG: dealing with " + parameters[i].getName()); |
352 | if (parameters[i].getEntity() == null) { // global |
353 | for (int j=0; j<equation.length; j++) { |
354 | if (equation[j].equals(parameters[i].getName())) { |
355 | equation[j] += " % one_dim(1) % value"; |
356 | } |
357 | } // end looping the equation |
358 | } else if (parameters[i].getEntity().isMatrix() == false) { // one-dimensional |
359 | if (parameters[i].getEntity().equals(functional.getEntity().getXCoordinate())) { |
360 | for (int j=0; j<equation.length; j++) { |
361 | if (equation[j].equals(parameters[i].getName())) { |
362 | if (spatialY) |
363 | equation[j] += " % one_dim(j) % value"; |
364 | else |
365 | equation[j] += " % one_dim(neighbour) % value"; |
366 | } |
367 | } // end looping the equation |
368 | } else { // either the same entity or equals y-coordinate |
369 | for (int j=0; j<equation.length; j++) { |
370 | if (equation[j].equals(parameters[i].getName())) { |
371 | if (spatialY) |
372 | equation[j] += " % one_dim(neighbour) % value"; |
373 | else |
374 | equation[j] += " % one_dim(i) % value"; |
375 | } |
376 | } // end looping the equation |
377 | } |
378 | |
379 | } else { // two-dimensional |
380 | for (int j=0; j<equation.length; j++) { |
381 | if (equation[j].equals(parameters[i].getName())) { |
382 | if (spatialY) |
383 | equation[j] += " % two_dim(neighbour, j) % value"; |
384 | else |
385 | equation[j] += " % two_dim(i, neighbour) % value"; |
386 | } |
387 | } // end looping the equation |
388 | } |
389 | } // end looping the parameters[] |
390 | |
391 | String finalEquation = ""; |
392 | for (int k=0; k<equation.length; k++) { |
393 | finalEquation = finalEquation + equation[k]; |
394 | } |
395 | |
396 | result.add(functional.getName() + indexing + " % value = " + finalEquation); |
397 | |
398 | return result; |
399 | |
400 | } |
401 | |
402 | private static ArrayList<String> acceptationAffectedOf(Variable variable, Variable depending){ |
403 | ArrayList<String> result = new ArrayList<String>(); |
404 | if (variable.getEntity() == null && depending.getEntity() == null) { |
405 | result.addAll(generateUpdateOneFunctional(depending)); |
406 | } else if (variable.getEntity() == null && |
407 | depending.getEntity().isMatrix() == false) { |
408 | result.add("DO i2 = 1, " + depending.getEntity().getSize()); |
409 | result.addAll(generateUpdateOneFunctional(depending)); |
410 | result.add("END DO"); |
411 | } else if (variable.getEntity() == null && |
412 | depending.getEntity().isMatrix()) { |
413 | result.add("DO i2 = 1, " + depending.getEntity().getYCoordinate().getSize()); |
414 | result.add("DO j2 = 1, " + depending.getEntity().getXCoordinate().getSize()); |
415 | result.addAll(generateUpdateOneFunctional(depending)); |
416 | result.add("END DO"); |
417 | result.add("END DO"); |
418 | } else if (variable.getEntity().isMatrix() == false && |
419 | depending.getEntity().isMatrix() == false) { |
420 | result.add("i2 = i"); |
421 | result.addAll(generateUpdateOneFunctional(depending)); |
422 | } else if (variable.getEntity().isMatrix() == false && |
423 | depending.getEntity().isMatrix() == true) { |
424 | if (variable.getEntity().equals(depending.getEntity().getYCoordinate())) { |
425 | result.add("i2 = i"); |
426 | result.add("DO j2 = 1, " + |
427 | depending.getEntity().getXCoordinate().getSize()); |
428 | result.addAll(generateUpdateOneFunctional(depending)); |
429 | result.add("END DO"); |
430 | } else { |
431 | result.add("j2 = i"); |
432 | result.add("DO i2 = 1, " + |
433 | depending.getEntity().getYCoordinate().getSize()); |
434 | result.addAll(generateUpdateOneFunctional(depending)); |
435 | result.add("END DO"); |
436 | } |
437 | } else { |
438 | result.add("i2 = i"); |
439 | result.add("j2 = j"); |
440 | result.addAll(generateUpdateOneFunctional(depending)); |
441 | } |
442 | return result; |
443 | } |
444 | |
445 | private static ArrayList<String> generateUpdateOneFunctional(Variable depending) { |
446 | |
447 | // This generates the code that replaces the value by new_value for one particular variable |
448 | |
449 | // depending is indexed: (1), (i) or (i2, j2). |
450 | |
451 | assert depending.isFunctional() == true; |
452 | |
453 | ArrayList<String> result=new ArrayList<String>(); |
454 | String indexing = ""; |
455 | |
456 | if (depending.getEntity() == null) { |
457 | indexing = "one_dim(1)"; |
458 | } else if (depending.getEntity().isMatrix() == false){ |
459 | indexing = "one_dim(i2)"; |
460 | } else indexing = "two_dim(i2, j2)"; |
461 | |
462 | result.add(depending.getName() + " % " + indexing + " % value = " + |
463 | depending.getName() + " % " + indexing + " % new_value"); |
464 | |
465 | return result; |
466 | |
467 | } |
468 | |
469 | |
470 | private static ArrayList<Variable> topologicalSort(ArrayList<Variable> sortThis) { |
471 | // This method sorts the list sortThis topologically. |
472 | // We assume that the variables are introduced in topological order in the model specification. |
473 | assert topologicalList != null; |
474 | |
475 | ArrayList<Variable> result = new ArrayList<Variable>(topologicalList); |
476 | result.retainAll(sortThis); |
477 | return result; |
478 | } |
479 | |
480 | private static ArrayList<String> generateNewValueForOneFunctional(Variable functional, |
481 | Set<Variable> newToBeUsed) throws InvalidModelException { |
482 | // this is a different approach to generateNewValuesFunctionalCode |
483 | |
484 | // We assume that functional is indexed by one_dim(1), one_dim(i2) or two_dim(i2, j2) |
485 | // and generate the code that calculates the new value and places it to new_value. |
486 | |
487 | // Note that the spatial functional parameters don't need new values here, so this method is not called. |
488 | |
489 | ArrayList<String> result = new ArrayList<String>(); |
490 | |
491 | //String[] equation = functional.getEquation().getEquation(); A BUG! |
492 | |
493 | String[] equation = functional.getEquation().getEquation(); |
494 | |
495 | /* the equation in parts: for example: |
496 | 3 * alpha + EXP(beta+gamma) -> |
497 | 3 * |
498 | alpha |
499 | + EXP( |
500 | beta |
501 | + |
502 | gamma |
503 | ) |
504 | */ |
505 | |
506 | Variable[] parameters = functional.getEquation().getParameters(); |
507 | |
508 | |
509 | // DEBUG |
510 | /* |
511 | System.out.println("GENERATOR DEBUG: generateNewValueForOneFunctional for " + functional.getName()); |
512 | System.out.print("newToBeUsed contains:"); |
513 | for (Variable n : newToBeUsed){ |
514 | System.out.print(n.getName() + " "); |
515 | } |
516 | System.out.println(); |
517 | */ |
518 | |
519 | //result.add("! DEBUG: a mysterious bug resides here somewhere."); |
520 | // check the equation of depending |
521 | for (int i=0; i<parameters.length; i++) { |
522 | // dealing with Variable parameters[i] |
523 | |
524 | //System.out.println("GENERATOR DEBUG: dealing with " + parameters[i].getName()); |
525 | if (parameters[i].getEntity() == null) { // global |
526 | for (int j=0; j<equation.length; j++) { |
527 | if (equation[j].equals(parameters[i].getName())) { |
528 | if (newToBeUsed.contains(parameters[i])) { |
529 | //System.out.println("here 1"); |
530 | equation[j] += " % one_dim(1) % new_value"; |
531 | } else { |
532 | //System.out.println("here 2"); |
533 | equation[j] += " % one_dim(1) % value"; |
534 | } |
535 | } |
536 | } // end looping the equation |
537 | } else if (parameters[i].getEntity().isMatrix() == false) { // one-dimensional |
538 | if (parameters[i].getEntity().equals(functional.getEntity().getXCoordinate())) { |
539 | for (int j=0; j<equation.length; j++) { |
540 | if (equation[j].equals(parameters[i].getName())) { |
541 | if (newToBeUsed.contains(parameters[i])) { |
542 | //System.out.println("here 3"); |
543 | equation[j] += " % one_dim(j2) % new_value"; |
544 | } else { |
545 | //System.out.println("here 4"); |
546 | equation[j] += " % one_dim(j2) % value"; |
547 | } |
548 | } |
549 | } // end looping the equation |
550 | } else { // either the same entity or equals y-coordinate |
551 | for (int j=0; j<equation.length; j++) { |
552 | if (equation[j].equals(parameters[i].getName())) { |
553 | if (newToBeUsed.contains(parameters[i])) { |
554 | //System.out.println("here 5"); |
555 | equation[j] += " % one_dim(i2) % new_value"; |
556 | } else { |
557 | //System.out.println("here 6"); |
558 | equation[j] += " % one_dim(i2) % value"; |
559 | } |
560 | } |
561 | } // end looping the equation |
562 | } |
563 | |
564 | } else { // two-dimensional |
565 | for (int j=0; j<equation.length; j++) { |
566 | if (equation[j].equals(parameters[i].getName())) { |
567 | if (newToBeUsed.contains(parameters[i])) { |
568 | //System.out.println("here 7"); |
569 | equation[j] += " % two_dim(i2, j2) % new_value"; |
570 | } else { |
571 | //System.out.println("here 8"); |
572 | equation[j] += " % two_dim(i2, j2) % value"; |
573 | } |
574 | } |
575 | } // end looping the equation |
576 | } |
577 | } // end looping the parameters[] |
578 | |
579 | String finalEquation = ""; |
580 | for (int k=0; k<equation.length; k++) { |
581 | finalEquation = finalEquation + equation[k]; |
582 | } |
583 | |
584 | if (functional.getEntity() == null) { |
585 | result.add(functional.getName() + " % one_dim(1) % new_value = " + finalEquation); |
586 | } else if (functional.getEntity().isMatrix() == false) { |
587 | result.add(functional.getName() + " % one_dim(i2) % new_value = " + finalEquation); |
588 | } else result.add(functional.getName() + " % two_dim(i2, j2) % new_value = " + finalEquation); |
589 | |
590 | return result; |
591 | } |
592 | |
593 | /** |
594 | * Generates code that calculates new values for all the functional parameters depending on |
595 | * the current parameter. |
596 | * |
597 | * @param variable The current parameter. We assume that it |
598 | * is indexed by "one_dim(1)" if it is global, by "one_dim(i)" if it is one-dimensional and by |
599 | * "two_dim(i, j)" if it is two-dimensional. Note that the new values for "SUM"-parameters are |
600 | * not calculated here. |
601 | */ |
602 | public static ArrayList<String> generateNewValuesFunctionalCode(Variable variable) |
603 | throws InvalidModelException { |
604 | |
605 | ArrayList<String> result = new ArrayList<String>(); |
606 | ArrayList<Variable> allAffected = new ArrayList<Variable>(variable.getAffectsList()); |
607 | Set<Variable> newToBeUsed = new HashSet<Variable>(); |
608 | newToBeUsed.add(variable); |
609 | |
610 | //System.out.println("GENERATOR DEBUG: generateNewValuesFunctionalCode for " + variable.getName()); |
611 | |
612 | for (int iterator = 0; iterator < allAffected.size(); iterator++) { |
613 | Variable depending = allAffected.get(iterator); |
614 | |
615 | //System.out.println("GENERATOR DEBUG: depending (phase 1) is : " + depending.getName()); |
616 | // not functional |
617 | if (depending.isFunctional() == false) continue; |
618 | |
619 | // the spatial parameters won't need new values here and no new dependencies are added |
620 | if (depending.isSpatial() == true) continue; |
621 | |
622 | // add further affected variables to all_depending |
623 | allAffected.addAll(depending.getAffectsList()); |
624 | newToBeUsed.add(depending); |
625 | } |
626 | |
627 | // DEBUG |
628 | /* |
629 | if (allAffected == null) { |
630 | System.out.println("GENERATOR DEBUG: allAffected is null."); |
631 | }*/ |
632 | |
633 | allAffected = topologicalSort(allAffected); |
634 | |
635 | for (int iterator = 0; iterator < allAffected.size(); iterator++) { |
636 | |
637 | Variable depending = allAffected.get(iterator); |
638 | |
639 | //System.out.println("GENERATOR DEBUG: depending (phase 2) is : " + depending.getName()); |
640 | |
641 | // not functional |
642 | if (depending.isFunctional() == false) continue; |
643 | if (depending.isSpatial()) continue; // we don't need to calculate new values for them |
644 | |
645 | result.add(""); |
646 | result.add("! calculating new value(s) for " + depending.getName()); |
647 | result.add(""); |
648 | |
649 | if (variable.getEntity() == null && depending.getEntity() == null) { |
650 | // no loops |
651 | result.addAll(generateNewValueForOneFunctional(depending, newToBeUsed)); |
652 | return result; |
653 | } |
654 | |
655 | if (variable.getEntity() == null && depending.getEntity().isMatrix() == false){ |
656 | // one loop |
657 | result.add("DO i2 = 1, " + depending.getEntity().getSize()); |
658 | result.addAll(generateNewValueForOneFunctional(depending, newToBeUsed)); |
659 | result.add("END DO"); |
660 | return result; |
661 | } |
662 | |
663 | if (variable.getEntity() == null && depending.getEntity().isMatrix() == true) { |
664 | // two loops |
665 | result.add("DO i2 = 1, " + depending.getEntity().getYCoordinate().getSize()); |
666 | result.add("DO j2 = 1, " + depending.getEntity().getXCoordinate().getSize()); |
667 | result.addAll(generateNewValueForOneFunctional(depending, newToBeUsed)); |
668 | result.add("END DO"); |
669 | result.add("END DO"); |
670 | return result; |
671 | } |
672 | |
673 | if (variable.getEntity().isMatrix() == false && depending.getEntity().isMatrix() == false) { |
674 | // no loops |
675 | result.add("i2 = i"); |
676 | result.addAll(generateNewValueForOneFunctional(depending, newToBeUsed)); |
677 | return result; |
678 | } |
679 | |
680 | if (variable.getEntity().isMatrix() == false && depending.getEntity().isMatrix() == true) { |
681 | // one loop |
682 | if (variable.getEntity().equals(depending.getEntity().getYCoordinate())) { |
683 | result.add("i2 = i"); |
684 | result.add("DO j2 = 1, " + depending.getEntity().getXCoordinate().getSize()); |
685 | result.addAll(generateNewValueForOneFunctional(depending, newToBeUsed)); |
686 | result.add("END DO"); |
687 | return result; |
688 | } else { |
689 | result.add("j2 = i"); |
690 | result.add("DO i2 = 1, " + depending.getEntity().getYCoordinate().getSize()); |
691 | result.addAll(generateNewValueForOneFunctional(depending, newToBeUsed)); |
692 | result.add("END DO"); |
693 | return result; |
694 | } |
695 | } |
696 | |
697 | if (variable.getEntity().isMatrix() == true && depending.getEntity().isMatrix() == true) { |
698 | // no loops |
699 | result.add("i2 = i"); |
700 | result.add("j2 = j"); |
701 | result.addAll(generateNewValueForOneFunctional(depending, newToBeUsed)); |
702 | return result; |
703 | } |
704 | } |
705 | |
706 | return result; |
707 | } |
708 | |
709 | |
710 | /** |
711 | * Generates code that calculates the acceptance probability for the current parameter. |
712 | * |
713 | * @param variable The current parameter. We assume that it |
714 | * is indexed by "one_dim(1)" if it is global, by "one_dim(i)" if it is one-dimensional and by |
715 | * "two_dim(i, j)" if it is two-dimensional. |
716 | */ |
717 | public static ArrayList<String> generateAcceptationFormula(Variable variable) |
718 | throws InvalidModelException, IllegalParametersException, MissingFunctionException { |
719 | |
720 | /* The idea: |
721 | |
722 | 1. probability for this parameter |
723 | 2. probabilities for all affected variables |
724 | 3. q-probabilities. |
725 | |
726 | Note: This method DOES NOT generate: |
727 | - the loops (acceptation for all x's for example) |
728 | - generating proposals |
729 | - acceptation |
730 | - updating functional parameters |
731 | or anything like that. |
732 | */ |
733 | |
734 | assert variable.isFunctional() == false; |
735 | assert variable.isData() == false || variable.getMissingValueCount() > 0; |
736 | |
737 | if (variable.getEntity() == null) { |
738 | return generateAcceptationFormulaGlobal(variable); |
739 | } else if (variable.getEntity().isMatrix() == false) { |
740 | return generateAcceptationFormulaOneDimensional(variable); |
741 | } else { |
742 | return generateAcceptationFormulaTwoDimensional(variable); |
743 | } |
744 | |
745 | } |
746 | |
747 | private static ArrayList<String> generateAcceptationFormulaGlobal(Variable variable) |
748 | throws InvalidModelException, IllegalParametersException, MissingFunctionException { |
749 | |
750 | //System.out.println("GENERATOR DEBUG: generateAcceptationFormulaGlobal"); |
751 | /* |
752 | This variable is global. |
753 | It is indexed like variable % one_dim(1). |
754 | |
755 | All affecting variables must also be global. |
756 | */ |
757 | |
758 | ArrayList<String> result = new ArrayList<String>(); |
759 | |
760 | int parameterCount = variable.getDistribution().getNumberOfParameters(); |
761 | |
762 | String[] indices = new String[parameterCount+2]; |
763 | |
764 | // 1. P(variable') / P(variable) |
765 | |
766 | // DEBUG |
767 | //System.out.println("GENERATOR DEBUG: 1. P(" + variable.getName() + "') / P(" + variable.getName() + ")"); |
768 | |
769 | result.add(""); |
770 | result.add("! P(" + variable.getName() + "') / P(" + variable.getName() + ")"); |
771 | result.add(""); |
772 | |
773 | result.add("p_acc = 1"); |
774 | |
775 | for (int i=0; i<parameterCount; i++) { |
776 | Object parameter = variable.getDistribution().getParameter(i); |
777 | |
778 | if (parameter instanceof Integer) { |
779 | indices[i] = ((Integer)parameter).toString(); |
780 | continue; |
781 | } else if (parameter instanceof Double) { |
782 | // we must add _dp to the real constants |
783 | indices[i] = ((Double)parameter).toString()+"_dp"; |
784 | continue; |
785 | } |
786 | // now we know that the parameter is a Variable. |
787 | |
788 | Variable varParameter=(Variable)parameter; |
789 | // it must be global |
790 | indices[i] = varParameter.getName()+" % one_dim(1) % value"; |
791 | } |
792 | indices[parameterCount] = variable.getName() + " % one_dim(1) % new_value"; |
793 | indices[parameterCount+1] = "new_frequency"; |
794 | |
795 | // P(variable') |
796 | |
797 | // DEBUG |
798 | /* |
799 | System.out.println("GENERATOR DEBUG: About to call getFreqCode with parameters: "); |
800 | for (int print=0; print<indices.length; print++) |
801 | { |
802 | System.out.println(indices[print]); |
803 | } |
804 | */ |
805 | |
806 | ArrayList<String> toAdd=variable.getDistribution().getFreqCode(indices); |
807 | result.addAll(toAdd); |
808 | |
809 | indices[parameterCount] = variable.getName() + " % one_dim(1) % value"; |
810 | indices[parameterCount+1] = "frequency"; |
811 | |
812 | // P(variable) |
813 | |
814 | // DEBUG |
815 | /* |
816 | System.out.println("GENERATOR DEBUG: About to call getFreqCode with parameters: "); |
817 | for (int print=0; print<indices.length; print++) |
818 | { |
819 | System.out.println(indices[print]); |
820 | } |
821 | */ |
822 | |
823 | toAdd=variable.getDistribution().getFreqCode(indices); |
824 | result.addAll(toAdd); |
825 | |
826 | result.add("p_acc = p_acc * new_frequency / frequency"); |
827 | |
828 | // 2) P(x | variable') / P(x | variable) for all x that depend on variable |
829 | |
830 | // DEBUG |
831 | /* |
832 | System.out.println("GENERATOR DEBUG: Phase 2. P( depending | " + variable.getName() + |
833 | ") / P( depending | " + variable.getName() + "')"); |
834 | */ |
835 | |
836 | ArrayList<Variable> allAffected = new ArrayList<Variable>(variable.getAffectsList()); |
837 | Set<Variable> newToBeUsed = new HashSet<Variable>(); |
838 | newToBeUsed.add(variable); |
839 | |
840 | Set<Variable> handledAlready = new HashSet<Variable>(); |
841 | |
842 | for (int iterator = 0; iterator < allAffected.size(); iterator++) { |
843 | Variable depending = allAffected.get(iterator); |
844 | |
845 | if (depending.isSpatial()) continue; |
846 | |
847 | // functional but not spatial |
848 | if (depending.isFunctional()) { |
849 | // add further affected variables to all_depending |
850 | allAffected.addAll(depending.getAffectsList()); |
851 | newToBeUsed.add(depending); |
852 | continue; |
853 | } |
854 | |
855 | if (depending.equals(variable)) continue; // no loops please |
856 | |
857 | // not functional |
858 | |
859 | // DEBUG |
860 | /* |
861 | System.out.println("GENERATOR DEBUG: Phase 2, in detail: P( " + depending.getName() + " | " |
862 | + variable.getName() + "') / P( " + depending.getName() + " | " + variable.getName() + ")"); |
863 | */ |
864 | |
865 | if (handledAlready.contains(depending)) continue; // no duplicates |
866 | |
867 | result.add(""); |
868 | result.add("! P( " + depending.getName() + " | " |
869 | + variable.getName() + "') / P( " + depending.getName() + " | " + variable.getName() + ")"); |
870 | result.add(""); |
871 | |
872 | handledAlready.add(depending); |
873 | |
874 | // now variable is global, so depending may be global, one-dimensional or two-dimensional |
875 | |
876 | if (depending.getEntity() == null) { |
877 | // depending is global |
878 | result.addAll(generateLikelihoodFormulaGlobal(depending, newToBeUsed)); |
879 | |
880 | } else if (depending.getEntity().isMatrix() == false) { |
881 | // depending is one-dimensional |
882 | |
883 | // we have to generate a loop |
884 | result.add("DO i=1, "+depending.getEntity().getSize()); |
885 | result.addAll(generateLikelihoodFormulaOneDimensional(depending, newToBeUsed)); |
886 | result.add("END DO"); |
887 | } |
888 | |
889 | else { |
890 | // depending is two-dimensional |
891 | |
892 | // we have to generate two loops |
893 | result.add("DO i=1, "+depending.getEntity().getYCoordinate().getSize()); |
894 | result.add("DO j=1, "+depending.getEntity().getXCoordinate().getSize()); |
895 | result.addAll(generateLikelihoodFormulaTwoDimensional(depending, newToBeUsed, true)); |
896 | result.add("END DO"); |
897 | result.add("END DO"); |
898 | } |
899 | } |
900 | |
901 | result.addAll(generateTransitionFormula(variable)); |
902 | return result; |
903 | } |
904 | |
905 | private static ArrayList<String> generateAcceptationFormulaOneDimensional(Variable variable) |
906 | throws InvalidModelException, IllegalParametersException, MissingFunctionException { |
907 | |
908 | //System.out.println("GENERATOR DEBUG: generateAcceptationFormulaOneDimensional"); |
909 | /* |
910 | This variable belongs to an one-dimensional entity. |
911 | It is indexed like variable % one_dim(i). |
912 | |
913 | All affecting variables must be either global |
914 | or belong to the same one-dimensional entity. |
915 | |
916 | All affected variables must belong to the same one-dimensional |
917 | entity or to the two-dimensional child entity of variable's entity. |
918 | */ |
919 | |
920 | // DEBUG |
921 | /* |
922 | System.out.println("GENERATOR DEBUG: called generateAcceptationFormulaOneDimensional with " + |
923 | variable.getName()); |
924 | */ |
925 | |
926 | ArrayList<String> result = new ArrayList<String>(); |
927 | |
928 | int parameterCount = variable.getDistribution().getNumberOfParameters(); |
929 | |
930 | String[] indices = new String[parameterCount+2]; |
931 | |
932 | // DEBUG |
933 | //System.out.println("GENERATOR DEBUG: 1. P(" + variable.getName() + ") / P(" + variable.getName() + "')"); |
934 | |
935 | result.add(""); |
936 | result.add("! P(" + variable.getName() + "') / P(" + variable.getName() + ")"); |
937 | result.add(""); |
938 | |
939 | result.add("p_acc = 1"); |
940 | |
941 | for (int i=0; i<parameterCount; i++) { |
942 | Object parameter = variable.getDistribution().getParameter(i); |
943 | |
944 | if (parameter instanceof Integer) { |
945 | indices[i] = ((Integer)parameter).toString(); |
946 | continue; |
947 | } else if (parameter instanceof Double) { |
948 | // we must add _dp to the real constants |
949 | indices[i] = ((Double)parameter).toString()+"_dp"; |
950 | continue; |
951 | } |
952 | // now we know that the parameter is a Variable. |
953 | |
954 | Variable varParameter=(Variable)parameter; |
955 | |
956 | if (varParameter.getEntity() == null) { |
957 | indices[i] = varParameter.getName() + " % one_dim(1) % value"; |
958 | } else if (varParameter.getEntity().equals(variable.getEntity())) { |
959 | indices[i] = varParameter.getName() + " % one_dim(i) % value"; |
960 | } else throw new InvalidModelException("Variable " + |
961 | varParameter.getName() + " affects variable " + variable.getName()); |
962 | } |
963 | indices[parameterCount] = variable.getName()+" % one_dim(i) % new_value"; |
964 | indices[parameterCount+1] = "new_frequency"; |
965 | |
966 | // P(variable') |
967 | |
968 | // DEBUG |
969 | /* |
970 | System.out.println("GENERATOR DEBUG: About to call getFreqCode with parameters: "); |
971 | for (int print=0; print<indices.length; print++) |
972 | { |
973 | System.out.println(indices[print]); |
974 | } |
975 | */ |
976 | |
977 | ArrayList<String> toAdd = variable.getDistribution().getFreqCode(indices); |
978 | result.addAll(toAdd); |
979 | |
980 | indices[parameterCount] = variable.getName()+" % one_dim(i) % value"; |
981 | indices[parameterCount+1] = "frequency"; |
982 | |
983 | // P(variable) |
984 | |
985 | // DEBUG |
986 | /* |
987 | System.out.println("GENERATOR DEBUG: About to call getFreqCode with parameters: "); |
988 | for (int print=0; print<indices.length; print++) |
989 | { |
990 | System.out.println(indices[print]); |
991 | } |
992 | */ |
993 | |
994 | toAdd = variable.getDistribution().getFreqCode(indices); |
995 | result.addAll(toAdd); |
996 | |
997 | result.add("p_acc = p_acc * new_frequency / frequency"); |
998 | |
999 | // 2) P(x | variable') / P(x | variable) for all x that depend on variable |
1000 | |
1001 | // DEBUG |
1002 | /* |
1003 | System.out.println("GENERATOR DEBUG: Phase 2. P( depending | " + variable.getName() + |
1004 | ") / P( depending | " + variable.getName() + "')"); |
1005 | */ |
1006 | |
1007 | result.add(""); |
1008 | |
1009 | ArrayList<Variable> allAffected = new ArrayList<Variable>(variable.getAffectsList()); |
1010 | Set<Variable> newToBeUsed = new HashSet<Variable>(); |
1011 | newToBeUsed.add(variable); |
1012 | |
1013 | Set<Variable> handledAlready = new HashSet<Variable>(); |
1014 | |
1015 | for (int iterator = 0; iterator < allAffected.size(); iterator++) { |
1016 | Variable depending = allAffected.get(iterator); |
1017 | |
1018 | if (depending.isSpatial()) continue; |
1019 | |
1020 | // functional |
1021 | if (depending.isFunctional()) { |
1022 | |
1023 | // add further affeced variables to all_depending |
1024 | allAffected.addAll(depending.getAffectsList()); |
1025 | newToBeUsed.add(depending); |
1026 | continue; |
1027 | } |
1028 | |
1029 | if (depending.equals(variable)) continue; // no loops please |
1030 | |
1031 | if (handledAlready.contains(depending)) continue; // no duplicates |
1032 | |
1033 | // not functional |
1034 | |
1035 | // DEBUG |
1036 | /* |
1037 | System.out.println("GENERATOR DEBUG: Phase 2, in detail: P( " + depending.getName() + " | " |
1038 | + variable.getName() + "') / P( " + depending.getName() + " | " + variable.getName() + ")"); |
1039 | */ |
1040 | |
1041 | result.add(""); |
1042 | result.add("! P( " + depending.getName() + " | " |
1043 | + variable.getName() + "') / P( " + depending.getName() + " | " + variable.getName() + ")"); |
1044 | result.add(""); |
1045 | |
1046 | // now variable is one-dimensional, so depending may be one-dimensional or two-dimensional |
1047 | |
1048 | handledAlready.add(depending); |
1049 | |
1050 | if (depending.getEntity() == null) { |
1051 | throw new InvalidModelException("One-dimensional variable " + |
1052 | variable.getName() + " affects global variable " + depending.getName()); |
1053 | } else if (depending.getEntity().isMatrix() == false) { |
1054 | // depending is one-dimensional |
1055 | |
1056 | // depending's entity must be the same as variable's entity. |
1057 | if (!depending.getEntity().equals(variable.getEntity())) { |
1058 | throw new InvalidModelException("Variable " + |
1059 | variable.getName() + " affects variable " + depending.getName()); |
1060 | } |
1061 | |
1062 | result.addAll(generateLikelihoodFormulaOneDimensional(depending, newToBeUsed)); |
1063 | } else { |
1064 | // depending is two-dimensional |
1065 | |
1066 | // we have to generate a loop |
1067 | if (depending.getEntity().getXCoordinate().equals(variable.getEntity())) { |
1068 | result.add("DO j=1, "+depending.getEntity().getYCoordinate().getSize()); |
1069 | |
1070 | // depending is indexed depending % two_dim(j, i) |
1071 | result.addAll(generateLikelihoodFormulaTwoDimensional(depending, newToBeUsed, false)); |
1072 | result.add("END DO"); |
1073 | |
1074 | } else if (depending.getEntity().getYCoordinate().equals(variable.getEntity())) { |
1075 | result.add("DO j=1, "+depending.getEntity().getXCoordinate().getSize()); |
1076 | |
1077 | // depending is indexed depending % two_dim(i, j) |
1078 | result.addAll(generateLikelihoodFormulaTwoDimensional(depending, newToBeUsed, true)); |
1079 | result.add("END DO"); |
1080 | } else { |
1081 | throw new InvalidModelException("Variable " + |
1082 | variable.getName() + " affects variable " + depending.getName()); |
1083 | } |
1084 | } |
1085 | } |
1086 | result.addAll(generateTransitionFormula(variable)); |
1087 | return result; |
1088 | } |
1089 | |
1090 | private static ArrayList<String> generateAcceptationFormulaTwoDimensional(Variable variable) |
1091 | throws InvalidModelException, IllegalParametersException, MissingFunctionException { |
1092 | |
1093 | //System.out.println("GENERATOR DEBUG: generateAcceptationFormulaTwoDimensional"); |
1094 | /* |
1095 | This variable belongs to a two-dimensional entity. |
1096 | It is indexed like variable % two_dim(i, j). |
1097 | |
1098 | All affecting variables may be global, |
1099 | belong to the vertical entity, belong to the horizontal entity, |
1100 | or belong to the same two-dimensional entity. |
1101 | |
1102 | All affected variables must belong to the same entity. |
1103 | */ |
1104 | |
1105 | ArrayList<String> result = new ArrayList<String>(); |
1106 | |
1107 | int parameterCount = variable.getDistribution().getNumberOfParameters(); |
1108 | |
1109 | String[] indices = new String[parameterCount+2]; |
1110 | |
1111 | // 1. P(variable') / P(variable) |
1112 | |
1113 | // DEBUG |
1114 | //System.out.println("GENERATOR DEBUG: 1. P(" + variable.getName() + ") / P(" + variable.getName() + "')"); |
1115 | |
1116 | result.add(""); |
1117 | result.add("! P(" + variable.getName() + "') / P(" + variable.getName() + ")"); |
1118 | result.add(""); |
1119 | |
1120 | result.add("p_acc = 1"); |
1121 | |
1122 | for (int i=0; i<parameterCount; i++) { |
1123 | //int type = variable.getDistribution().getParameter(i); |
1124 | Object parameter = variable.getDistribution().getParameter(i); |
1125 | |
1126 | if (parameter instanceof Integer) { |
1127 | indices[i] = ((Integer)parameter).toString(); |
1128 | continue; |
1129 | } else if (parameter instanceof Double) { |
1130 | // we must add _dp to the real constants |
1131 | indices[i] = ((Double)parameter).toString()+"_dp"; |
1132 | continue; |
1133 | } |
1134 | // now we know that the parameter is a Variable. |
1135 | |
1136 | Variable varParameter=(Variable)parameter; |
1137 | |
1138 | if (varParameter.getEntity() == null) { |
1139 | indices[i] = varParameter.getName()+" % one_dim(1) % value"; |
1140 | } else if (varParameter.getEntity().equals(variable.getEntity().getYCoordinate())) { |
1141 | indices[i] = varParameter.getName()+" % one_dim(i) % value"; |
1142 | } else if (varParameter.getEntity().equals(variable.getEntity().getXCoordinate())) { |
1143 | indices[i] = varParameter.getName()+" % one_dim(j) % value"; |
1144 | } else if (varParameter.getEntity().equals(variable.getEntity())) { |
1145 | indices[i] = varParameter.getName()+" % two_dim(i, j) % value"; |
1146 | } |
1147 | } |
1148 | indices[parameterCount] = variable.getName()+" % two_dim(i, j) % new_value"; |
1149 | indices[parameterCount+1] = "new_frequency"; |
1150 | |
1151 | // P(variable') |
1152 | |
1153 | // DEBUG |
1154 | /* |
1155 | System.out.println("GENERATOR DEBUG: About to call getFreqCode with parameters: "); |
1156 | for (int print=0; print<indices.length; print++) |
1157 | { |
1158 | System.out.println(indices[print]); |
1159 | } |
1160 | */ |
1161 | |
1162 | ArrayList<String> toAdd=variable.getDistribution().getFreqCode(indices); |
1163 | result.addAll(toAdd); |
1164 | |
1165 | indices[parameterCount] = variable.getName()+" % two_dim(i, j) % value"; |
1166 | indices[parameterCount+1] = "frequency"; |
1167 | |
1168 | // P(variable) |
1169 | |
1170 | // DEBUG |
1171 | /* |
1172 | System.out.println("GENERATOR DEBUG: About to call getFreqCode with parameters: "); |
1173 | for (int print=0; print<indices.length; print++) |
1174 | { |
1175 | System.out.println(indices[print]); |
1176 | } |
1177 | */ |
1178 | |
1179 | toAdd=variable.getDistribution().getFreqCode(indices); |
1180 | result.addAll(toAdd); |
1181 | |
1182 | result.add("p_acc = p_acc * new_frequency / frequency"); |
1183 | |
1184 | // 2) P(x | variable') / P(x | variable) for all x that depend on variable |
1185 | |
1186 | // DEBUG |
1187 | /* |
1188 | System.out.println("GENERATOR DEBUG: Phase 2. P( depending | " + variable.getName() + |
1189 | ") / P( depending | " + variable.getName() + "')"); |
1190 | */ |
1191 | |
1192 | ArrayList<Variable> allAffected = new ArrayList<Variable>(variable.getAffectsList()); |
1193 | Set<Variable> newToBeUsed = new HashSet<Variable>(); |
1194 | newToBeUsed.add(variable); |
1195 | |
1196 | Set<Variable> handledAlready = new HashSet<Variable>(); |
1197 | |
1198 | for (int iterator = 0; iterator < allAffected.size(); iterator++) { |
1199 | Variable depending = allAffected.get(iterator); |
1200 | |
1201 | if (depending.isSpatial()) continue; |
1202 | |
1203 | // functional |
1204 | if (depending.isFunctional()) { |
1205 | // add further affeced variables to all_depending |
1206 | allAffected.addAll(depending.getAffectsList()); |
1207 | newToBeUsed.add(depending); |
1208 | continue; |
1209 | } |
1210 | |
1211 | |
1212 | if (depending.equals(variable)) continue; // no loops please |
1213 | |
1214 | if (handledAlready.contains(depending)) continue; // no duplicates |
1215 | |
1216 | // not functional |
1217 | |
1218 | // DEBUG |
1219 | /* |
1220 | System.out.println("GENERATOR DEBUG: Phase 2, in detail: P( " + depending.getName() + " | " |
1221 | + variable.getName() + ") / P( " + depending.getName() + " | " + variable.getName() + "')"); |
1222 | */ |
1223 | |
1224 | result.add(""); |
1225 | result.add("! P( " + depending.getName() + " | " |
1226 | + variable.getName() + "') / P( " + depending.getName() + " | " + variable.getName() + ")"); |
1227 | result.add(""); |
1228 | |
1229 | handledAlready.add(depending); |
1230 | |
1231 | // now variable is two-dimensional, so depending must be two-dimensional |
1232 | |
1233 | if (depending.getEntity() == null) { |
1234 | throw new InvalidModelException("Two-dimensional variable " + |
1235 | variable.getName() + " affects global variable " + depending.getName()); |
1236 | } else if (depending.getEntity().isMatrix() == false) { |
1237 | throw new InvalidModelException("Two-dimensional variable " + |
1238 | variable.getName() + " affects one-dimensional variable " + depending.getName()); |
1239 | } else if (depending.getEntity().equals(variable.getEntity()) == false) { |
1240 | throw new InvalidModelException("Variable " + |
1241 | variable.getName() + " affects " + depending.getName() + " belonging to a different entity"); |
1242 | } else { |
1243 | // depending is two-dimensional and its entity is the same as variable's |
1244 | |
1245 | result.addAll(generateLikelihoodFormulaTwoDimensional(depending, newToBeUsed, true)); |
1246 | } |
1247 | } |
1248 | |
1249 | result.addAll(generateTransitionFormula(variable)); |
1250 | |
1251 | return result; |
1252 | } |
1253 | |
1254 | private static ArrayList<String> generateLikelihoodFormulaGlobal(Variable depending, Set<Variable> newToBeUsed) |
1255 | throws IllegalParametersException, InvalidModelException, MissingFunctionException { |
1256 | |
1257 | //System.out.println("GENERATOR DEBUG: generateLikelihoodFormulaGlobal"); |
1258 | // This method returns code that calculates the likelihood of depending, when using new values of variables in newToBeUsed |
1259 | ArrayList<String> result = new ArrayList<String>(); |
1260 | String[] indices; |
1261 | int parameterCount = depending.getDistribution().getNumberOfParameters(); |
1262 | indices = new String[parameterCount+2]; |
1263 | |
1264 | for (int i=0; i<parameterCount; i++) { |
1265 | Object parameter = depending.getDistribution().getParameter(i); |
1266 | |
1267 | if (parameter instanceof Integer) { |
1268 | indices[i] = ((Integer)parameter).toString(); |
1269 | continue; |
1270 | } else if (parameter instanceof Double) { |
1271 | // we must add _dp to the real constants |
1272 | indices[i] = ((Double)parameter).toString()+"_dp"; |
1273 | continue; |
1274 | } |
1275 | // now we know that the parameter is a Variable. |
1276 | |
1277 | Variable varParameter=(Variable)parameter; |
1278 | |
1279 | if (varParameter.getEntity() != null) { |
1280 | throw new InvalidModelException("Variable " + |
1281 | varParameter.getName() + " affects variable " + depending.getName()); |
1282 | } |
1283 | |
1284 | if (newToBeUsed.contains(varParameter)) { |
1285 | indices[i] = varParameter.getName() + "% one_dim(1) % new_value"; |
1286 | } else { |
1287 | indices[i] = varParameter.getName()+" % one_dim(1) % value"; |
1288 | } |
1289 | } |
1290 | indices[parameterCount] = depending.getName()+" % one_dim(1)"; |
1291 | indices[parameterCount+1] = "new_frequency"; |
1292 | |
1293 | // P(depending | variable') |
1294 | |
1295 | // DEBUG |
1296 | /* |
1297 | System.out.println("GENERATOR DEBUG: About to call getFreqCode with parameters: "); |
1298 | for (int print=0; print<indices.length; print++) { |
1299 | System.out.println(indices[print]); |
1300 | } |
1301 | */ |
1302 | |
1303 | ArrayList<String> toAdd=depending.getDistribution().getFreqCode(indices); |
1304 | result.addAll(toAdd); |
1305 | |
1306 | for (int i=0; i<parameterCount; i++) { |
1307 | indices[i] = indices[i].replace("% new_value", "% value"); |
1308 | } |
1309 | |
1310 | indices[parameterCount+1] = "frequency"; |
1311 | |
1312 | // P(depending | variable) |
1313 | |
1314 | // DEBUG |
1315 | /* |
1316 | System.out.println("GENERATOR DEBUG: About to call getFreqCode with parameters: "); |
1317 | for (int print=0; print<indices.length; print++) { |
1318 | System.out.println(indices[print]); |
1319 | } |
1320 | */ |
1321 | |
1322 | toAdd=depending.getDistribution().getFreqCode(indices); |
1323 | result.addAll(toAdd); |
1324 | |
1325 | result.add("p_acc = p_acc * new_frequency / frequency"); |
1326 | |
1327 | return result; |
1328 | } |
1329 | |
1330 | private static ArrayList<String> generateLikelihoodFormulaOneDimensional(Variable depending, |
1331 | Set<Variable> newToBeUsed) throws IllegalParametersException, InvalidModelException, |
1332 | MissingFunctionException { |
1333 | |
1334 | //System.out.println("GENERATOR DEBUG: generateLikelihoodFormulaOneDimensional"); |
1335 | ArrayList<String> result = new ArrayList<String>(); |
1336 | String[] indices; |
1337 | int parameterCount = depending.getDistribution().getNumberOfParameters(); |
1338 | indices = new String[parameterCount+2]; |
1339 | |
1340 | for (int i=0; i<parameterCount; i++) { |
1341 | Object parameter = depending.getDistribution().getParameter(i); |
1342 | |
1343 | if (parameter instanceof Integer) { |
1344 | indices[i] = ((Integer)parameter).toString(); |
1345 | continue; |
1346 | } else if (parameter instanceof Double) { |
1347 | // we must add _dp to the real constants |
1348 | indices[i] = ((Double)parameter).toString()+"_dp"; |
1349 | continue; |
1350 | } |
1351 | // now we know that the parameter is a Variable. |
1352 | |
1353 | Variable varParameter=(Variable)parameter; |
1354 | |
1355 | boolean useNew = false; |
1356 | |
1357 | if (newToBeUsed.contains(varParameter)) useNew = true; |
1358 | |
1359 | if (varParameter.getEntity() == null) { |
1360 | if (useNew) |
1361 | indices[i] = varParameter.getName() + " % one_dim(1) % new_value"; |
1362 | else |
1363 | indices[i] = varParameter.getName() + " % one_dim(1) % value"; |
1364 | } else if (varParameter.getEntity().equals(depending.getEntity())) { |
1365 | if (useNew) |
1366 | indices[i] = varParameter.getName() + " % one_dim(i) % new_value"; |
1367 | else |
1368 | indices[i] = varParameter.getName() + " % one_dim(i) % value"; |
1369 | } |
1370 | } |
1371 | indices[parameterCount] = depending.getName()+" % one_dim(i) % value"; |
1372 | indices[parameterCount+1] = "new_frequency"; |
1373 | |
1374 | // P(depending | variable') |
1375 | |
1376 | // DEBUG |
1377 | /* |
1378 | System.out.println("GENERATOR DEBUG: About to call getFreqCode with parameters: "); |
1379 | for (int print=0; print<indices.length; print++) { |
1380 | System.out.println(indices[print]); |
1381 | } |
1382 | */ |
1383 | |
1384 | ArrayList<String> toAdd=depending.getDistribution().getFreqCode(indices); |
1385 | result.addAll(toAdd); |
1386 | |
1387 | for (int i=0; i<parameterCount; i++) { |
1388 | indices[i] = indices[i].replace("% new_value", "% value"); |
1389 | } |
1390 | indices[parameterCount+1] = "frequency"; |
1391 | |
1392 | // P(depending | variable) |
1393 | |
1394 | // DEBUG |
1395 | /* |
1396 | System.out.println("GENERATOR DEBUG: About to call getFreqCode with parameters: "); |
1397 | for (int print=0; print<indices.length; print++) { |
1398 | System.out.println(indices[print]); |
1399 | } |
1400 | */ |
1401 | |
1402 | toAdd = depending.getDistribution().getFreqCode(indices); |
1403 | result.addAll(toAdd); |
1404 | |
1405 | result.add("p_acc = p_acc * new_frequency / frequency"); |
1406 | |
1407 | return result; |
1408 | } |
1409 | |
1410 | private static ArrayList<String> generateLikelihoodFormulaTwoDimensional(Variable depending, |
1411 | Set<Variable> newToBeUsed, boolean ij) throws IllegalParametersException, |
1412 | InvalidModelException, MissingFunctionException { |
1413 | |
1414 | //System.out.println("GENERATOR DEBUG: generateLikelihoodFormulaTwoDimensional"); |
1415 | ArrayList<String> result = new ArrayList<String>(); |
1416 | String[] indices; |
1417 | int parameterCount = depending.getDistribution().getNumberOfParameters(); |
1418 | indices = new String[parameterCount+2]; |
1419 | |
1420 | for (int i=0; i<parameterCount; i++) { |
1421 | Object parameter = depending.getDistribution().getParameter(i); |
1422 | |
1423 | if (parameter instanceof Integer) { |
1424 | indices[i] = ((Integer)parameter).toString(); |
1425 | continue; |
1426 | } else if (parameter instanceof Double) { |
1427 | // we must add _dp to the real constants |
1428 | indices[i] = ((Double)parameter).toString()+"_dp"; |
1429 | continue; |
1430 | } |
1431 | // now we know that the parameter is a Variable. |
1432 | |
1433 | Variable varParameter=(Variable)parameter; |
1434 | |
1435 | boolean useNew = false; |
1436 | |
1437 | if (newToBeUsed.contains(varParameter)) { |
1438 | useNew = true; |
1439 | } |
1440 | indices[i] = varParameter.getName(); |
1441 | if (varParameter.getEntity() == null) { |
1442 | if (useNew) |
1443 | indices[i] += " % one_dim(1) % new_value"; |
1444 | else |
1445 | indices[i] += " % one_dim(1) % value"; |
1446 | } else if (varParameter.getEntity().equals(depending.getEntity().getYCoordinate())) { |
1447 | if (ij) { |
1448 | indices[i] += " % one_dim(i)"; |
1449 | } else indices[i] += " % one_dim(j)"; |
1450 | if (useNew) |
1451 | indices[i] += " % new_value"; |
1452 | else |
1453 | indices[i] += " % value"; |
1454 | } else if (varParameter.getEntity().equals(depending.getEntity().getXCoordinate())) { |
1455 | if (ij) { |
1456 | indices[i] += " % one_dim(j)"; |
1457 | } else indices[i] += " % one_dim(i)"; |
1458 | if (useNew) |
1459 | indices[i] += " % new_value"; |
1460 | else |
1461 | indices[i] += " % value"; |
1462 | } else if (varParameter.getEntity().equals(depending.getEntity())) { |
1463 | if (useNew && ij) |
1464 | indices[i] += " % two_dim(i, j) % new_value"; |
1465 | else if (useNew && !ij) |
1466 | indices[i] += " % two_dim(j, i) % new_value"; |
1467 | else if (!useNew && ij) |
1468 | indices[i] +=" % two_dim(i, j) % value"; |
1469 | else |
1470 | indices[i] +=" % two_dim(j, i) % value"; |
1471 | } |
1472 | } |
1473 | if (ij) { |
1474 | indices[parameterCount] = depending.getName()+" % two_dim(i, j) % value"; |
1475 | } else indices[parameterCount] = depending.getName()+" % two_dim(j, i) % value"; |
1476 | indices[parameterCount+1] = "new_frequency"; |
1477 | |
1478 | // P(depending | variable') |
1479 | |
1480 | // DEBUG |
1481 | /* |
1482 | System.out.println("GENERATOR DEBUG: About to call getFreqCode with parameters: "); |
1483 | for (int print=0; print<indices.length; print++) { |
1484 | System.out.println(indices[print]); |
1485 | } |
1486 | */ |
1487 | |
1488 | ArrayList<String> toAdd = depending.getDistribution().getFreqCode(indices); |
1489 | result.addAll(toAdd); |
1490 | |
1491 | // DEBUG |
1492 | /* |
1493 | System.out.println("GENERATOR DEBUG: indices is (before):"); |
1494 | for (int i=0; i<parameterCount; i++) { |
1495 | System.out.println(indices[i]); |
1496 | } |
1497 | */ |
1498 | |
1499 | for (int i=0; i<parameterCount; i++) { |
1500 | indices[i] = indices[i].replace("% new_value", "% value"); |
1501 | } |
1502 | indices[parameterCount+1] = "frequency"; |
1503 | |
1504 | // DEBUG |
1505 | /* |
1506 | System.out.println("GENERATOR DEBUG: indices is (after ):"); |
1507 | for (int i=0; i<parameterCount; i++) { |
1508 | System.out.println(indices[i]); |
1509 | } |
1510 | */ |
1511 | |
1512 | // P(depending | variable) |
1513 | |
1514 | // DEBUG |
1515 | /* |
1516 | System.out.println("GENERATOR DEBUG: About to call getFreqCode with parameters: "); |
1517 | for (int print=0; print<indices.length; print++) { |
1518 | System.out.println(indices[print]); |
1519 | } |
1520 | */ |
1521 | |
1522 | toAdd = depending.getDistribution().getFreqCode(indices); |
1523 | result.addAll(toAdd); |
1524 | |
1525 | result.add("p_acc = p_acc * new_frequency / frequency"); |
1526 | |
1527 | return result; |
1528 | } |
1529 | |
1530 | private static ArrayList<String> generateTransitionFormula(Variable variable) |
1531 | throws IllegalParametersException, InvalidModelException, MissingFunctionException { |
1532 | // DEBUG |
1533 | /* |
1534 | System.out.println("GENERATOR DEBUG: Phase 3: q( " + variable.getName() + "', " + variable.getName() + |
1535 | ") / q(" + variable.getName() + ", " + variable.getName() + "')"); |
1536 | */ |
1537 | |
1538 | ArrayList<String> result = new ArrayList<String>(); |
1539 | result.add(""); |
1540 | result.add("! q(" + variable.getName() + "', " + variable.getName() + |
1541 | ") / q(" + variable.getName() + ", " + variable.getName() + "')"); |
1542 | result.add(""); |
1543 | |
1544 | String indexing = ""; |
1545 | if (variable.getEntity() == null) { |
1546 | indexing = "one_dim(1)"; |
1547 | } else if (variable.getEntity().isMatrix() == false){ |
1548 | indexing = "one_dim(i)"; |
1549 | } else indexing = "two_dim(i, j)"; |
1550 | |
1551 | |
1552 | ArrayList<String> toAdd = new ArrayList<String>(); |
1553 | |
1554 | if (variable.getStrategy() == "random walk") { |
1555 | // random walk proposal strategy |
1556 | |
1557 | if (variable.isInteger()) { |
1558 | result.add("transition_int = " + variable.getName() + " % " + indexing + |
1559 | " % new_value - " + variable.getName() + " % " + indexing + " % value"); |
1560 | } else { |
1561 | result.add("transition_real = " + variable.getName() + " % " + indexing + |
1562 | " % new_value - " + variable.getName() + " % " + indexing +" % value"); |
1563 | } |
1564 | |
1565 | int parameterCount = variable.getProposal().getNumberOfParameters(); |
1566 | String[] indices = new String[parameterCount+2]; |
1567 | |
1568 | for (int i=0; i<parameterCount; i++) { |
1569 | Object parameter = variable.getProposal().getParameter(i); |
1570 | |
1571 | if (parameter instanceof Integer) { |
1572 | indices[i] = ((Integer)parameter).toString(); |
1573 | continue; |
1574 | } else if (parameter instanceof Double) { |
1575 | // we must add _dp to the real constants |
1576 | indices[i] = ((Double)parameter).toString()+"_dp"; |
1577 | continue; |
1578 | } else { |
1579 | throw new InvalidModelException("Error in the proposal distribution of parameter " + |
1580 | variable.getName() + ". Only constants can appear in proposal distributions."); |
1581 | } |
1582 | } |
1583 | |
1584 | if (variable.isInteger()) { |
1585 | indices[parameterCount] = "-transition_int"; |
1586 | } else { |
1587 | indices[parameterCount] = "-transition_real"; |
1588 | } |
1589 | indices[parameterCount+1] = "frequency"; |
1590 | |
1591 | // DEBUG |
1592 | /* |
1593 | System.out.println("GENERATOR DEBUG: About to call getFreqCode with parameters: "); |
1594 | for (int print=0; print<indices.length; print++) { |
1595 | System.out.println(indices[print]); |
1596 | } |
1597 | */ |
1598 | |
1599 | toAdd = variable.getProposal().getFreqCode(indices); |
1600 | result.addAll(toAdd); |
1601 | |
1602 | if (variable.isInteger()) { |
1603 | indices[parameterCount] = "transition_int"; |
1604 | } else { |
1605 | indices[parameterCount] = "transition_real"; |
1606 | } |
1607 | indices[parameterCount+1] = "new_frequency"; |
1608 | |
1609 | |
1610 | // DEBUG |
1611 | /* |
1612 | System.out.println("GENERATOR DEBUG: About to call getFreqCode with parameters: "); |
1613 | for (int print=0; print<indices.length; print++) |
1614 | { |
1615 | System.out.println(indices[print]); |
1616 | } |
1617 | */ |
1618 | |
1619 | toAdd = variable.getProposal().getFreqCode(indices); |
1620 | result.addAll(toAdd); |
1621 | |
1622 | result.add("p_acc = p_acc * frequency / new_frequency"); |
1623 | } else { |
1624 | // fixed proposal strategy |
1625 | |
1626 | int parameterCount = variable.getProposal().getNumberOfParameters(); |
1627 | String[] indices = new String[parameterCount+2]; |
1628 | |
1629 | for (int i=0; i<parameterCount; i++) { |
1630 | Object parameter = variable.getProposal().getParameter(i); |
1631 | |
1632 | if (parameter instanceof Integer) { |
1633 | indices[i] = ((Integer)parameter).toString(); |
1634 | continue; |
1635 | } else if (parameter instanceof Double) { |
1636 | // we must add _dp to the real constants |
1637 | indices[i] = ((Double)parameter).toString()+"_dp"; |
1638 | continue; |
1639 | } |
1640 | } |
1641 | |
1642 | indices[parameterCount] = variable.getName() + " % " + indexing +" % value"; |
1643 | |
1644 | indices[parameterCount+1] = "frequency"; |
1645 | |
1646 | // DEBUG |
1647 | /* |
1648 | System.out.println("GENERATOR DEBUG: About to call getFreqCode with parameters: "); |
1649 | for (int print=0; print<indices.length; print++) { |
1650 | System.out.println(indices[print]); |
1651 | } |
1652 | */ |
1653 | |
1654 | toAdd = variable.getProposal().getFreqCode(indices); |
1655 | result.addAll(toAdd); |
1656 | indices[parameterCount] = variable.getName() + " % " + indexing +" % new_value"; |
1657 | indices[parameterCount+1] = "new_frequency"; |
1658 | |
1659 | // DEBUG |
1660 | /* |
1661 | System.out.println("GENERATOR DEBUG: About to call getFreqCode with parameters: "); |
1662 | for (int print=0; print<indices.length; print++) { |
1663 | System.out.println(indices[print]); |
1664 | } |
1665 | */ |
1666 | |
1667 | toAdd = variable.getProposal().getFreqCode(indices); |
1668 | result.addAll(toAdd); |
1669 | |
1670 | result.add("p_acc = p_acc * frequency / new_frequency"); |
1671 | } |
1672 | |
1673 | return result; |
1674 | } |
1675 | } |
1676 | |