Logic Programming,
Volume 5
DOV M. GABBAY
C. J. HOGGER
J. A. ROBINSON,
Editors
CLARENDON PRESS
HANDBOOK OF LOGIC
IN A R T I F I C I A L I N T E L L I G E N C E
AND LOGIC P R O G R A M M I N G
Editors
Dov M. Gabbay, C. J. Hogger, and J. A. Robinson
HANDBOOKS OF LOGIC IN COMPUTER SCIENCE
and
A R T I F I C I A L I N T E L L I G E N C E AND LOGIC
PROGRAMMING
Executive Editor
Dov M. Gabbay
Administrator
Jane Spurr
Handbook of Logic in Computer Science
Volume 1 Background: Mathematical structures
Volume 2 Background: Computational structures
Volume 3 Semantic structures
Volume 4 Semantic modelling
Volume 5 Theoretical methods in specification and verification
Handbook of Logic in Artificial Intelligence and
Logic Programming
Volume 1 Logical foundations
Volume 2 Deduction methodologies
Volume 3 Nonmonotonic reasoning and uncertain reasoning
Volume 4 Epistemic and temporal reasoning
Volume 5 Logic programming
HANDBOOK OF LOGIC IN
ARTIFICIAL INTELLIGENCE
AND LOGIC PROGRAMMING
Volume 5
Logic Programming
Edited by
DOV M. GABBAY
and
C. J. HOGGER
Imperial College of Science, Technology and Medicine
London
and
J. A. ROBINSON
Syracuse University, New York
C L A R E N D O N PRESS • O X F O R D
1998
Oxford University Press, Great Clarendon Street. Oxford OX2 6DP
Oxford New York
Athens Auckland Bangkok Bogota Bombay
Buenos Aires Calcutta Cape Town Dares Salaam
Delhi Florence Hong Kong Istanbul Karachi
Kuala Lumpur Madras Madrid Melbourne
Mexico City Nairobi Paris Singapore
Taipei Tokyo Toronto Warsaw
and associated companies in
Berlin Ibadan
Oxford is a trade mark of Oxford University Press
Published in the United States by
Oxford University Press Inc., New York
(C) The contributors listed on pp. xiv-xv, 1998
'Constraint logic programming: a survey' by J. Jaffar and M. J. Maher was
previously published in the Journal of Logic
Programming 19/20, 503-82. It is reproduced with
permission from Elsevier
AH rights reserved. No part of this publication may be
reproduced, stored in a retrieval system, or transmitted, in any
form or by any means, without the prior permission in writing of Oxford
University Press. Within the UK, exceptions are allowed in respect of any
fair dealing for the purpose of research or private study, or criticism or
review, as permitted under the Copyright, Designs and Patents Act, 1988, or
in the case of reprographic reproduction in accordance with the terms of
licences issued by the Copyright Licensing Agency. Enquiries concerning
reproduction outside those terms and in other countries should be sent to
the Rights Department, Oxford University Press, at the address above.
This book is sold subject to the condition that it shall not,
by way of trade or otherwise, be lent, re-sold, hired out. or otherwise
circulated without the publisher's prior consent in any form of binding
or cover other than that in which it is published and without a similar
condition including this condition being imposed
on the subsequent purchaser.
A catalogue record for this book is available from the British Library
Library of Congress Cataloging in Publication Data
(Data available)
ISBN 0 19 853792 I
Typeset by the authors using LATEX
Printed in Great Britain by
Bookcraft (Bath) Ltd
Midsomer Norton, A von
Preface
I am very happy to present to the community the fifth and last volume of
our Handbook series, covering the area of Logic and Logic Programming.
The ideas and methods of logic programming gave a substantial push to
the development of logic itself. Ideas like negation as failure, goal directed
presentation of a logic, metalevel features in the object level are applicable
to any logical system and not only to the classical Horn clause fragment.
The central role and success of these ideas in logic programming pro-
vided an example to follow for research into similar developments for gen-
eral logics.
Logic programming is also a central tool in the new and wide area of
non-monotonic logic and artificial intelligence. The methods of abduction,
the use of constraints and higher order features have all interacted and
supported the new systems of logic designed to cope with practical common
sense reasoning.
The Handbooks
The Handbook of Logic in Artificial Intelligence and Logic Programming
and its companion, the Handbook of Logic in Computer Science, have been
created in response to a growing need for an in-depth survey of the appli-
cation of logic in AI and computer science.
We see the creation of the Handbook as a combination of authoritative
exposition, comprehensive survey, and fundamental reasearch exploring the
underlying unifying themes in the various areas. The intended audience is
graduate students and researchers in the areas of computing and logic, as
well as other people interested in the subject. We assume as background
some mathematical sophistication. Much of the material will also be of
interest to logicians and mathematicians.
The tables of contents of the volumes were finalized after extensive dis-
cussions between Handbook authors and second readers. The first two
volumes present the background logic and mathematics extensively used
in artificial intelligence and logic programming. The point of view is ap-
plication oriented. The other volumes present major areas in which the
methods are used. These include: Volume 1—Logical foundations; Volume
2—Deduction methodologies; Volume 3—Nonmonotonic reasoning and un-
certain reasoning; Volume 4—Epistemic and temporal reasoning.
The chapters, which in many cases are of monographic length and scope,
are written with emphasis on possible unifying themes. The chapters have
an overview, introduction, and main body. A final part is dedicated to
vi PREFACE
more specialized topics.
Chapters are written by internationally renowned researchers in their
respective areas. The chapters are co-ordinated and their contents were dis-
cussed in joint meetings. Each chapter has been written using the following
procedures:
1. A very detailed table of contents was discussed and co-ordinated at
several meetings between authors and editors of related chapters.
The discussion was in the form of a series of lectures by the authors.
Once an agreement was reached on the detailed table of contents, the
authors wrote a draft and sent it to the editors and to other related
authors. For each chapter there is a second reader (the first reader is
the author) whose job it has been to scrutinize the chapter together
with the editors. The second reader's role is very important and has
required effort and serious involvement with the authors.
Second readers for this volume include (in alphabetical order) K. Apt,
M. Bruynooghe, G. Dowek, K. Fine, J. P. Gallagher, F. van Harmelen,
K. Inoue, B. Jayaraman, P. Kanellakis. R. Kowalski, J-L. Lassez, J.
Lloyd, M. Leuschel, D. W. Loveland, M. Maher, J. Meseguer, D.
Miller, G. Nadathur, T. Przymusinski, K. Satoh, D. J. Sherman, and
E. Wimmers.
2. Once this process was completed (i.e. drafts seen and read by a large
enough group of authors), there were other meetings on several chap-
ters in which authors lectured on their chapters and faced the criti-
cism of the editors and audience. The final drafts were prepared after
these meetings.
3. We attached great importance to group effort and co-ordination in the
writing of chapters. The first two parts of each chapter, namely the
introduction-overview and main body are not completely under the
discretion of the author, as he/she had to face the general criticism
of all the other authors. Only the third part of the chapter is entirely
for the authors' own personal contribution.
The Handbook meetings were generously financed by OUP, by SERC
contract SO/809/86, by the Department of Computing at Imperial Col-
lege, and by several anonymous private donations. We would like to thank
our colleagues, authors, second readers, and students for their effort and
professionalism in producing the manuscripts for the Handbook. We would
particularly like to thank the staff of OUP for their continued and enthusi-
astic support, Mrs L. Rivlin for help with design, and Mrs Jane Spurr, our
OUP Adminstrator for her dedication and efficiency.
London D. M. Gabbay
July 1997
Vll
Contents
List of contributors xiv
Introduction: Logic and Logic Programming
Languages
Michael J. O'Donnell 1
1 Introduction 1
1.1 Motivation 1
1.2 A notational apology 3
2 Specifying logic programming languages 7
2.1 Semantic systems and semantic consequences ... 7
2.2 Query Systems, questions and answers 11
2.3 Examples of logic programming languages 15
3 Implementing logic programming languages 37
3.1 Proof systems 37
3.2 Soundness and completeness of proof systems ... 40
3.3 Programming systems 44
3.4 Soundness and completeness of programming
systems 49
3.5 Proof-theoretic foundations for logic programming 56
4 The uses of semantics 57
4.1 Logical semantics vs. denotational semantics . . . . 57
4.2 Logical semantics vs. initial/final-algebra and
Herbrand semantics 58
Equational Logic Programming
Michael J. O'Donnell 69
1 Introduction to equational logic programming 69
1.1 Survey of prerequisites 69
1.2 Motivation for programming with equations . . . . 71
1.3 Outline of the chapter 74
2 Proof systems for equational logic 75
2.1 Inferential proofs 75
2.2 Term rewriting proofs 78
2.3 The confluence property and the completeness of
term rewriting 81
3 Term rewriting proof strategies 96
viii CONTENTS
3.1 Complete and outer most complete rewriting
sequences 97
3.2 Sequentiality analysis and optimal rewriting . . . . 100
4 Algorithms and data structures to implement
equational languages 111
4.1 Data structures to represent terms 111
4.2 Pattern-matching and sequencing methods 120
4.3 Driving procedures for term rewriting 129
5 Compiling efficient code from equations 137
6 Parallel implementation 139
7 Extensions to equational logic programming 141
7.1 Incremental infinite input and output 141
7.2 Solving equations 147
7.3 Indeterminate evaluation in subset logic 149
7.4 Relational rewriting 151
Proof Procedures for Logic Programming
Donald W. Loveland and Gopalan Nadathur 163
1 Building the framework: the resolution procedure . . . . 163
1.1 The resolution procedure 164
1.2 Linear resolution refinements 175
2 The logic programming paradigm 186
2.1 Horn clause logic programming 186
2.2 A framework for logic programming 190
2.3 Abstract logic programming languages 198
3 Extending the logic programming paradigm 212
3.1 A language for hypothetical reasoning 213
3.2 Near-Horn Prolog 219
4 Conclusion 229
The Role of Abduction in Logic Programming
A. C. Kakas, R. A. Kowalski and F. Toni 235
1 Introduction 236
1.1 Abduction in logic 237
1.2 Integrity constraints 241
1.3 Applications 243
2 Knowledge assimilation 244
3 Default reasoning viewed as abduction 249
4 Negation as failure as abduction 254
4.1 Logic programs as abductive frameworks 255
4.2 An abductive proof procedure for LP 257
4.3 An argumentation-theoretic interpretation 263
CONTENTS ix
4.4 An argumentation-theoretic interpretation of the abduc-
tive proof procedure 267
5 Abductive logic programming 269
5.1 Generalized stable model semantics 270
5.2 An abductive proof procedure for ALP 273
5.3 An argumentation-theoretic interpretation of the abduc-
tive proof procedure for ALP 277
5.4 Computation of abduction through TMS 279
5.5 Simulation of abduction 279
5.6 Abduction through deduction from the completion 285
5.7 Abduction and constraint logic programming . . . 286
6 Extended logic programming 288
6.1 Answer set semantics 289
6.2 Restoring consistency of answer sets 290
6.3 Rules and exceptions in LP 293
6.4 (Extended) Logic Programming without Negation as Fail-
ure 295
6.5 An argumentation-theoretic approach to ELP . . . 297
6.6 A methodology for default reasoning with explicit nega-
tion 299
6.7 ELP with abduction 300
7 An abstract argumentation-based framework for default reason-
ing 300
8 Abduction and truth maintenance 303
8.1 Justification-based truth maintenance 304
8.2 Assumption-based truth maintenance 305
9 Conclusions and future work 307
Semantics for Disjunctive and Normal
Disjunctive Logic Programs
Jorge Lobo, Jack Minker and Arcot Rajasekar 325
1 Introduction 325
2 Positive consequences in logic programs 327
2.1 Definite logic programming 328
2.2 Disjunctive logic programming 330
3 Negation in logic programs 337
3.1 Negation in definite logic programs 337
3.2 Negation in disjunctive logic programs 338
4 Normal or general disjunctive logic programs 340
4.1 Stratified definite logic programs 341
4.2 Stratified disjunctive logic programs 343
4.3 Well-founded and generalized well-founded
logic programs 346
x CONTENTS
4.4 Generalized disjunctive well-founded semantics . . 346
5 Summary 347
6 Addendum 349
Negation as Failure, Completion and
Stratification
J. C. Shepherdson 356
1 Overview/introduction 356
1.1 Negation as failure, the closed world assumption
and the Clark completion 356
1.2 Incompleteness of NF for comp(P) 359
1.3 Floundering, an irremovable source of
incompleteness 359
1.4 Cases where SLDNF-resolution is complete for
comp(P) 361
1.5 Semantics for negation via special classes of model 362
1.6 Semantics for negation using non-classical logics . . 363
1.7 Constructive negation: an extension of negation as fail-
ure 364
1.8 Concluding remarks 365
2 Main body 365
2.1 Negation in logic programming 365
2.2 Negation as failure; SLDNF-resolution 367
2.3 The closed world assumption, CWA(P) 370
2.4 The Clark completion, comp(P) 374
2.5 Definite Horn clause programs 384
2.6 Three-valued logic 385
2.7 Cases where SLDNF-resolution is complete for comp(P):
hierarchical, stratified and call-consistent programs. 391
2.8 Semantics for negation in terms of special classes
of models 393
2.9 Constructive negation; an extension of negation as
failure 402
2.10 Modal and autoepistemic logic 406
2.11 Deductive calculi for negation as failure 409
Meta-Programming in Logic Programming
P. M. Hill and J. Gallagher 421
1 Introduction 422
1.1 Theoretical foundations 423
1.2 Applications 425
1.3 Efficiency improvements 426
1.4 Preliminaries 427
CONTENTS xi
2 The non-ground representation 429
2.1 The representation 431
2.2 Reflective predicates 434
2.3 Meta-programming in Prolog 439
3 The ground representation 440
3.1 The representation 442
3.2 Reflective predicates 448
3.3 The language Godel and meta-programming . . . . 453
4 Self-applicability 459
4.1 Separated meta-programming 460
4.2 Amalgamated meta-programming 461
4.3 Ambivalent logic 467
5 Dynamic meta-programming 468
5.1 Constructing programs 468
5.2 Updating programs 471
5.3 The three wise men problem 473
5.4 Transforming and specializing programs 478
6 Specialization of meta-programs 481
6.1 Logic program specialization 481
6.2 Specialization and compilation 487
6.3 Self-applicable program specializers 488
6.4 Applications of meta-program specialization . . . . 489
Higher-Order Logic Programming
Gopalan Nadathur and Dale Miller 499
1 Introduction 500
2 A motivation for higher-order features 502
3 A higher-order logic 510
3.1 The language 510
3.2 Equality between terms 513
3.3 The notion of derivation 517
3.4 A notion of models 519
3.5 Predicate variables and the subformula property . 522
4 Higher-order Horn clauses 523
5 The meaning of computations 528
5.1 Restriction to positive terms 529
5.2 Provability and operational semantics 534
6 Towards a practical realization 537
6.1 The higher-order unification problem 538
6.2 P derivations 541
6.3 Designing an actual interpreter 546
7 Examples of higher-order programming 549
7.1 A concrete syntax for programs 549
xii CONTENTS
7.2 Some simple higher-order programs 552
7.3 Implementing tactics and tacticals 556
7.4 A comparison with functional programming . . . . 560
8 Using a-terms as data structures 561
8.1 Implementing an interpreter for Horn clauses . . . 563
8.2 Dealing with functional programs as data 565
8.3 A limitation of higher-order Horn clauses 572
9 Hereditary Harrop formulas 574
9.1 Universal quantifiers and implications in goals . . . 574
9.2 Recursion over structures with binding 577
10 Conclusion 584
Constraint Logic Programming: A Survey
Joxan Jaffar and Michael J. Maher 591
1 Introduction 592
1.1 Constraint languages 593
1.2 Logic Programming 595
1.3 CLP languages 596
1.4 Synopsis 598
1.5 Notation and terminology 599
2 Constraint domains 601
3 Logical semantics 608
4 Fixedpoint semantics 609
5 Top-down execution 611
6 Soundness and completeness results 615
7 Bottom-up execution 617
8 Concurrent constraint logic programming 619
9 Linguistic extensions 621
9.1 Shrinking the computation tree 621
9.2 Complex constraints 623
9.3 User-defined constraints 624
9.4 Negation 625
9.5 Preferred solutions 626
10 Algorithms for constraint solving 628
10.1 Incrementality 628
10.2 Satisfiability (non-incremental) 630
10.3 Satisfiability (incremental) 633
10.4 Entailment 637
10.5 Projection 640
10.6 Backtracking 643
11 Inference engine 645
11.1 Delaying/wakeup of goals and constraints .... 645
11.2 Abstract machine 651
CONTENTS xiii
11.3 Parallel implementations 657
12 Modelling of complex problems 658
12.1 Analysis and synthesis of analog circuits 658
12.2 Options trading analysis 660
12.3 Temporal reasoning 664
13 Combinatorial search problems 665
13.1 Cutting stock 666
13.2 DNA sequencing 668
13.3 Scheduling 670
13.4 Chemical hypothetical reasoning 671
13.5 Propositional solver 674
14 Further applications 675
Transformation of Logic Programs
Alberto Pettorossi and Maurizio Proietti 697
1 Introduction 697
2 A preliminary example 701
3 Transformation rules for logic programs 704
3.1 Syntax of logic programs 704
3.2 Semantics of logic programs 706
3.3 Unfold/fold rules 707
4 Correctness of the transformation rules 715
4.1 Reversible transformations 716
4.2 A derived goal replacement rule 719
4.3 The unfold/fold proof method 721
4.4 Correctness results for definite programs 723
4.5 Correctness results for normal programs . . . . . . 736
5 Strategies for transforming logic programs 742
5.1 Basic strategies 745
5.2 Techniques which use basic strategies 747
5.3 Overview of other techniques 760
6 Partial evaluation and program specialization 764
7 Related methodologies for program development 771
Index 789
Contributors
J. Gallagher Department of Computer Science, University of Bristol,
University Walk, Bristol BS8 3PN.
P. M. Hill School of Computer Studies, The University of Leeds, Leeds
LS2 9JT.
J. Jaffar Department of Information Systems and Computer Science,
National University of Singapore, Kent Ridge, Singapore 0511.
A. C. Kakas Department of Computer Science, University of Cyprus,
PO Box 537, CY-1678 Nicosia, Cyprus.
R. A. Kowalski Department of Computing, Imperial College of Science,
Technology and Medicine, 180 Queen's Gate, London SW7 2BZ.
J. Lobo Department of Computer Science, University of Illionois at
Chicago Circle, Chicago, Illinois, USA.
D. W. Loveland Computer Science Department, Box 91029, Duke Uni-
versity, Durham, NC 27708-0129, USA.
M. J. Maher IBM Thomas J. Watson Research Center, PO Box 704,
Yorktown Heights, NY 10598, USA.
D. Miller Computer and Information Science, University of Pennsylva-
nia, Philadelphia, PA 19104-6389, USA.
J. Minker Department of Computer Science and Institute for Advanced
Computer Studies, University of Maryland, College Park, Maryland 20742,
USA.
G. Nadathur Department of Computer Science, University of Chicago,
1100 East 58th Street, Chicago, Illinois 60637, USA.
M. J. O'Donnell Department of Computer Science, University of Chicago,
1100 East 58th Street, Chicago, Illinois 60637, USA.
A. Pettorossi Electronics Department, University of Rome II, Via della
Ricerca Scientifica, I-00133 Roma, Italy.
M. Proietti Viale Manzoni 30, I-00185 Roma, Italy.
A. Rajasekar San Diego Supercomputer Center, La Jolla, California
92093, USA.
J. Shepherdson Department of Mathematics, University of Bristol,
University Walk, Bristol BS8 3PN.
CONTRIBUTORS xv
F. Toni Department of Computing, Imperial College of Science, Tech-
nology and Medicine, 180 Queen's Gate, London SW7 2BZ.
Introduction: Logic and Logic
Programming Languages
Michael J. O'Donnell
Contents
1 Introduction 1
1.1 Motivation 1
1.2 A notational apology 3
2 Specifying logic programming languages 7
2.1 Semantic systems and semantic consequences ... 7
2.2 Query Systems, questions and answers 11
2.3 Examples of logic programming languages 15
3 Implementing logic programming languages 37
3.1 Proof systems 37
3.2 Soundness and completeness of proof systems ... 40
3.3 Programming systems 44
3.4 Soundness and completeness of programming systems 49
3.5 Proof-theoretic foundations for logic programming 56
4 The uses of semantics 57
4.1 Logical semantics vs. denotational semantics . . . . 57
4.2 Logical semantics vs. initial/final-algebra and
Herbrand semantics 58
1 Introduction
1.1 Motivation
Logic, according to Webster's dictionary [Webster, 1987], is 'a science that
deals with the principles and criteria of validity of inference and demon-
stration: the science of the formal principles of reasoning.' Such 'principles
and criteria' are always described in terms of a language in which infer-
ence, demonstration, and reasoning may be expressed. One of the most
useful accomplishments of logic for mathematics is the design of a particu-
lar formal language, the First Order Predicate Calculus (FOPC). FOPC is
so successful at expressing the assertions arising in mathematical discourse
2 Michael J. O'Donnell
that mathematicians and computer scientists often identify logic with clas-
sical logic expressed in FOPC. In order to explore a range of possible uses of
logic in the design of programming languages, we discard the conventional
identification of logic with FOPC, and formalize a general schema for a vari-
ety of logical systems, based on the dictionary meaning of the word. Then,
we show how logic programming languages may be designed systematically
for any sufficiently effective logic, and explain how to view Prolog, Dat-
alog, aProlog, Equational Logic Programming, and similar programming
languages, as instances of the general schema of logic programming. Other
generalizations of logic programming have been proposed independently by
Meseguer [Meseguer, 1989], Miller, Nadathur, Pfenning and Scedrov [Miller
et al., 1991], Goguen and Burstall [Goguen and Burstall, 1992].
The purpose of this chapter is to introduce a set of basic concepts for
understanding logic programming, not in terms of its historical develop-
ment, but in a systematic way based on retrospective insights. In order to
achieve a systematic treatment, we need to review a number of elementary
definitions from logic and theoretical computer science and adapt them to
the needs of logic programming. The result is a slightly modified logical
notation, which should be recognizable to those who know the traditional
notation. Conventional logical notation is also extended to new and anal-
ogous concepts, designed to make the similarities and differences between
logical relations and computational relations as transparent as possible.
Computational notation is revised radically to make it look similar to log-
ical notation. The chapter is self-contained, but it includes references to
the logic and theoretical computer science literature for those who wish to
explore connections.
There are a number of possible motivations for developing, studying,
and using logic programming languages. Many people are attracted to
Prolog, the best known logic programming language, simply for the spe-
cial programming tools based on unification and backtracking search that
it provides. This chapter is not concerned with the utility of particular
logic programming languages as programming tools, but with the value
of concepts from logic, particularly semantic concepts, in the design, im-
plementation, and use of programming languages. In particular, while
denotational and algebraic semantics provide excellent tools to describe
important aspects of programming systems, and often to prove correct-
ness of implementations, we will see that logical semantics can exploit the
strong traditional consensus about the meanings of certain logical notations
to prescribe the behavior of programming systems. Logical semantics also
provides a natural approach, through proof systems, to verifiably correct
implementations, that is sometimes simpler than the denotational and al-
gebraic approaches. A comparison of the three styles of semantics will show
that denotational and algebraic semantics provide descriptive tools, logical
semantics provides prescriptive tools, and the methods of algebraic seman-
Introduction 3
tics may be used to translate logical semantics into denotational/algebraic
semantics.
In this chapter, a relation is called computable if and only if its char-
acteristic function is total recursive, and a relation is semicomputable if
and only if the set of ordered pairs in the relation is recursively enumer-
able. Recursion theorists and theoretical computer scientists often refer to
computable sets as decidable sets, but logicians sometimes call a theory
decidable when every formula is either provable or refutable in the theory.
The two meanings of 'decidable' are closely connected, but not identical,
and we avoid confusion by choosing a different word. When some com-
ponent of a relation is a finite set, the set is assumed to be represented
by a list of its members for the purpose of discussing computability and
semicomputability.
1.2 A notational apology
In order to understand logic programming rigorously in terms of formal con-
cepts from mathematical logic, and at the same time intuitively, we need
to look closely at the details of several formal relations from logic and from
theory of computation. We must come to understand the formal similarities
and differences between these relations, and how those formal properties
arise from the intuitive similarities and differences in our intended applica-
tions of these relations. Unfortunately, the conventional notations for logic
and computation look radically different, and take advantage of different
simplifying assumptions, which obscures those connections that are essen-
tial to intuitive applications of the corresponding concepts. So, we will
make visually small variations on conventional logical notation, extending
it to deal with questions and their answers as well as the traditional asser-
tions and their semantic interpretations. Then, we will radically redesign
conventional recursion-theoretic notation in order to display visually the
connections between computational relations and logical relations. In or-
der to be prepared for the strange look of the notations, we need to review
them all briefly in advance, although the precise definitions for the concepts
that they denote will be introduced gradually through Sections 2-3.
The important domains of conventional logical objects for our study are
the sets of
• logical assertions, or formulae F
• sets of formulae, or theories T E 2F
• semantic interpretations, or models M
• sets of models, representing knowledge K E 2M
• proofs, or derivations D
We add the unconventional domain of
• questions Q
4 Michael J. O'Donnell
Answers to questions are particular formulae, so no additional domain is
required for them. The domains of conventional computational objects are
the sets of
• programs P
• inputs I
• computations C
• outputs O
In recursion-theoretic treatments of computation, programs, inputs, and
outputs are all integers, but our analysis is more convenient when they are
allowed to be different domains. We will find strong intuitive analogies and
formal connections between
• programs and sets of formulae
• inputs and questions
• computations and proofs
• outputs and formulae (intended as answers to questions)
In order to understand the analogies and formal connections thoroughly,
we must investigate a number of relations between domains with varying
arities from two to four. In all cases, we will use multiple infix notation.
That is, each n-ary relation will be denoted by n — 1 symbols separating
its arguments. With some care in the geometrical design of the separator
symbols, we get a reasonably mnemonic notation.
There are two quaternary relational notations from which all the other
notations may be derived. Let Q be a question, T a set of formulae, D a
proof, and F a formula. The notation
Q?- T | D - F
means that in response to the question Q, given the postulates in T, we
may discover the proof D of the answer F. Similarly, let I be an input, P
a program, C a computation, and O an output. The notation
I > P D|C -> O
means that in response to the input /, the program P may perform the
computation C, yielding output O. The correspondence between the ar-
guments Q and I, T and P, D and C, F and O displays the crucial cor-
respondence between logic and computation that is at the heart of logic
programming.
There are two closely related trinary notations.
Q7-TI-F
means that there exists a proof D such that Q ?- T I D - F, and
Introduction 5
means that there exists a computation C such that / > P 0 C —i O.
The symbol H in Q ?- F h F is the conventional symbol for proof in
mathematical logic; we take the liberty of decomposing it into the two
symbols I and - for the quaternary notation. The conventional recursion-
theoretic notation for our /> P [H O is <f>p(I) — O. The computational
symbol D-* and its components D and —> are designed to have similar shapes
to h, I, and -.
Other relations from logic do not correspond directly to computational
relations, but can be understood by their connections to the quaternary
form, in which the logic/computation correspondence is direct and trans-
parent. In Section 3.2 I define Q 1- T I D - F to hold exactly when
both
Q f- F and T ID - F
where Q 7- F means that F is an answer (not necessarily a correct one)
to the question Q, and T I D - F means that D is a proof of F, using
postulates in the set T. T I D - F is a conventional concept from math-
ematical logic (often written T, D \- F or T \-& F). The question-answer
relation f- is not conventional. Notice that each separating symbol in the
quaternary notation Q f- T \ D - F is used exactly once in the binary
and trinary forms from which it is defined, so the notational conjunction
of symbols suggests the logical conjunction of the denoted relations. Un-
fortunately, while the symbol 7- appears between the question Q and the
answer formula F in the binary notation Q f- F, it is not adjacent to F
in the quaternary notation Q ?- T I D - F. The dash component - of the
symbol ?- mimics the - symbol at the end of the quaternary notation, and
the similar component of the h symbol from the trinary notation above, as
a reminder that the ?- symbol is expressing a relation to the final answer
formula F, rather than to the set T of postulated formulae.
The quaternary computational relation is also defined as the conjunc-
tion of a binary and a trinary relation, but the arguments involved in these
relations do not correspond to the arguments of the binary and trinary
relations from logic. In Section 3.3 I define /> P D C ->• O to hold exactly
when both
/> P D C and C -+ O
where /> P D C means that the program P on input / may perform the
computation C, and C -> O means that the computation C yields output
O. In this case, the mnemonic suggestion of the conjunction of the trinary
and binary relations in the quaternary notation works out perfectly, as all
argument positions are adjacent to the appropriate separator symbols.
A few other derived notations are useful for denoting relations from
logic. These all agree with conventional notation in mathematical logic.
6 Michael J. O'Donnell
T\-F
means that there exists a proof D such that T I D - F—that is, F is for-
mally derivable from T. Corresponding to the relation I- of formal deriv-
ability is the relation ^ of semantic entailment.
T|=F
means that F is semantically entailed by T. Similarly,
Q?-T|=F
/
means that F is an answer to Q semantically entailed by T (Q 7~ F and
T (= F) in analogy to Q 1- T h F. The mathematical definition of semantic
entailment involves one more semantic relation. Let M be a model, and F
a formula.
M\=F
means that F is true in M.
Table 1 displays all of the special notations for semantic, proof-theoretic,
and computational relations. The precise meanings and applications of
these notations are developed at length in subsequent sections. The no-
tation described above is subscripted when necessary to distinguish the
logical and computational relations of different systems.
L ogic Computation
Semantics Proof
Q7-TID-F I> P 0 C ->• O
Q?-T|=F Q?-ThF I> P\HO
I> PDC
QT- F
C->0
T\D - F
T|=F TI-F
M \=F
Table 1. Special notations for logical and computational relations
Introduction 7
2 Specifying logic programming languages
Logic typically develops its 'principles and criteria of validity of inference'
by studying the relations between notations for assertions, the meanings
of those assertions, and derivations of notations expressing true assertions.
Mathematical logic formalizes these concepts using logical formulae as no-
tations, sets of models to analyze meanings and characterize truth, and
demonstrations or proofs as derivations of true formulae and inferences.
The structure of formulae alone is syntax, their relation to models is se-
mantics, and their relation to proofs is proof theory. Syntax is not relevant
to the present discussion. We must examine formal systems of semantics,
and augment them with formal concepts of questions and their answers, in
order to understand the specification of a logic programming language. In
Section 3 we see how formal systems of proof provide a natural approach
to the implementation of computations for logic programming.
2.1 Semantic systems and semantic consequences
A semantic system relates a set F of logical formulae to a set M of formal
models, each representing a conceivable state of the world in enough detail
to determine when a given formula represents a true assertion in that state
of the world.
Definition 2.1.1. A semantic system is a system S = (F,M, ^=), where
1. F is a set of logical formulae
2. M is a set of models
3. (= is a relation on M x F
Let K C M. Theory(K) = {F e F : M \= F for all M 6 K}.
Let T C F. Models(T) = {M e M : M \= F for all F e T}.
Intuitively, M \= F is intended to mean that formula F holds in, or is
valid in, or is satisfied by, model M. Theory(K) is the fullest possible
description of K using a set of formulae in the language of the system.
Models(T) represents the state of knowledge given implicitly by the for-
mulae in T—knowing T we know that reality corresponds to one of the
models in Models(T), but we do not know which one. Notice the anti-
monotone relation between F and M:
TI C T2 if and only if Models(Ti) D Models(T2)
Kj C K2 if and only if Theory(Ki) D Theory (K 2 )
Models(Ti U T2) = Models(Ti) n Models(T2)
Models(Tx n T2) = Models(T1) U Models(T2)
Theory(K1 U K2) = Theory(K1) n Theory(K2)
Theory(K1 n K2) = Theory (K1) U Theory(K2)
In order to provide satisfactory intuitive insight, a semantic system
must relate the syntactic structure of formulae to the determination of
8 Michael J. O'Donnell
truth. For example, well-known sets of formulae often come with a syntactic
operator to construct, from two formulae A and B, their logical conjunction
A ^ B. The semantics for conjunctions is defined structurally, by the rule
M |= A A B if and only if M |= A and M |= B. The formal analysis of this
chapter deals only with the abstract relation of a model to a formula that
holds in the state of the world represented by that model, not the internal
structure of that relation, because we are interested here in the use of
semantics for understanding logic programming, rather than the deeper
structure of semantics itself. Goguen's and Burstall's institutions [Goguen
and Burstall, 1992] are similar to semantic systems, but they capture in
addition the structural connection between syntax and semantics through
category theory, and show that the functions Models and Theory form a
Galois connection.
Notice that the sets F of formulae and M of models are not required to
be given effectively. In well-known semantic systems, the set of formulae is
normally computable, since formulae are normally finite syntactic objects,
and it is easy to determine mechanically whether a given object is a formula
or not. Infinite formulae, however, have important uses, and they can be
given practical computational interpretations, so we do not add any formal
requirement of computability. The set of models, on the other hand, is
typically quite complex, because models represent conceivable states of an
external world, rather than finite constructions of our own minds. In fact,
for many semantic systems there are technical set-theoretic problems even
in regarding the collection of models in the system as a set, but those
problems do not affect any of the results of this chapter.
In this chapter, basic concepts are illustrated through a running ex-
ample based on the shallow implicational calculus (SIC), designed to be
almost trivial, but just complex enough to make an interesting example.
More realistic examples are treated toward the end of the chapter.
Example 2.1.2. Let At be a set of atomic propositional formulae. The
set Fsh of formulae in the shallow implicational calculus is the smallest set
such that:
1. At C Fsh
2. If a, b € At, then (a => 6) <E Fsh
The set MSH of models in SIC is defined by
Msh = 2At
The semantic relation (=sh^ MSK * FSK is defined by:
1. For a G At, M \=sh a if and only if a € M
2. M |=sh (a => b) if and only if either 6 £ M or a £ M
Introduction 9
Now (Fsh M sh , NSH) is a semantic system, representing the classical con-
cept of meaning for the implicational formulae of SIC.
SIC is just the restriction of the classical propositional calculus [An-
drews, 1986; Kleene, 1952; Gallier, 1986] to atomic propositional formu-
lae, and implications between atomic propositional formulae. It is called
'shallow' because no nesting of implications is allowed. Since the truth of
formulae in SIC (as in the propositional calculus) is determined entirely by
the truth of atomic formulae, a model merely specifies the set of atomic
formulae that are true in a given conceivable state of the world. Following
the tradition of material implication in classical logic, an implication is true
precisely when its conclusion is true, or its hypothesis is false.
For the formal definition of a logic programming language, the impor-
tant thing about a semantic system is the semantic-consequence relation
that it defines, determining when the truth of a set of formulae justifies
inferring the truth of an additional formula.
Definition 2.1.3 ([Andrews, 1986; Gallier, 1986] ). Let S = (F,M,
t=) be a semantic system. The semantic-consequence relation defined by S
is (=C 2F x F, where T |= F if and only if M \= F for all M € Models(T).
The semantic-consequence relation (= is compact if and only if, for all
T C F and F € F, whenever T |= F there exists a finite subset Tf C T
such that Tf |= F.
Intuitively, T (= F means that F is a semantic consequence of T, since
F must be true whenever all formulae in T are true. Semantic consequences
are often called logical consequences; our terminology is chosen to highlight
the contrast between semantic consequences and the provable consequences
of Definition 3.1.4. Notice that Theory(Models(T)) is the set of semantic
consequences of T. It is easy to show that an arbitrary relation |= on 2F x F
is the semantic-consequence relation of some semantic system if and only
if it is
1. reflexive: F 6 T implies that T \= F
2. monotone: T |= F and T C U imply that U (= F
3. transitive: T \= F and T U {F} \= G imply that T \= G
In order for a semantic-consequence relation to be useful for logic program-
ming, or for rigorous formal reasoning, it must be sufficiently effective.
Well-known semantic systems normally define semantic-consequence rela-
tions that are compact—their behavior on arbitrary sets is determined by
their behavior on finite sets. Normal semantic-consequence relations are
semicomputable, but not necessarily computable, when restricted to finite
sets of formulae in the first component. Fortunately, semicomputability is
enough for logic programming.
Example 2.1.4. The semantic-consequence relation \=sh of the shallow
implicational calculus of Example 2.1.2 is compact, and has a particularly
10 Michael J. O'Donnell
simple behavior:
1. for atomic formulae a € At, T |=sh a if and only if there is a fi-
nite sequence {O.Q, ..., am) of atomic formulae such that OQ 6 T, and
(a,i =>• di+i) € T for all i < m, and am = a
2. T |=sh (o =>•fr)if and only if there is a finite sequence (OQ, ..., am) of
atomic formulae such that a0 € T U {a}, and (<n => Oi+i) 6 T for all
i < m, and am = b
We may think of the implications in T as directed edges in a graph whose
vertices are atomic formulae. Atomic formulae in T are marked true. An
atomic formula a is a semantic consequence of T precisely if there is a
directed path from some atomic formula in T to a. Similarly, an implication
a => b is a semantic consequence of T precisely if there is a directed path
from a, or from an atomic formula in T, to 6. Notice that SIC satisfies the
deduction property: [Andrews, 1986; Kleene, 1952; Gallier, 1986]
T |=sh (a => b) if and only if T U {a} (=Sh b
A semantic system provides a conceptual tool for analyzing a primitive sort
of communication in a monologue. A state of implicit knowledge is natu-
rally represented by the set of models corresponding to conceivable states of
the world that are consistent with that knowledge. Notice that larger sets
of models represent smaller amounts of knowledge. For a general discussion
of knowledge as sets of models, the shortcomings of such representations,
and problems and paradoxes that arise when subtle sorts of knowledge are
considered, see [Fagin et al., 1984]. The knowledge involved in formal anal-
ysis of the examples of logic programming in this chapter is simple enough
to be represented by sets of models without presenting the problems that
arise in a more general setting. Explicit knowledge is naturally represented
by a set of formulae. Models(T) is the implicit knowledge given explicitly
by T. Similarly, Theory(K) is the strongest explicit representation of the
implicit knowledge K that is expressible in a given language, but there
is no guarantee that an agent with implicit knowledge K can effectively
produce all of the explicit knowledge Theory (K).
Consider a speaker, whose state of knowledge is represented by Ks, and
an auditor with initial knowledge K0. The speaker wishes to communi-
cate some of her knowledge to the auditor, so she utters a set of formulae
T C Theory(Ks). The impact of the speaker's utterance on the auditor's
state of knowledge is to remove from the auditor's set of models those that
do not satisfy T. That is, K0 is replaced by K1 = K° n Models(T). No-
tice that, if the auditor's initial knowledge is minimal, that is if K° is the
set of all models in the semantic system, then K* = Models(T), so the
formulae implied by the new knowledge, Theory(K^), are exactly the se-
mantic consequences of T. In logic programming systems, the programmer
Introduction 11
plays the part of the speaker above, the processor plays the part of the
auditor, the program is the utterance, and the logical meaning of the pro-
gram is the resulting state of knowledge produced in the auditor/processor.
Inputs to, computations of, and outputs from logic programs are treated
later.
Notice that this style of semantic analysis of communication does not
give either speaker or auditor direct access to inspect or modify the models
constituting the other's state of implicit knowledge. Rather, all such access
is mediated by the utterance of explicit logical formulae. Also, notice that
there is no attempt to construct a unique model to represent a state of
knowledge, or the information communicated by an utterance. Rather, an
increase in implicit knowledge is represented by a reduction in the variabil-
ity of members of a set of models, any one of which might represent the
real state of the world. Unless the semantic-consequence relation of a se-
mantic system is very easy to compute—which it seldom is—the difference
between implicit knowledge and effectively utterable explicit knowledge can
be quite significant. The proof systems of Section 3.1 help describe a way
in which implicit knowledge is made explicit, and yield a rough description
of the computations of logic programs.
The preceding scheme for representing communication of knowledge
deals naturally with a sequence of utterances, by iterating the process of
shrinking the auditor's set of models. There is no provision, however, for
analyzing any sort of interactive dialogue, other than as a pair of formally
unrelated monologues. The query systems of the next section introduce a
primitive sort of interactive question-answering dialogue.
2.2 Query Systems, questions and answers
Semantic systems and semantic-consequence relations are conventional sub-
jects for logical investigation. They suffice for discussions of the truth of a
formula and the validity of the inference of a new formula from a given set
of formulae. In order to analyze the relation between input to a logic pro-
gram and the corresponding output, we need a formal basis for discussing
questions and their answers. Mathematical logicians have given very little
attention to this branch of logic—one exception is the formal treatment
by Belnap and Steel [Belnap Jr. and Steel, 1976]. Query systems are an
abstraction of the common formal schema from a number of instances of
question-answer domains defined by Belnap and Steel.
Definition 2.2.1. A query system is a system Q = (F, Q, ?-), where
1. F is a set of logical formulae
2. Q is a set of questions
3. T- is a relation on Q x F
12 Michael J. O'Donnell
Questions, like formulae, are normally finite syntactic objects, and the set
of all questions is normally computable, but we allow exceptions to the
normal case.
Q ?- F is intended to mean that F is an answer to Q. ?- is intended
only to determine the acceptable form for an answer to a question, not
to carry any information about correctness of an answer. For example, it
is reasonable to say that '2 + 2 = 5' is an incorrect answer to 'what is
2 + 2?', while '2 + 2 = 22' is correct, but not an answer. The correctness or
incorrectness of an answer is evaluated semantically with respect to explicit
knowledge.
Definition 2.2.2. Let Q = {Fq,Q,?-) be a query system, and let
«S = {Fs, M, ^=) be a semantic system with FQ C FS-
Q 7- T |= F means that F € FQ is a semantically correct answer to
Q 6 Q for explicit knowledge T C FS, defined by
Q ?- T |= F if and only if Q ?- F and T |= F
A question Q 6 Q is semantically answerable for explicit knowledge
T C FS if and only if there exists a formula F e FQ such that F is a
semantically correct answer to Q in T.
Meseguer [Meseguer, 1989; Meseguer, 1992] proposes a different notion
of question answering, in which a question is a formula, and an answer is a
proof (in an abstract notation omitting many details) of the formula. (This
is an interesting twist on the formulae as types concept [Howard, 1980;
Tait, 1967], which is more usually applied by letting a program specification
be a formula, and a program be a proof of the formula [Constable et al.,
1986].)
Several interesting query systems may be defined for the shallow impli-
cational calculus.
Example 2.2.3. Let imp be a new formal symbol, and let FSH be the
set of formulae in SIC defined in Example 2.1.2. Let
QS1 = {imp(F) : F € At}
Define the relation ?~siC QS1 x Fsh by
imp(c) ?~si (a =>• b) if and only if a = c
Now (Fsh,Qsi>^~si) is a query system representing the conceivable an-
swers to questions of the form 'what atomic formula does a imply?'
The query system of Example 2.2.3 above is susceptible to two sorts of
answers that may be intuitively unsatisfying. First, in a state of knowledge
in which an atomic formula b is known to be true, (a =>• b) is a correct
Introduction 13
answer to questions imp (a) for all atomic formulae a. This problem may
be avoided by considering states of knowledge in which only implications are
known, or it may be addressed by changing the underlying semantic system
to one with a relevant interpretation of implication [Anderson and Belnap
Jr., 1975]. Second, (a => a) is a correct answer to the question imp(a).
(a => a) is a tautology, that is, it holds in all models, so it cannot give
any information about a state of knowledge. We could define a new query
system, in which only nontautologies are considered to be answers. Since,
for most useful logics, the detection of tautologies ranges from intractable to
impossible, such a technique is generally unsatisfying. A better approach
is to let a question present a set of atomic formulae that must not be
used in an answer, since the questioner considers them to be insufficiently
informative. We may find later that certain nontautological formulae are
uninformative for various reasons, and this technique reserves the flexibility
to handle those cases.
Example 2.2.4. Let rest-imp be a new formal symbol, and let
Qs2 = {rest-imp(a, A) : a € At and A C At}
Define the relation ?~S2C QS2 x FSK by
rest-imp(c, C) ?~si (a =>• 6) if and only if a = c and 6 £ C
Now (Fsh,Qsi > ?~si) is a query system representing the conceivable an-
swers to questions of the form 'what atomic formula not in A does a imply?'
The new query system of Example 2.2.4 may be used very flexibly
to guide answers toward the most informative implications of an atomic
formula a. If the explicit knowledge available to the auditor to answer
questions is finite, then there are only a finite number of atomic formulae
that can appear in an answer, so the sets of prohibited formulae may simply
be listed. In more sophisticated languages than SIC, we need some sort
of finite notation for describing large and even infinite sets of prohibited
answers.
Query systems allow a further enrichment of the analysis of communi-
cation. Once a speaker has communicated some implicit knowledge K to
an auditor by uttering formulae, a questioner (sometimes, but not always,
identical with the speaker) may ask a question Q, which the auditor tries
to answer by discovering a formula F such that Q f- F (F is an answer
to the question Q), and F 6 Theory (K) (Q is correct according to the
implicit knowledge K).
So, given a set T of formulae expressing the knowledge Models(T), a
question Q provides an additional constraint on the search for a formula F
such that T (= F, to ensure that Q 1- F as well. In many cases, there is
more than one correct answer F such that Q ?- T (= F. Depending on the
14 Michael J. O'Donnell
context, the questioner may want a single answer chosen nondeterministi-
cally from the set of correct answers, or a best answer under some criterion.
The case where the questioner wants a list of all answers may be modelled
by representing that list by a single formula giving the conjunction of all
the list elements. A particularly useful criterion for best answer uses the
logical consequence relation.
Definition 2.2.5. Let Q = {Fq,Q, ?-) be a query system, and let
S = (Fs , W, |=) be a semantic system with FQ C FS . F is a consequen-
tially strongest correct answer to the question Q for explicit knowledge T
if and only if
2. for all G € FQ, whenever Q ?- T |= G, then {F} |= G
Consequentially strongest answers are not necessarily unique, but all con-
sequentially strongest answers are semantically equivalent. Notice that the
comparison of strength for two answers F and G is done without taking
into account the knowledge T. That is, we require {F} \= G, rather than
T U {F} |= G. This makes sense because T is known to the auditor, but
not necessarily to the questioner. Even if the questioner knows T, he may
not be able to derive its consequences. The whole purpose of the communi-
cation between questioner and auditor is to give the questioner the benefit
of the auditor's knowledge and inferential power. So, the value of an an-
swer to the questioner must be determined independently of the knowledge
used by the auditor in its construction (the alternative form T U {F} |= G
holds trivially by monotonicity, so it carries no information anyway).
In order to illustrate the use of consequentially strongest answers, we
extend SIC to deal with conjunctions of implications.
Example 2.2.6. Expand the formulae of SIC to the set
FSc = FSh U {Fi A • • • A Fm : F, G € Fsh}
of formulae in the shallow implicational-conjunctive calculus (SICC). The
semantic systems and proof systems of Examples 2.1.2, 3.1.3, 3.1.2 extend
in the natural way to deal with conjunctive formulae. Let conj-imp be a
new formal symbol, and let
Qsc = {conj-imp(a) : a £ At}
Define the relation ?-scC QSc x FSc by
conj-imp (c) ?~sc («i =>• Z»i) A • • • A (am =>• bm) if and only if
Oj = c for all i < m
Introduction 15
Now (Fsc,Qsc>?~Sc) is a query system representing the conceivable an-
swers to questions of the form 'what are some atomic formulae implied by
a?' A consequentially strongest answer to conj-imp(a) is a conjunction
of all of the implications with hypothesis a that hold in a given state of
knowledge.
The concept of consequentially strongest answers is particularly helpful
in systems where a potentially infinite answer is produced incrementally.
The entire infinite answer may often be read as an infinite conjunction of
finite formulae, and the requirement of consequentially strongest answers
guarantees that the incremental production of the answer does not stop
prematurely, before all available information is expressed.
In logic programming systems, the user of a program plays the part of
the questioner. The input is the question, and the output is the answer, if
any, discovered and proved by the processor/auditor. This scenario allows
the knowledge resources of a programmer/speaker to be combined with the
deductive powers of a processor/auditor, in order to answer questions from
the user/questioner.
2.3 Examples of logic programming languages
Now we can design a wide variety of logic programming languages, by
defining appropriate semantic systems and query systems.
2.3.1 Programming in first-order predicate calculus
Several logic programming systems, particularly Prolog and Relational
Databases, are essentially sublanguages of a general language for logic pro-
gramming in FOPC.
Definition 2.3.1 ([Andrews, 1986; Kleene, 1952; Gallier, 1986]).
Let V be a countably infinite set. Members of V are called variables, and
are written u,v,w, x, y,z, sometimes with subscripts.
Let Fun; be a countably infinite set for each i > 0, with Funi and Funj
disjoint when i = j. Members of Fun^ are called function symbols of arity
i, and are written f,g,h, sometimes with subscripts. A function symbol of
arity 0 in Funo is called a constant, and may be written a, 6, c, d, e.
Let Fred; be a countably infinite set for each i > 0, with Predj and
Predj disjoint when i ^ j, Predj and Funj disjoint for all i and j. Mem-
bers of Predi are called predicate or relation symbols of arity i, and are
written P,Q,R, sometimes with subscripts. A predicate symbol of arity 0
in Predo is called a propositional symbol, and is closely analogous to an
atomic propositional formula in At as used in Example 2.1.2.
The set Tp of terms in FOPC is defined inductively as the least set
such that:
1. if x€ V then x e TP
2. if a 6 Fun0 then a e Tp
16 Michael J. O'Donnell
3. if f 6EFun; for some i > 0 and ti,... ,t, € TP, then /(ti,... ,ti) 6 Tp
Terms are intended to represent objects in some universe of discourse.
/ ( < i , . . . , t { ) is intended to represent the result of applying the function
denoted by / to the objects represented by ti,...,ti. We often take the
liberty of writing binary function application in infix notation. For exam-
ple, if + € Fun2 we may write (ti + i?) for +(^1,^2)- A ground term is a
term containing no variables.
The set Fp of formulae in FOPC is defined inductively as the least set
such that:
1. True, False € Fp
2. if P e Predo, then P £ FP
3. if P E Predj for some i > O a n d f i , . . . ,tt e TP, thenP(ti,... ,ti) E Fp
4. if A, B e FP, then (A A B), (AVB),(A=* B), (->A) e FP
5. if A 6 Fp and x <E V, then (3x : A), (Vx :A)eFP
Formulae in FOPC are intended to represent assertions about the objects
represented by their component terms. True and False are the trivially
true and false assertions, respectively. P(ti,..., ti) represents the assertion
that the relation denoted by P holds between ti,... ,ti. (A A B), (A V B),
(A => B), (-*A) represent the usual conjunction, disjunction, implication,
and negation. (3x : A) represents 'there exists x such that A,' and (Vx : A)
represents 'for all x A.' Parentheses may dropped when they can be inferred
from normal precedence rules.
In a more general setting, it is best to understand Furii and Pred^ as
parameters giving a signature for first-order logic, and let them vary to
produce an infinite class of predicate calculi. For this chapter, we may take
Fun; and Predi to be arbitrary but fixed. In many texts on mathematical
logic, the language of FOPC includes a special binary predicate symbol '='
for equality. We follow the Prolog tradition in using the pure first-order
predicate calculus, without equality, and referring to it simply as FOPC.
The intended meanings of FOPC formulae sketched above are formal-
ized by the traditional semantic system defined below. First, we need a set
of models for FOPC.
Definition 2.3.2 ([Andrews, 1986; Kleene, 1952; Gallier, 1986]).
Let U be an infinite set, called the universe. Let U C U.
A variable assignment over U is a function z/: V —)• U.
A predicate assignment over U is a function
p : LKPredi : i > 0} -> U{2 (£/i) : i > 0}
such that P 6 Pred; implies p(P) C [/' for all i > 0.
A function assignment over U is a function
T : LKFuni : i > 0} -> (J{U^ :i>0}
such that / e Funi implies r(f) : Ui -> U for all i > 0.
If U C U, T is a function assignment over U, and p is a predicate
Introduction 17
assignment over U, then (U, r, p) is a model of FOPC. Mp is the set of all
models of FOPC.
Notice that FOPC models assign values to function and predicate sym-
bols, but not to variables. The exclusion of variable assignments from
models is the only technically significant distinction between variables and
constant symbols. A function assignment and a variable assignment to-
gether determine a valuation of terms. With a predicate assignment, they
also define a valuation of formulae.
Definition 2.3.3 ([Andrews, 1986; Kleene, 1952; Gallier, 1986]).
Let r be a function assignment over U, v a variable assignment over U.
The term valuation rv : Tp —>• U is defined inductively by
1. if x e V, then TV(X) = v(x)
2. if / e Funi, and t 1 , . . . , ti € TP, then
rv(f(ti,..., ti)) = T ( f ) ( r v ( t i ) , . . . , rv(ti))
In addition, let p be a predicate assignment over U. The formula valuation
PT,V '• FP ->• {0,1} is defined inductively by
1. p,.,,, (False) = 0
2. p r>v (True) = 1
3. if Pe Predi, and * i , . . . , * i £ Tp, then pT,v(P(ti,... ,<<)) = 1 if and
Only if (Tr,v ( t 1 ) , . . .,TT,v(ti)) € p(P)
4. pT,v(A A B) = 1 if and only if pTjU(A) = 1 and pr,v(B) = 1
5. pT,v(A V B) = 1 if and only if pr,v(A) = 1 or pT,v(B) = 1
6. pT,v(A =>• B) — 1 if and only if pT<v(A) = 0 or pT^(B) = 1
7- pT,v(-^A) = 1 if and only if pr^(A) = 0
8. pT}V(Bx : A) = 1 if and only if /?,-,„/ (A) — I for some v' such that y ^ x
implies v(y] = v'(y)
9. p Tit/ (Va;: .A) = 1 if and only if pTy(A) = 1 for all v' such that y ^ x
implies v(y) = v'(y)
Now, we may define an appropriate semantic system for FOPC.
Definition 2.3.4. The classical semantic system for FOPC is (Fp,Mp,
(=p), where (U,r,p) (=p F if and only if pTtll(F) = 1 for all variable as-
signments v over U.
FOPC is particularly well suited to defining relations, letting variables
stand for the parameters in the relations. For such purposes, it is important
to distinguish between uses of variables that are bound by the quantifiers
3 and V, and those that are free to be used as relational parameters.
Definition 2.3.5 ([Andrews, 1986; Kleene, 1952; Gallier, 1986]).
An occurrence of a variable a; in a formula is bound if and only if it is
located within a subformula of the form (3x : F) or the form (Vz : F). An
occurrence of a variable a; in a formula is free if and only if it is not bound.
18 Michael J. O'Donnell
A sentence is a formula with no free occurrences of variables. If F € Fp
is a formula, and all free occurrences of variables in F are among xi,. . .,14,
then the sentence (Vxi : • • • Vzj : F) is a closure of F. It is easy to see that
F is semantically equivalent to each of its closures.
Let xi, . . . , Xi be a list of variables with no repetitions, and let ti , . . . , t j
6 Tp. F[ti , . . . , ti/xi , . . . , Xi] is the formula that results from substituting
the term tj for every free occurrence of the variable Xj in the formula F,
for each j, 1 < j; < i, renaming bound variables of F when necessary
so that the variables of ti,...,ti are free in the result [Andrews, 1986;
Kleene, 1952; Gallier, 1986] . When G = F[ti , . . . , ti/n , . . . , x^ , we say
that G is an instance of F, and that F is more general than G. These
relations apply naturally to terms as well as formulae.
G is a variable renaming of F if and only if G = F[yi ,..., yi/Xi , . . . , Xi] ,
for some list of variables j/i, . . . , j/t with no repetitions (equivalently, G is an
instance of F and F is an instance of G, since we get F = G[XI ,..., Xi/y\ ,
...,W]).
It is very natural to think of a query system in which we may ask what
substitutions for the free variables of a formula make it true.
Definition 2.3.6 ([Belnap Jr. and Steel, 1976]). Let what be a
new formal symbol. Let
= {(whatzi,...,Zi :F) : F 6
Define the relation ?-pC Qp x Fp by
(what x\ , . . . , Xi : F) T- p G
if and only if
G = F[ti, . . . ,*i/asi, . . . ,arj for some ti, . . . ,fc € TP
Now (Fp, QP, ?-p) is a query system representing the conceivable single
answers to questions of the form 'for what terms t\ , . . . , ti does F[t i , . . . , ti/
* ! , . . . , Si] hold?'
The query system above has a crucial role in the profound theoretical
connections between logic and computation. For each finite (or even semi-
computable) set T C Fp of formulae, and each question Q = (what xi , . . . ,
Xi : F), the set
{<ti, . . - , ti) : Q ?-P T \=P F[*i, . . . , ti/xi ,..., Xi]}
is semicomputable. If we use some constant symbol c G Funo to repre-
sent the number 0, some unary function symbol / & Funi to represent the
Introduction 19
successor function, and some binary predicate symbol E to represent the
equality relation, then we may define all semicomputable sets of integers by
formulae in a simple and natural way. We let R C Fp be a finite set of pos-
tulates for Robinson's arithmetic (system Q of [Mostowski et al., 1953])—a
primitive theory sufficient for deriving answers to all addition and multi-
plication problems. Then every semicomputable set is of the form
{j : (what x : F) T-P R \=P F[fi(c)/x}}
for some formula F 6 Fp. Similarly, every partial computable function </>
may be defined by choosing an appropriate formula F 6 Fp, and letting
(j)(i) be the unique number j such that
(whaty : F(f(c)/x}) ^p R \=P F(f(c),r(c)/x,y}
Notice that the FOPC questions (what Xi,..., Xi : F) do not allow triv-
ial tautological answers, such as the correct answer (a => a) to the question
imp(a) ('what atomic formula does a imply?', Example 2.2.3, Section 2.2).
In fact, (what xi,..., Xi : F) has a tautological answer if and only if F is
a tautology. FOPC questions avoid this problem through the distinction
between predicate symbols and function symbols. When we try to find an
answer F[ti,..., tifx\,..., £;] to the question (what x\,..., Xi : F), the in-
formation in the question (what xi,..., Xi : F) is carried largely through
predicate symbols, while the information in the answer F[t\,..., tijx\,...,
Xi] is carried entirely by the function symbols in ti,..., ti, since the pred-
icate symbols in the formula F are already fixed by the question. It is
the syntactic incompatibility between the formula given in the question
and the terms substituted in by the answer that prevents tautological an-
swers. Suppose that FOPC were extended with a symbol choose, where
(choosex : F) is a term such that (3x : F) implies F[(choosea;: F)/x}.
Then jP[(choose x : F)/x] would be a trivially (but not quite tautologi-
cally) correct answer to (what x : F) except when no correct answer exists.
The absence of trivial tautological answers does not mean that all an-
swers to FOPC questions are equally useful. In some cases a question
has a most general semantically correct answer. This provides a nice syn-
tactic way to recognize certain consequentially strongest answers, and a
useful characterization of all answers even when there is no consequentially
strongest answer.
Proposition 2.3.7. // G' is an instance of G, then G' is a semantic
consequence of G (G ^p G'). It follows immediately that if G is a se-
mantically correct answer to Q £ Qp (Q ?-p T \=p G), then G' is also a
semantically correct answer (Q ?-p T \=p G').
If G' is a variable renaming of G, then they are semantically equivalent.
20 Michael J. O'Donnell
Definition 2.3.8. Let T C Fp be a set of formulae, and let Q = (what x\ ,
. . . , Xi : F) e QP be a question. G is a most general answer to Q for explicit
knowledge T if and only if
2. for all GO <E FP, if G is an instance of G0 and Q 7-P T |=P G0, then
GO is a variable renaming of G.
A set A C Fp of formulae is a most general set of correct answers to Q
for T if and only if
1. each formula F e A is a most general answer to Q for T
2. for all formulae G e Fp, if Q ?-p T ^p G, then G is an instance of
some F € A
3. for all formulae FI, F2 £ A, if F2 is an instance of FI, then F2 = FI
It is easy to see that for each question Q £ QP and set of formulae T C Fp
there is a most general set of correct answers (possibly empty or infinite).
Furthermore, the most general set of correct answers is unique up to vari-
able renaming of its members.
Notice that it is very easy to generate all correct answers to a question
in Qp from the most general set— they are precisely the instances of its
members. If Q has a consequentially strongest answer, then it has a conse-
quentially strongest answer that is also most general. If the most general
set of correct answers is the singleton set {F}, then F is a consequentially
strongest answer.
Example 2.3.9. Let G <E Pred2 be a binary predicate symbol, where
G(ti , £2) is intended to assert that ti is strictly larger than t% . Suppose that
objects in the universe have left and right portions, and that l,r € Funi
denote the operations that produce those portions. A minimal natural
state of knowledge about such a situation is
A natural question is Q = (what Z, y : G(x,y)). The most general set of
answers is
Ao = {G(z, !(*)), G(x,r(x))}
Other answers include G(l(x),r(l(x))), G(r(x),l(r(x))), etc.
TO has only the specific knowledge that a whole is larger than its por-
tions, but not the general knowledge that the relation G is a strict ordering
relation. Let
Ti = T0L>{Vx,y,z:(G(x,y)AG(y,z))=>
G(x, z), Vx, y : -(G(z, y) A G(y, a?))}
For this extended knowledge, the most general set of answers to Q is the
infinite set
Introduction 21
A! = AoU{G(*,l(J(*))), G(*,i(r(*))), G(x,r(r(x))), G ( x , l ( l ( l ( x ) ) ) ) , • ••}
The first formula added to TI above, which expresses the transitivity of
ordering, leads to the additional answers.
In some cases, it is convenient to allow conjunctions of answers to ques-
tions in Qp to be conjoined into a single answer.
Definition 2.3.10. Let conj-what be a new formal symbol. Let
QPA = {(conj-what xi, . . . ,Xi : F) : F € FP}
Define the relation T-FA^ QPA x Fp by
(conj-what xi,...,Xi : F) ?-pA G
if and only if
G = F[t{, ..., t}/xi,. . . ,Xi] A • • • A F[t?, . . . , *r/zi, ...,xt] for some
Now (FpA,Qp A , ?~PA) is a query system representing the conceivable
conjunctive answers to questions of the form 'for what terms ti , . . . , £; does
Answers to (conj-what x\ , . . . , Xi : F) are precisely conjunctions of
answers to (what xi,...,Xi : F). (conj-what x\ , . . . , Xj : F) may have
a consequentially strongest answer even though (what x\, . . . ,Xi : F) does
not. In particular, whenever the most general set of answers to (what xi,
. . . , Xi : F) is finite, the conjunction of those answers is a consequentially
strongest answer to (conj-what xi , . . . , Xi : F).
2.3.2 Prolog
The most famous programming language associated with logic program-
ming, and the one that instigated scientists to study logic programming as
a specialty within computer science, is Prolog [Kowalski, 1974; van Emden
and Kowalski, 1976], the creation of Kowalski and Colmerauer. The name
'Prolog' is usually associated with a group of very similar programming
languages based on logic programming in Horn clauses— a particular sub-
language of the first-order predicate calculus. Prolog as it is actually used
deviates from pure logic programming in several ways: it fails to produce
some logically entailed answers; in rare cases it produces logically incor-
rect answers; and it contains constructs that are not definable naturally
in FOPC, and which are normally understood in conventional imperative
ways. Furthermore, the criteria by which Prolog chooses one of several
possible answers cannot be explained naturally in terms of the semantics
22 Michael J. O'Donnell
of FOPC. The discrepancy between Prolog and Horn-clause logic program-
ming is closely comparable to the discrepancy between Lisp and the purely
functional language based on the lambda calculus that is sometimes called
'pure lazy Lisp'. In spite of the discrepancies, the best way to understand
Prolog is to conceive of it as an approximation to, and extension of, a
Horn-clause logic programming language.
The essential idea behind Prolog is to find correct answers to predi-
cate calculus questions in QP of Section 2.3.1 above. In principle, all such
answers are computable. Currently known implementation techniques re-
quire fairly stringent conditions on the sets of formulae that may be used as
explicit knowledge for question answering, and on the questions that may
be asked, in order to search for and generate proofs in a relatively simple
and disciplined way. Prolog is based on the restriction of programs to sets
of Horn clauses, and questions to simple conjunctions of positive atomic
formulae.
Definition 2.3.11. A formula F € Fp is a Horn clause if and only if it
is in one of the forms
1. F = (Rl(ti,!,. . . , * M l ) A • • • A Rm(tm,l,- • • , *m,i m ) => P(«l, • . . , Uj))
2. F = (.Ri(ti,i, . . .,<!,;,) A • • • A R m (t m , i, . . .,tm,im) => False)
3. F = (True=»P(«i,...,«,-))
4. F - (True =>• False)
where R 1 , . . . , Rm, P are predicate symbols, and titi, . . . , t m , i m > W i > - . . ,Uj
are terms.
A pure Prolog program is a finite set of Horn clauses.
A pure Prolog input is a question of the form
(what x\,...,Xi:Pi («i,i , . . . , titil ) A • • • A Pm(£m,i , . . . , im,im ))
where x 1 , . . . , x i are precisely the free variables of PI (<i,i , . . . , 1 1,^ ) A • • • A
•*• m ( * m , l > • • • i *TO,i m j-
In order to promote readability of programs, within the limitations of
older keyboards and printers, typical Prolog implementations replace the
conventional logical symbol 'A' by ';', they write the arguments to implica-
tions in the reverse of the usual order and replace the symbol '•<=' by ':— '.
Also, they denote the symbol 'False' in the conclusion of an implication,
and 'True' in the hypothesis, by the empty string. Predicate symbols are
written in lower case, and variables are written in upper case. So, the four
forms of Horn clause in actual Prolog programs look like
Introduction 23
Since a question always requests substitutions for all free variables, the
header 'whatxi,...,Xi' is omitted and the question is abbreviated in the
form
Since the substitution in an answer of the form
(Rl(ti,i,. . ., tl.ij A • • • A Rm(tm,i,. . ., t m ,t m ))[*l, • • • ,Si/Xi, ...,Xi]
completely determines the answer, actual Prolog output presents only the
substitution, in the form
These notational variations and abbreviations have a substantial impact on
the way Prolog programs, inputs, and outputs look, but they are completely
transparent to the logical meaning.
When a pure Prolog input is presented to a pure Prolog program, all
possible answers may be derived systematically by treating each clause of
form 1 as a recursive part of a definition of the procedure P in terms of calls
to the procedures j R i , . . . , Rm- Because the same predicate symbol F may
appear in the conclusion of more than one clause, each clause normally pro-
vides only a part of the definition of P. Clauses of form 3 are nonrecursive
parts of the definition of a procedure P. Clauses of form 2 are somewhat
peculiar: they act like extra hardcoded parts of the input. Clauses of form 4
are useless in programs, but allowed by the formal definition. Different im-
plementations may or may not prohibit the degenerate forms. Prolog tries
to choose more general answers instead of their instances, but it does not
guarantee that all answers produced are most general. An understanding
of the precise correspondence of Prolog to the answering of pure Prolog
input questions using pure Prolog programs requires a lot of detail that
must wait until the chapter 'Horn clause logic programming'.
A notable variation on Prolog is aProlog [Nadathur and Miller, 1990;
Nadathur and Miller, 1988]. This language extends predicate calculus logic
programming into the omega-order predicate calculus, also called type the-
ory [Andrews, 1986]. Higher-order predicate calculi add variables ranging
over predicates, quantification over such variables, and predicates that ap-
ply to other predicates. aProlog generalizes the Horn clauses of FOPC
to the hereditary Harrop formulae of the omega-order predicate calculus
[Miller et al., 1991].
2.3.3 Relational databases and Datalog
Relational databases [Date, 1986; Codd, 1970] were invented by Codd,
completely independently of the development of Prolog and logic program-
ming in the programming language community. Nonetheless, relational
24 Michael J. O'Dormell
databases and their queries may be understood very naturally in terms of
logic programming concepts. This point has been noted by the Prolog com-
munity, leading to the definition of Datalog [Maier and Warren, 1988], a
variant of relational databases in the style of Prolog. Gallaire, Minker, and
Nicolas have developed the concept of deductive databases [Gallaire et al.,
1984] to capture the logical content of relational databases and their vari-
ants. Reiter [Reiter, 1984] has shown how a logical view of databases has
advantages of robustness under several useful generalizations of database
functionality. My proposed approach to logic programming applies logic
to programming languages in essentially the same way that Reiter applies
logic to databases.
Like Prolog, relational database systems find correct answers to pred-
icate calculus questions in QF of Section 2.3.1. The different natural as-
sumptions and performance requirements of the database world lead to far
more stringent restrictions on the sets of formulae that may be used for
question answering. The questions, which correspond to database queries,
are essentially unrestricted. Because of the stringent restrictions on knowl-
edge formulae, which limit answers to a predetermined finite set of pos-
sibilities, actual relational database implementations do not deviate from
pure logic programming, except by offering constructs that go beyond the
logical definitions. On purely relational queries, they produce precisely all
of the semantically correct answers.
Definition 2.3.12. A pure relational database is a finite set of formu-
lae of the form P(C 1 , ... ,C i ), where P 6 Predj is a predicate symbol and
c i , . . . ,a £ Funo are constant symbols.
A pure relational database as defined above is the natural logical view
of the contents of a relational database system at any given time. The
constant symbols are the objects that may appear in fields of relations in
the database. Each predicate symbol represents one of the relations in the
database. Each formula P(CI, ... ,c±) represents the presence of the tuple
(GI, ..., a) in the relation P.
Pure relational database query languages are equivalent to QP—all
queries of the form (what xi,..., Xi : F) are allowed. Because of the sim-
plicity of the formulae in the database, restrictions on the queries are not re-
quired for tractable implementation. Notice the complementarity of Prolog
and relational database query languages. Prolog allows relatively powerful
Horn clauses as knowledge formulae, but restricts queries to conjunctions of
atomic formulae. Relational database query languages restrict knowledge
formulae to the very simple form of predicate symbols applied to constant
symbols, but allow unrestricted FOPC what queries.
The simplicity of the formulae in a pure relational database guaran-
tees that the set of answers to (what x\,..., Xi : F) is finite, and relational
database query systems actually produce all the semantically correct an-
Introduction 25
swers. Equivalently, we may think of a relational database query system
as producing the consequentially strongest answer (unique up to the or-
der of the conjuncts) to (conj-what xi,...,n : F). The consequentially
strongest answer to the conj-what form of the question is simply the
conjunction of all the answers to the what form.
Datalog restricts queries to the Prolog form, but allows Horn clauses
with no function symbols (no 'functors' in Prolog jargon) to be added to the
formulae of the database to provide additional knowledge for the purpose
of answering a given query. The Horn clauses are thought of as defining
new relations to be used in the query, rather than as adding information
to the database.
A variety of notations have been used for the expression of FOPC
queries in relational database systems. These variant notations may look
very different from FOPC at first glance, but in fact they are equivalent in
querying power. The complete translations between notations are clumsy
to define formally, so we consider the general principles behind the nota-
tion, and illustrate the translation with examples. I use Codd's language
DSL ALPHA [Date, 1986; Codd, 1971], often called relational calculus, for
the database notation.
Instead of referring directly to objects in the universe U, relational
database languages generally refer to tuples in relations, because they cor-
respond to records in a conventional file. Instead of the positional notation
P(ti,... ,ti), they give domain names D\,... ,Di to the parameter posi-
tions. The name of a relation (predicate symbol) is treated as a variable
ranging over the set of tuples in that relation. The value of the domain D
in an arbitrary tuple of the relation P is denoted by the record notation
P.D. P.D = c means that the value in the domain D of an unknown tuple
in the relation P is c, and P.D = Q.E means that the value in the domain
D of some tuple in P is the same as that in domain E of some tuple in
Q. Because of the absence of function symbols with arity greater than 0,
this use of equality does not introduce the general capabilities of FOPC
with equality, it merely captures the limited sort of equality information
that is represented in pure FOPC by multiple occurrences of constants and
variables, and by binding variables to constants. In principle, the equation
x = c can be understood as Pc(x), where P is a special predicate postulated
to hold on c, and to not hold on all other constant symbols. For example,
if P and Q are binary predicates and D,E,F,G are appropriate domain
names, then the DSL ALPHA expression
P.D = c A P.E = Q.F A Q.G = d
is equivalent to the FOPC formula
26 Michael J. O'Donndl
Additional variables may be declared in DSL ALPHA to range over the
tuples of a relation in the database, and these variables may be quantified
with V and 3. So, in the presence of the declarations
RANGE X P
RANGE Y O
which declare the variable X to range over tuples of the relation P and Y
to range over tuples of Q, the expression
VX(X.D = c V BY (X.E = Y.F A Y.G = d))
is equivalent to the FOPC formula
Van :Vz 2 :(P(ii,z 2 )=*(zi = cV Q(x2,d))).
Notice that the existential quantifier in the DSL ALPHA expression is left
out of the FOPC formula, because one of its components is bound to the
constant d, and the other to the E component of the variable X, whose
quantification occurs before that of Y. In general, a FOPC quantifier is
required for each domain position of a quantified tuple in a DSL ALPHA
expression that is not bound by equality either to a constant or to a com-
ponent of a variable that has already been quantified. With the same
RANGE declarations above, the DSL ALPHA expression
VX3Y(X.D = Y.G)
is equivalent to the FOPC formula
So, there are some syntactic subtleties in translating quantification from
DSL ALPHA into FOPC, but they are all solvable with sufficient care.
There is one semantic problem that prevents DSL ALPHA from express-
ing everything that can be expressed by FOPC formulae with only 0-ary
function symbols. That is the limitation of the range of quantified variables
in DSL ALPHA to the set of tuples actually occurring in a relation in the
database, while FOPC may quantify over an abstract universe U. There is
no expression in DSL ALPHA semantically equivalent to Vx : P(x), since
DSL ALPHA can only express the fact that every object in a tuple of the
database satisfies the predicate P. Because these objects are exactly those
mentioned by the knowledge formulae, however, the restricted quantifica-
tion of DSL ALPHA yields the same answers to queries as the unrestricted
quantification of FOPC, so in terms of the behavior of query-answering
Introduction 27
systems the notations are equivalent. Another way of viewing this seman-
tic difference is to suppose that each database implicitly contains a dosed
world assumption [Reiter, 1978] expressing the fact that only the objects
mentioned in the database exist. In FOPC with equality, the closed world
assumption may be expressed by the formula Va; : x = CQ V • • • V x = cn ,
where CD, . . . , cn are all of the constant symbols appearing in the database.
Without equality, we can only express the fact that every object acts just
like one of CQ, . . . , cn (i.e., it satisfies exactly the same formulae), and even
that requires an infinite number of formulae.
Given the translation of DSL ALPHA expressions to FOPC formulae
suggested above, we may translate DSL ALPHA queries into FOPC ques-
tions. DSL ALPHA queries have the general form
GET
where PI , . . . , Pi are relations in the database, Q is a new relational symbol
not occurring in the database, D\, . . . ,Di are domain names, and E is an
expression. Appropriate declarations of the ranges of variables in E must
be given before the query. Let F be a FOPC formula equivalent to E, using
the variables x\ , . . . , Xi for the values PI .D\ , . . . , Pi-Di . Then, the effect of
the DSL ALPHA query above is to assign to Q the relation (set of tuples)
answering the question
That is,
where D is the set of formulae in the database. Equivalently, the value of
Q may be thought of as an abbreviation for the consequentially strongest
answer to conj-what Xi , . . . , Xi : F for D, which is just the conjunction of
all the answers to what x 1 , . . . , X i : F.
Another type of notation for relational database queries avoids ex-
plicit quantification entirely, and uses the relational operations of pro-
jection, join, etc. to define new relations from those in the database.
Notation in the style of DSL ALPHA above is called relational calcu-
lus, because of the similarity to predicate calculus in the use of explicit
quantification. The alternate approach through operations on relations
is called relational algebra, because the equations that express the prop-
erties of the relational operations resemble well-known definitions of al-
gebras. In fact, each notation has its own algebra and its own calculus,
and the difference is just the way in which relations are denoted. Most
recent work on relational databases refers to the relational algebra nota-
28 Michael J. O'Donnell
tion, which looks even more distant from FOPC than the relational cal-
culus notation, but is still easily translatable into FOPC. See [Date, 1986;
Codd, 1972] for a description of relational algebra notation for database
queries, and a translation to the relational calculus notation.
2.3.4 Programming in equational logic
Another natural logical system in which to program is equational logic.
A large number of programming languages may be viewed essentially as
different restrictions of programming in equational logic.
Definition 2.3.13. Let the set V of variables, the sets Fun0, Funi,... of
constant and function symbols, and the set Tp of terms be the same as in
FOPC (see Definition 2.3.1). Let = be a new formal symbol (we add the
dot to distinguish between the formal symbol for equality in our language
and the meaningful equality symbol = used in discussing the language).
The set F = of equational formulae (or simply equations) is
Models for equational logic are the same as models for FOPC, omit-
ting the predicate assignments. Although = behaves like a special binary
predicate symbol, it is given a fixed meaning (as are A, V, ->, =>, 3, V),
so it need not be specified in each model. An equational formula t\ = t-z
holds in a model precisely when t\ denotes the same object as tz for every
variable assignment.
Definition 2.3.14. Let the infinite universe U and the set of function
assignments be the same as in FOPC (Definition 2.3.4). If U C U and r
is a function assignment over U, then {U, T) is a model of equational logic.
M^. is the set of all models of equational logic.
Let the set of variable assignments be the same as in FOPC (Def-
inition 2.3.2), as well as the definition of a term valuation rv from a function
assignment T and variable assignment v (Definition 2.3.3). The classical
semantic system for equational logic is {F_L,M_L, (=_:.), where (U,r) (=.:. t\
= t2 if and only if rv(ti) = Tvfo) for all variable assignments v over U.
Models of equational logic are essentially algebras [Cohn, 1965; Gratzer,
1968; Mac Lane and Birkhoff, 1967] . The only difference is that alge-
bras are restricted to signatures—subsets, usually finite, of the set of con-
stant and function symbols. Such restriction does not affect any of the
properties discussed in this chapter. If T is a finite subset of Tj., then
the set of algebras Models(T) (restricted, of course, to an appropriate
signature) is called a variety. For example, the monoids are the models
of {m(x,m(y,z)) = m(m(x,y),z), m(x,e) = x, m(e,x) == e} restricted to
the signature with one constant symbol e and one binary function symbol
m.
Introduction 29
Perhaps the simplest sort of question that is naturally answered by an
equation is 'what is io?' for a term to- For each term t\, the equation to = ti
is an answer to this question. The trouble with such a primitive question
is that it admits too many answers. For example, the tautology to = to is
always a correct answer to 'what is to?'- This problem is closely analogous
to the problem of the tautological answer (a =>• a) to the question imp(a)
('what atomic formula does a imply?', Example 2.2.3, Section 2.2). For
the shallow implicational calculus, we avoided undesired answers simply
by listing a set A of them, in the form rest-imp(a, A) ('what atomic
formula not in A does a imply?', Example 2.2.4). Since the number of
terms t1 making to = ti true is generally infinite, we need a finite notation
for describing the prohibited answers. A particularly useful way is to give a
finite set of terms with variables, and prohibit all instances of those terms
from appearing as subterms in an answer term.
Definition 2.3.15. Let x 1 , . . . , X i be a list of variables with no repeti-
tions, and let t,ti,...,ti € Tp. t[ti,. ..,ti/xi,... , #i] is the formula that
results from substituting the term tj for every occurrence of the variable
Xj in the term t, for each j, 1 < j <i. When s — t[ti,..., ti/xi,..., n], we
say that s is an instance of t, and that t is more general than s.
The concepts of substitution, instance, and generality for terms are
analogous to the corresponding concepts defined for formulae in Defini-
tion 2.3.5, simplified because all occurrences of variables in terms are
free.
Definition 2.3.16. Let t\,...,ti € Tp be terms. A term s is a normal
form for {t\,..., t^} if and only if no subterm of s is an instance of a term
in {ti,...,ti}.
Let norm be a new formal symbol. Let
Q= = {(norm t l t . . . , tt : t) : t,«lf..., tt £ TP}
Define the relation 7-^C Q^ x F^ by
(normii,..., ti : t) !-± (s\ = $2)
if and only if si = t and S2 is a normal form for {*i,..., ti}.
Now (Fj., Qj., ?-.i) is a query system representing the answers to ques-
tions of the form 'what normal form for t 1 ,...,t i is equal to t?'
For every semicomputable set T C F.^, the set of equations (t = s) such
that (norm ti,..., ti : t) 7-^ T (=_:. (t = s) is semicomputable. It is easy to
define a query system with conjunctive equational answers, similar to the
conjunctive FOPC answers of Definition 2.3.10. Such a step is most useful
when infinite conjunctions are allowed, so it is reserved for Section 7.1 of the
30 Michael J. O'Donnell
chapter 'Equational Logic Programming.'
Example 2.3.17. Let a € Funo be a constant symbol representing zero,
let s 6 Funx be a unary function symbol representing the successor func-
tion, and let p E Fun2 be a binary function symbol representing addition.
A natural state of knowledge about these symbols is
T =-{p(a,x) = x, p(s(x),y) = s(p(x,y))}
A natural question is (normp(x, y) :p(s(s(a)),s(s(s(a))))). The unique
correct answer is (p(s(s(a)),s(s(s(a)))) = s(s(s(s(s(a)))))). That is, the
answer to the question 'what is a term for 2 plus 3, not using the plus
operator?' is '2 plus 3 equals 5.'
Another question, peculiar but formally legitimate, is (norms(s(o:)),
s(p(x,y)) : s(s(a))). Correct answers include (s(s(a)) = p(s(o),s(o))),
(s(s(a)) = p(s(a),p(s(a),a))), (s(s(a)) = p(p(s(a),a),s(a))), etc. The an-
swers to this question express 2 as sums of 1 and 0. The simplest form is
1 plus 1; all other forms simply add extraneous 0s.
Every partial computable function o may be defined similarly by letting
o(i) be the unique j such that
(norm «!,...,* : /(**(o))) ?- T ^ (/(«>)) = sj(a))
for appropriately chosen 11,..., ti and finite set T of equations defining
/. In principle, we might ask for most general or consequentially strongest
answers to questions in Q^. In practice, multiple answers to such questions
are usually incomparable.
A more powerful form of equational question answering involves the
solution of equations.
Definition 2.3.18. Let solve be a new formal symbol. Let
Qs= = {(solvexi,...,au :t1 = *a) :«i,*2 € TP}
Define the relation t~s± by
(solve xi,..., Xi : ti = t?) "hs± (sj = s2)
if and only if there are terms u i , . . . , u< 6 Tp such that si = 11 [HI ,..., Ui/
X i , . . . , X i ] and s 2 = t2[u1:... ,«i/£i,... ,0^].
Now (Qs=, F^, ?-«=) is a query system representing the answer to ques-
tions of the form 'what values of x\,..., Xi solve the equation t\ = t^T
Notice the close analogy between the question (solve x\,...,Xi :t1 =t 2 )
above, and the FOPC question (what n,..., Xi : F) of Definition 2.3.6,
Section 2.3.1. Syntactically, the equational question is merely the spe-
cial case of the FOPC question where the formula F is restricted to be an
Introduction 31
equation. The semantics of equational logic lead, however, to very different
typical uses for, and implementations of, equation solving.
2.3.5 Functional and equational programming languages
A wide variety of nonprocedural programming languages have been inspired
by Backus' proposal of functional programming languages [Backus, 1974;
Backus, 1978] defined by equations. The previous development of Lisp by
McCarthy [McCarthy, 1960], although not originally conceived in terms of
functional programming, fits in retrospect into the functional approach,
and its success has boosted the interest in functional languages substan-
tially. Languages for the algebraic description of abstract data types [Gut-
tag and Horning, 1978; Wand, 1976; Futatsugi et al., 1985] use equations
in individual programs, rather than in the language design, and one exper-
imental language is defined explicitly in terms of equational logic program-
ming [Hoffmann and O'Donnell, 1982; Hoffmann et al., 1985; O'Donnell,
1985]. The essential idea behind functional, algebraic, and equational, pro-
gramming languages is to find correct answers to normalization questions
in Q= of Section 2.3.4 above. A number of different styles are used to
specify these languages, often obscuring the logic programming content.
In this section, 'functional programming languages' include all program-
ming languages that can be described naturally as answering normalization
questions, and we view them as a form of equational logic programming,
whether or not they are conventionally thought of in that way. Actual
functional languages differ widely on a number of dimensions:
• the notation in which terms are written;
• the way in which the knowledge formulae are determined by the lan-
guage design and the program;
• the way in which questions are determined by the language design,
the program, and the input;
• deviations from pure equational logic programming.
Because of the complexity of these variations, the discussion in this section
is organized around the various decisions involved in designing a functional
programming language, rather than around a survey of the most important
languages.
The style in which many functional programming languages are spec-
ified creates an impression that there are fundamental logical differences
between functional programming and equational logic programming. This
impression is false—functional programming and equational logic program-
ming are two different ways of describing the same behaviors. The different
styles of description may encourage different choices in language design, but
they do not introduce any fundamental logical deviations. In particular,
'higher order' functional programming languages are not higher order in
any fundamental logical sense, and may be described very naturally by
32 Michael J. O'Donnell
first-order equational logic [Goguen, 1990]. The chapter 'Equational Logic
Programming,' Section 1.2, provides more discussion of the connection be-
tween functional and equational programming ideologies.
Determining equational knowledge from language design and program. The
equational formulae used as explicit knowledge for answering normaliza-
tion questions in functional programming languages are derived from the
language design itself and from the program that is being executed. In
principle, they could also be given in the input, but this possibility has
not been exploited explicitly. Many functional languages are processed by
interactive interpreters, which blur the distinction between program and
input, and many functional languages have mechanisms, such as lambda
abstraction [McCarthy, 1960] or the let construct, that simulate the intro-
duction of certain equations within an input term. Interactive interpretive
processing, and the simulation of additional equations within terms, pro-
vide implicitly a lot of the power of explicit equations in the input.
Most functional languages are designed around substantial sets of prim-
itive operations, defined by equations. For example, the primitives cons
(construct ordered pair), car (first component of pair), and cdr (second
component of pair) in Lisp are defined by the two equations (car(cons(x, y))
= x) and (cdr (cons(x,y)) = y) [McCarthy, 1960]. Primitive operators that
manipulate term structure, or provide program control structures, are usu-
ally defined by explicitly given small finite sets of equations. Primitive
operators for basic mathematical operations are defined by large or infinite
sets of equations that must be described rather than listed. For exam-
ple, the conventional arithmetic operation of addition is defined by the
equations add(0,0) = 0, add(Q, 1) = 1,..., add (1,0) = 1, add (1,1) = 2,...,
add(2,0) = 2, add(2,1) = 3, add(2,2) = 4,....
Most functional programming languages have rich enough primitive sets
of operators defined by equations in the language design that it is not nec-
essary to introduce new equations in a program—the goals of the program
may be accomplished by appropriate combinations of primitive operations.
In particular, many functional languages have operators that simulate the
introduction of additional local equations within a term. Even in lan-
guages with powerful primitives, it is often convenient to introduce explicit
equations defining new operators in a given program. A few functional
languages have weak primitives, and depend upon equations in programs
for their expressive power.
Most functional languages impose restrictions on the equations that
may be introduced by programs, in order to allow simple and efficient
proof searches in the implementation. Typical restrictions are surveyed
in the chapter 'Equational Logic Programming,' Section 2.3.2. In most
languages, the restrictions on equations in programs allow each equation
f ( t 1 , . . . , ti) = t in a program to be treated as a part of the definition of a
Introduction 33
procedure to compute /. Note the similarity to the treatment of clauses in
Prolog programs (Section 2.3.2).
Determining a question from language design, program, and input. Re-
call that the form of a normalization question is (norm t1 , . . . , ti : t) . An
answer to such a question gives a term equal to t that does not contain
a subterm of any of the forms t1, . . . , ti. The determination of a question
divides naturally into the determination of the prohibited forms t1 , . . . ,
ti and the term t to normalize.
In most functional programming languages, the prohibited forms t 1 , . . . ,
ti are determined by partitioning the set of symbols into constructors, prim-
itive functions, and defined functions. Constructors are intended to be com-
putationally inert—they are treated as elements of a data structure. The
use of constructors in equations is highly restricted to ensure this inertness.
The binary symbol cons in Lisp is the archetypal constructor. In languages
that distinguish constructors, the prohibited forms in normalization ques-
tions are precisely the terms f(x 1 , . . . , x i ) , where / is a primitive function
or a defined function of arity i. That is, the normal forms for questions in
constructor systems are precisely the constructor expressions—terms com-
posed entirely of variables and constructors. The set of constructors may
be fixed by the language design, or a program may be allowed to introduce
new constructors, in explicit declarations of the symbols or in recursive
type definitions.
In a functional language without constructors, the prohibited forms
may be implicit in the equations of a program. Most functional languages
infer from the presentation of the equation t1 = t2 that the left-hand side
t1 is to be transformed into the right-hand side t2. Such an inference is
not justified directly by the semantics of equational logic, but it is often
justified by restrictions on the form of equations imposed by the language.
So, the prohibited forms in questions are often taken to be precisely the
terms on the left-hand sides of equations in the program.
The term to be normalized is typically in the form
where tla is fixed by the language design, tp, . . . ,tp are determined by
the program, and tin, . . . ,tin are determined by the input. In principle,
other forms are possible, but it seems most natural to view the language
design as providing an operation to be applied to the program, producing
an operation to be applied to the input. For example, in a pure Lisp
eval interpreter, tla = eval(x 1 , nil). The program to be evaluated is tpr
(the second argument nil to the eval function indicates an empty list of
definitions under which to evaluate the program). Pure Lisp has no input—
conceptual input may be encoded into the program, or extralogical features
34 Michael J. O'Donnell
may be used to accomplish input. A natural extension of pure Lisp to
allow definitions of symbols in a program yields tla = eval(x 1 , x 2 ), tpr is
the expression given by the program to be interpreted, and tpr is a list of
bindings representing the definitions given in the program. In a language,
unlike Lisp, where a program designates a particular defined function /
as the main procedure to be executed on the input, we can have tla = x1
(the language design does not contribute to the term to be normalized),
tpr = f ( y 1 ) where f is the designated main function, and tin is the input.
In yet other languages, the term to be normalized is given entirely by the
input.
Notational variations and abbreviations. Functional programming lang-
uages vary widely in the notations used for terms, using all sorts of prefix,
infix, postfix, and mixfix forms. A survey of the possibilities is pointless. All
current functional languages determine the prohibited forms in questions
implicitly, either from the language design or from the left-hand sides of
equations in a program. Questions are presented by specifying some or all
of the term to be normalized—other parts of the term may be implicit as
described above. Outputs always present only the normal form s rather
than the equation t = s, since the question term t is already given explicitly
or implicitly.
Deviations from pure equational logic programming. Implementations of
functional programming languages have generally come closer to the ideal
of pure equational logic programming than Prolog systems have to pure
Horn-clause logic programming, largely because of a simpler correspon-
dence between logical and procedural concepts in functional languages than
in Prolog. Many functional languages extend pure logic programming with
side-effect-producing operations, similar to those in Prolog. These exten-
sions are usually used to deal with input and output. Some functional
languages avoid such extensions by modelling the entire input and output
as an expression, called a stream, that lists the atomic elements of the in-
put and output [Karlsson, 1981; Thompson, 1990; Hudak and Sundaresh,
1988; Hudak, 1992; Gordon, 1992; Dwelly, 1988]; others use a functional
representation of input and output based on continuations [Perry, 1991;
Hudak and Sundaresh, 1988; Hudak, 1992]. Also see [Williams and Wim-
mers, 1988] for an implicit approach to functional I/O. A protocol that
decouples the temporal order of input and output from its representa-
tion in a functional program has been proposed as well [Rebelsky, 1993;
Rebelsky, 1992] .
The purely functional subsets of functional programming languages usu-
ally avoid giving incorrect answers. Implementations of Lisp before the
1980s are arguably incorrect in that their use of dynamic scope [Stark, 1990;
Moses, 1970] for parameter bindings gives answers that are incorrect ac-
cording to the conventional logical equations for substitution of terms for
Introduction 35
parameters, taken from the lambda calculus [Church, 1941; Stenlund, 1972;
Barendregt, 1984] . Since the equations for manipulating bindings were
never formalized precisely in the early days of Lisp, implementors may ar-
gue that their work is correct with respect to an unconventional definition
of substitution. Early Lispers seem to have been unaware of the logical
literature on variable substitution, and referred to the dynamic binding
problem as the 'funarg' problem.
Essentially all functional programming languages before the 1980s fail
to find certain semantically correct answers, due to infinite evaluation of
irrelevant portions of a term. In conventional Lisp implementations, for
example, the defining equation car (cons (x, y)) = x is not applied to a term
cor(cons(t1, t 2 )) until both t1 and £2 have been converted to normal forms.
If the attempt to normalize t2 fails due to infinite computation, then the
computation as a whole fails, even though a semantically correct answer
might have been derived using only t1. Systems that fail to find a normal
form for car(cons(t 1 , t2)) unless both of t1 and t2 have normal forms are said
to have strict cons functions. The discovery of lazy evaluation [Friedman
and Wise, 1976; Henderson and Morris, 1976; O'Donnell, 1977] showed
how to avoid imposing unnecessary strictness on cons and other functions,
and many recent implementations of functional programming languages are
guaranteed to find all semantically correct answers. Of course, it is always
possible to modify defining equations so that the strict interpretation of a
function is semantically complete.
Example 2.3.19. Consider Lisp, with the standard equations
car(cons(x, y)) = x and cdr(cons(x, y)) = y
To enforce strict evaluation of lists, even in a lazily evaluated implemen-
tation of equational logic programming, add new function symbols test,
strict, and, and a new constant true, with the equations
test(true, x) = x, and(true, true) = true,
strict(cons(x, y)) = and (strict (x), strict (y)), strict(a) = true
for each atomic symbol a. Then, redefine car and cdr by
car (cons (x, y)) = test(strict(y), x) and cdr (cons (x, y)) = test(strict(x), y)
Lazy evaluation with the new set of equations has the same effect as strict
evaluation with the old set.
Some definitions of functional programming language specify strictness
explicitly. One might argue that the strict version of cons was intended in
the original definition of Lisp [McCarthy, 1960], but strictness was never
stated explicitly there.
36 Michael J. O'Donnell
2.3.6 Equation solving and predicate calculus with equality
Given successful applications of logic programming in the pure first-order
predicate calculus without equality, and in pure equational logic, it is
very tempting to develop languages for logic programming in the first-
order predicate calculus with equality (FOPC=). Unfortunately, there
is a mismatch between the style of questions used in the two sorts of
logic programming. FOPC logic programming uses questions of the form
(what x 1 ,. . . , X2 : F) (Definition 2.3.6), whose answers supply substitu-
tions for the variables x1, . . . , xi satisfying F. Equational logic program-
ming uses questions of the form (norm t1, . . . ,ti : t) (Definition 2.3.16),
whose answers supply normal forms equal to t, not containing the forms
t1, . . .,ti- The implementation techniques for answering these two sorts of
questions do not appear to combine well.
The most natural idea for achieving logic programming in FOPC= is
to use the FOPC style of question, and extend it to deal with equations.
In principle that is feasible, because the formal equality symbol = may be
treated as another binary predicate symbol in Precb, and Horn clauses ex-
pressing its crucial properties are easy to find. Unfortunately, the natural
Horn clauses for the equality predicate, when treated by current imple-
mentation techniques for FOPC logic programming, yield unacceptably
inefficient results. In practice, a satisfactory realization of logic program-
ming in FOPC= will require new techniques for solving equations—that
is, for answering questions of the form (solve x 1 , . . . , xi : t1 = t2) (Defini-
tion 2.3.18). An interesting experimental language incorporating signifi-
cant steps toward logic programming in FOPC= is EqL [Jayaraman, 1985],
but this language only finds solutions consisting of constructor expressions.
The problem of finding nonconstructor solutions is much more difficult.
It is also possible to define FOPC logic programming in terms of a
normalization-style query. Consider a question 'what acceptable formula
implies FO', which presents a goal formula F0, and some description of
which answer formulae are acceptable and which are prohibited (the prob-
lem of describing such prohibited formulae is more complex in FOPC than
in equational logic because of the structural properties of the logical con-
nectives ^, V, . . . ). An answer to such a question is an implication of the
form F1 => FO , where F1 is an acceptable formula. The conventional FOPC
questions (what x 1 , . . . , xi : F0) may be understood as a variant of the
'what implies FO' questions, where the acceptable formulae are precisely
those of the form x1 = t1 ^ . . . ^ xi = t2. The proposed new style of FOPC
question may be seen as presenting a set of constraints expressed by FO,
and requesting a normalized expression of constraints F1 such that every
solution to the constraints expressed by F1 is also a solution to the con-
straints of F0. Constraint Logic Programming [Jaffar and Lassez, 1987;
Lassez, 1991] has taken some steps in this direction, although Constraint
Introduction 37
Logic Programming generally views the normalized constraints expressed
by F1 not as a final result to be output as an answer, but as something to
be solved by techniques outside of FOPC, such as numerical techniques for
solving linear systems of equations.
3 Implementing logic programming languages
Semantic systems and query systems are convenient tools for specifying
logic programming languages: we require a language to provide semanti-
cally correct answers to questions. In order to implement logic program-
ming languages, we first develop sound (correct) and complete (powerful)
proof systems to provide effective certificates of the semantic correctness of
inferences. Then, we convert proof systems to programming systems that
process inputs and programs efficiently to produce outputs, by introduc-
ing strategies for choosing incrementally which proofs to construct. In this
chapter we consider only the abstract forms of implementations, far above
the level of actual code for real machines. Truly practical implementations
do, however, follow these abstract forms quite closely.
3.1 Proof systems and provable consequences
A semantic-consequence relation determines in principle whether it is cor-
rect to infer one logical formula from others. In order to give a formal
justification for an inference, we need a notation for proofs. We reserve the
initial P for programs, so D is used to stand for proofs, which might also
be called demonstrations or derivations.
Definition 3.1.1. A proof system is a system D = {F,D, I -), where
1. F is a set of formulae
2. D is a set of proofs
3. I - is a relation on 2F x D x F (when (T, D, F) are in the relation
I -, we write T I D - F)
4. I - is monotone (if T I D - F and T C U, then U | D - F)
The proof system D is compact if and only if, for all T C F, P 6 D,
and F £ F, whenever T I D - F there exists a finite subset Tf C T such
that Tf I D - F.
T I D - F is intended to mean that D is a proof of F which is allowed
to use hypotheses in T. The fact that D is not required to use all hypothe-
ses leads to monotonicity (4). There are a number of proposals for systems
of 'nonmonotonic logic,' but they may be regarded as studies of different
relations between proofs and formulae than the notion of derivability rep-
resented by I - above, rather than as arguments about the properties of I -.
The controversy about nonmonotonic logic is not relevant to the discussion
in this chapter, and fans of nonmonotonic relations between proofs and
formulae may translate into their own notation if they like.
38 Michael J. O'Donnell
In well-known proof systems, proofs as well as formulae are finite syntac-
tic objects, and the set D of all proofs is computable. There are important
uses, however, for infinite proofs of infinite formulae, so we do not add
a formal requirement of computability. Typically, a proof D determines
uniquely the conclusion formula F and minimum hypothesis set T such
that T I D - F, but there is no need to require such a property. Meseguer
[Meseguer, 1989] proposed a similar general notion of proof calculus.
It is straightforward to design a proof system for SIC. The following
proof system follows the conventional style of textbooks in logic. Proofs
are sequences of formulae, each one either a hypothesis, a postulate, or a
consequence of earlier formulae in the proof.
Example 3.1.2. Let FSh be the set of formulae in SIC. The set of linear
proofs in SIC is PSl = F+sh, the set of nonempty finite sequences of formulae.
The proof relation I -51 is defined by
T I (Fo,..., Fm) -si F if and only if Fm = F and,
for alii < m, one of the following cases holds:
1. F; € T
2. Fi = (a =>• a) for some atomic formula a € At
3. Ft = 6, and there exist j, k < i such that Fj = a and Fk = (a => b)
for some atomic formulae a, 6 e At
4. FJ = (a => c), and there exist j, k < i such that F, = (a => b) and
Ft = (b => c) for some atomic formulae a,b,c£ At
Now (Fsh,Ps1 | - si) is a compact proof system, representing the Hilbert,
or linear, style of proof for implications.
Intuitively, a linear or Hilbert-style proof is a finite sequence of formu-
lae, each one being either a hypothesis (case 1 above), a postulate (case 2
above, expressing the postulate scheme of reflexivity of implication), or
the consequence of previous formulae by a rule of inference (case 3 above,
expressing the rule of modus ponens, and case 4, expressing the rule of
transitivity of implication). The conclusion of a linear proof is the last
formula in the list.
An alternative proof system for SIC, less conventional but more con-
venient for some purposes, follows the natural deduction style of proof
[Prawitz, 1965]. Natural deduction proofs are trees, rather than sequences,
to display the actual logical dependencies of formulae. They also allow the
introduction and discharging of temporary assumptions in proofs, to mimic
the informal style in which we prove a => 6 by assuming a and proving b.
Example 3.1.3. Let FSh be the set of formulae in the shallow implica-
tional calculus defined in Example 2.1.2. Let assume, modus-ponens,
and deduction-rule be new formal symbols.
Introduction 39
The set Psn of natural deduction proofs in SIC and the proof relation
I "SnQ 2 Sh x Psn x FSK are denned by simultaneous inductive definition
to be the least set and relation such that:
1. for each atomic formula a £ At, and each set of formulae T C
assume(a) £ Psn
and
T U {a} I assume(a) -sn a
2. if a, 0 £ Psni and T I a - sn a for some atomic formula a £ At, and
U I ft -Sn (a =*• 6), then
modus-ponens(a, ft) £ Psn and TuU I modus-ponens(a, ft) ~sn b
3. if /? 6 Psn and T U {a} I /3 ~sn b for some atomic formula a € At,
then
deduction-rule (a, /3) € Psn and T I deduction-rule (a, 0) -sn (a => b)
Now {Fsh,Psn | -Sn) is a compact proof system, representing the natural
deduction style of proof for implications.
Intuitively, assume(a) is a trivial proof of a from hypothesis a. rnodus-
ponens (a, 0) is the result of using a proof a of some atomic formula
a, a proof B of an implication (a => b), and combining the results along
with the rule of modus ponens to conclude 6. The set of hypotheses for
the resulting proof includes all hypotheses of a and all hypotheses of ft.
deduction-rule(a,B) is the result of taking a proof ft of b from hypotheses
including a, and discharging some (possibly 0) of the assumptions of a from
the proof, to get a proof of (a => 6) by the deduction rule. In clause 3 of the
inductive definition above, notice that the hypothesis set T may contain
a, in which case T U {a} = T. It is this case that allows for the possibility
that one or more assumptions of a remain undischarged in an application
of the deduction rule.
The style of proof formalized in Example 3.1.3 is called natural deduc-
tion, since it mimics one popular informal style of proof in which an implica-
tion is proved by assuming its hypothesis and deriving its conclusion. Nat-
ural deduction style [Prawitz, 1965], and the similar style of sequent deriva-
tion [Gentzen, 1935; Kleene, 1952], both due to Gentzen, are the styles of
proof most commonly treated by research in proof theory [Stenlund, 1972;
Prawitz, 1965; Takeuti, 1975; Schutte, 1977; Girard et al., 1989]. In proof
theory, natural deduction rules are expressed very naturally as terms in a
typed lambda calculus, where the type of a lambda term is the formula
that it proves [Howard, 1980; Tait, 1967].
40 Michael J. O'Donnell
In many cases, we are interested only in the provability of an inference,
and not the proof itself. So, we let each proof system define a provable-
consequence relation, analogous to the semantic-consequence relation asso-
ciated with a semantic system.
Definition 3.1.4. Let D = (F,D, I -) be a proof system. The provable-
consequence relation defined by D is HC 2F x F, where
T I- F if and only if there exists a proof D € D such that T I D - F.
The provable-consequence relation h is compact if and only if, for all
T C F, and F e F, whenever T |- F then there exists a finite subset Tf C T
such that Tf |- F.
Intuitively, T |- F means that F is provable from hypotheses in T. It
is easy to show that an arbitrary relation |- on 2F x F is the provable-
consequence relation of some proof system if and only if it is monotone
(T |- F and T C U imply that U |- F). See [Meseguer, 1989] for another
abstract definition of provable consequence relations, with more stringent
requirements.
Most well-known semantic/provable-consequence relations are compact,
and semicomputable on the finite sets of formulae. The trinary proof rela-
tions of proof systems (restricted to finite sets of hypotheses) are normally
computable. That is, in a reasonable proof system we can determine defi-
nitely and mechanically whether or not a supposed proof is in fact a proof of
a given conclusion from a given finite set of hypotheses. It is easy to see that
a proof system with semicomputable set D of proofs and semicomputable
trinary proof relation I - also has a semicomputable provable-consequence
relation, and that compactness of the proof system implies compactness of
the provable-consequence relation. In fact, every semicomputable provable-
consequence relation is defined by some proof system with computable D
and trinary proof relation |- . In this respect the trinary proof relation acts
as a Godel T-predicate [Kleene, 1952] to the binary provable consequence
relation.
3.2 Soundness and completeness of proof systems
The behavior of a proof system may be evaluated in a natural way with re-
spect to a semantic system with the same or larger set of formulae. We say
that the proof system is sound for the semantic system when every prov-
able consequence is a semantic consequence, and that the proof system is
complete when every semantic consequence is provable. Roughly, sound-
ness means correctness, and completeness means maximal power within the
constraints imposed by the set of formulae available in the proof system.
Definition 3.2.1. Let D = (FD,D, I -) be a proof system, and let S =
Introduction 41
(Fs,M, |=> be a semantic system, with FD C FS-
D is sound for S if and only if, for all T C F and F e FD,
T |- F implies T |= F
D is complete for 5 if and only if, for all T C F and F £ FD,
T |= F implies T |- F
Each of the proposed proof systems for SIC is sound and complete
for the semantic system of SIC. The following proofs of completeness for
SIC are similar in form to completeness proofs in general, but unusu-
ally simple. Given a set of hypotheses T, and a formula F that is not
provable from T, we construct a model M satisfying exactly the set of
provable consequences of T within some sublanguage FF containing F
(Theory(M) n FF 3 Theory(Models(T)) n FF). In our example below,
FF is just the set of all shallow implicational formulae (F Sh ), and the model
construction is particularly simple.
Example 3.2.2. Each of the proof systems (Fsh, PSn, |-Sn) of Exam-
ple 3.1.3 and-(F sh , PSl, |- S1) of Example 3.1.2 is sound and complete for
the semantic system (FSh, Msh, |=sh >of Example 2.1.2.
The proofs of soundness involve elementary inductions on the size of
proofs. For the natural deduction system, the semantic correctness of a
proof follows from the correctness of its components; for the linear system
correctness of a proof (F0,..., F m+1 ) follows from the correctness of the
prefix <F0, . . . , Fm>.
The proofs of completeness require construction, for each set T of for-
mulae, of a model M — {a € At : T |-Sn a} (or T |-si a). So M =Sh a for all
atomic formulae a E T n At trivially. It is easy to show that M |=sh (a => &)
for all implications (a = b) 6 T as well, since either a £ M, or b follows by
modus ponens from a and a => b, so b € M. Finally, it is easy to show that
M =sh F if and only if T |-Sn F (or T |-S1 F).
In richer languages than SIC, containing for example disjunctions or
negations, things may be more complicated. For example, if the disjunction
(A V B) is in the set of hypotheses T, each model satisfying T must satisfy
one of A or B, yet neither may be a logical consequence of T, so one of them
must be omitted from Ff. Similarly, in a language allowing negation, we
often require that every model satisfy either A or - A. Such considerations
complicate the construction of a model substantially.
Notice that the formal definitions above do not restrict the nature of
semantic systems and proof systems significantly. All sorts of nonsensical
formal systems fit the definitions. Rather, the relationships of soundness
and completeness provide us with conceptual tools for evaluating the be-
havior of a proof system, with respect to a semantic system that we have
42 Michael J. O'Donnell
already accepted as appropriate. Logic is distinguished from other tech-
nical sciences, not by the formal definition of the systems that it studies,
but rather by the use of logical concepts to evaluate these systems. The
distinction between logic programming and other forms of programming is
similarly based on the approach to evaluating the systems, rather than the
formal qualities of the systems.
While formal studies may reveal pleasing or disturbing properties of
semantic systems, there is also an unavoidable intuitive component in the
evaluation of a semantic system. A semantic system is reasonable only if
it accurately captures enough of the structure of the mental meaning that
we want to associate with a formula to allow a sensible determination of
the correctness or incorrectness of steps of reasoning. Since different people
have different intuitive notions about the proper meanings of formulae, and
the same person may find different intuitions useful for different purposes,
we should be open minded about considering a broad variety of semantic
systems. But, the mere satisfaction of a given form of definition, whether
the form in Definition 2.1.1 above, or one of the popular 'denotational'
forms using lattices or chain-complete partial orderings and fixpoints, does
not make a 'semantics' meaningful. A number of additional mathemati-
cal and philosophical dissertations are needed to give practical aid in the
evaluation and selection of semantic proposals. The best one-sentence ad-
vice that I can offer is to always ask of a proposed semantic system, 'for
a given formula F, what does the semantic system tell about the informa-
tion regarding the world that is asserted by F.' For this chapter, I use
only systems of semantics based on first-order classical forms of logic that
have been shaken down very thoroughly over the years. In these systems,
the individual models clearly present enough alleged facts about a possible
state of the world to determine the truth or falsehood of each formula. So,
the information asserted by a formula is that the world under discussion
is one of the ones satisfying the formula in the sense of |=. There are
many reasons to prefer nonclassical logics for programming and for other
purposes. But, we must never rest satisfied with 'semantic' treatments of
these logics until they have been connected convincingly to an intuitive
notion of meaning.
A semantic system and a sound proof system may be used to analyze
the process by which implicit knowledge is made explicit—we are particu-
larly interested in the derivation of explicit knowledge in order to answer
a question. Consider an agent with implicit knowledge given by the set
K of models consistent with that knowledge, and represent the agent's ex-
plicit knowledge by a set T of formulae that he can utter effectively. The
correctness of the explicit knowledge requires that T C Theory(K). Sup-
pose that the agent knows that the proof system is sound, and suppose
that he can recognize at least some cases when the relation T I D - F
holds—often this capability results from computing the appropriate deci-
Introduction 43
sion procedure for a computable proof system (or enumeration procedure
for a semicomputable proof system), with an appropriate finite subset of T.
Then, whenever he finds a formula F and a proof D such that T I D - F,
the agent may add the formula F to his explicit knowledge. The soundness
of the proof system guarantees that F E Theory(K). Notice that sound
proofs can never extend explicit knowledge beyond the bound determined
by implicit knowledge, which is Theory(K).
Definition 3.2.3. Let Q = (FQ, Q,?-) be a query system, and let D =
(F D , D, I -) be a proof system with FQ C FD.
Q ?- T I- F means that F E FQ is a provably correct answer to Q E Q
for explicit knowledge T C FS , defined by
Q ?- T |- F if and only if Q ?- F and T |- F
Similarly,
Q ?- T I D - F if and only if Q ?- F and T I D - F
If P is sound, then provable correctness implies semantic correctness
(Definition 2.2.2). If P is complete, then semantic correctness implies prov-
able correctness.
Going back to the communication analysis of previous sections, let Ks
be the speaker's implicit knowledge, let K0 be the auditor's initial im-
plicit knowledge, and let T0 be the auditor's initial explicit knowledge.
When the speaker utters a set of formulae Tu, consistent with her im-
plicit knowledge, the auditor's implicit knowledge improves as before to
K1 = K0 n Models(Tu), and the auditor's explicit knowledge improves to
T1 = T0 U Tu. Let a questioner ask a question Q of the auditor. Without
further communication from the speaker, the auditor may improve his ex-
plicit knowledge by proving new formulae from hypotheses in T1 in order to
answer the question Q. If the auditor's initial explicit knowledge is empty,
then T1 = Tu, so the formulae derivable in this way are exactly the prov-
able consequences of Tu, and the answers that may be found are exactly
the provably correct answers to Q for Tu. If the proof system used by the
auditor is sound, then all such answers are semantically correct; if the proof
system is complete then all semantically correct answers are provable. Now
let the speaker be a programmer who utters a set of formulae constituting
a logic program, let the auditor be a processor, and let the questioner be a
user whose question is given as input to the program. Then, computations
performed by the processor take the form of search for and construction of
proofs deriving the explicit knowledge needed to produce an output answer,
from the explicit knowledge given in the program.
44 Michael J. O'Donnell
3.3 Programming systems
A programming system represents the computational behavior of a proces-
sor. In order to understand logic programming, we consider an arbitrary,
possibly ineffective and nondeterministic, programming system, and then
show how to evaluate its behavior logically with respect to a given semantic
system and query system. We choose an unconventional formal notation
for programming systems in order to expose the close analogy of sets of for-
mulae to programs, questions to inputs, proofs to computations, answers
to outputs.
Definition 3.3.1. A programming system is a system P = (P, I, C, O,
> D, ->}, where
1. P is a set of programs
2. I is a set of inputs
3. C is a set of computations
4. O is a set of outputs
5. > D is a relation on I x P x C (when (I, P, C) are in the relation> D,
we write I> P D C)
6. For each I E I and P e P, there is at least one C € C with I> P D C
7. ->• is a relation on C x O
8. For each C 6 C, there is at most one O e O with C ->• O (that is, ->
is a partial function from C to O)
We define the relation > D -»C I x P x C x O by
I> P D C is intended to mean that, when input / is presented to pro-
gram P, one possible resulting computation is C. C —> O is intended to
mean that the computation C produces output O. Multiple computa-
tions for a given P and I are allowed, indicating nondeterminism, but each
computation produces at most one output. The intended meaning of a
nondeterministic computation relation is that we do not know which of
the several possible computations will occur for a given input and output
[Dijkstra, 1976]. The choice may be determined by unknown and time-
dependent factors, or it may be random. In order to guarantee some
property of the result of computation, we must ensure that it holds for
all possible nondeterministic choices.
In well-known programming systems from theory textbooks, programs,
inputs, and outputs (like formulae, proofs, and questions) are finite syntac-
tic objects, and the sets P, I, and O are computable. Infinite computations,
in the form of infinite sequences of finite memory-state descriptions, are al-
lowed, but in theory textbooks the infinite computations normally have
Introduction 45
no output. On the other hand, the straightforward abstractions of well-
known programming systems from real life (abstracted only by ignoring
all bounds on time and space resources in the computation) allow infinite
computations to consume infinite inputs and produce infinite outputs.
In many cases, we are interested only in the input-output behavior of
a program, and not in the computations themselves. So, we let each pro-
gramming system define a trinary relation determining the possible outputs
for a given program and input.
Definition 3.3.2. Let P = {P, I, C, O,> D, -») be a programming system.
The computed-output relation defined by P is> D->C P x I x O, where
I> PD->O if and only if there exists a computation C € C
such that I> P D C -> O.
For a programming system to be useful, the computed-output relation >
(D-> must be sufficiently effective to allow a mechanical implementation.
Computed-output relations in theory textbooks, like provable-consequence
relations, are normally semicomputable; computation and output relations
> D and ->, like trinary proof relations I -, are normally computable (and
even primitive recursive). If C, > D, and -> are all semicomputable, then
so is> (D->. In fact, every semicomputable computed-output relation >
inputs and/or infinite outputs require more liberal, and less conventional,
notions of effectiveness.
The programming systems of Definition 3.3.1 are not required to be de-
terministic, or effective. They are a simple generalization of the program-
ming systems, also called indexings and Godel numberings, of recursion
theory [Machtey and Young, 1978; Kleene, 1952]. Our I> P D-> O corre-
sponds to the recursion-theoretic notation o p ( I ) = O. Recursion theory
normally considers only determinate programming systems.
Definition 3.3.3. A programming system P = {P, I, C, O,> 0,->) is de-
terminate if and only if, for each program P and input /, there is at most
one output O such that I> PD->O. That is, > (H is a partial function
from P x I to O.
A programming system P = (P, I, C, O,> D, —>) is deterministic if and
only if, for each program P and input /, there is a unique computation C
such that I> P D C. That is, > 0 is a partial function from P x I to C.
Determinism implies determinacy, but not the converse—a nondeter-
ministic programming system may provide many computations that yield
the same determinate output.
A number of different programming systems may be defined to answer
questions in the shallow implicational calculus, depending on the type of
question and the stringency of requirements for the answer.
46 Michael J. O'Donnell
Example 3.3.4. Let F=> = {(a => b) : a, b € At} be the set of implica-
tional SIC formulae (F$h — At, with FSh and At defined in Example 2.1.2).
The set of implicational logic programs (P=>) is the set of finite subsets of
Let the set of inputs to implicational logic programs be QS1—the set of
questions of the form imp(a) ('what atomic formula does a imply?') de-
fined in Example 2.2.3.
The set of naive implicational computations (Cs1) is the set of nonempty
finite and infinite sequences of atomic formulae.
The computation relation > DS1 is defined by imp(a) > T DS1 (c0,
c1 , . . .) if and only if
1. CQ = a
2. (ci-1 => Ci) £ T for all i > 0 in the (finite or infinite) range of the
sequence (C0,.. .)
The output relation -»s1 is defined by
Infinite computations have no output.
Now (P=>, QS1, Cs1,F=>,>DSI, ->s1) is a programming system, computing
answers to questions of the form 'what atomic formula does a imply?'
The programming system above behaves nondeterministically and in-
determinately in proving some implication of a. Its computations may halt
at any point and output the latest atomic conclusion found. Loops in the
graph of implications lead to infinite computations with no output. Notice
that each finite computation (C0, . . .ci, . . . ,c m ), with output (c0 => cm),
translates very easily into the linear proof
of (C0 =>• Cm) in the proof system of Example 3.1.2. The first line is an
instance of the reflexive rule, and subsequent lines alternate between im-
plications in T, and applications of transitivity.
In order to avoid uninformative outputs, such as (a => a), we need a
programming system with a slightly more sophisticated notion of when to
stop a computation.
Example 3.3.5. Let fail be a new formal symbol, and let the set of naive
implicational computations with failure be
(the set of finite and infinite sequences of atomic formulae, possibly ending
in the special object fail).
Introduction 47
Let the set of inputs to implicational logic programs be QS2—the set of
questions of the form rest-imp(a, A) ('what atomic formula not in A does
a imply?').
The computation relation > DS2 is defined by rest-imp(a, A)> T Ds2 (C0,
. . .) if and only if
1. c0 = a
2. if Ci e A, and there is a d € At such that (c; => d) £ T, then the
sequence has an i + 1st element ci+1, and (a => Ci+1) e T
3. if Ci e A, and there is no d € At such that (ci => d) e T, then the
sequence has an i + 1st element, and Ci+1 = fail
4. if ci € At — A, then either there is no i+lst element, or (ci => Ci+1) € T
5. if Ci — fail, then there is no i + 1st element
So, > Qs2 allows computations to terminate only when an atomic formula
outside of A has been found, or a dead end in the implication graph has
been reached.
The output relation ->S2 is defined by
Infinite computations and finite computations ending in fail have no out-
put.
Now (P=>, QS2, Cs2, F=>,> Ds2, ->S2) is a programming system, computing
answers to questions of the form 'what atomic formula not in A does a
imply?'
The programming system of Example 3.3.5 is nondeterministic and in-
determinate. It avoids useless answers, but it still may fall into infinite or
finite failing computations, even when a legitimate answer exists. It also
may find an answer, but fail to output it and proceed instead into a failure
or an infinite computation. Successful computations translate into proofs
as in Example 3.3.4.
We may further strengthen the behavior of a programming system by
letting it back up and try new proofs after finite failures, and by insisting
that answers be output as soon as they are found.
Example 3.3.6. Let the set of inputs to implicational logic programs
again be QS2—the set of questions of the form rest-imp (a, A) ('what
atomic formula not in A does a imply?').
Let print be a new formal symbol. The set of backtracking implicational
computations (Cs3) is the set of nonempty finite and infinite sequences of
finite sets of atomic formulae, possibly ending in the special form print (a)
where a is an atomic formula (fail of Example 3.3.5 is represented now by
the empty set).
The computation relation > Ds3 is defined by rest-imp(a, A)> T DS3 (C0,
. . .) if and only if
48 Michael J. O'Donnell
1. C0 = {a}
2. if Ci C A and Ci = 0, then there is an i + 1st element, and
for some atomic formula c € Ci
3. if Ci C At, and Ci — A = 0, then there is an i + 1st element, and
Ci+1= print (c) for some c £ Ci - A
4. if Ci = 0, or Ci = print (c), then there is no i + 1st element
So, > DS3 allows a computation to replace any atomic formula that has
already been proved with the set of atomic formulae that it implies directly
in T. A computation halts precisely when it chooses a unique atomic
formula not in A to output, or when it fails by producing the empty set.
The output relation -»s3 is defined by
Infinite computations, and finite computations ending in 0, have no output.
Now (P=>, Qs2, Cs3, F=>,> DS3, ->s3) is another programming system, com-
puting answers to questions of the form 'what atomic formula not in A does
a imply?'
The programming system of Example 3.3.6 is nondeterministic and in-
determinate. It is less susceptible to missing answers than that of Exam-
ple 3.3.5. The new system does not get stuck with a failure when a single
path in the implication graph leads to a dead end: a computation ends in
0 only when all paths have been followed to a dead end. When there is a
finite path to an answer, and also a cycle, the nondeterministic choice of
which formula to replace at each step determines which path is followed in
the computation, and so determines success or infinite computation. The
translation of a computation in the latest system to a proof is not quite
as transparent as in Examples 3.3.4 and 3.3.5, but it is still simple. Each
successful computation ({C0}, C1, . . ., C m _1, print(c m )) must contain a se-
quence of atomic formulae (C0 , c1, . . . , cm _ 1, cm), where for i < m ci 6 ,
and for adjacent pairs Ci,Ci+1, either ci = Cj+1, or (ci => ci+1) 6 T. This
sequence of atomic formulae transforms to a linear proof as before.
A final example of a programming system illustrates the use of incre-
mental output from possibly infinite computations to produce consequen-
tially strong answers.
Example 3.3.7. Let the set of inputs to implicational logic programs be
QSc—the set of questions of the form conj-imp(a) ('what are some atomic
formulae that a implies?') from Example 2.2.6.
The set of conjunctive implicational computations (Cs4) is the set of non-
empty finite or infinite sequences of finite sets of atomic formulae (the same
Introduction 49
as Cs3, without the final elements print (a)).
The computation relation> Ds4 is defined by conj-imp(a)> T Ds4 (C0,...)
if and only if
1. C0 = {a}
2. if Ci = 0, then there is an i + 1st element, and
for some atomic formula c € Ci
3. if Ci = 0, then there is no i + 1st element
The computations above are the same as those of Example 3.3.6, except
that we never choose a single atomic formula to output. 0 is no longer
regarded as a failure.
The output relation -»S4 is defined by (Co,...) ->S4 (a => b1) A ... A
(a => bm) if and only if
1. C0 = {a}
2. {b1,...b m } = C0 U Ci U . . . , and b1,...b m are given in the order of
first appearance in the sequence Co,..., with ties broken by some
arbitrary ordering of atomic formulae
Notice that even infinite computations have output.
Now (P => ,Q Sc , Cs4, F=>,> Ds4,->S4) is a programming system, computing
answers to questions of the form 'what are some atomic formulae that a
implies?'
The programming system above should be thought of as producing its
output incrementally at each computation step. It is nondeterministic and
indeterminate. Even though the computation may be infinite, it never
fails to produce an answer, although the output may be the trivial formula
a => a. The strength of the answer produced depends on the nondetermin-
istic choices of the atomic formula replaced in each computation step.
3.4 Soundness and completeness of programming sys-
tems
A query system determining what constitutes an answer, and the semantic-
consequence relation of a semantic system determining the correctness of
an answer, yield criteria for evaluating the behavior of a programming
system, similar to the criteria for evaluating a proof system in Section 3.1.
We define soundness and completeness of programming systems, in analogy
to the soundness and completeness of proof systems. Logic programming
is distinguished from other sorts of programming by the use of such logical
concepts to evaluate programming systems.
There is only one sensible concept of soundness for a programming
system: every output is a correct answer to the input program. When
50 Michael J. O'Donnell
a given question has more than one correct answer, completeness criteria
vary depending on the way in which we expect an output answer to be
chosen.
Definition 3.4.1. Let P = <P, I, C, O,> D, ->) be a programming system,
let S = (F S ,M, |=) be a semantic system, and let Q = (F Q ,Q,?-) be a
query system, with P C 2Fs, I C Q, and O C Fs n FQ.
P is sound for S and Q if and only if, for all P e P and I € I,
I> P H- O implies I ?- P |= O
P is weakly complete for S and Q if and only if, for all P e P and 7 € I
such that / is semantically answerable for P (Definition 2.2.2), and for all
computations C e C such that I> P D C, there exists O e O such that
C-» O and I?- P |= O
(O is unique because —> is a partial function).
P is consequentially complete for S and Q if and only if P is weakly
complete and, in addition, O above is a consequentially strongest correct
answer ({O} |= N for all N € FQ such that I ?- P |= N).
So, a programming system is sound if all of its outputs are correct an-
swers to input questions, based on the knowledge represented explicitly
by programs. A system is weakly complete if, whenever a correct answer
exists, every computation outputs some correct answer. A system is conse-
quentially complete if, whenever a correct answer exists, every computation
outputs a consequentially strongest correct answer. Notice that, for conse-
quential completeness, the strength of the output answer is judged against
all possible answers in the query system, not just those that are possible
outputs in the programming system, so we cannot achieve consequential
completeness by the trickery of disallowing the truly strongest answers.
A programming system provides another approach to analyzing a simple
form of communication. While semantic systems, proof systems, and query
systems yield insight into the meaning of communication and criteria for
evaluating the behavior of communicating agents, programming systems
merely describe that behavior. A programmer provides a program P to a
processor. A user (sometimes, but not always, identical with the program-
mer) provides an input /, and the processor performs a computation C such
that I> P D C from which the output O, if any, such that C —> O, may be
extracted. We allow the mapping from computation to output to depend
on purely conventional rules that are adopted by the three agents. What
aspects of a computation are taken to be significant to the output is really
a matter of convention, not necessity. Often, only the string of symbols
displayed on some printing device is taken to be the output, but in various
contexts the temporal order in which they are displayed (which may be
Introduction 51
different from the printed order if the device can backspace), the temporal
or spatial interleaving of input and output, the speed with which output
occurs, the color in which the symbols are displayed, which of several de-
vices is used for display, all may be taken as significant. Also, convention
determines the treatment of infinite computation as having no output, null
output, or some nontrivial and possibly infinite output produced incremen-
tally. The presentation of input to a computation is similarly a matter of
accepted convention, rather than formal computation.
In logic programming, where the programmer acts as speaker, the pro-
cessor as auditor, and the user as questioner, soundness of the program-
ming system guarantees that all outputs constitute correct answers. Vari-
ous forms of completeness guarantee that answers will always be produced
when they exist. In this sense, soundness and completeness mean that a
programming system provides a correct and powerful implementation of
the auditor in the speaker-auditor-questioner scenario of Section 2.2.
There is a close formal correspondence between programming systems
and pairs of proof and query systems: inputs correspond to questions,
programs correspond to sets of hypotheses, computations to proofs, and
outputs to theorems (for a different correspondence, in which programs
in the form of lambda terms correspond to natural deduction proofs, see
[Howard, 1980; Tait, 1967; Constable et al., 1986]—compare this to the in-
terpretation of formulae as queries and proofs as answers [Meseguer, 1989]).
Notice that both quaternary relations Q ?- T I D - F and I> P 0 C -> O
are typically computable, while both of the trinary relations Q ?- T |- F
and I> P D-> O are typically semicomputable. Furthermore, the defini-
tions of the trinary relations from the corresponding quaternary relations
are analogous. In both cases we quantify existentially over the third argu-
ment, which is variously a proof or a computation.
There is an important difference, however, between the forms of defi-
nition of the provable-answer relation Q ?- T I D - F, and of the compu-
tational relation I> P 0 C —> O, reflecting the difference in intended uses
of these relations. This difference has only a minor impact on the rela-
tions definable in each form, but a substantial impact on the efficiency of
straightforward implementations based on the definitions. In the query-
proof domain, we relate formulae giving explicit knowledge (program) to
the proofs (computations) that can be constructed from that knowledge,
yielding formulae (outputs) that are provable consequences of the given
knowledge in the relation T I D - F. We independently relate questions
(inputs) to the answers (outputs) in the relation Q ?- F, and then take
the conjunction of the two. There is no formal provision for the question
(input) to interact with the knowledge formulae (program) to guide the
construction of the proof (computation)—the question (input) is only used
to select a completed proof. In the computational domain, we relate inputs
(questions) directly to programs (knowledge formulae) to determine com-
52 Michael J. O'Donnell
putations (proofs) that they can produce in the relation I> P 0 C. Then,
we extract outputs (answer formulae) from computations (proofs) in the
relation C -> O. The relation I> P 0 C provides a formal concept that
may be used to represent the interaction of input (question) with program
(knowledge) to guide the construction of the computation (proof).
Given a proof system and a query system, we can construct a pro-
gramming system with essentially the same behavior. This translation is
intended as an exercise in understanding the formal correspondence be-
tween proofs and computations. Since our requirements for proof systems
and programming systems are quite different, this construction does not
normally lead to useful implementations.
Proposition 3.4.2. Let D = (F, D, I -) be a proof system, and let Q =
(F, Q,?-) be a query system. Define the programming system
where
1. Q> T 0 (P, F) if and only if Q ?- T I P - F
2. Q> T O fail if and only if there are no P and F such that
Q?- T I P - F
3. (P, F) -> G if and only if F = G
4. fail -> F is false for all F € F
Then,
Q?-T\P-Fifand only if Q> T D (P,F) -> F
Therefore,
Q ? - T | - F if and only if Q> T D-> F
If D above is sound for some semantic system 5, then P is sound for
S and Q, but the converse fails because some formulae may never occur
as answers to questions. Proposition 3.4.2 shows that a proof may be
interpreted as a nondeterministically chosen computation that outputs a
theorem.
Because hypotheses to proofs are sets of formulae, rather than single for-
mulae, and the proof relation must be monotone with respect to the subset
relation, there are computational relations > D-> defined by programming
systems that are not the same as the relation ?- |- of any proof and query
systems. Intuitively, in order to mimic an arbitrary programming system
with a proof system and a query system, we must augment the output O
resulting from input / into a formula asserting that input I produces out-
put O. This augmentation is almost trivial, in the sense that echoed input
may just as well be regarded as an implicit part of the output. Informal
question answering uses such implicit augmentation: in response to the
Introduction 53
question 'what is the capital city of Idaho?' the abbreviated answer 'Boise'
is generally accepted as equivalent to the full answer 'the capital city of
Idaho is Boise.'
Proposition 3.4.3. Let P = (P, I, C, O) be a programming system. De-
fine the proof system D = (P U (I x O), C, I -), where
1. T I C - (I, O) if and only if I> P 0 C -> O for some P € T
2. T I C - P is false for all P € P
Also define the query system Q = (I x O, I, ?-), where
1. I ?- (J, O) if and only if I = J.
Then,
Therefore,
As in the construction of Proposition 3.4.2, soundness of V implies
soundness of P, but the converse fails, and completeness does not transfer
either way. Proposition 3.4.3 shows that a computation may be interpreted
as a proof that a given program and input produce a certain output.
Example 3.4.4. The programming systems of Examples 3.3.4, 3.3.5, 3.3.6,
and 3.3.7 are all sound for their appropriate semantic and query systems.
The proof of soundness is easy—every computation can be transformed
easily into a proof in a sound proof system.
The programming system of naive implicational computations in Ex-
ample 3.3.4 is not weakly complete. Consider the program
Given the input question imp(a) ('what logical formula does a imply?'), a
possible computation is the infinite sequence
(a, b, a, 6, . . .)
which has no output. There are three correct answers,
each of which is found by a short computation.
The programming system of naive implicational computations with fail-
ure in Example 3.3.5 is not weakly complete. Consider the program
54 Michael J. O'Donnell
Given the input question rest-imp(a, {a, b, c}) ('what logical formula not
in {a, 6, c} does a imply?'), two possible computations with no output are
(a, b, fail) and (a, c, a, c, . . .)
There is a correct answer, a => d, which is found by the computation (a, d).
The programming system of backtracking implicational computations
in Example 3.3.6 avoids the finite failure of the naive computations with
failure, but is still not weakly complete because of infinite computations. It
succeeds on the program and question above, with the unique computation
but fails on a slightly trickier case. Consider the program
and the question rest-imp(a, {a, b, c, d}). There is no finite failing compu-
tation, and the correct answer a => e is output by the computation
({a}, {b, c, d}, {b, d}, {a, d}, {a, e}, print(e)}
But there is still an infinite computation that misses the output:
The programming system of conjunctive implicational computations in
Example 3.3.7 is weakly complete, simply because every computation out-
puts some correct answer of the form (a => a) A . . ., where in the worst case
only the first conjunct is given. This system was clearly aimed, however,
toward producing consequentially strong answers. It is not consequentially
complete. Consider again the program
and the new question conj-imp(a). The computation
({a}, {&, c, d}, {b, c, e}, {b, a, e}, {b, c, d, e}, {&, a, d, e}, {b, c, d, e}, . . .)
outputs the consequentially strongest answer
But the computation
Introduction 55
outputs only the weaker answer
missing the conjunct a => e.
In each case above, the failure of completeness results from the possi-
bility of unfortunate choices for the next computational step.
Most practical implementations of logic programming languages are
not complete, and many are not even sound. Nonetheless, soundness and
completeness are useful standards against which to judge implementations.
Most implementations are sound and complete for well-characterized sub-
sets of their possible programs and inputs. The cases where soundness
and/or completeness fail are typically considered at least peculiar, and
sometimes pathological, and they are the topics of much discussion and
debate. The history of programming languages gives some hope for a
trend toward stricter adherence at least to soundness criteria. For ex-
ample, early Lisp processors employed dynamic scoping, which is essen-
tially an unsound implementation of logical substitution. Modern Lisp
processors are usually statically scoped, and provide sound implementa-
tions of substitution [Muchnick and Pleban, 1980; Brooks et al., 1982;
Rees Clinger, 1986]. As compiler technology matured, the logically cor-
rect static scoping was found to be more efficient than dynamic scoping,
although early work assumed the contrary.
In spite of the close formal correspondence outlined above between
proof and computation, our natural requirements for proof systems and
programming systems differ significantly. The requirements for correct-
ness, formalized as soundness, are essentially the same—everything that is
proved/computed must be a logical consequence of given information. But,
the requirements for power, formalized as completeness, vary substantially.
Proofs are thought of as things to search for, using any available tools
whether formal, intuitive, or inspirational, and we only demand formal or
mechanical verification of the correctness of a proof, not mechanical dis-
covery of the proof. So, proofs are quantified existentially in the definition
of completeness of a proof system, and we are satisfied with the mere ex-
istence of a proof of a given true formula. Computations, on the other
hand, are thought of as being generated on demand by a computing agent
in order to satisfy the requirement of a user. So, we require that a complete
programming system be guaranteed to produce a sufficiently strong correct
answer whenever a correct answer exists. Since we do not know which of
several possible computations will be generated nondeterministically by the
computing agent, we quantify universally over computations.
Because of the requirement that all computations in a complete pro-
56 Michael J. O'Donnell
gramming system yield correct answers, merely mimicking the relational
behavior of a proof system, as in Proposition 3.4.2, is not sufficient for use-
ful implementation. Practical implementations must use complete strate-
gies for choosing proofs in order to provide programming systems with the
desired guaranteed results.
3.5 Proof-theoretic foundations for logic programming
Given a suitable proof system, a practical implementation of a logic pro-
gramming language still must solve the difficult problem of searching the set
of proofs for one that provides an answer to a given input question. Meth-
ods for choosing and generating proofs are called proof strategies. While
logical semantics provides the conceptual tools for specifying logic program-
ming languages, proof theory [Stenlund, 1972; Prawitz, 1965; Takeuti, 1975;
Schutte, 1977; Girard et al, 1989]. provides the tools for developing proof
strategies. Once a proof strategy has been defined, the remaining prob-
lems in implementation are the invention of appropriate algorithms and
data structures for the strategy, and the details of code generation or in-
terpreting. The organization of logic programming into the application of
semantics to specification, and the application of proof theory to imple-
mentation, does not mean, however, that the former precedes the latter in
the design of a logic programming language. Design normally requires the
simultaneous consideration of specification and implementation, and the
designer must search the two spaces of semantic specifications and proof-
theoretic strategies in parallel for a compatible pair of ideas. In different
circumstances either topic can be the primary driver of design decisions.
In writing this chapter, I have not been able to develop the proof theoretic
side of logic programming design as thoroughly as the semantic side, merely
because I ran out of time, pages, and energy. In this section, I will only
outline the issues involved in applying proof theory to logic programming.
The choice of a proof strategy affects both the power and the complexity
of an implementation, but not the soundness. Given a sound proof system,
a proof strategy can only choose (or fail to find) a correct proof, it cannot
expand the class of proofs. But, a given proof strategy may be incapable of
discovering certain provably correct answers, so it may yield an incomplete
computing system, even when starting with a complete proof system. So,
there is great value in proof theoretic theorems demonstrating that, when-
ever a formula F is provable, there is a proof in some usefully restricted
form. Even when these do not lead to complete implementations, they can
improve the power/complexity tradeoff dramatically. Fortunately, proof
theorists have concentrated a lot of attention on such results, particularly
in the form of proof normalization theorems, which show that all proofs
may be reduced to a normal form with special structure. Many normal-
ization results are expressed as cut elimination theorems, showing that a
particular version of modus ponens called the cut rule may be removed from
Introduction 57
proofs. Cut elimination theorems are usually associated with the predicate
calculus and its fragments, variants, and extensions. The impact of cut
elimination on proof strategies has been studied very thoroughly, leading
to an excellent characterization of the sequent-style proof systems that
are susceptible to generalizations of the simple goal-directed proof strategy
used in Prolog [Miller et al., 1991]. These proof-theoretic methods have
been applied successfully in some novel logics where the model-theoretic
semantics are not yet properly understood.
In the term rewriting literature, there are similar results on the nor-
malization of equational proofs. Many of these come from confluence (also
called Church-Rosser) results. A system of equations
presented with each equation oriented in a particular left-right order, is
confluent precisely if every proof of an equation s = t may be transformed
into a rewriting of each of s and t to a common form u. Rewriting means
here that an equational hypothesis li = yi may only be used from left to
right, to replace instances of li by corresponding instances of ri but not the
reverse. The restriction of equational proofs to rewritings allows complete
strategies that are much simpler and more efficient than those that search
through all equational proofs. See Sections 2.2 and 2.3 of the chapter
'Equational Logic Programming' in this volume, as well as [Klop, 1991],
for more on the application of term rewriting to equational proofs.
4 The uses of semantics
The development of logic programming systems from logics, given above,
provides a particular flavor of semantics, called logical semantics, for logic
programming languages. Logical semantics, rather than competing directly
with other flavors of programming language semantics, provides different
insights, and is useful for different purposes. The careful comparison of dif-
ferent styles of semantics is a wide-open area for further research. In this
section, I sketch the sort of relations that I believe should be explored be-
tween logical semantics, denotational semantics, and algebraic semantics.
Meseguer proposes two sorts of logic programming— 'weak' logic program-
ming uses essentially the same notion of logical semantics as mine, while
'strong' logic programming uses the theory of a single model, such as a
model derived by algebraic semantics [Meseguer, 1989].
4.1 Logical semantics vs. denotational semantics
Roughly, denotational semantics [Scott, 1970; Scott and Strachey, 1971;
Stoy, 1977] takes the meaning of a program to be an abstract descrip-
tion of its input/output behavior, where inputs and outputs are uninter-
preted tokens. Denotational semantics assigns to each program a unique
58 Michael J. O'Donnell
value carrying that meaning. One problem of denotational semantics is
how to deal with observable computational behavior, such as nontermi-
nation, that does not produce output tokens in the concrete sense. This
problem was solved by expanding the domains of input and output, as
well as the domains of program meanings, to partially ordered sets (usu-
ally chain-complete partial orderings [Markowsky, 1976] or lattices [Scott,
1976]) containing objects representing abstract computational behaviors,
not all of which produce tokens as output [Reynolds, 1973; Scott, 1982]. In
practice, the definition of appropriate domains is often the most challeng-
ing task in creating a denotational semantic description of a programming
language, and domain theory has become a definite specialty in theoretical
computer science [Schmidt, 1986; Stoy, 1977; Zhang, 1991; Gunter, 1992;
Winksel, 1993].
The denotational approach provides a useful tool for characterizing
what a particular type of implementation actually does, but it does not
give any intuitive basis for discussing what an implementation ought to
do. Logical semantics, on the other hand, begins with an interpretation
of input and output. It does not directly address techniques for analyz-
ing the behavior of programs—that is left to a metalanguage. But it does
provide an intuitive basis for distinguishing logically reasonable behaviors
from other behaviors.
For example, denotational semantics for functional languages was ini-
tially defined using eager evaluation [Backus, 1978] The domains that were
used to define eager evaluation are not rich enough to represent lazy evalu-
ation. In fact the definition of domains for lazy evaluation [Winksel, 1993]
posed difficult technical problems, causing resistance to the use of lazy
evaluation. Denotational semantics for lazy evaluation matured long after
the idea had been implemented, and informal evidence for its utility had
been presented. [Friedman and Wise, 1976; Henderson and Morris, 1976]
Logical semantics for equational programming, on the other hand, requires
lazy evaluation for completeness, and the demand for lazy evaluation from
this point of view precedes its invention as a programming tool—at latest
it goes back to [O'Donnell, 1977] and the essential roots are already there
in work on combinatory logic and the lambda calculus [Curry and Feys,
1958]. Once lazy evaluation was explained denotationally, that explanation
became a very useful tool for analysis and for deriving implementations. In
general logical semantics predicts and prescribes useful techniques, while
denotational semantics explains and analyzes them.
4.2 Logical semantics vs. initial/final-algebra and
Herbrand semantics
Semantics that use initial or final algebras or Herbrand models [Guttag and
Horning, 1978; Goguen et al., 1978; Meseguer and Goguen, 1985] to repre-
Introduction 59
sent the meanings of programs provide systematic techniques for deriving
denotational-like semantics from logical semantics. Logical semantics de-
termines a large class of models consistent with a given program. Algebraic
semantic techniques construct a single model, depending on the language
in which output is expressed as well as the given program, whose output
theory is the same as that of the class of models given by logical semantics.
This single model can be used for the same sorts of analysis as denotational
semantics (although it is not always based on a lattice or chain-complete
partial ordering). Such single-model semantics must be reconsidered when-
ever the output language expands, since in the larger language the theory
of the single model may not be the same as the theory of the class of models
consistent with the program.
For example, consider a language (based on ideas from Lucid [Ashcroft
and Wadge, 1977] ) with symbols cons, first, more, a, b, satisfying the
equations
first(cons(x,y)) = first(x)
first(a) = a
•first(b) = b
more(cons(x,y)) = y
more (a) = a
more (b) = b
Assume that only the symbols a and b are allowed as output—that
is, we are only interested in deriving equations of the forms s = a and
t = b, where s and t are arbitrary input terms. Algebraic semantic tech-
niques typically interpret this system over a universe of infinite flat (i.e.,
not nested) lists with elements from the set {a, b}, where after some fi-
nite prefix, all elements of the list are the same. cons(s,t) is interpreted
as the list beginning with the first element of s, followed by all the ele-
ments o f f . In this algebraic interpretation, cons (cons (a, b), b) = cons(a,b)
and cons(b, cons(a,a)) = cons(b,a) hold, although neither is a semantic
consequence of the given equations. If, however, we add the conventional
symbols cor and cdr, and define them by the equations
car (cons ( x , y ) ) = x
cdr (cons ( x , y ) ) = y
then we must expand the universe of the algebraic interpretation to the
universe of binary trees with leaves marked a and b. There is no way to
define the functions car and cdr in the flat list model so that they satisfy
the new equations. If we take the full equational theory of the flat list
model, and add the defining equations for car and cdr, then the resulting
theory trivializes. Every two terms s and t are equal by the derivation
s = cdr(car(cons(cons(a, s),b)))
60 Michael J. O'Donnell
= cdr(car(cons(a,b)))
= cdr(car(cons(cons(a,t),b)))
= t
Of course, nobody would apply algebraic semantics in this way—taking the
model for a smaller language and trying to interpret new function symbols
in the same universe. But, what the example shows is that an algebraic
model of a given system of equations may not preserve all of the relevant
information about the behavior of those equations in extended languages.
The set of models associated with a system of equations by logical semantics
is much more robust, and carries enough information to perform extensions
such as the example above.
In general, algebraic semantic techniques, based on initial models, final
models, and Herbrand universes, provide useful tools for determining, in a
given program, the minimum amount of information that a data structure
must carry in order to support the computational needs of that program.
They do not, and are not intended to, represent the inherent information
given by the formulae in the program, independently of a particular def-
inition of the computational inputs and outputs that the program may
operate on.
Acknowledgements
I am very grateful for the detailed comments that I received from the
readers, Bharay Jayaraman, Jose Meseguer, Dale Miller, Gopalan Nadathur
and Ed Wimmers. All of the readers made substantial contributions to the
correctness and readability of the chapter.
References
[Anderson and Belnap Jr., 1975] Alan Ross Anderson and Nuel D. Belnap
Jr. Entailment—the Logic of Relevance and Necessity, volume 1. Prince-
ton University Press, Princeton, NJ, 1975.
[Andrews, 1986] Peter B. Andrews. An Introduction to Mathematical Logic
and Type Theory: To Truth Through Proof. Computer Science and Ap-
plied Mathematics. Academic Press, New York, NY, 1986.
[Ashcroft and Wadge, 1977] E. Ashcroft and W. Wadge. Lucid: A non-
procedural language with iteration. Communications of the ACM,
20(7):519-526, 1977.
[Backus, 1974] John Backus. Programming language semantics and closed
applicative languages. In Proceedings of the 1st ACM Symposium on
Principles of Programming Languages, pages 71-86. ACM, 1974.
Introduction 61
[Backus, 1978] John Backus. Can programming be liberated from the von
Neumann style? a functional style and its algebra of programs. Com-
munications of the ACM, 21(8):613-641, 1978.
[Barendregt, 1984] Hendrik Peter Barendregt. The Lambda Calculus: Its
Syntax and Semantics. North-Holland, Amsterdam, 1984.
[Belnap Jr. and Steel, 1976] Nuel D. Belnap Jr. and T. B. Steel. The Logic
of Questions and Answers. Yale University Press, New Haven, CT, 1976.
[Brooks et al., 1982] R. A. Brooks, R. P. Gabriel, and Guy L. Steele. An
optimizing compiler for lexically scoped Lisp. In Proceedings of the 1982
ACM Compiler Construction Conference, June 1982.
[Church, 1941] A. Church. The Calculi of Lambda-Conversion. Princeton
University Press, Princeton, New Jersey, 1941.
[Codd, 1970] E. F. Codd. A relational model of data for large shared data
banks. Communications of the ACM, 13(6), June 1970.
[Codd, 1971] E. F. Codd. A data base sublanguage founded on the rela-
tional calculus. In Proceedings of the 1971 ACM SIGFIDET Workshop
on Data Description, Access and Control, 1971.
[Codd, 1972] E. F. Codd. Relational completeness of data base sublan-
guages. In Data Base Systems, volume 6 of Courant Computer Science
Symposia. Prentice-Hall, Englewood Cliffs, NJ, 1972.
[Cohn, 1965] P. M. Cohn. Universal Algebra. Harper and Row, New York,
NY, 1965.
[Constable et al, 1986] Robert L. Constable, S. F. Allen, H. M. Brom-
ley, W. R. Cleaveland, J. F. Cremer, R. W. Harper, D. J. Howe,
Todd B. Knoblock, N. P. Mendler, Prakesh Panangaden, J. T. Sasaki,
and Scott F. Smith. Implementing Mathematics with the Nuprl Proof
Development System. Prentice-Hall, Englewood Cliffs, NJ, 1986.
[Curry and Feys, 1958] H. B. Curry and R. Feys. Combinatory Logic, vol-
ume 1. North-Holland, Amsterdam, 1958.
[Date, 1986] C. J. Date. An Introduction to Database Systems. Systems
Programming. Addison-Wesley, Reading, MA, 4 edition, 1986.
[Dijkstra, 1976] Edsger W. Dijkstra. A Discipline of Programming.
Prentice-Hall, Englewood Cliffs, NJ, 1976.
[Dwelly, 1988] Andrew Dwelly. Synchronizing the I/O behavior of func-
tional programs with feedback. Information Processing Letters, 28, 1988.
[Fagin et al., 1984] Ronald Fagin, Joseph Y. Halpern, and Moshe Y. Vardi.
A model-theoretic analysis of knowledge. In Proceedings of the 25th
Annual IEEE Symposium on Foundations of Computer Science, pages
268-278, 1984.
[Friedman and Wise, 1976] Daniel Friedman and David S. Wise. Cons
should not evaluate its arguments. In 3rd International Colloquium on
62 Michael J. O'Donnell
Automata, Languages and Programming, pages 257-284. Edinburgh Uni-
versity Press, 1976.
[Futatsugi et al., 1985] K. Futatsugi, Joseph A. Goguen, J.-P. Jouannaud,
and Jose Meseguer. Principles of OB J2. In 12th Annual Symposium on
Principles of Programming Languages, pages 52-66. ACM, 1985.
[Gallaire et al., 1984] Herve Gallaire, Jack Minker, and J. M. Nicolas.
Databases: A deductive approach. ACM Computing Surveys, 16(2),
June 1984.
[Gallier, 1986] Jean H. Gallier. Logic for Computer Science—Foundations
of Automatic Theorem Proving. Harper & Row, New York, NY, 1986.
[Gentzen, 1935] Gerhard Gentzen. Untersuchungen iiber das logische
schlieBen. Mathematische Zeitschrift, 39:176-210, 405-431, 1935. En-
glish translation in [Gentzen, 1969].
[Gentzen, 1969] Gerhard Gentzen. Investigations into logical deductions,
1935. In M. E. Szabo, editor, The Collected Works of Gerhard Gentzen,
pages 68-131. North-Holland, Amsterdam, 1969.
[Girard et al., 1989] Jean-Yves Girard, Yves Lafont, and Paul Taylor.
Proofs and Types. Cambridge Tracts in Theoretical Computer Science.
Cambridge University Press, Cambridge, UK, 1989.
[Goguen and Burstall, 1992] Joseph A. Goguen and Rod M. Burstall. In-
stitutions: Abstract model theory for specification and programming.
Journal of the ACM, 39(1):95-146, January 1992.
[Goguen et al., 1978] Joseph A. Goguen, James Thatcher, and Eric Wag-
ner. An initial algebra approach to the specification, correctness and
implementation of abstract data types. In Raymond Yeh, editor, Cur-
rent Trends in Programming Methodology, pages 80-149. Prentice-Hall,
1978.
[Goguen, 1990] Joseph A. Goguen. Higher order functions considered un-
necessary for higher order programming. In David A. Turner, editor,
Research Topics in Functional Programming, pages 309-351. Addison-
Wesley, 1990.
[Gordon, 1992] Andrew D. Gordon. Functional Programming and In-
put/Output. PhD thesis, University of Cambridge, 1992.
[Gratzer, 1968] G. Gratzer. Universal Algebra. Van Nostrand, Princeton,
NJ, 1968.
[Gunter, 1992] Carl A. Gunter. Semantics of Programming Languages:
Structures and Techniques. Foundations of Computing. MIT Press, Cam-
bridge, MA, 1992.
[Guttag and Horning, 1978] John V. Guttag and J. J. Horning. The alge-
braic specification of abstract data types. Ada Informatica, 10(l):l-26,
1978.
Introduction 63
[Henderson and Morris, 1976] P. Henderson and J. H. Morris. A lazy eval-
uator. In 3rd Annual ACM Symposium on Principles of Programming
Languages, pages 95-103. SIGPLAN and SIGACT, 1976.
[Hoffmann and O'Donnell, 1982] C. M. Hoffmann and M. J. O'Donnell.
Programming with equations. A CM Transactions on Programming Lan-
guages and Systems, 4(1):83-112, 1982.
[Hoffmann et al., 1985] C. M. Hoffmann, M. J. O'Donnell, and R. I.
Strandh. Implementation of an interpreter for abstract equations. Soft-
ware — Practice and Experience, 15(12):1185-1203, 1985.
[Howard, 1980] William Howard. The formulas-as-types notion of con-
struction. In John P. Seldin and J. R. Hindley, editors, To H. B. Curry:
Essays on Combinatory Logic, Lambda-Calculus, and Formalism, pages
479-490. Academic Press, New York, NY, 1980.
[Hudak and Sundaresh, 1988] Paul Hudak and Raman S. Sundaresh. On
the expressiveness of purely functional I/O systems. Technical Report
YALEU/DCS/RR665, Yale University, New Haven, CT, December 1988.
[Hudak, 1992] Report on the programming language Haskell, a non-strict,
purely functional language, version 1.2. ACM SIGPLAN Notices, 27(5),
May 1992.
[Jaffar and Lassez, 1987] Joxan Jaffar and Jean-Louis Lassez. Constraint
logic programming. In Fourteenth Annual ACM Symposium on Princi-
ples of Programming Languages, pages 111-119, 1987.
[Jayaraman, 1985] Bharat Jayaraman. Equational programming: A uni-
fying approach to functional and logic programming. Technical Report
85-030, The University of North Carolina, 1985.
[Karlsson, 1981] K. Karlsson. Nebula, a functional operating system. Tech-
nical report, Chalmers University, 1981.
[Kleene, 1952] Steven Cole Kleene. Introduction to Metamathematics, vol-
ume 1 of Biblioteca Mathematica. North-Holland, Amsterdam, 1952.
[Klop, 1991] Jan Willem Klop. Term rewriting systems. In S. Abramsky,
Dov M. Gabbay, and T. S. E. Maibaum, editors, Handbook of Logic in
Computer Science, volume 1, chapter 6. Oxford University Press, Oxford,
1991.
[Kowalski, 1974] R. Kowalski. Predicate logic as a programming language.
In Information Processing 74, pages 569-574. North-Holland, 1974.
[Lassez, 1991] Jean-Louis Lassez. From LP to CLP: Programming with
constraints. In T. Ito and A. R. Meyer, editors, Theoretical Aspects of
Computer Software: International Conference, volume 526 of Lecture
Notes in Computer Science. Springer-Verlag, 1991.
[Mac Lane and Birkhoff, 1967] Saunders Mac Lane and G. Birkhoff. Alge-
bra. Macmillan, New York, NY, 1967.
64 Michael J. O'Donnell
[Machtey and Young, 1978] Michael Machtey and Paul Young. An Intro-
duction to the General Theory of Algorithms. Theory of Computation.
North-Holland, New York, NY, 1978.
[Maier and Warren, 1988] David Maier and David S. Warren. Comput-
ing with Logic—Logic Programming with Prolog. Benjamin Cummings,
Menlo Park, CA, 1988.
[Markowsky, 1976] G. Markowsky. Chain-complete posets and directed sets
with applications. Algebra Universalis, 6:53-68, 1976.
[McCarthy, 1960] John McCarthy. Recursive functions of symbolic expres-
sions and their computation by machine, part I. Communications of the
ACM, 3(4):184-195, 1960.
[Meseguer and Goguen, 1985] Jose Meseguer and Joseph A. Goguen. Ini-
tiality, induction, and computability. In Maurice Nivat and John
Reynolds, editors, Algebraic Methods in Semantics, pages 459-541. Cam-
bridge University Press, 1985.
[Meseguer, 1989] Jose Meseguer. General logics. In H.-D. Ebbinghaus et.
al., editor, Logic Colloquium '87: Proceedings of the Colloquium held in
Granada, Spain July 20-25, 1987, Amsterdam, 1989. Elsevier North-
Holland.
[Meseguer, 1992] Jose Meseguer. Multiparadigm logic programming. In
H. Kirchner and G. Levi, editors, Proceedings of the 3rd Interna-
tional Conference on Algebraic and Logic Programming, Volterra, Italy,
September 1992, Lecture Notes in Computer Science. Springer-Verlag,
1992.
[Miller et al., 1991] Dale Miller, Gopalan Nadathur, Prank Pfenning, and
Andre Scedrov. Uniform proofs as a foundation for logic programming.
Annals of Pure and Applied Logic, 51:125-157, 1991.
[Moses, 1970] Joel Moses. The function of FUNCTION in LISP, or why
the FUNARG problem should be called the environment problem. A CM
SIGSAM Bulletin, 15, 1970.
[Mostowski et al., 1953] Andrzej Mostowski, Raphael M. Robinson, and
Alfred Tarski. Undecidability and Essential Undecidability in Arithmetic,
chapter II, pages 37-74. Studies in Logic and the Foundations of Mathe-
matics. North-Holland, Amsterdam, 1953. Book author: Alfred Tarski in
collaboration with Andrzej Mostowski and Raphael M. Robinson. Series
editors: L. E. J. Brouwer, E. W. Beth, A. Heyting.
[Muchnick and Pleban, 1980] Steven S. Muchnick and Uwe F. Pleban. A
semantic comparison of Lisp and Scheme. In Proceedings of the 1980
Lisp Conference, pages 56-64, 1980. Stanford University.
[Nadathur and Miller, 1988] Gopalan Nadathur and Dale Miller. An
overview of AProlog. In Proceedings of the 5th International Confer-
ence on Logic Programming, pages 810-827, Cambridge, MA, 1988. MIT
Press.
Introduction 65
[Nadathur and Miller, 1990] Gopalan Nadathur and Dale Miller. Higher-
order Horn clauses. Journal of the ACM, 37(4):777-814, October 1990.
[O'Donnell, 1977] Michael James O'Donnell. Computing in Systems De-
scribed by Equations, volume 58 of Lecture Notes in Computer Science.
Springer-Verlag, 1977.
[O'Donnell, 1985] Michael James O'Donnell. Equational Logic as a Pro-
gramming Language. Foundations of Computing. MIT Press, Cambridge,
MA, 1985.
[Perry, 1991] Nigel Perry. The Implementation of Practical Functional Pro-
gramming Languages. PhD thesis, Imperial College of Science, Technol-
ogy and Medicine, University of London, 1991.
[Prawitz, 1965] Dag Prawitz. Natural Deduction—a Proof-Theoretic Study.
Alqvist and Wiksell, Stockholm, 1965.
[Rebelsky, 1992] Samuel A. Rebelsky. I/O trees and interactive lazy func-
tional programming. In Maurice Bruynooghe and Martin Wirsing, ed-
itors, Proceedings of the Fourth International Symposium on Program-
ming Language Implementation and Logic Programming, volume 631 of
Lecture Notes in Computer Science, pages 458-472. Springer-Verlag, Au-
gust 1992.
[Rebelsky, 1993] Samuel A. Rebelsky. Tours, a System for Lazy Term-
Based Communication. PhD thesis, The University of Chicago, June
1993.
[Rees Clinger, 1986] The Revised3 report on the algorithmic language
Scheme. ACM SIGPLAN Notices, 21(12):37-79, 1986.
[Reiter, 1978] Raymond Reiter. On closed world databases. In Herve Gal-
laire and Jack Minker, editors, Logic and Databases, pages 149-178.
Plenum Press, 1978. also appeared as [Reiter, 1981].
[Reiter, 1981] Raymond Reiter. On closed world databases. In Bon-
nie Lynn Webber and Nils J. Nilsson, editors, Readings in Artificial
Intelligence, pages 119-140. Tioga, Palo Alto, CA, 1981.
[Reiter, 1984] Raymond Reiter. Towards a logical reconstruction of rela-
tional database theory. In Michael L. Brodie, John Mylopoulos, and
Joachim W. Schmidt, editors, On Conceptual Modelling—Perspectives
from Artificial Intelligence, Databases, and Programming Languages,
Topics in Information Systems, pages 191-233. Springer-Verlag, 1984.
[Reynolds, 1973] John C. Reynolds. On the interpretation of Scott's do-
mains. In Proceedings of Convegno d'Informatica Teorica, Rome, Italy,
February 1973. Instituto Nazionale di Alta Matematica (Citta Universi-
taria).
[Schmidt, 1986] David A. Schmidt. Denotational Semantics: A Methodol-
ogy for Language Development. Allyn and Bacon, 1986.
66 Michael J. O'Donnell
[Schutte, 1977] Kurt Schutte. Proof Theory. Springer-Verlag, New York,
NY, 1977.
[Scott and Strachey, 1971] Dana Scott and Christopher Strachey. Toward
a mathematical semantics for computer languages. In Proceedings of
the Symposium on Computers and Automata, pages 19-46, Polytechnic
Institute of Brooklyn, 1971.
[Scott, 1970] Dana Scott. Outline of a Mathematical Theory of Compu-
tation, volume PRG-2 of Oxford Monographs. Oxford University Press,
Oxford, UK, 1970.
[Scott, 1976] Dana Scott. Data types as lattices. SIAM Journal on Com-
puting, 5(3), 1976.
[Scott, 1982] Dana Scott. Domains for denotational semantics. In
M. Nielsen and E. M. Schmidt, editors, Automata, Languages and
Programming—Ninth Colloquium, volume 140 of Lecture Notes in Com-
puter Science, pages 577-613. Springer-Verlag, Berlin, 1982.
[Stark, 1990] W. Richard Stark. LISP, Lore, and Logic—An Algebraic
View of LISP Programming, Foundations, and Applications. Springer-
Verlag, New York, NY, 1990.
[Stenlund, 1972] Soren Stenlund. Combinators, A-Terms, and Proof The-
ory. D. Reidel, Dordrecht, Netherlands, 1972.
[Stoy, 1977] Joseph E. Stoy. Denotational Semantics: The Scott-Strachey
Approach to Programming Language Theory. MIT Press, Cambridge,
MA, 1977.
[Tait, 1967] William W. Tait. Intensional interpretation of functionals of
finite type. Journal of Symbolic Logic, 32(2):187-199, 1967.
[Takeuti, 1975] Gaisi Takeuti. Proof Theory. North-Holland, Amsterdam,
1975.
[Thompson, 1990] Simon Thompson. Interactive functional programs, a
method and a formal formal semantics. In David A. Turner, editor,
Research Topics in Functional Programming. Addison-Wesley, 1990.
[van Emden and Kowalski, 1976] M. H. van Emden and R. A. Kowalski.
The semantics of predicate logic as a programming language. Journal of
the ACM, 23(4):733-742, 1976.
[Wand, 1976] Mitchell Wand. First order identities as a defining language.
Acta Informatica, 14:336-357, 1976.
[Webster, 1987] Webster's Ninth New Collegiate Dictionary. Merriam-
Webster Inc., Springfield, MA, 1987.
[Williams and Wimmers, 1988] John H. Williams and Edward L. Wim-
mers. Sacrificing simplicity for convenience: Where do you draw the
line? In Proceedings of the Fifteenth Annual ACM Symposium on Prin-
ciples of Programming Languages, pages 169-179. ACM, 1988.
Introduction 67
[Winksel, 1993] Glynn Winksel. The Formal Semantics of Programming
Languages—An Introduction. Foundations of Computing. MIT Press,
Cambridge, MA, 1993.
[Zhang, 1991] Guo-Qiang Zhang. Logic of Domains. Progress in Theoret-
ical Computer Science. Birkhauser, Boston, MA, 1991.
This page intentionally left blank
Equational Logic Programming
Michael J. O'Donnell
Contents
1 Introduction to equational logic programming 69
1.1 Survey of prerequisites 69
1.2 Motivation for programming with equations 71
1.3 Outline of the chapter 74
2 Proof systems for equational logic 75
2.1 Inferential proofs 75
2.2 Term rewriting proofs 78
2.3 The confluence property and the completeness of term
rewriting 81
3 Term rewriting proof strategies 96
3.1 Complete and outermost complete rewriting sequences 97
3.2 Sequentiality analysis and optimal rewriting 100
4 Algorithms and data structures to implement
equational languages 111
4.1 Data structures to represent terms 111
4.2 Pattern-matching and sequencing methods 120
4.3 Driving procedures for term rewriting 129
5 Compiling efficient code from equations 137
6 Parallel implementation 139
7 Extensions to equational logic programming 141
7.1 Incremental infinite input and output 141
7.2 Solving equations 147
7.3 Indeterminate evaluation in subset logic 149
7.4 Relational rewriting 151
1 Introduction to equational logic programming
1.1 Survey of prerequisites
Sections 2.3.4 and 2.3.5 of the chapter 'Introduction: Logic and Logic Pro-
gramming Languages' are crucial prerequisites to this chapter. I summarize
70 Michael J. O'Donnell
their relevance below, but do not repeat their content.
Logic programming languages in general are those that compute by
deriving semantic consequences of given formulae in order to answer ques-
tions. In equational logic programming languages, the formulae are all
equations expressing postulated properties of certain functions, and the
questions ask for equivalent normal forms for given terms. Section 2.3.4 of
the 'Introduction . . .' chapter gives definitions of the models of equational
logic, the semantic consequence relation
T |== (t1 = t2)
(t1 = t2 is a semantic consequence of the set T of equations, see Defini-
tion 2.3.14), and the question answering relation
(norm t1, . . . ,ti :t) ?-= (t = s)
(t = s asserts the equality of t to the normal form s, which contains no
instances of t1, . . . , ti, see Definition 2.3.16). Since this chapter is entirely
about Equational Logic, we drop the subscripts and write |= for |== and
?= for ?-_;.. The composed relation
(norm t1, . . . , ti : t) ?- T |= (t = s)
(t = s is a semantically correct answer to the question (norm t1, . . . , ti : t)
for knowledge T, see Definition 2.2.2) means that s is a normal form—a
term containing no instances of t1, . . . , ti—whose equality to t is a seman-
tic consequence of the equations in T. Equational logic programming lan-
guages in use today all take sets T of equations, prohibited forms t1, . . . , ti,
and terms t to normalize, and they compute normal forms 5 satisfying the
relation above.
Section 2.3.5 of the 'Introduction . . .' chapter explains how different
equational languages variously determine T, t1, . . . ,ti, and t from the
language design, the program being executed, and the input. An alter-
nate style of equational logic programming, using questions of the form
(solve x1, . . . , xi :t1 = t2) that ask for substitutions for x1, . . . , xi solving
the equation (t1 = t2), is very attractive for its expressive power, but much
harder to implement efficiently (see Section 7.2).
There is a lot of terminological confusion about equational logic pro-
gramming. First, many in the Prolog community use 'logic' to mean the
first-order predicate calculus (FOPC), while I stick closer to the dictionary
meaning of logic, in which FOPC is one of an infinity of possible logical
systems. Those who identify logic with FOPC often use the phrase 'equa-
tional logic programming' to mean some sort of extension of Prolog using
equations, such as logic programming in FOPC with equality. In this chap-
ter, 'equational logic programming' means the logic programming of pure
Equational Logic Programming 71
equational logic, as described in the chapter 'Introduction: Logic and Logic
Programming Languages.'
A second source of confusion is that many equational logic programming
languages have been invented under different labels. Lisp [McCarthy, 1960],
APL [Iverson, 1962], Red languages [Backus, 1974], functional program-
ming languages [Backus, 1978; Hudak, 1992], many dataflow languages
[Ashcroft and Wadge, 1985; Pingali and Arvind, 1985; Pingali and Arvind,
1986], and languages for algebraic specification of abstract datatypes [Fu-
tatsugi et al, 1985; Guttag and Horning, 1978; Wand, 1976] are all forms
of equational logic programming languages, although they are seldom re-
ferred to as such. This chapter focuses on a generic notion of equational
logic programming, rather than surveying particular languages.
1.2 Motivation for programming with equations
From a programmer's point of view, an equational logic programming lan-
guage is the same thing as a functional programming language[Backus,
1978]. The advantages of functional programming languages are discussed
in [Hudak, 1989; Bird and Wadler, 1988; Field and Harrison, 1988]—
equational logic programming languages offer essentially the same advan-
tages to the programmer. Functional programming and equational logic
programming are different views of programming, which provide different
ways of designing and describing a language, but they yield essentially the
same class of possible languages. The different styles of design and descrip-
tion, while they allow the same range of possibilities, influence the sense
of naturalness of different languages, and therefore the relative importance
of certain features to the designer and implementer. The most important
impact of the equational logic programming view on language design is
the strong motivation that it gives to implement lazy, or demand-driven,
computation.
In the conventional view of functional programming, computation is
the evaluation of an input term in a unique model associated with the pro-
gramming language. This view makes it very natural to evaluate a term of
the form f ( s 1 , . . . , sn) by first evaluating all of the arguments Si, and then
applying the function denoted by / to the values of the arguments. If the
attempt to evaluate one of the arguments leads to infinite computation,
then the value of that argument in the model is said to be an object called
'undefined' (the word is used here as a noun, although the dictionary rec-
ognizes it only as an adjective), and typically denoted by the symbol JL.
But, since the value J. is indicated by the behavior of infinite computation,
there is no chance to actually apply the function denoted by / to it, so that
every function is forced to map _L to _L. Such functions are called strict
functions.
Early functional programming languages required all primitive func-
tions to be strict, except for the conditional function cond. The normal
72 Michael J. O'Donnell
way to evaluate a term of the form cond(s,t, u) is to evaluate s, then use
its value to determine which of t or u to evaluate, omitting the other. The
function denoted by cond is thus not strict, since for example the value
of cond (true, 0,JL) is 0 rather than _L. Only Backus seems to have been
annoyed by the inconsistency between the nonstrictness of the conditional
function and the strictness of all other primitives. He proposed a strict
conditional, recovering the selective behavior of the nonstrict conditional
through a higher-order coding trick [Backus, 1978]. In effect, he took ad-
vantage of the nearly universal unconscious acceptance of a nonstrict in-
terpretation of function application, even when the function to be applied
is strict.
In the equational logic programming view, computation is the deriva-
tion of an equivalent normal form for an input term using the information
given by a set of equations describing the symbols of the programming
language. The equivalence of input to output holds in all of the infinitely
many models of those equations. This view makes it very natural to ap-
ply equations involving / to derive an equivalent form for f(s1, . . . , sn) at
any time, possibly before all possible derivation has been performed on the
arguments Si. The natural desire for completeness of an implementation re-
quires that infinite computation be avoided whenever possible. Notice that
the equational logic programming view does not assign a value JL denoting
'undefined' (the noun) to a term with infinite computational behavior. In
fact, in each individual model all functions are total. Rather, we might ob-
serve that a term is undefined (the word is now an adjective, as approved by
the dictionary) if there is no equivalent term suitable for output, although
each model of the given equations assigns it some value. So, equational
logic programming leads naturally to computational behavior that is not
strict—in fact, a logically complete implementation of equational logic pro-
gramming must make functions as unstrict as possible. The preference for
nonstrictness comes from regarding undefinedness as our inability to dis-
cover the value of a function, rather than the inherent lack of a semantic
value.
The contrast between strict and nonstrict treatments of functions is
best understood by comparing the conventional implementation of cond,
true and false to that of cons, car and cdr in Lisp.
Example 1.2.1. The following equations define the relationship between
cond, true, and false:
T =
cond {(cond(true,x,y) = x), (cond(false,x,y) = y)}
Similarly the following equations define the relationship between cons, car,
and cdr:
Tcons = {(car(cons(x,y)) = x), (cdr(cons(x,y)) = y)}
Equational Logic Programming 73
These equations were given, without explicit restriction, in the earliest
published definition of Lisp [McCarthy, 1960].
Notice the formal similarity between T cond and Tcons in Example 1.2.1
above. In both cases, two equations provide a way to select one of the two
subterms denoted by the variables x and y. In T c o n d , the selection is de-
termined by the first argument to cond, in Tcons it is determined by the
function symbol applied to the term headed by cons. Yet in all early Lisp
implementations cons is evaluated strictly, while cond is not. The equation
(car (cons (0, s)) = 0) is a logical consequence of Tcons, even when s leads
to infinite computation, so a complete implementation of equational logic
programming must not treat cons strictly.
In the Lisp and functional programming communities, nonstrict evalu-
ation of functions other than the conditional is called lazy evaluation. The
power of lazy evaluation as a programming tool is discussed in [Friedman
and Wise, 1976; Henderson and Morris, 1976; Henderson, 1980; Hudak,
1989; Bird and Wadler, 1988; Field and Harrison, 1988; O'Donnell, 1985].
Lazy evaluation is demand-driven—computation is performed only as re-
quired to satisfy demands for output. So, the programmer may define large,
and even infinite, data structures as intermediate values, and depend on
the language implementation to compute only the relevant parts of those
structures. In particular, lazily computed lists behave as streams [Karlsson,
1981; Hudak and Sundaresh, 1988], allowing a straightforward encoding of
pipelined coroutines in a functional style.
Many modern implementations of functional programming languages
offer some degree of lazy evaluation, and a few are now uniformly lazy. But,
in the functional programming view, lazy evaluation is an optional added
feature to make programming languages more powerful. The basic denota-
tional semantic approach to functional programming makes strictness very
natural to describe, while denotational semantics for lazy evaluation seems
to require rather sophisticated use of domain theory to construct models
with special values representing all of the relevant nonterminating and par-
tially terminating behaviors of terms [Winksel, 1993]. In the equational
logic programming view, lazy evaluation is required for logical complete-
ness, and strict evaluation is an arbitrary restriction on derivations that
prevents certain answers from being found.
The functional and equational views also diverge in their treatments
of certain terms that are viewed as pathological. From the functional
programming view, pathological terms seem to require specialized logical
techniques treating errors as values, and even new types of models called
error algebras [Goguen, 1977]. For example, in a language with stacks,
the term pop(empty) is generally given a value which is a token denoting
the erroneous attempt to pop an empty stack. Given a set of equations,
equational logic programming provides a conceptual framework, based on
74 Michael J. O'Donnell
well-understood traditional concepts from mathematical logic, for prescrib-
ing completely the computational behavior of terms. The judgement that
a particular term is pathological is left to the consumer of that answer,
which might be a human reader or another program. For example, the
term pop(empty) need not be evaluated to an error token: it may be out-
put as a normal form, and easily recognized as a pathological case by the
consumer. Or, an explicit equation pop(empty) = e may be added to the
program, where e gives as much or as little detailed information about the
particular error as desired.
So, for the programmer there is nothing to choose between lazy func-
tional programming and equational logic programming—these are two styles
for describing the same programming languages, rather than two different
classes of programming languages. To the language designer or implemen-
tor, the functional programming view provides a connection to a large body
of previous work, and offers some sophisticated tools for the thorough de-
scription of the processing of erroneous programs and the use of varying
degrees of strictness or laziness. The equational logic programming view
offers a deeper explanation of the logical content of computations, a way
of defining correctness of the computation of answers independently of the
classification of programs as correct or erroneous, and a strong motivation
for uniformly lazy evaluation. It also connects equational/functional pro-
gramming to other sorts of logic programming in a coherent way, which
may prove useful to future designs that integrate equational/functional
programming with other styles.
1.3 Outline of the chapter
The next part of this chapter is primarily concerned with problems in
the implementation of equational logic programming and some interest-
ing variants of it. Those problems arise at four very different levels of
abstraction—logic, strategy, algorithm, and code. At the level of pure
logic, Section 2 discusses two different formal systems of proof for equa-
tional logic—inferential proof and term rewriting proof—and argues that
the latter is logically weaker in general, but more likely to provide efficient
computation for typical equational programs. The confluence property of
sets of equations is introduced, and shown to be a useful way of guarantee-
ing that term rewriting proof can succeed. Next, Section 3 treats high-level
strategic questions in the efficient search for a term rewriting proof to an-
swer a given question. The crucial problem is to choose the next rewriting
step out of, a number of possibilities, so as to guarantee that all correct an-
swers are found, and to avoid unnecessary steps. Then, Section 4 discusses
the design of efficient algorithms and data structures for finding and choos-
ing rewriting steps, and for representing the results of rewriting. Section 5
contains a brief description of the conventional machine code that a com-
piler can generate based on these algorithms and data structures. Section 6
Equational Logic Programming 75
discusses briefly some of the problems involved in parallel implementation
of equational logic programming. Finally, Section 7 treats several possible
extensions to the functionality of equational logic programming and the
problems that arise in their semantics and implementation.
2 Proof systems for equational logic
The basic idea in implementations of equational logic programming is to
search for a proof that provides a correct answer to a given question. The
basic idea behind proofs in equational logic is that the equation t1 = t2
allows t1 and t2 to be used interchangeably in other formulae. As in Def-
inition 3.1.1, of the chapter 'Introduction: Logic and Logic Programming
Languages,' T I D - F means that D is a correct proof of the formula F
from hypotheses in T. T I- F means that there exists a proof of F from
hypotheses in T. In this chapter, subscripts on the generic symbols I -
and |- are omitted whenever the particular proof system is clear from the
context.
In Sections 2.1 and 2.2, we consider two different styles of equational
proof. Inferential proofs derive equations step by step from other equa-
tions. Term rewriting proofs use equations to transform a given term into
a provably equivalent term by substituting equals for equals.
2.1 Inferential proofs
In order to explore a variety of approaches to proving equations, we first
define generic concepts of rules of inference and proofs using rules, and
then consider the power of various sets of rules.
Definition 2.1.1. Let the set V of variables, the sets Funi of i-ary func-
tion symbols, and the set Tp of terms, be the same as in Definition 2.3.1
of the 'Introduction . . .' chapter Section 2.3, and let the set of equational
formulae, or simply equations, be F= = {t1 = t2 : t1, t2 6 Tp}, as in Defi-
nition 2.3.13 in Section 2.3.4 of the chapter 'Introduction: Logic and Logic
Programming Languages.'
An equational rule of inference is a binary relation
When T R F, we say that F follows from T by rule R. Members of T axe
called hypotheses to the application of the rule, and F is the conclusion.
When 0 R F, we call F a postulate. (It is popular now to call a postulated
formula F an axiom, although the dictionary says that an axiom must be
self-evident, not just postulated.) Rules of inference are usually presented
in the form
76 Michael J. O'Donnell
Where H1 . . . , Hm are schematic descriptions of the hypotheses, and C is
a schematic description of the conclusion of an arbitrary application of the
rule. Notice that the union of rules of inference is itself a rule.
The set of inferential equational proofs is P= = F+, the set of nonempty
finite sequences of equations. Given a rule of inference R, the proof relation
is defined by
T I <F0, . . . , Fm) -R F if and only if Fm = F and,
for all i < m, one of the following cases holds:
1. Fi € T
2. There exist j1, . . . ,jn< i such that {Fj1 , . . . , Fjn } R Fi
So, a proof of F from hypotheses in T using rule R is a sequence of equa-
tions, each one of which is either a hypothesis, or it follows from previous
equations by the rule R. The following are popular rules of inference for
proofs in equational logic.
Definition 2.1.2.
Equational Logic Programming 77
Now, when R is the union of any of the rules presented above, ( F = , P=,
I -R) is a compact proof system (Definition 2.1.3, Section 2.1).
The rules above are somewhat redundant. Every proof system using a
subset of these rules is sound, and those using the Reflexive, Symmetric,
Transitive and Instantiation rules, and at least one of Substitution and
Congruence, are also complete.
Proposition 2.1.3. Let R be the union of any of the rules in Defini-
tion 2.1.2. Then (F= ,P=, I -R) is a sound proof system for the standard
semantic system of Definition 2.3.14, Section 2.3.4 of the chapter 'Introduc-
tion: Logic and Logic Programming Languages.' That is, T |-R (t1 = t2)
implies T | = ( t 1 = t 2 ) .
The proof of soundness is an elementary induction on the number of
steps in a formal equational proof, using the fact that each of the rules of
inference proposed above preserves truth.
Proposition 2.1.4. Let R be the union of the Reflexive, Symmetric,
Transitive, and Instantiation rules, and at least one of the Substitution
and Congruence rules. Then (F = ,P = , I -R) is a complete proof system.
That is, T |= (t1 = t2) implies T |-R (t1 = t2).
To prove completeness, we construct for each set T of equations, a
term model MT such that Theory ({MT}) contains exactly the semantic
consequences of T. For each term t e Tp,
Because R includes the Reflexive, Symmetric, and Transitive rules, prov-
able equality is an equivalence relation on terms, and |t|T is the equivalence
class containing t. Now, construct the model
whose universe is
and whose function assignment is defined by
Either of the rules Substitution and Congruence is sufficient to guaran-
tee that TT is well defined. Finally, the Instantiation rule guarantees that
T |- (s = t) if and only if T T v ( s ) = T T v ( t ) for all variable assignments v,
which by Definition 2.3.14 is equivalent to T |= (s = t).
78 Michael J. 0 'Donnell
Notice that each inference by the Congruence rule is derivable by k
applications of the Substitution rule, combined by the Transitive rule. In
effect, Congruence is just a special form of multiple simultaneous substi-
tution. Similarly, each inference by the Substitution rule is derivable by
repeated applications of the Congruence rule and additional instances of
the Reflexive rule (this can be proved easily by induction on the structure
of the term r on which substitution is performed in the Substitution rule).
In the rest of this chapter, the symbols I -inf and |-inf refer to a sound
and complete system of inferential equational proof, when the precise rules
of inference are not important.
2.2 Term rewriting proofs
The most commonly used methods for answering normal form questions
(norm t1, . . . , ti : t) all involve replacing subterms by equal subterms, using
the Substitution rule, to transform the term t into an equivalent normal
form. Substitution of subterms according to given rules is called term
rewriting, and is an interesting topic even when the rewriting rules are
not given by equations (see the chapter 'Equational Reasoning and Term
Rewriting Systems' in Volume 1). In this chapter, we are concerned only
with the use of term rewriting to generate equational proofs—this technique
is also called demodulation [Loveland, 1978] in the automated deduction
literature.
Definition 2.2.1. Let T = {li = r1, . . .,ln = rn} be a set of equations.
Recall that an instance of a formula or term is the result of substituting
terms for variables (Definition 2.3.5 in Section 2.3.1 of the chapter 'Intro-
duction: Logic and Logic Programming Languages').
A term s1 rewrites to s2 by T (written s1 —> s2) if and only if there is
a term t, a variable x with exactly one occurrence in t, and an instance
l'i = ri of an equation li = ri in T, such that s1 = tty'Jx] and 52 = t[r'Jx].
That is, $2 results from finding exactly one instance of a left-hand side of
an equation in T occurring as a subterm of s1, and replacing it with the
corresponding right-hand side instance.
A term rewriting sequence for T is a nonempty finite or infinite sequence
(U0,u1, . . .) such that, for each i, Ui -> ui+1.
Term rewriting sequences formalize the natural intuitive process of re-
placing equals by equals to transform a term. A term rewriting sequence
may be viewed as a somewhat terse proof.
Definition 2.2.2. Let T+ be the set of nonempty finite sequences of terms
in Tp. The proof relation I -tr is defined by T I (u0, . . ., um) -tr (s = t) if
and only if U0 = s, um = t, and for each i < m, Ui -> Ui+1.
Then (F = , T+, I- t r ), is a compact proof system, representing the term
Equational Logic Programming 79
rewriting style of equational proof.
A term rewriting proof for T represents an inferential proof from hy-
potheses in T in a natural way.
Proposition 2.2.3. // T |-tr (s = t), then T |-inf (s = t).
Let (u0, . . . ,u n ) be the term rewriting sequence such that
In particular, U0 = s and un = t. The proof of the proposition is an ele-
mentary induction on n.
BASIS: For n = 0, s = U0 = un = t, so T I (U0 = U0) —inf (s = t), by
the Reflexive rule.
INDUCTION: For n > 0, since a nonempty prefix of a term rewrit-
ing proof is also a term rewriting proof, we have T I (U0,. . . , u n - 1 ) -tr
(s = u n-1 ). By the induction hypothesis, there is a D such that T I D -inf
(s = u n - 1 ) . It is easy to extend D to D' so that T I D' — (s = t), by
adding the following steps:
• the appropriate equation from T;
• a sequence of applications of the Instantiation rule to produce the
appropriate instance of the equation above;
• one application of the Substitution rule to produce un-1 = t;
• one application of the Transitive rule to produce s = t.
Since inferential proof is sound, it follows that term rewriting proof is
also sound.
Example 2.2.4. Let T = {f(a,f(x,y)) = f(y,x), g(x) = x}.
is a term rewriting proof of
from T. The corresponding inferential proof from the induction in Propo-
sition 2.2.3 is given below. Line numbers are added on the left, and rules
cited on the right, for clarity: formally the proof is just the sequence of
equations. The key occurrences of the terms in the term rewriting sequence
above are boxed to show the correspondence.
80 Michael J. O'Donnell
Steps 5, 10, and 12 above are redundant (they reproduce the results already
obtained in steps 4, 9, 2), but the systematic procedure in the induction of
Proposition 2.2.3 includes them for uniformity.
So, a term rewriting proof is a convenient and natural shorthand for an
inferential proof.
Not every inferential proof corresponds to a term rewriting proof. First,
the proofs corresponding to term rewriting sequences do not use the Sym-
metric rule. This represents a serious incompleteness in term rewriting
proof. Section 2.3 shows how restrictions on equational hypotheses can
avoid the need for the Symmetric rule, and render term rewriting complete
for answering certain normal form questions.
Example 2.2.5. Let T = {a = b, c = b, c = d}. T |= (a = d), and
T |-inf (a = d), by one application of the Symmetric rule and two appli-
cations of the Transitive rule. But, there is no term rewriting sequence
from a to d, nor from d to o, nor from a and d to a common form equal to
both.
Second, term rewriting proofs limit the order in which the Instantiation,
Substitution, and Transitive rules are applied. This second limitation does
not affect the deductive power of the proof system.
Proposition 2.2.6. Let T = {li = r1, . . .,ln= rn }be a set of equations.
Let TR = {r1 = lj, . . . ,rn = ln}. TR is the same as T except that the left
and right sides of equations are interchanged—equivalently, T contains
Equational Logic Programming 81
the results of applying the Symmetric rule to the equations in T.
For all equations (s = t), if T |-inf (s = t) (equivalently, if T |=(s = t))
then T U TR |-tr (s = t).
The proof of the proposition, given in more detail in [O'Donnell, 1977],
works by permuting the steps in an arbitrary inferential proof of s = t into
the form:
1. hypotheses;
2. applications of the Symmetric rule;
3. applications of the Instantiation rule;
4. applications of the Substitution rule;
5. applications of the Transitive rule.
The reflexive rule is only needed in the degenerate case when s = t (s
and t are the same term). In this form, it is easy to represent each of
the applications of the Transitive rule as concatenating two term rewriting
sequences. The crucial quality of the permuted form of the proof is that
all uses of the Instantiation rule come before any use of the Transitive and
Substitution rules.
The implementor of a logic programming system often faces a trade-
off between the cost of an individual proof, and the cost of the search for
that proof. The discipline of term rewriting can be very advantageous in
reducing the number of possible steps to consider in the search for a proof
to answer a question, but it increases the lengths of proofs in some cases.
Section 4.3.3 shows how clever uses of Instantiation sometimes reduce the
length of a proof substantially compared to term rewriting proofs. Effi-
cient implementations of programming languages have not yet succeeded
in controlling the costs of search for a proof with the more sophisticated
approaches to Instantiation, so term rewriting is the basis for almost all
implementations.
2.3 The confluence property and the completeness of
term rewriting
Term rewriting is often much more efficient than an undisciplined search
for an equational proof. But, for general sets T of equational hypotheses,
term rewriting is not complete, due to its failure to apply the Symmet-
ric rule. It is tempting, then, to use each equation in both directions,
and take advantage of the completeness result of Proposition 2.2.6. Un-
fortunately, known techniques for efficient term rewriting typically fail or
become inefficient when presented with the reversed forms of equations.
So, we find special restrictions on equations that imply the completeness of
term rewriting for the answering of particular normal form questions. The
confluence property, also called the Church-Rosser property, provides the
key to such restrictions.
82 Michael J. O'Donnell
Definition 2.3.1. Let -» be a binary relation, and ->* be its reflexive-
transitive closure. -» is confluent if and only if, for all s, t1, t2 in its
domain such that s ->* t1 and s ->* t2, there exists a u such that ti ->* u
and t2 —>* u (see Figure 1 B)
A. Local confluence B. Confluence C. One-step confluence
The circle around u indicates that it is existentially quantified, the uncircled
s, t1, t2 are universally quantified.
Fig. 1. Confluence and related properties.
Two similar properties that are very important in the literature are
local confluence, which is weaker than confluence, and one-step confluence,
which is stronger than confluence.
Definition 2.3.2 ([Newman, 1942]). Let -> be a binary relation, and
->* be its reflexive-transitive closure. -> is locally confluent if and only if,
for all s, t1, t2 in its domain such that s —> t1 and s —> t2, there exists a u
such that t1 -> u and t2-»* u (see Figure 1 A).
While confluence guarantees that divergent term rewriting sequences
may always be rewritten further to a common form, local confluence guar-
antees this only for single step term rewriting sequences.
Definition 2.3.3 ([Newman, 1942]). Let -> be a binary relation. -> is
locally confluent if and only if, for all s, t1, t2 in its domain such that s -> t1
and s -> t2, there exists a u such that t1 -» u and t2 -> u (see Figure 1 C).
While confluence guarantees that divergent term rewriting sequences
may always be rewritten further to a common form, one-step confluence
guarantees that for single step divergences, there is a single-step conver-
gence.
Proposition 2.3.4. One-step confluence implies confluence implies local
confluence.
The first implication is a straightforward induction on the number of
steps in the diverging rewrite sequences. The second is trivial.
Equational Logic Programming 83
2.3.1 Consequences of confluence
T
When the term rewriting relation -> for a set T of equations has the con-
fluence property, term rewriting is sufficient for deriving all logical conse-
quences of T, in the sense that T |= (s = t) implies that s and t rewrite to
some common form u.
Proposition 2.3.5 ([Curry and Feys, 1958]). Let T be a set of equa-
tions, and let -> be the term rewriting relation for T (Definition 2.2.1). If
-> is confluent, then for all terms s and t such that T |= (s = t), there is
a term u such that T |-tr (s = u) and T |-tr (t = u).
The proof of the proposition is an elementary induction on the length
of an inferential proof D such that T I D -inf (s = t).
So, confluent term rewriting is nearly complete, in the sense that every
logical consequence s = t of a set of equations T may be derived by choosing
an appropriate term u, and finding two term rewriting proofs and a trivial
inferential proof as follows:
1. T |-tr (S = u)
2. T |-tr (t = u)
3. {s = u, t = u} |-inf (s = t) trivially, by one application of Symmetry
and one application of Transitivity.
The near-completeness of confluent term rewriting leads to its use in the-
orem proving [Knuth and Bendix, 1970; Loveland, 1978]. For equational
logic programming, term rewriting can answer all normal form queries in
a confluent system, when the prohibited terms in normal forms are all the
left-hand sides of equations.
Proposition 2.3.6. Let T = {l1 = r1, . . . ,lm = rm} be a set of equa-
tions, with confluent term rewriting relation —>, and let t be any term.
If
(norm l1, . . . , lm : t) ?- T |= (t = s)
then
(norm l1, . . . ,lm : t) ?- T |-tr (t = s)
The proof is elementary. By confluence, t and s rewrite to a common
form u. Since s is a normal form, it is not rewritable, and must be the
same as u.
So, for equations T with confluent rewriting relation, term rewriting
based on T is sufficient for answering all queries requesting normal forms
that prohibit left-hand sides of equations in T. From now on, a normal
form will mean a normal form for the left-hand sides of whatever set of
equations we are discussing (see Definition 2.3.16 in the chapter 'Introduc-
tion: Logic and Logic Programming Languages' for the general concept of
normal form).
84 Michael J. O'Donnell
The most famous consequence of the confluence property is uniqueness
of normal forms.
Proposition 2.3.7. Let T = {l1 = r1, . . . ,lm = rm} be a set of equa-
tions, with confluent term rewriting relation ->. If
and
then S1 = S2 (s1 and s2 are the same term).
The proof is elementary. By confluence, s1 and s2 rewrite to a common
form u. Since s1 and s2 are normal forms, they are not rewritable, and
must be the same as u.
So, equational logic programs using confluent systems of equations have
uniquely defined outputs. This is an interesting property to note, but it is
not essential to the logic programming enterprise — logic programs in FOPC
are allowed to have indeterminate answers (Section 2.3.1 of the 'Introduc-
tion' chapter), and this freedom is often seen as an advantage. In efficient
equational' logic programming, confluence is required for the completeness
of term rewriting, and uniqueness of answers is an accidental side-effect
that may be considered beneficial or annoying in different applications.
Confluence, in effect, guarantees that the order of applying rewrite steps
cannot affect the normal form. In Section 3 we see that the order of appli-
cation of rewrite rules can affect the efficiency with which a normal form is
found, and in some cases whether or not the unique normal form is found
at all.
2.3.2 Testing for confluence
Proposition 2.3.8. Confluence is an undecidable property of finite sets
of equations.
The proof is straightforward. Given an arbitrary Turing Machine M,
modify M so that, if it halts, it does so in the special configuration If.
Encode configurations (instantaneous descriptions) of M. as terms (just let
the tape and state symbols be unary function symbols), and provide rewrit-
ing rules to simulate the computation of M. So far, we have a system
of equations in which an arbitrary encoding of an initial configuration I0
rewrites to If if and only if M. halts on I0 . Choose a new symbol a not
used in encoded configurations, and add two more equations: I0 = a and
If = a. The extended system is confluent if and only if M halts on I0.
For practical purposes in programming language implementations, we
need a sufficient condition for confluence that is efficient to test.
Equational Logic Programming 85
Orthogonality. A particularly useful sort of condition for guaranteeing
confluence is orthogonality, also called regularity (but not connected in
any sensible way to the regular languages). Orthogonality is a set of re-
strictions on rewrite rules insuring that they do not interfere with one
another in certain pathological ways. We consider three versions of or-
thogonality. Rewrite-orthogonality insures that the rewrites performed by
the rules do not interfere, while the stronger condition of rule-orthogonality
prohibits even the appearance of interference based on an inspection of the
left-hand sides of the rules, and ignoring the right-hand sides. Constructor-
orthogonality is an even stronger and simpler syntactic condition that guar-
antees rule-orthogonality. In other literature on term rewriting, 'orthogo-
nality' and 'regularity' refer to the stronger form, rule-orthogonality.
Definition 2.3.9. Let T = {l1 = r1, ...,l n = rn} be a set of equations.
T is rewrite-orthogonal if and only if the following conditions hold:
1. (Nontrivial) No left-hand side li of an equation li = ri in T consists
entirely of a variable.
2. (Rule-like) Every variable in the right-hand side ri of an equation
li = ri in T occurs in the left-hand side li as well.
3. (Left-linear) No variable occurs more than once in the left-hand side
li of an equation li = ri in T.
4. (Rewrite-Nonambiguous) Let li and lj be left-hand sides of equations
in T, and let s be a term with a single occurrence of a new variable
y (not occurring in any equation of T). If
then either s is an instance of lj, or
In clause 4 the nested substitution may be hard to read.
is the result of substituting t1,,..., tm for x 1 ,..., xm in ri , to produce ri =
r i [ t 1 , . . . ,tm /x 1 ,.. .,x m ], then substituting r2[ for y in s. Clause 4 is best
understood by considering an example where it fails. The set of equations
{f(g(v,w),x) = a, g(h(y),z) = b} is rewrite-ambiguous because, in the
term f ( g ( h ( c ) , d ) , e ) , there is an instance of f ( g ( w , x ) ) and an instance
of g ( h ( y ) , z ) , and the two instances share the symbol g. Furthermore,
f(g(h(c),d),e) rewrites to a using the first equation, and to a different
result, f ( b , e ) , using the second equation.
Nontriviality and the Rule-like property are required in order for the
interpretation of the equations as term rewriting rules to make much sense.
86 Michael J. O'Donnell
Left-linearity is of practical importance because the application of a rule
with repeated variables on the left-hand side requires a test for equality.
Non-left-linear systems also fail to be confluent in rather subtle ways, as
shown in Example 2.3.16 below. Rewrite-nonambiguity says that if two
rewriting steps may be applied to the same term, then they are either
completely independent (they apply to disjoint sets of symbols), or they
are equivalent (they produce the same result). Example 2.3.16 below shows
more cases of rewrite-ambiguity and its consequences.
One simple way to insure rewrite-nonambiguity is to prohibit all inter-
ference between left-hand sides of rules.
Definition 2.3.10 (Klop [1991; 1980]). Let T = {l1 = r 1 ; . . . , ln = rn}
be a set of equations. T is rule-orthogonal if and only if T satisfies condi-
tions 1-3 of Definition 2.3.9 above, and also
4' (Rule-Nonambiguous) Let li and lj be left-hand sides of equations in
T, and let s be a term with a single occurrence of a new variable y
(not occurring in any equation of T). If
then either s is an instance of lj, or s = y and i = j .
Rule-nonambiguity says that if two rewriting steps may be applied to the
same term, then they are either completely independent, or they are iden-
tical (the same rule applied at the same place). Notice that rule nonambi-
guity depends only on the left-hand sides of equations, not the right-hand
sides. In fact, only the Rule-like condition of rule-orthogonality depends
on right-hand sides.
Definition 2.3.11. Two systems of equations are left-similar if the mul-
tisets of left-hand sides of equations are the same, except for renaming of
variables.
Proposition 2.3.12. A set T of equations is rule-orthogonal if and only
if
• T satisfies the rule-like restriction, and
• every rule-like set of equations left-similar to T is rewrite-orthogonal.
That is, rule-orthogonality holds precisely when rewrite-orthogonality can
be guaranteed by the forms of the left-hand sides alone, independently of
the right-hand sides.
An even simpler way to insure rule-nonambiguity is to use a constructor
system, in which symbols appearing leftmost in rules are not allowed to
appear at other locations in left-hand sides.
Definition 2.3.13. Let T = {l1 = r 1 , . . . , ln = rn} be a set of equations.
T is constructor-orthogonal if and only if T satisfies conditions 1-3 of
Equational Logic Programming 87
Definition 2.3.9 above, and the symbols of the system partition into two
disjoint sets—the set C of constructor symbols, and the set D of defined
symbols, satisfying
4" (Symbol-Nonambiguous)
• Every left-hand side of an equation in T has the form f ( t 1 , . . . ,
tm), where / € D is a defined symbol, and t 1 , . . . , t m contain
only variables and constructor symbols in C.
• Let li and lj be left-hand sides of equations in T. If there exists
a common instance s of li and lj, then i = j.
In most of the term-rewriting literature, 'orthogonal' and 'regular' both
mean rule-orthogonal. It is easy to see that constructor orthogonality im-
plies rule-orthogonality, which implies rewrite-orthogonality. Most func-
tional programming languages have restrictions equivalent or very similar
to constructor-orthogonality.
Orthogonal systems of all varieties are confluent.
Proposition 2.3.14. Let T be a constructor-, rule- or rewrite-orthogonal
set of equations. Then the term rewriting relation —>• is confluent.
Let — be the rewrite relation that is to be proved confluent. The essen-
tial idea of these, and many other, proofs of confluence is to choose another
relation - with the one-step confluence property (Definition 2.3.3, whose
transitive closure is the same as the transitive closure of -. Since conflu-
ence is defined entirely in terms of the transitive closure, — is confluent
if and only if —>' is confluent. - is confluent because one-step confluence
implies confluence. To prove confluence of orthogonal systems of equations,
the appropriate - allows simultaneous rewriting of any number of disjoint
subterms.
Theorem 10.1.3 of the chapter 'Equational Reasoning and Term-
Rewriting Systems' in Section 10.1 of Volume 1 of this handbook is the
rewrite-orthogonal portion of this proposition, which is also proved in [Huet
and Levy, 1991; Klop, 1991]. The proof for rewrite.-orthogonal systems has
never been published, but it is a straightforward generalization. [0 'Donnell,
1977] proves a version intermediate between rule-orthogonality and rewrite-
orthogonality.
In fact, for nontrivial, rule-like, left-linear systems, rule-nonambiguity
captures precisely the cases of confluence that depend only on the left-hand
sides of equations.
Proposition 2.3.15. A nontrivial, rule-like, left-linear set T of equations
is rule-nonambiguous if and only if, for every set of equations T' left-
similar to T, -> is confluent.
(=>) is a direct consequence of Propositions 2.3.14 and 2.3.12. (•=) is
straightforward. In a rule-ambiguous system, simply fill in each right-hand
88 Michael J. O'Donnell
side with a different constant symbol, not appearing on any left-hand side,
to get a nonconftuent system.
In the rest of this chapter, we use the term 'orthogonal' in assertions
that hold for both rewrite- and rule-orthogonality. To get a general un-
derstanding of orthogonality, and its connection to confluence, it is best
to consider examples of nonorthogonal systems and investigate why they
are not confluent, as well as a few examples of systems that are not rule
orthogonal, but are rewrite orthogonal, and therefore confluent.
Example 2.3.16. The first example, due to Klop [Klop, 1980], shows
the subtle way in which non-left-linear systems may fail to be confluent.
Let
eq represents an equality test, a very useful operation to define with a
non-left-linear equation. Now
and also
true is in normal form, and f(true) rewrites infinitely as
The system is not confluent, because the attempt to rewrite f(true) to true
yields an infinite regress with f(true) -4 eq(true,f(true)). Notice that -4
has unique normal forms. The failure of confluence involves a term with
a normal form, and an infinite term rewriting sequence from which that
normal form cannot be reached. Non-left-linear systems that satisfy the
other requirements of rule-orthogonality always have unique normal forms,
even when they fail to be confluent [Chew, 1981]. I conjecture that this
holds for rewrite-orthogonality as well.
A typical rewrite-ambiguous set of equations is
c represents a primitive sort of nondeterministic choice operator. T2 vio-
lates condition (4') because
but
Equational Logic Programming 89
-4 is not confluent, as c(a, b) -4 a by the first equation, and c(a, b) -4 b by
the second equation, but a and 6 are in normal form.
By contrast, consider the set
of equations defining the positive parallel or operator. Although Tor+ is
rule-ambiguous, it is rewhte-nonambiguous:
and w is not an instance of or(x, true), but the corresponding right-hand
sides are both true:
tor+ is rewrite-orthogonal, so -+ is confluent.
A more subtle example of a rewrite-orthogonal set of equations that is
rule-ambiguous is the negative parallel or:
Although
and w is not an instance of or(x, false), the substitution above unifies the
corresponding right-hand sides as well:
T—
Tor- is rewrite-orthogonal, so or-* is confluent.
Another type of rewrite-ambiguous set of equations is
These equations express the fact that / is a homomorphism for g (i.e., /
distributes over g), and that i is a left identity for g. The left-hand sides of
the two equations overlap in f ( g ( i , z ) ) , with the symbol g participating in
instances of the left-hand sides of both equations. Condition (4) is violated,
because
90 Michael J. O'Donnell
but f(w) is not an instance of f(g(x, y ) ) . —? is not confluent, as f ( g ( i , i)} -4
g ( f ( i ) , f ( i ) ) by the first equation, and f ( g ( i , i ) ) - f(i) by the second equa-
tion, but both g(f(i),f(i)) and f(i) are in normal form. While the previous
examples of ambiguity involved two rules applying to precisely the same
term, the ambiguity in T3 comes from two overlapping applications of
rules to a term and one of its subterms. Some definitions of orthogonal-
ity/regularity treat these two forms of ambiguity separately.
By contrast, consider the set
Although T4 is rule-ambiguous, it is rewrite-nonambiguous:
and f(w) is not an instance of f ( g ( x , y ) ) , but the corresponding right-hand
sides yield
T4 is rewrite-orthogonal, so -4 is confluent.
Condition (4) may also be violated by a single self-overlapping equation,
such as
The left-hand side f(f(x)) overlaps itself in f(f(f(x))), with the second
instance of the symbol / participating in two different instances of f ( f ( x ) ) .
Condition (4) is violated, because
T5 T5
but f(y) is not an instance of f(f(x)). - is not confluent, as f ( f ( f ( a ) ) ) —
g(f(a)) and f(f(f(a)))- f(g(a\)), but both g(f(a)) and f(g(a)) are in
normal form.
A final example of overlapping left-hand sides is
The left-hand sides of the two equations overlap in f(g(a, b ) , y ) , with the
symbol g participating in instances of the left-hand sides of both equations.
Condition (4) is violated, because
but f(w,y) is not an instance of f(g(a,x),y). - is not confluent, as
f ( g ( a , b ) , c ) - a by the first equation, and f ( g ( a , b ) , c ) - f ( b , c ) by the
second equation, but both a and f(b, c) are in normal form.
Equational Logic Programming 91
The equations for combinatory logic
are rule-orthogonal, but not constructor-orthogonal, since the symbol @
(standing for application of a function to an argument) appears leftmost
and also in the interior of left-hand sides. In more familiar notation, @(a, (3)
is written (a/3), and leftward parentheses are omitted, so the equations look
like
Many functional programming languages vary the definition of constructor-
orthogonality to allow pure applicative systems (the only symbol of arity
greater than zero is the apply symbol @) in which the zeroary symbols
(5 and K in the example above) are partitioned into defined symbols and
constructors.
The equations for addition of Horner-rule form polynomials in the sym-
bolic variable V (V is a variable in the polynomials, but is treated formally
as a constant symbol in the equations) are
This system is rule-orthogonal, but not constructor-orthogonal, because
the symbols + and * appear leftmost and also in the interior of left-hand
sides. In the more familiar infix form for -I- and *, the equations look like
No natural variation on the definition of constructor-orthogonality seems to
allow these equations. The only obvious way to simulate their behavior with
a constructor-orthogonal system is to use two different symbols for addition,
and two different symbols for multiplication, depending on whether the
operation is active in adding two polynomials, or is merely part of the
representation of a polynomial in Horner-rule form.
Although the polynomial example above shows that some natural sets of
equations are rule-orthogonal but not constructor-orthogonal, Thatte has
an automatic translation from rule-orthogonal to constructor-orthogonal
systems [Thatte, 1985] showing that in some sense the programming power
of the two classes of systems is the same. I still prefer to focus attention on
the more general forms of orthogonality, because they deal more directly
92 Michael J. O'Donnell
with the intuitive forms of equations, and because I believe that improved
equational logic programming languages of the future will deal with even
more general sets of equations, so I prefer to discourage dependence on the
special properties of constructor systems.
Knuth-Bendix Methods. Although overlapping left-hand sides of equa-
tions may destroy the confluence property, there are many useful equa-
tional programs that are confluent in spite of overlaps. In particular, the
equation expressing the associative property has a self-overlap, and equa-
tions expressing distributive or homomorphic properties often overlap with
those expressing identity, idempotence, cancellation, or other properties
that collapse a term. These overlaps are usually benign, and many useful
equational programs containing similar overlaps are in fact confluent.
Example 2.3.17. Consider the singleton set
expressing the associative law for the operator g. This equation has a self-
overlap, violating condition (4) of rewrite-orthogonality (Definition 2.3.9)
because
but the corresponding right-hand sides disagree:
by different applications of the equation, the two results rewrite to a com-
mon normal form by
and
Consider also the set
Equational Logic Programming 93
expressing the distribution of / over g, and the fact that i is a left identity
for g and a fixed point for /. The first and second equations overlap,
violating condition (4) of rewrite-orthogonality, because
but the corresponding right-hand sides disagree:
Nonetheless, -I is confluent. For example, while
by the first equation and
by the second equation, the first result rewrites to the second, which is in
normal form, by
Notice that T8 = T3 U {f(i) = i}, and that confluence failed for T3 (Ex-
ample 2.3.16).
Experience with equational logic programming suggests that most
naively written programs contain a small number of benign overlaps, which
are almost always similar to the examples above. An efficient test for con-
fluence in the presence of such overlaps would be extremely valuable.
The only known approach to proving confluence in spite of overlaps is
based on the Knuth-Bendix procedure [Knuth and Bendix, 1970]. This
procedure relies on the fact that local confluence (Definition 2.3.2) is often
easier to verify than confluence, and that local confluence plus termination
imply confluence.
Proposition 2.3.18 ([Newman, 1942]). // -» is locally confluent, and
there is no infinite sequence SQ -> si -*•••, then -»• is confluent.
The proof is a simple induction on the number of steps to normal form.
Unfortunately, a system with nonterminating rewriting sequences may
be locally confluent, but not confluent.
Example 2.3.19. T1 of Example 2.3.16 is locally confluent, but not
confluent.
94 Michael J. O'Donnell
Consider also the set of equations
-4 is locally confluent, but not confluent. Notice how confluence fails due
to the two-step rewritings a -4 b -4 d and b -4 a -4 c (see Figure 2).
Fig. 2. T9 is locally confluent, but not confluent.
Another example, without a rewriting loop, is the set of equations
-4° is locally confluent, but not confluent. Again, confluence fails due
to the two-step rewritings f ( x ) -4° g(h(x)) -4° d and g(x) -4° f ( h ( x ) ) -¥ c
(see Figure 3).
Fig. 3. T10 is locally confluent, but not confluent.
Equational Logic Programming 95
The Knuth-Bendix procedure examines overlaps one at a time to see
whether they destroy the local confluence property. Given a pair of equa-
tions l1 = r1 and l2 = r2 be such that their left-hand sides overlap)—i.e.,
there is a term s ^ y with one occurrence of y such that
but s is not an instance of l2. For each s, l1 and l2, use the smallest
t 1 ,...,t m and t(,..., t'n that satisfy this equation. The results of rewrit-
ing the instance of s above in two different ways, according to the over-
lapping instances of equations, are c1 = s[r 1 [t 1 , . . . , t m / x 1 , . . . , xm]/y] and
c2 = r^t'i,..., t'nl%\,..., x'n]. The pair (c1, c2) is called a critical pair. A
finite set of equations generates a finite set of critical pairs, since only a
finite number of ss can be compatible with some l2, but not an instance
of l2. The procedure checks all critical pairs to see if they rewrite to a
common normal form. If so, the system is locally confluent.
Proposition 2.3.20 ([Huet, 1980]). Let T be a set of equations. If for
every critical pair (c1,c2) of T there is a term d such that c\ -^* d and
c1 —t* d, then —t is locally confluent.
This proposition, and the Knuth-Bendix method, apply even to non-
left-linear sets of equations. For example, the local confluence of T1 in
Example 2.3.16 may be proved by inspecting all critical pairs.
When some critical pair cannot be rewritten to a common form, the
Knuth-Bendix procedure tries to add an equation to repair that failure
of local confluence. For equational logic programming, we would like
to use just the part of the procedure that checks local confluence, and
leave it to the programmer to decide how to repair a failure. Although,
in principle, the search for a common form for a critical pair might go
on forever, in practice a very shallow search suffices. I have never ob-
served a natural case in which more than two rewriting steps were in-
volved. Unfortunately, many useful equational programs have nontermi-
nating term rewriting sequences, so local confluence is not enough. The
design of a variant of the Knuth-Bendix procedure that is practically
useful for equational logic programming is an open topic of research—
some exploratory steps are described in [Chen and O'Donnell, 1991]. A
number of methods for proving termination are known [Dershowitz, 1987;
Guttag et al., 1983], which might be applied to portions of an equational
program even if the whole program is not terminating, but we have no
experience with the practical applicability of these methods. If the rewrit-
ing of the terms c1 and c2 in a critical pair to a common form d (see
Proposition 2.3.20) takes no more than one rewriting step (this is one-step
confluence, Definition 2.3.3), then we get confluence and not just local con-
fluence. Rewrite-orthogonal systems are those whose critical pairs are all
96 Michael J. O 'Donnell
trivial—the members of the pair are equal, and so the reduction to a com-
mon form takes zero steps. Unfortunately, all of the important examples so
far of confluent but not rewrite-orthogonal equational programs have the
basic structure of associativity or distributivity (see Example 2.3.17) and
require two rewriting steps to resolve their critical pairs.
The sets of equations in Example 2.3.17 pass the Knuth-Bendix test
for local confluence, and a number of well-known techniques can be used to
prove that there is no infinite term rewriting sequence in these systems.
But, we need to recognize many variations on these example systems,
when they are embedded in much larger sets of equations which gener-
ate some infinite term rewriting sequences, and no completely automated
method has yet shown practical success at that problem (although there are
special treatments of commutativity and associativity [Baird et al., 1989;
Dershowitz et al., 1983]). On the other hand, in practice naturally con-
structed systems of equations that are locally confluent are almost always
confluent. Surely someone will find a useful and efficient formal criterion
to distinguish the natural constructions from the pathological ones of Ex-
ample 2.3.19.
3 Term rewriting proof strategies
Given an orthogonal set of equations T = {/i = r i , . . . , lm = rm}, or any set
with confluent term rewriting relation —>, we may now answer all questions
of the form (norm l\,..., lm : t) by exploring term rewriting sequences
starting with t. Confluence guarantees that if there is an answer, some
term rewriting sequence will find it (Proposition 2.3.6). Furthermore, con-
fluence guarantees that no finite number of term rewriting steps can be
catastrophic, in the sense that if s -^* t and if s rewrites to a normal form,
then t rewrites to the same normal form. Confluence, however, does not
guarantee that no infinite term rewriting sequence can be catastrophic.
Example 3.0.1. Consider the set of equations
The first equation is the usual definition of the car (left projection) function
of Lisp, the second is a silly example of an equation leading to infinite
term rewriting. T11 is orthogonal, so -V is confluent. But car(cons(b,a))
rewrites to the normal form 6, and also in the infinite rewriting sequence
car(cons(b,a)) -¥ car(cons(b, f ( a ) ) ) -V
Notice that, due to confluence, no matter how far we go down the infi-
nite term rewriting sequence car (cons(b, a)) -V car(cons(b, f(a))) -V • • •,
one application of the first equation leads to the normal form b. Nonethe-
less, a naive strategy might fail to find that normal form by making an infi-
Equational Logic Programming 97
nite number of unfortunate rewrites. In fact, the usual recursive evaluation
techniques used in Lisp and other term-evaluating languages correspond to
term rewriting strategies that choose infinite sequences whenever possible.
A breadth-first search of all possible rewriting sequences is guaranteed to
find all normal forms, but at the cost of a lot of unnecessary work.
For efficient implementation of equational logic programming, we need
strategies for choosing term rewriting steps so that
• a small number of term rewriting sequences is explored, preferably
only one;
• if there is a normal form, it is found, preferably by the shortest or
cheapest sequence possible.
Some theoretical work on sequencing in the lambda calculus has already
been explored under the title of one-step strategies [Barendregt, 1984].
3.1 Complete and outermost complete rewriting se-
quences
In orthogonal systems of equations, there are two useful results on strate-
gies that are guaranteed to find normal forms. The formal notation for
stating these results precisely is somewhat involved (see the chapter 'Equa-
tional Reasoning and Term Rewriting Systems' in Volume 1), so I only
give rough definitions here. The concepts in this section can be extended
to nonorthogonal systems, but in some cases there are very subtle problems
in the extensions, and they have never been treated in the literature.
Definition 3.1.1 ([Huet and Levy, 1991]). A redex is an occurrence
of an instance of a left-hand side of an equation in a term. An outermost
redex is one that is not nested inside any other redex. When a is a redex in
s, and s -5-* t, the residuals of a in t are the redexes in t that correspond in
the obvious way to a in s—they are essentially explicit copies of a, except
that some rewriting step may have rewritten a subterm of a, so that some
copies may be modified. All residuals of a are occurrences of instances of
the same left-hand side as a.
Example 3.1.2. Consider the rule-orthogonal set of equations
The term g(f(f(h(a))), f(h(a))) has five redexes: two occurrences each of
the terms a and f(h(a)), and one occurrence of f(f(h(a))). The latter
two are both instances of the left-hand side f ( x ) of the first equation.
The leftmost occurrence of f(h(a)) is nested inside f(f(h(a))), so it is not
outermost. Each occurrence of a is nested inside an occurrence of f ( h ( a ) ) ,
so neither is outermost. The rightmost occurrence of f(h(a)), and the sole
occurrence of f(f(h(a))), are both outermost redexes. In the rewriting
98 Michael J. O'Donnell
sequence below, the leftmost occurrence of f ( h ( a ) ) , and its residuals in
each succeeding term, are boxed.
Notice how the leftmost occurrence of f ( h ( a ) ) in the first term of the
sequence is copied into two occurrences in the second, due to the rewriting
of a redex in which it is nested. The first of these is changed to f(h(b))
in the third term of the sequence, but it is still a residual of the original
leftmost f ( h ( a ) ) . In the fourth term of the sequence, f(h(b)) is rewritten,
eliminating one of the residuals. In the sixth term, the remaining residual,
still in the form f ( h ( a ) ) , is eliminated due to rewriting of a redex in which
it is nested. Another occurrence of f ( h ( a ) ) remains, but it is a residual of
the rightmost occurrence of that term in the first term of the sequence.
In general, a residual a of a redex is eliminated when a is rewritten (or,
in rewrite-orthogonal systems, when a redex overlapping a is rewritten). a
is copied zero, one, or more times (zero times eliminates the residual) when
another redex in which a is nested is rewritten, a remains the same when
another redex disjoint from a is rewritten. Finally, a is modified in form,
but remains an instance of the same left-hand side, when another redex
nested inside a is rewritten.
In orthogonal systems, the nontrivial, rule-like, and nonambiguous qual-
ities of equations (restrictions 1, 2, 4 or 4' of Definition 2.3.9 or 2.3.10) guar-
antee that a given redex may be rewritten in precisely one way. So, a term
rewriting strategy need only choose a redex to rewrite at each step. The
most obvious way to insure that all normal forms are found is to rewrite
every redex fairly.
Definition 3.1.3 ([O'Donnell, 1977]). A finite or infinite term rewriting
sequence to —>• t1 — ) • • • • is complete (also called fair) if and only if, for every
i and every redex a in ti, there exists a j > i such that tj contains no
residual of a.
A complete term rewriting sequence is fair to all redexes, in the sense
that every redex a (or its residuals, which are essentially the later versions
of the redex) eventually gets eliminated, either by rewriting a (with rewrite-
Equational Logic Programming 99
orthogonality, a redex overlapping a), or by making zero copies of a while
rewriting another redex in which a is nested. Complete term rewriting
sequences are maximal, in the sense that they produce terms that are
rewritten further than every other sequence. Since nothing is rewritten
further than a normal form, complete sequences produce a normal form
whenever there is one.
Proposition 3.1.4 ([O'Donnell, 1977]). Let T be an orthogonal set of
equations, let t0 ->• t1 -»• • • • be a complete rewriting sequence, and let s
be any term such that to —»•* s. There exists an i such that s —I* ti. In
particular, if s is in normal form, then ti = s.
Computing a single complete term rewriting sequence is generally
cheaper than searching breadth-first among a number of sequences, but
fair rewriting strategies (such as the strategy of adding new redexes to a
queue, and rewriting all residuals of the head redex in the queue) typically
perform a substantial number of superfluous rewriting steps, and can eas-
ily waste an exponentially growing amount of work in some cases. Since a
residual a of a redex may only be eliminated by rewriting a, or some redex
inside which a is nested, we need only be fair to the outermost redexes in
order to be sure of finding normal forms.
Definition 3.1.5 ([O'Donnell, 1977]). A finite or infinite term rewrit-
ing sequence to -> *i ->• • • • is outermost complete or outermost fair (called
eventually outermost in [O'Donnell, 1977]) if and only if, for every i and
every outermost redex a in ti, there exists a j > i such that the unique
residual of a in tj-1 is either eliminated by rewriting in tj, or is no longer
outermost in tj (equivalently, no residual of a is outermost in tj).
Since, for the least j satisfying the definition above, a remains outer-
most from ti through tj-1 and cannot be copied, there is no loss of gener-
ality in requiring the residual of a in tj-i to be unique.
Proposition 3.1.6 ([O'Donnell, 1977]). Let T be a rule-orthogonal
set of equations, let t0 -> <i -> • • • be an outermost complete rewriting se-
quence, and let s be a (unique) normal form for t0. There exists an i such
that ti = s.
[O'Donnell, 1977] proves this proposition for a form of orthogonality
intermediate between rule- and rewrite-orthogonality. I conjecture that the
proof generalizes to rewrite-orthogonality.
The requirement that T be orthogonal, and not just confluent, is essen-
tial to Proposition 3.1.6.
Example 3.1.7. Consider the set of equations
100 Michael J. O'Donnell
These equations are confluent, but not rewrite-orthogonal, since the left-
hand sides of the first and second equations overlap in f ( g ( x , b ) ) , but the
corresponding right-hand sides yield 6 ^ f ( g ( f ( x ) , b ) ) . The natural out-
ermost complete rewriting sequence starting with f(g(b, a)) is the infinite
one
But f(g(b, a)) rewrites to normal form by
The problem is that rewriting the nonoutermost redex a to b creates a
new outermost redex for the first equation above the previously outermost
one for the second equation. This leapfrogging effect allows an inner re-
dex to kill an outer one indirectly, by creating another redex even closer
to the root. There should be some interesting conditions, weaker than
rewrite-orthogonality, that prohibit this leapfrogging effect and guarantee
outermost termination for confluent systems.
The obvious way to generate outermost-complete rewriting sequences
is to alternate between finding all outermost redexes, and rewriting them
all. The order in which the outermost redexes are rewritten is irrelevant
since they are all disjoint and cannot cause copying or modification of one
another. Unfortunately, this strategy often generates a lot of wasted work.
For example, consider a system containing the equations Tcond for the
conditional function from Example 1.2.1
In a term of the form cond(r, s, t), there will usually be outermost redexes
in all three of r s and t. But, once r rewrites to either true or false, one of
s and t will be thrown away, and any rewriting in the discarded subterm
will be wasted. The ad hoc optimization of noticing when rewriting of one
outermost redex immediately causes another to be nonoutermost sounds
tempting, but it probably introduces more overhead in detecting such cases
than it saves in avoiding unnecessary steps. Notice that it will help the cond
example only when r rewrites to true or false in one step. So, we need
some further analysis to choose which among several outermost redexes to
rewrite.
3.2 Sequentiality analysis and optimal rewriting
For rewrite-orthogonal systems of equations in general, it is impossible to
choose reliably a redex that must be rewritten in order to reach normal
form, so that there is no risk of wasted work.
Equational Logic Programming 101
Example 3.2.1. Let Tc be equations defining some general-purpose
programming system, such as Lisp. The forms of the particular equations
in Tc are not important to this example, merely the fact that they are
powerful enough for general-purpose programming. Assume that in the
system Tc there is an effective way to choose a redex that must be rewritten
to reach normal form (this is the case for typical definitions of Lisp). Now,
add the positive parallel-or equations
and consider the system Tc U T or+.
For an arbitrary given term or(s, t), we would like to choose either
s or t to rewrite first. If s rewrites to true, but t does not, then it is
crucial to choose s, else work (possibly infinitely much work) will be wasted.
Similarly, if t rewrites to true, but s does not, it is crucial to choose t. If
neither s nor t rewrites to true, then both must be rewritten to normal
form in order to normalize the whole term, so we may choose either. If both
s and t rewrite to true then, ideally, we would like to choose the one that
is cheapest to rewrite, but suppose that we are satisfied with either choice
in this case also.
Suppose that we have an effective way to choose s or t above. Then,
we have a recursive separation of the terms or(s, t) in which s rewrites
to true and t has no normal form from those in which t rewrites to true
and s has no normal form. Such a separation is known to be impossible.
(It would lead easily to a computable solution of the halting problem. See
[Machtey and Young, 1978] for a discussion of recursive inseparability.) So,
we cannot decide effectively whether to rewrite redexes in s or in t without
risking wasted work.
The case where both s and t rewrite to true poses special conceptual
problems for sequentiality theory. Although it is necessary to rewrite one
of s or t in order to reach the normal form true, it is neither necessary to
rewrite s, nor necessary to rewrite t. The criterion of choosing a redex that
must be rewritten fails to even define a next rewriting step mathematically,
and the question of computability does not even arise. Notice that this
latter case is problematic for T or+ alone, without the addition of Tc.
The difficulty in Example 3.2.1 above appears to depend on the unifia-
bility of the left-hand sides of the two equations in T or+, which is allowed
in rewrite-orthogonal systems, but not rule-orthogonal systems. A more
subtle example, due to Huet and Levy, shows that rule-orthogonality is
still not sufficient for effective sequencing.
Example 3.2.2 ([Huet and Levy, 1991]). Replace the parallel-or
equations of Example 3.2.1 by the following:
102 Michael J. O'Donnell
and consider the system Tc U T14. Given a term of the form f ( r , s, t), we
cannot decide whether to rewrite redexes in r, in s, or in t without risking
wasted work, because we cannot separate computably the three cases
• r -t* a and s ->•* b
• r ->* b and t -»* a
• s -)•* a and t ->•* b
Unlike the parallel-or example, it is impossible for more than one of
these three cases to hold. There is always a mathematically well-defined
redex that must be rewritten in order to reach a normal form, and the
problem is entirely one of choosing such a redex effectively. In fact, for sets
T of equations such that T U T14 is terminating (every term has a normal
form), the choice of whether to rewrite r, s, or t in f(r, s, t) is effective, but
usually unacceptably inefficient.
So, some further analysis of the form of equations beyond checking for
orthogonality is required in order to choose a good redex to rewrite next
in a term rewriting sequence. Analysis of equations in order to determine
a good choice of redex is called sequentiality analysis.
3.2.1 Needed redexes and weak sequentiality
The essential ideas for sequentiality analysis in term rewriting are due to
Huet and Levy [Huet and Levy, 1991], based on a notion of sequential pred-
icate by Kahn [Kahn and Plotkin, 1978]. A redex that may be rewritten
without risk of wasted work is called a needed redex.
Definition 3.2.3 ([Huet and Levy, 1991]). Given an orthogonal set T
of equations and a term t0, a redex a in t0 is a needed redex if and only if,
for every term rewriting sequence to ->• t\ -^ • • • -> tm, either
• there exists an i, 1 < i < m such that a residual of a is rewritten in
the step ti-1 -> ti, or
• a has at least one residual in tm.
A needed redex is a redex whose residuals can never be completely elim-
inated by rewriting other redexes. So, the rewriting of a needed redex is
not wasted work, since at least one of its residuals has to be rewritten in
order to reach normal form. Huet and Levy defined needed redexes only for
terms with normal forms, but the generalization above is trivial. A system
is weakly sequential if there is always a needed redex to rewrite.
Definition 3.2.4. A rewrite-orthogonal set of equations is weakly se-
quential if and only if every term that is not in normal form contains at
least one needed redex. A set of equations is effectively weakly sequential
if and only if there is an effective procedure that finds a needed redex in
each term not in normal form.
Equational Logic Programming 103
The word 'sequential' above is conventional, but may be misleading to
those interested in parallel computation. A weakly sequential system is not
required to be computed sequentially—typically there is great opportunity
for parallel evaluation. Rather, a weakly sequential system allows sequen-
tial computation without risk of wasted rewriting work. In this respect
'sequentializable' would be a more enlightening word than 'sequential.'
The parallel-or system T or+ of Example 3.2.1 is rewrite-orthogonal,
but not weakly sequential, because the term
or(or (true, a), or(true, a))
has two redexes, neither of which is needed, since either can be elimi-
nated by rewriting the other, then rewriting the whole term to true. Rule-
orthogonality guarantees weak sequentiality.
Proposition 3.2.5 ([Huet and Levy, 1991]). A nontrivial, rule-like,
and left-linear set of equations (Definition 2.3.9) is weakly sequential if
and only if it is rule-orthogonal.
The proof of (•$=) is in [Huet and Levy, 1991]. It involves a search
through all rewriting sequences (including infinite ones), and does not yield
an effective procedure. (=*•) is straightforward, since when two redexes over-
lap neither is needed.
Proposition 3.2.5 above shows that no analysis based on weak sequen-
tiality can completely sequentialize systems whose confluence derives from
rewrite-orthogonality, or from a Knuth-Bendix analysis. Section 3.2.4 dis-
cusses possible extensions of sequentiality beyond rule-orthogonal systems.
The system Tc U T14 of Example 3.2.2 is rule-orthogonal, and therefore
weakly sequential. For example, in a term of the form f ( r , s, t), where
r —>* a and s —>•* b, both r and s contain needed redexes. The subsystem
T14, without the general-purpose programming system Tc, is effectively
weakly sequential, but only because it is terminating. I conjecture that
effective weak sequentiality is undecidable for rule-orthogonal systems.
3.2.2 Strongly needed redexes and strong sequentiality
The uncomputability of needed redexes and the weak sequential property
are addressed analogously to the uncomputability of confluence: by finding
efficiently computable sufficient conditions for a redex to be needed, and
for a system to be effectively weakly sequential. A natural approach is
to ignore right-hand sides of equations, and detect those cases of needed
redexes and effectively weakly sequential systems that are guaranteed by
the structure of the left-hand sides. To this end we define w-rewriting, in
which a redex is replaced by an arbitrary term.
Definition 3.2.6 ([Huet and Levy, 1991]). Let T = {l1 = r 1 , . . . ,
ln = rn} be a rule-orthogonal set of equations.
104 Michael J. O'Donnell
A term s1 w-rewrites to s2 by T (written s1 -^ s2) if and only if there
is a term t, a variable x with exactly one occurrence in t, an instance l\ of a
left-hand side li in T, and a term r such that s1 = t[^/x] and s2 = t[r/x].
That is, S2 results from finding exactly one instance of a left-hand side
of an equation in T occurring as a subterm of s1, and replacing it with
an arbitrary term. The definition of residual (Definition 3.1.1) generalizes
naturally to w-rewriting.
Now, a strongly needed redex is defined analogously to a needed redex,
using w-rewriting instead of rewriting.
Definition 3.2.7 ([Huet and Levy, 1991]). Given a rule-orthogonal set
T of equations and a term t0, a redex a in t0 is strongly needed if and only
if, for every w-rewriting sequence to -jf ti -&"•-$ tm, either
• there exists an i, 1 < i <m such that a residual of a is rewritten in
the step <i_i -^ ti, or
• a has at least one residual in tm.
Because of rule-orthogonality, the property of being strongly needed de-
pends only on the location of a redex occurrence, and not on its internal
structure. So, we call an arbitrary occurrence in a term strongly needed if
and only if a redex substituted in at that location is strongly needed. [Huet
and Levy, 1991] defines strong indexes, and shows that they determine ex-
actly the strongly needed redexes. It is easy to see that every strongly
needed redex is needed, and outermost. And, it is easy to detect whether
a given redex is strongly needed (see Section 4 and [Huet and Levy, 1991]).
A system of equations is strongly sequential if there is always a strongly
needed redex to be rewritten, except in a normal form term.
Definition 3.2.8 ([Huet and Levy, 1991]). A rule-orthogonal set of
equations is strongly sequential if and only if every term that is not in
normal form contains at least one strongly needed redex.
It is obvious that every strongly sequential system is effectively weakly
sequential, but the converse does not hold.
Example 3.2.9. The system T14 of Example 3.2.2, although it is effec-
tively weakly sequential, is not strongly sequential. f(f(a,b,c),f(a,b,c),
f ( a , b, c)) w-rewrites to f(f(a, b, c),a, b), which is a redex, so the first redex
f(a, b, c) is not strongly needed. Similarly, f(f(a, 6, c), f(a, 6, c), f(a, b, c))
w-rewrites to the redexes f ( b , f ( a , b, c), a) and f(a, 6, f(a, 6, c)), so the sec-
ond and third redexes are not strongly needed. All three redexes are weakly
needed.
By contrast, consider the strongly sequential system
Equational Logic Programming 105
In the term f ( g ( a , a), h(a, a)), the first and last occurrences of a are strongly
needed, but the second and third are not.
Notice that w-rewriting allows different redexes that are occurrences
of instances of the same left-hand side to be rewritten inconsistently in
different w-rewriting steps. Such inconsistency is critical to the example
above, where in one case f ( a , b, c) w-rewrites to a, and in another case it
w-rewrites to b.
Strong sequentiality is independent of the right-hand sides of equa-
tions.
Proposition 3.2.10. If T1 and T2 are left-similar (see Definition 2.3.11),
and T1 is strongly sequential, then so is T2.
The proof is straightforward, since T1 and T2 clearly have the same
<w-rewriting relations (Definition 3.2.6).
It is not true, however, that a system is strongly sequential whenever
all left-similar systems are weakly sequential. The system of Example 3.2.2
and all left-similar systems are weakly sequential, but not strongly sequen-
tial. But in that case, no given redex is needed in all of the left-similar
systems. An interesting open question is whether a redex that is needed in
all left-similar systems must be strongly needed.
For finite rule-orthogonal sets of equations, strong sequentiality is de-
cidable.
Proposition 3.2.11 ([Huet and Levy, 1991; Klop and Middeldorp,
1991]). Given a finite rule-orthogonal set T of equations, it is decidable
whether T is strongly sequential.
The details of the proof are quite tricky, but the essential idea is that
only a finite set of terms, with sizes limited by a function of the sizes of
left-hand sides of equations, need to be checked for strongly needed redexes.
In developing the concept of strongly needed redexes and connecting it
to the concept of weakly needed redexes, Huet and Levy define the inter-
mediately powerful concept of an index. Roughly, an index is a needed
redex that can be distinguished from other redexes just by their relative
positions in a term, without knowing the forms of the redexes themselves
[Huet and Levy, 1991]. Every index is a weakly needed redex, but not vice
versa. Strong indexes are equivalent to strongly needed redexes. A system
in which every term not in normal form has at least one index is called
sequential. The precise relation between sequentiality in all left-similar
systems, and strong sequentiality, is an interesting open problem.
All of the sequentiality theory discussed in this section deals with se-
quentializing the process of rewriting a term to normal form. Example 7.1.6
in Section 7.1 shows that even strongly sequential systems may require a
parallel evaluation strategy for other purposes, such as a complete proce-
dure for rewriting to head-normal form.
106 Michael J. O'Donnell
3.2.3 Optimal rewriting
Prom a naive point of view, the natural strategy of rewriting a strongly
needed redex at each step does not lead to minimal-length rewriting se-
quences ending in normal form. The problem is that the rewriting of a
strongly needed redex may cause another needed (but not strongly needed)
redex to be copied arbitrarily many times. Since strongly needed redexes
are always outermost, they are particularly likely to cause such copying.
Example 3.2.12. In the strongly sequential system of equations
given the initial term f(f(a)), both redexes, f(f(a)) and f(a), are needed,
but only the outermost one is strongly needed. By rewriting a strongly
needed redex at each step, we get the 3-step sequence
But, there is a 2-step sequence
which does not rewrite the unique strongly needed redex in the first step.
It is easy to construct further examples in which the number of steps
wasted by rewriting strongly needed redexes is arbitrarily large.
Proposition 3.2.13. Given an arbitrary strongly sequential system of
equations, and a term, there is no effective procedure to choose a redex at
each step so as to minimize the length of the rewriting sequence to normal
form.
I am not aware of a treatment of this point in the literature. The basic
idea is to use the equations
similar to T16 of Example 3.2.12, and add additional equations to define h
as the evaluator for Lisp or some other general-purpose computing system.
Now, start with a term of the form f(a, p), where p is an arbitrary program.
If evaluation of p halts with value 0 (that is, if h(p) rewrites to 0), then
an optimal rewriting sequence rewrites f(a, p) to g(a, a, h(p)) in the first
step, and never rewrites the occurrences of a. If evaluation of p halts with
any value other than 0, then an optimal sequence rewrites a to 6 in the
first step (else it must be rewritten twice later). An effective method for
choosing the first step would yield a recursive separation of the programs
that halt with output 0 from those that halt with output 1, which is known
to be impossible [Machtey and Young, 1978].
Equational Logic Programming 107
Notice that, when there is a normal form, breadth-first search over all
rewriting sequences yields a very expensive computation of a minimal se-
quence. But, no effective procedure can choose some redex in all cases (even
in the absence of a normal form), and minimize the number of rewriting
steps when there is a normal form.
The uncomputability of minimal-length rewriting strategies in Propo-
sition 3.2.13 sounds discouraging. The number of rewriting steps is not,
however, a good practical measure of the efficiency of a sequencing strat-
egy. Given equations, such as f ( x ) = g(x, x) in Example 3.2.12, with more
than one occurrence of the same variable x on the right-hand side, normal
sensible implementations do not make multiple copies of the subterm sub-
stituted for that variable. Rather, they use multiple pointers to a single
copy. Then, only one actual computing step is required to rewrite all of
the apparent multiple copies of a redex within that substituted subterm.
So, in Example 3.2.12, the strategy of choosing a strongly needed redex
actually leads to only two steps, from f(f(a)) to g ( f ( a ) , f ( a ) ) , and then
directly to g(g(a,a),g(a,a)). The normal form is represented in practice
with only one copy of the subterm g(a, a), and two pointers to it for the
two arguments of the outermost g. If we charge only one step for rewriting
a whole set of shared redexes, then rewriting strongly needed redexes is
optimal.
Proposition 3.2.14. Consider multiple-rewriting sequences, in which in
one step all of the shared copies of a redex are rewritten simultaneously.
Given a strongly sequential set of equations and a term, the strategy of
rewriting at each step a strongly needed redex and all of its shared copies
leads to normal form in a minimal number of steps.
This proposition has never been completely proved in print. I claimed
a proof [O'Donnell, 1977] but had a fatal error [Berry and Levy, 1979;
O'Donnell, 1979]. The hard part of the proposition—that the rewriting
of a strongly needed redex is never a wasted step—was proved by Huet
and Levy [Huet and Le"vy, 1991]. The remaining point—that rewriting a
strongly needed redex never causes additional rewriting work later in the
sequence—seems obvious, but has never been treated formally in general.
Levy [Levy, 1978] treated a similar situation in the lambda calculus, but
in that case there is no known efficient implementation technique for the
sequences used in the optimality proof. Although the formal literature on
optimal rewriting is still incomplete, and extensions of optimality theory to
systems (such as the lambda calculus) with bound variables are extremely
subtle, for most practical purposes Huet's and Levy's work justifies the
strategy of rewriting all shared copies of a strongly needed redex at each
step. Optimality aside, rewriting strategies that always choose a strongly
needed redex are examples of one-step normalizing strategies, which pro-
vide interesting theoretical problems in combinatory logic and the lambda
108 Michael J. O'Donnell
calculus [Barendregt, 1984].
3.2.4 Extensions to sequentiality analysis
Proposition 3.2.5 seems to invalidate rewrite-orthogonal systems for effi-
cient or optimal sequential rewriting. A closer look shows that the defini-
tion of weakly needed redexes and weak sequentiality is inappropriate for
rewrite-orthogonal systems. When two redexes from a rewrite-orthogonal
system overlap, we get the same result by rewriting either one. So, there is
no need for a sequential strategy to choose between them, and we might as
well allow an arbitrary selection. This observation suggests a more liberal
concept of needed redex.
Definition 3.2.15. Given a rewrite-orthogonal set T of equations and a
term to, a redex a in t0 is a rewrite-needed redex if and only if, for every
term rewriting sequence to —> ti — > • • • — » • t m , either
• there exists an i, 1 < i < m such that a residual of a is rewritten in
T
the step ti-1 —> ti, or
• there exists an i, 1 < i < m such that a redex overlapping a residual
T
of a is rewritten in the step ti-1 —*• ti, or
• a has at least one residual in tm.
This is the same as Definition 3.2.3 of needed redex, except that when one
redex is reduced, we give credit to all redexes that overlap it. We generalize
Definition 3.2.4 with the new version of needed redexes.
Definition 3.2.16. An orthogonal set of equations is weakly rewrite-
sequential if and only if every term that is not in normal form contains
at least one rewrite-needed redex. A set of equations is effectively weakly
rewrite-sequential if and only if there is an effective procedure that finds a
rewrite-needed redex in each term not in normal form.
Three sorts of overlaps between left-hand sides of equations have dif-
ferent impacts on weak rewrite-sequentiality. Recall (Definition 2.3.9) that
the problematic overlaps occur when there is a term s, and left-hand sides
l1 and l1,-, such that
Rewrite-nonambiguity requires that either s is an instance of lj, or the
corresponding right-hand sides ri and rj satisfy
1. Sometimes the structure of the inner term li is entirely subsumed
by the structure of the outer term lj—that is, the substituted terms
t,...,t'n are trivial, and
Equational Logic Programming 109
In this case, the equation lj = rj is redundant, since every possible
application of it can be accomplished by applying li = ri instead.
2. Sometimes the structure of the inner term li extends below the struc-
ture of the outer term lj—that is, the substituted terms ti,...,tm
are trivial, and
Overlaps of this sort appear not to destroy weak rewrite-sequentiality.
3. Otherwise, neither set of substituted terms t1,... , tm nor t^,..., t'n is
trivial. This is the interesting case. Weak rewrite-sequentiality may
hold or not, depending on the extent to which redexes in substituted
subterms are copied or eliminated by the right-hand sides.
Figure 4 illustrates the three types of overlap with suggestive pictures.
Example 3.2.17. Consider the set
The overlap here is of type 1, since
The first equation is redundant since it is essentially a special case of the
second.
Next, consider
T19 = {f(g(x), a) = f(x, a), g(h(x)) = h(x)}
110 Michael J. O'Donnell
The overlap here is of type 2, since
T19 is weakly rewrite-sequential. In a term of the form f ( s , t ) , in which
s -¥ g(h(s')) and also t -¥ a, it is always safe to rewrite t first, since by
rewriting s to g(h(s')) and then rewriting this to h(s'), we cannot eliminate
the redexes in t.
Now, consider
The overlap here is of type 3, since
is the smallest substitution showing the overlap, and neither substitution
is trivial. T20 is not weakly rewrite-sequential, since the term f ( g ( g ( a , a ) ,
g(a, a))) has the two rewrite sequences
which shows that the rightmost occurrence of g(a, a) is not needed and
which shows that the leftmost occurrence of g(a, a) is not needed.
Modify the previous example slightly, by changing the right-hand sides:
The result is still a type 3 overlap, but the system is weakly rewrite-
sequential, since the redexes that are not needed immediately in the cre-
ation of an outer redex are preserved for later rewriting.
The positive parallel-or equations in Tor+ of Examples 2.3.16 and 3.2.1
give another example of a type 3 overlap where weak rewrite-sequentiality
fails. On the other hand, the negative parallel-or equations of Tor- in
Example 2.3.16 have type 2 overlap, but they are sequential. In a term
T T _
of the form or(s,t) where s -3-~ false and t -3T false, it is safe to rewrite
either s or t first, since the redexes in the other, unrewritten, subterm are
preserved for later rewriting.
Theories extending sequentiality analysis, through concepts such as
weak rewrite-sequentiality, are open topics for research. I conjecture that
Equational Logic Programming 111
weak rewrite-sequentiality is an undecidable property of rewrite-orthogonal
systems, and that the natural concept of strong rewrite-sequentiality has
essentially the same properties as strong sequentiality, except for allow-
ing type 2 overlaps. Optimality is very subtle in these extensions, since
the amount of sharing may vary depending on which of two overlapping
redexes is reduced. More interesting and powerful extensions of sequential-
ity will require analysis of right-hand sides to deal with type 3 overlaps.
Such analysis should be related in interesting ways to strictness analysis in
functional programming languages [Mycroft, 1980; Hughes, 1985b] , which
detects partial strictness properties of defined functions. Abstract interpre-
tation [Abramsky and Hankin, 1987; Cousot and Cousot, 1977] provides a
promising approach to sequentiality analysis based on right-hand sides.
Extensions of useful sequentiality analysis to systems whose confluence
is established by variations on the Knuth-Bendix procedure will require
the concept of residual to be generalized so that the residual of a redex a
may be an arbitrarily long rewriting sequence used in resolving a critical
pair involving a. Variations on sequentiality analysis for incremental and
parallel implementations of equational logic programming are discussed in
Sections 6 and 7, respectively.
4 Algorithms and data structures to implement
equational languages
The basic idea of implementing equational logic programming for strongly
sequential systems is straightforward. Represent terms as linked structures
with sharing, in the time-honored style of Lisp [McCarthy et al., 1965;
McCarthy, 1960]. At every step, find a strongly needed redex and rewrite
it, halting if and when the sequence ends with a normal form. A lot of work
is required to reduce these basic ideas to efficient practice. At the abstract
level of algorithm and data-structure design, the problem breaks naturally
into three components: a data structure to represent terms, a pattern-
matching and sequencing algorithm to find strongly needed redexes, and
a driving procedure to invoke the pattern-matcher/sequencer, perform the
chosen rewrites, and incorporate the results into the term data structure.
4.1 Data structures to represent terms
The natural data structure for terms is a linked structure in a heap, with
sharing allowed. Each occurrence of a symbol / in a term is represented by
a node of storage containing / and pointers to its arguments. Sharing is
accomplished by allowing several different argument pointers to point to the
same node. There are a number of optimizations that coalesce small nodes,
or break large nodes into linked sequences, that have been explored in the
literature on Lisp compilers [Bobrow and Clark, 1979]. In this section, we
consider data structures at an abstract level with precisely one symbol per
112 Michael J. O'Donnell
heap node, and assume that such optimizations are applied at a lower level
of implementation.
4.1.1 A conceptual model for term data structures
Some useful techniques for implementing equational logic programming
require more than the linked heap structures representing terms. For ex-
ample, it is sometimes better to represent the rewriting of s to t by a link
from the head node of the representation of s pointing to the head node
of t, rather than by an actual replacement of s by t. This representation
still uses a heap, but the heap now represents a portion of the infinite
rewriting graph for a starting term, rather than just a single term at some
intermediate stage in rewriting to normal form. Other techniques involve
the memoing of intermediate steps to avoid recomputation—these require
more efficient table lookup than may be achieved with a linked heap. For-
tunately, there is a single abstract data structure that subsumes all of the
major proposals as special cases, and which allows a nice logical interpre-
tation [Sherman, 1990]. This data structure is best understood in terms of
three tables representing three special sorts of functions.
Definition 4.1.1. For each i > 0 let Funi be a countably infinite set of
function symbols of arity i. The 0-ary function symbols in Fun0 are called
constant symbols. T°P is the set of ground terms (terms without variables)
constructed from the given function symbols (see Definition 2.3.1 of the
chapter 'Introduction: Logic and Logic Programming Languages'). Let P
be a countably infinite set. Members of P are called parameters, and are
written a, /?,..., sometimes with subscripts. Formally, parameters behave
just like the variables of Definition 2.3.1, but their close association with
heap addresses later on makes us think of them somewhat differently.
An i-ary signature is a member of Funi x Pi. The signature (/, ( a 1 , . . . ,
ai)), is normally denoted by f ( a 1 , . . . , ai). Sig denotes the set of signatures
of all arities.
Let nil be a symbol distinct from all function symbols, parameters, and
signatures.
A parameter valuation is a function val: P —> Sig U {nil}.
A parameter replacement is a function repl: P -» P U {nil}.
A signature index is a function ind : Sig —>• P U {nil}.
A parameter valuation, parameter replacement, or signature index is
finitely based if and only if its value is nil for all but a finite number of
arguments.
The conventional representation of a term by a linked structure in a
heap may be understood naturally as a table representing a finitely based
parameter valuation. The parameters are the heap addresses, and the
signatures are the possible values for data nodes. val(a) is the signature
stored at address a. But, we may also think of parameters as additional
Equational Logic Programming 113
Table 1. Parameter valuation representing f(g(a, f(a, a)), f(a, a)).
Fig. 5. Linked structure representing f(g(a, f(a, a)), f(a, a)).
0-ary symbols, of signatures as terms of height 1 built from parameters,
and of the function val as a set of formulae asserting equalities between
parameters and signatures. Each value val(a) = /(/?1,..., &) ^ nil of the
valuation function represents the formula a = f(01, • • • , Ai). When val
represents the contents of a heap with the head symbol of a term t stored at
address a, then a = t is a logical consequence of the equations represented
by val.
Example 4.1.2. Consider the finitely based parameter valuation val given
by Table 1. All values of val not shown in the tables are nil. The linked
heap structure associated with val is shown in Figure 5. The set of equa-
tions represented by val is
Logical consequences of these equations include a2 = f(a, a), a1 = g(a,
f(a,a)), and «0 = f(g(a, f(a, a)), f(a,a)).
It is useful to have a notation for the term represented explicitly by a
parameter valuation at a particular parameter.
114 Michael J. O'Donnell
Definition 4.1.3. Let val be a parameter valuation. The partial function
val* : P —> Tp is defined inductively by
when val(a) = f ( 0 1 , . . . , /?i). Notice that the case where / is a constant
symbol, and therefore i = 0, provides a basis for the inductive definition. If
a value of nil is encountered anywhere in the induction, or if the induction
fails to terminate because of a loop, val* is undefined.
When val* (a) is well-defined, the equation a = val* (a) is always a
logical consequence of the equations represented by val.
Optimized implementations of equational logic programming languages
sometimes find it more efficient to link together nodes representing left-
and right-hand sides of equations, rather than to actually perform rewrit-
ing steps. Such linking can be implemented by an additional pointer in
each node of a heap structure. The information in these links is natu-
rally represented by a parameter replacement function. Given a set T
of equations, it first appears that we should think of the function repl
as a set of formulae asserting that one term rewrites to another—that is,
repl(a) = ft ^ nil represents the formula val* (a) -^* val*(/3). But further
rewriting steps on subterms of the term represented by a may invalidate
such a relation. There are also implementations that make efficient use
of data structures for which val* is ill defined. So, the proper logical in-
terpretation of repl(a) = 0 as a formula is merely a = /3. An efficient
implementation manipulates val and repl so that /? is in some way a bet-
ter starting point for further rewriting than a. The precise sense in which
it is better varies among different implementations. val and repl together
yield a set of terms for each parameter, all of which are known to be equal.
The set val*repl(a) defined below is the set of terms that may be read by
starting at a and following links in val and repl.
Definition 4.1.4. Let val be a parameter valuation and let repl be a
parameter replacement. The function val*repl : P ->• 2Tp is defined so that
val*repl(a) is the least set satisfying
In the presence of loops, val*repl(a) may be infinite. Even without loops,
its size may be exponential in the size of the data structure representing
val and repl. The power of such data structures derives from this ability
to represent large sets of equivalent terms compactly. When val* (a) is
well defined, val* (a) € val*repl(a). Another special member of val*repl(a)
Equational Logic Programming 115
Table 2. Parameter valuation and replacement.
is particularly interesting—the one reached by following repl links as much
as possible.
Definition 4.1.5. Let val be a parameter valuation and let repl be a
parameter replacement. The partial function valrepl™^ : P —>• Tp is defined
inductively by
when repl(a) ^ nil.
when repl(a) = nil and val(a) = f(A1,• • •, Ai)- As with val*, valrepl™"*, is
undefined if nil is encountered as a value of val, or if the induction fails
to terminate because of a loop.
Example 4.1.6. Consider the finitely based parameter valuation val
and parameter replacement repl given by Table 2. All values of val and
repl not shown in the tables are nil. These tables represent some of the
consequences of the equations
when used to rewrite the term f ( f ( a , b ) , b ) The linked heap structure as-
sociated with val and repl is shown in Figure 6. The rightmost link in
each node a points to repl(a). By following links from a0 in the table we
can construct the six ground terms in val*repl(ao): val*(ao) = f(f(a, b), b),
f(f(a,b),c), f(f(a,c), b), f ( f ( a , c ) , c ) , g(a,b), and valrepl^l^o) = g(a,c).
Every equality between these terms is a logical consequence of T22, and
all of these equalities may be read immediately from the data structure by
following links from a0.
A prime weakness of data structures based on parameter valuations
and replacements is that both functions require a parameter as argument.
Given a newly constructed signature, there is no direct way, other than
116 Michael J. O'Donnell
Fig. 6. Linked structure showing val and repl links.
searching through the parameter valuation, to discover whether informa-
tion on that signature is already available. Signature indexes are intended
precisely to allow a newly constructed signature to be translated to an
equivalent parameter. While finitely based parameter valuations and re-
placements are normally implemented by direct memory access, using pa-
rameters as addresses, the number of possible signatures is generally too
great to allow such an implementation of a finitely based signature index.
General-purpose table-look-up methods are used instead, usually hash ta-
bles [Knuth, 1973]. A typical application of a hash-table representation of
a signature index is the hashed cons optimization in Lisp [Spitzen et al.,
1978], where every newly constructed node is looked up in a hash table to
see whether it already exists in the heap—if it does the existing node may be
shared instead of creating another copy in the heap. The most obvious use
of a signature index ind, such as the hashed cons application, requires that
whenever ind(f(/31,... ,&i)) = a ^ nil, then val(a) = f(/?1,... ,&i); that
is, val is a partial inverse to ind. It may be advantageous in some cases to
let ind(f(/31,...,/%i)) be a parameter known to be equal to /(/?i,. • • ,/?i).
The proper logical interpretation of ind(f(/?1,..., &i)) = a ^ nil is merely
the formula f(/?i,..., $i) = a. So, ind provides the same type of logical in-
formation as val, but allows access to that information through a signature
argument, instead of a parameter argument.
Equational Logic Programming 117
4.1.2 Logical interpretation of term data structures
Each point in the graph of a parameter valuation val, a parameter re-
placement repl, and a signature index ind represents an equation. An
entire data structure consisting of finitely based functions val, repl, and
ind represents a suitably quantified conjunction of these equations. For
definiteness, suppose that inputs and outputs are rooted at the parameter
a0- Then the logical meaning of val, repl, and ind is the conjunction of all
their equations, with all parameters except a0 existentially quantified.
Definition 4.1.7. Let val, repl, ind be a parameter valuation, a parame-
ter replacement, and a signature index, respectively, all three finitely based.
Let a 1 , . . . , an be all of the parameters J3 occurring in the finite basis of the
domain of val or of repl (val(B) = nil or repl(B) = nil), or in the range of
repl, or as a component of a signature in the finite basis of the domain of
ind or in the range of val, except for the input/output parameter a0- The
logical interpretation of val, repl, ind is the formulaFval,repl,inddefined
by
where G is the conjunction of all the equations
Example 4.1.8. Consider the finitely based parameter valuation val and
parameter replacement repl discussed in Example 4.1.6, and shown in Ta-
ble 2 and Figure 6. If a0 is the parameter used for the root of the input
and output, then the logical interpretation of val and repl is
The interpretation of parameter valuations, parameter replacements,
and signature indexes as encodings of existentially quantified conjunctions
of equations makes it much easier to insure correctness of proposed algo-
rithms for manipulating data structures based on these functions. The
essential idea is that a transformation of a data structure from a state
representing val0, repl0, ind0 to one representing val1, repll ind1 in the
computation of an equational program T is logically permissible if and only
if the formula represented by val1, repl1, ind1 is a logical consequence of
T plus the formula represented by val0, repl0, ind0. So, an evaluation
algorithm may take input s, start in a state where valmax(a0) = s, and ap-
ply permissible transformations to reach a state where t € valmaxrepl(a0), for
some normal form t. The permissibility of the transformations guarantees
that t is a correct answer.
118 Michael J. O'Donnell
The interpretation of the term data structures as sets of formulae applies
the concepts of logic programming to the implementation of a logic pro-
gramming language. A similar use of logical concepts within the implemen-
tation of a logic programming language occurs in recent presentations of
unification algorithms (used in the implementation of Prolog) as processes
that derive solutions to equations, where every intermediate step repre-
sents a new and simpler set of equations to be solved [Kapur et al., 1982;
Martelli and Montanari, 1976]. The view of unification as transformation
of equations to be solved clarifies the correctness of a number of clever and
efficient algorithmic techniques.
Similarly, the logical view of term data structures shows immediately
that a wide range of transformations of such data structures are correct,
leaving an implementer free to choose the ones that appear to be most
efficient. In order to represent new terms during a computation, we must
be careful not to introduce spurious information about the input/output
parameter a0, nor to postulate the solvability of nontrivial equations. The
concept of reachability, defined below, may be used to enforce both of these
conditions.
Definition 4.1.9. The set of parameters reachable from a given param-
eter a is defined inductively by
1. a is reachable from a
2. If 0 is reachable from a, and one of the following holds as well
then 7 is reachable from a
Permissible transformations include
1. Building new terms: when a is not reachable from any of a0, B1,..., Bi,
reassign val(a) := f ( B 1 , . . . , Bi). (This allows both bottom-up and
top-down construction of directed-acyclic representations of terms,
using names completely unconnected to a0. More liberal conditions
than the unreachability of a from a0, B 1 , . . . , Bi are possible, but they
are somewhat complex to define.)
2. Representing rewriting in repl: when some s 6 val*repl(a) rewrites
to some t,E val*repl(B), reassign repl(a) := B.
3. Rewriting in val: when repl(a) = nil,
reassign val(a) := val(repl(a)).
Equational Logic Programming 119
4. Compressing paths in repl: when repl(repl(a)) = nil,
reassign repl(a) := repl(repl(a)).
5. Rewriting arguments in val: when val(a) = f(B1,..., Bi) and
repl(Bj) = nil, reassign val(a) := f(B1,..., repl(Bj),..., Bi).
6. Opportunistic sharing: when ind(val(a)) = nil, a,
reassign repl(a) := ind(val(a))
7. Indexing: when val(a) = f(B1,..., Bi),
reassign ind(f(B1,..., Bi)) := a.
8. Garbage collecting: reassign val(a) := nil, and/or repl(a) := nil,
and/or ind(f(...)) := nil. (This is always permissible, because it
only erases assertions. It is desirable only when the information re-
moved is not useful for the remainder of the computation.)
A straightforward evaluator scans valmaxrepl (a0) to find an instance of a left-
hand side s of an equation rooted at some node 0, uses transformation 1
repeatedly to build a copy of the corresponding right-hand side t in free
nodes rooted at 7, then links B to r by transformation 2. Transformations
3-5 allow the same term valmaxrepl(a0) to be scanned more efficiently, by
reducing the number of repl links that must be followed. Transformations
6 and 7 are used for optimizations such as hashed cons, congruence closure,
and memo functions to avoid re-evaluating the same subterm when it is
constructed repeatedly in a computation. Section 4.3 discusses several
optimizations using transformations 3-7.
The existential quantification of all parameters other than a0 is re-
quired for the logical correctness of transformation 1 (term building), which
changes the meaning of some existentially quantified parameter, without
affecting any assertion about a0. 2-8 are permissible independent of the
quantification. Notice that only transformation 2 depends on the given
equational program, and only 2 adds information to the data structure. 1
is needed to build new terms required by 2, but by itself 1 does not change
the logical assertions about a0. 3-8 can only reduce the information given
by val and repl, but they may improve the efficiency of access to infor-
mation that is retained. 3-7 never changevalmaxrepl(a0).Transformation 8
is normally applied only to nodes that are inaccessible from a0, in which
case 8 also preserves valmaxrepl(a0).
The logical interpretation introduced in Definition 4.1.7 seems to be
the most natural one for explaining currently known techniques for imple-
menting equational logic programming, but others are possible, and might
lead to useful extensions of, or variations on, the current sort of equa-
tional logic programming. Let a1,..., an be all of the parameters used in
val, repl, ind, other than the input/output parameter a0, and let G be
the conjunction of all the equations represented by points in the graphs
of val, repl, ind, just as in Definition 4.1.7. Two other interesting logical
interpretations worthy of study are
120 Michael J. O'Donndl
The first proposal above allows introduction of arbitrary structures not
connected to the input/output variable a0. The second one allows for
solution of equations, where every solution to the output is guaranteed to
be a solution to the input problem as well.
4.2 Pattern-matching and sequencing methods
Given a representation of a term, the implementation of an equational
logic program must perform pattern-matching to discover instances of left-
hand sides of equations that may be rewritten, and must apply sequencing
techniques to determine which of several such redexes to rewrite. These
two conceptual tasks appear to be inextricably connected, so it is best to
provide a single procedure to do both—that is, to find the next appropriate
redex to rewrite in a given term. In order to find and choose a redex
in a term, a procedure traverses the term until it has gathered enough
information about the symbols in the term to make its choice. The full
details of pattern-matching and sequencing methods are too long for this
chapter. So, I describe two basic approaches to the problem and illustrate
them by examples. The reader who needs more detail should consult [Huet
and Levy, 1991; Hoffmann and O'Donnell, 1979; Hoffmann et al., 1985;
O'Donnell, 1985; Klop, 1991; Klop and Middeldorp, 1991].
4.2.1 Representing sequencing information by A-terms
A natural way to represent partial information about a term is to present
the known structure as a term, with a special symbol (ft) representing
unknown portions.
Definition 4.2.1. The set Tp of A-terms is defined in the same way as
the set Tp of terms (Definition 2.3.1 of the chapter 'Introduction: Logic
and Logic Programming Languages'), except the new constant ft is added
to the set Fun0 of symbols of arity 0.
An A-term s is less defined than an A-term t, written s C t, if and only
if s is the result of replacing zero or more subterms of t by ft.
s n t denotes the greatest lower bound of s and t.
When A-terms s and t have a common upper bound (that is, when
there is a u such that s C u and t C u), we write s f t.
The A in an A-term behaves formally much like a variable, except that
each occurrence of the same symbol ft is treated as a unique variable,
occurring only at that location.
There is an elegant and simple procedure, called melting, for computing
all of the possible effects of w-rewriting on an A-term.
Definition 4.2.2. The function patt : TP -» Tp is defined by
Equational Logic Programming 121
where x1,..., xm are all of the variables occurring in t.
Extend patt to sets of equations T = {l1 = r1, . . . , ln = rn} by
Given a set T of equations, and an A-term s E Tp, s is transformed into
meltTW(s) by the following extremely simple polynomial-time procedure:
1. If s = t[u/x], where u=Aand u | p for some p (E patt(T), then re-
place s by t[A/x\.
2. Repeat (1) above until it is not applicable.
If s is an A-term representing current information about a term t that we
are rewriting to normal form, then meltTW(s) represents precisely the in-
formation in s that is guaranteed to hold for all t' such that t ^* t'. By
marking an occurrence with a new inert symbol, and melting, we can deter-
mine whether w-rewriting may eliminate that occurrence without rewriting
it—that is, we determine whether the occurrence is strongly needed.
Proposition 4.2.3. Let s be an A-term, and let a be an occurrence in
s. Let s' be the result of replacing a in s with a new constant symbol, •. a
is strongly needed if and only if meltTW(s) contains an occurrence of •.
Huet and Levy [Huet and Levy, 1991] propose a pattern-matching and
sequencing technique that accumulates an A-term sa (initially just A),
representing information about the subterm at a particular node a in a
term t. At each step, they choose a strongly needed occurrence of A in
sa, and extend sa by reading the symbol at the corresponding subterm
occurrence in t. The information in sa may be used to control pattern-
matching and sequencing as follows:
1. If there is a pattern p E patt(T) such that p C sa, then a is a redex
occurrence (in strongly sequential systems we always get sa = p, but
it is better to think of the more general case).
2. If there is no pattern p E patt(T) such that sa t p, then a is not
currently a redex occurrence.
3. If meltTW(sa) = A, then a will never be a redex occurrence.
4. It is safe to query the symbol in t corresponding to a strongly needed
occurrence of A in sa, and to rewrite any redex occurring there, since
it must be strongly needed.
In cases 2 and 3, Huet and Levy move to a proper descendant a' of a corre-
sponding to the largest subterm s' of sa, containing the newly read symbol,
such that s' t p for some p E patt(T) (because of strong sequentiality, in
fact s' C p). Then they let sa' = s' and proceed at a'. In case 1, the fact
that we have reached a by safe moves implies that the redex is strongly
122 Michael J. O'Donnell
Fig. 7. Pictures of terms for sequencing example
needed. So, they rewrite, and continue processing at an appropriate ances-
tor of a, rereading whatever symbols have been changed by rewriting at a.
Example 4.2.4. Consider the strongly sequential system
and search for a strongly needed redex in the term
with occurrences A (the root), 1 (leftmost 6), 2 (f(f(b, b), f ( b , f(f(b, b), b)))),
2.1 (leftmost f(b, b)), 2.1.1, 2.1.2 (second and third bs), 2.2 (f(b, f(f(b, b), b))).
2.2.1 (fourth b), 2.2.2 (f(f(b,b),b)), 2.2.2.1 (rightmost f(b,b)), 2.2.2.1.1,
2.2.2.1.2, 2.2.2.2 (fifth, sixth and seventh bs). The pattern f(A, f(f(A, a), a)),
and the term t, are shown pictorially in Figure 7. The occurrence of A cho-
sen for expansion at each step is underlined, and the subterm replacing it
is shown in a box.
• Start at the root of t, with SA = Q.
* There is only one choice, so read the / at the root, and expand
to sA = f/(n,n) -
* Only the rightmost n is strongly needed, so read the correspond-
ing symbol, and expand to SA = f(n, f(£l,Q) )-
Equational Logic Programming 123
* Only the rightmost fi is strongly needed, so expand to
* The new fl-term is incompatible with left-hand side patterns
(the / conflicts with an a in the pattern), so we find the largest
subterm containing the box that is compatible with a pattern.
That subterm is the second principal subterm at 2,
• Now process the second principal subterm of t,
* Only the rightmost fl is strongly needed, so expand to
* The new ft-term is incompatible with the patterns (the / con-
flicts with an a in the pattern), so we find s' = /(fi,/(fi, fi)),
initialize s2.2 to s', and continue at 2.2.
* Only the rightmost fl is strongly needed, so expand to
* Only the rightmost (7 is strongly needed, so expand to
* The new fi-term is incompatible with the patterns (the b con-
flicts with an a in the pattern), so we find s' = b, initialize s2.2.2.2
to s', and continue at 2.2.2.2.
Now process the subterm t2.2.2.2 = b at 2.2.2.2, with s2.2.2.2 = b.
b C S2.2.2.2, and b E patt(T23), so this subterm is a strongly needed
redex. Rewrite it to a, yielding
and continue at 2.2, using the last value for s2.2 before reading 2.2.2.2:
* Expand the fourth Q again, but this time we read an a instead
* Only the rightmost fl is strongly needed, so expand to
* Only the rightmost J7 is strongly needed, so expand to
* Again the new fi-term is incompatible with the patterns, and
further processing at 2.2.2.1.2 rewrites the b to a, yielding
124 Michael J. O'Donnell
We continue at 2.2, with the last version of s2.2 before reading
2.2.2.1.2. Extend s2.2 = /(ft,/(/(ft, ft), a)) again, this time to
* Now /(ft,/(/(ft,a),a))Es 2 . 2 , and /(ft, /(/(ft,a),a)) €
patt(T2s), so we have a strongly needed redex, which we rewrite
to o, yielding
• Continue at 2 with the last ft-term before reading 2.2: s2 = /(ft, ft).
* Expand the rightmost ft again, but this time we read an a in-
stead of an /, yielding s2 = /(ft,fa])).
* The new ft-term is incompatible with the patterns, and there is
no compatible subterm, so we move back toward the root.
• Continue at A with the last ft term before reading 2.2:
* This time we read an a instead of an /, yielding:
Only the rightmost ft is strongly needed, so expand to
* Only the rightmost ft is strongly needed, so expand to
* As before, the ft-term is incompatible with the patterns; further
processing at 2.1.2 discovers that b is a redex, and rewrites it to
a, yielding
Then we continue at A with SA = /(ft,/(/(ft, ft), a)) again, this
time reading an a and extending to SA = /(ft,/(/(ft,[a]), a)).
* Now we have a redex pattern /(ft, /(/(ft, a), a)) at the root. We
rewrite to a and start over at the root.
• In general, there might be more computation at the root, but in this
example we immediately get SA = a, which is incompatible .with the
patterns. Since there is nowhere left to go, we have a normal form.
Huet and Levy use ft-terms in a pattern-matching and sequentializing
method that succeeds for every strongly sequential system of equations.
Several similar but less general methods have been proposed in order to sim-
plify the method in special cases [O'Donnell, 1985; Strandh, 1988; Strandh,
1989; Durand and Salinier, 1993; Durand, 1994; Ramakrishnan and Sekar,
1990].
4.2.2 Representing Sequencing Information by Sets of Subpat-
terns
Another natural approach to pattern-matching and sequencing is to focus
on the left-hand sides of equations, and represent information about a term
Equational Logic Programming 125
according to the ways that it does and does not match portions of those
left-hand sides.
Definition 4.2.5. Let T be a set of equations. UT is the set of all sub-
terms of members of patt(T).
A subpattern set for T is a subset B C UT.
Subpattern sets may be used to present information about pattern-
matching and sequencing in several ways:
1. A match set is a subpattern set containing all of the subpatterns
known to match at a particular node in a term.
2. A possibility set is a subpattern set containing all of the subpatterns
that might match at a particular node in a term, as the result of
w-rewriting the proper subterms of that node.
3. A search set is a subpattern set containing subpatterns to search for
at a particular node, in order to contribute to a redex.
Notice that match sets and possibility sets always contain fi (except in the
unusual case when T has no occurrence of a variable), because everything
matches fl. Search sets never contain fi, since it is pointless to search for
something that is everywhere; they always contain patt(T), since finding
an entire redex occurrence is always useful.
In order to control pattern-matching and sequencing with subpattern
sets, associate a match set Ma and a possibility set Pa with each node in
a term t. Initially, Ma = {ft} and Pa = UT for all a. At all times the
subterm at a will match every subpattern in Ma, but no subpattern that
is not in Pa. That is, [M, P] is an interval in the lattice of subpattern sets
in which the true current description of the subterm at a always resides.
At every visit to a node a, update Ma and Pa based on the symbol / at a
and the information at the children a1, . . . , an of a as follows:
P'a represents the set of all subpatterns that may match at node a, as
the result of w-rewriting at proper descendants of a. Notice the similarity
between the calculation of Pa and the process of melting—UT above plays
the role of fi in melting.
126 Michael J. 0 'Donnell
Similarly, keep a search set Sa at each node that is visited in the traver-
sal, entering at the root with SA = patt(T). When moving from a node a
to the ith child a.i of a, update the search set at a.i by
{s : s is the iih principal subterm of a member of Sa D P'a}
The information in Ma, Pa, Sa, and the corresponding information at
the children ai, . . . an of a, may be used to control pattern-matching and
sequencing as follows:
1. If Ma n patt(T) = 0, then a is a redex occurrence.
2. If Pa n patt(T) = 0, then a will never be a redex occurrence.
3. If Ma n Sa = 0, then a contributes to a possible redex at one of its
ancestors.
4. If Pa n Sa = 0, then the symbol at a will never contribute to a redex
occurrence.
5. If there is no Q-term s E Sa whose ith principal subterm is in Ma.i,
then it is safe to move to a.i and process it further—in particular,
any redex occurrence reached by safe moves is strongly needed.
Hoffmann and I proposed a pattern-matching and sequencing method based
on match/possibility/search sets. The method appears heuristically to suc-
ceed on most naturally defined orthogonal systems, but Jiefei Hong noticed
that there are some strongly sequential systems for which it fails.
Example 4.2.6. Consider the strongly sequential system
and search for a strongly needed redex in the term f ( g ( c , c ) , c ) with oc-
currences A (the root), 1 (the subterm g(c, c)), 1.1, 1.2, and 2 (the three
occurrences of c, from left to right).
• Initially, we search at A, with
Update MA and PA based on M1 = M2 = {fi}, PI = P? = UT24> and
the symbol / at the root—in this case MA and PA do not change,
and
Prom condition (5) above, it is safe to move to either of 1 or 2.
Suppose that we choose arbitrarily to move to 1.
Equational Logic Programming 127
• Now, we search at 1, with
Update MI and PI to
The possibility set decreases in this case, because there is no left-
hand side with g at the root. Now by condition (5), it is not safe to
move to the first child of 1, 1.1, because g(£l, a) € S1 has (7 as its first
principal subterm, and fi € MI.I. Similarly, it is not safe to move to
1.2, because of g(a,fi) e Si. The method suggested in [Hoffmann
and O'Donnell, 1979] is not capable of backing up to parents and
siblings of 1 in order to decide which of the children of 1 to visit first.
On the other hand, suppose we choose arbitrarily to move from A to 2
instead of 1.
• Now, we search at 2, with
Since c 6 M2 npatt(T), there is a redex, which is strongly needed
since we found it by safe moves, and we rewrite c to o, yielding
f ( g ( c , c ) , a ) . Recalculate M2 and P2 to
a E M2 n S2, so continue back at A trying to complete a redex using
the a at 2.
Search again at A; update MA, PA an<^ ^*A again. M\ and P\ do not
change, but now
It is still safe to move to 1.
Search at 1 with
128 Michael J. O'Donnell
Notice that information from 2 has led to a smaller search set, not
containing g(£l,a). Update MI and PI to
This time it is safe to move to 1.1, but not to 1.2, so we choose the
former.
• Search at 1.1 with
The results are the same as in the search at 2 above—c rewrites to a
and we continue back at 1.
• Search again at 1, update MI, PI again to
g(a,fZ) € MI n Si, so continue back at A
• Search one more time at A, recalculating MA, PA to
f ( g ( a , £ l ) , a ) £ MA Dpatt(T), so there is a redex at A. Rewrite it,
yielding d. Update MA, PA to
PA n patt(T) = 0, so the d at A will never change. Since A now has
no children, we are done, and d is a normal form.
T24 shows that for some strongly sequential systems, the success of the
subpattern set analysis depends on the choice of traversal order. In the
strongly sequential system
no order of traversal allows the subpattern set analysis to succeed. The
only way to sequence with T2s is to visit both of the children of an /
before descending to grandchildren. The Huet-Levy method allows this
breadth-first behavior, but the Hoffmann-O'Donnell method does not.
Equational Logic Programming 129
4.2.3 Applying the sequencing techniques
Neither fi-terms nor subpattern sets should be computed explicitly at run
time. Rather, at compile time we compute the finite set of values that can
possibly occur while executing a given system of equations T, along with
tables of the operations required to update them at run time. It is natural
to think of fi-terms and subpattern sets as components of the state of a
finite automaton, and the tables of operations as a representation of the
transition graph. A key problem is that the number of states may grow ex-
ponentially in the size of T. [Hoffmann and O'Donnell, 1982] analyzes the
number of match sets associated with a set of patterns. There is no pub-
lished analysis of the number of fJ-terms, nor of possibility and search sets,
but it appears that all three may grow at an exponential rate also. Most
implementations of equational logic programming appear to use methods
that are equivalent to highly restricted forms of the fi-term method.
The Huet-Levy fi-term method is the only published method that suc-
ceeds for all strongly sequential systems. The only published method using
subpatterns fails in cases, such as T25, where it is necessary to back up
before reaching the leaves of a pattern, in order to carry information about
sequencing to a sibling. I conjecture that a simple variation in the algorithm
of [Hoffmann and O'Donnell, 1979] will succeed on all strongly sequential
systems. Besides the superior generality of the Huet-Levy algorithm, fi-
term methods have the advantage of a simple notation, making it relatively
easy to discover restrictions that control the number of possible values. On
the other hand, subpattern sets express the significance of information for
pattern matching purposes in a particularly transparent way. The subpat-
tern set method also has the advantage of separating clearly the information
that is passed up the tree (match and possibility sets) from the informa-
tion that is passed down the tree (search sets). Match and possibility sets
may be associated with nodes in a heap representation of a tree, taking
advantage of sharing in the heap. Search sets and fJ-terms depend on the
path by which a node was reached, so they must be stored on a traversal
stack, or otherwise marked so that they are not shared inappropriately.
4.3 Driving procedures for term rewriting
4.3.1 A recursive schema for lazy evaluation
It is natural to drive the conventional strict evaluation of a term by a recur-
sive procedure, eval, shown in Figure 8. For each function symbol / that
appears in a term, there is a predefined procedure / to compute the value
of that function on given arguments. The simplicity of recursive evaluation
is appealing, and it has a direct and transparent correspondence to the
semantic definition of the value of a term (Definition 2.3.3 of the chapter
'Introduction: Logic and Logic Programming Languages). It is straightfor-
ward to let the value of a term be its normal form, and use the recursive eval
130 Michael J. O'Donnell
Procedure eval(t)
Let * = /(*!,...,*„); (1)
For i := l , . . . , n do (2)
Vi :— eval(ti) (3)
end for;
Return/(vi,...,v n ) (4)
end procedure eval
Fig. 8. Recursive schema for strict evaluation.
above to find the normal form of its input. But, the structure of the proce-
dure is heavily biased toward strict evaluation. Even the conditional func-
tion cond requires a special test between lines (1) and (2) to avoid evaluat-
ing both branches. Lazy functional languages have been implemented with
conventional recursive evaluation, by adding new values, called suspensions,
thunks, or closures to encode unevaluated subterms [Peyton Jones, 1987;
Bloss et al., 147-164]. The overhead of naive implementations of suspen-
sions led to early skepticism about the performance of lazy evaluation.
Clever optimizations of suspensions have improved this overhead substan-
tially, but it is still arguably better to start with an evaluation schema that
deals with lazy evaluation directly.
For orthogonal systems of equations, a function symbol that contributes
to a redex occurrence at a proper ancestor cannot itself be at the root of a
redex. So, a term may be normalized by a recursive procedure that rewrites
its argument only until the root symbol can never be rewritten.
Definition 4.3.1. Let T be a set of equations, and t be a term. t is a
(weak) head-normal form for T if and only if there is no redex u such that
t$*u.
t is a strong head-normal form for T if and only if there is no redex u
such that t -^* u.
Head normality is undecidable, but strong head normality is easy to
detect by melting.
Proposition 4.3.2. Let t be a term, t is a strong head-normal form for
T if and only if meltj(i) / ft.
Let t be an fl-term. The folowing are equivalent:
• u is a strong head-normal form for T, for all u 3 t
• meli£(«) 56 n.
The procedure head-eval in Figure 9 below rewrites its argument only to
strong head-normal form, instead of all the way to normal form. The
tests whether t is in strong head-normal form (1), whether t is a redex
(2), and the choice of a safe child i (5), may be accomplished by any
Equational Logic Programming 131
Procedure head-eval(t)
While t is not in strong head-normal form do (1)
If t is a redex then (2)
t := right-side(t) (3)
else
Let * = /(*!,...,*„); (4)
Choose i € [l,n] that is safe to process; (5)
ti := head-eval(ti); (6)
t :=/(«!,...,tn) (7)
end if
end while;
Return t (8)
end procedure head-eval
Fig. 9. Recursive schema to find head-normal form.
pattern-matching and sequencing method that succeeds on the given sys-
tem of equations. The procedure right-side called by head-eval above builds
and returns the right-hand side instance corresponding to a given redex.
right-side contains the information about function symbols analogous to
that contained in the collection of /s used by the strict evaluator eval. In
a detailed implementation, pattern-matching and sequencing require some
additional data structures, and possibly some additional values returned
by head-eval.
In order to produce a normal form for t, head-eval must be called recur-
sively on the subterms of t, as shown by the procedure norm in Figure 10
below. Section 7 shows how other schemes for calling head-eval, more so-
Procedure norm(t)
t := head-eval(t); (1)
Lett = /(«!,..., t w ); (2)
Fori := 1, . . . , n do (3)
ti := norm(ti) (4)
end for;
t :=/(«!,...,<n); (5)
Return t (6)
end procedure norm
Fig. 10. Recursive schema to normalize a term lazily.
phisticated than norm, may be used to generalize the behavior of input
and output in equational logic programming.
132 Michael J. O'Donnell
4.3.2 Using the term data structure in rewriting
The basic recursive schema of head-eval may manipulate the tables val,
repl and ind in a variety of different ways, with various advantages and dis-
advantages in performance. In most cases, particularly in implementations
of orthogonal systems of equations, the pattern-matching and sequencing
method operates on val^^ao), where a0 is a heap address that initially
represents the root of the input term, val^pj^ao) is typically the closest
thing to a normal form for the original input that can be read easily from
val, repl and ind, so we achieve the best progress by rewriting it further.
It is also clearly correct to run the pattern-matcher/sequencer on another
term in val*epi(ao). I am not aware of any current implementation that
does this, but it is likely to be necessary in complete implementations of
nonconfluent systems, and equation solving systems (Section 7.2), which
will presumably need to explore several rewriting sequences in parallel. The
details of access to val and repl for pattern-matching/sequencing fit into
the implementation of the conditions tested in lines (1) and (2) of head-eval,
and in the choice of i in line (5). If the calculation of val™p*(ao) follows
repl links, it is usually desirable to compress the paths using transforma-
tions (4) and (5) from Section 4.1.2, which speeds up future calculations of
val™p*(ao). The benefits of transformations (4) and (5) are essentially the
same as the benefits of path compression in the UNION/FIND algorithm
[Aho et ai, 1974] (think of repl as representing a partition of terms into
equivalence classes of terms that have been proved equal).
The implementation of right-side, called in line (3) of head-eval, is the
only place where updating of val, repl and ind is required. Suppose that
we are applying the equation / = r to rewrite the term t, represented in
the heap with root node a. The most obvious implementation of right-side
builds all of the nonvariable structure of r in newly allocated heap nodes in
val, using pointers to pre-existing structure for the variable substitutions
(this is essentially what a conventional Lisp implementation does). Let /? be
the root node of the constructed representation of the appropriate instance
of r. Once the instance of r is built, /3 may be copied into a. Unfortunately,
when r consists of a single variable, as in car(cons(x, y)) = x, /3 may have
already been shared extensively, and this copying loses an obvious oppor-
tunity for further sharing [O'Donnell, 1977]. The natural alternative to
copying 0 is to assign repl(a) := 0 (represent the rewriting step by a link,
instead of rewriting in place). This avoids any loss of sharing, and if path
compression is applied in calculating val™p*(ao), it appears to have an
acceptable cost in overhead for access to the heap. In many programs, a
more sophisticated implementation of right-side can save an exponentially
growing amount of wasted work by sharing identical subterms of r. Many
natural programs have such identical subterms of right-hand sides, and in
practice this makes the difference between efficiency and infeasibility often
Equational Logic Programming 133
enough to be well worth the effort. The cost of detecting identical subterms
of right-hand sides using the tree isomorphism algorithm [Aho et al., 1974]
is quite modest, and can be borne entirely at compile time.
4.3.3 Dynamic exploitation of sharing and memoing of ground
terms
There are several ways that the signature index ind may be used to im-
prove sharing dynamically and opportunistically at run time (these are
examples of transformations (6) and (7) of Section 4.1.2). A further so-
phistication of right-side builds the structure of the instance of r from
the leaves and variable instances up, and for each constructed signature
f(a\,..., an) it checks ind(/(ai,..., a n )). If the result is nil, right-side
builds a new heap node (3 containing signature f(a\,..., an), and updates
ind by ind(/(a1,..., an) := 0. If the result is 7 ^ nil it shares the pre-
existing representation rooted at 7. This technique is essentially the same
as the hashed cons optimization in Lisp implementations [Spitzen et al.,
1978]. There are more places where it may be valuable to check the
signature index for opportunistic sharing. Immediately after line (6) of
head-eval, the signature at the root a of the heap representation of t may
have changed, due to rewriting of ti and path-compression. A sophisticated
implementation may check ind(val(a)), and if the result is /? ^ nil, a, re-
assign repl(a) := /3, so that further path compression will replace links
pointing to a by links to B, thus increasing sharing. If ind(val(a)) = nil,
then reassign ind(val(a)) := a. Finally, when head-eval is called recur-
sively on a subterm rooted at the heap address a, the signature at a may
be modified as the result of rewriting of a shared descendant of a that was
visited previously by a path not passing through a. So, the same check-
ing of ind and updating of repl or ind may be performed in step (1) of
head-eval, after any implicit path compression, but before actually testing
for strong head-normal form.
The opportunistic sharing techniques described above have a nontriv-
ial cost in overhead added to each computation step, but in some cases
they reduce the number of computation steps by an exponentially growing
amount. See [Sherman, 1990] for more details on opportunistic sharing,
and discussion of the tradeoff between ovehead on each step and number
of steps. The method that checks new opportunities for sharing at every
node visit as described above is called lazy directed congruence closure. An
even more aggressive strategy, called directed congruence closure [Chew,
1980], makes extra node visits wherever there is a chance that a change in
signature has created new sharing opportunities, even though the pattern-
matcher/sequencer has not generated a need to visit all such nodes (i.e.,
when the signature at a shared node changes, directed congruence closure
visits all parents of the node, many of which might never be visited again
by head-eval). Directed congruence closure may reduce the number of
134 Michael J. O'Donnell
steps in lazy directed congruence closure by an exponential amount, but
the added overhead appears heuristically large, and changes the structure
of the implementation significantly from the recursive schema of head-eval.
Opportunistic sharing strategies are generalizations of the idea of memo
functions [Keller and Sleep, 1986; Mitchie, 1968; Field and Harrison, 1988].
Most memoing techniques limit themselves to remembering equalities of
the form f(t\, . . . , < „ ) = u, where the tiS and u are all in normal form.
Lazy directed congruence closure and its variants can remember partial
evaluations as well, as can the lazy memo functions of Hughes [Hughes,
1985a]. There is a nice theoretical characterization of the memoing power
of directed congruence closure.
Proposition 4.3.3 ([Chew, 1980]). At any step in the process of rewrit-
ing a term, there is a set G of ground instances of equations that have been
applied in rewriting. Using directed congruence closure, we never apply a
ground instance that is a semantic consequence of G.
Not only does directed congruence closure avoid ever doing the same
rewriting step twice in different contexts, it only performs a new rewriting
step when new substitution of terms for variables in the given equations is
absolutely necessary to derive that step.
4.3.4 Sharing and memoing nonground terms—paramodulation
The next natural step beyond directed congruence closure is sharing/
memoing nonground terms. Abstractly in theorem-proving language, this
amounts to applying paramodulation [Robinson and Wos, 1969; Loveland,
1978; Gallier, 1986] to derive new equations with variables, instead of using
demodulation to merely rewrite a given term. Paramodulation takes two
equations p = q[r/x] and s = t and substitutions <r r , <rs of terms for vari-
ables such that rar = scrs, and derives the new equation par = qo-T[tas/x],
which follows from the first two by instantiation, substitution, and tran-
sitivity. Paramodulation sometimes improves the lengths of proofs by ex-
ponentially growing amounts compared to pure term rewriting [Loveland,
1978].
Example 4.3.4. Consider the set Trev of equations defining list reversal
(rev) and appending an element to the end of a list (app).
Trev = {{ rev(nil) = nil,
rev (cons
(cons(x,y))
( x , y ) ) = app (x, rev
rev(y)),
(y)),
app(x, nil) = x,
app(x, cons(y, z)) = cons(y, app(x, z)) }
The number of rewriting steps required to append an element to a list
of i elements is i + I, But, consider applying paramodulation instead.
One step of paramodulating the last equation in Trev with itself yields
Equational Logic Programming 135
app(w, cons(x, cons(y, z))) = cons(x, cons(y, app(w, z))), which moves the
appended element w past the first two elements in the list. The new equa-
tion paramodulates again with app(x, cons(y,z)) = cons(y, app(x, z)) to
move the appended element past three list elements, but paramodulat-
ing the new equation with itself does even better, moving the appended
element past four list elements. It is straightforward to produce a sequence
of equations, each by paramodulating the previous one with itself, so that
the ith equation in the sequence moves an appended element past 2i list
elements. So, paramodulation reduces the number of steps involved in nor-
malizing app(a,/3), where 0 is a list of i elements, from i + 1 to O(log i).
The improvement in normalizing rev (a) is less dramatic, but perhaps
more useful in practice. If a has i elements, then rewriting requires fi(i 2 )
steps to normalize rev(a), because it involves appending to the end of a
sequence of lists of lengths 0,1,..., i. But, we may produce a sequence of
equations, each by paramodulating the previous one with
so that the ith equation in the sequence appends an arbitrary element to a
list of length i. The whole sequence requires only i steps of paramodulation,
so a list of i elements may be reversed by O(i) paramodulation steps.
There are several problems in reducing the ideas on paramodulation
suggested in Example 4.3.4 to useful practice. First, we need a way to
control paramodulation—that is, to choose useful steps of paramodulation
to perform (equivalently, useful derived nonground equations to save and
use along with the originally given program equations for further evalua-
tion steps). Sequential strategies for lazy evaluation appear to solve this
problem in principle. Whenever a sequential rewriting process discovers
that a ground term s rewrites in one step to a ground term t, and existing
links in the repl table rewrite t further to u, ground sharing techniques
such as lazy directed congruence closure in effect save the derived ground
equation s = u for later use as a single step (this is accomplished by setting
repl(a) := 7 where t = val*repl(a) and u = val*repl(7)). A method for non-
ground sharing should save instead the nonground equation s' = u', where
s' is the generalization of s containing all of the symbol instances in s that
were scanned by the sequential rewriting process in order to rewrite s to u,
with unique variables replacing the unscanned portions of s. The appropri-
ate generalization u' of u is easy to derive from the same information that
determines s'. The equation s' = u' may be derived by paramodulation,
using the same equations that were used to rewrite s to u. This strategy
for driving paramodulation by the same sequentializing process that drives
rewriting accomplishes the improvement of list reversal from quadratic to
a linear number of inference steps in Example 4.3.4 above.
A second problem is to deal efficiently with the more general sets of
136 Michael J. O'Donnell
equations that we get by adding the results of paramodulation to the orig-
inal program equations. Notice that, even when the original program is
orthogonal, there are overlaps between the original equations and the re-
sults of paramodulation. When several different equations apply to the
same subterm, we probably should choose the most specific one, but that
may not always be uniquely determined (see Figure 4 in Section 3.2.4 for
the different sorts of overlap). At least in Example 4.3.4 above, choosing
the most specific applicable equation accomplishes the improvement of list
appending from linear to logarithmic.
Finally, we need an efficient data structure for representing sets of non-
ground equations, with a good way to add the new equations that result
from paramodulation. Suffix trees [Aho et al., 1974] appear to provide a
good basis for representing dynamically increasing sets of patterns and/or
equations [Strandh, 1984], but it is not at all clear how to generalize these
ideas efficiently to terms instead of strings (a good dissertation project:
implement string rewriting with as much sharing as possible at both ends
of a substring—this is essentially nonground sharing with only unary func-
tions). A more detailed examination of Example 4.3.4 above reveals that,
although the number of abstract steps required to reverse a list of length i
using paramodulation is only O(i), each abstract step involves an equation
with a larger left-hand side than the one before. So, while the number of
steps decreases, the cost of pattern-matching in each step increases, and
the total cost for reversal remains fi(i2). The exponential improvement
in appending to the end of a list still yields a net win, but it is not clear
how often such exponential improvements will arise in practice. In order
to decrease the total cost of reversal to O(i), we need a way to make the
pattern matching process incremental, so that the work done to match a
smaller pattern may be reused in matching a larger pattern derived from
it. I cannot find a reason why such efficient incremental pattern matching
is impossible, but no known technique accomplishes it today.
Another starting point for research on nonground sharing is the work
on sharing in the lambda calculus [Staples, 1982; Lamping, 1990; Kathail,
1984; Gonthier et al., 1992]. Some surprisingly powerful data structures
have been discovered already, but the overhead of using them is still not
understood well enough to determine their practical impact.
4.3.5 Storage allocation
Essentially all of the known ideas for automatic storage allocation and
deallocation are applicable to the val/repl/ind heap [Cohen, 1981; Ap-
pel, 1991]. Unfortunately, one of the most attractive methods in current
practice—generational garbage collection [Lieberman and Hewitt, 1983]—
has been analyzed on the assumption that it is rare for old nodes in the
heap to point to much more recently allocated ones. The repl links in lazy
implementations of equational logic programming appear to violate that as-
Equational Logic Programming 137
sumption. I know of no experimental or theoretical study of the efficiency
of generational garbage collection with lazy evaluation. The aggressive
sharing techniques also call into question the normal definition of 'garbage'
nodes as those that cannot be reached starting from some set of directly
accessible root nodes. In the discussion above, the directly accessible nodes
are ao and all of the nodes entered in the ind table. With the more ag-
gressive approaches to sharing, every node in the heap is usually accessible
from nodes in ind, so there is no garbage according to the strict defini-
tion. On the other hand, nodes that are inaccessible from ao (the root of
the term being rewritten to normal form) contain information that may be
recalculated from the ao-accessible nodes and the equational program, so,
while they are not useless garbage, they are not essential to the calculation
of a final result. I am not aware of any published literature on deallocation
of useful but inessential nodes in a heap, which might be called 'rum-
mage sale' instead of 'garbage collection.' Phillip Wadler proposed that a
garbage-collection/rummage-sale procedure might also perform rewriting
steps that reduce the size of the given term. Such a technique appears
to provide the space-saving benefits of strictness analysis [Mycroft, 1980;
Hughes, 1985b], avoiding both the compile-time cost and the nonunifor-
mity in the run-time control. Research is needed on the practical impact
of various heuristic strategies for looking ahead in a rewriting sequence in
search of a smaller version of the current term.
5 Compiling efficient code from equations
Conventional approaches to compiling functional programs, following early
Lisp compilers, associate a block of machine code with each function sym-
bol /, and use the recursive schema for eval in Figure 8, with some rep-
resentation of suspensions to encode partially evaluated terms as a new
sort of value [Peyton Jones, 1987]. A natural and less explored alterna-
tive is to associate a block of machine code with each state in a finite
automaton whose states are derived from an analysis of the program using
ft-terms or subpattern sets [Bondorf, 1989; Durand et al., 1991]. The state-
based approach has no explicit representation of suspensions, although in
effect terms that it must build in the heap are implicit suspensions. And,
a naive implementation of the state-based approach leads to more and
smaller recursive procedures than the symbol-based approach. Of course,
sophisticated symbol-based compilers may optimize by compiling multiple
specialized versions of a single function for different sorts of arguments,
and sophisticated state-based compilers may optimize by inlining some of
the recursive calls. The supercombinator method [Hughes, 1982] introduces
new symbols internal to the implementation, reducing the dependence of
symbol-based compiling on the actual symbols in the source program. Af-
ter such optimizations, it is not clear whether symbol-based compiling and
138 Michael J. O'Dormell
state-based compiling will actually generate different code. The function
symbols appear to be conceptually tied to the programmer's view of her
program, while the automaton states appear to be conceptually tied to the
computational requirements of the program. I conjecture that in the long
run the state-based approach will prove more convenient for achieving the
best run-time performance, while the symbol-based approach will maintain
a more intuitive connection between program structure and performance.
Both the function-based and state-based methods compile the informa-
tion in the set of equations constituting a program, but they both treat
the input term and all of the intermediate terms produced in rewriting to
normal form as static data structures, which must be interpreted by the
compiled equational code. The Tigre system [Koopman and Lee, 1989;
Koopman, 1990] by contrast compiles each function symbol in the term
being evaluated into a block of code—the entire term becomes a self mod-
ifying program that reduces itself to normal form. Tigre compiles only a
particular extension of the combinator calculus; an interesting generaliza-
tion would be a Tigre-like compiler for an arbitrary orthogonal system.
Several abstract machine languages have been proposed as intermediate
languages for equational compilers, or as real machine languages for spe-
cialized term-rewriting machines. Landin's SECD machine [Landin, 1965]
is designed to support evaluation of lambda terms. The G Machine [Johns-
son, 1984; Augustsson, 1984; Burn et al., 1988] is intended as a specialized
machine language or intermediate language for term rewriting in general.
Equational Machine (EM) code [Durand et al., 1991; Strandh, 1988] is
designed to support state-based compiling of equational programs, and
the optimizations that seem most important in that approach. Several
other abstract machine proposals are in [Cardelli, 1983; Cardelli, 1984;
Cousineau et al., 1985]. Turner proposes to compile equational systems
into the combinator calculus, using the well-known capability of the com-
binator calculus to encode substitution in the lambda calculus [Turner,
1979]. Then, an implementation of the combinator calculus, fine tuned
for performance, can support essentially all equational logic programming
languages. The impact of such translations of one rewriting system to an-
other is ill understood—in particular the effects on sharing and parallelism
(see Section 6) are quite subtle. The Warren Abstract Machine (WAM)
[Warren, 1983], intended as an intermediate language for Prolog compilers,
has also been used in theorem provers as a representation for terms—t is
represented by WAM code to unify an arbitrary input with t. I am not
aware of any published study of the applicability of such a WAM encoding
of terms to functional or equational logic programming.
Equational Logic Programming 139
6 Parallel implementation
One of the primary early motivations for studying functional programming
languages was the apparent opportunities for parallel evaluation [Backus,
1978]. So, it is ironic that most of the effort in functional and equational
logic programming to date involves sequential implementation. A variety
of proposals for parallel implementation may be found in [Peyton Jones,
1987].
Both strictness analysis and sequentiality analysis are used primarily
to choose a sequential order of computation that avoids wasted steps. An
important open topic for research is the extension of sequentiality analysis
to support parallel computation. Huet and Levy's sequentiality analysis
is already capable of identifying more than one strongly needed redex in
a term. A parallel implementation might allocate processors first to the
strongly needed redexes, and then to other more speculative efforts. It ap-
pears that sequentiality analysis can be generalized rather easily (although
this has not been done in print) to identify strongly needed sets of re-
dexes, where no individual redex is certain to be needed, but at least one
member of the set is needed. For example, with the positive parallel-or
equations in Tor+ of Examples 2.3.16 and 3.2.1, it is intuitively clear that
if a is needed in t, and 0 is needed in u, then at least one of a and /3 must
be rewritten in or(t, u) (although neither is needed according to the for-
mal Definition 3.2.3). Further research is required on the practical impact
of heuristic strategies for allocating parallel processors to the members of
strongly needed sets. It is natural to give priority to the singleton sets
(that is, to the strongly needed redexes), but it is not clear whether a set
of size 2 should be preferred to one of size 3—perhaps other factors than
the size of the set should be considered. Strongly needed redex sets are
essentially disjunctive assertions about the need for redexes—more general
sorts of boolean relations may be useful (e.g., either all of ai,... ,am or
all of /3i,..., (3n are needed).
Unfortunately, since strongly needed redexes are all outermost, sequen-
tiality analysis as known today can only help with parallelism between
different arguments to a function. But, one of the most useful qualities of
lazy programming is that it simulates a parallel producer-consumer rela-
tionship between a function and its arguments. It seems likely that much
of the useful parallelism to be exploited in equational logic programming
involves parallel rewriting of nested redexes. An analysis of nonoutermost
needed redexes appears to require the sort of abstract interpretation that is
used in strictness analysis [Mycroft, 1980; Hughes, 1985b]—it certainly will
depend on right-hand sides as well as left-hand sides of equations. Unfor-
tunately, most of the proposed intermediate languages for compiling equa-
tional programs are inherently sequential, and a lot of work is required to
convert current sequential compiling ideas to a parallel environment. The
140 Michael J. O'Donnell
idea of compiling everything into combinators may not be useful for parallel
implementation. The known translations of lambda terms into combinators
eliminate some apparent parallelism between application of a function and
rewriting of the definition of the function (although no direct implemen-
tation is known to support all of this apparent parallelism either). Only
very preliminary information is available on the inherent parallel power of
rewriting systems: even the correct definition of such power is problematic
[O'Donnell, 1985].
At a more concrete level, there are a lot of problems involved in par-
allelizing the heap-based execution of evaluation/rewriting sequences. A
data structure, possibly distributed amongst several processors, is needed
to keep track of the multiple locations at which work is proceeding. If any
speculative work is done on redexes that are not known to be needed, there
must be a way to kill off processes that are no longer useful, and reallocate
their processing to to useful processes (although aggressive sharing through
the signature index confuses the question of usefulness of processes in the
same way that it confuses the usefulness of heap nodes).
Sharing presents another challenge. Several different processors may
reach a shared node by different paths. It is important for data integrity
that they do not make simultaneous incompatible updates, and important
for efficiency that they do not repeat work. But, it is incorrect for the
first process to lock all others completely out of its work area. Suppose we
are applying a system of equations including car (cons ( x , y ) ) = x. There
may be a node a in the heap containing the signature cons(/3i,/32) shared
between two parents, one of them containing cons (a, 6) and the other con-
taining car (a). A process might enter first through the cons parent, and
perform an infinite loop rewriting inside /32. If a second process enters
through the car node, it is crucial to allow it to see the cons at a, to link
to /?i, and depending on the context above possibly to continue rewriting
at /3j and below.
Abstractly, we want to lock node/state pairs, and allow multiple pro-
cesses to inspect the same node, as long as they do so in different states,
but when a process reaches a node that is already being processed in the
same state it should wait, and allow its processor to be reassigned, since
any work that it tries to do will merely repeat that of its predecessor. It is
not at all clear how to implement such a notion of locking with acceptable
overhead. Perhaps a radically different approach for assigning work to pro-
cessors is called for, that does not follow the structure of current sequential
implementations so closely. For example, instead of the shared-memory ap-
proach to the heap in the preceding discussion, perhaps different sections
of the heap should be assigned to particular processors for a relatively long
period, and demands for evaluation should be passed as messages between
processors when they cross the boundaries of heap allocation.
Equational Logic Programming 141
7 Extensions to equational logic programming
7.1 Incremental infinite input and output
The logic programming approach to answering normal form queries leads
naturally to the use of lazy evaluation to guarantee completeness. But,
once we commit to lazy evaluation, the basic scheme of normal form queries
seems too limited. Inside an equational computation, it is natural to con-
ceive of procedures consuming and producing potentially infinite terms in-
crementally, in the manner of communicating coroutines. It is perfectly sen-
sible to define objects that correspond intuitively to infinite terms, as long
as only finite portions of these infinite terms are required to produce output.
It is annoying that the full flexibility of incremental demand-driven com-
putation in the internal computation is not available at the input/output
interface. Aside from the loss of input/output programming power per se,
such a discrepancy between internal and external communication tends to
encourage large, unwieldy, monolithic programs, and discourage the col-
lections of small, separate, modular programs that are more desirable in
many ways.
The desired abstract behavior of a demand-driven incremental I/O in-
terface is essentially clear. The consumer of output demands the symbol
at the root of the output. The equational program computes until it has
produced a head-normal form equivalent to the input, then it outputs the
root symbol of that head-normal form, and recursively makes the principal
subterms available to the consumer of output, who can demand symbols
down different paths of the output tree in any order. During the compu-
tation of a head-normal form, the equational program generates demands
for symbols in the input. The producer of input is responsible only for
providing those input symbols that are demanded. In this way, both input
and output terms are treated incrementally as needed, and each may be
infinite.
A direct generalization of equational logic programming by extending
the set of terms to include infinite ones is semantically problematic.
Example 7.1.1. Consider the system of equations
The natural infinite output to expect from input a is f(c, f(c,...)). b pro-
duces the same infinite output. So, if in our semantic system f(c, f(c,...))
is a generalized term, with a definite value (no matter what that value is),
then T27 |= (a = b). But, according to the semantics of Definition 2.3.14
in Section 2.3.4 of the chapter 'Introduction: Logic and Logic Program-
ming Languages', T27 ^j. (a = b), because there are certainly models in
which the equation x = f(c,x) has more than one solution. For example,
interpret / as integer addition, and c as the identity element zero. Every
142 Michael J. O'Donnell
integer n satisfies n = 0 + n.
Even if we replace the second equation with the exact substitution of 6
for a in the first, that is b == f ( c , b), it does not follow by standard equational
semantics that a = b. With some difficulty we may define a new semantic
system, with a restricted set of models in which all functions have sufficient
continuity properties to guarantee unique values for infinite terms. But it is
easy to see that the logical consequence relation for such a semantic system
is not semicomputable (recursively enumerable). It is always suspect to say
that we understand a system of logic according to a definition of meaning
that we cannot apply effectively.
Instead, I propose to interpret outputs involving infinite terms as ab-
breviations for infinite conjunctions of formulae in the first-order predicate
calculus (FOPC) (such infinite conjunctions, and infinite disjunctions as
well, are studied in the formal system called Lw1,w [Karp, 1964]).
Definition 7.1.2. The first- order predicate calculus with equality (FOPC_i)
is the result of including the equality symbol = in the set Pred2 of binary
predicate symbols, and combining the semantic rules for FOPC (Defini-
tions 2.3.1-2.3.4, Section 2.3.1 of the chapter 'Introduction: Logic and
Logic Programming Languages') and Equational Logic (Definitions 2.3.13-
2.3.14, Section 2.3.4 of the 'Introduction . . . ' chapter) in the natural way
(a model for FOPC.:. satisfies the restrictions of a model for FOPC and the
restrictions of a model for equational logic).
La u JL is the extension of FOPCj. to allow countably infinite conjunc-
tions and disjunctions in formulae. Let FFu u ± be the set of formulae
in Lu u _L. . Extend the semantic system for FOPC_L to a semantic system
for Lj 'u ± by the following additional rules for infinite conjunctions and
disjunctions:
1. pT,l/(f\{Ai,A2, ...}) = 1 if and only if pT<l/(Ai) = 1 for all i > 1
2- Pr,v(M{Ai, A%, ...}) = 1 if and only if pTtV(Ai) = 1 for some i > 1
That is, an infinite conjunction is true precisely when all of its conjuncts
are true; and an infinite disjunction is true precisely when at least one of
its disjuncts is true.
A set T of terms is a directed set if and only if, for every two terms
t1, t2 € T, there is a term t3 € T such that £3 is an instance of t1 and also
an instance of t%.
Let U be a countable directed set of linear terms. For each u € U, let
yu be a list of the variables occurring in u. Let t be a finite ground term.
The conjunctive equation of t and U is the infinite conjunction
Tp is the set of finite and infinite terms.
Equational Logic Programming 143
The term limit of a directed set U (written lim(U)) is the possibly infi-
nite term resulting from overlaying all of the terms u £ U, and substituting
the new symbol for any variables that are not overlaid by nonvariable
symbols. Since members of U are pairwise consistent, every location in the
limit gets a unique symbol, or by default comes out as _L. To see more
rigorously that the term limit of U is well defined, construct a (possibly
transfinite) chain, (to E ti C • • • ) . First, to = _L. Given ta, choose (axiom
of choice) an s £ U such that s % ta, and let ta+i be the overlay of s with
ta. At limit ordinals A, let t\ be the limit of the chain of terms preceding
A. With a lot of transfinite induction, we get to a tp such that, for all
s £ U, s C t/3, at which point the chain is finished. lim(J7) is the limit of
that chain.
The canonical set of an infinite term t (written approx(t)) is the set of
all finite linear terms t1 (using some arbitrary canonical scheme for naming
the variables) such that t is an instance of t'. approx(t) is a directed set,
and lim(approx(i)) = t.
A careful formal definition of infinite terms and limits is in [Kenneway
et al., 1991; Dershowitz et al, 1991], but an intuitive appreciation suffices
for this section.
When the finite input t produces the infinite output lim(U), instead
of interpreting the output as the equation t = lim(U), interpret it as the
conjunctive equation of t and U. Notice that a chain (a sequence ui,uy,...
such that Uj+i is an instance of Ui) is a special case of a directed set.
The infinite outputs for finite inputs may be expressed by chains, but the
generality of directed sets is needed with infinite outputs for infinite inputs
below.
Infinite inputs require a more complex construction, since they intro-
duce universal quantification that must be nested appropriately with the
existential quantification associated with infinite output. Also, different
orders in which a consumer explores the output may yield different se-
quences of demands for input, and this flexibility needs to be supported by
the semantics.
Definition 7.1.3. Let T and U be directed sets of linear terms such that
no variable occurs in both t € T and u € U. For each term t € T and u €. U,
let Xt and yu be lists of the variables occurring in t and w, respectively. Let
/ : T -4 2U be a function from terms in T to directed subsets of U, such
that when t% is an instance of t1, every member of f(t%) is an instance of
every member of f(<i). The conjunctive equation of T and U by f is the
infinite conjunction
Definition 7.1.4. Let s1,..., Si € Tp be terms. A term u is an incre-
144 Michael J. O'Donnell
mental normal form for {s1,...,«i} if and only if no nonvariable subterm
of u unifies with a term in {s1,... ,Si}. Equivalently, u is an incremen-
tal normal form if and only if u is a normal form and every substitution
of normal forms for variables leaves u in normal form. Equivalently, u is
an incremental normal form if and only if melting preserves ua, where un
results from substituting ft for each variable in u.
Let norm" be a new formal symbol. Let
Define the relation ?-|C C£ x Fp,u>i w ^ by
if and only if there exists a directed set U and a monotonic (in the instance
ordering C) function f : approx(tw) ->• 2U such that
1. A is the conjunctive equation of approx(tw) and U by f;
2. u is in incremental normal form, for all u € U.
Now ( F a ) i u _L,Q",?-^) is a query system representing the answers to
questions of' the form 'what set of incremental normal forms for s 1 , . . . , si
is conjunctively equal to t?' In an implementation of equational logic pro-
gramming based on norm" , the consumer of output generates demands
causing the computation of some u €. U. Some of the symbols in u are
demanded directly by the consumer, others may be demanded by the sys-
tem itself in order to get an incremental normal form. The implementation
demands enough input to construct t £ approx(tw) such that u 6 f ( t ) . By
modelling the input and output as directed sets, rather than sequences, we
allow enough flexibility to model all possible orders in which the consumer
might demand output. The function / is used to model the partial synchro-
nization of input with output required by the semantics of equational logic.
Unfortunately, the trivial output y,y,..., with term limit _L, always satisfies
1-2 above. The most useful implementation would provide consequentially
strongest answers (Definition 2.2.5, Section 2.2 of the chapter 'Introduction:
Logic and Logic Programming Languages')—that is, they would demand
the minimum amount of input semantically required to produce the de-
manded output. If consequentially strongest answers appear too difficult
to implement, a more modest requirement would be that lim(U) is max-
imal among all correct answers—that is, all semantically correct output
is produced, but not necessarily from the minimal input. The techniques
outlined above do not represent sharing information, either within the in-
put, within the output, or between input and output. Further research is
needed into semantic interpretations of sharing information.
Example 7.1.5. Consider the system
Equational Logic Programming 145
and the infinite input term
and the query
The natural desired answer A to this query is the conjunction of
A represents the infinite output t'u = h(h(g(t'u,t'u))). U does not contain
all approximations to t'u, but only the ones that have gs as the rootmost
non-J. symbols. The monotone function mapping partial inputs to the
portions of output that they determine is:
146 Michael J. O'Donndl
A natural approach to representing sharing information would be to use
Vxi,z 2 : f(g(xi,xt)) = h(h(g(xi,xi))) instead of Vxi,x 2 : 3t/i,y2 :
f ( g ( x i , x 2 ) ) = h(h(g(yi,y2))), etc., but this idea has yet to be explored.
It is simple in principle to modify an implementation of equational logic
programming to deal incrementally with infinite input queries and output
answers in the query system Q^. The practical details of such an implemen-
tation are interesting and challenging. The tours protocol [Rebelsky, 1992;
Rebelsky, 1993] provides one design for incremental input and output of in-
finite terms. Implementations based on the recursive scheme for head-eval
in Figure 9 may be adapted relatively simply to incremental input and out-
put, simply by replacing the scheme for norm in Figure 10 by a scheme that
issues calls to head-eval only as symbols are demanded by the consumer
of output. Unfortunately, such adaptations are not normally complete, be-
cause of sequentializing problems. The trouble is that conjunctive behavior
(which is easy to sequentialize) in the application of a rule corresponds to
disjunctive behavior (which is impossible to sequentialize) in the produc-
tion of strong head-normal forms, and vice versa.
Example 7.1.6. Consider the following equation defining the negative
sequential-or:
This equation causes no problem in sequentializing the rewriting of a term
to a finite normal form, since it requires both arguments to or. But, or(s, t)
is a strong head-normal form if and only if either of s or t is a strong head-
normal form ^ false. So, it is not safe to rewrite s, because of the possibility
that s has no strong head-normal form, while t rewrites to strong head-
normal form u ^ false. For symmetric reasons, it is not safe to rewrite t.
Only a parallel rewriting of both s and t is complete, and such parallel
rewriting is very likely to waste steps.
By contrast, the positive parallel-or equations T0r+ of Examples 2.3.16
and 3.2.1 prevent sequential computation of a finite normal form, but pose
no problem to sequential head-normalization of or(s, t) by rewriting s and
t—both arguments must rewrite to strong head-normal forms ^ true in
order to head-normalize or(s,t).
So, to achieve complete implementations of equational logic program-
ming with incremental input and output, we must solve the sticky problems
of efficient implementation of parallel rewriting, even if the parallelism is
simulated by multitasking on a sequential processor. In the meantime, se-
quential and incomplete implementations are likely to be practically useful
for many problems—the incompleteness appears to be no more serious than
the incompleteness of Prolog, which is widely accepted.
Beyond the incremental evaluation of an input that increases over time,
there is an even more challenging problem to evaluate a changing input. In
Equational Logic Programming 147
principle, changing input may be reduced to increasing input by represent-
ing the entire edit history of a term as another term [Rebelsky, 1993]. In
practice, there is a lot of research required to achieve practical efficiency.
A highly efficient general scheme for re-evaluation after a change in in-
put will be extremely valuable. There are several techniques known for
re-evaluation, in special structures, such as attributed parse trees [Demers
et al., 1981; Pugh and Teitelbaum, 1989], but none approaches the gener-
ality or fine-grainedness of equational re-evaluation. A late result for the
A-calculus that I have not had a chance to review is in [Field and Teit-
elbaum, 1990]. Powerful memo techniques seem to be crucial to efficient
re-evaluation of a changed input term. In some sense efficient re-evaluation
is precisely the intelligent reuse of partial results from the previous evalua-
tion. I conjecture that nonground memoing will be especially valuable for
this problem.
Finally, we should study implementations of equational logic program-
ming in which the set of equations is changing. Changing sets of equations
arise in rapid recompiling during program development, in applications
that use equations as inputs rather than as programs, and in methods
based on nonground memoing or paramodulation (Section 4.3.4). Very lit-
tle is known about this problem—all that I am aware of is a technique
for incremental maintenance of a finite automaton for pattern matching
[Strandh, 1984].
7.2 Solving equations
Queries of the form (solvex1,...,x n • s = t) (Definition 2.3.18, Section
2.3.4 of the chapter 'Introduction: Logic and Logic Programming Lan-
guages') require the solution of the equation s = t for the values of x1,... ,xn.
This appears to be much more difficult than finding normal forms, and to
offer more programming power. In particular, it appears that solving equa-
tions is the essential problem in the most natural approach to combining
the useful qualities of Prolog and lazy functional programming. Notice that
solve queries are quite similar to the what queries processed by Prolog
(Section 2.3.1 of the 'Introduction . . . " chapter). A combination of the
methods for solving equations with the techniques of Prolog should pro-
vide a way of answering what queries in the first-order predicate calculus
with equality.
Much of the theory of term rewriting falls short of dealing with the
problems posed by equation solving. Confluence appears to help—if the
given set T of equations is confluent, then we may seek an instance s' of
s and t' of t, and a term u, such that s' -^* u and t' 5* u, ignoring the
symmetric rule and applying equations only from left to right. But, for
a complete implementation, it is not sufficient to rewrite needed redexes.
That is, it may be that there is a u such that s' -3-* u and t' ^* u, but no
148 Michael J. O'Donnell
such u may be reached by rewriting only needed redexes (Definition 3.2.3,
Section 3.2.3). Outermost complete rewriting (Definition 3.1.5, Section 3.1)
is similarly insufficient. Complete rewriting sequences (Definition 3.1.3)
come a bit closer. If s' and t' have a common form, then a complete
rewriting sequence starting with s' is guaranteed eventually to produce
a term u such that t' —>* u. But, another complete rewriting sequence
starting with t' is not guaranteed to produce the same u. Finally, even if
we generate rewriting sequences from s' and t' that both contain u, it is
not clear how to synchronize the sequences so that u appears in both of
them at the same time.
No thoroughly satisfactory method is known for a complete implemen-
tation of equation solving in an arbitrary strongly sequential system. But,
enough is known to make two observations that are likely to be useful in
such an implementation.
1. Suppose we are solving f ( s 1 , . . . , sm) = g(t1, • • •, tn), where f ^ g. It
suffices to rewrite only needed redexes until the head symbols agree.
Unfortunately, it is hard to know whether to rewrite f(s1,...,s m )
or g ( t 1 , . . . , tn) or both, but within each we can use the same sort of
sequentializer that rewrites a single term to normal form.
2. There are only two cases in which it is helpful to instantiate a variable:
(a) when the instantiation creates a redex at a proper ancestor of
the variable, which we immediately rewrite (so, in the situation
of (1) above, the redex must be needed);
(b) when the instantiation unifies corresponding subterms of s and
t.
In each case, we should substitute the most general (smallest) term
that achieves the redex or the unification.
Jayaraman noticed (1) [Jayaraman, 1985], and used it to implement a
system called EqL for solving equations s = t only in the case where in-
stances s' of s and t' of t reduce to a common form consisting entirely of
constructor symbols in a constructor-orthogonal system (Definition 2.3.13,
Section 2.3.2). For this purpose, it suffices to rewrite s' and t' to head-
normal forms. If the head symbols agree, recursively solve equations be-
tween the corresponding arguments, otherwise there is no solution. It
should be straightforward to generalize EqL to find solutions in normal
form in strongly sequential rewrite- and rule-orthogonal systems. If we
want all solutions, even those that are not in normal form, we must some-
how explore in parallel the attempt to rewrite the head symbol of s' and
the attempt to solve the equation without head rewriting one or both of
them (and a similar parallelism for t'). This introduces all of the problems
of parallelism discussed in Section 6, and it probably limits or eliminates
the ability to do path compression on repl links (Section 4.3), since it is not
sufficient to work only on the most rewritten form of a term
Equational Logic Programming 149
where a<j is the root of the heap representation of the term being rewritten).
Heuristically, it appears that the majority of the individual steps in
solving an equation are unlikely to create such parallelism. But, EqL's uni-
form requirement of finding a solution in normal form is likely to introduce
the same huge inefficiencies in some cases as strict evaluation (notice that
the individual evaluations of s', t' to normal form are lazy, but the equation
solution is not lazy, as it may take steps that are required to reach normal
form, but not to solve the equation). If these heuristic observations are ac-
curate, even an implementation with rather high overhead for parallelism
may be very valuable, as long as the cost of parallelism is introduced only
in proportion to the actual degree of parallelism, rather than as a uniform
overhead on sequential evaluation as well.
Among the theoretical literature on term rewriting, the most useful
material for equation solving will probably be that on narrowing [Fay,
1979] (see the chapter 'Equational Reasoning and Term Rewriting Systems
in Volume 1), which is a careful formalization of observation (2) above.
Information on sequencing narrowing steps seems crucial to a truly efficient
implementation: some new results are in [Antoy et al., 1994].
7.3 Indeterminate evaluation in subset logic
Until now, I have considered only quantified conjunctions of equations as
formulae, else I cannot claim to be using equational logic. The discipline
of equational logic constrains the use of term rewriting systems, and leads
us to insist on confluent systems with lazy evaluation. Lazy evaluation
appears to be mostly a benefit, but the restriction to confluent systems
is annoying in many ways, and it particularly weakens the modularity of
equational logic programming languages, since orthogonality depends on
the full textual structure of left-hand sides of equations, and not just on an
abstract notion of their meanings. As well as improving the techniques for
guaranteeing confluence, we should investigate nonconfluent term rewrit-
ing. Since, without confluence, term rewriting cannot be semantically com-
plete for equational logic, we need to consider other logical interpretations
of term rewriting rules.
A natural alternative to equational logic is subset logic [O'Donnell,
1987]. Subset logic has the same terms as equational logic, the formu-
lae are the same except that they use the backward subset relation symbol
D instead of = (Definition 2.3.13, Section 2.3.4 of the chapter 'Introduction:
Logic and Logic Programming Languages'). Subset logic semantics are the
same as equational (Definition 2.3.14, Section 2.3.4 of the 'Introduction
...' chapter ), except that every term represents a subset of the universe of
values instead of a single value, function symbols represent functions from
subsets to subsets that are extended pointwise from functions of individual
values (i.e., f ( S ) = U { f ( { x } ) : x € S}). Subset logic is complete with the
reflexive, transitive, and substitution rules of equality, omitting the sym-
150 Michael J. O'Donnell
metric rule (Definition 2.1.2, Section 2.1). So, term rewriting from left to
right is complete for subset logic, with no restrictions on the rules. Tech-
nically, it doesn't matter whether the left side of a rule is a subset of the
right, or vice versa, as long as the direction is always the same. Intuitively,
it seems more natural to think of rewriting as producing a subset of the
input term, since then a term may be thought of as denoting a set of pos-
sible answers. Thus, a single line of a subset logic program looks like / D r .
Note that normal forms do not necessarily denote singleton sets, although
it is always possible to construct models in which they do.
Subset logic programming naturally supports programs with indetermi-
nate answers. When a given input s rewrites to two different normal forms
t and M, subset logic merely requires that s 3 t and s D u are true, from
which it does not follow that t = u is true, nor t D u, nor u 2 t. While
equational logic programming extends naturally to infinite inputs and out-
puts, without changing its application to finite terms, such extension of
subset logic programming is more subtle. If only finite terms are allowed,
then infinite computations may be regarded as a sort of failure, and a finite
normal form must be found whenever one exists. If incremental output
of possibly infinite normal forms is desired, then there is no effective way
to give precedence to the finite forms when they exist. The most natural
idea seems to be to follow all possible rewriting paths, until one of them
produces a stable head symbol (that is, the head symbol of a strong head-
normal form) for output. Whenever such a symbol is output, all rewriting
paths producing different symbols at the same location are dropped. Only
a reduction path that has already agreed with all of the symbols that have
been output is allowed to generate further output. The details work out es-
sentially the same as with infinite outputs for equational programs, merely
substituting D for ==. It is not at all clear whether this logically natu-
ral notion of commitment to a symbol, rather than a computation path,
is useful. I cannot find a natural semantic scheme to support the more
conventional sort of commitment to a computation path instead of an in-
termediate term, although a user may program in such a way that multiple
consistent computation paths never occur and the two sorts of commitment
are equivalent.
Efficient implementation of nonconfluent rewriting presents a very in-
teresting challenge. It is obviously unacceptable to explore naively the
exponentially growing set of rewriting sequences. A satisfying implemen-
tation should take advantage of partial confluent behavior to prune the
search space down to a much smaller set of rewriting sequences that is still
capable of producing all of the possible outputs. The correct definition
of the right sort of partial confluence property is not even known. It is
not merely confluence for a subset of rules, since two rules that do not
interfere with one another may interfere differently with a third, so that
the order in which the two noninterfering rules are applied may still make
Equational Logic Programming 151
a difference to the outcome. Pattern-matching and sequencing techniques
must be generalized as well, and a good data structure designed to rep-
resent simultaneously the many different rewritings under consideration
as compactly as possible. A good complete implementation of noncon-
fluent rewriting will probably allow the prohibited terms in normal forms
(Definition 2.3.16, Section 2.3.4 of the chapter 'Introduction: Logic and
Logic Programming Languages') to be different from the left-hand sides of
rules. Sharing of equivalent subterms becomes problematic since it may be
necessary to reduce two different occurrences of the same subterm in two
different ways. The difficulties in discovering a complete implementation of
subset logic programming would be well rewarded, since this style of pro-
gramming can capture the useful indeterminate behavior of Prolog, while
avoiding the repeated generation of the same solution by slightly different
paths that slows some Prolog programs down substantially.
Even an incomplete implementation of nonconfluent rewriting might be
very valuable. In the spirit of logic programming, such an implementation
should depend on inherent structural properties of the rules in a program
to determine which of a set of possible rewriting steps is chosen when the
redex patterns overlap. From the point of view of implementation, the most
natural approach appears to be to select an outermost connected compo-
nent of overlapping redex patterns, but to rewrite within the component
from innermost out. It is not clear how to resolve the ambiguous case where
two redex patterns have the same root, nor has anyone proposed a sensi-
ble semantic explanation based on logic programming for any principle for
choosing between conflicting rules.
Jayaraman has a different concept of subset logic programming [Jayara-
man, 1992]. Meseguer's rewriting logic has the same rules as my subset
logic, with a different semantic justification. [Meseguer, 1992]
7.4 Relational rewriting
Equation solving can lead to a combination of Prolog and functional pro-
gramming through logic programming in the first-order predicate calculus
with equality. Subset logic programming, implemented with nonconfluent
term rewriting, can lead to an implementation of predicate calculus pro-
gramming in a sort of indeterminate functional programming. Another
intriguing way to reconcile some of the good qualities of Prolog and func-
tional programming is relational logic programming. Relational logic pro-
gramming can be approached as a generalization of terms to systems of
relational constraints, or as a purification of Prolog by removing the func-
tion symbols (called 'functors' in Prolog).
A relational formula is a FOPC formula with no function symbols (this
prohibition includes zeroary functions, or constants). The natural analogue
to a term in relational logic is a conjunction of atomic formulae, which may
be represented as a hypergraph (like a graph, but edges may touch more
152 Michael J. O'Donnell
than two nodes) with nodes standing for variables and hyperedges (edges
touching any number of nodes, not necessarily two) representing predicate
symbols. Two fundamental problems stand in the way of a useful imple-
mentation of relational logic programming through hypergraph rewriting.
1. We need an efficient implementation of hypergraph rewriting. The
pattern-matching problem alone is highly challenging, and no practi-
cal solution is yet known.
2. We need a semantic system that makes intuitive sense, and also sup-
ports computationally desirable methods of hypergraph rewriting.
A first cut at (2) might use the semantic system for FOPC, and express
rewrite rules as formulae of the form
These clauses differ from the Horn clauses of Prolog in two ways. The
quantification above is Vx : 3y :, where clauses are universally quantified.
And, the consequence of the implication above is a conjunction, where
Horn clauses allow at most one atomic formula in the consequence, and
even general clauses allow a disjunction, rather than a conjunction. No-
tice that, with Prolog-style all-universal quantification, the implication dis-
tributes over conjunctions in the consequence ((A\ A ^2) •<= B is equivalent
to (A1 4= B) A (A2 <= B)). But, if existentially quantified variables from y
appear in AI,..., Am, the distribution property does not hold.
Since the consequence and hypothesis of our formula are both con-
junctions of atomic formulae, they may be represented by hypergraphs,
and it is natural to read the formula as a hypergraph rewrite rule. A
natural sort of hypergraph rewriting will be sound for deriving univer-
sally quantified implications from V3 implications, as long as the exis-
tentially quantified variables y correspond to nodes in the graph that
participate only in the hyperedges representing Ai,...,Am. The uni-
versally quantified variables in x correspond to nodes that may connect
in other ways as well as by hyperedges representing A1,...,A m , so they
are the interface nodes to the unrewritten part of the hypergraph. In-
terestingly, the final result of a computation on input / is an implica-
tion VtZ? : I <= O. This implication does not give a solution to the goal
/, as in Prolog. Rather, it rewrites the goal / into a (presumably sim-
pler or more transparent) goal O, such that every solution to O is also
a solution to I. This is formally similar to functional and equational
logic programming, in that the class of legitimate outputs is a subclass
of the legitimate inputs—in Prolog inputs are formulae and outputs are
substitutions. Constraint logic programming [Jaffar and Lassez, 1987;
Lassez, 1991] is perhaps heading in this direction.
The semantic treatment suggested above is not very satisfactory, as it
Equational Logic Programming 153
rules out lazy evaluation, and even storage reclamation (an intermediate
part of a hypergraph that becomes disconnected from the input and out-
put cannot be thrown away, even though it cannot affect the nature of
a solution, since if any part of the hypergraph is unsolvable, the whole
conjunction is unsolvable). Also, the logically sound notion of unification
of the left-hand side of a rule with a portion of a hypergraph in order to
rewrite it seems far too liberal with this semantic system—without the
single-valued quality of functions, additional relations can be postulated
to hold anywhere. I conjecture that the first problem can be solved by a
semantic system in which every unquantified formula is solvable, so that a
disconnected portion of the hypergraph may be discarded as semantically
irrelevant. One way to achieve this would be to use some sort of measured
universe [Cohn, 1980], and require every atomic predicate to hold for all but
a subset of measure 0—then every finite intersection of atomic predicates
(equivalently, the value of every finite conjunction of atomic formulae) has
a solution. Such a semantic system is not as weird as it first seems, if we
understand the universe as a space of concepts, rather than real objects,
and think of each predicate symbol as giving a tiny bit of information about
a concept. We can conceive of every combination of information (such as a
green unicorn with a prime number of feet that is a large power of 2), even
though most such combinations never enter our notion of reality. Although
the question of solvability becomes trivial in this semantic system, impli-
cations between solutions still have interesting content. The problem of
limiting unifications in a useful way appears more difficult. I suggest that
nonclassical 'relevant' interpretations of implication [Anderson and Belnap
Jr., 1975] are likely to be helpful.
Acknowledgements
I am very grateful for the detailed comments that I received from the
readers, Bharat Jayaraman, Donald W. Loveland, Gopalan Nadathur and
David J. Sherman.
References
[Abramsky and Hankin, 1987] S. Abramsky and C. Hankin. Abstract In-
terpretation of Declarative Languages. Ellis Horwood, Chichester, UK,
1987.
[Aho et al., 1974] A. V. Aho, John E. Hopcroft, and J. D. Ullman. The
Design and Analysis of Computer Algorithms. Addison-Wesley, 1974.
[Anderson and Belnap Jr., 1975] Alan Ross Anderson and Nuel D. Belnap
Jr. Entailment—the Logic of Relevance and Necessity, volume 1. Prince-
ton University Press, Princeton, NJ, 1975.
[Antoy et al., 1994] Sergio Antoy, Rachid Echahed, and Michael Hanus. A
needed narrowing strategy. In Proceedings of the 21st ACM Symposium
154 Michael J. O'Donnell
on Principles of Programming Languages, pages 268-279. ACM, January
1994.
[Appel, 1991] Andrew Appel. Garbage collection. In Peter Lee, editor,
Topics in Advanced Language Implementation Techniques. MIT Press,
1991.
[Ashcroft and Wadge, 1985] E. A. Ashcroft and W. W. Wadge. Lucid, the
Dataflow Programming Language. Academic Press, London, UK, 1985.
[Augustsson, 1984] Lennart Augustsson. A compiler for lazy ML. In A CM
Symposium on Lisp and Functional Programming, August 1984.
[Backus, 1974] John Backus. Programming language semantics and closed
applicative languages. In Proceedings of the 1st ACM Symposium on
Principles of Programming Languages, pages 71-86. ACM, 1974.
[Backus, 1978] John Backus. Can programming be liberated from the von
Neumann style? a functional style and its algebra of programs. Com-
munications of the ACM, 21(8):613-641, 1978.
[Baird et al, 1989] T. Baird, G. Peterson, and R. Wilkerson. Complete
sets of reductions modulo associativity, commutativity, and identity. In
Proceedings of the 3rd International Conference on Rewriting Techniques
and Applications, volume 355 of Lecture Notes in Computer Science,
pages 29-44, 1989.
[Barendregt, 1984] Hendrik Peter Barendregt. The Lambda Calculus: Its
Syntax and Semantics. North-Holland, Amsterdam, 1984.
[Berry and Levy, 1979] Gerard Berry and Jean-Jacques Levy. Letter to the
editor, SIGACT News, 11, 3-4, 1979.
[Bird and Wadler, 1988] R. Bird and P. Wadler. Introduction to Functional
Programming. Prentice-Hall, New York, NY, 1988.
[Bloss et al., 147-164] A. Bloss, Paul Hudak, and J. Young. Code opti-
mizations for lazy evaluation. Lisp and Symbolic Computation: an In-
ternational Journal, 1, 147-164.
[Bobrow and Clark, 1979] D. Bobrow and D. Clark. Compact encodings
of list structure. A CM Transactions on Programming Languages and
Systems, l(2):266-286, 1979.
[Bondorf, 1989] Anders Bondorf. A self-applicable partial evaluator for
term-rewriting systems. In International Joint Conference on the Theory
and Practice of Software Development, volume 352 of Lecture Notes in
Computer Science. Springer-Verlag, 1989.
[Burn et al., 1988] G. L. Burn, Simon L. Peyton Jones, and J. D. Robson.
The spineless g-machine. In Proceedings of the 1988 ACM Conference
on Lisp and Functional Programming, pages 244-258, 1988.
[Cardelli, 1983] Luca Cardelli. The functional abstract machine. Polymor-
phism, 1(1), 1983.
Equational Logic Programming 155
[Cardelli, 1984] Luca Cardelli. Compiling a functional language. In Pro-
ceedings of the ACM Symposium on Lisp and Functional Programming,
August 1984.
[Chen and O'Donnell, 1991] Yiyun Chen and Michael James O'Donnell.
Testing confluence of nonterminating overlapping systems of rewrite
rules. In Conditional and Typed Rewriting Systems 2nd International
CTRS Workshop, Montreal, June 1990, volume 516 of Lecture Notes in
Computer Science, pages 127-136. Springer-Verlag, 1991.
[Chew, 1980] Leslie Paul Chew. An improved algorithm for computing
with equations. In 21st Annual Symposium on Foundations of Computer
Science, pages 108-117. IEEE, 1980.
[Chew, 1981] Leslie Paul Chew. Unique normal forms in term rewriting
systems with repeated variables. In 13th Annual ACM Symposium on
Theory of Computing, pages 7-18, 1981.
[Cohen, 1981] J. Cohen. Garbage collection of linked data structures. Com-
puting Surveys, 13(3), September 1981.
[Cohn, 1980] Donald L. Cohn. Measure Theory. Birkhauser, Boston, MA,
1980.
[Cousineau et al., 1985] G. Cousineau, P.-L. Curien, and M. Mauny. The
categorical abstract machine. In Symposium on Functional Programming
Languages and Computer Architecture, volume 201 of Lecture Notes in
Computer Science. Springer-Verlag, 1985.
[Cousot and Cousot, 1977] P. Cousot and R. Cousot. Abstract interpreta-
tion: A unified framework for static analysis of programs by construction
or approximation of fixpoints. In Fourth Annual ACM Symposium on
Principles of Programming Languages. ACM, 1977.
[Curry and Feys, 1958] H. B. Curry and R. Feys. Combinatory Logic, vol-
ume 1. North-Holland, Amsterdam, 1958.
[Demers et al., 1981] Alan Demers, Thomas Reps, and Tim Teitelbaum.
Incremental evaluation of attribute grammars with application to syntax-
directed editors. In Conference Record of the 13th Annual ACM Sym-
posium on Principles of Programming Languages, pages 105-116. ACM,
1981.
[Dershowitz, 1987] Nachum Dershowitz. Termination of rewriting. Journal
of Symbolic Computation, 3:69-116, 1987.
[Dershowitz et al., 1983] Nachum Dershowitz, Jieh Hsiang, N. Josephson,
and David A. Plaisted. Associative-commutative rewriting. In Proceed-
ings of the 8th International Joint Conference on Artificial Intelligence,
pages 940-944, August 1983.
[Dershowitz et al., 1991] Nachum Dershowitz, Simon Kaplan, and David
A. Plaisted. Rewrite, rewrite, rewrite, rewrite, rewrite. Theoretical Com-
puter Science, 83:71-96, 1991.
156 Michael J. O'Donnell
[Durand, 1994] Irene Durand. Bounded, strongly sequential, and forward-
branching term-rewriting systems. Journal of Symbolic Computation,
18, 319-352, 1994.
[Durand and Salinier, 1993] Irene Durand and Bruno Salinier. Constructor
equivalent term rewriting systems. Information Processing Letters, 47,
1993.
[Durand et al., 1991] Irene Durand, David J. Sherman, and Robert I.
Strandh. Optimization of equational programs using partial evaluation.
In Proceedings of the ACM/IFIP Symposium on Partial Evaluation and
Semantics-Based Program Manipulation, New Haven, CT, 1991.
[Fay, 1979] M. Fay. First order unification in equational theories. In Pro-
ceedings of the 4th Workshop on Automated Deduction, volume 87 of Lec-
ture Notes in Computer Science, pages 161-167. Springer-Verlag, 1979.
[Field and Harrison, 1988] A. J. Field and P. G. Harrison. Functional Pro-
gramming. Addison-Wesley, 1988.
[Field and Teitelbaum, 1990] John Field and Tim Teitelbaum. Incremen-
tal reduction in the lambda calculus. In Proceedings of the 1990 ACM
Conference on Lisp and Functional Programming, pages 307-322. ACM
Press, 1990.
[Friedman and Wise, 1976] Daniel Friedman and David S. Wise. Cons
should not evaluate its arguments. In 3rd International Colloquium on
Automata, Languages and Programming, pages 257-284. Edinburgh Uni-
versity Press, 1976.
[Futatsugi et al., 1985] K. Futatsugi, Joseph A. Goguen, J.-P. Jouannaud,
and Jose Meseguer. Principles of OBJ2. In 12th Annual Symposium on
Principles of Programming Languages, pages 52-66. ACM, 1985.
[Gallier, 1986] Jean H. Gallier. Logic for Computer Science—Foundations
of Automatic Theorem Proving. Harper & Row, New York, NY, 1986.
[Goguen, 1977] Joseph A. Goguen. Abstract errors for abstract data types.
In E. J. Neuhold, editor, Proceedings of IFIP Working Conference on
Formal Description of Program Concepts. North-Holland, 1977.
[Gonthier et al., 1992] Georges Gonthier, Martin Abadi, and Jean-Jacques
Levy. The geometry of optimal lambda reduction. In Conference Record
of the 19th Annual ACM Symposium on Principles of Programming Lan-
guages, pages 15-26. ACM, 1992.
[Guttag and Horning, 1978] John V. Guttag and J. J. Horning. The alge-
braic specification of abstract data types. Acta Informatica, 10(l):l-26,
1978.
[Guttag et al., 1983] John V. Guttag, Deepak Kapur, and David Musser.
On proving uniform termination and restricted termination of rewriting
systems. SIAM Journal on Computing, 12:189-214,1983.
Equational Logic Programming 157
[Henderson, 1980] P. Henderson. Functional Programming—Application
and Implementation. Prentice-Hall, 1980.
[Henderson and Morris, 1976] P. Henderson and J. H. Morris. A lazy eval-
uator. In 3rd Annual ACM Symposium on Principles of Programming
Languages, pages 95-103. SIGPLAN and SIGACT, 1976.
[Hoffmann and O'Donnell, 1979] C. M. Hoffmann and M. J. O'Donnell.
Interpreter generation using tree pattern matching. In 6th Annual Sym-
posium on Principles of Programming Languages, pages 169-179. SIG-
PLAN and SIGACT, 1979.
[Hoffmann and O'Donnell, 1982] C. M. Hoffmann and M. J. O'Donnell.
Pattern matching in trees. Journal of the ACM, 29(1):169-179, 1982.
[Hoffmann et al, 1985] C. M. Hoffmann, M. J. O'Donnell, and R. I.
Strandh. Implementation of an interpreter for abstract equations. Soft-
ware — Practice and Experience, 15(12):1185-1203,1985.
[Hudak, 1989] Paul Hudak. Conception, evolution, and application of func-
tional programming languages. ACM Computing Surveys, 21(3):359-411,
1989.
[Hudak, 1992] Report on the programming language Haskell, a non-strict,
purely functional language, version 1.2. ACM SIGPLAN Notices, 27(5),
May 1992.
[Hudak and Sundaresh, 1988] Paul Hudak and Raman S. Sundaresh. On
the expressiveness of purely functional I/O systems. Technical Report
YALEU/DCS/RR665, Yale University, New Haven, CT, December 1988.
[Huet, 1980] G. Huet. Confluent reductions: Abstract properties and appli-
cations to term rewriting. Journal of the ACM, 27(4):797-821, October
1980.
[Huet and Levy, 1991] Ge'rard Huet and Jean-Jacques Levy. Computa-
tions in orthogonal rewriting systems. In Jean-Louis Lassez and Gordon
Plotkin, editors, Computational Logic—Essays in Honor of Alan Robin-
son, pages 395-443. MIT Press, Cambridge, MA, 1991.
[Hughes, 1982] R. J. M. Hughes. Super-combinators: A new implementa-
tion method for applicative languages. In ACM Symposium on Lisp and
Functional Programming, August 1982.
[Hughes, 1985a] J. Hughes. Lazy memo-functions. In Functional Program-
ming Languages and Computer Architecture, volume 201 of Lecture Notes
in Computer Science, pages 129-146. Springer-Verlag, 1985.
[Hughes, 1985b] R. J. M. Hughes. Strictness detection in non-flat domains.
In Neil Jones and Harald Ganzinger, editors, Workshop on Programs
as Data Objects, volume 217 of Lecture Notes in Computer Science.
Springer-Verlag, 1985.
[iverson, 1962] K. E. Iverson. A Programming Language. John Wiley and
Sons, New York, NY, 1962.
158 Michael J. O'Donnell
[Jaffar and Lassez, 1987] Joxan Jaffar and Jean-Louis Lassez. Constraint
logic programming. In 14th Annual ACM Symposium on Principles of
Programming Languages, pages 111-119, 1987.
[Jayaraman, 1985] Bharat Jayaraman. Equational programming: A uni-
fying approach to functional and logic programming. Technical Report
85-030, The University of North Carolina, 1985.
[Jayaraman, 1992] Bharat Jayaraman. Implementation of subset-
equational programming. The Journal of Logic Programming, 12(4),
April 1992.
[Johnsson, 1984] Thomas Johnsson. Efficient compilation of lazy evalua-
tion. In Proceedings of the ACM SIGPLAN'84 Symposium on Compiler
Construction, 1984. SIGPLAN Notices 19(6) June, 1984.
[Kahn and Plotkin, 1978] Gilles Kahn and Gordon Plotkin. Domaines con-
crets. Technical report, IRIA Laboria, LeChesnay, France, 1978.
[Kapur et al, 1982] Deepak Kapur, M. S. Krishnamoorthy, and P. Naren-
dran. A new linear algorithm for unification. Technical Report 82CRD-
100, General Electric, 1982.
[Karlsson, 1981] K. Karlsson. Nebula, a functional operating system. Tech-
nical report, Chalmers University, 1981.
[Karp, 1964] Carol R. Karp. Languages with Expressions of Infinite Length.
North-Holland, Amsterdam, 1964.
[Kathail, 1984] Arvind and Vinod Kumar Kathail. Sharing of computation
in functional langauge implementations. In Proceedings of the Interna-
tional Workshop on High-Level Computer Architecture, 1984.
[Keller and Sleep, 1986] R. M. Keller and M. R. Sleep. Applicative caching.
ACM Transactions on Programming Languages and Systems, 8(1):88-
108, 1986.
[Kenneway et ai, 1991] J. R. Kenneway, Jan Willem Klop, M. R. Sleep,
and F. J. de Vries. Transfinite reductions in orthogonal term rewriting
systems. In Proceedings of the 4th International Conference on Rewriting
Techniques and Applications, volume 488 of Lecture Notes in Computer
Science. Springer-Verlag, 1991.
[Klop, 1980] Jan Willem Klop. Combinatory Reduction Systems. PhD
thesis, Mathematisch Centrum, Amsterdam, 1980.
[Klop, 1991] Jan Willem Klop. Term rewriting systems. In S. Abramsky,
Dov M. Gabbay, and T. S. E. Maibaum, editors, Handbook of Logic in
Computer Science, volume 1, chapter 6. Oxford University Press, Oxford,
1991.
[Klop and Middeldorp, 1991] Jan Willem Klop and A. Middeldorp. Se-
quentiality in orthogonal term rewriting systems. Journal of Symbolic
Computation, 12:161-195,1991.
Equational Logic Programming 159
[Knuth, 1973] Donald E. Knuth. The Art of Computer Programming—
Sorting and Searching, volume 3. Addison-Wesley, Reading, MA, 1973.
[Knuth and Bendix, 1970] Donald E. Knuth and P. Bendix. Simple word
problems in universal algebras. In J. Leech, editor, Computational Prob-
lems in Abstract Algebra, pages 127-146. Pergamon Press, Oxford, 1970.
[Koopman, 1990] Philip J. Koopman. An Architecture for Combinator
Graph Reduction. Academic Press, Boston, MA, 1990.
[Koopman and Lee, 1989] Philip J. Koopman and Peter Lee. A fresh look
at combinator graph reduction. In Proceedings of the SIGPLAN'89 Con-
ference on Programming Language Design and Implementation, October
1989.
[Lamping, 1990] John Lamping. An algorithm for optimal lambda calculus
reduction. In Conference Record of the 17th Annual ACM Symposium
on Principles of Programming Languages, pages 16-30. ACM, 1990.
[Landin, 1965] P. J. Landin. A correspondence between ALGOL 60 and
Church's lambda-notation: Part I. Communications of the ACM,
8(2):89-101, 1965.
[Lassez, 1991] Jean-Louis Lassez. Prom LP to CLP: Programming with
constraints. In T. Ito and A. R. Meyer, editors, Theoretical Aspects of
Computer Software: International Conference, volume 526 of Lecture
Notes in Computer Science. Springer-Verlag, 1991.
[Levy, 1978] Jean-Jacques Levy. Reductions Correctes et Optimales dans
le Lambda-Calcul. PhD thesis, Universite Paris, January 1978.
[Lieberman and Hewitt, 1983] Henry Lieberman and Carl Hewitt. A real-
time garbage collector based on the lifetimes of objects. Communications
of the ACM, 26(6):419-429, June 1983.
[Loveland, 1978] Donald W. Loveland. Automated Theorem Proving: A
Logical Basis. Elsevier North-Holland, New York, NY, 1978.
[Machtey and Young, 1978] Michael Machtey and Paul Young. An Intro-
duction to the General Theory of Algorithms. Theory of Computation.
North-Holland, New York, NY, 1978.
[Martelli and Montanari, 1976] A. Martelli and U. Montanari. Unification
in linear time and space: A structured presentation. Technical Report
B76-16, Institut di Elaborazione delle Informazione, Consiglio Nazionale
delle Ricerche, Pisa, Italy, 1976.
[McCarthy, I960] John McCarthy. Recursive functions of symbolic expres-
sions and their computation by machine, part I. Communications of the
ACM, 3(4):184-195, 1960.
[McCarthy et al., 1965] John McCarthy, Paul W. Abrahams, Daniel J. Ed-
wards, Timothy P. Hart, and Michael I. Levin. LISP 1.5 Programmer's
Manual. MIT Press, Cambridge, MA, 1965.
[Meseguer, 1992] Jose Meseguer. Multiparadigm logic programming. In
160 Michael J. O'Donnell
H. Kirchner and G. Levi, editors, Proceedings of the 3rd Interna-
tional Conference on Algebraic and Logic Programming, Volterra, Italy,
September 1992, Lecture Notes in Computer Science. Springer-Verlag,
1992.
[Mitchie, 1968] D. Mitchie. 'Memo' functions and machine learning. Na-
ture, 1968.
[Mycroft, 1980] Alan Mycroft. The theory and practice of transforming
call-by-need into call-by-value. In International Symposium on Program-
ming, volume 83 of Lecture Notes in Computer Science. Springer-Verlag,
1980.
[Newman, 1942] M. H. A. Newman. On theories with a combinatorial
definition of 'equivalence'. Annals of Mathematics, 43(2):223-243, 1942.
[O'Donnell, 1977] Michael James O'Donnell. Computing in Systems De-
scribed by Equations, volume 58 of Lecture Notes in Computer Science.
Springer-Verlag, 1977.
[O'Donnell, 1979] Michael James O'Donnell. Letter to the editor, SIGACT
News, 11, 2, 1979.
[O'Donnell, 1985] Michael James O'Donnell. Equational Logic as a Pro-
gramming Language. Foundations of Computing. MIT Press, Cambridge,
MA, 1985.
[O'Donnell, 1987] Michael James O'Donnell. Tree-rewriting implementa-
tion of equational logic programming. In Pierre Lescanne, editor, Rewrit-
ing Techniques and Applications — Bordeaux, France, May 1987 — Pro-
ceedings, volume 256 of Lecture Notes in Computer Science. Springer-
Verlag, 1987.
[Peyton Jones, 1987] Simon L. Peyton Jones. The Implementation of Func-
tional Programming Languages. Prentice-Hall, Englewood Cliffs, NJ,
1987.
[Pingali and Arvind, 1985] Keshav Pingali and Arvind. Efficient demand-
driven evaluation, part 1. ACM Transactions on Programming Lan-
guages and Systems, 7(2):311-333, April 1985.
[Pingali and Arvind, 1986] Keshav Pingali and Arvind. Efficient demand-
driven evaluation, part 2. ACM Transactions on Programming Lan-
guages and Systems, 8(1):109-139, January 1986.
[Pugh and Teitelbaum, 1989] William Pugh and Tim Teitelbaum. Incre-
mental computation via function caching. In Conference Record of the
Sixteenth Annual ACM Symposium on Principles of Programming Lan-
guages, pages 315-328. ACM, 1989.
[Ramakrishnan and Sekar, 1990] I. V. Ramakrishnan and R. C. Sekar. Pro-
gramming in equational logic: Beyond strong sequentiality. In Proceed-
ings of the IEEE Conference on Logic in Computer Science, 1990.
[Rebelsky, 1992] Samuel A. Rebelsky. I/O trees and interactive lazy func-
Equational Logic Programming 161
tional programming. In Maurice Bruynooghe and Martin Wirsing, ed-
itors, Proceedings of the 4th International Symposium on Programming
Language Implementation and Logic Programming, volume 631 of Lec-
ture Notes in Computer Science, pages 458-472. Springer-Verlag, August
1992.
[Rebelsky, 1993] Samuel A. Rebelsky. Tours, a System for Lazy Term-based
Communication. PhD thesis, The University of Chicago, June 1993.
[Robinson and Wos, 1969] G. A. Robinson and L. Wos. Paramodulation
and theorem-proving in first-order logic with equality. Machine Intelli-
gence, 4:135-150, 1969.
[Sherman, 1990] David J. Sherman. Lazy directed congruence closure.
Technical Report 90-028, The University of Chicago, 1990.
[Spitzen et al, 1978] Jay M. Spitzen, Karl N. Levitt, and Lawrence Robin-
son. An example of hierarchical design and proof. Communications of
the ACM, 21 (12):1064-1075, December 1978.
[Staples, 1982] John Staples. Two-level expression representation for faster
evaluation. In Hartmut Ehrig, Manfred Nagl, and Grzegorz Rozenberg,
editors, Graph Grammars and their Application to Computer Science:
2nd International Workshop, volume 153 of Lecture Notes in Computer
Science. Springer-Verlag, 1982.
[Strandh, 1984] R. I. Strandh. Incremental suffix trees with multiple sub-
ject strings. Technical Report JHU/EECS-84/18, The Johns-Hopkins
University, 1984.
[Strandh, 1988] Robert I. Strandh. Compiling Equational Programs into
Efficient Machine Code. PhD thesis, The Johns Hopkins University,
Baltimore, MD, 1988.
[Strandh, 1989] Robert I. Strandh. Classes of equational programs that
compile into efficient machine code. In Proceedings of the 3rd Interna-
tional Conference on Rewrite Techniques and Applications, 1989.
[Thatte, 1985] Satish Thatte. On the correspondence between two classes
of reduction systems. Information Processing Letters, 1985.
[Turner, 1979] D. A. Turner. A new implementation technique for applica-
tive languages. Software—Practice and Experience, 9:31-49, 1979.
[Wand, 1976] Mitchell Wand. First order identities as a defining language.
Ada Informatica, 14:336-357, 1976.
[Warren, 1983] David H. D. Warren. An abstract Prolog instruction set.
Technical Report 309, Artificial Intelligence Center, SRI International,
Menlo Park, CA, October 1983.
[Winksel, 1993] Glynn Winksel. The Formal Semantics of Programming
Languages—An Introduction. Foundations of Computing. MIT Press,
Cambridge, MA, 1993.
This page intentionally left blank
Proof Procedures for Logic
Programming
Donald W. Loveland and Gopalan Nadathur
Contents
1 Building the framework: the resolution procedure . . . . 163
1.1 The resolution procedure 164
1.2 Linear resolution refinements 175
2 The logic programming paradigm 186
2.1 Horn clause logic programming 186
2.2 A framework for logic programming 190
2.3 Abstract logic programming languages 198
3 Extending the logic programming paradigm 212
3.1 A language for hypothetical reasoning 213
3.2 Near-Horn Prolog 219
4 Conclusion 229
1 Building the framework: the resolution procedure
A proof procedure is an algorithm (technically, a semi-decision procedure)
which identifies a formula as valid (or unsatisfiable) when appropriate, and
may not terminate when the formula is invalid (satisfiable). Since a proof
procedure concerns a logic the procedure takes a special form, superimpos-
ing a search strategy on an inference calculus. We will consider a certain
collection of proof procedures in the light of an inference calculus format
that abstracts the concept of logic programming. This formulation al-
lows us to look beyond SLD-resolution, the proof procedure that underlies
Prolog, to generalizations and extensions that retain an essence of logic
programming structure.
The inference structure used in the formulation of the logic program-
ming concept and first realization, Prolog, evolved from the work done in
the subdiscipline called automated theorem proving. While many proof
procedures have been developed within this subdiscipline, some of which
appear in Volume 1 of this handbook, we will present a narrow selection,
164 Donald W. Loveland and Gopalan Nadathur
namely the proof procedures which are clearly ancestors of the first proof
procedure associated with logic programming, SLD-resolution. Extensive
treatment of proof procedures for automated theorem proving appear in
Bibel [Bibel, 1982], Chang and Lee [Chang and Lee, 1973] and Loveland
[Loveland, 1978].
1.1 The resolution procedure
Although the consideration of proof procedures for automated theorem
proving began about 1958 we begin our overview with the introduction of
the resolution proof procedure by Robinson in 1965. We then review the
linear resolution procedures, model elimination and SL-resolution proce-
dures. Our exclusion of other proof procedures from consideration here
is due to our focus, not because other procedures are less important his-
torically or for general use within automated or semi-automated theorem
process.
After a review of the general resolution proof procedure, we consider
the linear refinement for resolution and then further restrict the proce-
dure format to linear input resolution. Here we are no longer capable of
treating full first-order logic, but have forced ourselves to address a smaller
domain, in essence the renameable Horn clause formulas. By leaving the
resolution format, indeed leaving traditional formula representation, we see
there exists a linear input procedure for all of first-order logic. This is the
model elimination(ME) procedure, of which a modification known as the
SL-resolution procedure was the direct inspiration for the SLD-resolution
procedure which provided the inference engine for the logic programming
language Prolog. The ME-SL-resolution linear input format can be trans-
lated into a very strict resolution restriction, linear but not an input re-
striction, as we will observe.
The resolution procedure invented by Alan Robinson and published in
1965 (see [Robinson, 1965]) is studied in depth in the chapter on resolution-
based deduction in Volume 1 of this handbook, and so quickly reviewed
here. The resolution procedure is a refutation procedure, which means
we establish unsatisfiability rather than validity. Of course, no loss of
generality occurs because a formula is valid if and only if (iff) its negation
is unsatisfiable. The formula to be tested for unsatisfiability is "converted
to conjunctive normal form with no existential quantifiers present". By this
we mean that with a given formula F to be tested for unsatisfiability, we
associate a logically equivalent formula F' which is in conjunctive normal
form (a conjunction of clauses, each clause a disjunction of atomic formulas
or negated atomic formulas, called literals) with no existential quantifiers.
F' may be written without any quantifiers, since we regard F, and therefore
F', as a closed formula, so the universal quantifiers are implicitly assumed
to be present preceding each clause. (Thus we are free to rename variables
of each clause so that no variable occurs in more than one clause.) The
Proof Procedures for Logic Programming 165
formula F' is derivable from F by standard logical equivalences plus the
use of Skolem functions to replace quantifiers. We shall say that F' is in
Skolem conjunctive form and that F1 is the Skolem conjunctive form of F.
Precise algorithms for conversion are given in many textbooks, including
Chang and Lee [Chang and Lee, 1973] and Loveland [Loveland, 1978].
The formula
is the Skolem conjunctive form of
where g(x) is a Skolem function introduced for the y that occurs in the
intermediate formula
(Recall that an existentially quantified variable is replaced by a new func-
tion letter followed by arguments consisting of all universally quantified
variables where the universal quantifier contains the existential quantifier
within its scope.) The formula
has
as its Skolem conjunctive form formula, where a is a Skolem function having
0 arguments. Note that in this example immediate Skolemization, before
applying the distributive law and then importing the quantifiers, would
have introduced a Skolem function f(z) instead of the Skolem constant a
used above. For pragmatic reasons regarding the cost of search in auto-
mated proof procedures it is best to seek Skolem functions with the fewest
number of arguments. We have adopted the traditional logic notation of
capital letters for predicate letters, and non-capitals for variables, func-
tion and constant letters. Variables are represented by end of the alphabet
letters.
For those accustomed to logic programming notation, based on clauses
as implications, it is a natural question to ask: why use conjunctive normal
form? The resolution procedure (and hence its restrictions) does not dis-
tinguish between positive literals (atomic formula, or atoms) and negative
literals (negated atoms). Also, the general resolution procedure (and many
variants) requires symmetric calling access to all literals of a clause. Thus
the symmetry of OR as the connective in the clause is very suitable. Of
course, we could present the entire set of procedures using implicative form
but there is no insight gained and the presentation would differ from the
traditional presentations for no essential reason. Therefore, we will invoke
166 Donald W. Loveland and Gopalan Nadathur
a notation change in the middle of the paper, but this reflects common
sense and historical precedent, so we forsake uniform notation.
Resolution procedures are based on the resolution inference rule
C1 V a ->a V C2
where C1 V a and ->a V C2 are two known clauses, with C1 and C2 repre-
senting arbitrary disjuncts of literals. The literals a and ->a are called the
resolving literals. The derived clause is called the resolvent. The similarity
of the inference rule to Gentzen's cut rule is immediately clear and the rule
can be seen as a generalization of modus ponens. The resolvent is true in
any model for the two given clauses, so the inference rule preserves validity.
The resolution inference rule just given is the prepositional rule, also
called the ground resolution rule for a reason given later. We postpone
discussion of the very similar first-order inference rule to delay some com-
plications.
Because the Skolem conjunctive format is so uniform in style, it is con-
venient to simplify notation when using it. We drop the OR symbol in
clauses and instead simply concatenate literals. Clauses themselves are ei-
ther written one per line or separated by commas. When the non-logical
symbols are all single letters it is also convenient to drop the parentheses as-
sociated with predicate letters and the commas between arguments. Thus
the Skolem conjunctive form formula (P(a) V P(b)) A (-'P(a)) A (~P(b)) is
shortened to PaPb, –Pa, –Pb by use of the simplifying notation.
Using the just-introduced shorthand notation for a formula in this form,
often called a clause set, we present a refutation of a clause set. We use
the terms input clause to designate a clause from the input clause set given
by the user to distinguish such clauses from derived clauses of any type.
1. PaPb input clause
2. Pa–Pb input clause
3. –PaPb input clause
4. –Pa–Pb input clause
5. Pa resolvent of clauses 1, 2
6. –Pa resolvent of clauses 3, 4
7. contradiction Pa and –Pa cannot both hold
Note that in line 5 the two identical literals are merged.
Since each resolvent is true in any model satisfying the two parent
clauses, a satisfiable clause set could not yield two contradictory unit
clauses. Thus Pa, -Pa signals an unsatisfiable input clause set. The
resolution inference rule applied to Pa and -Pa yields the empty clause,
denoted D. This is customarily entered instead of the word "contradiction",
as we do hereafter.
Proof Procedures for Logic Programming 167
We have noted that the ground resolution inference system is sound,
i.e. will not deduce D if the original clause set is satisfiable. We now
note that this inference system is complete, i.e. for every propositional
unsatisfiable clause set there is a resolution refutation. A proof appears
in Chang and Lee [Chang and Lee, 1973] or Loveland [Loveland, 1978].
A proof by induction on the number of "excess" literal occurrences in the
clause set (the number of literal occurrences minus the number of clauses in
the set) is not difficult and the reader may enjoy trying the proof himself.
Above, we have given a proof of unsatisfiability, or a refutation. There
is no indication there as to how such a proof might be found. Descriptions
of search algorithms that employ the resolution inference rule comprise
proof procedures for resolution. Perhaps the most natural proof procedure
for resolution is the level saturation procedure, where all resolvents at a
certain level are determined before beginning the next level. Because we
enumerate all resolvents eventually, we have a complete proof procedure.
We define all the given, or input, clauses to be at level 0. A resolvent is
at level k + 1 if the parent clauses are at level k and j, for j < k. For the
preceding example we list the clauses by level:
Level 0: PaPb, Pa-Pb, -PaPb, -Pa-Pb
Level 1: Pa, Pb, -Pa, -Pb, -PaPa, -PbPb
Level 2: D , and all Level 0 and Level 1 clauses.
Level 2 resolvents include all previously obtained clauses because the tau-
tologies -PaPa and -PbPb as one parent clause will always produce the
other parent clause as the resolvent. Thus we can remove tautologies with-
out affecting completeness. This is true for almost all resolution restric-
tions also. (An exception can occur when clauses are ordered, such as in
the locking, or indexing, strategy. For example, see Loveland [1978].)
Other deletion rules can be advantageous, given that only clause D is
sought. Once Pa is produced, resolving thereafter with PaPb or Pa-Pb
is counterproductive because the resolvents again contain Pa. It is almost
immediate that, when trying to derive the (length 0) clause D, there is no
need to retain a clause that contains another existing clause as a subclause.
Eliminating a clause C1 V C2 when C2 also exists, for clauses C1 and C2, is
known as subsumption elimination. This generalizes at the first-order level
(noted later) and can get reasonably technical, with various options. This
is studied in detail in Loveland [1978]. Also see Wos et al. [1991].
A variant of the level saturation proof procedure that has proved useful
in practice employs a unit preference search strategy. (See Wos et al. [Wos
et al., 1964].) Here resolvents at higher levels than the current level being
"saturated" are computed whenever one of the parents is a unit clause
(one-literal clause). The intuition here is that the resolvent is always at
least one literal less in cardinality ("shorter") than the longer parent clause,
which is progress since the goal clause is the empty clause, having length 0.
168 Donald W. Loveland and Gopalan Nadathur
Except for merging, these unit clause resolutions must be the resolutions
that occur near the end of refutations, so it makes sense to "look ahead"
in this limited way.
Having treated the level-saturation resolution proof procedure, which is
a breadth-first search ordering, it is natural to ask about depth-first search
procedures. This is of particular interest to logic programmers who know
that this is the search order for Prolog. We want to do this in a manner
that preserves completeness. (Why it is desirable to preserve completeness
is a non-trivial question, particularly at the first-order level where searches
need not terminate and the combinatorial explosion of resolvent produc-
tion is the dominant problem. Two points speak strongly for considering
completeness: 1) these inference systems have such a fine-grained inference
step that incompleteness in the inference proof procedures leads to some
very simple problems being beyond reach and 2) it is best to understand
what one has to do to maintain completeness to know what price must
be paid if completeness is sacrificed. We will make some further specific
comments on this issue later.)
Before presenting a depth-first proof procedure let us observe that at the
prepositional, or ground, level there are only a finite number of resolvents
possible beginning with any given (finite) clause set. This follows directly
from two facts: 1) no new atoms are created by the resolution inference
rule, and 2) a literal appears at most once in a clause, so there is an upper
bound on the number of literals in any resolvent.
A straightforward depth-first proof procedure proceeds as follows. If
there are n input clauses then we temporarily designate clause n as the focus
clause. In general the focus clause is the last resolvent still a candidate for
inclusion in a resolution refutation (except for the first clause assignment,
to clause n). We begin by resolving focus clause n against clause 1, then
clause 2, etc. until a new non-subsumed non-tautological clause is created
as a resolvent. This resolvent is labeled clause n+1 and becomes the new
focus clause. It is resolved against clause 1, clause 2, etc. until a new clause
is created that is retained. This becomes the new focus clause and the
pattern continues. If D is obtained the refutation is successful. Otherwise,
some focus clause m creates no new surviving clause and backtracking is
begun. The clause m — 1 is relabeled the focus clause (but clause m is
retained) and clause m — 1 is resolved against those clauses not previously
tried, beginning with clause j + 1 where clause j is the clause that paired
with clause m — 1 to produce clause m. The first retained resolvent is
labeled clause m + 1. Clause m + 1 now becomes the focus clause and the
process continues as before. This backtracking is close to the backtracking
employed by Prolog.
The above depth-first procedure does differ from that used in Prolog,
however. The primary difference is that after one backtracks from a clause
that yields no new resolvent, the clause is not removed. If we are interested
Proof Procedures for Logic Programming 169
in a complete procedure then we might need to consider using this "aban-
doned" clause C with clauses of higher index not yet defined, and hence not
yet tried with C. Suppose hypothetically that a four clause given set has
only the following resolution refutation (excluding renumbering): clause 3
and clause 4 create a resolvent (clause 5), clause 1 and clause 2 create a
resolvent (clause 6), and D is the resolvent of clause 5 and clause 6. The
depth-first search starts its search by creating clause 5 as before, failing
to create any new resolvent using clause 5, and backtracks by restarting
with clause 4. Clause 4 first pairs with itself, but automatically skips this
since no nontautologous clause resolves with itself, and fails when paired
with clause 5. We have exhausted our first chosen focus clause; when this
happens the backtracking continues backwards through all clauses. Thus,
clause 3 is the new focus clause, does create a resolvent when paired with
clause 4, but that is subsumed by (is identical to) clause 5. Clause 3 sub-
sequently fails as the focus clause and clause 2 becomes the focus clause,
and produces a resolvent when paired with clause 1. This new clause 6
immediately becomes the focus clause, is eventually paired with clause 5
and D is produced. The point of all this is that clause 5 had to be retained
to be used when clause 6 was finally created.
The reader may object to the supposition that clause 5 fails to produce
any resolvent, but the contention that it would always pair with a lower
indexed clause if it is ever used in a refutation would require a theorem
about behavior of resolution refutations. The depth-first search utilized
here is simply designed to sweep the same proof space as swept by the
breadth-first search, but in a different order.
It does happen that clauses that exhaust their pairings and force a back-
track do not need to be retained. (That is, clause 5 above would either yield
a resolvent under some pairing or could be removed upon backtracking.)
This is a consequent of the existence of linear resolution refinements. The
linear refinement asserts that if a clause set is unsatisfiable then there is a
resolution refutation such that each resolvent has the preceding clause as
one of the parent clauses and the other parent clause must appear earlier
in the deduction or be an input clause. The preceding parent clause is
called the near parent clause. The other clause, the far parent clause, can
be defined more precisely as follows: The far parent clause must be either
an input clause or an ancestor clause, where the set of ancestor clauses of a
clause C is the smallest set of clauses containing the near parent clause of
C and the ancestors of the near parent clause of C. Again note that this is
a condition on proof form, not on search. There exists a linear refutation
with any input clause as first near-parent clause if that clause is in a mini-
mally unsatisfiable subset of the input clauses. We call the first near-parent
clause the top clause of the linear deduction. We give a linear refutation of
the clause set given earlier. It is common to list the top clause as the last
input clause.
170 Donald W. Loveland and Gopalan Nadathur
A linear refutation:
1. PaPb input clause
2. Pa-Pb input clause
3. -PaPb input clause
4. -Pa-Pb input clause
5. -Pb resolvent of 2, 4
6. Pa resolvent of 1,5
7. Pb resolvent of 3,6
8. a resolvent of 5,7
The last step in the above refutation involved two resolvents. This is
true of every refutation of this clause set, since no input clause is a one-
literal clause and D must have two one-literal parents. This provides an
example that not every clause set has a linear refutation where the far
parent is always a input clause. Clauses 4, 5 and 6 are the ancestors of
clause 7 in the above example. This definition of ancestor omits clauses 1,
2 and 3 as ancestors of clause 7 but our intent is to capture the derived
clauses used in the derivation of clause 7.
The linear restriction was independently discovered by Loveland (see
[Loveland, 1970], where the name linear was introduced and a stronger re-
striction s-linear resolution also was introduced) and by Luckham (where
the name ancestor filter was used; see [Luckham, 1970].) A proof of com-
pleteness of this restriction also is given in Chang and Lee [Chang and Lee,
1973] and Loveland [Loveland, 1978].
With this result we can organize our depth-first search to discard any
clause when we backtrack due to failure of that clause to lead to a proof.
It follows that we need only try a given resolvent with clauses of lower
index than the resolvent itself and that all retained resolvents are elements
of the same (linear) proof attempt. Use of this restriction permits a great
saving in space since only the current proof attempt clauses are retained.
However, a large cost in search effectiveness may be paid because of much
duplication of resolvent computation. In a proof search the same clause (or
close variant) is often derived many times through different proof histories.
In a breadth-first style search the redundant occurrences can be eliminated
by subsumption check. This is a check not available when resolved clauses
are eliminated upon backtracking as usually done in the depth-first linear
resolution procedures. Each recreation of a clause occurrence usually means
a search to try to eliminate the occurrence. This produces the high search
price associated with depth-first search procedures.
The redundant search problem suffered by depth-first linear resolution
procedures may make this approach unwise for proving deep mathematical
theorems, where much computation is needed and few heuristic rules exist
to guide the search. Depth-first linear resolution is often just the right pro-
cedure when there is a fairly strong guidance mechanism suggesting which
Proof Procedures for Logic Programming 171
clauses are most likely to be useful at certain points in the search. This
principle is at work in the success of Prolog, which implements a depth-first
linear strategy. When using Prolog, the user generally uses many predi-
cate names, which means that relatively few literals are possible matches.
This trims the branching rate. Secondly, the user orders the clauses with
knowledge of how he expects the computation to proceed. Clearly, when
some information exists to lead one down essentially correct paths, then
there is a big win over developing and retaining all possible deductions to
a certain depth. Besides logic programming applications, the depth-first
approach is justified within artificial intelligence (AI) reasoning system ap-
plications where the search may be fairly restricted with strong heuristic
guidance. When such conditions hold, depth-first search can have an ad-
ditional advantage in that very sophisticated implementation architectures
exist (based on the Warren Abstract Machine; see [Ait-Kaci, 1990]) allow-
ing much higher inference rates (essentially, the number of resolution opera-
tions attempted) than is realized by other procedure designs. This speed is
realized for a restricted linear form called linear input procedures, which we
discuss later, which is usually implemented using depth-first search mode.
It is important to realize that the linear resolution restriction need not
be implemented in a depth-first manner. For example, one might begin with
several input clauses "simultaneously" (either with truly parallel compu-
tation on a parallel computer or by interleaving sequential time segments
on a sequential machine) and compute all depth n + 1 resolvents using
all depth n parents before proceeding to depth n + 2 resolvents. This
way subsumption can be used on the retained clauses (without endanger-
ing completeness) yet many resolution rule applications are avoided, such
as between two input clauses not designated as start clauses for a linear
refutation search.
The mode of search described above is very close to the set-of-support
resolution restriction introduced by Wos et al. [1964; 1965]. A refutation
of a clause set S with set-of-support T C S is a resolution refutation where
every resolvent has at least one parent a resolvent or a member of T. Thus
two members of S — T cannot be resolved together. To insure completeness
it suffices to determine that S—T is a satisfiable set. The primary difference
between this restriction and the quasi-breadth-first search for linear resolu-
tion described in the preceding paragraph is that for the linear refutation
search of the previous paragraph one could choose to segregate clauses by
the deduction responsible for its creation (labeled by initial parents), and
not resolve clauses from different deductions. This reduces the branching
factor in the search tree. If this is done, then any subsuming clause must
acquire the deduction label of the clause it subsumes. The resulting refu-
tation will not be linear if a subsuming clause is utilized, but usually the
refutation existence, and not the style of refutation, is what matters. One
could call such refutations locally linear refutations. Loveland [Loveland,
172 Donald W. Loveland and Gopalan Nadathur
1978] discusses linear restrictions with subsumption.
Before concluding this discussion of search strategies, we consider ori-
ented clause sets. So far, we have treated the clause set as non-oriented, in
that no clause or subset of clauses received special notice a priori. Such is
the situation when an arbitrary logical formula is tested for unsatisfiabil-
ity. However, often the clause set derives from a theorem of form A D B,
where A is a set of axioms of some theory and B is the theorem statement
believed to hold in the theory. Analogously, A may be viewed as a logic
programming program and B is the query. It is well-known that testing
the validity of A D B answers the question: Is B a logical consequence of
A?
We test A D B for validity by testing A A -B for unsatisfiability. The
conversion to Skolem conjunctive form of A A -B permits A and -B to
be converted separately and the two clause sets conjoined. The clause set
5A from A is called the theory base, database or axiom set, and the clause
set SB from -B is called the goal set, query set or theorem statement
(set). In practice, the cardinality of set 5A is usually much larger than the
cardinality of SB. Also, there is often no assurance that all the clauses of
SA are needed in the proof, whereas usually all clauses of SB are needed.
Moreover, SA is usually a consistent clause set. Thus, the support set T is
usually a subset of SB, and linear refutations are started with one parent
from SB.
In this oriented clause set setting there are natural notions of direction of
search. A linear refutation with one parent from SB is called a backchain-
ing, goal-oriented, or top-down refutation and the associated search is a
backchaining or goal-oriented search. If the linear refutation begins with
both parents from SA then it is a forward chaining, forward-directed, or
bottom-up refutation, with the same labels applied to the associated search.
The same labels apply to the set-of-support refinement with support set
T C SB or T C 5A. If top-down and bottom-up refutations are sought
simultaneously, then the search is said to be bidirectional. The idea of bidi-
rectionality is to share resolvents between the bottom-up and top-down
searches, in effect having search trees growing bottom-up and top-down
which meet and provide a complete proof path from data to goal. If this
occurs, the search trees involved are roughly half the depth of a search
tree strictly top-down or a tree strictly bottom-up. Since the number of
tree nodes (resolvents) of any level generally grows exponentially with the
depth of the level a tremendous potential savings exists in search size. Au-
tomated theorem provers use bidirectional search sometimes, but use is by
no means universal. One problem is what clauses from 5A are appropriate.
In back-chaining systems, often definitions are expanded forward several
steps, a case of forward chaining.
A study of bidirectional search in a more general setting that resolu-
tion inference was done by Pohl [Pohl, 1971]. A related study on search
Proof Procedures for Logic Programming 173
strategies, explicitly considering resolution, is given in Kowalski [Kowalski,
1970].
Before proceeding to further restrictions of resolution we need to present
the first-order version of the resolution procedure. The more c