next up previous contents index
Next: Debugging Up: Standard Predicates Previous: Execution State   Contents   Index


Tabling

In XSB, tables are designed so that they can be used transparently by computations. However, it is often useful to be able to explicitly inspect a table, or to alter its state. In the following predicates, which are provided for this purpose, Skeleton refers to information about the function and arity of a predicate. If p/2 is a predicate, its skeleton can be represented as $p(\langle arg1
\rangle,\langle arg2 \rangle)$ where arg1 and arg2 can be any instantiation pattern. Thus the information derived from the skeletons p(1,2) and p(A,B) would be the same.

The user should be aware that skeletons which are dynamically created (e.g. by functor/3) are located in usermod (cf. Section 3.3). In such a case, the tabling predicates below may not behave in the desired manner if the tabled predicates themselves have not been imported into usermod.

get_calls(+Skeleton,-Subgoal_Structure_Pointer,-Return_Skeleton)
Tabling
Backtracks through the subgoal trie, unifying Skeleton with entries in the call trie. As it does so, get_calls/3 binds Subgoal_Structure_Pointer with the pointer to the subgoal structure and binds Return_Skeleton to a term of the form ret/n where each of its arguments corresponds to a free variable in the call. Example:

For the following program and table

:- table p/2.
p(1,2).
p(1,3).
p(1,X).
p(2,3).
Call Returns
p(1,X) p(1,2)
  p(1,3)
  p(1,X)
p(X,3) p(1,3)
  p(2,3)
calls to get_calls/3 will act as follows

                   | ?- get_calls(p(X,Y),Cs,Ret).

                   X = _864816
                   Y = 3
                   Cs = 2927152
                   Ret = ret(_864816);

                   X = 1
                   Y = _864644
                   Cs = 2927104
                   Ret = ret(_864644);

                   no
                   | ?- get_calls(p(1,Y),Cs,Ret).

                   Y = 3
                   Cs = 2927152
                   Ret = ret(1);

                   Y = _864620
                   Cs = 2927104
                   Ret = ret(_864620);

                   no
                   | ?- get_calls(p(Y,3),Cs,Ret).

                   Y = _864792
                   Cs = 2927152
                   Ret = ret(_864792);

                   Y = 1
                   Cs = 2927104
                   Ret = ret(3);

                   no
                   | ?- get_calls(p(1,3),Cs,Ret).

                   Cs = 2927152
                   Ret = ret(1);

                   Cs = 2927104
                   Ret = ret(3);

                   no

get_call(+Skeleton,-Subgoal_Structure_Pointer,-Return_Skeleton)
Tabling
This predicate binds Subgoal_Structure_Pointer and Return_Skeleton only if Skeleton is a variant (i.e., identical up to variable renaming) of some entry in the subgoal table. It may be compared to the previous predicate get_call/3 which unifies Skeleton with entries in the subgoal trie. Repeating the example from get_calls/3, calls to get_call/3 will act as follows


                   | ?- get_call(p(X,Y),Cs,Ret).

                   no
                   | ?- get_call(p(1,Y),Cs,Ret).

                   Y = _864620
                   Cs = 2927104
                   Ret = ret(_864620);

                   no
                   | ?- get_call(p(Y,3),Cs,Ret).

                   Y = _864792
                   Cs = 2927152
                   Ret = ret(_864792);

                   no
                   | ?- get_call(p(1,3),Cs,Ret).

                   no

get_calls_for_table(+Skeleton,-Call)
Tabling
Succeeds whenever Skeleton unfies with an entry in the subgoal table. When this predicate suceeds, it returns a variant of the call entry with which Skeleton unifies.

This predicate does not provide any information about whether a table is complete. Use table_state to inquire about a table's state.

Calls to get_calls_for_table/2 for the example in get_calls/3 would act as follows

 

                   |?- get_calls_for_table(p(X,Y), Call).  
                   X = _646608 
                   Y = _646436
                   Call = p(1,_646724) ;

                   X = _646608
                   Y = _646436
                   Call = p(_646720,3) ;

                   no
                   | ?- get_calls_for_table(p(1,2), Call).
                   Call = p(1,_646676)

                   Call = p(_646672,3) ;

                   no
The second example backtracks through all entries in the table, since only skeletal information is used from the first argument.

Exception:

instantiation_error
First argument is not instantiated.
table_error
First argument is not a tabled predicate.

get_returns(+Subgoal_Structure_Pointer,-Return_Skeleton)
Tabling
Backtracks through the answer trie for the subgoal whose subgoal structure is pointed to by Subgoal_Structure_Pointer, and instantiates the Return_Skeleton with the bindings corresponding to the return.

One way of accessing subgoals and answers of the example in in get_calls/3 is as follows

 
                   | ?- get_calls(p(Y,3),Cs,Ret), get_returns(Cs,Ret).

                   Y = 2
                   Cs = 2561656
                   Ret = ret(2);

                   Y = 1
                   Cs = 2561656
                   Ret = ret(1);

                   Y = 1
                   Cs = 2559032
                   Ret = ret(3);

                   Y = 1
                   Cs = 2559032
                   Ret = ret(3);

                   no

get_returns(+Subgoal_Structure_Pointer,-Return_Skeleton,-LeafNode)
Tabling
Same as above, except for the fact that the third argument is bound to the leaf node corresponding to the return in the return trie.

get_returns_for_call(+Call,-Return)
Tabling
Succeeds whenever there is a table entry for a variant of Call. If this is the case, Return is instantiated with an entry for the table corresponding to call, and successive entries are returned by backtracking. If there are no answers in the table, or no table entry for Call, the goal fails.

This predicate creates fresh variables for the return, rather than unifying them with variables in the first argument. An explicit unification of a call with its return can be done if so desired.

Example: Let us continue from the example in get_calls_for_table/3.


                   | ?- get_returns_for_call(p(1,X), Return).

                   X = _646412
                   Return = p(1,_646628);

                   X = _646412
                   Return = p(1,2);

                   X = _646412
                   Return = p(1,3);

                   no
                   | ?- get_returns_for_call(p(X,Y), Return).
                   no

                   | ?- get_returns_for_call(p(1,2), Return).
                   no

Exception:

instantiation_error
First argument is not instantiated.
table_error
First argument is not a tabled predicate.

get_residual(?Skeleton,?Delay_list)
Tabling
get_residual/2 is used to backtrack through answers that unify with a skeleton. These answers may in fact come from any call that unifies with Skeleton. Since the Delay_list of an answer consists of those literals whose truth value is unknown in the well-founded model of the program (see Section 5) get_residual/2 can be useful when extensions of the well-founded model are desired. Consider the program

For the following program and table

:- table p/2.
p(1,2).
p(1,3):- tnot(p(2,3)).
p(2,3):- tnot(p(1,3)).
Call Returns
p(1,X) p(1,2)
  p(1,3):- tnot(p(2,3))
  p(2,3):- tnot(p(1,3))
p(1,3) p(1,3):- tnot(p(2,3))
p(2,3) p(2,3):- tnot(p(1,3))
calls to get_residual/3 will act as follows
 
                   | ?- get_residual(p(X,Y),List).

                   X = 1
                   Y = 2;
                   Z = [];

                   X = 1
                   Y = 3;
                   Z = [tnot(p(2,3))];

                   X = 2
                   Y = 3;
                   Z = [tnot(p(1,3))];

                   X = 1
                   Y = 3;
                   Z = [tnot(p(2,3))];

                   X = 2
                   Y = 3;
                   Z = [tnot(p(1,3))];

                   no

delete_return(+Subgoal_Structure_Pointer,+LeafNode)
Tabling
Deletes a return from the return trie. The LeafNode parameter should be obtained from a call to get_returns/3.

abolish_all_tables
Tabling
abolish_all_tables/0 abolishes all tables presently in the system. Predicates which have been declared tabled remain tabled, but information about calls and returns is deleted. In Version 2.2, abolish_all_tablesl/0 reclaims used space. The predicate always succeeds.

Note that incomplete tables are abolished automatically by the system on exceptions and when the interpreter level is resumed. In these cases, the user does not need to abolish tables to maintain correctness.

abolish_table_pred(+PredSpecification or +Skeleton)
Tabling
Predicate abolish_table_pred/1 abolishes tables for all calls to the predicate denoted by PredSpecification (as in path/2) or by Skeleton (as in path(X,Y)). The predicate remains tabled, but information about its calls and their returns is removed from the system. In Version 2.2, abolish_table_pred/1 reclaims the space used by the calls to this predicate (and their answers). Note that incomplete tables are abolished automatically by the system on exceptions and when the interpreter level is resumed. In these cases, the user does not need to abolish tables to maintain correctness.

Exception:

instantiation_error
Argument is a variable.
type_error
Argument is not a predicate specification of a callable term.
table_error
Argument is not a (specification of a) tabled predicate.

abolish_table_call(?Call)
Tabling
Predicate abolish_table_call/1 abolishes tables for a particular call to a predicate denoted by Call. The predicate remains tabled, and information about all other tables remains intact. In Version 2.2, abolish_table_call/1 does not reclaim used space. Note that incomplete tables are abolished automatically by the system on exceptions and when the interpreter level is resumed. In these cases, the user does not need to abolish tables to maintain correctness.

Example:

Continuing the example started in the description of predicate get_calls_for_table/3 the call abolish_table_call(p(1,X)) would produce the table

Call Returns
p(X,3) p(1,3)
  p(2,3)

Exception:

table_error
Argument 1 is not a callable predicate.

table_state(?Call,-State)
Tabling
If the first argument is a valid Term indicator, table_state/1 unifies state with one of the set { not_yet_called, complete, incomplete, undef}. The meaning of these atoms is defined as:
not_yet_called
iff the predicate corresponding to Call has been declared tabled, but there is no table entry for call.
complete
iff the table entry for Call contains all solutions.
incomplete
iff the table entry for Call may not contain all solutions.
undef
iff the predicate corresponding to Call has not been declared tabled.

Exceptions:

type_error
Argument 1 is not a callable predicate.


next up previous contents index
Next: Debugging Up: Standard Predicates Previous: Execution State   Contents   Index
Baoqiu Cui
2000-04-23