00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 #include "soarkernel.h"
00052 #include "soar_ecore_api.h"
00053 #include "explain.h"
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 void init_explain(void)
00076 {
00077
00078
00079
00080 current_agent(explain_chunk_name[0]) = '\0';
00081 current_agent(explain_chunk_list) = NULL;
00082 current_agent(explain_backtrace_list) = NULL;
00083
00084
00085
00086
00087 set_sysparam(EXPLAIN_SYSPARAM, FALSE);
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 }
00098
00099
00100
00101
00102
00103 void free_backtrace_list(backtrace_str * prod)
00104 {
00105
00106 backtrace_str *next_prod;
00107
00108 while (prod != NULL) {
00109 next_prod = prod->next_backtrace;
00110 deallocate_condition_list(prod->trace_cond);
00111 deallocate_condition_list(prod->grounds);
00112 deallocate_condition_list(prod->potentials);
00113 deallocate_condition_list(prod->locals);
00114 deallocate_condition_list(prod->negated);
00115 free((void *) prod);
00116 prod = next_prod;
00117 }
00118 }
00119
00120
00121
00122
00123
00124 void reset_backtrace_list(void)
00125 {
00126
00127 free_backtrace_list(current_agent(explain_backtrace_list));
00128 current_agent(explain_backtrace_list) = NULL;
00129
00130
00131 }
00132
00133
00134
00135
00136
00137 condition *copy_cond_list(condition * top_list)
00138 {
00139
00140 condition *new_top, *new_bottom;
00141
00142 copy_condition_list(top_list, &new_top, &new_bottom);
00143 return (new_top);
00144 }
00145
00146
00147
00148
00149
00150 condition *copy_conds_from_list(cons * top_list)
00151 {
00152
00153 condition *top, *cond, *prev, *next;
00154 cons *cc;
00155
00156 prev = next = top = NIL;
00157
00158 for (cc = top_list; cc != NIL; cc = cc->rest) {
00159 cond = copy_condition(cc->first);
00160 cond->prev = prev;
00161 cond->next = NIL;
00162
00163 if (prev == NIL)
00164 top = cond;
00165 else
00166 prev->next = cond;
00167
00168 prev = cond;
00169 }
00170 return (top);
00171 }
00172
00173
00174
00175
00176
00177 void explain_add_temp_to_backtrace_list
00178 (backtrace_str * temp, cons * grounds, cons * pots, cons * locals, cons * negateds) {
00179
00180 backtrace_str *back;
00181
00182 back = (backtrace_str *) malloc(sizeof(backtrace_str));
00183 back->result = temp->result;
00184 back->trace_cond = copy_condition(temp->trace_cond);
00185 if (back->trace_cond != NULL)
00186 back->trace_cond->next = NULL;
00187 strncpy(back->prod_name, temp->prod_name, PROD_NAME_SIZE);
00188 back->prod_name[PROD_NAME_SIZE - 1] = 0;
00189
00190 back->grounds = copy_conds_from_list(grounds);
00191 back->potentials = copy_conds_from_list(pots);
00192 back->locals = copy_conds_from_list(locals);
00193 back->negated = copy_conds_from_list(negateds);
00194
00195 back->next_backtrace = current_agent(explain_backtrace_list);
00196 current_agent(explain_backtrace_list) = back;
00197
00198
00199 }
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 void explain_add_temp_to_chunk_list(explain_chunk_str * temp)
00213 {
00214
00215 explain_chunk_str *chunk;
00216
00217 chunk = (explain_chunk_str *) malloc(sizeof(explain_chunk_str));
00218 chunk->conds = temp->conds;
00219 chunk->actions = temp->actions;
00220 strncpy(chunk->name, temp->name, PROD_NAME_SIZE);
00221 chunk->name[PROD_NAME_SIZE - 1] = 0;
00222
00223 chunk->backtrace = current_agent(explain_backtrace_list);
00224 current_agent(explain_backtrace_list) = NULL;
00225
00226
00227 chunk->all_grounds = copy_cond_list(temp->all_grounds);
00228
00229 chunk->next_chunk = current_agent(explain_chunk_list);
00230 current_agent(explain_chunk_list) = chunk;
00231
00232
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242 void free_explain_chunk(explain_chunk_str * chunk)
00243 {
00244
00245
00246 free_backtrace_list(chunk->backtrace);
00247
00248 deallocate_condition_list(chunk->conds);
00249 deallocate_action_list(chunk->actions);
00250 deallocate_condition_list(chunk->all_grounds);
00251
00252
00253 free((void *) chunk);
00254 }
00255
00256
00257
00258
00259
00260 void reset_explain(void)
00261 {
00262
00263 explain_chunk_str *top, *chunk;
00264
00265 top = current_agent(explain_chunk_list);
00266
00267
00268 while (top != NULL) {
00269 chunk = top;
00270 top = top->next_chunk;
00271 free_explain_chunk(chunk);
00272 }
00273
00274 current_agent(explain_chunk_list) = NULL;
00275
00276
00277 reset_backtrace_list();
00278 }
00279
00280
00281
00282
00283
00284
00285
00286 explain_chunk_str *find_chunk(explain_chunk_str * chunk, char *name)
00287 {
00288
00289 while (chunk != NULL) {
00290 if (strcmp(chunk->name, name) == 0)
00291 return (chunk);
00292 chunk = chunk->next_chunk;
00293 }
00294
00295 print("Could not find the chunk. Maybe explain was not on when it was created.");
00296
00297 print("\nFor Soar 7: set save_backtraces 1 before the chunk is created.\n");
00298
00299 return (NULL);
00300 }
00301
00302
00303
00304
00305
00306
00307 condition *find_ground(explain_chunk_str * chunk, int number)
00308 {
00309
00310 condition *ground, *cond;
00311
00312 ground = NIL;
00313 for (cond = chunk->all_grounds; cond != NIL; cond = cond->next) {
00314 number--;
00315 if (number == 0)
00316 ground = cond;
00317 }
00318 if (number > 0) {
00319 print("Could not find this condition.\n");
00320 return (NIL);
00321 }
00322 return (ground);
00323 }
00324
00325
00326
00327
00328
00329 void explain_trace_chunk(explain_chunk_str * chunk)
00330 {
00331
00332 backtrace_str *prod;
00333
00334 print("Chunk : %s\n", chunk->name);
00335 prod = chunk->backtrace;
00336 while (prod != NULL) {
00337 print("Backtrace production : %s\n", prod->prod_name);
00338 print("Result : %d\n", prod->result);
00339 if (prod->trace_cond != NULL) {
00340 print("Trace condition : ");
00341 print_condition(prod->trace_cond);
00342 } else
00343 print("The result preference is not stored, sorry.\n");
00344 print_string("\nGrounds:\n");
00345 print_list_of_conditions(prod->grounds);
00346 print_string("\nPotentials:\n");
00347 print_list_of_conditions(prod->potentials);
00348 print_string("\nLocals:\n");
00349 print_list_of_conditions(prod->locals);
00350 print_string("\nNegateds:\n");
00351 print_list_of_conditions(prod->negated);
00352 prod = prod->next_backtrace;
00353 print("\n\n");
00354 }
00355 }
00356
00357
00358
00359
00360
00361
00362 condition *explain_find_cond(condition * target, condition * cond_list)
00363 {
00364
00365 condition *cond, *match;
00366
00367 match = NULL;
00368 for (cond = cond_list; cond != NULL; cond = cond->next) {
00369 if (conditions_are_equal(target, cond))
00370 match = cond;
00371 }
00372 return (match);
00373 }
00374
00375
00376
00377
00378
00379
00380
00381 void explain_trace(char *chunk_name, backtrace_str * prod_list, condition * ground)
00382 {
00383
00384 int count;
00385 condition *match, *target;
00386 backtrace_str *prod;
00387
00388
00389
00390
00391
00392
00393 prod = prod_list;
00394 match = NULL;
00395 while (prod != NULL && match == NULL) {
00396 match = explain_find_cond(ground, prod->potentials);
00397 if (match == NULL)
00398 match = explain_find_cond(ground, prod->grounds);
00399 if (match == NULL)
00400 match = explain_find_cond(ground, prod->negated);
00401 if (match == NULL)
00402 prod = prod->next_backtrace;
00403 }
00404
00405 if (match == NULL) {
00406 print("EXPLAIN: Error, couldn't find the ground condition\n");
00407 return;
00408 }
00409
00410 print("Explanation of why condition ");
00411 print_condition(ground);
00412 print(" was included in %s\n\n", chunk_name);
00413
00414 print("Production %s matched\n ", prod->prod_name);
00415 print_condition(match);
00416 print(" which caused\n");
00417
00418
00419
00420
00421
00422
00423
00424
00425 target = prod->trace_cond;
00426 count = 0;
00427
00428 while (prod->result == FALSE && count < 50 && match != NULL) {
00429 prod = prod_list;
00430 match = NULL;
00431 count++;
00432 while (prod != NULL && match == NULL) {
00433 match = explain_find_cond(target, prod->locals);
00434
00435 if (match == NULL)
00436 match = explain_find_cond(target, prod->negated);
00437 if (match == NULL)
00438 match = explain_find_cond(target, prod->potentials);
00439 if (match == NULL)
00440 match = explain_find_cond(target, prod->grounds);
00441 if (match == NULL)
00442 prod = prod->next_backtrace;
00443 }
00444
00445 if (match == NULL) {
00446 print("EXPLAIN : Unable to find which production matched condition ");
00447 print_condition(target);
00448 print("\nTo help understand what happened here and help debug this\n");
00449 print("here is all of the backtracing information stored for this chunk.\n");
00450 print("\n");
00451 soar_ecExplainChunkTrace(chunk_name);
00452 } else {
00453 print("production %s to match\n ", prod->prod_name);
00454 print_condition(match);
00455 print(" which caused\n");
00456 target = prod->trace_cond;
00457 }
00458 }
00459
00460 if (prod->result == TRUE)
00461 print("A result to be generated.\n");
00462 if (count >= 50)
00463 print("EXPLAIN: Exceeded 50 productions traced through, so terminating now.\n");
00464 }
00465
00466
00467
00468
00469
00470 void explain_list_chunks(void)
00471 {
00472
00473 explain_chunk_str *chunk;
00474
00475 chunk = current_agent(explain_chunk_list);
00476
00477
00478 if (!chunk)
00479 print("No chunks/justifications built yet!\n");
00480 else {
00481 print("List of all explained chunks/justifications:\n");
00482 while (chunk != NULL) {
00483 print("Have explanation for %s\n", chunk->name);
00484 chunk = chunk->next_chunk;
00485 }
00486 }
00487 }
00488
00489
00490
00491
00492
00493 void explain_full_trace(void)
00494 {
00495
00496 explain_chunk_str *chunk;
00497
00498 chunk = current_agent(explain_chunk_list);
00499
00500
00501 while (chunk != NULL) {
00502 explain_trace_chunk(chunk);
00503 chunk = chunk->next_chunk;
00504 }
00505 }