Logic programming beyond Prolog

Logic programming beyond Prolog
Notice: This research summary and analysis were automatically generated using AI technology. For absolute accuracy, please refer to the [Original Paper Viewer] below or the Original ArXiv Source.

A logic program is an executable specification. For example, merge sort in pure Prolog is a logical formula, yet shows creditable performance on long linked lists. But such executable specifications are a compromise: the logic is distorted by algorithmic considerations, yet only indirectly executable via an abstract machine. This paper introduces relational programming, a method that solves the difficulty with logic programming by a separation of concerns. It requires three texts: (1) the axioms, a logical formula that specifies the problem and is not compromised by algorithmic considerations, (2) the theorem, a logical formula that expresses the idea of the algorithm and follows from the axioms, and (3) the code, a transcription of the theorem to a procedural language. Correctness of the code relies on the logical relationship of the theorem with the axioms and relies on an accurate transcription of the theorem to the procedural language. Sorting is an example where relational programming has the advantage of a higher degree of abstractness: the data to be sorted can be any data type in C++ (the procedural language we use in our examples) that satisfies the axioms of linear order, while the pure-Prolog version is limited to data structures in the form of linked cells. We show another advantage of relational programs: they have a model-theoretic and fixpoint semantics equivalent to each other and analogous to those of pure Prolog programs.


💡 Research Summary

The paper “Logic programming beyond Prolog” addresses a fundamental tension in traditional logic programming: while languages like Prolog allow programs to be written as logical formulas that can be executed directly, the need for efficient algorithms inevitably distorts the pure logical specification. The authors illustrate this problem with the classic example of merge‑sort. In pure Prolog, the only sortable structure is a list of linked cells, and the most natural Prolog definition of sorting (a recursive split‑sort‑merge pattern) is efficient but does not correspond to the clean specification “output is a permutation of the input that is ordered”. Conversely, a specification that directly states “sorted = ordered permutation of input” is logically pure but computationally infeasible when executed as a Prolog program.

To resolve this mismatch, the authors introduce relational programming, a methodology that separates concerns into three distinct texts:

  1. Axioms – a set of logical formulas that define the problem domain (e.g., the axioms of a linear order, the definition of permutation) without any algorithmic bias.
  2. Theorem – a logical formula that captures the algorithmic idea and is provably derivable from the axioms.
  3. Code – a transcription of the theorem into a conventional procedural language (the authors use C++).

Correctness of the code follows from two facts: (a) the theorem is a logical consequence of the axioms, and (b) the transcription faithfully implements the theorem’s structure. Because the axioms describe only the abstract properties of the data, any C++ class or template that satisfies those axioms (for example, arrays, vectors, custom iterators) can be used with the same code, giving the approach a level of abstraction far beyond what pure Prolog can provide.

The paper builds on the earlier “Elements of Programming” (EOP) framework, which also separates axioms from the algorithmic theorem but still relies on Prolog as the theorem language. Relational programming generalizes this by allowing the theorem to be expressed in a broader class of logical formulas (essentially “if‑half” clauses reminiscent of Clark completion) that can be directly mapped to procedural constructs such as function headers, disjunctive bodies, and conjunctive sub‑goals. The authors formalize relational programs as sentences of the form ∀ A ← B, where A is an atomic head and B is a disjunction of conjunctions possibly containing existential quantifiers. This syntax mirrors the structure of typical procedural code and simplifies transcription.

From a semantic standpoint, the authors provide both a model‑theoretic and a fixpoint semantics for relational programs. They replace the traditional Herbrand universe with (F,=)-interpretations, where F is the set of function symbols and = is equality, allowing interpretations over arbitrary domains. The fixpoint operator maps sets of such interpretations to themselves, and the least fixpoint coincides with the minimal model, just as in classical logic programming. Consequently, relational programs retain the well‑studied formal properties of Prolog while being language‑agnostic.

The paper presents several concrete examples. The merge‑sort algorithm is rewritten as a relational program: the head sort(v,w) is defined by a disjunction of the base case (empty list) and the recursive case involving split, two recursive sort calls, and merge. This relational specification is then transcribed into C++ using a template Seg class that abstracts any contiguous sequence. The resulting C++ code can sort arrays, vectors, or any user‑defined container that satisfies the linear‑order axioms, demonstrating the claimed portability.

Another example is De Bruijn’s fast multiplication algorithm, which the authors adapt from the EOP literature. By expressing the algorithm as a theorem over the axioms of an Archimedean monoid, they obtain a C++ implementation that works not only for integers but also for rationals, binary fractions, or any structure that fulfills the monoid axioms.

The authors acknowledge limitations. Relational programs lose some of Prolog’s inherent nondeterminism and reversibility because procedural languages typically have fixed input‑output modes. The transcription step introduces a potential source of error; while the logical relationship guarantees correctness in principle, human mistakes in mapping existential quantifiers or disjunctions to code can break the guarantee. Moreover, the current work focuses on C++; extending the approach to other paradigms (functional, parallel, or distributed languages) remains future work.

In conclusion, the paper proposes a robust framework that combines the declarative clarity of logic programming with the practical flexibility of conventional languages. By isolating pure logical specifications (axioms) from algorithmic ideas (theorem) and providing a systematic way to translate the latter into efficient code, relational programming offers a path to reusable, formally verified algorithms that are applicable across diverse data structures. The dual semantics ensure that the approach inherits the solid theoretical foundation of traditional logic programming while overcoming its practical constraints. Future research directions include automated theorem‑to‑code translators, richer support for nondeterministic constructs, and broader language integration.


Comments & Academic Discussion

Loading comments...

Leave a Comment