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 #include "soarkernel.h"
00045 #include <ctype.h>
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 char *name_of_production_being_reordered;
00063
00064 #define symbol_is_constant_or_marked_variable(sym,tc) \
00065 ( ((sym)->common.symbol_type!=VARIABLE_SYMBOL_TYPE) || \
00066 ((sym)->var.tc_num == (tc)) )
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 bool legal_to_execute_action(action * a, tc_number tc);
00093
00094 bool reorder_action_list(action ** action_list, tc_number lhs_tc)
00095 {
00096 list *new_bound_vars;
00097 action *remaining_actions;
00098 action *first_action, *last_action;
00099 action *a, *prev_a;
00100 bool result_flag;
00101
00102 new_bound_vars = NIL;
00103 remaining_actions = *action_list;
00104 first_action = NIL;
00105 last_action = NIL;
00106
00107 while (remaining_actions) {
00108
00109 prev_a = NIL;
00110 a = remaining_actions;
00111 for (;;) {
00112 if (!a)
00113 break;
00114 if (legal_to_execute_action(a, lhs_tc))
00115 break;
00116 prev_a = a;
00117 a = a->next;
00118 }
00119 if (!a)
00120 break;
00121
00122 if (prev_a)
00123 prev_a->next = a->next;
00124 else
00125 remaining_actions = a->next;
00126 a->next = NIL;
00127 if (last_action)
00128 last_action->next = a;
00129 else
00130 first_action = a;
00131 last_action = a;
00132
00133 add_all_variables_in_action(a, lhs_tc, &new_bound_vars);
00134 }
00135
00136 if (remaining_actions) {
00137
00138 print("Error: production %s has a bad RHS--\n", name_of_production_being_reordered);
00139 print(" Either it creates structure not connected to anything\n");
00140 print(" else in WM, or it tries to pass an unbound variable as\n");
00141 print(" an argument to a function.\n");
00142
00143 if (last_action)
00144 last_action->next = remaining_actions;
00145 else
00146 first_action = remaining_actions;
00147 result_flag = FALSE;
00148 } else {
00149 result_flag = TRUE;
00150 }
00151
00152
00153 unmark_variables_and_free_list(new_bound_vars);
00154
00155
00156 *action_list = first_action;
00157 return result_flag;
00158 }
00159
00160 bool all_variables_in_rhs_value_bound(rhs_value rv, tc_number tc)
00161 {
00162 cons *c;
00163 list *fl;
00164 Symbol *sym;
00165
00166 if (rhs_value_is_funcall(rv)) {
00167
00168 fl = rhs_value_to_funcall_list(rv);
00169 for (c = fl->rest; c != NIL; c = c->rest)
00170 if (!all_variables_in_rhs_value_bound(c->first, tc))
00171 return FALSE;
00172 return TRUE;
00173 } else {
00174
00175 sym = rhs_value_to_symbol(rv);
00176 if (sym->common.symbol_type == VARIABLE_SYMBOL_TYPE)
00177 return (bool) (sym->var.tc_num == tc);
00178 return TRUE;
00179 }
00180 }
00181
00182 bool legal_to_execute_action(action * a, tc_number tc)
00183 {
00184 if (a->type == MAKE_ACTION) {
00185 if (!all_variables_in_rhs_value_bound(a->id, tc))
00186 return FALSE;
00187 if (rhs_value_is_funcall(a->attr) && (!all_variables_in_rhs_value_bound(a->attr, tc)))
00188 return FALSE;
00189 if (rhs_value_is_funcall(a->value) && (!all_variables_in_rhs_value_bound(a->value, tc)))
00190 return FALSE;
00191 if (preference_is_binary(a->preference_type) &&
00192 rhs_value_is_funcall(a->referent) && (!all_variables_in_rhs_value_bound(a->referent, tc)))
00193 return FALSE;
00194 return TRUE;
00195 }
00196
00197 return all_variables_in_rhs_value_bound(a->value, tc);
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 typedef struct saved_test_struct {
00224 struct saved_test_struct *next;
00225 Symbol *var;
00226 test the_test;
00227 } saved_test;
00228
00229 void print_saved_test(saved_test * st)
00230 {
00231 print_with_symbols(" Symbol: %y Test: ", st->var);
00232 print_string(test_to_string(st->the_test, NULL, 0));
00233 }
00234
00235 void print_saved_test_list(saved_test * st)
00236 {
00237 while (st) {
00238 print_saved_test(st);
00239 print("\n");
00240 st = st->next;
00241 }
00242 }
00243
00244 saved_test *simplify_test(test * t, saved_test * old_sts)
00245 {
00246 test new, subtest;
00247 saved_test *saved;
00248 Symbol *var, *sym;
00249 cons *c, *prev_c, *next_c;
00250 complex_test *ct;
00251
00252 if (test_is_blank_test(*t)) {
00253 sym = generate_new_variable("dummy-");
00254 *t = make_equality_test_without_adding_reference(sym);
00255 return old_sts;
00256 }
00257
00258 if (test_is_blank_or_equality_test(*t)) {
00259 return old_sts;
00260 }
00261
00262 ct = complex_test_from_test(*t);
00263
00264 switch (ct->type) {
00265
00266 case CONJUNCTIVE_TEST:
00267
00268 sym = NIL;
00269 for (c = ct->data.conjunct_list; c != NIL; c = c->rest) {
00270 subtest = c->first;
00271 if (test_is_blank_or_equality_test(subtest))
00272 sym = referent_of_equality_test(subtest);
00273 }
00274
00275 if (!sym) {
00276 sym = generate_new_variable("dummy-");
00277 new = make_equality_test_without_adding_reference(sym);
00278 allocate_cons(&c);
00279 c->first = new;
00280 c->rest = ct->data.conjunct_list;
00281 ct->data.conjunct_list = c;
00282 }
00283
00284 prev_c = NIL;
00285 c = ct->data.conjunct_list;
00286 while (c) {
00287 next_c = c->rest;
00288 subtest = c->first;
00289 if (!test_is_blank_or_equality_test(subtest)) {
00290
00291 allocate_with_pool(¤t_agent(saved_test_pool), &saved);
00292 saved->next = old_sts;
00293 old_sts = saved;
00294 saved->var = sym;
00295 symbol_add_ref(sym);
00296 saved->the_test = subtest;
00297 if (prev_c)
00298 prev_c->rest = next_c;
00299 else
00300 ct->data.conjunct_list = next_c;
00301 free_cons(c);
00302 } else {
00303 prev_c = c;
00304 }
00305 c = next_c;
00306 }
00307 break;
00308
00309 default:
00310
00311 var = generate_new_variable("dummy-");
00312 new = make_equality_test_without_adding_reference(var);
00313 allocate_with_pool(¤t_agent(saved_test_pool), &saved);
00314 saved->next = old_sts;
00315 old_sts = saved;
00316 saved->var = var;
00317 symbol_add_ref(var);
00318 saved->the_test = *t;
00319 *t = new;
00320 break;
00321 }
00322 return old_sts;
00323 }
00324
00325 saved_test *simplify_condition_list(condition * conds_list)
00326 {
00327 condition *c;
00328 saved_test *sts;
00329
00330 sts = NIL;
00331 for (c = conds_list; c != NIL; c = c->next) {
00332 if (c->type == POSITIVE_CONDITION) {
00333 sts = simplify_test(&(c->data.tests.id_test), sts);
00334 sts = simplify_test(&(c->data.tests.attr_test), sts);
00335 sts = simplify_test(&(c->data.tests.value_test), sts);
00336 }
00337 }
00338 return sts;
00339 }
00340
00341 byte reverse_direction_of_relational_test(byte type)
00342 {
00343 switch (type) {
00344 case NOT_EQUAL_TEST:
00345 return NOT_EQUAL_TEST;
00346 case LESS_TEST:
00347 return GREATER_TEST;
00348 case GREATER_TEST:
00349 return LESS_TEST;
00350 case LESS_OR_EQUAL_TEST:
00351 return GREATER_OR_EQUAL_TEST;
00352 case GREATER_OR_EQUAL_TEST:
00353 return LESS_OR_EQUAL_TEST;
00354 case SAME_TYPE_TEST:
00355 return SAME_TYPE_TEST;
00356 default:
00357 {
00358 char msg[MESSAGE_SIZE];
00359 strncpy(msg, "Internal error: arg to reverse_direction_of_relational_test\n", MESSAGE_SIZE);
00360 msg[MESSAGE_SIZE - 1] = 0;
00361 abort_with_fatal_error(msg);
00362 }
00363 }
00364 return 0;
00365 }
00366
00367 saved_test *restore_saved_tests_to_test(test * t,
00368 bool is_id_field, tc_number bound_vars_tc_number, saved_test * tests_to_restore)
00369 {
00370 saved_test *st, *prev_st, *next_st;
00371 bool added_it;
00372 Symbol *referent;
00373 complex_test *ct;
00374
00375 prev_st = NIL;
00376 st = tests_to_restore;
00377 while (st) {
00378 next_st = st->next;
00379 added_it = FALSE;
00380 ct = complex_test_from_test(st->the_test);
00381 switch (ct->type) {
00382 case GOAL_ID_TEST:
00383 case IMPASSE_ID_TEST:
00384 if (!is_id_field)
00385 break;
00386
00387 case DISJUNCTION_TEST:
00388 if (test_includes_equality_test_for_symbol(*t, st->var)) {
00389 add_new_test_to_test_if_not_already_there(t, st->the_test);
00390 added_it = TRUE;
00391 }
00392 break;
00393 default:
00394 referent = ct->data.referent;
00395 if (test_includes_equality_test_for_symbol(*t, st->var)) {
00396 if (symbol_is_constant_or_marked_variable(referent, bound_vars_tc_number) || (st->var == referent)) {
00397 add_new_test_to_test_if_not_already_there(t, st->the_test);
00398 added_it = TRUE;
00399 }
00400 } else if (test_includes_equality_test_for_symbol(*t, referent)) {
00401 if (symbol_is_constant_or_marked_variable(st->var, bound_vars_tc_number) || (st->var == referent)) {
00402 ct->type = reverse_direction_of_relational_test(ct->type);
00403 ct->data.referent = st->var;
00404 st->var = referent;
00405 add_new_test_to_test_if_not_already_there(t, st->the_test);
00406 added_it = TRUE;
00407 }
00408 }
00409 break;
00410 }
00411 if (added_it) {
00412 if (prev_st)
00413 prev_st->next = next_st;
00414 else
00415 tests_to_restore = next_st;
00416 symbol_remove_ref(st->var);
00417 free_with_pool(¤t_agent(saved_test_pool), st);
00418 } else {
00419 prev_st = st;
00420 }
00421 st = next_st;
00422 }
00423 return tests_to_restore;
00424 }
00425
00426 void restore_and_deallocate_saved_tests(condition * conds_list,
00427
00428 tc_number tc, saved_test * tests_to_restore)
00429 {
00430 condition *cond;
00431 list *new_vars;
00432
00433 new_vars = NIL;
00434 for (cond = conds_list; cond != NIL; cond = cond->next) {
00435 if (cond->type != POSITIVE_CONDITION)
00436 continue;
00437 tests_to_restore = restore_saved_tests_to_test((&cond->data.tests.id_test), TRUE, tc, tests_to_restore);
00438 add_bound_variables_in_test(cond->data.tests.id_test, tc, &new_vars);
00439 tests_to_restore = restore_saved_tests_to_test((&cond->data.tests.attr_test), FALSE, tc, tests_to_restore);
00440 add_bound_variables_in_test(cond->data.tests.attr_test, tc, &new_vars);
00441 tests_to_restore = restore_saved_tests_to_test((&cond->data.tests.value_test), FALSE, tc, tests_to_restore);
00442 add_bound_variables_in_test(cond->data.tests.value_test, tc, &new_vars);
00443 }
00444 if (tests_to_restore) {
00445 if (current_agent(sysparams)[PRINT_WARNINGS_SYSPARAM]) {
00446 print("\nWarning: in production %s,\n", name_of_production_being_reordered);
00447 print(" ignoring test(s) whose referent is unbound:\n");
00448 print_saved_test_list(tests_to_restore);
00449 }
00450
00451 }
00452 unmark_variables_and_free_list(new_vars);
00453 }
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 list *collect_vars_tested_by_test_that_are_bound(test t, tc_number tc, list * starting_list)
00478 {
00479 cons *c;
00480 complex_test *ct;
00481 Symbol *referent;
00482
00483 if (test_is_blank_test(t))
00484 return starting_list;
00485
00486 if (test_is_blank_or_equality_test(t)) {
00487 referent = referent_of_equality_test(t);
00488 if (referent->common.symbol_type == VARIABLE_SYMBOL_TYPE)
00489 if (referent->var.tc_num == tc)
00490 starting_list = add_if_not_member(referent, starting_list);
00491 return starting_list;
00492 }
00493
00494 ct = complex_test_from_test(t);
00495
00496 switch (ct->type) {
00497 case GOAL_ID_TEST:
00498 case IMPASSE_ID_TEST:
00499 case DISJUNCTION_TEST:
00500 return starting_list;
00501
00502 case CONJUNCTIVE_TEST:
00503 for (c = ct->data.conjunct_list; c != NIL; c = c->rest)
00504 starting_list = collect_vars_tested_by_test_that_are_bound(c->first, tc, starting_list);
00505 return starting_list;
00506
00507 default:
00508
00509 referent = ct->data.referent;
00510 if (referent->common.symbol_type == VARIABLE_SYMBOL_TYPE)
00511 if (referent->var.tc_num == tc)
00512 starting_list = add_if_not_member(referent, starting_list);
00513 return starting_list;
00514 }
00515 }
00516
00517 list *collect_vars_tested_by_cond_that_are_bound(condition * cond, tc_number tc, list * starting_list)
00518 {
00519 condition *c;
00520
00521 if (cond->type == CONJUNCTIVE_NEGATION_CONDITION) {
00522
00523 for (c = cond->data.ncc.top; c != NIL; c = c->next)
00524 starting_list = collect_vars_tested_by_cond_that_are_bound(c, tc, starting_list);
00525 } else {
00526
00527 starting_list = collect_vars_tested_by_test_that_are_bound(cond->data.tests.id_test, tc, starting_list);
00528 starting_list = collect_vars_tested_by_test_that_are_bound(cond->data.tests.attr_test, tc, starting_list);
00529 starting_list = collect_vars_tested_by_test_that_are_bound(cond->data.tests.value_test, tc, starting_list);
00530 }
00531 return starting_list;
00532 }
00533
00534 void fill_in_vars_requiring_bindings(condition * cond_list, tc_number tc)
00535 {
00536 list *new_bound_vars;
00537 condition *c;
00538
00539
00540 new_bound_vars = NIL;
00541 for (c = cond_list; c != NIL; c = c->next)
00542 if (c->type == POSITIVE_CONDITION)
00543 add_bound_variables_in_condition(c, tc, &new_bound_vars);
00544
00545
00546 for (c = cond_list; c != NIL; c = c->next) {
00547 if (c->type != POSITIVE_CONDITION)
00548 c->reorder.vars_requiring_bindings = collect_vars_tested_by_cond_that_are_bound(c, tc, NIL);
00549 if (c->type == CONJUNCTIVE_NEGATION_CONDITION)
00550 fill_in_vars_requiring_bindings(c->data.ncc.top, tc);
00551 }
00552
00553 unmark_variables_and_free_list(new_bound_vars);
00554 }
00555
00556 void remove_vars_requiring_bindings(condition * cond_list)
00557 {
00558 condition *c;
00559
00560
00561 for (c = cond_list; c != NIL; c = c->next) {
00562 if (c->type != POSITIVE_CONDITION)
00563 free_list(c->reorder.vars_requiring_bindings);
00564 if (c->type == CONJUNCTIVE_NEGATION_CONDITION)
00565 remove_vars_requiring_bindings(c->data.ncc.top);
00566 }
00567 }
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582 list *collect_root_variables(condition * cond_list, tc_number tc,
00583 bool allow_printing_warnings)
00584 {
00585
00586 list *new_vars_from_value_slot;
00587 list *new_vars_from_id_slot;
00588 cons *c;
00589 condition *cond;
00590 bool found_goal_impasse_test;
00591
00592
00593 new_vars_from_value_slot = NIL;
00594 for (cond = cond_list; cond != NIL; cond = cond->next)
00595 if (cond->type == POSITIVE_CONDITION)
00596 add_bound_variables_in_test(cond->data.tests.value_test, tc, &new_vars_from_value_slot);
00597
00598
00599 new_vars_from_id_slot = NIL;
00600 for (cond = cond_list; cond != NIL; cond = cond->next)
00601 if (cond->type == POSITIVE_CONDITION)
00602 add_bound_variables_in_test(cond->data.tests.id_test, tc, &new_vars_from_id_slot);
00603
00604
00605 unmark_variables_and_free_list(new_vars_from_value_slot);
00606 for (c = new_vars_from_id_slot; c != NIL; c = c->rest)
00607 ((Symbol *) (c->first))->var.tc_num = 0;
00608
00609
00610 if (allow_printing_warnings && current_agent(sysparams)[PRINT_WARNINGS_SYSPARAM]) {
00611 for (c = new_vars_from_id_slot; c != NIL; c = c->rest) {
00612 found_goal_impasse_test = FALSE;
00613 for (cond = cond_list; cond != NIL; cond = cond->next) {
00614 if (cond->type != POSITIVE_CONDITION)
00615 continue;
00616 if (test_includes_equality_test_for_symbol(cond->data.tests.id_test, c->first))
00617 if (test_includes_goal_or_impasse_id_test(cond->data.tests.id_test, TRUE, TRUE)) {
00618 found_goal_impasse_test = TRUE;
00619 break;
00620 }
00621 }
00622 if (!found_goal_impasse_test) {
00623 print("\nWarning: On the LHS of production %s, identifier ", name_of_production_being_reordered);
00624 print_with_symbols("%y is not connected to any goal or impasse.\n", (Symbol *) (c->first));
00625 }
00626 }
00627 }
00628
00629 return new_vars_from_id_slot;
00630 }
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642 #define MAX_COST 10000005
00643 #define BF_FOR_ACCEPTABLE_PREFS 8
00644 #define BF_FOR_VALUES 8
00645 #define BF_FOR_ATTRIBUTES 8
00646
00647
00648
00649
00650
00651
00652
00653
00654 bool test_covered_by_bound_vars(test t, tc_number tc, list * extra_vars)
00655 {
00656 cons *c;
00657 Symbol *referent;
00658 complex_test *ct;
00659
00660 if (test_is_blank_test(t))
00661 return FALSE;
00662
00663 if (test_is_blank_or_equality_test(t)) {
00664 referent = referent_of_equality_test(t);
00665 if (symbol_is_constant_or_marked_variable(referent, tc))
00666 return TRUE;
00667 if (extra_vars)
00668 return member_of_list(referent, extra_vars);
00669 return FALSE;
00670 }
00671
00672 ct = complex_test_from_test(t);
00673 if (ct->type == CONJUNCTIVE_TEST) {
00674 for (c = ct->data.conjunct_list; c != NIL; c = c->rest)
00675 if (test_covered_by_bound_vars(c->first, tc, extra_vars))
00676 return TRUE;
00677 }
00678 return FALSE;
00679 }
00680
00681
00682
00683
00684
00685
00686
00687 long get_cost_of_possible_multi_attribute(Symbol * sym)
00688 {
00689 multi_attribute *m = current_agent(multi_attributes);
00690 while (m) {
00691 if (m->symbol == sym)
00692 return m->value;
00693 m = m->next;
00694 }
00695 return 1;
00696 }
00697
00698
00699
00700
00701
00702
00703
00704
00705 long cost_of_adding_condition(condition * cond, tc_number tc, list * root_vars_not_bound_yet)
00706 {
00707 cons *c;
00708 long result;
00709
00710
00711 if ((!root_vars_not_bound_yet) &&
00712 (cond->type == POSITIVE_CONDITION) &&
00713 (test_is_blank_or_equality_test(cond->data.tests.id_test)) &&
00714 (test_is_blank_or_equality_test(cond->data.tests.attr_test)) &&
00715 (test_is_blank_or_equality_test(cond->data.tests.value_test)) &&
00716 (!test_is_blank_test(cond->data.tests.id_test)) &&
00717 (!test_is_blank_test(cond->data.tests.attr_test)) && (!test_is_blank_test(cond->data.tests.value_test))) {
00718
00719 if (!symbol_is_constant_or_marked_variable(referent_of_equality_test(cond->data.tests.id_test), tc))
00720 return MAX_COST;
00721 if (symbol_is_constant_or_marked_variable(referent_of_equality_test(cond->data.tests.attr_test), tc))
00722 result = get_cost_of_possible_multi_attribute(referent_of_equality_test(cond->data.tests.attr_test));
00723 else
00724 result = BF_FOR_ATTRIBUTES;
00725
00726 if (!symbol_is_constant_or_marked_variable(referent_of_equality_test(cond->data.tests.value_test), tc)) {
00727 if (cond->test_for_acceptable_preference)
00728 result = result * BF_FOR_ACCEPTABLE_PREFS;
00729 else
00730 result = result * BF_FOR_VALUES;
00731 }
00732 return result;
00733 }
00734
00735 if (cond->type == POSITIVE_CONDITION) {
00736
00737 if (!test_covered_by_bound_vars(cond->data.tests.id_test, tc, root_vars_not_bound_yet))
00738 return MAX_COST;
00739 if (test_covered_by_bound_vars(cond->data.tests.attr_test, tc, root_vars_not_bound_yet))
00740 result = 1;
00741 else
00742 result = BF_FOR_ATTRIBUTES;
00743 if (!test_covered_by_bound_vars(cond->data.tests.value_test, tc, root_vars_not_bound_yet)) {
00744 if (cond->test_for_acceptable_preference)
00745 result = result * BF_FOR_ACCEPTABLE_PREFS;
00746 else
00747 result = result * BF_FOR_VALUES;
00748 }
00749 return result;
00750 }
00751
00752
00753
00754 for (c = cond->reorder.vars_requiring_bindings; c != NIL; c = c->rest) {
00755 if (((Symbol *) (c->first))->var.tc_num != tc)
00756 return MAX_COST;
00757 }
00758 return 1;
00759 }
00760
00761
00762
00763
00764
00765
00766
00767 long find_lowest_cost_lookahead(condition * candidates,
00768 condition * chosen, tc_number tc, list * root_vars_not_bound_yet)
00769 {
00770 condition *c;
00771 long min_cost, cost;
00772 list *new_vars;
00773
00774 new_vars = NIL;
00775 add_bound_variables_in_condition(chosen, tc, &new_vars);
00776 min_cost = MAX_COST + 1;
00777 for (c = candidates; c != NIL; c = c->next) {
00778 if (c == chosen)
00779 continue;
00780 cost = cost_of_adding_condition(c, tc, root_vars_not_bound_yet);
00781 if (cost < min_cost) {
00782 min_cost = cost;
00783 if (cost <= 1)
00784 break;
00785 }
00786 }
00787 unmark_variables_and_free_list(new_vars);
00788 return min_cost;
00789 }
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801 void reorder_condition_list(condition ** top_of_conds,
00802 condition ** bottom_of_conds, list * roots, tc_number tc, bool reorder_nccs);
00803
00804 void reorder_simplified_conditions(condition ** top_of_conds,
00805 condition ** bottom_of_conds,
00806 list * roots, tc_number bound_vars_tc_number, bool reorder_nccs)
00807 {
00808 condition *remaining_conds;
00809 condition *first_cond, *last_cond;
00810 condition *cond, *next_cond;
00811 condition *min_cost_conds, *chosen;
00812 long cost = 0, min_cost;
00813 list *new_vars;
00814
00815 remaining_conds = *top_of_conds;
00816 first_cond = NIL;
00817 last_cond = NIL;
00818 new_vars = NIL;
00819
00820
00821
00822
00823
00824
00825
00826 while (remaining_conds) {
00827
00828 min_cost_conds = NIL;
00829 min_cost = 0;
00830 for (cond = remaining_conds; cond != NIL; cond = cond->next) {
00831 cost = cost_of_adding_condition(cond, bound_vars_tc_number, roots);
00832 if ((!min_cost_conds) || (cost < min_cost)) {
00833 min_cost = cost;
00834 min_cost_conds = cond;
00835 cond->reorder.next_min_cost = NIL;
00836 } else if (cost == min_cost) {
00837 cond->reorder.next_min_cost = min_cost_conds;
00838 min_cost_conds = cond;
00839 }
00840
00841
00842
00843
00844 }
00845
00846 if ((min_cost == MAX_COST) && current_agent(sysparams)[PRINT_WARNINGS_SYSPARAM]) {
00847 print("Warning: in production %s,\n", name_of_production_being_reordered);
00848 print(" The LHS conditions are not all connected.\n");
00849
00850 }
00851
00852 if ((min_cost > 1) && (min_cost_conds->reorder.next_min_cost)) {
00853 min_cost = MAX_COST + 1;
00854 for (cond = min_cost_conds, next_cond = cond->reorder.next_min_cost;
00855 cond != NIL; cond = next_cond, next_cond = (cond ? cond->reorder.next_min_cost : NIL)) {
00856 cost = find_lowest_cost_lookahead(remaining_conds, cond, bound_vars_tc_number, roots);
00857 if (cost < min_cost) {
00858 min_cost = cost;
00859 min_cost_conds = cond;
00860 cond->reorder.next_min_cost = NIL;
00861 } else {
00862
00863
00864
00865
00866
00867
00868 if (cost == min_cost && cond->type == POSITIVE_CONDITION) {
00869 if (canonical_cond_greater(min_cost_conds, cond)) {
00870 min_cost = cost;
00871 min_cost_conds = cond;
00872 cond->reorder.next_min_cost = NIL;
00873 }
00874 }
00875 }
00876
00877
00878 }
00879 }
00880
00881 if (min_cost == 1 && (min_cost_conds->reorder.next_min_cost)) {
00882 for (cond = min_cost_conds; cond != NIL; cond = cond->reorder.next_min_cost) {
00883 if (cond->type == POSITIVE_CONDITION &&
00884 min_cost_conds->type == POSITIVE_CONDITION && canonical_cond_greater(min_cost_conds, cond)) {
00885 min_cost = cost;
00886 min_cost_conds = cond;
00887 } else if (cond->type != POSITIVE_CONDITION && min_cost_conds->type == POSITIVE_CONDITION) {
00888 min_cost = cost;
00889 min_cost_conds = cond;
00890 }
00891 }
00892 }
00893
00894
00895
00896 chosen = min_cost_conds;
00897 remove_from_dll(remaining_conds, chosen, next, prev);
00898 if (!first_cond)
00899 first_cond = chosen;
00900
00901
00902 insert_at_head_of_dll(last_cond, chosen, prev, next);
00903
00904
00905 if ((chosen->type == CONJUNCTIVE_NEGATION_CONDITION) && reorder_nccs) {
00906 list *ncc_roots;
00907 ncc_roots = collect_root_variables(chosen->data.ncc.top, bound_vars_tc_number, TRUE);
00908 reorder_condition_list(&(chosen->data.ncc.top),
00909 &(chosen->data.ncc.bottom), ncc_roots, bound_vars_tc_number, reorder_nccs);
00910 free_list(ncc_roots);
00911 }
00912
00913
00914 add_bound_variables_in_condition(chosen, bound_vars_tc_number, &new_vars);
00915
00916
00917 if (roots) {
00918 cons *c;
00919 for (c = roots; c != NIL; c = c->rest)
00920 if (((Symbol *) (c->first))->var.tc_num != bound_vars_tc_number)
00921 break;
00922 if (!c)
00923 roots = NIL;
00924 }
00925
00926 }
00927
00928 unmark_variables_and_free_list(new_vars);
00929 *top_of_conds = first_cond;
00930 *bottom_of_conds = last_cond;
00931 }
00932
00933 void reorder_condition_list(condition ** top_of_conds, condition ** bottom_of_conds, list * roots, tc_number tc,
00934 bool reorder_nccs)
00935 {
00936 saved_test *saved_tests;
00937
00938 saved_tests = simplify_condition_list(*top_of_conds);
00939 reorder_simplified_conditions(top_of_conds, bottom_of_conds, roots, tc, reorder_nccs);
00940 restore_and_deallocate_saved_tests(*top_of_conds, tc, saved_tests);
00941 }
00942
00943
00944
00945
00946
00947
00948
00949 bool test_tests_for_root(test t, list * roots)
00950 {
00951
00952 cons *c;
00953 complex_test *ct;
00954 Symbol *referent;
00955
00956
00957
00958 if (test_is_blank_test(t))
00959 return FALSE;
00960
00961 if (test_is_blank_or_equality_test(t)) {
00962 referent = referent_of_equality_test(t);
00963 if ((referent->common.symbol_type == VARIABLE_SYMBOL_TYPE) && member_of_list(referent, roots))
00964 return TRUE;
00965 return FALSE;
00966 }
00967 ct = complex_test_from_test(t);
00968
00969 switch (ct->type) {
00970 case GOAL_ID_TEST:
00971 case IMPASSE_ID_TEST:
00972 case DISJUNCTION_TEST:
00973 return FALSE;
00974 break;
00975
00976 case CONJUNCTIVE_TEST:
00977 for (c = ct->data.conjunct_list; c != NIL; c = c->rest)
00978 if (test_tests_for_root(c->first, roots))
00979 return TRUE;
00980 return FALSE;
00981 break;
00982
00983 default:
00984
00985 referent = ct->data.referent;
00986 if ((referent->common.symbol_type == VARIABLE_SYMBOL_TYPE) && member_of_list(referent, roots))
00987 return TRUE;
00988 return FALSE;
00989 break;
00990 }
00991 }
00992
00993
00994
00995 void remove_isa_state_tests_for_non_roots(condition ** lhs_top, list * roots)
00996 {
00997 condition *cond;
00998 bool a, b;
00999 test temp;
01000
01001 a = FALSE;
01002 b = FALSE;
01003
01004 for (cond = *lhs_top; cond != NIL; cond = cond->next) {
01005 if ((cond->type == POSITIVE_CONDITION) &&
01006 (test_is_complex_test(cond->data.tests.id_test)) &&
01007 (test_includes_goal_or_impasse_id_test(cond->data.tests.id_test,
01008 TRUE, FALSE)) &&
01009 (!test_tests_for_root(cond->data.tests.id_test, roots))) {
01010 temp = cond->data.tests.id_test;
01011 cond->data.tests.id_test = copy_test_removing_goal_impasse_tests(temp, &a, &b);
01012 deallocate_test(temp);
01013 }
01014 }
01015 }
01016
01017 bool reorder_lhs(condition ** lhs_top, condition ** lhs_bottom, bool reorder_nccs)
01018 {
01019 tc_number tc;
01020 list *roots;
01021
01022 tc = get_new_tc_number();
01023
01024
01025 roots = collect_root_variables(*lhs_top, tc, TRUE);
01026
01027
01028
01029
01030 if (roots)
01031 remove_isa_state_tests_for_non_roots(lhs_top, roots);
01032
01033
01034 if (!roots) {
01035 condition *cond;
01036
01037 for (cond = *lhs_top; cond != NIL; cond = cond->next) {
01038 if ((cond->type == POSITIVE_CONDITION) &&
01039 (test_includes_goal_or_impasse_id_test(cond->data.tests.id_test, TRUE, FALSE))) {
01040 add_bound_variables_in_test(cond->data.tests.id_test, tc, &roots);
01041 if (roots)
01042 break;
01043 }
01044 }
01045 }
01046
01047 if (!roots) {
01048 print("Error: in production %s,\n", name_of_production_being_reordered);
01049 print(" The LHS has no roots.\n");
01050
01051 return FALSE;
01052 }
01053
01054 fill_in_vars_requiring_bindings(*lhs_top, tc);
01055 reorder_condition_list(lhs_top, lhs_bottom, roots, tc, reorder_nccs);
01056 remove_vars_requiring_bindings(*lhs_top);
01057 free_list(roots);
01058 return TRUE;
01059 }
01060
01061 void init_reorderer(void)
01062 {
01063 init_memory_pool(¤t_agent(saved_test_pool), sizeof(saved_test), "saved test");
01064 }