Logic Programming Systems
The XSB Logic Programming System

      The XSB Research Group
SUNY Stony Brook
USA

Editor: Enrico Pontelli



PDF Version available HERE.

System Web Page: http://xsb.sourceforge.net

The goal of the XSB project, which continues under active development at SUNY Stony Brook and Universidade Nova de Lisboa, is to extend Prolog with features for deductive databases and non-monotonic reasoning.  The resulting system has proven useful in a wide variety of research areas, and has been heavily used by a number of commercial companies.

At the core of XSB is an industrial-strength, multi-threaded Prolog system that is largely ISO-compliant, executes in both 32-bit and 64-bit modes, and has full support for various forms of tabling and constraint-handling rules at the engine level.  Numerous libraries and packages have been written for XSB that allow sophisticated interfaces to Java, C, and to various database systems.  Other packages allow GUI
development from within XSB, provide for ontology management, and support other functionality.  We discuss some of the more significant features in the following.

  • Tabling. The most distinctive aspect of XSB is its implementation of tabled evaluation.  Tabling is a simple idea with far-reaching  implications. At a conceptual level, during computation of a goal to a logic program, each subgoal S is registered in a table the first time it is called, and unique answers to S are added to the table as they are derived. When subsequent calls are made to S, the evaluation ensures that answers to S re-derived using program clauses. Even from this simple description, an advantage of tabling can be seen -  it ensures termination for various classes of programs. Consider the case of positive datalog programs, i.e. Horn Clause programs with terms consisting of only variables and constants from a finite alphabet. Such a program contains only finitely many atomic formulas. Each of these atoms can be added at most once to the table as a subgoal, and each such subgoal can have at most finitely many answers, leading to a finite computation.
However, tabling can be used to far greater effect than simply ensuring termination for some Horn clause programs.  One powerful feature of tabling is its ability to maintain other global elements of a computation in the "table," such as information about whether one subgoal depends on another, and whether the dependency is through negation. By maintaining this global information, tabling can be used to evaluate normal logic programs under the Well-Founded Semantics (WFS).  The essential idea is that global information about dependencies is used to determine the truth value of literals that do not have a derivation. If such literals are involved in a cyclic dependency through negation, they are undefined under WFS; if not, the literals belong to an unfounded set and are false in WFS. In fact, it can be shown that tabling allows non-floundering datalog programs with negation to terminate with quadratic data complexity under WFS.  Of course not every goal in an evaluation must be tabled: users can choose whether individual predicates use tabled evaluation, or can allow the system to decide which predicates in a given module should be tabled.
    • Call-Variance and Call-Subsumption. By default, a  call-variant evaluation is performed - in other words, a goal G uses a table if the table contains a goal G' that is a  variant of G.  Call-variance is a useful form of tabling when it is desirable to preserve certain meta-logical properties of an evaluation.  As one example, when a meta-interpreter is tabled using call-variance, it still functions as a meta-interpreter, but will have the semantic, termination, and complexity properties of the  tabled program.  Call-variant tabling has proven useful in applications including program analysis, ontology management, diagnosis, model checking, machine learning, and natural language analysis.  Applications in many of these areas make heavy use of well-founded tabled negation in addition to tabling Horn clauses.
Alternatively, a predicate can be declared to use call-subsumption where a goal G uses a table if the table contains a goal G' that subsumes G.  This seemingly minor change gives rise to very different evaluation properties.  If a goal is called with an uninstantiated goal Guninst, whenever a subgoal is encountered with the same predicate symbol as Guninst the table for Guninst will be used, and so the evaluation can be made to behave as a bottom-up computation of a least fixed  point.  Call subsumption is most useful for semantics that are modeled as simple fixed points, such as inferencers for RDF and other semantic web tools.
    • Tabled Aggregation. Tabled aggregation does not preserve all answers for a goal, but only those that are deemed ``best''  according to a given measure.  If this measure is a lattice, the  table may maintain only the join of all answers to a goal; if the measure is a simple partial order, the table may maintain only the maximal answers to a goal.  The ability to maintain the join of answers in a lattice has proven useful for reactive agents and semantic classifiers through implementations of para-consistent, fuzzy and possibilistic logics.
    • Incremental Table Maintenance. XSB has recently been extended with a capability for incremental table maintenance (aka view maintenance or truth maintenance.)  When a user declares a  table to be incrementally maintained, the table will be kept up-to-date when changes are made to dynamic predicates on which the table depends.  This facility allows XSB to easily support the ``model-view-controller'' architecture of interactive systems: dynamic predicates store facts constituting the model; tables maintain the views defined in terms of these facts that are presented to the user; and the controller takes user input, modifies the dynamic predicates appropriately, and efficiently updates the tabled views through incremental table maintenance.
  • Support for Constraints. Like many other Prologs, XSB offers support for Constraint Logic Programming, doing so through an implementation of Constraint Handling Rules (CHR).  However XSB also provides the ability to combine tabling and constraints in the same evaluation.  When a tabled goal G is encountered with a set of constraints C on its variables, a check is made to determine whether the table contains a variant goal with the same constraints: if so, the table is used.  When an answer is resolved against a goal, unifications in its resolution may spark constraint evaluation just as in traditional CLP evaluations.  The combination of tabling and constraints has proven useful for applications such as verification of security protocols and of real-time systems.
  • Multi-threading. XSB supports a draft ISO-standard for  multi-threaded Prologs  based on the semantics of Unix Pthreads and Windows threads.  XSB's multi-threaded  implementation allows numerous threads to be created quickly and to execute with high concurrency.  Threads can be created using a command such as
  ?- thread_create(Goal,Child_id).

which creates a thread with id Child_id to execute Goal.  Within the calling thread, thread_create/2 returns immediately, and Child_id} executes Goal asynchronously,  without directly sharing bindings with the calling thread.  Each thread has all the functionality of a sequential engine.  By default, tables and dynamic code are thread-private, so each thread can concurrently execute tabling under WFS (perhaps with tabled constraints), can assert and retract code to a private store (including asserting tabled code), and so on.  This design, which requires minimal synchronization, supports scalability of evaluations when dozens or more threads are used, and these evaluations can exploit the newer multi-core, 64-bit architectures.
Threads can communicate through message queues, through shared dynamic predicates, or through shared tables.  Message queues are either private to a thread (so that the queue can be read only by that thread) or public.  A thread accessing a message queue will, if no message is found, suspend until a message is added.  Information in thread-shared dynamic code or in a thread-shared table that is completed (i.e. one for which all available answers have been derived) can be read by any thread.  Shared tables computed by different threads can depend on one another; by default  thread-shared tables in XSB use an optimistic concurrency control mechanism that prevents two threads from creating the same table at  the same time.

  • Dynamic Code. One goal of the XSB system is to support deductive database applications, which critically depend on database update, so much work has gone into XSB's implementation  of dynamic code and facts.  The first type of dynamic code is  standard in Prolog: clauses may be added by assert/1 and related predicates, and removed by retract/1 and related predicates.  XSB differs from other Prologs, however, in the varieties of indexing it supports.  The indexing of a dynamic predicate  p/n is specified by a declaration index/2. Clauses may be indexed on any argument or on alternate arguments. E.g., :- index(p/6,[3,2]) on the outer functor symbol of argument 3 when a call to p/6 has its third argment bound, and use an index on argument 2 when argument 3 is a variable, but argument 2 is bound.  Dynamic clauses may also be indexed on combinations of arguments if a single argument does not provide enough discrimination for good indexing - thus :- index(p/6,[3+2]) forms an index from the outer functor symbol of argument 3 together with the outer functor symbol of argument 2.  Finally star-indexing allows discrimination on information that may be in the first 5 symbols of a term, so that dynamic code containing lists or other complex structures may be effectively indexed.  Standard dynamic code is thread-private by default, but can be declared thread-shared at the predicate level.  Asserting and retracting clauses in XSB is fast: millions of clauses can be read and asserted in a few seconds.
Trie-indexed dynamic code offers an alternate mechanism for storing and maintaining large numbers of facts.  Trie-indexed code compiles facts into trie-instructions similar to those used for XSB's tables.
For instance set of facts { rt(a,f(a,b),a), rt(a,f(a,X),Y), rt(b,V,d)} } would be stored in a trie as shown in
Figure 1, where each node corresponds to an instruction in XSB's virtual machine.


Figure 1:Terms Stored as a Trie

Using a trie for indexing has the advantage that discrimination can be made on a position anywhere in a fact, and asserts and retracts are 2-3x faster than with standard dynamic code.  In addition, in trie-dynamic code, there is no distinction between the index and the code itself, so for many sets of facts trie indexing can use much less space than standard dynamic code.  However, trie indexing comes with tradeoffs: only facts can be made trie-dynamic, and unlike standard dynamic code, no ordering is preserved among the facts and duplicate facts are not supported.

Based on the engine described above, a number of packages and libraries have been written for XSB (some by groups independent of the XSB Group).
  • InterProlog and XJ. InterProlog (http://www.declarativa.com/interprolog) is a library that allows Java programs to communicate with XSB, supporting the interconversion of objects between Java and Prolog datatypes. InterProlog supports either socket or JNI communication between Java and XSB.  InterProlog has been used to implement XJ (http://www.xsb.com/xj.aspx), a subsystem that allows XSB programmers to create GUIs using the Java Swing Library.  The XSB programmer sends Prolog terms that represent GUI objects to XJ, which creates the desired Swing object and manages callbacks to XSB to handle user interactions.  Complex and sophisticated interfaces can be created from XSB without any Java programming.
  • XASP. allows users to integrate Prolog and answer set programming (ASP).  An answer set program can be passed to Smodels (http://www.tcs.hut.fi/Software/smodels) directly from a  residual program, consisting of atoms whose truth could not be determined during a well-founded evaluation and their inter-dependencies.  Alternately, an ASP program can be explicitly constructed and sent to Smodels.  Furthermore, each XSB thread has the ability to invoke its own private copy of Smodels within the XSB process, leading to the ability to efficiently compute disjunctive programs, preferred stable models and other extensions of stable model computation.  The XASP package has proven useful for implementations of collaborative agents and logics of change.
  • The Coherent Description Framework (CDF) is a library for maintaining ontology-style information in XSB.  Users can define an  inheritance hierarchy containing classes, along with objects that are members of those classes.  Objects in each class may have mandatory or optional relationships to objects in other classes: these relationships may be defined at the level of the objects themselves or of the classes that contain them.  Definitions of classes, objects, and their relationships may be either extensional (consisting of dynamic facts) or intensional (consisting of dynamic rules).  A variety of routines are provided for quickly loading and updating ontologies with millions of elements: alternatively the ontology may be stored in a database and lazily accessed.  When queries are made to a CDF ontology, answers are correct both according to WFS and to a description logic-like semantics.  CDF has been used extensively at XSB, Inc. (http://www.xsb.com) for semantic-web applications  involving knowledge extraction and classification.
  • For those who want a programming environment that combines logic and objects more thoroughly than CDF, Flora (http://flora.sourceforge.net) amalgamates F-logic, Transaction Logic, and HiLog.  Flora's syntax differs from Prolog's. The term:
john[spouse->mary, child->>bob,bill]
indicates that the object  john has a unique spouse-attribute of mary and child-attributes bob and bill. Such an F-logic term is analogous to a Prolog term - it may appear as a fact, as the head of a rule, or in a literal in the body of a rule.  Flora is implemented by an optimizing compiler whose target code is a normal program executable by XSB.  This compiler makes heavy use of XSB's indexing mechanisms and negation.  However, Flora also has its own sophisticated user environment with a debugger and module system, as well as support for meta-programming of HiLog programs.  Flora has been used for numerous research and commercial projects involving the semantic web, network diagnosis and other application areas.
  • Other Libraries and Packages. XSB has a set of well-developed C interfaces that allow XSB and C to recursively call each other.  Using these interfaces XSB has been embedded in other languages, such as Ruby, Delphi, and Visual Basic.  XSB also has efficient interfaces to a variety of database drivers, and I/O routines for XML and SGML.  Finally, using the xsbdoc packages, adapted from Ciao Prolog's lpdoc generate manuals from declarations made at the module, predicate, and other levels.
XSB is available from {\tt http://xsb.sourceforge.net} under the GNU Library General Public License, so that it can be freely used for research and commercial applications.  Papers about XSB, its implementation and applications can be found on the home pages of its contributing members.








Last updated: 12/25/07.