fix invalid answers for mode directed tabling
This commit is contained in:
parent
f06489ffe5
commit
e85854c1bb
@ -518,36 +518,38 @@ static inline void adjust_freeze_registers(void) {
|
||||
|
||||
static inline void mark_as_completed(sg_fr_ptr sg_fr) {
|
||||
LOCK(SgFr_lock(sg_fr));
|
||||
#ifdef MODE_DIRECTED_TABLING
|
||||
if (SgFr_mode_directed(sg_fr) && SgFr_invalid_chain(sg_fr)) {
|
||||
ans_node_ptr current_answer, next_answer;
|
||||
/* first first valid answer */
|
||||
current_answer = SgFr_first_answer(sg_fr);
|
||||
while (IS_INVALID_LEAF_NODE(current_answer))
|
||||
current_answer = TrNode_child(current_answer);
|
||||
SgFr_first_answer(sg_fr) = current_answer;
|
||||
/* chain next valid answers */
|
||||
next_answer = TrNode_child(current_answer);
|
||||
while (next_answer) {
|
||||
if (! IS_INVALID_LEAF_NODE(next_answer)) {
|
||||
TrNode_child(current_answer) = next_answer;
|
||||
current_answer = next_answer;
|
||||
}
|
||||
next_answer = TrNode_child(next_answer);
|
||||
}
|
||||
SgFr_last_answer(sg_fr) = current_answer;
|
||||
/* free invalid answer nodes */
|
||||
current_answer = SgFr_invalid_chain(sg_fr);
|
||||
SgFr_invalid_chain(sg_fr) = NULL;
|
||||
while (current_answer) {
|
||||
next_answer = TrNode_next(current_answer);
|
||||
FREE_ANSWER_TRIE_NODE(current_answer);
|
||||
current_answer = next_answer;
|
||||
}
|
||||
}
|
||||
#endif /* MODE_DIRECTED_TABLING */
|
||||
SgFr_state(sg_fr) = complete;
|
||||
UNLOCK(SgFr_lock(sg_fr));
|
||||
#ifdef MODE_DIRECTED_TABLING
|
||||
if (SgFr_invalid_chain(sg_fr)) {
|
||||
ans_node_ptr current_node, next_node;
|
||||
/* find first valid answer */
|
||||
current_node = SgFr_first_answer(sg_fr);
|
||||
while (IS_INVALID_LEAF_NODE(current_node))
|
||||
current_node = TrNode_child(current_node);
|
||||
SgFr_first_answer(sg_fr) = current_node;
|
||||
/* chain next valid answers */
|
||||
next_node = TrNode_child(current_node);
|
||||
while (next_node) {
|
||||
if (! IS_INVALID_LEAF_NODE(next_node)) {
|
||||
TrNode_child(current_node) = next_node;
|
||||
current_node = next_node;
|
||||
}
|
||||
next_node = TrNode_child(next_node);
|
||||
}
|
||||
SgFr_last_answer(sg_fr) = current_node;
|
||||
#ifndef YAPOR
|
||||
/* free invalid answer nodes */
|
||||
current_node = SgFr_invalid_chain(sg_fr);
|
||||
SgFr_invalid_chain(sg_fr) = NULL;
|
||||
while (current_node) {
|
||||
next_node = TrNode_next(current_node);
|
||||
FREE_ANSWER_TRIE_NODE(current_node);
|
||||
current_node = next_node;
|
||||
}
|
||||
#endif /* ! YAPOR */
|
||||
}
|
||||
#endif /* MODE_DIRECTED_TABLING */
|
||||
return;
|
||||
}
|
||||
|
||||
@ -753,8 +755,42 @@ static inline void abolish_incomplete_subgoals(choiceptr prune_cp) {
|
||||
#ifdef INCOMPLETE_TABLING
|
||||
SgFr_state(sg_fr) = incomplete;
|
||||
UNLOCK(SgFr_lock(sg_fr));
|
||||
#ifdef MODE_DIRECTED_TABLING
|
||||
if (SgFr_invalid_chain(sg_fr)) {
|
||||
ans_node_ptr current_node, next_node;
|
||||
/* find first valid answer */
|
||||
current_node = SgFr_first_answer(sg_fr);
|
||||
while (IS_INVALID_LEAF_NODE(current_node))
|
||||
current_node = TrNode_child(current_node);
|
||||
SgFr_first_answer(sg_fr) = current_node;
|
||||
/* chain next valid answers */
|
||||
next_node = TrNode_child(current_node);
|
||||
while (next_node) {
|
||||
if (! IS_INVALID_LEAF_NODE(next_node)) {
|
||||
TrNode_child(current_node) = next_node;
|
||||
current_node = next_node;
|
||||
}
|
||||
next_node = TrNode_child(next_node);
|
||||
}
|
||||
SgFr_last_answer(sg_fr) = current_node;
|
||||
#ifndef YAPOR
|
||||
/* free invalid answer nodes */
|
||||
current_node = SgFr_invalid_chain(sg_fr);
|
||||
SgFr_invalid_chain(sg_fr) = NULL;
|
||||
while (current_node) {
|
||||
next_node = TrNode_next(invalid_node);
|
||||
FREE_ANSWER_TRIE_NODE(current_node);
|
||||
current_node = node_node;
|
||||
}
|
||||
#endif /* ! YAPOR */
|
||||
}
|
||||
#endif /* MODE_DIRECTED_TABLING */
|
||||
#else
|
||||
ans_node_ptr node;
|
||||
#ifdef MODE_DIRECTED_TABLING
|
||||
ans_node_ptr invalid_node = SgFr_invalid_chain(sg_fr);
|
||||
SgFr_invalid_chain(sg_fr) = NULL;
|
||||
#endif /* MODE_DIRECTED_TABLING */
|
||||
SgFr_state(sg_fr) = ready;
|
||||
free_answer_hash_chain(SgFr_hash_chain(sg_fr));
|
||||
SgFr_hash_chain(sg_fr) = NULL;
|
||||
@ -764,6 +800,14 @@ static inline void abolish_incomplete_subgoals(choiceptr prune_cp) {
|
||||
TrNode_child(SgFr_answer_trie(sg_fr)) = NULL;
|
||||
UNLOCK(SgFr_lock(sg_fr));
|
||||
free_answer_trie(node, TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST);
|
||||
#if defined(MODE_DIRECTED_TABLING) && ! defined(YAPOR)
|
||||
/* free invalid answer nodes */
|
||||
while (invalid_node) {
|
||||
node = TrNode_next(invalid_node);
|
||||
FREE_ANSWER_TRIE_NODE(invalid_node);
|
||||
invalid_node = node;
|
||||
}
|
||||
#endif /* MODE_DIRECTED_TABLING && ! YAPOR */
|
||||
#endif /* INCOMPLETE_TABLING */
|
||||
}
|
||||
#ifdef LIMIT_TABLING
|
||||
|
@ -1004,8 +1004,10 @@ sg_fr_ptr subgoal_search(yamop *preg, CELL **Yaddr) {
|
||||
current_sg_node = subgoal_search_loop(tab_ent, current_sg_node, Deref(XREGS[j]), &subs_arity, &stack_vars);
|
||||
if (subs_arity != old_subs_arity) {
|
||||
if (subs_pos && MODE_DIRECTED_GET_MODE(aux_mode_directed[subs_pos-1]) == MODE_DIRECTED_GET_MODE(mode_directed[i-1])) {
|
||||
/* same mode as before -> use the current entry in the aux_mode_directed[] array */
|
||||
aux_mode_directed[subs_pos-1] += MODE_DIRECTED_SET(subs_arity - old_subs_arity, 0);
|
||||
} else {
|
||||
/* new mode -> init a new entry in the aux_mode_directed[] array */
|
||||
aux_mode_directed[subs_pos] = MODE_DIRECTED_SET(subs_arity - old_subs_arity, MODE_DIRECTED_GET_MODE(mode_directed[i-1]));
|
||||
subs_pos++;
|
||||
}
|
||||
@ -1081,23 +1083,62 @@ ans_node_ptr answer_search(sg_fr_ptr sg_fr, CELL *subs_ptr) {
|
||||
#ifdef MODE_DIRECTED_TABLING
|
||||
mode_directed = SgFr_mode_directed(sg_fr);
|
||||
if (mode_directed) {
|
||||
ans_node_ptr invalid_ans_node = NULL;
|
||||
int i = subs_arity, j = 0;
|
||||
while (i) {
|
||||
int mode = MODE_DIRECTED_GET_MODE(mode_directed[j]);
|
||||
int n_subs = MODE_DIRECTED_GET_ARG(mode_directed[j]);
|
||||
do {
|
||||
TABLING_ERROR_CHECKING(answer search, IsNonVarTerm(subs_ptr[i]));
|
||||
if (TrNode_child(current_ans_node) == NULL || mode == MODE_DIRECTED_INDEX || mode == MODE_DIRECTED_ALL)
|
||||
TABLING_ERROR_CHECKING(answer_search, IsNonVarTerm(subs_ptr[i]));
|
||||
if (mode == MODE_DIRECTED_INDEX || mode == MODE_DIRECTED_ALL)
|
||||
current_ans_node = answer_search_loop(sg_fr, current_ans_node, Deref(subs_ptr[i]), &vars_arity);
|
||||
else { /* TrNode_child(current_node) != NULL && mode != MODE_DIRECTED_INDEX && mode != MODE_DIRECTED_ALL */
|
||||
if (mode == MODE_DIRECTED_FIRST)
|
||||
else {
|
||||
#if defined(TABLE_LOCK_AT_NODE_LEVEL)
|
||||
LOCK(TrNode_lock(current_ans_node));
|
||||
#elif defined(TABLE_LOCK_AT_WRITE_LEVEL)
|
||||
LOCK_TABLE(current_ans_node);
|
||||
#endif /* TABLE_LOCK_LEVEL */
|
||||
if (TrNode_child(current_ans_node) == NULL) {
|
||||
#ifdef YAPOR
|
||||
struct answer_trie_node virtual_ans_node;
|
||||
ans_node_ptr parent_ans_node = current_ans_node;
|
||||
TrNode_init_lock_field(&virtual_ans_node);
|
||||
TrNode_parent(&virtual_ans_node) = NULL;
|
||||
TrNode_child(&virtual_ans_node) = NULL;
|
||||
current_ans_node = answer_search_loop(sg_fr, &virtual_ans_node, Deref(subs_ptr[i]), &vars_arity);
|
||||
TrNode_child(parent_ans_node) = TrNode_child(&virtual_ans_node);
|
||||
#else
|
||||
current_ans_node = answer_search_loop(sg_fr, current_ans_node, Deref(subs_ptr[i]), &vars_arity);
|
||||
#endif /* YAPOR */
|
||||
} else if (mode == MODE_DIRECTED_MIN || mode == MODE_DIRECTED_MAX) {
|
||||
ans_node_ptr parent_ans_node = current_ans_node;
|
||||
invalid_ans_node = TrNode_child(parent_ans_node); /* by default, assume a better answer */
|
||||
current_ans_node = answer_search_mode_directed_min_max(sg_fr, current_ans_node, Deref(subs_ptr[i]), mode);
|
||||
if (invalid_ans_node == TrNode_child(parent_ans_node)) /* worse or equal answer */
|
||||
invalid_ans_node = NULL;
|
||||
} else if (mode == MODE_DIRECTED_FIRST)
|
||||
current_ans_node = NULL;
|
||||
else if (mode == MODE_DIRECTED_LAST) {
|
||||
invalidate_answer_trie(TrNode_child(current_ans_node), sg_fr, TRAVERSE_POSITION_FIRST);
|
||||
else { /* mode == MODE_DIRECTED_LAST */
|
||||
#ifdef YAPOR
|
||||
struct answer_trie_node virtual_ans_node;
|
||||
ans_node_ptr parent_ans_node = current_ans_node;
|
||||
invalid_ans_node = TrNode_child(parent_ans_node);
|
||||
TrNode_init_lock_field(&virtual_ans_node);
|
||||
TrNode_parent(&virtual_ans_node) = NULL;
|
||||
TrNode_child(&virtual_ans_node) = NULL;
|
||||
current_ans_node = answer_search_loop(sg_fr, &virtual_ans_node, Deref(subs_ptr[i]), &vars_arity);
|
||||
TrNode_child(parent_ans_node) = TrNode_child(&virtual_ans_node);
|
||||
#else
|
||||
invalid_ans_node = TrNode_child(current_ans_node);
|
||||
TrNode_child(current_ans_node) = NULL;
|
||||
current_ans_node = answer_search_loop(sg_fr, current_ans_node, Deref(subs_ptr[i]), &vars_arity);
|
||||
} else /* mode == MODE_DIRECTED_MIN || mode == MODE_DIRECTED_MAX */
|
||||
current_ans_node = answer_search_mode_directed_min_max(sg_fr, current_ans_node, Deref(subs_ptr[i]), mode);
|
||||
#endif /* YAPOR */
|
||||
}
|
||||
#if defined(TABLE_LOCK_AT_NODE_LEVEL)
|
||||
UNLOCK(TrNode_lock(current_ans_node));
|
||||
#elif defined(TABLE_LOCK_AT_WRITE_LEVEL)
|
||||
UNLOCK_TABLE(current_ans_node);
|
||||
#endif /* TABLE_LOCK_LEVEL */
|
||||
}
|
||||
n_subs--;
|
||||
i--;
|
||||
@ -1106,16 +1147,18 @@ ans_node_ptr answer_search(sg_fr_ptr sg_fr, CELL *subs_ptr) {
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
if (invalid_ans_node)
|
||||
invalidate_answer_trie(invalid_ans_node, sg_fr, TRAVERSE_POSITION_FIRST);
|
||||
} else
|
||||
#endif /* MODE_DIRECTED_TABLING */
|
||||
if (IsMode_GlobalTrie(TabEnt_mode(SgFr_tab_ent(sg_fr)))) {
|
||||
for (i = subs_arity; i >= 1; i--) {
|
||||
TABLING_ERROR_CHECKING(answer search, IsNonVarTerm(subs_ptr[i]));
|
||||
TABLING_ERROR_CHECKING(answer_search, IsNonVarTerm(subs_ptr[i]));
|
||||
current_ans_node = answer_search_terms_loop(sg_fr, current_ans_node, Deref(subs_ptr[i]), &vars_arity);
|
||||
}
|
||||
} else {
|
||||
for (i = subs_arity; i >= 1; i--) {
|
||||
TABLING_ERROR_CHECKING(answer search, IsNonVarTerm(subs_ptr[i]));
|
||||
TABLING_ERROR_CHECKING(answer_search, IsNonVarTerm(subs_ptr[i]));
|
||||
current_ans_node = answer_search_loop(sg_fr, current_ans_node, Deref(subs_ptr[i]), &vars_arity);
|
||||
}
|
||||
}
|
||||
@ -1234,6 +1277,18 @@ void free_subgoal_trie(sg_node_ptr current_node, int mode, int position) {
|
||||
if (TrNode_child(ans_node))
|
||||
free_answer_trie(TrNode_child(ans_node), TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST);
|
||||
FREE_ANSWER_TRIE_NODE(ans_node);
|
||||
#if defined(MODE_DIRECTED_TABLING) && defined(YAPOR)
|
||||
if (SgFr_invalid_chain(sg_fr)) {
|
||||
ans_node_ptr next_node, invalid_node = SgFr_invalid_chain(sg_fr);
|
||||
SgFr_invalid_chain(sg_fr) = NULL;
|
||||
/* free invalid answer nodes */
|
||||
while (invalid_node) {
|
||||
next_node = TrNode_next(invalid_node);
|
||||
FREE_ANSWER_TRIE_NODE(invalid_node);
|
||||
invalid_node = next_node;
|
||||
}
|
||||
}
|
||||
#endif /* MODE_DIRECTED_TABLING && YAPOR */
|
||||
#ifdef LIMIT_TABLING
|
||||
remove_from_global_sg_fr_list(sg_fr);
|
||||
#endif /* LIMIT_TABLING */
|
||||
|
@ -1203,8 +1203,14 @@ static inline ans_node_ptr answer_search_loop(sg_fr_ptr sg_fr, ans_node_ptr curr
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(MODE_DIRECTED_TABLING) && ! defined(MODE_TERMS_LOOP) && ! defined(MODE_GLOBAL_TRIE_LOOP)
|
||||
#define ANSWER_SAFE_INSERT_ENTRY(NODE, ENTRY, INSTR) \
|
||||
{ ans_node_ptr new_node; \
|
||||
NEW_ANSWER_TRIE_NODE(new_node, INSTR, ENTRY, NULL, NODE, NULL); \
|
||||
TrNode_child(NODE) = new_node; \
|
||||
NODE = new_node; \
|
||||
}
|
||||
|
||||
static inline ans_node_ptr answer_search_mode_directed_min_max(sg_fr_ptr sg_fr, ans_node_ptr current_node, Term t, int mode) {
|
||||
#define in_pair 0
|
||||
ans_node_ptr child_node;
|
||||
Term child_term;
|
||||
Float trie_value, term_value;
|
||||
@ -1255,10 +1261,8 @@ static inline ans_node_ptr answer_search_mode_directed_min_max(sg_fr_ptr sg_fr,
|
||||
if (term_value == trie_value)
|
||||
return child_node;
|
||||
/* better answer */
|
||||
invalidate_answer_trie(TrNode_child(current_node), sg_fr, TRAVERSE_POSITION_FIRST);
|
||||
TrNode_child(current_node) = NULL;
|
||||
if (IsAtomOrIntTerm(t)) {
|
||||
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, t, _trie_retry_atom + in_pair);
|
||||
ANSWER_SAFE_INSERT_ENTRY(current_node, t, _trie_retry_atom);
|
||||
} else if (IsApplTerm(t)) {
|
||||
Functor f = FunctorOfTerm(t);
|
||||
if (f == FunctorDouble) {
|
||||
@ -1267,21 +1271,20 @@ static inline ans_node_ptr answer_search_mode_directed_min_max(sg_fr_ptr sg_fr,
|
||||
Float dbl;
|
||||
} u;
|
||||
u.dbl = FloatOfTerm(t);
|
||||
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, AbsAppl((Term *)f), _trie_retry_null + in_pair);
|
||||
ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_null);
|
||||
#if SIZEOF_DOUBLE == 2 * SIZEOF_INT_P
|
||||
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, u.t_dbl[1], _trie_retry_extension);
|
||||
ANSWER_SAFE_INSERT_ENTRY(current_node, u.t_dbl[1], _trie_retry_extension);
|
||||
#endif /* SIZEOF_DOUBLE x SIZEOF_INT_P */
|
||||
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, u.t_dbl[0], _trie_retry_extension);
|
||||
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, AbsAppl((Term *)f), _trie_retry_double);
|
||||
ANSWER_SAFE_INSERT_ENTRY(current_node, u.t_dbl[0], _trie_retry_extension);
|
||||
ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_double);
|
||||
} else if (f == FunctorLongInt) {
|
||||
Int li = LongIntOfTerm(t);
|
||||
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, AbsAppl((Term *)f), _trie_retry_null + in_pair);
|
||||
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, li, _trie_retry_extension);
|
||||
ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, AbsAppl((Term *)f), _trie_retry_longint);
|
||||
ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_null);
|
||||
ANSWER_SAFE_INSERT_ENTRY(current_node, li, _trie_retry_extension);
|
||||
ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_longint);
|
||||
}
|
||||
}
|
||||
return current_node;
|
||||
#undef in_pair
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user