%{ The operational semantics of Twelf are similar to those of Prolog, a style known as ''backward chaining'' or ''goal-directed'' proof search. '''Tabled logic programming''', which uses Twelf's [[%tabled]] and [[%querytabled]] directives to allow Twelf to prove theorems that might be time-consuming or impossible to prove otherwise. The tabled logic programming capabilities are a part of Twelf's capabilities as a logical framework, but not as a metalogical framework; in other worlds, tabled logic programming cannot be used to prove [[metatheorems]]. [[Image:Searchgraph-found.svg|thumb|right|325px|The graph used in this example, and the path that the tabled logic query finds to get from node a to node g.]] The simplest examples of the power of tabled logic programming in practice involve judgments that involve transitive and/or symmetric closures, such as searching for a path in a graph or formalizing a language with subtyping. Using standard backward-chaining proof search, it is almost impossible to write terminating programs that search for paths, and using backward-chaining search for subtyping typically requires a separate definition of "algorithmic subtyping" that must be shown to be sound and complete with respect to the clearer, simpler definition of subtyping that uses transitivity. This article will use as its example a path-finding algorithm on an undirected graphs. }% %{ == Defining the graph == }% %{ === Nodes === }% node : type. a : node. b : node. c : node. d : node. e : node. f : node. g : node. h : node. %{ === Edges === }% %{ While we will consider edges in our graph to be undirected, we will only define the edge in one, arbitrary, direction. }% edge : node -> node -> type. ab : edge a b. ac : edge a c. bc : edge b c. bd : edge b d. cd : edge c d. ce : edge c e. de : edge d e. df : edge d f. fg : edge f g. %{ === Paths in the graph === }% %{ This is normally where we would get into trouble; in standard logic programming, it is difficult if not impossible to avoid non-terminating behavior when writing a judgment defining a transitive-symmetric closure like path. However, by adding the directive [[%tabled]] path, we will be able to use [[%querytabled]] directives to cause each instance of path A B to be derived at most once during the course of a search: the result is a query that terminates rapidly, instead of not at all. }% path : node -> node -> type. %tabled path. path/link : edge A B -> path A B. path/refl : path A B -> path B A. path/trans : path A B -> path B C -> path A C. %{ == Searching the graph == }% %{ It is crucial that we use [[%querytabled]] rather than [[%query]] in our queries if we wish for them to terminate. Even though we ask Twelf for as many solutions as it can find, the tabled proof search ensures that we can only find one proof of any given path, and the path that is found is by not necessarily the shortest. While the path that is found is shown on the graph above, the edge ab actually appears three times here - if we use parenthesis to show the order in which tabled search connected paths, the path that is found is a - ((b - ((a - b - d) - f)) - g). |check=decl noinclude=true}% %querytabled * * D : path a g. %{ We can also run a terminating search for a path that does not exist, such as one from a to h. |check=decl noinclude=true}% %querytabled * * D : path a h. %. == See also == * [[%tabled]] * [[%querytabled]] * {{guide|chapter=5|section=31|title=Tabled Logic Programming}}