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
00052
00053
00054
00055
00056
00057 #include "soarkernel.h"
00058 #include "soarapi_datatypes.h"
00059 #include <assert.h>
00060 #include <math.h>
00061 #include <time.h>
00062
00063 #ifdef NUMERIC_INDIFFERENCE
00064
00065 preference *probabilistically_select(slot * s, preference * candidates);
00066
00067
00068
00069 void print_candidates(preference * candidates)
00070 {
00071 preference *cand = 0;
00072 int max_count = 0;
00073
00074 for (cand = candidates; cand != NIL; cand = cand->next_candidate) {
00075 max_count++;
00076 print("\n Candidate %d", cand);
00077 print_with_symbols("\n %y %y %y", cand->id, cand->attr, cand->value);
00078 if (max_count > 10)
00079 break;
00080 }
00081 }
00082
00083
00084
00085 #endif
00086
00087 extern void soar_ecGDSPrint();
00088
00089 void remove_existing_attribute_impasse_for_slot(slot * s);
00090 void post_link_addition(Symbol * from, Symbol * to);
00091 void post_link_removal(Symbol * from, Symbol * to);
00092
00093
00094 void elaborate_gds(void);
00095 void gds_invalid_so_remove_goal(wme * w);
00096 void free_parent_list(void);
00097 void uniquely_add_to_head_of_dll(instantiation * inst);
00098 void create_gds_for_goal(Symbol * goal);
00099 extern void remove_operator_if_necessary(slot * s, wme * w);
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 #define NOTHING_DECIDER_FLAG 0
00141 #define CANDIDATE_DECIDER_FLAG 1
00142 #define CONFLICTED_DECIDER_FLAG 2
00143 #define FORMER_CANDIDATE_DECIDER_FLAG 3
00144 #define BEST_DECIDER_FLAG 4
00145 #define WORST_DECIDER_FLAG 5
00146 #define UNARY_INDIFFERENT_DECIDER_FLAG 6
00147 #define ALREADY_EXISTING_WME_DECIDER_FLAG 7
00148 #define UNARY_PARALLEL_DECIDER_FLAG 8
00149
00150
00151
00152 #define UNARY_INDIFFERENT_CONSTANT_DECIDER_FLAG 9
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 void mark_context_slot_as_acceptable_preference_changed(slot * s)
00167 {
00168 dl_cons *dc;
00169
00170 if (s->acceptable_preference_changed)
00171 return;
00172 allocate_with_pool(¤t_agent(dl_cons_pool), &dc);
00173 dc->item = s;
00174 s->acceptable_preference_changed = dc;
00175 insert_at_head_of_dll(current_agent(context_slots_with_changed_acceptable_preferences), dc, next, prev);
00176 }
00177
00178
00179 void do_acceptable_preference_wme_changes_for_slot(slot * s)
00180 {
00181 wme *w, *next_w;
00182 preference *p;
00183
00184
00185 for (w = s->acceptable_preference_wmes; w != NIL; w = w->next)
00186 w->value->common.decider_flag = NOTHING_DECIDER_FLAG;
00187
00188
00189 for (p = s->preferences[REQUIRE_PREFERENCE_TYPE]; p != NIL; p = p->next)
00190 p->value->common.decider_flag = CANDIDATE_DECIDER_FLAG;
00191 for (p = s->preferences[ACCEPTABLE_PREFERENCE_TYPE]; p != NIL; p = p->next)
00192 p->value->common.decider_flag = CANDIDATE_DECIDER_FLAG;
00193
00194
00195
00196
00197 w = s->acceptable_preference_wmes;
00198 while (w) {
00199 next_w = w->next;
00200 if (w->value->common.decider_flag == CANDIDATE_DECIDER_FLAG) {
00201 w->value->common.decider_flag = ALREADY_EXISTING_WME_DECIDER_FLAG;
00202 w->value->common.a.decider_wme = w;
00203 w->preference = NIL;
00204 } else {
00205 remove_from_dll(s->acceptable_preference_wmes, w, next, prev);
00206
00207
00208
00209
00210
00211
00212
00213 #ifndef SOAR_8_ONLY
00214 if (current_agent(operand2_mode))
00215 #endif
00216 remove_operator_if_necessary(s, w);
00217
00218 remove_wme_from_wm(w);
00219 }
00220 w = next_w;
00221 }
00222
00223
00224
00225 for (p = s->preferences[REQUIRE_PREFERENCE_TYPE]; p != NIL; p = p->next) {
00226 if (p->value->common.decider_flag == ALREADY_EXISTING_WME_DECIDER_FLAG) {
00227
00228 w = p->value->common.a.decider_wme;
00229 if (!w->preference)
00230 w->preference = p;
00231 } else {
00232 w = make_wme(p->id, p->attr, p->value, TRUE);
00233 insert_at_head_of_dll(s->acceptable_preference_wmes, w, next, prev);
00234 w->preference = p;
00235 add_wme_to_wm(w);
00236 p->value->common.decider_flag = ALREADY_EXISTING_WME_DECIDER_FLAG;
00237 p->value->common.a.decider_wme = w;
00238 }
00239 }
00240 for (p = s->preferences[ACCEPTABLE_PREFERENCE_TYPE]; p != NIL; p = p->next) {
00241 if (p->value->common.decider_flag == ALREADY_EXISTING_WME_DECIDER_FLAG) {
00242
00243 w = p->value->common.a.decider_wme;
00244 if (!w->preference)
00245 w->preference = p;
00246 } else {
00247 w = make_wme(p->id, p->attr, p->value, TRUE);
00248 insert_at_head_of_dll(s->acceptable_preference_wmes, w, next, prev);
00249 w->preference = p;
00250 add_wme_to_wm(w);
00251 p->value->common.decider_flag = ALREADY_EXISTING_WME_DECIDER_FLAG;
00252 p->value->common.a.decider_wme = w;
00253 }
00254 }
00255 }
00256
00257 void do_buffered_acceptable_preference_wme_changes(void)
00258 {
00259 dl_cons *dc;
00260 slot *s;
00261
00262 while (current_agent(context_slots_with_changed_acceptable_preferences)) {
00263 dc = current_agent(context_slots_with_changed_acceptable_preferences);
00264 current_agent(context_slots_with_changed_acceptable_preferences) = dc->next;
00265 s = dc->item;
00266 free_with_pool(¤t_agent(dl_cons_pool), dc);
00267 do_acceptable_preference_wme_changes_for_slot(s);
00268 s->acceptable_preference_changed = NIL;
00269 }
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 void post_link_addition(Symbol * from, Symbol * to)
00314 {
00315
00316
00317
00318 if ((to->id.isa_goal || to->id.isa_impasse) && from)
00319 return;
00320
00321 to->id.link_count++;
00322
00323 #ifdef DEBUG_LINKS
00324 if (from)
00325 print_with_symbols("\nAdding link from %y to %y", from, to);
00326 else
00327 print_with_symbols("\nAdding special link to %y", to);
00328 print(" (count=%lu)", to->id.link_count);
00329 #endif
00330
00331 if (!from)
00332 return;
00333
00334
00335 if (from->id.promotion_level == to->id.promotion_level)
00336 return;
00337
00338
00339 if (from->id.promotion_level > to->id.promotion_level) {
00340 to->id.could_be_a_link_from_below = TRUE;
00341 return;
00342 }
00343
00344
00345 to->id.promotion_level = from->id.promotion_level;
00346 symbol_add_ref(to);
00347 push(to, current_agent(promoted_ids));
00348 }
00349
00350
00351
00352
00353
00354 #define promote_if_needed(sym) \
00355 { if ((sym)->common.symbol_type==IDENTIFIER_SYMBOL_TYPE) \
00356 promote_id_and_tc(sym,new_level); }
00357
00358 void promote_id_and_tc(Symbol * id, goal_stack_level new_level)
00359 {
00360 slot *s;
00361 preference *pref;
00362 wme *w;
00363
00364
00365 if (id->id.level <= new_level)
00366 return;
00367 if (id->id.promotion_level < new_level)
00368 return;
00369
00370
00371 id->id.level = new_level;
00372 id->id.promotion_level = new_level;
00373 id->id.could_be_a_link_from_below = TRUE;
00374
00375
00376 if (id->id.isa_goal || id->id.isa_impasse) {
00377 char msg[MESSAGE_SIZE];
00378 strncpy(msg, "decide.c: Internal error: tried to promote a goal or impasse id\n", MESSAGE_SIZE);
00379 msg[MESSAGE_SIZE - 1] = 0;
00380 abort_with_fatal_error(msg);
00381
00382
00383 }
00384
00385
00386 for (w = id->id.input_wmes; w != NIL; w = w->next)
00387 promote_if_needed(w->value);
00388 for (s = id->id.slots; s != NIL; s = s->next) {
00389 for (pref = s->all_preferences; pref != NIL; pref = pref->all_of_slot_next) {
00390 promote_if_needed(pref->value);
00391 if (preference_is_binary(pref->type))
00392 promote_if_needed(pref->referent);
00393 }
00394 for (w = s->wmes; w != NIL; w = w->next)
00395 promote_if_needed(w->value);
00396 }
00397 }
00398
00399
00400
00401
00402
00403 void do_promotion(void)
00404 {
00405 cons *c;
00406 Symbol *to;
00407
00408 while (current_agent(promoted_ids)) {
00409 c = current_agent(promoted_ids);
00410 to = c->first;
00411 current_agent(promoted_ids) = current_agent(promoted_ids)->rest;
00412 free_cons(c);
00413 promote_id_and_tc(to, to->id.promotion_level);
00414 symbol_remove_ref(to);
00415 }
00416 }
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 void post_link_removal(Symbol * from, Symbol * to)
00454 {
00455 dl_cons *dc;
00456
00457
00458
00459 if ((to->id.isa_goal || to->id.isa_impasse) && from)
00460 return;
00461
00462 to->id.link_count--;
00463
00464 #ifdef DEBUG_LINKS
00465 if (from) {
00466 print_with_symbols("\nRemoving link from %y to %y", from, to);
00467 print(" (%d to %d)", from->id.level, to->id.level);
00468 } else {
00469 print_with_symbols("\nRemoving special link to %y ", to);
00470 print(" (%d)", to->id.level);
00471 }
00472 print(" (count=%lu)", to->id.link_count);
00473 #endif
00474
00475
00476 if (current_agent(link_update_mode) == JUST_UPDATE_COUNT)
00477 return;
00478
00479 if ((current_agent(link_update_mode) == UPDATE_DISCONNECTED_IDS_LIST) && (to->id.link_count == 0)) {
00480 if (to->id.unknown_level) {
00481 dc = to->id.unknown_level;
00482 remove_from_dll(current_agent(ids_with_unknown_level), dc, next, prev);
00483 insert_at_head_of_dll(current_agent(disconnected_ids), dc, next, prev);
00484 } else {
00485 symbol_add_ref(to);
00486 allocate_with_pool(¤t_agent(dl_cons_pool), &dc);
00487 dc->item = to;
00488 to->id.unknown_level = dc;
00489 insert_at_head_of_dll(current_agent(disconnected_ids), dc, next, prev);
00490 }
00491 return;
00492 }
00493
00494
00495
00496 if (from && (from->id.level != to->id.level))
00497 return;
00498
00499 if (!to->id.unknown_level) {
00500 symbol_add_ref(to);
00501 allocate_with_pool(¤t_agent(dl_cons_pool), &dc);
00502 dc->item = to;
00503 to->id.unknown_level = dc;
00504 insert_at_head_of_dll(current_agent(ids_with_unknown_level), dc, next, prev);
00505 }
00506 }
00507
00508
00509
00510
00511
00512
00513
00514 void garbage_collect_id(Symbol * id)
00515 {
00516 slot *s;
00517 preference *pref, *next_pref;
00518
00519 #ifdef DEBUG_LINKS
00520 print_with_symbols("\n*** Garbage collecting id: %y", id);
00521 #endif
00522
00523
00524
00525
00526
00527 remove_wme_list_from_wm(id->id.input_wmes);
00528 id->id.input_wmes = NIL;
00529
00530 for (s = id->id.slots; s != NIL; s = s->next) {
00531
00532 if (s->impasse_type != NONE_IMPASSE_TYPE)
00533 remove_existing_attribute_impasse_for_slot(s);
00534
00535 remove_wme_list_from_wm(s->wmes);
00536 s->wmes = NIL;
00537
00538 pref = s->all_preferences;
00539 while (pref) {
00540 next_pref = pref->all_of_slot_next;
00541 remove_preference_from_tm(pref);
00542
00543
00544 pref = next_pref;
00545 }
00546 mark_slot_for_possible_removal(s);
00547 }
00548 }
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569 #define mark_unknown_level_if_needed(sym) \
00570 { if ((sym)->common.symbol_type==IDENTIFIER_SYMBOL_TYPE) \
00571 mark_id_and_tc_as_unknown_level(sym); }
00572
00573 void mark_id_and_tc_as_unknown_level(Symbol * id)
00574 {
00575 slot *s;
00576 preference *pref;
00577 wme *w;
00578 dl_cons *dc;
00579
00580
00581 if (id->id.tc_num == current_agent(mark_tc_number))
00582 return;
00583
00584
00585
00586 if (id->id.level < current_agent(level_at_which_marking_started))
00587 return;
00588
00589
00590 id->id.tc_num = current_agent(mark_tc_number);
00591
00592
00593 if (id->id.level < current_agent(highest_level_anything_could_fall_from))
00594 current_agent(highest_level_anything_could_fall_from) = id->id.level;
00595 if (id->id.level > current_agent(lowest_level_anything_could_fall_to))
00596 current_agent(lowest_level_anything_could_fall_to) = id->id.level;
00597 if (id->id.could_be_a_link_from_below)
00598 current_agent(lowest_level_anything_could_fall_to) = LOWEST_POSSIBLE_GOAL_LEVEL;
00599
00600
00601 if (!id->id.unknown_level) {
00602 allocate_with_pool(¤t_agent(dl_cons_pool), &dc);
00603 dc->item = id;
00604 id->id.unknown_level = dc;
00605 insert_at_head_of_dll(current_agent(ids_with_unknown_level), dc, next, prev);
00606 symbol_add_ref(id);
00607 }
00608
00609
00610 for (w = id->id.input_wmes; w != NIL; w = w->next)
00611 mark_unknown_level_if_needed(w->value);
00612 for (s = id->id.slots; s != NIL; s = s->next) {
00613 for (pref = s->all_preferences; pref != NIL; pref = pref->all_of_slot_next) {
00614 mark_unknown_level_if_needed(pref->value);
00615 if (preference_is_binary(pref->type))
00616 mark_unknown_level_if_needed(pref->referent);
00617 }
00618 if (s->impasse_id)
00619 mark_unknown_level_if_needed(s->impasse_id);
00620 for (w = s->wmes; w != NIL; w = w->next)
00621 mark_unknown_level_if_needed(w->value);
00622 }
00623 }
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634 #define update_levels_if_needed(sym) \
00635 { if ((sym)->common.symbol_type==IDENTIFIER_SYMBOL_TYPE) \
00636 if ((sym)->id.tc_num!=current_agent(walk_tc_number)) \
00637 walk_and_update_levels(sym); }
00638
00639 void walk_and_update_levels(Symbol * id)
00640 {
00641 slot *s;
00642 preference *pref;
00643 wme *w;
00644 dl_cons *dc;
00645
00646
00647 id->id.tc_num = current_agent(walk_tc_number);
00648
00649
00650 if ((!id->id.unknown_level) && (id->id.level < current_agent(walk_level)))
00651 return;
00652
00653
00654 if (id->id.unknown_level) {
00655 dc = id->id.unknown_level;
00656 remove_from_dll(current_agent(ids_with_unknown_level), dc, next, prev);
00657 free_with_pool(¤t_agent(dl_cons_pool), dc);
00658 symbol_remove_ref(id);
00659 id->id.unknown_level = NIL;
00660 id->id.level = current_agent(walk_level);
00661 id->id.promotion_level = current_agent(walk_level);
00662 }
00663
00664
00665 for (w = id->id.input_wmes; w != NIL; w = w->next)
00666 update_levels_if_needed(w->value);
00667 for (s = id->id.slots; s != NIL; s = s->next) {
00668 for (pref = s->all_preferences; pref != NIL; pref = pref->all_of_slot_next) {
00669 update_levels_if_needed(pref->value);
00670 if (preference_is_binary(pref->type))
00671 update_levels_if_needed(pref->referent);
00672 }
00673 if (s->impasse_id)
00674 update_levels_if_needed(s->impasse_id);
00675 for (w = s->wmes; w != NIL; w = w->next)
00676 update_levels_if_needed(w->value);
00677 }
00678 }
00679
00680
00681
00682
00683
00684 void do_demotion(void)
00685 {
00686 Symbol *g, *id;
00687 dl_cons *dc, *next_dc;
00688
00689
00690
00691 for (dc = current_agent(ids_with_unknown_level); dc != NIL; dc = next_dc) {
00692 next_dc = dc->next;
00693 id = dc->item;
00694 if (id->id.link_count == 0) {
00695 remove_from_dll(current_agent(ids_with_unknown_level), dc, next, prev);
00696 insert_at_head_of_dll(current_agent(disconnected_ids), dc, next, prev);
00697 }
00698 }
00699
00700
00701 current_agent(link_update_mode) = UPDATE_DISCONNECTED_IDS_LIST;
00702 while (current_agent(disconnected_ids)) {
00703 dc = current_agent(disconnected_ids);
00704 current_agent(disconnected_ids) = current_agent(disconnected_ids)->next;
00705 id = dc->item;
00706 free_with_pool(¤t_agent(dl_cons_pool), dc);
00707 garbage_collect_id(id);
00708 symbol_remove_ref(id);
00709 }
00710 current_agent(link_update_mode) = UPDATE_LINKS_NORMALLY;
00711
00712
00713 if (!current_agent(ids_with_unknown_level))
00714 return;
00715
00716
00717 current_agent(highest_level_anything_could_fall_from) = LOWEST_POSSIBLE_GOAL_LEVEL;
00718 current_agent(lowest_level_anything_could_fall_to) = -1;
00719 current_agent(mark_tc_number) = get_new_tc_number();
00720 for (dc = current_agent(ids_with_unknown_level); dc != NIL; dc = dc->next) {
00721 id = dc->item;
00722 current_agent(level_at_which_marking_started) = id->id.level;
00723 mark_id_and_tc_as_unknown_level(id);
00724 }
00725
00726
00727 g = current_agent(top_goal);
00728 for (;;) {
00729 if (!g)
00730 break;
00731 if (g->id.level > current_agent(lowest_level_anything_could_fall_to))
00732 break;
00733 if (g->id.level >= current_agent(highest_level_anything_could_fall_from)) {
00734 current_agent(walk_level) = g->id.level;
00735 current_agent(walk_tc_number) = get_new_tc_number();
00736 walk_and_update_levels(g);
00737 }
00738 g = g->id.lower_goal;
00739 }
00740
00741
00742 current_agent(link_update_mode) = JUST_UPDATE_COUNT;
00743 while (current_agent(ids_with_unknown_level)) {
00744 dc = current_agent(ids_with_unknown_level);
00745 current_agent(ids_with_unknown_level) = current_agent(ids_with_unknown_level)->next;
00746 id = dc->item;
00747 free_with_pool(¤t_agent(dl_cons_pool), dc);
00748 id->id.unknown_level = NIL;
00749
00750 garbage_collect_id(id);
00751 symbol_remove_ref(id);
00752 }
00753 current_agent(link_update_mode) = UPDATE_LINKS_NORMALLY;
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764 void do_buffered_link_changes(void)
00765 {
00766
00767 #ifndef NO_TIMING_STUFF
00768 #ifdef DETAILED_TIMING_STATS
00769 struct timeval saved_start_tv;
00770 #endif
00771 #endif
00772
00773
00774 if (!(current_agent(promoted_ids) || current_agent(ids_with_unknown_level) || current_agent(disconnected_ids)))
00775 return;
00776
00777 #ifndef NO_TIMING_STUFF
00778 #ifdef DETAILED_TIMING_STATS
00779 start_timer(&saved_start_tv);
00780 #endif
00781 #endif
00782 do_promotion();
00783 do_demotion();
00784 #ifndef NO_TIMING_STUFF
00785 #ifdef DETAILED_TIMING_STATS
00786 stop_timer(&saved_start_tv, ¤t_agent(ownership_cpu_time[current_agent(current_phase)]));
00787 #endif
00788 #endif
00789 }
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823 byte require_preference_semantics(slot * s, preference ** result_candidates)
00824 {
00825 preference *p;
00826 preference *candidates;
00827 Symbol *value;
00828
00829
00830 for (p = s->preferences[REQUIRE_PREFERENCE_TYPE]; p != NIL; p = p->next)
00831 p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
00832 candidates = NIL;
00833 for (p = s->preferences[REQUIRE_PREFERENCE_TYPE]; p != NIL; p = p->next) {
00834 if (p->value->common.decider_flag == NOTHING_DECIDER_FLAG) {
00835 p->next_candidate = candidates;
00836 candidates = p;
00837
00838 p->value->common.decider_flag = CANDIDATE_DECIDER_FLAG;
00839 }
00840 }
00841 *result_candidates = candidates;
00842
00843
00844 if (candidates->next_candidate)
00845 return CONSTRAINT_FAILURE_IMPASSE_TYPE;
00846
00847
00848 value = candidates->value;
00849 for (p = s->preferences[PROHIBIT_PREFERENCE_TYPE]; p != NIL; p = p->next)
00850 if (p->value == value)
00851 return CONSTRAINT_FAILURE_IMPASSE_TYPE;
00852
00853
00854 return NONE_IMPASSE_TYPE;
00855 }
00856
00857 byte run_preference_semantics(slot * s, preference ** result_candidates)
00858 {
00859 preference *p, *p2, *cand, *prev_cand;
00860 bool match_found, not_all_indifferent, not_all_parallel;
00861 preference *candidates;
00862
00863
00864 if (!s->all_preferences) {
00865 if (!s->isa_context_slot)
00866 mark_slot_for_possible_removal(s);
00867 *result_candidates = NIL;
00868 return NONE_IMPASSE_TYPE;
00869 }
00870
00871
00872 if (s->preferences[REQUIRE_PREFERENCE_TYPE]) {
00873 return require_preference_semantics(s, result_candidates);
00874 }
00875
00876
00877
00878
00879
00880 for (p = s->preferences[ACCEPTABLE_PREFERENCE_TYPE]; p != NIL; p = p->next)
00881 p->value->common.decider_flag = CANDIDATE_DECIDER_FLAG;
00882 for (p = s->preferences[PROHIBIT_PREFERENCE_TYPE]; p != NIL; p = p->next)
00883 p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
00884 for (p = s->preferences[REJECT_PREFERENCE_TYPE]; p != NIL; p = p->next)
00885 p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
00886
00887
00888 candidates = NIL;
00889 for (p = s->preferences[ACCEPTABLE_PREFERENCE_TYPE]; p != NIL; p = p->next) {
00890 if (p->value->common.decider_flag == CANDIDATE_DECIDER_FLAG) {
00891 p->next_candidate = candidates;
00892 candidates = p;
00893
00894 p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
00895 }
00896 }
00897
00898
00899 #ifndef SOAR_8_ONLY
00900 if (((current_agent(attribute_preferences_mode) == 2) ||
00901 (current_agent(operand2_mode) == TRUE)) && (!s->isa_context_slot)) {
00902 #else
00903 if (!s->isa_context_slot) {
00904 #endif
00905 *result_candidates = candidates;
00906 return NONE_IMPASSE_TYPE;
00907 }
00908
00909
00910 if ((!candidates) || (!candidates->next_candidate)) {
00911 *result_candidates = candidates;
00912 return NONE_IMPASSE_TYPE;
00913 }
00914
00915
00916 if (s->preferences[BETTER_PREFERENCE_TYPE] || s->preferences[WORSE_PREFERENCE_TYPE]) {
00917 Symbol *j, *k;
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942 for (p = s->preferences[BETTER_PREFERENCE_TYPE]; p != NIL; p = p->next) {
00943 p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
00944 p->referent->common.decider_flag = NOTHING_DECIDER_FLAG;
00945 }
00946 for (p = s->preferences[WORSE_PREFERENCE_TYPE]; p != NIL; p = p->next) {
00947 p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
00948 p->referent->common.decider_flag = NOTHING_DECIDER_FLAG;
00949 }
00950 for (cand = candidates; cand != NIL; cand = cand->next_candidate) {
00951 cand->value->common.decider_flag = CANDIDATE_DECIDER_FLAG;
00952 }
00953 for (p = s->preferences[BETTER_PREFERENCE_TYPE]; p != NIL; p = p->next) {
00954 j = p->value;
00955 k = p->referent;
00956 if (j == k)
00957 continue;
00958 if (j->common.decider_flag && k->common.decider_flag) {
00959 if (k->common.decider_flag != CONFLICTED_DECIDER_FLAG)
00960 k->common.decider_flag = FORMER_CANDIDATE_DECIDER_FLAG;
00961 if ((j->common.decider_flag != CONFLICTED_DECIDER_FLAG) ||
00962 (k->common.decider_flag != CONFLICTED_DECIDER_FLAG)) {
00963 for (p2 = s->preferences[BETTER_PREFERENCE_TYPE]; p2; p2 = p2->next)
00964 if ((p2->value == k) && (p2->referent == j)) {
00965 j->common.decider_flag = CONFLICTED_DECIDER_FLAG;
00966 k->common.decider_flag = CONFLICTED_DECIDER_FLAG;
00967 break;
00968 }
00969 for (p2 = s->preferences[WORSE_PREFERENCE_TYPE]; p2; p2 = p2->next)
00970 if ((p2->value == j) && (p2->referent == k)) {
00971 j->common.decider_flag = CONFLICTED_DECIDER_FLAG;
00972 k->common.decider_flag = CONFLICTED_DECIDER_FLAG;
00973 break;
00974 }
00975 }
00976 }
00977 }
00978 for (p = s->preferences[WORSE_PREFERENCE_TYPE]; p != NIL; p = p->next) {
00979 j = p->value;
00980 k = p->referent;
00981 if (j == k)
00982 continue;
00983 if (j->common.decider_flag && k->common.decider_flag) {
00984 if (j->common.decider_flag != CONFLICTED_DECIDER_FLAG)
00985 j->common.decider_flag = FORMER_CANDIDATE_DECIDER_FLAG;
00986 if ((j->common.decider_flag != CONFLICTED_DECIDER_FLAG) ||
00987 (k->common.decider_flag != CONFLICTED_DECIDER_FLAG)) {
00988 for (p2 = s->preferences[WORSE_PREFERENCE_TYPE]; p2; p2 = p2->next)
00989 if ((p2->value == k) && (p2->referent == j)) {
00990 j->common.decider_flag = CONFLICTED_DECIDER_FLAG;
00991 k->common.decider_flag = CONFLICTED_DECIDER_FLAG;
00992 break;
00993 }
00994 }
00995 }
00996 }
00997
00998
00999 for (cand = candidates; cand != NIL; cand = cand->next_candidate)
01000 if (cand->value->common.decider_flag == CONFLICTED_DECIDER_FLAG)
01001 break;
01002 if (cand) {
01003
01004 prev_cand = NIL;
01005 cand = candidates;
01006 while (cand) {
01007 if (cand->value->common.decider_flag != CONFLICTED_DECIDER_FLAG) {
01008 if (prev_cand)
01009 prev_cand->next_candidate = cand->next_candidate;
01010 else
01011 candidates = cand->next_candidate;
01012 } else {
01013 prev_cand = cand;
01014 }
01015 cand = cand->next_candidate;
01016 }
01017 *result_candidates = candidates;
01018 return CONFLICT_IMPASSE_TYPE;
01019 }
01020
01021 prev_cand = NIL;
01022 cand = candidates;
01023 while (cand) {
01024 if (cand->value->common.decider_flag == FORMER_CANDIDATE_DECIDER_FLAG) {
01025 if (prev_cand)
01026 prev_cand->next_candidate = cand->next_candidate;
01027 else
01028 candidates = cand->next_candidate;
01029 } else {
01030 prev_cand = cand;
01031 }
01032 cand = cand->next_candidate;
01033 }
01034 }
01035
01036
01037 if (s->preferences[BEST_PREFERENCE_TYPE]) {
01038 for (cand = candidates; cand != NIL; cand = cand->next_candidate)
01039 cand->value->common.decider_flag = NOTHING_DECIDER_FLAG;
01040 for (p = s->preferences[BEST_PREFERENCE_TYPE]; p != NIL; p = p->next)
01041 p->value->common.decider_flag = BEST_DECIDER_FLAG;
01042 prev_cand = NIL;
01043 for (cand = candidates; cand != NIL; cand = cand->next_candidate)
01044 if (cand->value->common.decider_flag == BEST_DECIDER_FLAG) {
01045 if (prev_cand)
01046 prev_cand->next_candidate = cand;
01047 else
01048 candidates = cand;
01049 prev_cand = cand;
01050 }
01051 if (prev_cand)
01052 prev_cand->next_candidate = NIL;
01053 }
01054
01055
01056 if (s->preferences[WORST_PREFERENCE_TYPE]) {
01057 for (cand = candidates; cand != NIL; cand = cand->next_candidate)
01058 cand->value->common.decider_flag = NOTHING_DECIDER_FLAG;
01059 for (p = s->preferences[WORST_PREFERENCE_TYPE]; p != NIL; p = p->next)
01060 p->value->common.decider_flag = WORST_DECIDER_FLAG;
01061 prev_cand = NIL;
01062 for (cand = candidates; cand != NIL; cand = cand->next_candidate)
01063 if (cand->value->common.decider_flag != WORST_DECIDER_FLAG) {
01064 if (prev_cand)
01065 prev_cand->next_candidate = cand;
01066 else
01067 candidates = cand;
01068 prev_cand = cand;
01069 }
01070 if (prev_cand)
01071 prev_cand->next_candidate = NIL;
01072 }
01073
01074
01075 if ((!candidates) || (!candidates->next_candidate)) {
01076 *result_candidates = candidates;
01077 return NONE_IMPASSE_TYPE;
01078 }
01079
01080
01081 for (cand = candidates; cand != NIL; cand = cand->next_candidate)
01082 cand->value->common.decider_flag = NOTHING_DECIDER_FLAG;
01083 for (p = s->preferences[UNARY_INDIFFERENT_PREFERENCE_TYPE]; p; p = p->next)
01084 p->value->common.decider_flag = UNARY_INDIFFERENT_DECIDER_FLAG;
01085
01086
01087 #ifdef NUMERIC_INDIFFERENCE
01088
01089
01090
01091
01092
01093 for (p=s->preferences[BINARY_INDIFFERENT_PREFERENCE_TYPE]; p; p=p->next)
01094 if((p->referent->fc.common_symbol_info.symbol_type == INT_CONSTANT_SYMBOL_TYPE) ||
01095 (p->referent->fc.common_symbol_info.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE))
01096
01097 p->value->common.decider_flag = UNARY_INDIFFERENT_CONSTANT_DECIDER_FLAG;
01098
01099
01100
01101 #endif
01102
01103 not_all_indifferent = FALSE;
01104 for (cand = candidates; cand != NIL; cand = cand->next_candidate) {
01105
01106 if (cand->value->common.decider_flag == UNARY_INDIFFERENT_DECIDER_FLAG)
01107 continue;
01108
01109 #ifdef NUMERIC_INDIFFERENCE
01110 else if ( cand->value->common.decider_flag==UNARY_INDIFFERENT_CONSTANT_DECIDER_FLAG )
01111 continue;
01112 #endif
01113
01114
01115 for (p = candidates; p != NIL; p = p->next_candidate) {
01116 if (p == cand)
01117 continue;
01118 match_found = FALSE;
01119 for (p2 = s->preferences[BINARY_INDIFFERENT_PREFERENCE_TYPE]; p2 != NIL; p2 = p2->next)
01120 if (((p2->value == cand->value) && (p2->referent == p->value)) ||
01121 ((p2->value == p->value) && (p2->referent == cand->value))) {
01122 match_found = TRUE;
01123 break;
01124 }
01125 if (!match_found) {
01126 not_all_indifferent = TRUE;
01127 break;
01128 }
01129 }
01130 if (not_all_indifferent)
01131 break;
01132 }
01133
01134 if (!not_all_indifferent) {
01135
01136
01137
01138
01139
01140
01141
01142
01143 switch (current_agent(sysparams)[USER_SELECT_MODE_SYSPARAM]) {
01144 case USER_SELECT_FIRST:
01145 *result_candidates = candidates;
01146 break;
01147
01148 case USER_SELECT_LAST:
01149
01150
01151
01152
01153
01154 for (cand = candidates; cand->next_candidate != NIL; cand = cand->next_candidate);
01155 *result_candidates = cand;
01156 break;
01157
01158 case USER_SELECT_ASK:{
01159 soar_apiAskCallbackData askd;
01160
01161 askd.candidates = candidates;
01162 askd.selection = result_candidates;
01163
01164 if (soar_exists_callback(soar_agent, ASK_CALLBACK)) {
01165 soar_invoke_first_callback(soar_agent, ASK_CALLBACK, (soar_call_data) & askd);
01166
01167 break;
01168 } else {
01169 print("\nError: \n");
01170 print(" User Select ASK failed becuase no ask callback is defined\n");
01171 print(" Setting to user select RANDOM\n");
01172 set_sysparam(USER_SELECT_MODE_SYSPARAM, USER_SELECT_RANDOM);
01173 current_agent(stop_soar) = TRUE;
01174
01175
01176 }
01177
01178
01179 }
01180 case USER_SELECT_RANDOM:{
01181
01182 #ifdef NUMERIC_INDIFFERENCE
01183
01184 cand = probabilistically_select(s, candidates);
01185 if (!cand) {
01186 *result_candidates = candidates;
01187 return TIE_IMPASSE_TYPE;
01188 }
01189 *result_candidates = cand;
01190 break;
01191 #else
01192 int num_candidates, chosen_num;
01193 num_candidates = 0;
01194
01195 for (cand = candidates; cand != NIL; cand = cand->next_candidate)
01196 num_candidates++;
01197
01198 chosen_num = sys_random() % num_candidates;
01199
01200 cand = candidates;
01201 while (chosen_num) {
01202 cand = cand->next_candidate;
01203 chosen_num--;
01204 }
01205 *result_candidates = cand;
01206 break;
01207 #endif
01208 }
01209 default:
01210 {
01211 char msg[MESSAGE_SIZE];
01212 snprintf(msg, MESSAGE_SIZE, "decide.c: Error: bad value of user_select_mode: %ld\n",
01213 current_agent(sysparams)[USER_SELECT_MODE_SYSPARAM]);
01214 msg[MESSAGE_SIZE - 1] = 0;
01215 abort_with_fatal_error(msg);
01216 }
01217 }
01218 (*result_candidates)->next_candidate = NIL;
01219 return NONE_IMPASSE_TYPE;
01220 }
01221
01222
01223 if (s->isa_context_slot) {
01224 *result_candidates = candidates;
01225 return TIE_IMPASSE_TYPE;
01226 }
01227
01228
01229 for (cand = candidates; cand != NIL; cand = cand->next_candidate)
01230 cand->value->common.decider_flag = NOTHING_DECIDER_FLAG;
01231 for (p = s->preferences[UNARY_PARALLEL_PREFERENCE_TYPE]; p; p = p->next)
01232 p->value->common.decider_flag = UNARY_PARALLEL_DECIDER_FLAG;
01233 not_all_parallel = FALSE;
01234 for (cand = candidates; cand != NIL; cand = cand->next_candidate) {
01235
01236 if (cand->value->common.decider_flag == UNARY_PARALLEL_DECIDER_FLAG)
01237 continue;
01238
01239 for (p = candidates; p != NIL; p = p->next_candidate) {
01240 if (p == cand)
01241 continue;
01242 match_found = FALSE;
01243 for (p2 = s->preferences[BINARY_PARALLEL_PREFERENCE_TYPE]; p2 != NIL; p2 = p2->next)
01244 if (((p2->value == cand->value) && (p2->referent == p->value)) ||
01245 ((p2->value == p->value) && (p2->referent == cand->value))) {
01246 match_found = TRUE;
01247 break;
01248 }
01249 if (!match_found) {
01250 not_all_parallel = TRUE;
01251 break;
01252 }
01253 }
01254 if (not_all_parallel)
01255 break;
01256 }
01257
01258 *result_candidates = candidates;
01259
01260 if (!not_all_parallel) {
01261
01262 return NONE_IMPASSE_TYPE;
01263 }
01264
01265
01266 return TIE_IMPASSE_TYPE;
01267 }
01268
01269 byte run_preference_semantics_for_consistency_check(slot * s, preference ** result_candidates)
01270 {
01271 preference *p, *p2, *cand, *prev_cand;
01272 bool match_found, not_all_indifferent, not_all_parallel;
01273 preference *candidates;
01274
01275
01276
01277 if (!s->all_preferences) {
01278 if (!s->isa_context_slot)
01279 mark_slot_for_possible_removal(s);
01280 *result_candidates = NIL;
01281 return NONE_IMPASSE_TYPE;
01282 }
01283
01284
01285 if (s->preferences[REQUIRE_PREFERENCE_TYPE]) {
01286 return require_preference_semantics(s, result_candidates);
01287 }
01288
01289
01290
01291
01292
01293 for (p = s->preferences[ACCEPTABLE_PREFERENCE_TYPE]; p != NIL; p = p->next)
01294 p->value->common.decider_flag = CANDIDATE_DECIDER_FLAG;
01295 for (p = s->preferences[PROHIBIT_PREFERENCE_TYPE]; p != NIL; p = p->next)
01296 p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
01297 for (p = s->preferences[REJECT_PREFERENCE_TYPE]; p != NIL; p = p->next)
01298 p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
01299
01300
01301 candidates = NIL;
01302 for (p = s->preferences[ACCEPTABLE_PREFERENCE_TYPE]; p != NIL; p = p->next) {
01303 if (p->value->common.decider_flag == CANDIDATE_DECIDER_FLAG) {
01304 p->next_candidate = candidates;
01305 candidates = p;
01306
01307 p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
01308 }
01309 }
01310
01311
01312 #ifndef SOAR_8_ONLY
01313 if (((current_agent(attribute_preferences_mode) == 2) ||
01314 (current_agent(operand2_mode) == TRUE)) && (!s->isa_context_slot)) {
01315 #else
01316 if (!s->isa_context_slot) {
01317 #endif
01318 *result_candidates = candidates;
01319 return NONE_IMPASSE_TYPE;
01320 }
01321
01322
01323 if ((!candidates) || (!candidates->next_candidate)) {
01324 *result_candidates = candidates;
01325 return NONE_IMPASSE_TYPE;
01326 }
01327
01328
01329 if (s->preferences[BETTER_PREFERENCE_TYPE] || s->preferences[WORSE_PREFERENCE_TYPE]) {
01330 Symbol *j, *k;
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355 for (p = s->preferences[BETTER_PREFERENCE_TYPE]; p != NIL; p = p->next) {
01356 p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
01357 p->referent->common.decider_flag = NOTHING_DECIDER_FLAG;
01358 }
01359 for (p = s->preferences[WORSE_PREFERENCE_TYPE]; p != NIL; p = p->next) {
01360 p->value->common.decider_flag = NOTHING_DECIDER_FLAG;
01361 p->referent->common.decider_flag = NOTHING_DECIDER_FLAG;
01362 }
01363 for (cand = candidates; cand != NIL; cand = cand->next_candidate) {
01364 cand->value->common.decider_flag = CANDIDATE_DECIDER_FLAG;
01365 }
01366 for (p = s->preferences[BETTER_PREFERENCE_TYPE]; p != NIL; p = p->next) {
01367 j = p->value;
01368 k = p->referent;
01369 if (j == k)
01370 continue;
01371 if (j->common.decider_flag && k->common.decider_flag) {
01372 if (k->common.decider_flag != CONFLICTED_DECIDER_FLAG)
01373 k->common.decider_flag = FORMER_CANDIDATE_DECIDER_FLAG;
01374 if ((j->common.decider_flag != CONFLICTED_DECIDER_FLAG) ||
01375 (k->common.decider_flag != CONFLICTED_DECIDER_FLAG)) {
01376 for (p2 = s->preferences[BETTER_PREFERENCE_TYPE]; p2; p2 = p2->next)
01377 if ((p2->value == k) && (p2->referent == j)) {
01378 j->common.decider_flag = CONFLICTED_DECIDER_FLAG;
01379 k->common.decider_flag = CONFLICTED_DECIDER_FLAG;
01380 break;
01381 }
01382 for (p2 = s->preferences[WORSE_PREFERENCE_TYPE]; p2; p2 = p2->next)
01383 if ((p2->value == j) && (p2->referent == k)) {
01384 j->common.decider_flag = CONFLICTED_DECIDER_FLAG;
01385 k->common.decider_flag = CONFLICTED_DECIDER_FLAG;
01386 break;
01387 }
01388 }
01389 }
01390 }
01391 for (p = s->preferences[WORSE_PREFERENCE_TYPE]; p != NIL; p = p->next) {
01392 j = p->value;
01393 k = p->referent;
01394 if (j == k)
01395 continue;
01396 if (j->common.decider_flag && k->common.decider_flag) {
01397 if (j->common.decider_flag != CONFLICTED_DECIDER_FLAG)
01398 j->common.decider_flag = FORMER_CANDIDATE_DECIDER_FLAG;
01399 if ((j->common.decider_flag != CONFLICTED_DECIDER_FLAG) ||
01400 (k->common.decider_flag != CONFLICTED_DECIDER_FLAG)) {
01401 for (p2 = s->preferences[WORSE_PREFERENCE_TYPE]; p2; p2 = p2->next)
01402 if ((p2->value == k) && (p2->referent == j)) {
01403 j->common.decider_flag = CONFLICTED_DECIDER_FLAG;
01404 k->common.decider_flag = CONFLICTED_DECIDER_FLAG;
01405 break;
01406 }
01407 }
01408 }
01409 }
01410
01411
01412 for (cand = candidates; cand != NIL; cand = cand->next_candidate)
01413 if (cand->value->common.decider_flag == CONFLICTED_DECIDER_FLAG)
01414 break;
01415 if (cand) {
01416
01417 prev_cand = NIL;
01418 cand = candidates;
01419 while (cand) {
01420 if (cand->value->common.decider_flag != CONFLICTED_DECIDER_FLAG) {
01421 if (prev_cand)
01422 prev_cand->next_candidate = cand->next_candidate;
01423 else
01424 candidates = cand->next_candidate;
01425 } else {
01426 prev_cand = cand;
01427 }
01428 cand = cand->next_candidate;
01429 }
01430 *result_candidates = candidates;
01431 return CONFLICT_IMPASSE_TYPE;
01432 }
01433
01434 prev_cand = NIL;
01435 cand = candidates;
01436 while (cand) {
01437 if (cand->value->common.decider_flag == FORMER_CANDIDATE_DECIDER_FLAG) {
01438 if (prev_cand)
01439 prev_cand->next_candidate = cand->next_candidate;
01440 else
01441 candidates = cand->next_candidate;
01442 } else {
01443 prev_cand = cand;
01444 }
01445 cand = cand->next_candidate;
01446 }
01447 }
01448
01449
01450 if (s->preferences[BEST_PREFERENCE_TYPE]) {
01451 for (cand = candidates; cand != NIL; cand = cand->next_candidate)
01452 cand->value->common.decider_flag = NOTHING_DECIDER_FLAG;
01453 for (p = s->preferences[BEST_PREFERENCE_TYPE]; p != NIL; p = p->next)
01454 p->value->common.decider_flag = BEST_DECIDER_FLAG;
01455 prev_cand = NIL;
01456 for (cand = candidates; cand != NIL; cand = cand->next_candidate)
01457 if (cand->value->common.decider_flag == BEST_DECIDER_FLAG) {
01458 if (prev_cand)
01459 prev_cand->next_candidate = cand;
01460 else
01461 candidates = cand;
01462 prev_cand = cand;
01463 }
01464 if (prev_cand)
01465 prev_cand->next_candidate = NIL;
01466 }
01467
01468
01469 if (s->preferences[WORST_PREFERENCE_TYPE]) {
01470 for (cand = candidates; cand != NIL; cand = cand->next_candidate)
01471 cand->value->common.decider_flag = NOTHING_DECIDER_FLAG;
01472 for (p = s->preferences[WORST_PREFERENCE_TYPE]; p != NIL; p = p->next)
01473 p->value->common.decider_flag = WORST_DECIDER_FLAG;
01474 prev_cand = NIL;
01475 for (cand = candidates; cand != NIL; cand = cand->next_candidate)
01476 if (cand->value->common.decider_flag != WORST_DECIDER_FLAG) {
01477 if (prev_cand)
01478 prev_cand->next_candidate = cand;
01479 else
01480 candidates = cand;
01481 prev_cand = cand;
01482 }
01483 if (prev_cand)
01484 prev_cand->next_candidate = NIL;
01485 }
01486
01487
01488 if ((!candidates) || (!candidates->next_candidate)) {
01489 *result_candidates = candidates;
01490 return NONE_IMPASSE_TYPE;
01491 }
01492
01493
01494 for (cand = candidates; cand != NIL; cand = cand->next_candidate)
01495 cand->value->common.decider_flag = NOTHING_DECIDER_FLAG;
01496 for (p = s->preferences[UNARY_INDIFFERENT_PREFERENCE_TYPE]; p; p = p->next)
01497 p->value->common.decider_flag = UNARY_INDIFFERENT_DECIDER_FLAG;
01498
01499 #ifdef NUMERIC_INDIFFERENCE
01500
01501
01502
01503
01504
01505
01506 for (p=s->preferences[BINARY_INDIFFERENT_PREFERENCE_TYPE]; p; p=p->next)
01507 if( (p->referent->fc.common_symbol_info.symbol_type == INT_CONSTANT_SYMBOL_TYPE) ||
01508 (p->referent->fc.common_symbol_info.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE))
01509
01510 p->value->common.decider_flag = UNARY_INDIFFERENT_CONSTANT_DECIDER_FLAG;
01511
01512 #endif
01513
01514 not_all_indifferent = FALSE;
01515 for (cand = candidates; cand != NIL; cand = cand->next_candidate) {
01516
01517 if (cand->value->common.decider_flag == UNARY_INDIFFERENT_DECIDER_FLAG)
01518 continue;
01519
01520 #ifdef NUMERIC_INDIFFERENCE
01521 else if ( cand->value->common.decider_flag==UNARY_INDIFFERENT_CONSTANT_DECIDER_FLAG ) {
01522
01523 continue;
01524 }
01525 #endif
01526
01527
01528 for (p = candidates; p != NIL; p = p->next_candidate) {
01529 if (p == cand)
01530 continue;
01531 match_found = FALSE;
01532 for (p2 = s->preferences[BINARY_INDIFFERENT_PREFERENCE_TYPE]; p2 != NIL; p2 = p2->next)
01533 if (((p2->value == cand->value) && (p2->referent == p->value)) ||
01534 ((p2->value == p->value) && (p2->referent == cand->value))) {
01535 match_found = TRUE;
01536 break;
01537 }
01538 if (!match_found) {
01539 not_all_indifferent = TRUE;
01540 break;
01541 }
01542 }
01543 if (not_all_indifferent)
01544 break;
01545 }
01546
01547 if (!not_all_indifferent) {
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565 *result_candidates = candidates;
01566
01567
01568
01569
01570
01571 return NONE_IMPASSE_TYPE;
01572
01573 }
01574
01575
01576 if (s->isa_context_slot) {
01577 *result_candidates = candidates;
01578 return TIE_IMPASSE_TYPE;
01579 }
01580
01581
01582 for (cand = candidates; cand != NIL; cand = cand->next_candidate)
01583 cand->value->common.decider_flag = NOTHING_DECIDER_FLAG;
01584 for (p = s->preferences[UNARY_PARALLEL_PREFERENCE_TYPE]; p; p = p->next)
01585 p->value->common.decider_flag = UNARY_PARALLEL_DECIDER_FLAG;
01586 not_all_parallel = FALSE;
01587 for (cand = candidates; cand != NIL; cand = cand->next_candidate) {
01588
01589 if (cand->value->common.decider_flag == UNARY_PARALLEL_DECIDER_FLAG)
01590 continue;
01591
01592 for (p = candidates; p != NIL; p = p->next_candidate) {
01593 if (p == cand)
01594 continue;
01595 match_found = FALSE;
01596 for (p2 = s->preferences[BINARY_PARALLEL_PREFERENCE_TYPE]; p2 != NIL; p2 = p2->next)
01597 if (((p2->value == cand->value) && (p2->referent == p->value)) ||
01598 ((p2->value == p->value) && (p2->referent == cand->value))) {
01599 match_found = TRUE;
01600 break;
01601 }
01602 if (!match_found) {
01603 not_all_parallel = TRUE;
01604 break;
01605 }
01606 }
01607 if (not_all_parallel)
01608 break;
01609 }
01610
01611 *result_candidates = candidates;
01612
01613 if (!not_all_parallel) {
01614
01615 return NONE_IMPASSE_TYPE;
01616 }
01617
01618
01619 return TIE_IMPASSE_TYPE;
01620 }
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637 void add_impasse_wme(Symbol * id, Symbol * attr, Symbol * value, preference * p)
01638 {
01639 wme *w;
01640
01641 w = make_wme(id, attr, value, FALSE);
01642 insert_at_head_of_dll(id->id.impasse_wmes, w, next, prev);
01643 w->preference = p;
01644 add_wme_to_wm(w);
01645 }
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655 Symbol *create_new_impasse(bool isa_goal, Symbol * object, Symbol * attr, byte impasse_type, goal_stack_level level)
01656 {
01657 Symbol *id;
01658
01659 id = make_new_identifier((char) (isa_goal ? 'S' : 'I'), level);
01660 post_link_addition(NIL, id);
01661
01662 add_impasse_wme(id, current_agent(type_symbol),
01663 isa_goal ? current_agent(state_symbol) : current_agent(impasse_symbol), NIL);
01664
01665 if (isa_goal)
01666 add_impasse_wme(id, current_agent(superstate_symbol), object, NIL);
01667 else
01668 add_impasse_wme(id, current_agent(object_symbol), object, NIL);
01669
01670 if (attr)
01671 add_impasse_wme(id, current_agent(attribute_symbol), attr, NIL);
01672
01673 switch (impasse_type) {
01674 case NONE_IMPASSE_TYPE:
01675 break;
01676 case CONSTRAINT_FAILURE_IMPASSE_TYPE:
01677 add_impasse_wme(id, current_agent(impasse_symbol), current_agent(constraint_failure_symbol), NIL);
01678 add_impasse_wme(id, current_agent(choices_symbol), current_agent(none_symbol), NIL);
01679 break;
01680 case CONFLICT_IMPASSE_TYPE:
01681 add_impasse_wme(id, current_agent(impasse_symbol), current_agent(conflict_symbol), NIL);
01682 add_impasse_wme(id, current_agent(choices_symbol), current_agent(multiple_symbol), NIL);
01683 break;
01684 case TIE_IMPASSE_TYPE:
01685 add_impasse_wme(id, current_agent(impasse_symbol), current_agent(tie_symbol), NIL);
01686 add_impasse_wme(id, current_agent(choices_symbol), current_agent(multiple_symbol), NIL);
01687 break;
01688 case NO_CHANGE_IMPASSE_TYPE:
01689 add_impasse_wme(id, current_agent(impasse_symbol), current_agent(no_change_symbol), NIL);
01690 add_impasse_wme(id, current_agent(choices_symbol), current_agent(none_symbol), NIL);
01691 break;
01692 }
01693 return id;
01694 }
01695
01696
01697
01698
01699
01700
01701
01702
01703 void create_new_attribute_impasse_for_slot(slot * s, byte impasse_type)
01704 {
01705 Symbol *id;
01706
01707 s->impasse_type = impasse_type;
01708 id = create_new_impasse(FALSE, s->id, s->attr, impasse_type, ATTRIBUTE_IMPASSE_LEVEL);
01709 s->impasse_id = id;
01710 id->id.isa_impasse = TRUE;
01711
01712 #ifndef FEW_CALLBACKS
01713 soar_invoke_callbacks(soar_agent, CREATE_NEW_ATTRIBUTE_IMPASSE_CALLBACK, (soar_call_data) s);
01714 #endif
01715
01716 }
01717
01718 void remove_existing_attribute_impasse_for_slot(slot * s)
01719 {
01720 Symbol *id;
01721
01722 #ifndef FEW_CALLBACKS
01723 soar_invoke_callbacks(soar_agent, REMOVE_ATTRIBUTE_IMPASSE_CALLBACK, (soar_call_data) s);
01724
01725 #endif
01726
01727 id = s->impasse_id;
01728 s->impasse_id = NIL;
01729 s->impasse_type = NONE_IMPASSE_TYPE;
01730 remove_wme_list_from_wm(id->id.impasse_wmes);
01731 id->id.impasse_wmes = NIL;
01732 post_link_removal(NIL, id);
01733 symbol_remove_ref(id);
01734 }
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763 preference *make_fake_preference_for_goal_item(Symbol * goal, preference * cand)
01764 {
01765 slot *s;
01766 wme *ap_wme;
01767 instantiation *inst;
01768 preference *pref;
01769 condition *cond;
01770
01771
01772 s = cand->slot;
01773 for (ap_wme = s->acceptable_preference_wmes; ap_wme != NIL; ap_wme = ap_wme->next)
01774 if (ap_wme->value == cand->value)
01775 break;
01776 if (!ap_wme) {
01777 char msg[MESSAGE_SIZE];
01778 strncpy(msg, "decide.c: Internal error: couldn't find acceptable pref wme\n", MESSAGE_SIZE);
01779 msg[MESSAGE_SIZE - 1] = 0;
01780 abort_with_fatal_error(msg);
01781 }
01782
01783
01784 pref = make_preference(ACCEPTABLE_PREFERENCE_TYPE, goal, current_agent(item_symbol), cand->value, NIL);
01785 symbol_add_ref(pref->id);
01786 symbol_add_ref(pref->attr);
01787 symbol_add_ref(pref->value);
01788 insert_at_head_of_dll(goal->id.preferences_from_goal, pref, all_of_goal_next, all_of_goal_prev);
01789 pref->on_goal_list = TRUE;
01790 preference_add_ref(pref);
01791
01792 allocate_with_pool(¤t_agent(instantiation_pool), &inst);
01793 pref->inst = inst;
01794 pref->inst_next = pref->inst_prev = NIL;
01795 inst->preferences_generated = pref;
01796 inst->prod = NIL;
01797 inst->next = inst->prev = NIL;
01798 inst->rete_token = NIL;
01799 inst->rete_wme = NIL;
01800 inst->match_goal = goal;
01801 inst->match_goal_level = goal->id.level;
01802 inst->okay_to_variablize = TRUE;
01803 inst->backtrace_number = 0;
01804 inst->in_ms = FALSE;
01805
01806 allocate_with_pool(¤t_agent(condition_pool), &cond);
01807 cond->type = POSITIVE_CONDITION;
01808 cond->next = cond->prev = NIL;
01809 inst->top_of_instantiated_conditions = cond;
01810 inst->bottom_of_instantiated_conditions = cond;
01811 inst->nots = NIL;
01812 cond->data.tests.id_test = make_equality_test(ap_wme->id);
01813 cond->data.tests.attr_test = make_equality_test(ap_wme->attr);
01814 cond->data.tests.value_test = make_equality_test(ap_wme->value);
01815 cond->test_for_acceptable_preference = TRUE;
01816 cond->bt.wme = ap_wme;
01817 wme_add_ref(ap_wme);
01818 cond->bt.level = ap_wme->id->id.level;
01819 cond->bt.trace = NIL;
01820 cond->bt.prohibits = NIL;
01821
01822
01823 return pref;
01824 }
01825
01826 void remove_fake_preference_for_goal_item(preference * pref)
01827 {
01828 preference_remove_ref(pref);
01829 }
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840 void update_impasse_items(Symbol * id, preference * items)
01841 {
01842 wme *w, *next_w;
01843 preference *cand;
01844 preference *bt_pref;
01845
01846
01847 for (w = id->id.impasse_wmes; w != NIL; w = w->next)
01848 if (w->attr == current_agent(item_symbol))
01849 w->value->common.decider_flag = NOTHING_DECIDER_FLAG;
01850
01851
01852 for (cand = items; cand != NIL; cand = cand->next_candidate)
01853 cand->value->common.decider_flag = CANDIDATE_DECIDER_FLAG;
01854
01855
01856
01857 w = id->id.impasse_wmes;
01858 while (w) {
01859 next_w = w->next;
01860 if (w->attr == current_agent(item_symbol)) {
01861 if (w->value->common.decider_flag == CANDIDATE_DECIDER_FLAG) {
01862 w->value->common.decider_flag = ALREADY_EXISTING_WME_DECIDER_FLAG;
01863 w->value->common.a.decider_wme = w;
01864 } else {
01865 remove_from_dll(id->id.impasse_wmes, w, next, prev);
01866 if (id->id.isa_goal)
01867 remove_fake_preference_for_goal_item(w->preference);
01868 remove_wme_from_wm(w);
01869 }
01870 }
01871 w = next_w;
01872 }
01873
01874
01875 for (cand = items; cand != NIL; cand = cand->next_candidate) {
01876 if (id->id.isa_goal)
01877 bt_pref = make_fake_preference_for_goal_item(id, cand);
01878 else
01879 bt_pref = cand;
01880 if (cand->value->common.decider_flag == ALREADY_EXISTING_WME_DECIDER_FLAG) {
01881 if (id->id.isa_goal)
01882 remove_fake_preference_for_goal_item(cand->value->common.a.decider_wme->preference);
01883 cand->value->common.a.decider_wme->preference = bt_pref;
01884 } else {
01885 add_impasse_wme(id, current_agent(item_symbol), cand->value, bt_pref);
01886 }
01887 }
01888 }
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898 void decide_non_context_slot(slot * s)
01899 {
01900 byte impasse_type;
01901 wme *w, *next_w;
01902 preference *candidates, *cand;
01903 #ifndef DONT_CALC_GDS_OR_BT
01904 preference *pref;
01905 #endif
01906
01907 impasse_type = run_preference_semantics(s, &candidates);
01908
01909 if (impasse_type == NONE_IMPASSE_TYPE) {
01910
01911 if (s->impasse_type != NONE_IMPASSE_TYPE)
01912 remove_existing_attribute_impasse_for_slot(s);
01913
01914 for (w = s->wmes; w != NIL; w = w->next)
01915 w->value->common.decider_flag = NOTHING_DECIDER_FLAG;
01916
01917 for (cand = candidates; cand != NIL; cand = cand->next_candidate)
01918 cand->value->common.decider_flag = CANDIDATE_DECIDER_FLAG;
01919
01920
01921 w = s->wmes;
01922 while (w) {
01923 next_w = w->next;
01924 if (w->value->common.decider_flag == CANDIDATE_DECIDER_FLAG) {
01925 w->value->common.decider_flag = ALREADY_EXISTING_WME_DECIDER_FLAG;
01926 w->value->common.a.decider_wme = w;
01927 } else {
01928 remove_from_dll(s->wmes, w, next, prev);
01929
01930 #ifndef DONT_CALC_GDS_OR_BT
01931
01932 #ifndef SOAR_8_ONLY
01933 if (current_agent(operand2_mode)) {
01934 #endif
01935 if (w->gds) {
01936 if (w->gds->goal != NIL) {
01937
01938 if (current_agent(soar_verbose_flag)) {
01939 print("\n Removing goal %d because element in GDS changed.",
01940 w->gds->goal->id.level);
01941 print(" WME: ");
01942 print_wme(w);
01943 }
01944 gds_invalid_so_remove_goal(w);
01945 }
01946 }
01947 #ifndef SOAR_8_ONLY
01948 }
01949 #endif
01950 #endif
01951
01952 remove_wme_from_wm(w);
01953 }
01954 w = next_w;
01955 }
01956
01957
01958 for (cand = candidates; cand != NIL; cand = cand->next_candidate) {
01959 if (cand->value->common.decider_flag == ALREADY_EXISTING_WME_DECIDER_FLAG) {
01960
01961
01962
01963
01964 cand->value->common.a.decider_wme->preference = cand;
01965 } else {
01966 w = make_wme(cand->id, cand->attr, cand->value, FALSE);
01967 insert_at_head_of_dll(s->wmes, w, next, prev);
01968 w->preference = cand;
01969
01970 #ifndef DONT_CALC_GDS_OR_BT
01971
01972 #ifndef SOAR_8_ONLY
01973 if (current_agent(operand2_mode)) {
01974 #endif
01975
01976
01977
01978
01979
01980
01981
01982 #ifndef NO_TIMING_STUFF
01983 #ifdef DETAILED_TIMING_STATS
01984
01985 start_timer(¤t_agent(start_gds_tv));
01986
01987 #endif
01988 #endif
01989 current_agent(parent_list_head) = NIL;
01990
01991
01992
01993
01994
01995
01996
01997
01998 #ifdef NO_TOP_JUST
01999
02000 if ((w->preference->o_supported == TRUE) && (w->preference->match_goal_level != 1)) {
02001
02002 if (w->preference->match_goal->id.gds == NIL) {
02003
02004
02005 if (w->preference->match_goal_level == w->preference->id->id.level) {
02006
02007 create_gds_for_goal(w->preference->match_goal);
02008 #else
02009 if ((w->preference->o_supported == TRUE) && (w->preference->inst->match_goal_level != 1)) {
02010
02011 if (w->preference->inst->match_goal->id.gds == NIL) {
02012
02013
02014
02015 if (w->preference->inst->match_goal_level == w->preference->id->id.level) {
02016
02017 create_gds_for_goal(w->preference->inst->match_goal);
02018 #endif
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038 } else {
02039 char msg[MESSAGE_SIZE];
02040 print_wme(w);
02041 print_preference(w->preference);
02042 #ifdef NO_TOP_JUST
02043 snprintf(msg, MESSAGE_SIZE,
02044 "**** (NO_TOP_JUST) Wanted to create a GDS for a WME level (%d) different from the instantiation level (%d).....Big problems....exiting....(instantiation = %p, inst->match_goal_level = %d)****\n\n",
02045 w->preference->id->id.level, w->preference->match_goal_level,
02046 w->preference->inst, w->preference->inst->match_goal_level);
02047 msg[MESSAGE_SIZE - 1] = 0;
02048 #else
02049 snprintf(msg, MESSAGE_SIZE,
02050 "**** Wanted to create a GDS for a WME level (%d) different from the instantiation level (%d).....Big problems....exiting....****\n\n",
02051 w->preference->id->id.level, w->preference->inst->match_goal_level);
02052 msg[MESSAGE_SIZE - 1] = 0;
02053 #endif
02054 abort_with_fatal_error(msg);
02055 }
02056 }
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068 for (pref = w->preference; pref != NIL; pref = pref->next) {
02069 #ifdef DEBUG_GDS_HIGH
02070 print("\n\n ");
02071 print_preference(pref);
02072 print(" Goal level of preference: %d\n", pref->id->id.level);
02073 #endif
02074
02075 if (pref->inst->GDS_evaluated_already == FALSE) {
02076 #ifdef DEBUG_GDS_HIGH
02077 print_with_symbols(" Match goal lev of instantiation %y ", pref->inst->prod->name);
02078 print("is %d\n", pref->inst->match_goal_level);
02079 #endif
02080 if (pref->inst->match_goal_level > pref->id->id.level) {
02081 #ifdef DEBUG_GDS_HIGH
02082 print_with_symbols
02083 (" %y is simply the instantiation that led to a chunk.\n Not adding it the current instantiations.\n",
02084 pref->inst->prod->name);
02085 #endif
02086
02087 } else {
02088 #ifdef DEBUG_GDS_HIGH
02089 print_with_symbols("\n Adding %y to list of parent instantiations\n",
02090 pref->inst->prod->name);
02091 #endif
02092 uniquely_add_to_head_of_dll(pref->inst);
02093 pref->inst->GDS_evaluated_already = TRUE;
02094 }
02095 }
02096 #ifdef DEBUG_GDS_HIGH
02097 else
02098 print_with_symbols("\n Instantiation %y was already explored; skipping it\n",
02099 pref->inst->prod->name);
02100 #endif
02101
02102 }
02103
02104 #ifdef DEBUG_GDS_HIGH
02105 print("\n CALLING ELABORATE GDS....\n");
02106 #endif
02107 elaborate_gds();
02108
02109
02110
02111 free_parent_list();
02112 #ifdef DEBUG_GDS_HIGH
02113 print(" FINISHED ELABORATING GDS.\n\n");
02114 #endif
02115 }
02116
02117
02118 #ifndef NO_TIMING_STUFF
02119 #ifdef DETAILED_TIMING_STATS
02120
02121 stop_timer(¤t_agent(start_gds_tv),
02122 ¤t_agent(gds_cpu_time[current_agent(current_phase)]));
02123
02124 #endif
02125 #endif
02126 #ifndef SOAR_8_ONLY
02127 }
02128 #endif
02129
02130 #endif
02131
02132
02133
02134 add_wme_to_wm(w);
02135 }
02136 }
02137 return;
02138 }
02139
02140
02141
02142 if (s->wmes) {
02143 remove_wme_list_from_wm(s->wmes);
02144 s->wmes = NIL;
02145 }
02146
02147 if (s->impasse_type != NONE_IMPASSE_TYPE) {
02148 if (s->impasse_type != impasse_type) {
02149 remove_existing_attribute_impasse_for_slot(s);
02150 create_new_attribute_impasse_for_slot(s, impasse_type);
02151 }
02152 update_impasse_items(s->impasse_id, candidates);
02153 } else {
02154 create_new_attribute_impasse_for_slot(s, impasse_type);
02155 update_impasse_items(s->impasse_id, candidates);
02156 }
02157 }
02158
02159
02160
02161
02162
02163
02164
02165
02166 void decide_non_context_slots(void)
02167 {
02168 dl_cons *dc;
02169 slot *s;
02170
02171 while (current_agent(changed_slots)) {
02172 dc = current_agent(changed_slots);
02173 current_agent(changed_slots) = current_agent(changed_slots)->next;
02174 s = dc->item;
02175 decide_non_context_slot(s);
02176 s->changed = NIL;
02177 free_with_pool(¤t_agent(dl_cons_pool), dc);
02178 }
02179 }
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191 bool context_slot_is_decidable(slot * s)
02192 {
02193 Symbol *v;
02194 preference *p;
02195
02196 if (!s->wmes)
02197 return (bool) (s->changed != NIL);
02198 v = s->wmes->value;
02199 for (p = s->preferences[RECONSIDER_PREFERENCE_TYPE]; p != NIL; p = p->next)
02200 if (v == p->value)
02201 return TRUE;
02202 return FALSE;
02203 }
02204
02205
02206
02207
02208
02209
02210
02211
02212 void remove_wmes_for_context_slot(slot * s)
02213 {
02214 wme *w;
02215
02216 if (!s->wmes)
02217 return;
02218
02219
02220 w = s->wmes;
02221 preference_remove_ref(w->preference);
02222 remove_wme_from_wm(w);
02223 s->wmes = NIL;
02224 }
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234 void remove_existing_context_and_descendents(Symbol * goal)
02235 {
02236 preference *p;
02237
02238 ms_change *head, *tail;
02239
02240
02241 #ifdef GOAL_SANITY_CHECK
02242
02243
02244 if (goal->id.level < 0 || goal->id.level > 1000) {
02245 print("Warning: goal id is of a bizzare value: %d\n", goal->id.level);
02246 printf("Warning: goal id is of a bizzare value: %d\n", goal->id.level);
02247 }
02248 #endif
02249 if (goal->id.lower_goal)
02250 remove_existing_context_and_descendents(goal->id.lower_goal);
02251
02252 #ifndef FEW_CALLBACKS
02253
02254
02255 soar_invoke_callbacks(soar_agent, POP_CONTEXT_STACK_CALLBACK, (soar_call_data) goal);
02256
02257 #endif
02258
02259 if (goal == current_agent(top_goal)) {
02260 current_agent(top_goal) = NIL;
02261 current_agent(bottom_goal) = NIL;
02262 } else {
02263 current_agent(bottom_goal) = goal->id.higher_goal;
02264 current_agent(bottom_goal)->id.lower_goal = NIL;
02265 }
02266
02267
02268 while (goal->id.preferences_from_goal) {
02269 p = goal->id.preferences_from_goal;
02270 remove_from_dll(goal->id.preferences_from_goal, p, all_of_goal_next, all_of_goal_prev);
02271 p->on_goal_list = FALSE;
02272 if (!remove_preference_from_clones(p))
02273 if (p->in_tm)
02274 remove_preference_from_tm(p);
02275 }
02276
02277
02278 remove_wmes_for_context_slot(goal->id.operator_slot);
02279 update_impasse_items(goal, NIL);
02280 remove_wme_list_from_wm(goal->id.impasse_wmes);
02281 goal->id.impasse_wmes = NIL;
02282
02283
02284
02285
02286
02287 if (goal->id.gds != NIL)
02288 goal->id.gds->goal = NIL;
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299 if (goal->id.ms_retractions) {
02300
02301 head = goal->id.ms_retractions;
02302 tail = head;
02303
02304
02305 while (tail->next_in_level) {
02306 tail->goal = NIL;
02307 tail = tail->next_in_level;
02308 }
02309 tail->goal = NIL;
02310
02311 if (current_agent(nil_goal_retractions)) {
02312
02313
02314
02315 current_agent(nil_goal_retractions)->prev_in_level = tail;
02316 tail->next_in_level = current_agent(nil_goal_retractions);
02317 current_agent(nil_goal_retractions) = head;
02318
02319 } else {
02320 current_agent(nil_goal_retractions) = head;
02321 }
02322 }
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334 post_link_removal(NIL, goal);
02335 symbol_remove_ref(goal);
02336 }
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347 void create_new_context(Symbol * attr_of_impasse, byte impasse_type)
02348 {
02349 Symbol *id;
02350
02351 if (current_agent(bottom_goal)) {
02352 id = create_new_impasse(TRUE, current_agent(bottom_goal), attr_of_impasse, impasse_type, (goal_stack_level)
02353 (current_agent(bottom_goal)->id.level + 1));
02354 id->id.higher_goal = current_agent(bottom_goal);
02355 current_agent(bottom_goal)->id.lower_goal = id;
02356 current_agent(bottom_goal) = id;
02357 add_impasse_wme(id, current_agent(quiescence_symbol), current_agent(t_symbol), NIL);
02358 } else {
02359 id = create_new_impasse(TRUE, current_agent(nil_symbol), NIL, NONE_IMPASSE_TYPE, TOP_GOAL_LEVEL);
02360 current_agent(top_goal) = id;
02361 current_agent(bottom_goal) = id;
02362 current_agent(top_state) = current_agent(top_goal);
02363 id->id.higher_goal = NIL;
02364 id->id.lower_goal = NIL;
02365 }
02366 id->id.isa_goal = TRUE;
02367 id->id.operator_slot = make_slot(id, current_agent(operator_symbol));
02368 id->id.allow_bottom_up_chunks = TRUE;
02369
02370 #ifndef FEW_CALLBACKS
02371
02372
02373 soar_invoke_callbacks(soar_agent, CREATE_NEW_CONTEXT_CALLBACK, (soar_call_data) id);
02374
02375 #endif
02376 }
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387 byte type_of_existing_impasse(Symbol * goal)
02388 {
02389 wme *w;
02390 char msg[MESSAGE_SIZE];
02391
02392 if (!goal->id.lower_goal)
02393 return NONE_IMPASSE_TYPE;
02394 for (w = goal->id.lower_goal->id.impasse_wmes; w != NIL; w = w->next)
02395 if (w->attr == current_agent(impasse_symbol)) {
02396 if (w->value == current_agent(no_change_symbol))
02397 return NO_CHANGE_IMPASSE_TYPE;
02398 if (w->value == current_agent(tie_symbol))
02399 return TIE_IMPASSE_TYPE;
02400 if (w->value == current_agent(constraint_failure_symbol))
02401 return CONSTRAINT_FAILURE_IMPASSE_TYPE;
02402 if (w->value == current_agent(conflict_symbol))
02403 return CONFLICT_IMPASSE_TYPE;
02404 if (w->value == current_agent(none_symbol))
02405 return NONE_IMPASSE_TYPE;
02406 strncpy(msg, "decide.c: Internal error: bad type of existing impasse.\n", MESSAGE_SIZE);
02407 msg[MESSAGE_SIZE - 1] = 0;
02408 abort_with_fatal_error(msg);
02409 }
02410 strncpy(msg, "decide.c: Internal error: couldn't find type of existing impasse.\n", MESSAGE_SIZE);
02411 msg[MESSAGE_SIZE - 1] = 0;
02412 abort_with_fatal_error(msg);
02413 return 0;
02414 }
02415
02416 Symbol *attribute_of_existing_impasse(Symbol * goal)
02417 {
02418 wme *w;
02419
02420 if (!goal->id.lower_goal)
02421 return NIL;
02422 for (w = goal->id.lower_goal->id.impasse_wmes; w != NIL; w = w->next)
02423 if (w->attr == current_agent(attribute_symbol))
02424 return w->value;
02425 {
02426 char msg[MESSAGE_SIZE];
02427 strncpy(msg, "decide.c: Internal error: couldn't find attribute of existing impasse.\n", MESSAGE_SIZE);
02428 msg[MESSAGE_SIZE - 1] = 0;
02429 abort_with_fatal_error(msg);
02430 }
02431 return NIL;
02432 }
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443 bool decide_context_slot(Symbol * goal, slot * s)
02444 {
02445 byte impasse_type;
02446 Symbol *attribute_of_impasse;
02447 wme *w;
02448 preference *candidates;
02449 preference *temp;
02450
02451 if (!context_slot_is_decidable(s)) {
02452
02453
02454
02455 impasse_type = NO_CHANGE_IMPASSE_TYPE;
02456 candidates = NIL;
02457 } else {
02458
02459 impasse_type = run_preference_semantics(s, &candidates);
02460 remove_wmes_for_context_slot(s);
02461
02462 if (impasse_type == NONE_IMPASSE_TYPE) {
02463 if (!candidates) {
02464
02465 impasse_type = NO_CHANGE_IMPASSE_TYPE;
02466 } else if (candidates->next_candidate) {
02467
02468 char msg[MESSAGE_SIZE];
02469 strncpy(msg, "decide.c: Internal error: more than one winner for context slot\n", MESSAGE_SIZE);
02470 msg[MESSAGE_SIZE - 1] = 0;
02471 abort_with_fatal_error(msg);
02472 }
02473 }
02474 }
02475
02476
02477 s->changed = NIL;
02478
02479
02480
02481 if (impasse_type == NO_CHANGE_IMPASSE_TYPE) {
02482 if (s->wmes) {
02483 attribute_of_impasse = s->attr;
02484 } else {
02485 attribute_of_impasse = current_agent(state_symbol);
02486 }
02487 } else {
02488
02489 attribute_of_impasse = s->attr;
02490 }
02491
02492
02493 if (attribute_of_impasse == current_agent(state_symbol)) {
02494 remove_wmes_for_context_slot(goal->id.operator_slot);
02495 }
02496
02497
02498
02499 if (impasse_type == NONE_IMPASSE_TYPE) {
02500 for (temp = candidates; temp; temp = temp->next_candidate)
02501 preference_add_ref(temp);
02502 if (goal->id.lower_goal)
02503 remove_existing_context_and_descendents(goal->id.lower_goal);
02504 w = make_wme(s->id, s->attr, candidates->value, FALSE);
02505 insert_at_head_of_dll(s->wmes, w, next, prev);
02506 w->preference = candidates;
02507 preference_add_ref(w->preference);
02508 add_wme_to_wm(w);
02509 for (temp = candidates; temp; temp = temp->next_candidate)
02510 preference_remove_ref(temp);
02511 return TRUE;
02512 }
02513
02514
02515
02516 if ((impasse_type == type_of_existing_impasse(goal)) &&
02517 (attribute_of_impasse == attribute_of_existing_impasse(goal))) {
02518 update_impasse_items(goal->id.lower_goal, candidates);
02519 return FALSE;
02520 }
02521
02522
02523
02524 for (temp = candidates; temp; temp = temp->next_candidate)
02525 preference_add_ref(temp);
02526 if (goal->id.lower_goal)
02527 remove_existing_context_and_descendents(goal->id.lower_goal);
02528
02529
02530 #ifndef SOAR_8_ONLY
02531 if (current_agent(operand2_mode) && current_agent(waitsnc) &&
02532 (impasse_type == NO_CHANGE_IMPASSE_TYPE) && (attribute_of_impasse == current_agent(state_symbol))) {
02533 #else
02534 if (current_agent(waitsnc) &&
02535 (impasse_type == NO_CHANGE_IMPASSE_TYPE) && (attribute_of_impasse == current_agent(state_symbol))) {
02536 #endif
02537 current_agent(waitsnc_detect) = TRUE;
02538 if (soar_exists_callback(soar_agent, WAIT_CALLBACK)) {
02539 soar_invoke_first_callback(soar_agent, WAIT_CALLBACK, NULL);
02540 }
02541
02542 } else {
02543
02544 create_new_context(attribute_of_impasse, impasse_type);
02545 update_impasse_items(goal->id.lower_goal, candidates);
02546 }
02547
02548 for (temp = candidates; temp; temp = temp->next_candidate)
02549 preference_remove_ref(temp);
02550 return TRUE;
02551 }
02552
02553
02554
02555
02556
02557
02558
02559
02560 void decide_context_slots(void)
02561 {
02562 Symbol *goal;
02563 slot *s;
02564
02565 if (current_agent(highest_goal_whose_context_changed)) {
02566 goal = current_agent(highest_goal_whose_context_changed);
02567 } else
02568
02569 goal = current_agent(bottom_goal);
02570
02571 s = goal->id.operator_slot;
02572
02573
02574 for (;;) {
02575
02576 for (;;) {
02577 if (context_slot_is_decidable(s))
02578 break;
02579
02580 if ((s == goal->id.operator_slot) || (!s->wmes)) {
02581
02582
02583 if (!goal->id.lower_goal)
02584 break;
02585
02586 goal = goal->id.lower_goal;
02587 s = goal->id.operator_slot;
02588 }
02589 }
02590
02591
02592 if (decide_context_slot(goal, s))
02593 break;
02594
02595 }
02596 current_agent(highest_goal_whose_context_changed) = NIL;
02597 }
02598
02599
02600
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620 void init_decider(void)
02621 {
02622 init_memory_pool(¤t_agent(slot_pool), sizeof(slot), "slot");
02623 init_memory_pool(¤t_agent(wme_pool), sizeof(wme), "wme");
02624 init_memory_pool(¤t_agent(preference_pool), sizeof(preference), "preference");
02625 }
02626
02627 void do_buffered_wm_and_ownership_changes(void)
02628 {
02629 do_buffered_acceptable_preference_wme_changes();
02630 do_buffered_link_changes();
02631 do_buffered_wm_changes();
02632 remove_garbage_slots();
02633 }
02634
02635 void do_working_memory_phase(void)
02636 {
02637
02638 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
02639
02640 if (current_agent(sysparams)[TRACE_PHASES_SYSPARAM]) {
02641 #ifndef SOAR_8_ONLY
02642 if (current_agent(operand2_mode) == TRUE) {
02643 #endif
02644 switch (current_agent(FIRING_TYPE)) {
02645 case PE_PRODS:
02646 print("\t--- Change Working Memory (PE) ---\n");
02647 break;
02648 case IE_PRODS:
02649 print("\t--- Change Working Memory (IE) ---\n");
02650 break;
02651 }
02652 #ifndef SOAR_8_ONLY
02653 }
02654
02655 else
02656 print("\n--- Working Memory Phase ---\n");
02657 #endif
02658 }
02659 #endif
02660
02661 decide_non_context_slots();
02662 do_buffered_wm_and_ownership_changes();
02663 }
02664
02665 void do_decision_phase(void)
02666 {
02667
02668 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
02669
02670 if (current_agent(sysparams)[TRACE_PHASES_SYSPARAM])
02671 print("\n--- Decision Phase ---\n");
02672
02673 #endif
02674
02675 decide_context_slots();
02676 do_buffered_wm_and_ownership_changes();
02677
02678
02679
02680
02681 decide_non_context_slots();
02682 do_buffered_wm_and_ownership_changes();
02683 }
02684
02685 void create_top_goal(void)
02686 {
02687 create_new_context(NIL, NONE_IMPASSE_TYPE);
02688 current_agent(highest_goal_whose_context_changed) = NIL;
02689 do_buffered_wm_and_ownership_changes();
02690 }
02691
02692 void clear_goal_stack(void)
02693 {
02694 if (!current_agent(top_goal))
02695 return;
02696 remove_existing_context_and_descendents(current_agent(top_goal));
02697 current_agent(highest_goal_whose_context_changed) = NIL;
02698 do_buffered_wm_and_ownership_changes();
02699 current_agent(top_state) = NIL;
02700 do_input_cycle();
02701 do_output_cycle();
02702 }
02703
02704 void print_lowest_slot_in_context_stack(void)
02705 {
02706
02707
02708
02709 if (current_agent(operand2_mode) && current_agent(waitsnc) && current_agent(waitsnc_detect)) {
02710
02711 current_agent(waitsnc_detect) = FALSE;
02712 print_stack_trace(current_agent(wait_symbol), current_agent(bottom_goal), FOR_ANYTHING_TF, TRUE);
02713 } else {
02714
02715
02716
02717 if (current_agent(bottom_goal)->id.operator_slot->wmes)
02718 print_stack_trace(current_agent(bottom_goal)->id.operator_slot->wmes->value,
02719 current_agent(bottom_goal), FOR_OPERATORS_TF, TRUE);
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729 else {
02730
02731
02732 #ifndef SOAR_8_ONLY
02733 if (current_agent(operand2_mode) == FALSE)
02734 print_stack_trace(current_agent(bottom_goal), current_agent(bottom_goal), FOR_STATES_TF, TRUE);
02735
02736
02737 else {
02738 #endif
02739 if (current_agent(d_cycle_count) == 0)
02740 print_stack_trace(current_agent(bottom_goal), current_agent(bottom_goal), FOR_STATES_TF, TRUE);
02741 else {
02742 if (current_agent(bottom_goal)->id.higher_goal &&
02743 current_agent(bottom_goal)->id.higher_goal->id.operator_slot->wmes) {
02744 print_stack_trace(current_agent(bottom_goal), current_agent(bottom_goal), FOR_STATES_TF, FALSE);
02745 } else {
02746 print_stack_trace(current_agent(bottom_goal), current_agent(bottom_goal), FOR_STATES_TF, TRUE);
02747 }
02748 }
02749 #ifndef SOAR_8_ONLY
02750 }
02751 #endif
02752 }
02753 }
02754
02755
02756 }
02757
02758
02759
02760 void uniquely_add_to_head_of_dll(instantiation * inst)
02761 {
02762
02763 parent_inst *new_pi, *curr_pi;
02764
02765
02766
02767 for (curr_pi = current_agent(parent_list_head); curr_pi; curr_pi = curr_pi->next) {
02768 if (curr_pi->inst == inst) {
02769 #ifdef DEBUG_GDS
02770 print_with_symbols("UNIQUE DLL: %y is already in parent list\n", curr_pi->inst->prod->name);
02771 #endif
02772 return;
02773 }
02774 #ifdef DEBUG_GDS
02775 print_with_symbols("UNIQUE DLL: %y\n", curr_pi->inst->prod->name);
02776 #endif
02777 }
02778
02779 new_pi = (parent_inst *) malloc(sizeof(parent_inst));
02780 new_pi->next = NIL;
02781 new_pi->prev = NIL;
02782 new_pi->inst = inst;
02783
02784 new_pi->next = current_agent(parent_list_head);
02785
02786 if (current_agent(parent_list_head) != NIL)
02787 current_agent(parent_list_head)->prev = new_pi;
02788
02789 current_agent(parent_list_head) = new_pi;
02790 #ifdef DEBUG_GDS
02791 print_with_symbols("UNIQUE DLL: added: %y\n", inst->prod->name);
02792 #endif
02793 }
02794
02795 void elaborate_gds()
02796 {
02797
02798 wme *wme_matching_this_cond;
02799 goal_stack_level wme_goal_level;
02800 preference *pref_for_this_wme, *pref;
02801 condition *cond;
02802 parent_inst *curr_pi, *temp_pi;
02803 slot *s;
02804 instantiation *inst;
02805
02806 for (curr_pi = current_agent(parent_list_head); curr_pi; curr_pi = temp_pi) {
02807
02808 inst = curr_pi->inst;
02809
02810 #ifdef DEBUG_GDS
02811 print_with_symbols("\n EXPLORING INSTANTIATION: %y\n", curr_pi->inst->prod->name);
02812 print(" ");
02813 print_instantiation_with_wmes(curr_pi->inst, TIMETAG_WME_TRACE);
02814 #endif
02815
02816 for (cond = inst->top_of_instantiated_conditions; cond != NIL; cond = cond->next) {
02817
02818 if (cond->type != POSITIVE_CONDITION)
02819 continue;
02820
02821
02822
02823 wme_matching_this_cond = cond->bt.wme;
02824 wme_goal_level = cond->bt.level;
02825 pref_for_this_wme = wme_matching_this_cond->preference;
02826
02827 #ifdef DEBUG_GDS
02828 print("\n wme_matching_this_cond at goal_level = %d : ", wme_goal_level);
02829 print_wme(wme_matching_this_cond);
02830
02831 if (pref_for_this_wme) {
02832 print(" pref_for_this_wme : ");
02833 print_preference(pref_for_this_wme);
02834 }
02835 #endif
02836
02837
02838
02839
02840
02841 if ((pref_for_this_wme == NIL) || (wme_goal_level < inst->match_goal_level)) {
02842
02843 #ifdef DEBUG_GDS
02844 if (pref_for_this_wme == NIL) {
02845 print(" this wme has no preferences (it's an arch-created wme)\n");
02846 } else if (wme_goal_level < inst->match_goal_level) {
02847 print(" this wme is in the supergoal\n");
02848 }
02849 print_with_symbols("inst->match_goal [%y]\n", inst->match_goal);
02850 #endif
02851
02852 if (wme_matching_this_cond->gds != NIL) {
02853
02854
02855 if (wme_matching_this_cond->gds->goal == NIL) {
02856
02857
02858 fast_remove_from_dll(wme_matching_this_cond->gds->wmes_in_gds,
02859 wme_matching_this_cond, wme, gds_next, gds_prev);
02860
02861
02862
02863
02864 if (!wme_matching_this_cond->gds->wmes_in_gds) {
02865 free_memory(wme_matching_this_cond->gds, MISCELLANEOUS_MEM_USAGE);
02866 #ifdef DEBUG_GDS
02867 print("\n REMOVING GDS FROM MEMORY.");
02868 #endif
02869 }
02870 wme_matching_this_cond->gds = inst->match_goal->id.gds;
02871 insert_at_head_of_dll(wme_matching_this_cond->gds->wmes_in_gds,
02872 wme_matching_this_cond, gds_next, gds_prev);
02873 #ifdef DEBUG_GDS
02874 print("\n .....GDS' goal is NIL so switching from old to new GDS list....\n");
02875 #endif
02876
02877 } else if (wme_matching_this_cond->gds->goal->id.level > inst->match_goal_level) {
02878
02879
02880
02881
02882
02883
02884
02885
02886 if (inst->match_goal_level == 1)
02887 print("\n\n\n HELLO! HELLO! The inst->match_goal_level is 1");
02888
02889 fast_remove_from_dll(wme_matching_this_cond->gds->wmes_in_gds,
02890 wme_matching_this_cond, wme, gds_next, gds_prev);
02891 if (!wme_matching_this_cond->gds->wmes_in_gds) {
02892 free_memory(wme_matching_this_cond->gds, MISCELLANEOUS_MEM_USAGE);
02893 #ifdef DEBUG_GDS
02894 print("\n REMOVING GDS FROM MEMORY.");
02895 #endif
02896 }
02897 wme_matching_this_cond->gds = inst->match_goal->id.gds;
02898 insert_at_head_of_dll(wme_matching_this_cond->gds->wmes_in_gds,
02899 wme_matching_this_cond, gds_next, gds_prev);
02900 #ifdef DEBUG_GDS
02901 print("\n ....switching from old to new GDS list....\n");
02902 #endif
02903 wme_matching_this_cond->gds = inst->match_goal->id.gds;
02904 }
02905 } else {
02906
02907
02908
02909 wme_matching_this_cond->gds = inst->match_goal->id.gds;
02910
02911 insert_at_head_of_dll(wme_matching_this_cond->gds->wmes_in_gds,
02912 wme_matching_this_cond, gds_next, gds_prev);
02913 if (wme_matching_this_cond->gds->wmes_in_gds->gds_prev)
02914 print("\nDEBUG DEBUG : The new header should never have a prev value.\n");
02915 #ifdef DEBUG_GDS
02916 print_with_symbols("\n ......WME did not have defined GDS. Now adding to goal [%y].\n",
02917 wme_matching_this_cond->gds->goal);
02918 #endif
02919 }
02920
02921 #ifdef DEBUG_GDS
02922 print(" Added WME to GDS for goal = %d", wme_matching_this_cond->gds->goal->id.level);
02923 print_with_symbols(" [%y]\n", wme_matching_this_cond->gds->goal);
02924 #endif
02925 }
02926
02927 else {
02928
02929
02930
02931
02932 if (pref_for_this_wme->o_supported == TRUE) {
02933 #ifdef DEBUG_GDS
02934 print(" this wme is local and o-supported\n");
02935 #endif
02936 continue;
02937 }
02938
02939 else {
02940
02941
02942
02943
02944 if (inst->match_goal_level == 1) {
02945 #ifdef DEBUG_GDS
02946 print(" don't back up through top state\n");
02947 if (inst->prod)
02948 if (inst->prod->name)
02949 print_with_symbols(" don't back up through top state for instantiation %y\n",
02950 inst->prod->name);
02951 #endif
02952 continue;
02953 }
02954
02955 else {
02956 #ifdef DEBUG_GDS
02957 print(" this wme is local and i-supported\n");
02958 #endif
02959 s = find_slot(pref_for_this_wme->id, pref_for_this_wme->attr);
02960 if (s == NIL) {
02961
02962
02963 #ifdef DEBUG_GDS
02964 print("here's the wme with no slot:\t");
02965 print_wme(pref_for_this_wme->inst->top_of_instantiated_conditions->bt.wme);
02966 #endif
02967
02968
02969
02970
02971 {
02972 wme *fake_inst_wme_cond;
02973
02974 fake_inst_wme_cond = pref_for_this_wme->inst->top_of_instantiated_conditions->bt.wme;
02975 if (fake_inst_wme_cond->gds != NIL) {
02976
02977
02978 if (fake_inst_wme_cond->gds->goal == NIL) {
02979
02980
02981
02982 fast_remove_from_dll(fake_inst_wme_cond->gds->wmes_in_gds,
02983 fake_inst_wme_cond, wme, gds_next, gds_prev);
02984
02985
02986
02987
02988 if (!fake_inst_wme_cond->gds->wmes_in_gds) {
02989 free_memory(fake_inst_wme_cond->gds, MISCELLANEOUS_MEM_USAGE);
02990 #ifdef DEBUG_GDS
02991 print("\n REMOVING GDS FROM MEMORY.");
02992 #endif
02993 }
02994
02995 fake_inst_wme_cond->gds = inst->match_goal->id.gds;
02996 insert_at_head_of_dll(fake_inst_wme_cond->gds->wmes_in_gds,
02997 fake_inst_wme_cond, gds_next, gds_prev);
02998 #ifdef DEBUG_GDS
02999 print
03000 ("\n .....GDS' goal is NIL so switching from old to new GDS list....\n");
03001 #endif
03002 } else if (fake_inst_wme_cond->gds->goal->id.level > inst->match_goal_level) {
03003
03004
03005
03006
03007
03008
03009
03010
03011 if (inst->match_goal_level == 1)
03012 print("\n\n\n\n\n HELLO! HELLO! The inst->match_goal_level is 1");
03013
03014 fast_remove_from_dll(fake_inst_wme_cond->gds->wmes_in_gds,
03015 fake_inst_wme_cond, wme, gds_next, gds_prev);
03016 if (!fake_inst_wme_cond->gds->wmes_in_gds) {
03017 free_memory(fake_inst_wme_cond->gds, MISCELLANEOUS_MEM_USAGE);
03018 #ifdef DEBUG_GDS
03019 print("\n REMOVING GDS FROM MEMORY.");
03020 #endif
03021 }
03022
03023 fake_inst_wme_cond->gds = inst->match_goal->id.gds;
03024 insert_at_head_of_dll(fake_inst_wme_cond->gds->wmes_in_gds,
03025 fake_inst_wme_cond, gds_next, gds_prev);
03026 #ifdef DEBUG_GDS
03027 print("\n .....switching from old to new GDS list....\n");
03028 #endif
03029 fake_inst_wme_cond->gds = inst->match_goal->id.gds;
03030 }
03031 } else {
03032
03033
03034
03035 fake_inst_wme_cond->gds = inst->match_goal->id.gds;
03036
03037 insert_at_head_of_dll(fake_inst_wme_cond->gds->wmes_in_gds,
03038 fake_inst_wme_cond, gds_next, gds_prev);
03039 if (fake_inst_wme_cond->gds->wmes_in_gds->gds_prev)
03040 print("\nDEBUG DEBUG : The new header should never have a prev value.\n");
03041 #ifdef DEBUG_GDS
03042 print_with_symbols
03043 ("\n ......WME did not have defined GDS. Now adding to goal [%y].\n",
03044 fake_inst_wme_cond->gds->goal);
03045 #endif
03046 }
03047 #ifdef DEBUG_GDS
03048 print(" Added WME to GDS for goal = %d",
03049 fake_inst_wme_cond->gds->goal->id.level);
03050 print_with_symbols(" [%y]\n", fake_inst_wme_cond->gds->goal);
03051 #endif
03052 }
03053 } else {
03054
03055
03056
03057 for (pref=s->preferences[ACCEPTABLE_PREFERENCE_TYPE];
03058 pref;
03059 pref=pref->next) {
03060
03061 #ifdef DEBUG_GDS
03062 print(" looking at pref for the wme: ");
03063 print_preference(pref);
03064 #endif
03065
03066 if (pref->inst->GDS_evaluated_already == FALSE) {
03067 #ifdef DEBUG_GDS
03068 print_with_symbols("\n adding inst that produced the pref to GDS: %y\n",pref->inst->prod->name);
03069 #endif
03070
03071
03072
03073
03074
03075
03076
03077 if (pref->inst->match_goal_level <= inst->match_goal_level) {
03078 uniquely_add_to_head_of_dll(pref->inst);
03079 pref->inst->GDS_evaluated_already = TRUE;
03080 } else {
03081 #ifdef DEBUG_GDS
03082 print_with_symbols("\n ignoring inst %y because it is at a lower level than the GDS\n",pref->inst->prod->name);
03083 #endif
03084
03085 }
03086
03087
03088
03089 } else {
03090 #ifdef DEBUG_GDS
03091 print(" the inst producing this pref was already explored; skipping it\n");
03092 #endif
03093 }
03094
03095 }
03096 }
03097 }
03098 }
03099 }
03100
03101 }
03102
03103
03104
03105 #ifdef DEBUG_GDS
03106 print_with_symbols("\n removing instantiation: %y\n", curr_pi->inst->prod->name);
03107 #endif
03108
03109 if (curr_pi->next != NIL)
03110 curr_pi->next->prev = curr_pi->prev;
03111 if (curr_pi->prev != NIL)
03112 curr_pi->prev->next = curr_pi->next;
03113
03114 if (current_agent(parent_list_head) == curr_pi)
03115 current_agent(parent_list_head) = curr_pi->next;
03116
03117 temp_pi = curr_pi->next;
03118 free(curr_pi);
03119
03120 }
03121
03122 if (current_agent(parent_list_head) != NIL) {
03123 #ifdef DEBUG_GDS
03124 print("\n RECURSING using these parents:\n");
03125 for (curr_pi = current_agent(parent_list_head); curr_pi; curr_pi = curr_pi->next) {
03126 print_with_symbols(" %y\n", curr_pi->inst->prod->name);
03127 }
03128 #endif
03129
03130
03131
03132 elaborate_gds();
03133
03134
03135
03136 free_parent_list();
03137 }
03138
03139 }
03140
03141
03142
03143
03144
03145
03146
03147
03148
03149
03150 void gds_invalid_so_remove_goal(wme * w)
03151 {
03152 #ifndef NO_TIMING_STUFF
03153 #ifdef DETAILED_TIMING_STATS
03154
03155 start_timer(¤t_agent(start_gds_tv));
03156
03157 #endif
03158 #endif
03159
03160 if (current_agent(soar_verbose_flag))
03161 soar_ecGDSPrint();
03162
03163
03164
03165
03166
03167
03168
03169
03170
03171
03172
03173
03174
03175
03176
03177
03178
03179
03180 if (current_agent(highest_goal_whose_context_changed)) {
03181 if (current_agent(highest_goal_whose_context_changed)->id.level >= w->gds->goal->id.level) {
03182 current_agent(highest_goal_whose_context_changed) = w->gds->goal->id.higher_goal;
03183 }
03184 } else {
03185
03186
03187 current_agent(highest_goal_whose_context_changed) = w->gds->goal->id.higher_goal;
03188 }
03189
03190 #ifndef TRACE_CONTEXT_DECISIONS_ONLY
03191
03192 if (current_agent(sysparams)[TRACE_OPERAND2_REMOVALS_SYSPARAM]) {
03193 print_with_symbols("\n REMOVING GOAL [%y] due to change in GDS WME ", w->gds->goal);
03194 print_wme(w);
03195 }
03196 #endif
03197
03198 remove_existing_context_and_descendents(w->gds->goal);
03199
03200
03201
03202
03203
03204
03205
03206 #ifndef NO_TIMING_STUFF
03207 #ifdef DETAILED_TIMING_STATS
03208
03209 stop_timer(¤t_agent(start_gds_tv), ¤t_agent(gds_cpu_time[current_agent(current_phase)]));
03210
03211 #endif
03212 #endif
03213 }
03214
03215 void free_parent_list()
03216 {
03217 parent_inst *curr_pi;
03218
03219 for (curr_pi = current_agent(parent_list_head); curr_pi; curr_pi = curr_pi->next)
03220 free(curr_pi);
03221
03222 current_agent(parent_list_head) = NIL;
03223 }
03224
03225 void create_gds_for_goal(Symbol * goal)
03226 {
03227 goal_dependency_set *gds;
03228
03229 gds = allocate_memory(sizeof(goal_dependency_set), MISCELLANEOUS_MEM_USAGE);
03230 gds->goal = goal;
03231 gds->wmes_in_gds = NIL;
03232 goal->id.gds = gds;
03233 #ifdef DEBUG_GDS
03234 print_with_symbols("\nCreated GDS for goal [%y].\n", gds->goal);
03235 #endif
03236 }
03237
03238 #ifdef NUMERIC_INDIFFERENCE
03239
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249
03250
03251
03252
03253
03254
03255
03256
03257
03258
03259
03260 void initialize_indifferent_candidates_for_probability_selection(preference * candidates)
03261 {
03262 preference *cand = 0;
03263
03264 for (cand = candidates; cand != NIL; cand = cand->next_candidate) {
03265
03266
03267 cand->value->common.decider_flag = CANDIDATE_DECIDER_FLAG;
03268 cand->total_preferences_for_candidate = 0;
03269 cand->sum_of_probability = 0;
03270
03271 }
03272 }
03273
03274
03275 unsigned int count_candidates(preference * candidates)
03276 {
03277 unsigned int numCandidates = 0;
03278 preference *cand = 0;
03279
03280
03281
03282
03283
03284
03285
03286
03287
03288
03289 for (cand = candidates; cand != NIL; cand = cand->next_candidate)
03290 numCandidates++;
03291
03292 return numCandidates;
03293 }
03294
03295
03296
03297
03298
03299 #define TEMPERATURE 25.0
03300
03301 preference *probabilistically_select(slot * s, preference * candidates)
03302 {
03303 preference *cand = 0;
03304 preference *pref = 0;
03305 double total_probability = 0;
03306 unsigned int numCandidates = 0;
03307 double selectedProbability = 0;
03308 double currentSumOfValues = 0;
03309 static int initialized_rand = 0;
03310 unsigned long rn = 0;
03311 double default_ni;
03312
03313
03314
03315
03316
03317 assert(s != 0);
03318 assert(candidates != 0);
03319
03320 if (!initialized_rand) {
03321 srand((unsigned) time(NULL));
03322 initialized_rand = 1;
03323 }
03324
03325
03326
03327
03328
03329
03330
03331
03332
03333
03334 initialize_indifferent_candidates_for_probability_selection(candidates);
03335 numCandidates = count_candidates(candidates);
03336
03337
03338
03339
03340
03341
03342
03343
03344 switch (current_agent(numeric_indifferent_mode)) {
03345 case NUMERIC_INDIFFERENT_MODE_AVG:
03346 default_ni = 50;
03347 break;
03348
03349 case NUMERIC_INDIFFERENT_MODE_SUM:
03350 default:
03351 default_ni = 0;
03352 break;
03353 }
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364 for (pref = s->preferences[BINARY_INDIFFERENT_PREFERENCE_TYPE]; pref != NIL; pref = pref->next) {
03365
03366 float value;
03367 if (pref->referent->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE) {
03368 value = pref->referent->fc.value;
03369 } else if (pref->referent->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) {
03370 value = (float) pref->referent->ic.value;
03371 } else
03372 continue;
03373 for (cand = candidates; cand != NIL; cand = cand->next_candidate) {
03374
03375
03376 if (cand->value == pref->value) {
03377 cand->total_preferences_for_candidate += 1;
03378 cand->sum_of_probability += value;
03379 }
03380 }
03381 }
03382
03383 for (cand = candidates; cand != NIL; cand = cand->next_candidate) {
03384 if (cand->total_preferences_for_candidate == 0) {
03385 cand->sum_of_probability = default_ni;
03386 cand->total_preferences_for_candidate = 1;
03387 }
03388 }
03389
03390 if (current_agent(numeric_indifferent_mode) == NUMERIC_INDIFFERENT_MODE_SUM) {
03391
03392 total_probability = 0.0;
03393 for (cand = candidates; cand != NIL; cand = cand->next_candidate) {
03394
03395 if (current_agent(sysparams)[TRACE_INDIFFERENT_SYSPARAM]){
03396 print_with_symbols("\n Candidate %y: ", cand->value);
03397 print("Value (Sum) = %f", exp(cand->sum_of_probability / TEMPERATURE));
03398 }
03399
03400
03401
03402
03403 total_probability += exp(cand->sum_of_probability / TEMPERATURE);
03404
03405 }
03406
03407
03408
03409 print("\n");
03410 rn = rand();
03411 selectedProbability = ((double) rn / (double) RAND_MAX) * total_probability;
03412 currentSumOfValues = 0;
03413
03414 for (cand = candidates; cand != NIL; cand = cand->next_candidate) {
03415
03416 currentSumOfValues += exp(cand->sum_of_probability / TEMPERATURE);
03417
03418 if (selectedProbability <= currentSumOfValues) {
03419
03420
03421
03422
03423 return cand;
03424 }
03425 }
03426
03427 } else if (current_agent(numeric_indifferent_mode) == NUMERIC_INDIFFERENT_MODE_AVG) {
03428
03429 total_probability = 0.0;
03430 for (cand = candidates; cand != NIL; cand = cand->next_candidate) {
03431
03432 if (current_agent(sysparams)[TRACE_INDIFFERENT_SYSPARAM]) {
03433 print_with_symbols("\n Candidate %y: ", cand->value);
03434 print("Value (Avg) = %f", fabs(cand->sum_of_probability / cand->total_preferences_for_candidate));
03435 }
03436
03437
03438
03439
03440
03441 total_probability += fabs(cand->sum_of_probability / cand->total_preferences_for_candidate);
03442
03443 if (cand->sum_of_probability < 0.0) {
03444 print_with_symbols
03445 ("WARNING: Candidate %y has a negative value, which is unexpected with 'numeric-indifferent-mode -avg'",
03446 cand->value);
03447 }
03448
03449 }
03450
03451
03452
03453 print("\n");
03454 rn = rand();
03455 selectedProbability = ((double) rn / (double) RAND_MAX) * total_probability;
03456 currentSumOfValues = 0;
03457
03458 for (cand = candidates; cand != NIL; cand = cand->next_candidate) {
03459
03460 currentSumOfValues += fabs(cand->sum_of_probability / cand->total_preferences_for_candidate);
03461
03462 if (selectedProbability <= currentSumOfValues) {
03463
03464
03465
03466
03467 return cand;
03468 }
03469 }
03470
03471 } else {
03472 print("\nERROR: Invalid Numeric Indifferent Mode!\n");
03473 }
03474
03475 print("\nERROR: Probability Selection failed. This should never happen.\n");
03476 return NIL;
03477
03478 }
03479
03480 #endif