Academia.eduAcademia.edu

A framework for efficient execution of logic programs

1989

The focus of this dissertation is to develop an efficient framework for sequential execution of logic programs. Within this framework the logic programs are executed by pruning the goal-search tree whenever applicable. Three new concepts for pruning of computation during execution of logic programs are introduced. (1) Failure-binding. A Failure-binding for a literal is a binding which when applied to the literal fails the goal obtained from the literal. Failure-bindings for a literal are identified by analyzing the goal-tree of a goal which is obtained from the literal. The failure-bindings for a literal are used for intelligent backtracking based on the generator-consumer approach. Intelligent backtracking based on failure-bindings prune the computation of search space which lead to late detection of failure. (2) Failure-solution. A Failure-solution of a goal is unacceptable to some other subgoal in the forward execution. Failure-solutions of a goal are identified by analyzing the ...

Louisiana State University LSU Digital Commons LSU Historical Dissertations and Theses Graduate School 1989 A Framework for Efficient Execution of Logic Programs. Sudharsan R. Iyengar Louisiana State University and Agricultural & Mechanical College Follow this and additional works at: https://digitalcommons.lsu.edu/gradschool_disstheses Recommended Citation Iyengar, Sudharsan R., "A Framework for Efficient Execution of Logic Programs." (1989). LSU Historical Dissertations and Theses. 4783. https://digitalcommons.lsu.edu/gradschool_disstheses/4783 This Dissertation is brought to you for free and open access by the Graduate School at LSU Digital Commons. It has been accepted for inclusion in LSU Historical Dissertations and Theses by an authorized administrator of LSU Digital Commons. For more information, please contact [email protected]. INFORMATION TO USERS The m ost advanced technology has been used to photo­ graph and reproduce th is m anuscript from th e microfilm m aster. UMI film s th e te x t d irec tly from th e o rig in a l or copy subm itted. Thus, some thesis and dissertation copies are in typew riter face, w hile others may be from any type of com puter printer. The q u a lity of th is reproduction is d ep en d en t upon th e quality of th e copy subm itted. Broken or indistinct p rin t, colored or poor q u a lity illu s tra tio n s an d photographs, print bleedthrough, su b stan d ard m argins, and im proper alignm ent can adversely affect reproduction. In th e unlikely event th a t th e author did not send UMI a complete m anuscript and th ere are m issing pages, these will be noted. Also, if u n au th o riz ed copyright m a te ria l had to be removed, a note will indicate the deletion. Oversize m aterials (e.g., maps, draw ings, charts) are re ­ produced by sectio n in g th e o rig in al, b e g in n in g a t th e upper left-hand corner and continuing from left to rig h t in equal sections w ith sm all overlaps. Each original is also photographed in one exposure and is included in reduced form at the back of th e book. These are also available as one exposure on a stan d ard 35mm slide or as a 17" x 23" black an d w h ite p h o to g ra p h ic p r in t for an a d d itio n a l charge. P hotographs included in th e o rig in al m a n u sc rip t have been reproduced x ero g rap h ic ally in th is copy. H ig h e r q u ality 6" x 9" black an d w h ite photographic p rin ts are available for any photographs or illustrations appearing in th is copy for an additional charge. Contact UMI directly to order. University Microfilms In ter national A Bel t & H o w e l l I n f o r m a t i o n C o m p a n y 3 0 0 N o r t h Z e e b R o a d A n n A r b o r Ml 4 8 1 0 b 1 3 4 6 U S A 3 1 3 761 4 7 0 0 8 0 0 621 0 6 0 0 Order Number A fra m ew o rk for efficien t e x e c u tio n o f logic p ro g ra m s Iyengar, Sudharsan R., Ph.D . T h e L o u is ia n a S ta te U n iv e rs ity a n d A g ric u ltu ra l a n d M e c h a n ic a l C o l., 1989 UMI 300 N. Zccb Rd. Ann Arbor, Ml 48106 9017267 A Framework for Efficient Execution of Logic Programs A Dissertation Submitted to the Graduate Faculty of the Louisiana State University and Agricultural and Mechanical College in partial fulfillment of the requirements for the degree of Doctor of Philosophy in The Department of Computer Science by Sudharsan R. Iyengar B.E., Electrical Engineering, Regional Engineering College, Durgapur, India, 19S4 M.S., Systems Science, Louisiana State University, Baton Rouge, 1987 M.S., Electrical Engineering, Louisiana State University, Baton Rouge, 1987 August, 1989 Acknowledgem ents I am indebted to my major professors S. Sitarama Iyengar and Dr. Andijez Hoppe for their encouragement, support and guidance. More importantly, I am grateful for their enormous amount of time spent in discussing and writing this dissertation. I thank my committee members Prof. Donald H. Kraft, Dr. Doris Carver and Prof. El-Amawy. I acknowledge the assistance of Dr. Sukhamay Kundu in this project This work would not have been fruitful but for the relentless encouragement and motivation provided by my dear uncle. Prof. A. Raman, and his family. My parents and my sisters deserve special credit for the continuous love and affection, poured to me through the distance from India. Memories will always remain of my friends Lalitha Krishnamurthy, Krishna Prasad, Mohan B. Sharma, Ananta Prasad, Guja (Rajanarayan), and scores of others who all pro­ vided me with a nourishing environment throughout my Ph.D. work. I also acknowledge the Department of Computer Science, in particular Dr. Kraft, for the financial support. ii List of Tables Table I Trace of Naive Prolog E x e c u tio n ...................................................................... 32 Table n Comparison of Results in L ite ra tu re ..................................................................60 Table III Trace o f Execution by Intelligent B acktracking.............................................101 Table IV Trace of Execution by Intelligent Forward E x ecu tio n ................. .......... Table V Trace of Execution by Forward Jumping and IntelligentBacktracking . . 133 Table VI Trace of Execution by Intelligent Backtracking, Intelligent Forward . . . 155 Execution and Forward Jumping iii 115 List of Symbols symbol « meaning and V or - not <— if V for all 3 there exists 1 such that iff if and only if □ success ■ failure A solution of a goal £ belongs to U set union n set intersection 0 empty set 0, o state of computation A goal tree S search method Iv List of Figures Figure 1. Standard Goal-Search-Tree by P ro lo g ..........................................................................31 Figure 2. Execution of Prolog on a linear stack ........................................................................ 36 Figure 3.1. Recursive Execution Model, o f Pereira and P o r t o .....................................................41 Figure 3.2. Dependency Tag representation, of Pereira and P o rto ................................................41 Figure 4.1. Minimal Deduction Subtree that is consistent, o f B ru n o o g h ee............................... 43 Figure 4.2. Maximal Deduction Subtree that is consistent, of C o x ............................................ 43 Figure 5.1. Type I backtracking based on SDDA, of Chang and D cSpain...................................46 Figure 5.2. Type II backtracking based on SDDA, of Chang and D esp ain ................................. 47 Figure 5.3. Type III backtracking based on SDDA, of Chang and D espain ................................ 47 Figure 6. Backtracking based on B-list, of Conery and K ib le r................................................ 50 Figure 7. Backtracking based on dynamic B-list, of Vipin Kumar, e ta l ................................. 52 Figure 8. Variable Based Backtracking, of Rajasekhar, e ta l. ................................................. 5 4 Figure 9. Local-stack used by WAM, of Warren Figure 10. Identification of Failure-Bindings when a predicate is defined by facts..................6 9 Figure 11. Identification of Failure-Bindings when a predicate has facts and rules..................7 1 Figure 12.1. E ntriestoF B T ................................................................................................................75 Figure 12.2. Maximal tuples in FBT Figure 13. Unification with facts and Bit-vector manipulation Figure 14. Bit-vector manipulation with application of rules Figure 15. Identification of Failure-binding in the presence of facts and r u l e s ........................ 94 Figure 16. Incompleteness o f identification of Failure-bindings by r u l e s ................................ 97 Figure 17. Incompleteness of identification of Failure-bindings by u n ification ......................9 8 Figure 18. Goal-search tree explored by Intelligent Backtracking based on failure-bindings 100 Figure 19. Goal-search tree explored by Intelligent Forward Execution..................................... 114 Figure 20.1. Possible values of redo(2,9) for example in Figure 1. Figure 20.2. Possible values of redo(2, 11) for example in Figure 1 . .............................................I 26 ...................................................................... 5 8 ................................................................................................77 v ................................................. 92 ................................................... 93 125 Figure 21. Goal-search tree explored by Intelligent Backtracking and Forward lumping . . 1 3 2 Figure 22. Execution of logic programs on Segmented S t a c k ................................................. 146 Figure 23. Execution Model Implementing Intelligent Backtracking, Intelligent Forward Execution and Forward Jumping................................................................. 153 Figure 24 Goal-search tree by Intelligent Backtracking, Intelligent Forward Execution and Forward Ju m p in g ................................................................................154 vi T able of C ontents A c k n o w le d g e m e n ts ..................................................................................................................................i i List o f T a b l e s .......................................................................................................................................... i i i List o f Sym bols ....................................................................................................................................... *v List o f Figures .............................................................................................................................................v A bstract ........................................................................................................................................................ x 1. Introduction .......................................................................................................................................... 1 1.1. O v e r v i e w .................................................................................................................................... 1 1.2. Logic Program m ing as a Tool for A rtificial Intelligence .............................................. 3 1.3. Prolog as a L ogic Program m ing L anguage ...................................................................... 6 1.4. D isadvantages o f E x h au stiv e S earch b y P r o l o g ................... 10 1.5. M otivation for Efficient E x e c u tio n ................................................................................... 1.6. C ontribution o f the D issertation .........................................................................................1 5 1.7 O utline o f the D is s e r ta tio n ................................................................................................ 2. Introduction to Logic Program m ing 2.1. Logic Program s 17 * .............................................................................................19 .................................................................................................................. 2.2. R easoning by R e s o lu tio n .....................................................................................................22 2.3. U nification ..............................................................................................................................26 2.4. Procedural I n te rp r e ta tio n .....................................................................................................2 8 2.5. Interpreter ..............................................................................................................................33 2.6. Im plem entation I s s u e s .......................................................................................................... 3 7 3. L iterature R eview ...............................................................................................................................38 3.1. In tro d u c tio n .............................................................................................................................. 38 3.2. Selective B acktracking Based on U nification M apping In f o rm a tio n .....................3 9 3.3. R un-tim e Intelligent B a c k tra c k in g ....................................................................................4 2 3.4. S em i-Intelligent B acktracking Based on Static D ata D ependency A nalysis. . . . 4 4 3.5. G enerator-C onsum er A p p r o a c h ......................................................................................... 4 8 vii 3.6. Modified B-list Approach .............................................................................................51 3.7. Variable Based Intelligent Backtracking ...................................................................53 3.8 Warren Abstract M achine............................................................................................. 55 3.9. Discussion......................................................................................................................... 59 4. Intelligent Backtracking Based on Failure-B indings............................................................. 61 4.1. Introduction .................................................................................................................... 61 4.2. F ailure-B inding............................................................................................................... 63 4.3. Failure-Binding-Table * * .............................................................................................75 4.4. Forward Execution Based on Failure-Binding 4.5. Generators and Consumers ........................................................ 78 .......................................................................................... 81 4.6. Backward Execution Based on Failure-Bindings ......................................................87 4.7. Bit-vector Implementation to Identify Failure-Bindings .........................................90 4.8. Incompleteness of the Identification of F ailure-B indings.........................................9 ^ 4.9. Soundness and Completeness of < ; ......................................................................... 5. Intelligent Forward Execution Based on Failure-Solutions.................................................105 5.1. Introduction ..................................................................................................................1 0 5 5.2. F ailu re-S o lu tio n s..........................................................................................................1 0 7 5.3. Failure-Solution-Table ............................................................................................... 109 5.4. Intelligent Forward Execution Based on Failure-Solution...................................... 1 1 0 5.5. Backward Execution Based on F ailure-S olution......................................................1 1 2 5.6. Soundness and Completeness o f t ; '............................................................................. 110 5.7. Difficulty in Implementation o ft;' ............................................................................. 110 6. Intelligent Forward Jumping 6.1. Introduction .................................................................................................. 119 ........................................................................................ 119 6.2. Dependencies among subgoals.....................................................................................122 viit 6.3. Redo-list ....................................................................................................... 12 3 6.4. Forward J u m p in g ....................................................................................................... .1 3 0 6.3. Soundness and Completeness of ("Range Convergence for Forward Jump- . . . 134 ing 6.6. Difficulty in Implementation of (" ......................................................................... 1 3 5 7. Segmented Environment S ta c k .............................................................................................. 1 3 6 7.1. Introduction .................................................................................................................13 ® 7.2. Inapplicability of Linear Stack to Implement (* and ( ” ........................................... 138 7.3. Segmented S t a c k .................. .....1 3 9 7.4. Forward Execution on a Segmented S ta c k ................................................................ 3 * 3 7.5. Backward Execution on a Segmented S ta c k ............................................................. 3 * ^ 7.6. Space Complexity o f Segmented S ta c k .................................................................... 8. Effects of Non-logical Operators 8.1. Introduction ......................................................................................... 148 ..................................................................................................................1 4 8 8.2. Effect of Cut and F a i l . ..................................................................................................1 4 9 8.3. Effect of Assert and R e tr a c t ........................................................................................1 5 0 9. Summary ................................................................................................................................... 151 9.1. C on clu sio n s.................................................................................................................... 151 9.2. Future Directions .......................................................................................................... 158 R e fe re n c e s ..................................................................................................................................... 159 Vita ................................................................................................................................................ 1 6 6 lx Abstract The focus o f this dissertation is to develop an efficient framework for sequential execution of logic programs. Within this framework the logic programs are executed by pruning the goal-search tree whenever applicable. Three new concepts for pruning o f computation during execution of logic programs are introduced. Fallure*binding A Failure-binding for a literal is a binding which when applied to the literal fails the goal obtained from the literal. Failure-bindings for a literal are identified by analyzing the goal-trec o f a goal which is obtained from the literal. The failure-bindings for a literal are used for intelligent backtracking based on the generator-consumer approach. Intelligent backtracking based on failure-bindings prune the computation of search space which lead to late detection of failure. Failure-aolution A Failure-solution of a goal is unacceptable to some other subgoal in the for­ ward execution. Failure-solutions o f a goal are identified by analyzing the his­ tory of computation, during execution. Failure-soludons of the goals are used for intelligent forward execution. Intelligent forward execution prunes the computation of search space which leads to repeated failure resulting from repeated successes of a goal. Forward Jumping Forward jumping is a method to avoid reexecution of some subgoals after backtracking (instead of naive forward execution after backtracking). Forward jumping is based on the dynamic subgoal dependencies in a rule. Such jum p­ ing prunes the computation of the search spaces which leads to the same sequences of successes of subgoals after backtracking. x To facilitate the implementation o f these concepts a new data structure, called segm ented-stack, is defined. The space complexity o f a segmented stack is linear in the number o f nodes in the stack. Depth-first search as well as breadth-first search are very easily implemented on a segmented-stack during execution of logic programs. Execution of logic programs on a segmented-stack allows association o f the search space, as well as the solutions, of a goal with the frame of the goal. This enables implementation of intel­ ligent backtracking, intelligent forward execution and forward jumping. The search based on each of these paradigms is proved to be sound and complete. It is also shown that the implementation of these paradigms preserves the order of results obtained by Prolog. The effects of the non-logical operators, in Prolog, on the paradigms are studied. The search based on these paradigms is compared individually, and collec­ tively, with the standard search by Prolog. Keywords: logic program m ing, failure-binding, intelligent backtracking, failure-solution, intelligent forward execution, forward jum ping, segm ented stack. xi Chapter 1 Introduction 1.1. Overview Artificial Intelligence (AI), or computer intelligence, combines the automated computing power o f computers to implement effective intelligent techniques. Research in A1 has focused on the finding newer paradigms for automating intelligent behavior. Recent attempts to develop comprehensive and adaptable intelligent sys­ tems which obtain specific solutions to specific problems have proven beneficial in areas such as medical diagnosis, legal affairs, weather forecasting, testing and safe­ guarding of nuclear equipments, intelligent database and knowledge based systems, robotics [55, 58], language processing, effective and relevant information retrieval, and image processing. Research in AI is being directed towards the development of systems which not only obtain solutions for a given problem [5] but also refines their own process dynamically so as to perform more accurately and efficiently. Such techniques use some kind of a learning process, constraint-based efficient search methods, informa­ tion refinement and enhancement techniques, and self correcting principles. Over the past two decades, there has been a growing interest in the design and development of AI languages useful in building intelligent systems which ate not only efficient and easy to program, but which provide a framework for implementing learn­ ing. Fifth Generation projects, by ICOT in Japan [42], concentrate on developing languages and efficient frameworks for programming and executing knowledge based decision support systems. Automated deduction is central to the aim of achieving artificial intelligence. l 2 H ie A! requirements of a language include provisions for 1) automatic deduction, 2) early and effective constraint realization and propagation, 3) ability to intermix procedures and data, 4) goal directed behavior, 5) knowledge structuring and learning, 6) metalevel programming and control structures, [57]. Three types o f languages for programming and developing such intelligent sys­ tems are under consideration. 1. Functional languages, like Lisp, are used in developing expert and produc­ tion systems and for implementing constraint based computational models. 2. Relational or Logic languages, like Prolog [4], are used in developing advanced database and knowledge-base engineering and decision support systems. Logic languages are basically rule based languages. 3. Object oriented languages, like Smalltalk, are used for simulation, testing and performance analysis of real problems. O f these three types of languages, logic programming languages are most popular, mainly because of their expressive capacity and simplicity. The main focus of this dissertation is to obtain a general framework that provides efficient execution process o f logic programs. In spirit, we attempt to present new computational paradigms for efficient execution of logic programs using new charac­ terizations and a new data structure. 3 1.2. Logic Programming as a Tool for Artificial Intelligence Almost all AI problems are solved based on different types o f constraints which need to be globally satisfied. This requires extensive search to effect constraint gen­ eration, propagation and satisfiability. In logic programs the constraints are values for variables - see section 2.2. Logic programming enables specification of constraint propagation its execution performs the required search on these constraints. Logic programming began in the early 1970's as a direct outgrowth o f earlier work in automatic theorem proving and predicate logic. Earlier work by Herbrand, Prawitz, Gilmore, Davis, Putnam [4] and others culminated in 1965 with the publica­ tion o f the landmark paper by Robinson [ 1 - 6 ] which introduced the resolution princi­ ple - an inference rule well suited to automation on a computer. Kowalski [7 - 10] showed that an algorithm consists o f two disjoint components the logic and the control - the what and how part of a problem to be solved, respec­ tively. Logic is used to express the what part. Thus, an algorithm is converted to symbolic manipulation. Logic is an effective symbolic framework for theorem proving. Theorem prov­ ing is an automated deduction procedure, a procedure to derive newer information from a given information base. Resolution theorem proving is an effective tool for developing automated inference engine on a symbolic framework. A symbolic system is developed to express knowledge in the form of proposi­ tions, expressions which have only a True or False value, and the relationships between these propositions. The statements, or rules, about these propositions also express how one can validly infer newer propositions from those that are given. More complicated propositions can be expressed in terms of simple propositions by the use of the connectives (e.g. a , v , - i, *—) between them. 4 The programmer needs to specify only the logic component of the problem in the form o f propositions and rules about the propositions. The control during execution, which is independent of the problem description, provides an answer to the query requested by using standard deduction procedures on the propositions and rules specified by the programmer. Piopositional logic is a sound framework for symbolic computation. The argu­ ments for propositional logic can be extended to predicate logic, where propositions are expressed in terms of predicates, a predicate name followed by n-tuple arguments. Predicate logic is a more general framework, because it allows more generalized expressions in terms o f variables and ground terms. Variables can assume different values at different times. The programmer can then specify general information about a predicate using variables. First order predicate logic (FOPL), a restricted form of predicate logic, see section 2.1, provides methods for deducing newer theorems of a theory as logical consequences o f the axioms and the theorem which are provided. A logic program consists of a set of procedures, or axioms, and a goal statem ent Again the programmer needs to specify only the logic component of the problem which is information about predicates. The execution, or the control part, provides answer to the goal by using standard deduction procedures. Predicate logic has two aspects: the syntactic and the semantic aspects. The syn­ tactic aspect is concerned with syntactic constructs of the symbolic system. The semantics is concerned with the meanings attached to the statements in the syntactic constructs. A clause is a disjunction of literals, which are propositions in the form of predi­ cates. Ground unit clauses are facts, Le. a single literal with a fixed true or false value, and rules are generalized clauses. A logic program with only ground unit clauses, i.e. facts, is a relational database. 5 Theorem proving is an automated procedure to derive new information from a given information base. Resolution theorem proving is an effective tool for develop­ ing a automated deduction system. All logic programming systems are based on reso­ lution theorem proving. The problems in artificial intelligence can be converted into symbolic manipula­ tion by proper knowledge representation, manipulation and inferencing problems. Logic programs together with automatic deduction rules are based on the resolution principle and form a powerful framework for developing AI systems. Most logic pro­ gramming systems are resolution theorem provers. The credit for the introduction of logic programming goes mainly to Kowalski and Colmerauer [7 -10] who introduced in 1972 the fundamental idea that logic can be used as a programming language. A programming language for implementing logic programs is Prolog. The next section gives a brief introduction to Prolog. 6 1.3. Prolog as a Logic Programming Language Prolog (PROgramming in LOGic) is a programming language to describe logic programs. The first Prolog interpreter was implemented in Algol by Roussel in Mar­ seille in 1972 [4]. Prolog is based on Robinson’s Resolution Principle with specific top-down leftto-right control. The programmer describes his problem in a symbolic framework which he develops. Users can now test a goal on the logic program to obtain newer information. The goal is also a symbolic expression. The goal is mapped onto the program and the theorem proving technique is applied to see if the goal is satisfied by the theorems provided in the program in the form of program clauses - facts and rules. Programming in Prolog, with its well defined syntax, facilitates generalized specification o f information and their inter-relationships. It essentially implements a theorem prover for the programmer. The term "logic programs" has now become analogous to Prolog programs. Prolog systems employ the computation rule which always selects the leftmost goal in a sequence o f goals called the goal-list for execution. It also employs Linear Resolution with a Selector Function, a selection mechanism which uses the order of the program clauses, to select clauses during execution. The execution mechanism is independent of the program specification. Prolog employs deterministic top-down resolution which results in depth-first search to satisfy a goal. Success is reported if the goal unifies (see section 2.3) with a clause and the clause is true. The goal-list is modified during the execution o f a logic program. The search rule is implemented on a linear stack of goals, called the local-stack. An instance o f the goal stack represents the branch of the goal-search tree that is currently being investigated. The computation then essentially becomes an interleaved sequence of pushes and pops on this stack [see section 2.5]. 7 The resulting search is a depth-first search of the goal-tree. Depth first rules can be very efficiently implemented on a stack. For a system that searches depth-first, the search rule reduces to an ordering rule which specifies the order in which the program clauses are to be tried. Prolog systems use the order of clauses in a program as the fixed order in which they are to be tried. This is implemented in a very simple and efficient way. The positive features of Prolog can be enumerated as follows. • As any other programming language, it has well defined syntax. • It is closer to a declarative language than are logic programs (see section 2.1). The procedural interpretation of Prolog helps the programmer to follow Prolog programs more clearly. • The answers to the query are accurate within the domain o f the program lead­ ing to answers within the closed world (CW) of the program. • Not is implemented as a negation by failure - that is the negation of a goal is true if the goal cannot be satisfied by the program. This is sufficient within the CW o f the program. • The selection rule is fixed; hence, the behavior of the program is explicit to the programmer. • The input/output indirection as a result of the unification substitution mechan­ ism (see section 2.3) is a powerful characteristic. This removes the necessity of mode specification in the programs. Thus programs can be used to test for satisfiability of goals or to generate solutions for which the query is true, • Prolog interpreters are usually interactive in nature and hence encourage man-machine interaction. • Failure of a goal implies that the goal cannot be satisfied with the given con­ 8 straints applied to the goal. Consequently, the detection o f a success or failure of a goal is also sound. • Backtracking is used to get also another set of constraints for a failed goal. The actions taken by the interpreter to effect backtracking are elementary in nature. • Alternatives are selected top to bottom and failure is reported if and only if there are no more alternatives for a goal. Thus, all possible paths to satisfying a goal are explored. Consequently, every solution to a goal is reported. Since the search is exhaustive, it is complete within the CW of the program, as long as the search does not get trapped in an infinite loop. • Many non-logical operators like +, -, is, nl, write, cut, assert and retract, are provided to make Prolog useful for different applications. ■ Identical solutions for the predicates may be obtained via different search paths in the goal-search tree. There is no restriction on the type or size of the terms used and the number of solutions for a goal.1 • The control operates on a goal-list and a linear stack of activation records. The implementation of this control is very simple and efficient - translating itself into operations similar to the implementation of a Push Down Auto­ mata. Since Prolog implements depth first search with fixed ordering, the resulting search is naive and exhaustive. Each call to a definition tries the clauses in the definition in exactly the same order every time a program is executed. Even though it employs goal-oriented search, it does not effect selective and relevant search. t It is precisely due to this generality that the search process gets trapped into an infinite loop. 9 For an infinite search tree, depth-first search is not fair. Breadth-first search would be fair (avoid infinite search tree), but is less compatible with efficient imple­ mentations. The depth-first search method results in incompleteness o f Prolog resolu­ tion, because it does not guarantee finding the success branch - even if one exists because the search may get trapped in an infinite branch. Hence, Prolog systems, though sound, are partially incomplete. Exhaustive search is not always necessary, and the search process can be pruned without losing the soundness and completeness properties of Prolog. The disadvan­ tages o f the present implementation of Prolog is presented in the next section. 10 1.4. Pisadvantages of Exhaustive Search by Prolog Query processing should base its decisions on the entire search, i.e, the search space with all the permutations of the constraints. It is also true that only a select set o f permutations o f constraints satisfy the query. All sets o f permutations are tried by employing backtracking when a failure is encountered during the execution of logic programs. The set o f constraints and the resulting search space that is explored is rather large. The use o f traditional backtracking to explore a search space in a top-down, depth-first scheme starts with the initial state with the query goal as the current state. For each forward derivation step, one of the goals yet untried in the current state is used to derive a new current state. Success is reported when the set o f untried goals applicable in the current state is empty. Failure is reported when an untried goal in the current state cannot be solved. Forward execution is repeated until a success state, Q is reached, or a failed stated, ■ , is reached. In the □ state, the goal-list is empty and the local-stack contains the path to the successful state. In the ■ state, the localstack is empty and the goal-state contains the query goal. After reaching ■ , the system returns to a previous state. This process is called backtracking. Forward execution is repeated for this state to derive newer states. If backtracking returns to the state prior to ■ , then this is naive backtracking. A failure is cured only when the cause of the failed state is undone. Retracting to the previous state on reaching ■ may not be able to cure the failure. Unfortunately, there is no way to identify the cause of failure. The result of naive backtracking could be unusual trashing, unnecessary backtracking and forward execution. Due to the depth-first search a subgoal may be tried more than once during dif­ ferent stages o f computation. Consider a state, f, in which failure is reported and also assume that backtracking 11 takes us to state b. 1. Backtracking to b, after the failure at f, and subsequent return to f, without any change to the constraints applied in ft (this could be due to backtracking to b, and subsequent return, without changing the constraints applied in f, or due to applying the same set of constraints to the goal that failed in f) 2. Backtracking to b, after the failure in f, and subsequent return to f without cur­ ing the cause of failure of the subgoal in f, (this could be due to backtracking to b and solving a subgoal in b whose new solution does not cure the failure of the subgoal that failed in f). 3. Multiple appearance o f the same subgoal in different states during the search due to the appearance o f the same subgoal in different rules. In particular, repeated computation of a subgoal may occur both for the case when a subgoal succeeds (generating the same solutions) and for the case when a subgoal fails (generating the same failure). The specific deficiencies which result due to the exhaustive depth-first search implemented by Prolog can be enumerated as: • Naive backtracking (backtracking without any basis) to the immediately previous state results in an exhaustive search. This could result in inconse­ quential exploration of some of the search space. • There are dependencies among the subgoals in the rule which imply seman­ tic relationships among the subgoals. Naive backtracking does not use these semantic relationships among the subgoals to identify a better state for backtracking. Again, this could result in inconsequential exploration of some of the search space. The causes of failure of a subgoal in a state is not analyzed. This analysis could lead to identification of specific causes of failure which could be used for relevant exploration o f search-space. When a goal fails in a state f, the dependency directed backtracking [5] assumes the cause of failure of a goal as the set of all constraints applied to the subgoal that failed in f. The backtracking is based on the dependencies among the subgoals of the rule and the system selects the latest state that generated any constraint for backtracking to ensure completeness of search. The selection of the state for backtracking is not based on the causes of failure of the subgoal in f. H ie resulting search by dependency-directed backtracking may not cure the failure of the subgoal in f. The cause of failure will eventually be corrected. This amounts to late detection, and correction, o f the cause of failure. This results in futile exploration of some of the search space. The history of computation is not used during different stages of computa­ tion. Repeated failures could occur due to the result of repeated identical solutions, constraints, generated by certain other goals. This results in repeatedly exploring in vain search spaces which contain no solutions. This is a direct consequence of not maintaining the information from the history of computation. Such dynamic learning is not employed by Prolog. Computations continue blindly after backtracking. Some of the computa­ tions that are performed after backtracking may be independent of the corrective action taken by backtracking. Consequently, identical search spaces which lead to success, which are independent o f the reason of back­ tracking, may be repeated. These computations need not be repeated. Pro­ log does not employ any technique to avoid the repetition of such computa- 13 dons. • Search spaces o f different subgoals in a rule are not maintained separately. Prolog execution on a linear stack demands that computations be performed in a systematic manner where even independent computations are stacked on top of one another. This allows accessing different records in the chro­ nological order of execution. H u s rules out independent access to the search space o f different goals in a rule. Importantly, the information about the solutions of a goal cannot be associated with the goal. The area of efficient execution of logic programs have been addressed by many researchers. The next section presents the motivation for intelligent execution of logic programs. 14 1.5. Motivation tor Intelligent Execution Efficient backtracking methods [1-7], which are essentially variants of depen­ dency directed backtracking [9], have been proposed for eliminating certain inconse­ quential computations. An intelligent search mechanism employs a search rule which is directed by the information provided to it by the programmer. If no information is provided to determine the search rule (the order of search), then certain information derived during execution is used to effect selective and relevant search space explora­ tion. These intelligent search methods use one or more of the following: unification mapping information [11] (see section 3.2) dynamic data-dependency [12, 13, 14, 15, 16] (see section 3.2) static data-dependency [17,18] (see section 3.4) variable binding informations [27] (see section 3.7) generator-consumer lists of variables [19 - 26] (see sections 3.5 and 3.6) selective page retainment in the main memory [28, 35.40] elimination of tail-recursion [29 - 32] (see section 3.8) The major deficiencies of the exhaustive search employed Prolog, presented in section 1.3, have not been addressed by any of the existing solutions, for sequential Prolog, in the literature. The information content of the program is static in that there is no learning involved from the computations that are performed during execution. An intelligent search rule should utilize the semantics prescribed by the rules in the logic program together with a learning process and effective search techniques. The focus o f this dissertation is to develop and present paradigms to eliminate all inconse­ quential search space exploration during execution. 15 1.6. Contributions of the Dissertation We present newly developed paradigms applicable to logic programs. A frame­ work base for efficient execution of logic programs is developed based chi these para­ digms and a new data structure for implementing these paradigms. The major contri­ butions being made by this dissertation to the field of logic programs are as follows. i) An exact analysis of the failure o f a goal in logic programs is done to iden­ tify definite causes of failure o f a goal. This gives global informations about predicates which is associated with the predicates for future use, thus effecting a learning process. ii) A systematic evaluation method for identifying the causes of failure of the current goal, in Prolog, is presented. This analysis does not demand exces­ sive dynamic time and space. An algorithm to identify the causes of failure is also presented. iii) An intelligent backtracking scheme based on the identified exact causes of failure of a goal is proposed. The resulting search resulting from intelligent backtracking, based on exact causes of failure, is proved to be sound and complete. iv) An intelligent forward execution algorithm to identify and eliminate repeated computations which result in failure during forward execution is presented. The intelligent forward execution is based on the notion of a failure-solution of a goal. The failure solutions of a goal are identified from the history of the execution. The resulting search based on intelligent for­ ward execution based on failure solutions of a goal is proved to be complete and sound. v) Forward jumping algorithm to eliminate repetition of computation during forward execution after backtracking is presented. Forward jumping is 16 based on subgoal dependencies in a rule. The forward jumping algorithm, which further prunes redundant computations so as to result in successes, is proved to be complete and sound. vi) A new data structure, a segmented stack, for implementing the above algo­ rithms is defined. Execution of logic programs on a segmented stack facili­ tates associating search spaces and solutions with a goal. vii) Execution of logic programs based on the paradigms enumerated above is shown to preserve the order of results as obtained by Prolog. viii) The search space explored by the use o f the paradigms enumerated above is compared to the search space explored by standard Prolog. ix) A framework which employs all the proposed paradigms is detailed. 17 1.7. Outline o f the Dissertation Chapter 2 presents a formal introduction to logic programs describing in detail the resolution principle and the implementation o f Prolog as a programming language. The important implementation issues of a Prolog interpreter are analyzed in detail. Chapter 3 reviews the literature pertaining to efficient execution of logic pro­ grams and presents the significant contribution to intelligent sequential execution of logic programs. Some o f the contributions of parallel execution models which are applicable to sequential execution are exemplified. Chapter 4 introduces the concept of a failure-binding of a goal after presenting a discourse on the causes of failure of a goal. A modified unification algorithm which enables the identification of failure-bindings is also presented. The selection of the backtrack literal, backtracking and subsequent forward execution is illustrated. The resulting search space explored is related to the search space explored by Prolog. It is proved that the identification of failure-binding is sound. The causes of incomplete­ ness o f the identification o f failure-binding is scrutinized. A method to use the identified failure-bindings as global information about a predicate is described. This information is associated with the predicates and are used during subsequent search. The intelligent backtracking method based on failure-bindings is proved to be correct. The forward and backward execution algorithms based on failure-bindings are presented, and proved to preserve the soundness and completeness property of Prolog. Chapter 5 introduces the notion of a failure-solution of a goal. A method to use the dynamically identified failure solutions from the history of computation for intelli­ gent forward execution is proposed. H ie intelligent forward execution algorithm is presented. The correctness of this algorithm and the soundness and completeness pro­ perties o f the resulting search are proved. Hie concept o f forward-jumping during sequential execution of logic programs 18 is introduced in chapter 6. An algorithm to obtain to redo-list (see section 6.3), which contains the subgoals which are independent o f the corrective action taken by the the backtracking process, is presented. Different instances o f forward-jumping are illus­ trated. Forward jumping for recursive backtracking is also detailed. The resulting search is proved to be complete and sound. The search space explored by forward jumping is compared to the standard search space explored by ftolog. Chapter 7 introduces the new data structure, a segmented stack, for implement­ ing the paradigms and algorithms developed in chapters 3, 4 and 5. The segmented stack, together with its operations, is defined. The use o f a segmented stack as a local stack for executing logic programs is illustrated. Chapter 8 considers the effects o f non-logical operators on the paradigms intro­ duced in chapters 3 ,4 , and 5. Chapter 9 presents a brief sum m ary of the contributions of the dissertation. The flow-diagram of the framework which implements the concepts developed in this dissertation is given. A note for future research concludes the chapter. Chapter 2 2. Introduction to Logic Programming 2.1. Logic P ro g ram s Logic programming differs fundamentally from other conventional programming in that it requires the programmer to describe the logical structure of a problem. The primitive symbol in logic programs is a proposition (sec section 1.2). A proposition can have only one of the two values - True or False. Other primitive symbols are the connectives, viz a, v, —i , and . A sentence is made o f propositions with connectives over such propositions. The knowledge that can be represented by a proposition is the relationship among the propositions. AU queries are answered using logical infer­ ences. A logic program describing a problem consists of sentences, which are proposi­ tions, and which are predicates, expressing knowledge relevant to the problem. The formulation of this knowledge makes use of two basic concepts: the existence of discrete objects and the existence of relations between them. Objects are terms made up of constants and variables. The principal constituents of a logic program are objects, variables, propositions and connectives. Both objects and relations are given names - this creates symbolic models. Sentences express the relations or logical pro­ perties of the names. A predicate is a predicate name with an n-tuple of arguments. Each of the argu­ ments of a proposition is a term. Logic relations are named by predicate symbols and knowledge is expressed as sentences, formulas, constructed from predicates. A for­ mula is defined as follows: 1) any predicate is a formula 2) if FI and F2 are formulas, then so are (FI), FI 19 a F2, FI v F2, FI <— F2, and 20 —.F I . The use o f variables in the arguments of predicates allows the writing o f general­ ized sentences. The role of the variables in a sentence is governed by their mode of quantification (existential or universal). The set of all sentences constructed with rules 1 - 4 given below constitutes the language of first order logic. 1) A term is a constant or a variable or an n-tuple of terms prefixed by a func­ tor. 2) A predicate is a n-tuple o f terms prefixed by a predicate symbol. 3) A formula is either a predicate or several predicates with connectives, with a quantifier for the variables appearing in the formula. 4) A sentence is a formula in which every occurrence o f a variable is within the scope of the quantifier for that variable. Consider the following logic program: 1. fatherijohn, bob). 2. fatherCgeorge, john). 3. fatherCgeorge, donald). 4. motherCmary, bob). 5. motherCmary, jenniffer). 6. motherCchristina, donald). 7. V (parent(X, Y) <—mother(X, Y) v father(X, Y)) 8. V (sibling(X, Y) parent(Z, X) a parent(Z, Y)) The first six propositions in the logic program are facts. For example, the first fact, fatheiCjohn, bob), expresses the father relationship between the objects john and bob. Similarly, the fourth fact, motherCmary, bob), expresses the mother relationship 21 between the objects mary and bob. The father and mother relationship arc both 2-tuple predicates. H ie proposition father(john, bob) can represent the information that john is the father o f bob, i.e., the object which is the first argument is the father o f the object that is the second argu­ ment. The 7th and 8th propositions in the logic program given above are formulas, or rules. The knowledge represented by the formula V parent(X, Y) <— mother(X, Y) v fathcr<X, Y) is that, for all X and Y, X is a parent of Y if X is the mother o f Y or if X is the father of Y. This is expressed by the {Repositions which appear on the right hand side of the impli­ cation in the rule. Knowledge represented in the statements of logic programs are used during inferencing newer facts, or theorems. 22 2 2 . Reasoning by Resolution It is necessary to have a proof procedure that carries out the variety o f processes involved in reasoning with statements in predicate logic. Resolution is such a pro­ cedure. The resolution proof procedure gains its efficiency from the fact that it operates on statements that have been converted to a very convenient standard form. The convenient standard form is the clausal form. A literal is an instance o f a predicate. A clause is a disjunction of literals. The convenient clausal form is obtained from a general logic program by applying the fol­ lowing steps. 1. Convert all the formulae to conjunctive normal fo rm • for example ((a v c) is converted to ((a v c) 2. Converting all implications, a a b) (b v c)). , from formulas using the fact that (a <— b) is equivalent to (—i a v b). 3. The scope of the negation is reduced to the next literal (-<a 4. a b)) is equivalent to (-i a v using the fact that b). Normalize all quantifiers by moving all quantifiers to the left of theformula. This formula is said to be in prenex normal form . 3. Eliminating all existential quantifiers (3) by using assertions, i.e., facts. The resulting formula is said to be in skolem normal form . 6. The universal quantifiers are dropped as they are now implicit. A clause which contains at most one negation is called a Horn clauses. A Prolog pro­ gram is a set of Horn clauses. Resolution produces proofs by refutation. In other words, to prove a statement resolution attempts to show that the negation of the statement produces a contradic­ tion, unsatisfiability, with the known statements. The resolution procedure is a simple iterative process. At each step two clauses, called the parent clauses, are compared 23 (resolved) yielding a new clause, called the resolvent, that has been inferred from them. Given two clauses ( i v b v - i c ) and c), since either of a or -1 a is true and (b v ( - 1 - 1 av bv - 1 c) the resolvent of it is (b v —< c) is common to both the clauses. If (b v —» c) is true, giving an interpretation, then both parent clauses are true with this interpretation. The resolvent represents ways that the two parent clauses interact with e n.ch other. If the resolvent is satisfiable then both parent clauses can be satisfiable simul­ taneously. An interpretation of a formula is the truth set, i.e., the set of values for the variables in the formula, which makes the formula true. An interpretation of the resol­ vent is an interpretation of the parent clauses. If resolution produces an empty clause, then the parent clauses cannot be satisfied simultaneously. When resolution of clauses yields an empty clause, Bf, then there exists a con­ tradiction among the clauses. There may not be any contradiction among the clauses when the proof procedure is complete, in which case the clauses are said to be satisfiable. That is, when an empty clause is not derivable by the resolution proof pro­ cedure, then the clauses are said to be satisfiable. The resolution proof procedure is exhaustive. An interpretation which satisfies a set of clauses is said to be its model. Resolu­ tion tests for satisfiability for all clauses with all combinations of interpretations avail­ able to find a model. An interpretation over some domain D is said to satisfy a sentence iff (if and only if) it makes that statement to evaluate as true. It satisfies a set of sentences, S, iff t This is similar to a state in which failure occurs in Prolog Hence, the use of identical symbols. 24 it satisfies each sentence in S. S logically implies some sentence s iff for all possible domains every interpretation which satisfies S also satisfies s. Sentences are of three types - denials, assertions or implications - o f the form (“ ■(Al A j, .. A j ) , A, o r ( A B„ B j, B j, respectively. A is the consequent and ( B ,t , Bn) are antecedants o f the implication. If propositions are predicates, then we must consider all combination o f values for variables, i.e., bindings, to complete the proof procedure. The fundamental notion underlying the reasoning process which explores the logical consequences of the knowledge is the logical implication. A substitution is an assignment of a set of terms to variables. A unifying substi­ tution when applied to A and B, makes A = B. A most-general-unifier (mgu) is a most general substitution which makes A » B . All computational problems can be formulated using only denials, assertions or implications. All solvable problems can be solved by using general depth-first resolu­ tion. Resolution possesses the soundness and completeness properties That is, every theorem derivable by S is a valid formula and every valid formula is derivable by S, respectively. Sentences consisting only of denials, assertions and implications form a subclass o f the clausal form and are called Horn clauses. The resolution method is a good tool for testing the consistency of a set of Horn clauses, i.e., Prolog programs, provided an adequate selection strategy is used. Algo­ rithmic properties of a function can be represented in a suitable set of clauses. The values o f that function can then be obtained by the resolution method. Negation is implemented as "negation by failure", i.e. the negation of an expres­ sion is true if the expression is not true within the framework of the program (closed world assumption). This means that when the negation of a goal is true, then the goal 25 is false, within the framework o f the program. The closed world assumption gives partial incompleteness. What this means is that the resolution proof procedure is accurate within the framework o f the program the assertions and implications supplied in the program. The proof by refutation procedure uses the proof by negation principle, i.e., if a set o f sentences is unsatisfiable, then each of the sentences is true. W hen a goal, C , is tested with a logic program, P, then the clauses P u G i s tested for satisfiability. If the clauses in P u G are satisfiable then, G is false, because each clause in P is known to be true. If P u G is unsatisfiable, then G is also true. If the left hand side of an implication is a single literal, then we can convert this implication into conjunctive normal form using the rule that (B <—A) is equivalent to (—i B v A). The proof procedure becomes very simple in this case, because a goal which is identical to B is unsatisfiable if A is unsatisfiable. In B «—A, B is called the head and A is called the body of the implication or rule. If the goal G is identical to the head of the clauses C l, C2, Cn and the body of each of the clauses are false, then G is unsatisfiable. A Prolog program applies this principle during query process ing. Unification and substitution form the basic activities for resolution theorem prov­ ing in first order predicate logic. The first activity during the proof procedure is to identify if the goal G is identical to the head, H, of a clause, C. This is achieved by unification of G with H. 26 2 3 . Unification The unification of two expressions can be described as follows i) If either expression is a variable occurring in the other, then the the expres­ sions do not unify. (Occur check is done for assignments of the type X := f(X) unification, which is an unreasonable event) ii) If either expression is a variable not occurring in the other, then unification succeeds and the latter to the former is the unification substitution. (A vari­ able ’X ’ unifies with another variable *Y\ The substitution is X/Y. A vari­ able *X’ unifies with a constant ’a ’, then X takes a value *a*; the substitution X «— V or X/a) iii) If either expression is a constant and the other is either a different constant or a structured, term then the expressions do not unify. (A constant ’a ’ fails to unify with a constant ’b ’ or a structured term ’[X a]'.) iv) If the expressions are structured terms having different principal functors, then the expressions do not unify. If the expressions are structured terms having identical functors, then the expressions unify, if each of the argu­ ments unify. If any of the arguments fail to unify then the expressions fail to unify. All the substitutions which are applied during the unification of the arguments are recorded by the unification process to give the unification substitutions between the expressions. A predicate name is a functor name. The arguments of the predicate are the arguments of the function. Variables and constants form the n-tuple arguments o f a predicate functor. The unification procedure in Prolog is essentially a pattern matching and substi­ tution algorithm. The pattern matching proceeds matching the goal pattern G and the pattern H, which is the head of a clause C, from left to right. If the functors of G and 27 H are not identical, then G fails to unify with H. If the functors of G and H are identi­ cal then each argument o f G is unified with the corresponding argument o f H. Unification fails even if one o f the arguments of G fails to unify with the correspond­ ing argument of H. The left to right pattern matching and substitution quits at the first failure to unify. Exam ple H 7 Unity Substitution p(X, Y, a). p(H, y , R). Yes X <- P. Y 4 - Q; R <- a q(X, Y). q([a, b], c). Yes X <- (a, bj; Y <- c r(Xt Y( Y). r(a, a, a). Yes X <—a; Y <- a r(X, Y, Y). r(a, b, c). Fail 0 s(a, b, c). s(a, c, d). Fail 0 71-------------- If G unifies with H, then G is substituted by the body of C, with the unification substitutions applied to the subgoals in the body of C. G is true if the body of C is true. An interpretation of the body of C is an interpretation for G. Note that the body o f C can contain more than one subgoal. Each of these goals is processed in the same way G was processed. 28 2.4. Procedural Interpretation There are no factors to determine a precise course of execution of logic pro­ grams. The call selection rule is more casually called the computation rule. The stan­ dard computation rule always selects, in each step, the first call in the goal-lisL The selected subgoal is resolved with the clauses. Since the clauses are implications, on unification with the rule-head, the subgoal is replaced by the rule-body. Then, to solve the subgoal the rule-body is solved. The standard search rule chooses clause for unification in the order of appearances in the program tex t A logic program can be executed as any declarative program. This is done by considering the goal as a procedure, the procedure name is the predicate name and the parameters are the arguments o f the predicate. The procedures are defined as the clauses. The head of a clause is the header of the procedure and the subgoals in the body of the clause form the body of the procedure. The subgoals in a clause are exe­ cuted when a procedure is executed. Note that there can be more than one clause for any predicate. Each of these clauses uniquely defines one procedure. A Prolog program is farmed by a set o f instructions that can also be interpreted as productions of a definite clause grammar. The Prolog language uses resolution as an elementary execution mechanism. The choice of sequence o f instructions to be executed in the course of program execution is determined from the text of the pro­ gram. Each production is a two level process. When the goal matches with a rulehead, the goal is replaced by the rule-body and then the rule-body is executed instead o f the goal. The procedural interpretation [48] views the execution goals as a set of pro­ cedure calls. Each one is processed by calling an appropriate procedure. A goal-list [A , A j is a collection of procedures, A „ A 2, .., A ,. The procedure is the name of the predicate and its arguments are parameters. For any given program, the total com- 29 putadon space is the set of all computations derivable from it using standard pro­ cedures calling operations. The unification procedure draws upon a very important aspect of logic programs. The unification procedure finds a substitution which makes two literals identical. Using the procedural interpretation to execute a goal and using unification procedure to execute a call to the appropriate procedure leads to a property called I/O indirec­ tion. This means that the calling statement need not have all its arguments instan­ tiated. The calling statement contributes some instantiation to the called procedure and the unification with the head o f the called procedure and its execution contributes some instantiation to the calling statem ent It is understood that when this call becomes replaced by the invoked procedure body, the textual order of the latter’s calls is not altered. An application of a rule confines computation to a selected subspace defined by the subspace of the computa­ tion o f the subgoals in the rule. The total computation space is the computation tree whose root is the initial goal and whose paths from that node represent various com­ putation. A program is said to be unsolvable when its subspace contains no successful computation. The computation o f a goal can be depicted as a goal-search tree. Every node in the tree represents the execution of a subgoal in the path to solving the goal. The sub­ stitutions applied to a node are indicated on the path from the root to the node and the instantiations generated by the successful execution o f the goal corresponding to a node is indicated on the branches from the node. The number of branches from a node equals the number of alternative clauses that are applicable to a goal correspond­ ing to a node. Failure of a goal is shown as "F" next to the node. Consider the rule’ and the predicate relation given below. Figure 1 shows pan of the standard goalt This rule is take from Kundu, [34], search-tree by Prolog, for this rule, until the first success is encountered. Table I gives the corresponding trace of execution, using the notations developed in section 4.1. pO(X, Y) pI(Y, 2), p2(X), p3(Z), p4<X, Y. U), p5(Z. X. U, W), p6(V). p7(X, V), p8(Y). p9(X, U, V), plO(Y, U), p i 1(X, Z). pl(bl, cl). p l(b l,c l). pl(b2, c2). p2(a1). p2(a2). p3(cl). p3(c2), p4(i2. b l.d l). p4(a2. b2. dl). p5(c2, « 2 ,d l,e l). pS(c2,a2,dl,el). p6(fl). p6(f2). p7(«2, fl). p7(«2, f2). p8(b2). p9(«2,dl,f2). pl0(b2.dl). pll(a2.c2). 31 Y/b2; Z/c2 Y/ bl ; Z/cl Z/C 1 Y/bl X/q X/Q X/a X/ a X/a2 X/a U/d v/f plO pll Success!! Figure 1. Standard Goal-Search-Tree by Prolog 32 goal tpl(Y,Z), ()) (p2(X), {}) (p3(Z), {Z/cl}) <p4(X,Y.U). (X/al, Y/bl}) (p3CZ). {Z/cl» <p2(X),{)) (p3(Z). (ZA=H) tp4(X,Y,U), {X/i2, Y/blJ) <p5(Z, X, U. W), (Z/cl,X/a2, U /dl)) (p4(X, Y, U), (X/a2, Y /bl)) (p3(Z), (Z/cl)) <p2(X).{)) (plCY.Z).{J) (p2(X), (}) (p3(Z), (Z/cl)) (p4(X, Y, U), {X/al, Y/bl}) (p3(Z), {Z/cl)) <p2(X), {)) (p3(Z), (Z/cl)) <p4(X.Y.U), (X/a2. Y/bl)) (p5(Z, X. U. W). {Z/c 1.X/a2, U/dl}) (p4CX, Y, U), (X/a2, Y/bl}) (p3(Z), {Z/cl}) (P2CX), {}) (pl(Y, Z), {)) (p2(X), {}) (p3{Z), {Z/c2}) (p4(X, Y, U), {X/al, Y/b2)) (p3(Z), (Z/c2J) (p2(X), {)) (p3(Z), {Z/c2}) (p4(X. Y, U), {X/a2, Y/b2}) (p5(Z, X, U, W), (Z/c2, X/a2, U/dl ]) (P6CV).{}> <p7(X, V), {X/a2, V/fl}) (p8(Y). (Y/b2)) (p9(X, U, V). {X/a2,U/dl. V/fl)) (p8(Y), {Y/b2)) (p7(X,V), (X/a2, V /fl}) (p6CV),{)) (p7(X, V), (X/a2, V/f2)) (p8(Y), (Y/b2)) (p9(X. U, V). {X/a2,U/dl, V/T2}) {plO(Y.U), (Y/b2,U/dl}) (pllCX.Z), {X/a2,Z/c2}) success/fail success success success fail fail success success success fail fail fail fail success success success fail fail success success success fail fail fail fail success success success fail fail success success fail success success success success fail fail fail success success success success success success backtrack literal - binding Y/bl; 7jc\ X/al - - P3 p2 - X/a2 - - U/dl - P* p3 - Y/bl; Z/cl X/al X/a2 U/dl Y/b2; Z/c2 X/al X/a2 Wfcl V/fl - - V/f2 *■ * Tabic I: Trace of Standard Prolog Execution P10 - * P3 p2 - P3 pl P3 P2 P3 * p8 P7 p6 - 33 2 i . In te rp re te r The interpreter that executes a logic program has to remember what data has been assigned so far to the variables. It needs to r emember how the locus of control evolved to its current state. This is needed to deal with the return operation after every successful procedure exit and the need to deal with backtracking, since that operation has to recall previously discovered opportunities still open for exploration. Program execution accesses two important data areas. The first one contains some suitable compacted and codified facsimile of the input logic program and is static. The second area is highly dynamic and is used by the interpreter to record the history o f its own actions. This is generally in the input heap and the execution stack. The stack represents both the execution control state and the data state. The interpreter changes its attention from one control to another, and it traces out a path called the locus of control. Consider the following rules: P: A if Plt P2 P4 P„. Q: B if Qj.Q* Assume that some of the subgoals in body of P, Ph ..., PM, have been solved. The subgoal ^ is tried next. If P, matches with B then the procedure Q is executed. After Q Q, is solved, control goes back to procedure P to execute Phi- If any Q is unsolvable, then control goes back to P to try another candidate clause which are applicable for Pi. (This is shallow backtracking). If there are no untried candidate clauses applicable for P., then control goes back to P_,. (This is deep backtracking.) The complete computation space is explored before computation stops. Exploration of computation is achieved by creating and storing a frame for each procedure call on a linear stack called the local-stack. The procedure entered and not exited is called active. The frame is maintained as long as the procedure is active. 34 The frame can contain variable cells to know the variable values. But, the output assignments of a frame have to be undone on backtracking. If the frames contain cells for variables, then discarding the frame is enough to achieve backtracking. Havings cells for variables in a frame leads to excessive use of space, since duplication is ram ­ pant. One can use another area called the trail which contains the values for the active variables. A cell with trail pointer is created in every frame. On deleting a frame, all assignments from the trail-pointer to the top of the trail are undone for effective back­ tracking. A two stack representation has a local-stack and a global-stack. the local-stack contains the frames of the procedure calls. The global stack contains variables that are global to the called procedure. A cell for the global frame pointer is every frame. In order to search the complete computation space, a goal-list is maintained. The goal-list contains all the goal that have to be solved before the primary goal is announced as a success or failure. Every procedure call modifies the goal-list and the local-stack as follows: 1. H ie first literal in the goal-list is chosen for execution. 2. A frame is created for this goal and is added to the top o f the activation stack. 3. A procedure to solve this goal is selected. 4. If no procedure is available to solve this goal, then the goal is announced as a failure and backtracking is invoked. 5. If the procedure selected to solve the goal is an assertion, i.e., a fact, then the unification substitution that makes the procedure selectable is applied to the goal-list. 6. If the procedure selected to solve the goal is a rule, then the goal-list is the 35 resultant of appending the goal-list with the rule-body. 7. The above steps are repeated until the goal-list is empty - when a result to the primary goal is available. If the stack is empty, then announce failure; else announce success and pro­ nounce the substitution applicable to the primary goal as a result of the success. A push occurs when the goal at the top of the goal-list is selected for execution. If the goal at the top o f the stack unifies with a program clause, then the resolvent is added to the head of the goal-list. A pop occurs when there are no program clauses whose head matches the goal at the top of the stack. The goal at the top o f the stack is added to the head of the goal-list If the goal-list contains the body o f a program clause, then this body is removed from the goal-list. The next choice of matching clause for the new top of stack is investigated. Computation continues in this manner until the goal-list is empty. This is the state U and success is reported. If the localstack is empty then, the state ■ is reached and failure is reported. Figure 2 illustrates the execution of a Prolog program on a linear stack for two instances (marked "#") Figure 1. The execution of a logic program is carried out by the interpreter. There are numerous issues pertaining to the implementation of interpreters for logic programs. These are described briefly in the next section. 30 p9 p8 — r- P7 — r p6 ZH p5 — 1~ p4 ~ ~ l~ p3 P2 —r~ Pi pO Figure 2. E xecution o f Prolog on a linear stack. 37 2.6. Implementation Issues Many implementation issues pertaining to implementation of an interpreter for Prolog have been addressed by researchers. Some of the key issues that are addressed are the data structures that are to be used and efficient management o f dynamic data during execution. Efficient memory management [28, 33] and backtracking [11 - 23] schemes can be used to avoid unnecessary computations and prudent searches. Last call optimiza­ tion is a technique which deletes a frame from the activation stack, once the last call for a procedure has been activated. One of the most recent result is based on the locality of reference in the execu­ tion o f Prolog programs (the locality being the top of the stack). All but the page which contains the top o f the stack is kept in the main memory. Hashing, indexing and special techniques for coding the programs are developed for efficient selection of clause for executing a goal [28,33]. Warren [29, 31, 32] has developed a stack-based method of executing compiled Prolog clauses. The method employed by the Warren Abstract Machine (WAM) eliminates tail-recursion. WAM maintains certain information in registers to effect speedy selection o f the backtrack literal on the stack, and resetting of the local-stack, trail and heap. The significant results pertaining to efficient sequential execution of logic pro­ grams are described in the next chapter. These results are based on selective back­ tracking for re-exploration of the search space. Chapter 3 3. Literature Review 3.1. Introduction Research in the area o f efficient execution of logic programs is exemplified by the Japanese Fifth Generation Computer Project, started in the 1980’s. Towards this objective, researchers have been focusing on efficient implementation of logic pro­ grams, which would be useful in knowledge processing systems. Prolog has proved to be a successful programming language. In this chapter we describe in detail the results obtained by other researchers in their attempts to develop a model to efficiently execute logic programs. The basic computational mechanism of Prolog is pattern matching on terms of logic. The matching expands the computation into a proof tree, until terms are shown to be true or false. In sequential execution, the proof tree is expanded in a depth-first manner. The goals o f a clause are executed left to right and the goals of the most recent clause entry are executed first The unification creates a binding of variables to terms and other variables, which affects further unification attempts. If, at any time the system fails to find a match for a goal, it backtracks, rejecting the most recently activated clauses and undoing any bindings made by the matches with their clause heads. An obvious and simple technique in efficient execution of logic programs is identifying and backtracking to a better backtrack literal when a failure occurs during execution. 38 39 3.2. Selective B acktracking Baaed on Unification M apping Inform ation The unification substitution mappings employed during goal search brings in dependencies among the different goals. Pereira and Porto [11] developed a model to use this information that is generated at runtime to select a better backtrack literal when a failure occurs during goal search. In their model a goal execution is represented as a box with four ports, DO, DONE, REDO and UNDONE. The DO port o f a goal is entered when the goal is first activated. The DONE port of a goal is exited on a successful execution of the goal. On backtracking to a goal, the control re-enters the goal execution box through the REDO port. Control exits through the UNDONE port of a goal on unsuccessful exe­ cution of a goal. Every goal execution box decomposes itself into similar boxes for the subgoals in a rule on unification of the goal to the bead o f the rule. Figure 3.1 shows the execution model developed by Pereira and Porto. The main idea of selective backtracking is to select, at each failed goal, a single goal to backtrack to, not necessarily the previous goal as in standard backtracking in Prolog. Consequently, entry into the REDO port of G is allowed, only if G has been selected as the backtrack goal for the last failed goal; otherwise, control flows directly to the UNDONE port of G. At the UNDONE port of a goal, in a rule, selection of the backtrack goal takes place. Deselection of the backtrack goal is done when backtracking to the goal occurs. The backtrack goal is selected from among: Ancestors of G The goals whose alternative clauses avoid a reactivation of G (essentially the parent of G) 40 Modifying goals of G The goals whose match if undone will undo failure (the goals on which G is dependent) Legacy set of G The set of candidate backtrack goals inherited from the failed goals that selected the backtrack goal A dependency tag list representation is used to maintain all the dependencies generated at runtime, in a dependency-graph. After every unification this dependency-graph is modified. This graph maintains all the information required to do optimal backtracking. The modifying goals of a failing goal, G, is constructed whenever G fails and the backtracking goal is selected. The overhead incurred in modifying and maintaining the dependency-graph, with every unification, is rather large and complex. Analyzing unification failures to construct the modifying goals is also expensive. Figure 3.2 shows the dependency tag representation and the modifying goals for two instances (marked "#") from Figure 1. 41 DONE DO S e le c t backtrac < Clause Head M atch UNDONE D e se le c Body Executic n select' REDO Fig u r e 3.1. R e c u r s i u e E x e c u t i o n M o d e l bi Y —- 1 —- Z — - c l 2 -X - al b2 —- Y - 1 — Z c2 2 a2 - X 4 .... u —- dl 5 .... w —- el 6 —- V —- fl Figure 3 .2 D ep en dency Graph rep resen tation Figure 3. B acktracking based on U nification inform ation. (Pereira et al.) 42 3.3. R un-tim e Intelligent B acktracking The selection o f the appropriate backtrack goal without maintaining the dependency-graph can be done using runtime information [12 - 16]. As execution of goal search proceeds, a deduction tree is b uilt A naive interpreter always considers the whole proof tree as a failing tree when a failure occurs. A smaller deduction sub­ tree can be identified as the cause of failure. This could lead to pruning of redundant search space. Cox and Pietrzykowski [12, 13] and Bruynooghee and Matwin [14 - 16] describe methods to find a minimal deduction subtree in which unification is impossi­ ble, i.e., which holds no solution, and maximal deduction subtree in which unification is possible, Le. could contain solutions. W henever a goal fails, the whole deduction tree becomes inconsistent. A minimal failing deduction tree can be constructed by analyzing the variable bindings, [16]. The clause choice, i.e., the program clause currently applied, to one of the leaf nodes of one of the minimal failing trees is changed and computation proceeds as usual. Alternatively, a maximal subtree that is consistent can be constructed by analyzing the variable bindings, and then a clause choice of one o f the leaf nodes not in that subtree is changed and computation is continued as usual, [12,13]. Bruynooghee [15] also presents a backtracking scheme in which dependencies of a goal P are constructed when P is unified with various clause heads. Subsequently, a scheme to generate and maintain the modifying goals of P is developed in the same paper. A lot of information about runtime dependency and bindings has to be main­ tained to implement intelligent backtracking. Figures 4.1 and 4.2 show the minimal and maximal deduction subtrees described by Bruynooghee and Cox, et al., respec­ tively. 43 , Unification substitutions X /a 2 Y /b l z /c l U /d l at 2 at 1 at 1 at 4 1 and 3 do not share substitutions Minimal consistent deduction subtree Figure 4.1. Minimal Deduction Subtree th at is consistent, of Brunooghce. Maximal inconsistent deduction subtree On failure o f p5 modify either p i or p3. Figure 4.2. Maximal Deduction Subtree that is inconsistent, Cox. 44 3.4. Sem i-Intelligent B acktracking Based on Static D ata Dependency Analysis (SDDA) In general, there are two kinds of backtracking: shallow backtracking and deep backtracking. Shallow backtracking is backtracking to alternative candidate clauses, when the head of the current candidate clause cannot unify with the calling literal. Deep backtracking occurs when there are no untried candidate clauses for the current procedure call, so backtracking occurs to any previously invoked procedure. Dependencies among the subgoals in a rule are used for deep backtracking. A static-data-dependency-graph which represents the static dependencies of the subgoals in a rule, can be generated using the textual information about the rule. The SDDA of a rule is a directed acyclic graph and is independent of the runtime unification substi­ tution information. Literals in the SDDA which are equidistant from the root are said to be in one layer. Chang and Despain [17, 18] propose a method to select the backtrack literal from the SDDA, when a failure occurs. They construct an SDDA for each clause at com­ pile time. They assume that if two literals do not share any unbound variables, then they are independent, because the dependence among literals which do not share a variable (static information) is generated at runtime. They define three types of back­ tracking. Type I The parent of a literal, in the SDDA of a rule, is chosen as a backtrack literal when a literal fails during forward execution, i.e., without producing any solutions. Type II The next left brother sibling in the same layer of the SDDA of a rule is selected as the backtrack literal when a literal fails after producing solutions 45 in its forward execution. What this means is that the literal succeeded, but its solutions were not accepted by some successor o f the literal in the SDDA of the rule. Type HI Backtracking within a clause defaults to naive backtracking, as in Prolog, if the clauses succeeded. The SDDA is used during type I and type n backtracking. Intelligent back­ tracking based on the SDDA is local to a procedure (rule). This reduces the number of redundant steps and its effect is inter-procedural. Literals in the same layer of an SDDA of a clause (rule) are assumed to be independent during the forward execution. The literals in a layer may not be independent if any literal in the next layer has been executed. The backtracking based on SDDA does not always give the best selection of a backtrack literal, but avoids excessive runtime overhead. Hence, this method o f backtracking is called semi-intelligent backtracking. Also, many SDDAs can be constructed from a given rule. There is no systematic way of identifying the best SDDA. Figure 5.1, 5.2, and 5.3 show the use of SDDA for Type I, Type II and Type HI backtracking, Chang and Despain [17 -18], for two instances (marked "#") from Figure 1. Static Data Dependency Graph (SDDA) 4 On failure at 6 backtrack to 0. 5.1. Type I backtracking based on SDDA 47 Backtracking after Forward Execution. On failure at 6 after failure at 9 backtrack to 4. 5.2. Type 11 b ack track in g based on SDDA Backtracking after succeeding by a rule. On failure at 9 backtrack to 8. 5.3. Type III b ack track in g based on SDDA F ig u r e 5 . Semi-Intelligent Backtracking based on SDDA. (Chang et.al.) 48 3.5. Generator-Consumer Approach The generator-consumer relationship among the literals in a rule is based on the dependencies that are caused by sharing variables by the literals. This rela­ tionship gives information similar to the information obtained by the data-flow analysis o f the literals in a rule. Conery and Kibler [19 - 23] use the generatorconsumer information in a rule to select a backtrack literal. This scheme incurs small overhead and yet can eliminate redundant backtracking in many problems. The generator-consumer relationship can be described as follows. One of the literals sharing a variable X is considered the generator of X. the other literals which use the variable X are considered as consumers of X. The generatorconsumer relation can be depicted as a data dependency graph D, which is a directed graph, in which a literal L is the parent of another literal M, if for some variable X, M is the generator of X and L is a consumer of X. Whenever a goal P„ fails the backtrack point is chosen from the set of goals that have generated the values of the variables X, ... , X, that occur in the argu­ ments of To enable the construction o f this set of goals, some extra informa­ tion is maintained with each variable - namely, the generator o f the binding of the variable. The backtrack goal selection using the generators of the variables o f the failing goal is not precise, but runtime overhead is small. Whenever unification of a goal P with some clause head results in assign­ ment of a value to a variable, X, a tag P is attached to the variable X, indicating that the value to the variable X was generated at the goal P. This assignment is undone when backtracking takes to P, or to the left of P. This tag is unique at any moment due to the single assignment property of logic programs - there can be only one assignment to a variable at a time. When a goal P fails, then the modifying goals of P are the generators of the 49 variables used by P and the parent of P - the goal that unified with the head of the clause containing P. The B-list with a literal P is the order list o f the modifying goals of P. Backtracking takes the first element of B -list H u s method leads to backtracking to any point in the proof tree rather than to the clause containing the failed goal. This is because the generator/consumer relationship that tran­ scends clause boundaries is also maintained. Figure 6 illustrates the use of Blist, by Conery and Kibler, for backtracking for two example from Figure 1. The scheme developed by Conery and Kibler misses solutions under situa­ tions similar to the type n [17 - 18]. This was cured, independendy, by Kumar [24 - 25] and Woo and Choc [26], independendy. 50 goal B-list 1 [OJ 2 [01 3 [2] On failure at 9 backtrack to 6 4 [ 2 ,1 ] On failure at 6 backtrack to 0 3 [4, 2, 1] 6 [01 7 [6, 2] 8 [I] 9 [6. 4, 2] 10 [4. 11 11 [2 . 1] Figure 6. B acktracking based on B -list., o f C onery and Kibler. 51 3.6. Modified B-list Approach The approach by Kumar [24 - 25] and Woo and Choe [26] is as follows. When a literal Q is selected as the backtrack goal, when a goal P fails, Q being the most recent goal in modifying(P), Q is also passed the (modifying(P) {Q) >. When Q, fails the latest goal from (modifying(Q) u [modifying(P) {Q ) }) is selected as the backtrack goal. The major difference here is the use of dynamic B-lists. The backtracking method based on dynamic B-lists is shown to be complete. Figure 7 illustrates the modified B-list, approach by Vipin Kumar, for two instances (marked of Figure 1. 52 goal B-list goal B-list 1 10] 1 10] 2 [0] 2 10] 3 12] 3 12] 4 [2. 1] 4 12. 1] 5 [4. 2, 1] 5 [4. 2. 1] 6 10] 6 14. 2] 7 16. 2] 8 11] 9 16. 4, 2] Backtrack literal Is the B-list after backtracking from 9. elem ent in the B-list with a literal. Figure 7. B acktracking b ased on dynam ic B -list , ofVipin Kumar, et a l 53 3.7. Variable Baaed Intelligent Backtracking An approach based on variables, rather than the predicates, is presented by Rajasekhar and Narasimha Murthy [27]. The variables used by the goal is used for identifying the backtrack literal. These results developed are comparable to those of Kumar in terms of complexity, but could lead to the elimination of a lot of redundant backtracking. A tag with every variable is maintained. This tag indicates where the variable got its binding, its present instantiation. On failure of a goal, the tags o f the variables used by the goal is examined in order to select the backtrack literal. The modifying goals are maintained similarly as with Kum ar's method. This scheme is not very easily implemented on a linear stack. Figure 8 illustrates the use o f variable tags for backtracking for two instances (marked "#") of Figure 1. 5'1 1 Y- 1 1 Z- 1 i X 2 w Z - X Y U -4 W-5 V -6 Backtrack based on the variables used by the failing literal. Figure 8. Variable B ased Backtracking, o f Rajasekhar, e t al. 55 3.8. Warren Abstract Machine Prolog requires a stack, called the local-stack, to hold frames for each active procedure. The local-stack contains all the bookkeeping information together with the value cells for local variables. A frame is reclaimed only on backtracking. The Warren Abstract Machine (WAM) [29 - 32] is the most efficient method for executing Prolog programs by elimination of tail recursion. In WAM, the local-stack contains only the records o f the goals in the current path which have pending untried alternatives. A frame is reclaimed when its last alternative is used up. Maintaining the most recent choice-points in a register and employing structure sharing rather than structure copying leads to further efficiency [28]. The code for the clauses reside on a heap and execution unfolds on local, global and trail stacks. The local-stack contains the variables o f the clause, along with the environment pointer to manage code and data. The global-stack holds complex structures and the trail keeps pointers indicating the unification substitu­ tions created by the goals. The global-stack bolds complex structures, such as lists, and the trail keeps pointers to variables which are not local to the current clause and are assigned during unification, in order to undo their bindings during backtracking. As each goal is called for unification, an activation record is created on the local stack for its variables. New structures created by the goal are placed on the global-stack. Activations on the local-stack can be deallocated after a goal returns and has no alternate clauses to try (called success popping) or when backtracking occurs. Global locations are kept until backtracking occurs. Stack allocation and deallocation of the stacks eases storage reclamation substantially, reducing 56 runtime storage needs. On the local-stack, there can be several goals with alternatives yet to be tried. These goals are called choice-points. When unification fails, the most recent goal, which is called the choice-point is selected for backtracking. The last-choice register maintains this choice-point and helps in this selection. Each activation maintains the last-choice pointer, which is loaded to the register when this goal is executed. Each activation also maintains a fail point pointing to its next alternate, yet to be tried. The trail is unwound after backtracking by looking at the choice-point register, in order to undo some of the unification substitution. Thus, when a goal fails, the processor need only look at the choice-point register to find the correct environment to restore. The trail is unwound back to the beginning of that choice-point goal by popping each address and tagging the location as undefined. Shallow backtracking needs only transfer of control to the fail point, but deep backtracking needs to clear the local- and global- stack and reload stack pointers from the choice-point activation and then transfer control to the fail point of the choice-point goal. Figure 9 illustrates the information on the WAM local-stack for two instances (marked "#") o f Figure 1. 57 The departure from the conventional Prolog execution in WAM is that instead of passing the information about the caller to the procedure, it is now given a pointer to the actual goal to be executed next cm backtracking, called the choice-point. The choice-point points to the most recent ancestor with further alternatives left to execute. The execution is efficient in space and time by elimination of unnecessary activations on the stack and by prior knowledge of alternatives in the form of choicc-points. 58 p3 pO Figure 9. L ocal-stack u sed b y WAM, o f Warren, 59 3.9. Discussion The techniques described in sections 3.1 - 3.6 have significant inherent drawbacks in effective implementation for savings in sequential implementation of Prolog. These drawbacks arise due to excessive run-time time and space requirements for runtime maintenance of unification substitution information, and maintenance of dynamic data dependency graph. Severe difficulties in implementations of these results also arise due to the imple­ mentation of Prolog on a linear stack. The runtime cost is measured in terms of the amount of work done during execution and the amount of dynamic space that is required. A method is sound if every solution obtained by the method is valid (correct). A method is com­ plete if every solution to a problem (valid or invalid) is obtained by the method. The following table compares the various results for their time and space com­ plexity together with the savings in computation. 60 Authors Runtime cost Execution Linear Stack Sound/Complete Pereira & Porto Prohibitive No Yes/Yes Cox & Piertowzski Prohibitive No Yes/Yes Bruynooghee & Matwin Prohibitive No Yes/Yes Conery & Kibler Pair No Yes/No Vipin Kumar Fair No Yes/Yes Rajasckar Linear No Yes/Yes WAM Best Yes Yes/Yes " Table II: Comparison of Results in Literature Parallel execution models and parallel logic programming languages are being developed for faster execution of logic programs [36 - 54]. Table II com­ pares the performance of the existing results in literature. These methods do not address the central issues for intelligent search, described in section 2.4. This dissertation addresses these issues, leading to intelligent search; it proposes and presents efficient implementable algorithms. Chapter 4 + 4. Intelligent B acktracking Baaed on F ailure Bindings 4.1. Introduction When a goal fails, the conventional assumption is that the cause o f failure o f the goal is the set o f all bindings applied in obtaining the goal. In this chapter the notion of a failure-binding for a literal' is defined. This definition is extended to predicates. A failure-bin ding for a literal is a precise cause o f failure of the goal which is obtained from the literal.1 This precise cause is a member of the set containing the bindings applied to obtain the goal. There can be zero or more failure-bindings for a literal identified when a goal fails. This depends on the information content of the logic program. A method which uses a bit-vector to identify the failure-bindings of a literal is presented. Intelligent backtracking based on failure-bindings o f the currently failed literal is presented. The savings in redundant backtracking by intelligent backtracking based on the failure-bindings o f a literal is illustrated. The search based on failure-bindings, is shown to satisfy the complete­ ness and soundness properties of Prolog, g also obtains the results of a goal in the same order as obtained by Prolog. Forward and Backward Execution Algo­ rithms for ^ are given. Consider the example in Figure 1. When the failure o f p5(Z, X, U, W) with s e e 159]. A literal is an instance of a predicate. The arguments of the predicate arc substituted by terms made up of constants and w iables to give a literal. A more general definition of failure binding can be found in [34], 62 the bindings 77c!, X/a2, U /dl is detected, then the backtrack literal selected by dependency directed backtracking is the latest of the generators of Z, X and U. This is the generator of U, Le. p4. Hence, dependency directed backtracking selects p4 as the backtrack literal. On analysis o f the predicate relation of p5, it can be seen that p5 can never succeed with Z /cl. p5 will never succeed, unless the binding Z/c 1 is changed. W e show that such precise individual causes of failure of a goal can be identified and used effectively for pruning goal search tree. The premise to such identification is that every failure is due to failure during unification, which is a pattern matching process, and a failure occurs only after exploring the whole goal search tree of a goal. The gain in efficiency derived by employing intelligent backtracking based on failure-bindings is, however, not without a co st Additional work is required in identifying and maintaining the causes of failure during the search. The amount of work done in identifying and maintaining the causes of failure is overshadowed by the savings derived by their use, as is described in the later sec­ tions. 63 4.2. Failure-B inding When a goal G fails, the causes of failure of G is not known. In fact, the cause of failure is attributed to die set of bindings applied to obtain G. Intelli­ gent backtracking methods described in [5 - 13] perform relevant search. These methods still suffer in performance due to insufficient information about the cause of failure o f a goal. In a logic program a variable can be in either of the three states: Free, Ground or Partially-instantiated. In a Ground state the variable is instantiated to a ground value. For example, X/a means X is in the Ground state with a ground value ’a*. In a Free state the variable is completely uninstantiated. In the Partially-instantiated state, pan of the variable is in the Ground state and pan of it is in the Free state. If X/[Y, Z] with Y/b and Z in the Free state indicates, then X is said to be in the Partially-instantiated state. 64 E xam ple state Variable instantiation X- X/a Ground X none Free X X /[Y ,a] Partially Instantiated A Prolog literal is an instance of a predicate with many variables that form its arguments. There are no restrictions on the state o f these variables that form the arguments o f the goal (i.e., there are no mode restrictions). A consequence of a mode free program is the VO indirection of Logic Programs. During execu­ tion, a set of bindings is applied to a prolog literal to obtain a goal. The success of a goal may generate zero or more newer bindings to the variables which were in the Free state at the time o f the call of the goal. A goal fails if there is no solu­ tion to the predicate with the bindings applied to obtain the goal. The goal can never succeed with this set of bindings. A different set of bindings is necessary to satisfy the predicate. Definition 4.1.: A prolog goal g for a predicate p is a pair g = (p't a ) where 1. p ' is an instance of p.f 2. a is a set o f instantiations applied to all variables in p'. Alternately we represent the goal g with the argument tuple of p ' with the substi­ tutions from a applied to all the variables in p'.* t An instance of p is a literal of p. with its arguments substituted by terms. 5 A Prolog goal g » (p'. a ) is also an instance of the predicate p N otation suggested by K undu, (331. 65 Definition 4 2 .: Let g be a prolog goal, g « (p \ a ). The Variable-set of g, denoted v B, is the set of all the Free variables in g. The Constant-set of g, denoted C, is the set of all the constants in g.1 Exam ple argument tuple predicate goal p(argl, arg2, arg3, arg4). (p(X, Y ,d ,Z ), (X/aJ) p(a, Y, d, Z). q(argl, arg2, arg3). (q(P,Q , R), (R/[a, b])) q(P, Q, [a, b]). r(argl, arg2). (r(a, b), {)) r(a, b). s(argl, arg2, arg3). <s(P, Q, d), (}) s(P, Q, d). representation Exam ple instance ot Vanable-set (Jonstant-set predicate of instance of instance pCa, Y, d, Z) lY .Z j (a, d] q(P, Q, R) {P. Q .R} {) rfa, b) (} (a ,b ) s(P, Q, d) (P .Q ) Id} The successful execution of a goal g generates a set of new instantiations for the variables in Vg. Due to the single assignment rule, a successful execution of a goal can assign values only to variables whose instantiations are not defined in a . We 1 g uniquely defines Vf and Cg. 66 denote this set of newer instantiations generated when g succeeds by &, or simply A. A can possibly be empty. When g fails, A is necessarily empty. A goal g - (p \ a ) fails if every alternative applicable to the predicate p, of which p ' is an instance, fails to solve p". p" fails if 1) g fails to unify with any fact of p, 2) g fails to unify with the rule-heads of some rules for p, and 3) every rule for p, p pjj, p ^ ,.., pM , 1 £ j £ k, which is applicable to g (there are k rules applicable to p") fails to solve g. The classical assumption is that the cause of failure of p ', which gave g, is a, since p ' will always fail with this particular combination of bindings in a . The fol­ lowing definition is used for identifying precise cause of failure for p'. Definition 4.3.: If the goal p" * (p', {X/v}) fails, then X/v is a failure-binding for p'. Similarly, if p" ■ (p', {)) with the constant-set of p ' Cr- - {c) is false, then c is a failure binding for p'. It can be observed from the definition of a failure-binding of p ' that if X/v is a failure-binding for p', then any goal g' obtained by applying X/v to p' and any other values for other variables in Vp. is also false. In general there can be more than one failure-binding fo rp '. The failure-bindings for p ' are identified by combining the causes of failure for p' from the failure of a general goal g = (p', a ) by each alternative of p. When a goal g = (p', a ) fails, the causes of failure for p ' with respect to each of the alternatives are identified. The cause of failure for p* by an alternative is obtained from the facts:* * Pemonal com m unication, Kundu (33). 67 Fact 1: A binding X/v e a is a cause of failure for p ' due to a fact of p if v fails to unify for X in the fac t Fact 2: A constant c e O’ is a cause o f failure for p ' due to a fact of p if c fails to unify in the fact. Fact 3: A binding X/v € a is a cause of failure for p ' due to an alternative o f p which is a rule if a) v fails to unify for X in the rule-head of the rule or b) part of v is a failure-binding o f some subgoal in the rule-body of the rule. The unified version o f the rule, r”, obtained after g unifies with the rule head of the rule r r : p :* p i, p2, p 3 ,.... pm. is r p , p "* p i i p2 , J i _ M _ « , _ i » i _ A « i pm . _ _ « i X/v € a is a cause of failure for p ' by the rule r if there exists some X '/v', v ' is a pan of v, obtained via unification o f g to the rule-head of the rule, and X '/v' is a failure-binding of some subgoal pj" in the rule. Fact 4: A binding (c e Cp ) is a cause of failure for p' due to an alternative of p which is a rule if a) c fails to unify in the rule-head of the rule or b) part of c is a failure-binding o f some subgoal in the rule-body of the rule. The unified version o f the rule, r", obtained after g unifies with the rule head of the rule r r :p p i, p2, p3 pm. 68 is r p ,p _ * l _ * t1 •" p i *pZ * <ti pm * , _ * M - O " n 1 ^ 1 11 c is a cause of failure for p ' by the rule r if there exists some c', which is a part o f c, obtained via unification of g to the rule-head of the rule c ' is a failure-binding of some subgoal pj" in the rule. Fact 5: If there are no rules or facts of p, then every memberof a and every member o f Cy is a cause of failure for p'. A failure binding for p ' can be obtained from the complete goal-search-tree of gf = (p \ a ), which is known when the failure of g is detected. (1) If the goal-tree of g is o f height zero, i.e., there are no facts or rules of p, then every X/v e a and every c e is a failure-binding for p'. (Fact 5) (2) If the goal-search-tree of g is of height one, i.e., there are only facts of p but no rules, then a binding X/v e a (or a constant c € Cp.) is a failure-binding for p ' if X/v (c) is a cause of failure for p ' with all the facts o f p, by Fact 1 (Fact 2). (3) If the goal-tree of g has height 2 2, i.e., there are facts and rules of p, a bind­ ing X/v (a) e a (c e Cy) is a failure-binding for p ' iff X/v (c) is a cause of failure for p', according to Fact 1 (Fact 2) with respect to each o f the facts of p and (b) X/v (c) is a cause of failure for p', according to Fact 3with respect to each rule of p, by Fact 3 (Fact 4). Exam ple t Wc only consider goai-trees which *re finilc, i.e., there is no infinite branch. * IW i definition la my rewording of note* from Knndu [33). 69 For the goal p" - (p(X, b, Z), (X /al, Z/c2}) with no facts and rules for p the failure-bindings for p{X, b, Z) are b, X /al and Z/c2. Exam ple Consider that the predicate q is defined only by the facts given below* Facts ot q q(a2, b2, c l, d3). q(a3,b2, c 2 ,d l). q(a2, b3, c3, d2). The failure-bindings for diffierent instances of q according to (2) above is shown in Figure 10. goal taiiure-bindings reason (q(P, Q, R, d l), (P/a2, Q /b l}) Q /bl b l fails to unify for Q (q (a l,S , T, d l), (t/c 2 J) al al fails to unify (q (al, Y, 2, W), [ Y /bl, Z /c3J) a l; Y/bl a l fails to unify b l fails to unify for Y (q(X, Y, Z, d l), [X/a2, Z/c3J) none no common cause o f failure Figure 10. Identification of Failure-Bindings when a predicate is defined by facts. Consider the goal (q(P, Q, R, d l), {Q /b l}) in Figure 10. The value bl fails to unify, for Q, in each of the facts for q. Hence, Q /bl is a failure-binding for q(P, Q, d l). Consider another goal (q(al, S, T, d l), (T/c2J). The value a l fails to unify in each of the facts for p. Hence, al is a failure-binding in q (al, S, T, d l). Two failure- t From discussions with Kundu, [331. 70 bindings for q (al, Y, Z, W) can be identified when the goal (q(al, Y, Z, W), (Y /bl, Z/c3}) fails, because a l does not unify in each o f the facts for p and b l does not unify for Y in each o f the facts for p. No failure-bindings for q(X, Y, Z, d l) can be identified when the goal (q(X, Y, Z, d l), {X/a2, Z/c3}) fails, because none of a2, c3, or d l fails to unify in each of the facts for p. 71 Exam ple Figure 11. shows the identification of failure-binding for r(X, Y) using the facts and rules of r.f Consider the following facts and rules for the predicate r and the goal r" = (r(X, Y), {X/al, Y /bl}). 1 .r(a l,b 2 ) .------------------------------2. r l l<al ). 3. rl2(b2). 4. r21(al, c l). 5. r22(cl, b2). 6. r(X, Y) :-rll(X ),rl2 (Y ). 7. r(X, Y) alternative r21 (X, Z), i22(Z, Y). cause ot failure o f r(X, Y) 1 Y /bl 6 Y/bl 7 Y /bl Figure 11. Failure-binding in the presence of facts and rules. The facts of r, listed above, suggest that Y /bl is a failure-binding for r(X, Y). The first rule of r fails to solve r(a l, b l), because pl2(Y ) fails and Y /bl is a failure binding o f rl2(Y ). This suggests that Y /bl is a failure-binding for r(X, Y). The second rule proceeds with the computation of r21(X, Z), which succeeds with a solu­ tion Z /cl. The goal r22(Z, Y) fails and Y /bl is a failure-binding for r22(Z, Y). The t This example was given by Kiindu, [33]. 72 suggestion that Y /bl is a failure binding in r(X, Y) still holds. There are no more alternatives for r. H ius, the suggestion that Y /bl is a failure-binding for r(X , Y) is substantiated by all the facts and rules of r. Note that Y /bl is still the failure-binding for r(X, Y), even if the fact p21(al, c l) is removed.1 In general, removal of any fact or rule cannot eliminate or invalidate any failure-bindings in that if X/v is a failurebinding in g then on removing any fact or rule it will still be true that X/v is a failurebinding in p". Alternatively, the addition of a fact or a rule can easily eliminate or invalidate a failure-binding for g. It is interestion to note that a failure-binding which is identified by analyzing the goal-tree of a goal, g - (p', a ), is applicable to any other goal, g ' « (p', o'). What this means is that every goal which is obtained from p \ by applying a failure-binding for p', will fail. If the arguments of an instance are either variables or constants, but no generalized terms, then a failure-binding for p ' is applicable for any instance of the predicate p, i.e. any goal g" - (p’\ a ") will fail if either Cy or a ', or both, contain one or more failure-bindings for any instance p ' of p. The substitution of these failurebindings in p" should correspond to those in p'. T heorem 4.1.: If X/v € a (c e Cy)) is a cause of failure for p \ obtained by analyzing the goal-tree of g * (p \ a ) which fails, due to every alternative, then X/v (c) is a failure-binding for p'.* Proof. By definition, if there are no alternatives for p, then every X/v e a and every c e Cy is a failure-binding for p'. If X/v (c) is a cause of failure for p ' by each alternative, then either v failed to unify for X (c failed to unify) in each of t Developed in conjunction with Kundu, [33]. % A more general definition of failure-binding, and its use, is considered by Kundu [33 - 34}. 73 the facts of p, and in some rule-heads of p, or part of v (c) is a failure-binding of some subgoal in every rule that is applicable to g. Effectively, this says that X/v (c) individually would cause failure of g with each alternative o f p. This will then be true if a contained only X/v (Cy contained only c). Hence, every alterna­ tive o f p will fail a goal p" = (p', (X /v)) (p" - (p', {)), Cy * {c}), leading to failure o f p". Thus X/v (c) is a failure-binding for p'. T heorem 4.2.: If X/v e a (c e Cy) is a failure-binding for p', then X'/v e a ', or v e C y, (c € C y, or X'/c e a ) is a failure-binding for p* if X', or v, in p" corresponds to X in p ' (c, or X', in p" corresponds to c) in p'. Proof: Since X/v is a failure-binding for p ' we can say that v (c) fails to unify for X in the facts of p and in some rule-heads of the rules o f p and either v (c) or parts of v (c) are failure-bindings of some subgoal in each of the the rules o f p. The same facts and rules are applicable for p". Since X', or v, in pMcorresponds to X in p ' (c, or X', in p" corresponds to c) in pO the same cause of failures for p' are applicable to p". Hence, X/v (c) is a failure-binding for p”. The definition of a failure-binding can be generalized for the case of a compound goal containing several ANDed goals (such as a rule body). In this case, we say that a binding X/v (constant c) is a failure-binding for the compound goal if it is a failurebinding for at least one of the literals in the compound goal.1 Consider the facts and rules of r in Figure 11, without the fact r21(al, c l). There are two failure-bindings for the compound goal "p21(X, Z), p22(Z, Y)", namely, X/al (from p21(X, Z)) and Y /bl (from p22(Z, Y)). S Persona] communications, Kundu [33 • 34], 74 The definition of a failure-binding for a literal can also be generalized from the case o f a single binding of X/v, to the case o f a case of a set of bindings (X ,/v„ X /v 2, .... X ./V .), a set o f constants (c„ c* ... O * or a set o f bindings and constants, which together cause a failure of the literal. W e call such a composite set o f bindings that makes the literal false a composite failure-binding for the literal.* The conventional assumption that when a goal g = (p', a ) fails, the cause of failure is a u C^-. This gives us a composite failure-binding. E xam ple In Figure 10, we have (X/a3, Z/c3) as a composite failure-binding for q ' = q(X, Y, Z, W ), because the goal (q(X, Y, Z, d l), (X/a3, Z/c3)) fails.* The advantage of using the composite failure-bindings is that these may be encountered more often than the single variable failure-bindings. Put in another way, the composite failure-binding is a weaker notion than the single variable failurebinding. The generalization from singular failure-bindings to composite failurebindings is straightforward. The problem, however, is that the composite failurebindings can be numerous. Their identification and maintenance is much more com­ plex and expensive than identification o f singleton failure-bindings. t Personal communications, Kundu [33 - 34], t Personal communications, Kundu [33 - 34j. 75 4.3. F ailure Binding Table There is a failure binding table FBT(p) for each predicate p. H ie tuples of FBT(p) represent a failure-binding applicable to p. Every tuple of FBT(p) represents one failure-binding applicable to p. The tuples of FBT(p) are obtained as follows.* 1. Let X/v (c) be a failure-binding for p'. 2. We obtain p“ from p ' by substituting every constant in Cy by a dummy vari­ able # (obtain p“ from p ' by substituting every constant in Cy, other than c, by a dummy variable #). The dummy variable # always unifies. 3. The argument tuple o f (p“, (X /v)) (the argument tuple o f (p“, ())) is added to FBT(p). E xam ple The entries to the FBT(q) from Figure 10 is shown below. FBT(q) "IT T p bl al S T al Y Z # bl z # w w Entries to FBT from Figure 10. If a predicate p has only facts then FBT(p) can be computed by knowing the domain o f the program. The entries in FBT(p) could then be numerous. t Notation and concept of FBT developed in conjunction with Kundu, [33]. The use of subsump­ tion to keep the size of FBT small is due to Kundu, [33,34]. Kundu, [34], uses instead of 76 If there are rules of p, then no part of FBT(p) can be computed at compile time because no negative facts are allowed in Prolog. FBT(p) is initialized to be the empty table. All entries to FBT(p) are generated during execution.* As the execution proceeds, more and more failure-bindings for the various predicates are identified and they in turn are used to optimize the subsequent search process. The FBT(p) is void when the program is modified (externally or using the Prolog assert clause). If s = sl(S|, a ,..... i*) and t ■ tl(i„ tj O are two argument tuples, then s is said to subsume (i.e., be more general than) t if s unifies with t with the substitutions going from s to t, i.e., substitutions are made in s to make s identical to t.f Exam ple The tuple s - (al, bl, Z) subsumes the tuple t - (al, b l , c l) , because by substitut­ ing Z /cl, s can be made identical to t. However, s does not subsume the tuple q = (X, b l, cl). The tuples in each FBT(p) are maintained as maximal (most general) in the sense that tuple t is added to FBT(p) only if it is not subsumed by an existing tuple in FBT(p). Furthermore, when a tuple t is added to FBT(p), all the existing tuples s e FBT(p) which are subsumed by t are deleted. $ Personal communications, Kundu [33], t This subsianption definition corresponds to conventional definition of subsumption in database theory and other related fields of computer science. 77 Exam ple The maximal tuples in FBT(q) from Figure 10 are shown in Figure 12. al # " 5 " "5" bl z nr w Figure 12.2.: Maximal tuples in FBT 78 4 .4 . Forward Execution Based on Fallure-Bindings Forward execution is modified when there are failure-bindings for a literal which is used to obtain the current goal. The forward execution algorithm based on failurebindings is given in Algorithm A l. The failure-bindings of a literal are used for intelligent backtracking based on the generator-consumer approach. The generators and consumers of a variable in a rule dynamically change. The next section describes the maintenance of the generators and consumers in a rule in detail. 79 Phase I: Let g = (p't a ) be a new current goal. If (goal-list = em pty) then Report Success. Apply Algorithm B 1 (see section 4.6) elseif (g is subsumed by FBT(p)) or (no more alternatives o f p) then Report failure /* g fails */ Apply Algorithm B 1 (see section 4.6) else Phase D: Let i be the next alternative for p. If (no more alternative of p) then Report failure /* g fails */ Apply Algorithm B l If (alternative i is a fact and if g unifies with i) then Apply Algorithm A 1 at Phase I elseif (alternative i is a rule) then if (g fails to unify with the rule-head of i) then 80 Apply Algorithm A l at Phase II else let i" be the body o f the unified version of rule i. if (the a subgoal q*' in i” is subsumed by a tuple in FBT(q)) then Apply Algorithm A l at Phase II else Apply Algorithm A l at Phase I A lgorithm A I: F o rw ard Execution A lgorithm based on Failure-bindings. 4.5. Generators and Consumers Consider a rule r, The head of r is denoted head(r) and its body is denoted body(r). The generator-consumer list (in short, the gc-list) of a variable X in r is defined as the ordered list of subgoals in body(r) which contain the variable X in their arguments.1 The gc-list of a variable X in rule r is denoted gc(r, X). It is assumed that no rule in the program has alternate paths.1 If c is a constant in body(r), then we let gc(r, c) = head(r). This is done to indicate the fact that the presence of c is due to the rule itself. An instance o f a predicate may appear more than once in r. Hence, a con­ venient way to represent gc(r, X) is by a list o f the indices of the subgoals in body(r), where the subgoals are successively assigned the indices 1, 2, ... ,in left-right order ’ The indices imply the order of literals in the rule. The index 0 goes to head(r) and for a constant c, the assignment gc(r, c) = [0] is done to indi­ cate that c in r is explicit. The gc-lists for a rule r are easily determined by a sin­ gle left to right scan of the rule-body. An application t ' of a rule r is obtained from the set of unification substitutions applied to head(r), when a goal, g, unifies with head(r). The gc-lists of the variables in the unified form r' of r can be con­ structed from the gc-lists for r as follows. 1. Let (X, 4— e,} denote the unification mappings from g to head(r). X, This section on generators and consumers is largely taken from Kundu, [33 - 34], with adaptation to atomic constants and variables. For example the rule-body gl. g2, (g3; g4), g5." has two alternate paths, namely "gl. g2, g3, g5." and "gl,g2, g4,g5.". The index i 2 0 refers to a subgoal or the head of rule r which has the index i. 82 occurs in head(r) and t, is an expression made up of constants and vari­ ables, Yj’s, in g, 2. For each variable construct e(Xi) - {Xk | Xfc occurs in head(r) and body(r) and 3 Y, which appears in e* and in e*}. 3. Construct the gc-list o f the variables in / from e(X') as follows: gcfr', XO = ( u gc-list(r, X j | Xk e e(X,)) 4. The gc-lists of r* are ordered appropriately with duplicate occurrences of indices, if any, removed. Note that e(Xj * 0 if x* is substituted by a constant in r'. Consequently, gc(r', x j = [0]. If c is a constant in bodyfr'), then we let gc(r', c) - [0]. A simpler notation, gc(X), for gc(r, X), is used when the rule application is understood. Example Consider the rule r, from Figure 1.: r : pO(X, Y ) :- pl(Y , Z). p2(X), p3(Z), p4(X, Y. U), p5(Z, W). p6(V), p7(X, V), p8(Y), p9(X, U, V), pl(XY, U). pi 1(X, Z). The gc-lists of r axe gc(r, X) = [2, 4 ,7 , 9, 11 ] gc(r, U) = [4, 9, 10] gc(r, Y) = [1, 4, 8, 10] gc(r, V) = [6, 7,9] gc(r, Z) = [1, 3 ,5 , 11] gc(r, W) = [5] Now, consider an application r' of r obtained by the unification of the goal g = (pO(X\ X '), O ) to the head(r). The unification mapping from g to r is given by { X < - X ',Y 4 - X '} . 83 e(X) - (X, Y) and e(Y) - {X, Y) Therefore, the gc-lists of r ' are & ( /, X) « gc(r, X) u gc(r, Y) - [ 1 .2 ,4 ,7 , 8 ,9 , 10, 11] gcCr', Y) - gc(r, X) u gc(r, Y) - [ 1 ,2 ,4 ,7 ,8 ,9 ,1 0 .1 1 ] For the (dummy) variables Z, U, V, and W which appear only in the body of rule r (and hence only in the body of r0. their gc-lists remain unaltered, e.g., gc(r, Z) = gc(r/, Z). Consider r", which is an application of r for the goal gH■ (pO(X”, Y”), {Y/yO}). The unification mappings are {X «—X, Y «—yOJ. e (X )« (XJ and e(Y) - 0 . Therefore, the gc-lists of r" are gc(r", X )* g c (r, X) gc(r’\ Y) ** [0] The other gc-lists remain the same as before. The gc-lists of r"" which is an application of r for the goal (p(X""t Y""), {X""/[x0, yO])) are gc(r"H, X) = [0] gc(r’"’, Y) = gc(r, Y). The gc-lists give an abstract representation of the rule r in that these lists are not affected by certain changes in permutations and composition of the arguments of a literal in r. For example, if the literal p4(X, Y, U) in the above example were replaced by p4(Y, X, U), or by any other literal which uses the variables X, Y and U, the gclists would remain unchanged. 84 The importance of the gc-lists comes from the fact that they contain all the relevant information about the structure o f the rule r for determining intelligent back­ tracking operations as explained in subsequent sections (and forward jumping, as explained in chapter 7). A state of computation, 0, in a Prolog execution corresponds to a node in the goal-seaich tree, or more precisely, the path from the root to that node. The path describes the sequence of successive rule-applicadons and their associated unification substitutions. Thus, the state of computation gives the current goal, the active set of variables and their instantiations. If the same rule r is used more than once along a path, then they are distinguished by their order of occurrence in the path. The notion of a generator for a variable X in a particular application r' of rule r and in a computation state 6, the path from die root to a node in the goal-search-tree, is defined as follows: I Let the subgoals j £ 1 in r' be the subgoal that is being investigated in the state 6. The subgoals 1 £ i < j in r ' have been satisfied in states prior to 6. n If, for some i, 1 £ i < j and i £ g c(r\ X), X is assigned a value in course of satisfying the subgoal i in r', then i is called the generator of X for r' in the state 0 and we write gen(r', 0, X) * i* The subgoals m £ gc(r", X) and m > gen(r', 6, X) are called the consumers of X § The assignments of die form X «—c, where c is a constant value (atomic or structured constant) indicates that X is assigned a value. The discussion for the assignments of the form X «- e can be easily extended to the case when e is a general expression. The expression e could contain new variables which were not in r'. Hence, newer gc-lists appear and compulation proceeds described. as 85 denoted by confr', 8, X). If c is a constant in body(rO, then gentr', 8, c) - 0 and con(i/ , 0, c) = 0 for all applicable states 0 in r'. In general, only some of the variables o f r ' will have their generators defined in a state 0. A simple method for updating the values of gen(r\ X) as the search for the successive subgoals of r ' is continued is as follows. 1. Initially, for each variable X and constant in body(O gen(r', X) = 0. 2. When a subgoal i of r ' succeeds, we let genCr', X) - i for each variable X, which is assigned a constant value by i. 3. If i is the gen(r', X), then this is not modified unless backtracking goes to a subgoal j £ i. Simpler notations like gen(X) or gen(r', X) for gen(r', 0, X) and con(X) or con(r', X) for con(r', 0, X) can be used when an application o f a rule and the state o f compu­ tation is understood. Example: Consider an application r ' of the rule r, shown in Figure 1, for an application of a goal g = (pO(X', Y'),{Y7y0}). r*: pO(X, y O ) p l ( y 0 , Z), p2(X), p3(Z), p4(X, yO, U), P5(Z, W), p6(V), P?(X, V), P8(y0), p9(X, U, V), P 10(y0, U), p i 1(X, Z). The gc-lists of f arc g c(r\ X) = gc(r, X) gc(r', Y) = [0], The gc-lists of other variables appearing only in body(r') remain the same as the gc-lists of the rule r, as in the earlier example. The generators of all the variables and constants in r ' are set to 0. 86 Consider the computation state 6 where the first eight subgoals in b o d y (0 have succeeded and the computation o f the subgoal p9(X, U, V) is not yet complete. More specifically, assume that the state 0 was reached as follows: 1. The subgoal pl(yO, Z) succeeded, without generating a value for Z. 2. p2(X) succeeded, with an output assignment X/xO, modifying gen(X) = 2. 3. p3(Z) has succeeded, generating Z /zl and modifying gen(Z) = 3. 4. p4(x0, yO, U) succeeded, generating U/uO and modifying gen(U) = 4. 5. p 5 (z l, W) succeeded, without assigning a value to W. 6. p6(V) succeeded, generating V/vO and modifying gen(V) *= 6 7. p7(x0, vO) succeeded, without any output assignments. 8. p8(y0) succeeded, without any output assignments. The search for the subgoal p9(x0, uO, vO) is assumed to be incomplete. Here, j = 9. The associated generators and consumers for r' in the state 0 are given by gen(X) = 2 con(X) = [4 ,7 .9 . 11] gen(yO) -0 con(y0) = gen(Z) * 3 con(Z) - [ 5 ,1 1 ] gen(U) =4 con(U) -1 9 , 10] gen(V) = 6 con(V) = [7. 10] gen(W) = undefined con(W) = undefined. 0 87 4.6. Backward Execution Based on Failure-binding When a subgoal f reports failure in state 6 during execution then backtracking is applied. A previous state, 8 ', in which a goal b is executed, is selected for backtrack­ ing. Any subgoal £ (f-1) may be selected for backtracking. Forward execution is started in the state b and is executed. The intelligent backtracking schemes described in chapter 3 are based on identi­ fying the most recently generated binding that could cure the failure of a goal g, when g fails without any solution. However, a better backtrack point can be selected if the failure-bindings of literal f that failed in the state 8, are known. It is shown that the earliest o f the generators o f the failure-bindings can be selected as the backtrack literal/ This is based on the observation that every failure-binding of f has to be rectified before f can succeed. t The selection of backtrack literal was developed in conjunction with Dr. Kundu. 133. 34] 88 Example Consider a goal g = ((q(X, Y, Z, d l), {X/al, Y /bl, Z/c3)) that fails with the failuie-bindings X /al and Y/bl for q(X, Y, Z, d l). Also assume that gen(X) = 3, gen(Y) * 1 and gen(Z) - 4. Dependency directed backtracking will select the latest of the generators whose solutions were applied to g. Hence the backtrack literal selected would be 4. However, since both X /al and Y /bl have to be rectified to solve g we have to redo literals 3 and 1. Hence, the backtrack literal selection that is based on failurebindings would select 1 as the backtrack literal. This literal is the closer to the root of the goal-tree than those selected by other methods. B ackw ard Execution Algorithm If the argument tuple of a goal g * (p \ a ) is subsumed by any tuple in FBT(p), then g will fail because a failure-binding is applied to p ' to obtain g. The tuples that subsume g give failure-bindings of p'. This is because every tuple in FBT corresponds to one failure-binding of the predicate. Algorithm B 1 gives the Backward Execution algorithm based on failure-bindings. Example Consider the goal g = (q(X, Y, Z, d l), (X /al, Y /a l}). This gives the argument tuple of g as q (al, b l, Z, d l). Let the tuples si = q (al, S, T, #), s2 = q(X, b l, Z, W) in FBT(q) subsume p (al, b l, Z, d l). The tuple si represents X/al as a failure-binding of p and the tuple s2 represents Y/a2 as a failure-binding of p. Hence, X /al and Y/a2 are identified as the failure-bindings for q(X, Y, Z, dl). 89 Let g = (p \ a ) be the cunent goal that failed. If (g is subsumed by FBT(p)) then identify the failure bindings o f p' from FBT(p). else f* g is not subsumed by FBT(p) */ Identify failure-bindings for p ' from the alternatives of p Update FBT(p) for every failure-binding in p" If (there are no failure-bindings in p H) then Backtrack literal is selected according to Kumar else f* there are failure-bindings of p” */ if (c e Cp is a failure-binding for pO then backtrack literal = 0 else backtrack literal * min{gen(X) | X/v is failure-binding for p'J Backtrack Update bit-vector if backtrack literal « 0 (See section 5.7) Continue Forward Execution. Algorithm B l: Backward Execution Algorithm Based on Fallure-Bindings. 90 4.7. Bit-vector Implementation to Identify Failure Bindings The following discussion for identifying the failure-bindings is limited to Prolog program with only two modes for the arguments o f the predicates, the Ground state and the Free state. In essence, it is limited to programs without structured terms, though structured constants arc allowed. Structured terms lead to nested structures, and the unification process and identification o f cause of failure becomes dependent on this process. Failure-binding can be identified in a fairly straight forward manner as Prolog backtracks from a failure o f a subgoal to its parent (** the head of the rule which gave rise to the subgoal), by simply translating die failure-binding (if any) o f the subgoals in the rule as causes of failure for the goal using the unification substitution mapping in the reverse direction, and by combining the latter with the current tentative failurebindings at the parent The failure-bindings o f all the predicates can be identified by analyzing the pro­ gram. This is not always necessary. The objective is to prune computation during execution. In other words, the objective is to explore the search space efficiently while being relevant to the query. Hence, it would be ideal to identify the failurebindings, if any, during the computation, without incurring excessive runtime over­ head. An important observation to be kept in mind is that a goal fails only after an attempt to explore the entire search space of the predicate of which the goal is an instance. For every goal executed, the failure-bindings can be identified by identifying the causes o f failure by each of the alternatives from Facts 1, 2, 3, 4 and 5. (see section 4.2) Consider a goal g = (p't a ). The failure-bindings for p ' are identified as follows. 1. A bit-vector is maintained with g. The length of this bit-vector is | Cp- u a |, i.e., there is a bit for every constant in p ' and every binding in a . 2. Every bit in this bit-vector is initialized to ’ 1*. Thus each member o f C u a is a potential failure-bindings for p'. 3. The causes o f failure for p ' by every alternative of p are identified. The suggestion o f failure-bindings for p ' is maintained incrementally, i.e., the common causes of failure for p ' by all the alternatives that have been tried so far are suggested as potential failure-bindings for p', when the alternative m is tried. For each alternative, the bit corresponding to a binding X/v (c) in the bit- vector with g is ANDed with ’ 1’ if X /v (c) is a cause of failure for p ' due to the alternative. Otherwise, the bit is ANDed with a ’0*. 4. The common causes of failure for p ' after exhaustion of all the alternatives of p are identified as the failure-bindings for p'. The final bit-vector with g, after exhausting all the alternatives of p, is used to identify the failure-bindings for p \ if any. There is a one-to-one correspon­ dence between every bit in the bit-vector of g and the elements ofC^ u a Every bit which is ’ 1’ in the final bit-vector with p" gives the corresponding element in C u a a s a failure-binding in p". This is obtained from the bits which are ’1* in the bit-vector after all the alternatives are exhausted. The unification algorithm, which is essentially a pattern matching algorithm in Prolog, quits after the first mismatch. This pattern matching algorithm is modified to identify all the mismatches over the whole argument tuple of the goal g. Each mismatch then gives one cause of failure of g. It is to be noted that the extension of the unification algorithm to scan the whole argument tuple of the goal does not hurt the complexity of the unification process, but 92 can potentially perform more than the standard unification algorithm. In the bargain, more causes o f failures of p ' arc identified. Exam ple Consider the bit-vector modification with unification with facts. g = t(al, b l, c l). facts causes of failure bit-vector before unification t(a2, b l, c2). a l; c l [1 ,1 ,1 ] [1 ,0 ,1 ] t(a2, b2, c4). a l; b l; c l [1 ,0 ,1 ] [1 ,0 ,1 ] t(a2, b3. c l). a l; bl [1 ,0 ,1 ] [1 ,0 ,0 ] Figure 13. Unification with facts and Bit-vector manipulation Figure 13 illustrates the identification of the causes of failure of g obtained by unification and the refinement o f the bit-vector with g. During backtracking from a subgoal j in a rule, r, if the selected backtrack literal is 0, then the failure-bindings of j together with the unification mapping applied to the subgoal 0, head(r), in the reverse direction is used to identify the causes of failure of the goal by the rule. Example: Consider the goal g - (p(X, Y, Z), {X/[al, a2], Y /[bl, b2], ZJ[c l, c2]}) and the rules p(X, Y, Z ) p i IOC). pl2(Y ), pl3(Z). P([P. S], [Q, T |, rR, U]) p(M, N, O) p21(P, S), P22(Q, T), p23(R, U), p24(S, T, U). p31(M, N), p32(N, O), p33(0, M). The causes of failure of g by the rules and the corresponding modification to the bitvector with g are shown in Figure 14. bit-vector failure-binding before rule execution subgoals in rule [1 .1 . 1J —X /[al, a2] f o rp ll(X ) [1 ,0 ,0 ] S/al for p24(S, T, U) [1 ,0 , 0] M /[al, a2] for p33(OpM) Figure 14. Bit-vector manipulation with application of rules Example Consider the goal (query(X. Y), IX /al, Y /b l)) and the following program. The identification of the failure-bindings o f query(X, Y) by the facts and rules of the pro­ gram is shown in Figure 15. q l(a l). q2(b2). q2(b3). q3(al, c l). q3(a2, c l). q 4 (cl, b2). query(al, b2). query(X, Y) ql(X ),q2(Y ), query(X, Y ) q 3 ( X . Z), q4(Z. Y). 94 initial tut vector resultant bit vector applicable fact or rule auerWaT UV 11.1] query(X, Y ) q l ( x ) , q2(Y). to .il 1 o rn ql(al). [0] ID all facts and rules indicate [1] dl failure due lo to Y/bl. (Intelligent backtracking takes so coal beinc tried.) query (a 1, bl). query(X, Y):- q3(A, Z), q4(Z, V). 10.1] [0,1] [0,0] q3(al,cl). q3(al, Z). [1.0] q4<cl, bl). all alternatives fail ro, ij [1.1] for q4 indicating Y/bl as the the cause of failure. (Intelligent backtracking takes us the coal beinc tried) [0, 1] auery(al. bl). no more alternatives [0.1] Figure IS. Identification of Failure-binding in the presence of facts and rules. coal queryfal, bl). query(al. bl). ql(*l) q2(bl). In Figure IS computation starts with a search for a solution of to the goal query(al, bl) with the initialized bit-veccor [1, 1]. The first fact indicates that Y/bl is a cause of failure for query(al. bl), modifying the bit-vector [0,1]. On application of the next rule q l(a l) succeeds and q2(bl) foils. The failure of q2(bl) identifies Y/bl as a failure-binding far q2(Y). This eliminates all computation within the first rule appli­ cable to the query, Le., ql(X) is not tried any more, and backtracking goes to the ini­ tial goal, the query<al, bl). using the gc-list of Y. The bit-vector at the que^rtal, bl) is modified to [0,1). The next applicable rule translates itself into q3(al, Z) and q4(Z, bl). q3(al. Z) aucceeds with a banding Z/cl. q4<cl, bl) fails, identifying Y/bl, during unification a> the rale-head, as a failure-binding for q4(Z, Y). This suggests Y/bl as a cause of failure for qneryfal, b l) by this rule. The bit-vector of query(al, bl) is modified [0,1]. There are no more alternatives for query(al, bl), so the final bit-vector {0,1), which indicates Y/bl as a failure-binding for queryOX, Y). 95 4.8. Incompleteness o f the Identification of Fallure-Blndlngs An interesting point to be noted here is that if we focus our attention only on the part o f the goal-tree for the goal g which is visited by Prolog, then we may miss iden­ tifying some failure bindings. The identification o f failure-bindings by Prolog, using the bit-vector implementation, is not complete, i.e., every failure-binding o f a goal is not identified when the goal fails. The reasons for the incompleteness are two fold. They are 1. Left to right control of execution o f subgoals in a rule. This is due to incomplete gathering of information about the causes o f failure for the goal by the applicable rules for the goal. The failure o f a subgoal may invalidate the application o f a rule. Subsequent subgoals are not tried. The subse­ quent subgoals may indicate additional causes of failure for the goal. 2. Even with an extended unification algorithm, some failure-bindings can be missed by the bit-vector implementation algorithm. This happens if the unification fails and does not identify any cause o f failure. This is illustrated in Figure 16.* The following is true using the Prolog control structure. Every alternative can indicate many bindings as causes of failure by the alternative. As a rule body is exe­ cuted left-to-right, all the failure-bindings o f all the failing subgoals in the rule may not identified. The first subgoal that fails and leads to backtracking to the parent, i.e., head o f the rule, leads to preventing further execution of the body of the role. This results in incomplete information about the causes of failure by the role, because the failure-bindings o f the subgoals that are not executed may identify causes of failure of t The failure of unification without identifying a cause of failure was singularly pointed out by Kundu. [33] 96 the goal by the alternative. Since, no assumption can be made about the causes of failure of the goal by the alternative, only the identified causes o f failure are used to identify failure-bindings. What this means is that if we compute the failure-bindings only cm the basis of the searches performed by Prolog, then certain failure-bindings may be missed, though no erroneous failure-bindings will be reported. This will partially reduce the effectiveness o f the new backtracking method, in that it will be reduced more often than necessary to ordinary intelligent backtracking. Bits in the bit-vector are ANDed with ’1* only if the corresponding binding, or constant, is a cause of failure. Otherwise they are ANDed with 'O’. The incomplete information by an application of a rule could result in the improper ANDing of ’O' to some o f the potential causes of failure. This could result in not identifying possible failure-bindings, as shown in Figure 16. Example In Figure 11 we cannot identify Y/bl as the failure-binding for r22(Z, Y) if the fact r21(al, c l) is removed. The first fact for r identifies Y /bl as the cause of failure for r(X, Y). The first rule for r identifies Y /bl as a cause of failure of r ”. The left-toright processing of subgoals in a rule-body of the second rule by Prolog causes r21(X, Z) to fail, reporting X /al to be the failure-binding for r21(X, Z), which in turn translates to X /al a cause of failure for rfX, Y). This is not supported by the first fact or the first rule for r. The goal r22(Z, Y) is never tried, and hence Y /bl which is a failure binding for r22(Z, Y) is never identified, to identify Y /bl as a a cause of failure for r(X, Y). The second rule does not support Y /bl as a cause of failure of r". One then erroneously concludes that r(X, Y, Z) does not have a failure-binding. 97 Example Consider the goal (query(X, Y), (X/a2, Y /bl}) and the program in Figure 15. Figure 16 shows the incompleteness of the identification of failure-bindings. applicable fact or rule initial bit vector resultant bit vector queryf u , bl). [1. 11 querycx, Y) ql(X), q2(Y). U.O] n . ij X/a2 is failure-binding for ql(X) [1] i ll backtrack to query(a2. b l) query(a2. bl). 10. OJ query(X, Y ):- q3(X, Z), q4(Z, Y). [I* 0] q3(a2, Z). q3(al,cl). [0.0] [1.0] q4(cl, bl). Y/bl is failure-binding for q4(Z, Y) [0.1] [1.1] backtrack to auery(a2. bl) [0 . 1] query(a2, bl). [0.0] no more alternatives _& 0] Figure 16. Incompleteness of Identification of Failure-bindings by rales. goal query(a2, bl). query(a2, bl). ql(a2). Figure 16 shows the bit-vector method to identify the failure-bindings of (queiyCX, Y), (X/a2, Y/bl J). Computation of the goal queiy(al. bl) proceeds as fol­ lows: 1. The first fact modifies the bit-vector to be (1.1] i 2. The first rale is applied, and ql(a2) is tried first ql(a2) fails and indicates X/a2 as a failure-binding far ql(X). The first rule application fails, the goal q2(bl) is not executed. The bit corresponding to Y/bl in the bit-vector with the query<a2, bl) is ANDed with *0', because Y/bl is not identified as a cause of failure by the first rale. The resulting bit-vector with the goal is [ 1, 0] (the bit corresponding to X/a2 is ANDed with '1'). 3. The next applicable rale translates itself into q3(a2. Z) and q4{Z, bl). q3(X, Z) succeeds generating the binding Z/cl. q4(cl, bl) fails and identifies Y/bl as a failure binding for q4(Z, Y). This modifies the bit-vector with the query(a2, bl) to [0. 0], ANDing the bit corresponding to Y/bl with *1* and the others with '0 ’s. 98 4. There are no more alternatives applicable to the query. The query(a2, b l) fails and no failure-binding for query(X, Y) is identified. According to Theorem 4.2 and Figure IS, Y /bl is a failure-binding for queryfX, Y). The information that Y /bl is a cause of failure of query(a2, b l) is not substan­ tiated by the first rule during the execution, because the subgoal q2(Y) was not exe­ cuted when the subgoal q l(X ) fails. Hence, the incompleteness prevails in the identification of failure-bindings. Exam ple The incompleteness of identification of failure-binding is also due to unification failure without identifying any cause of failure. Consider the goal (p(X, Y, Y), (X/a, Y/b}). Figure 17 shows the unification with the facts for p. tacts initial bit-vector hnai bit-vector p (al, b l, b2). U, 1J [1.1] p(a, b l, b2). [1.1] [0,1] p (al, b, b). [0,1] [0,0] Figure 17. Incompleteness o f identification of failure-binding by unification. Consider that the goal (p(X, Y, Y), (X/a, Y/b}) as defined only by the facts in Figure 17. The unification process and the subsequent bit-vector does not identify any failure-binding for p(X, Y, Y). It is easy to observe that the goal (p(X, Y, Y), (X, Y }, {}, (X /a)) fails and, as per the Definition 1, X/a is a failure-binding of p(X, Y, Y). The unification algorithm identifies mismatches as causes o f failure. In the above example, the failure in unification in the different facts are due to different bindings. The failure-binding in the goal (p(X, Y, Y), {X/a}) is due to the interaction o f X and Y in different facts. The unification algorithm is oblivious to such situations. 99 Exam ple The following example illustrates recursive intelligent backtracking based on failure-bindings across clauses. query(X, Y) q l(X . Y). q2(Yt Z). q3(Xt Z). ql(X , Y ) ..... q2(Y, Z ) .... q3(X, Y) q31 (X, Z), q32(Z, Y), q33(X. Y). q31(X, Y ) .... q32(X, Y ) .... q33(X, Y) q331(X, Z), q332(Y, Z). q333(X, Y). q331(X, Y ) : - .... q332(X, Y) .... q333(X, Y) q3331(X, Y). q3332(X, Y). Suppose, the goal (queryCX, Y), {X, Y}, {}, {X /al}) is tried. Also, assume that the literals, obtained after unification and substitution, q l, q2, q3, q31, q32, q33, q331, q332, q333, q3331, q3332 have succeeded and the literal q333 fails with X /al as a failure-binding. Also, assume that the literals q333, q33 and q3 have exhausted their alternatives. Then, gen(X) in the rules "q33(..) and ”query(..) ...." , ”q33(..) ..." , "q3(..> ....” ..." would be 0. Hence, backtracking is recursively applied from q333 to q33 to q3 to query, since q333, q33 and q3 have exhausted their alternatives. Applying the techniques used in WAM, it is easy to implement intelligent backtrack­ ing based on failure-bindings and can backtrack across clauses. Figure 18. shows the complete goal search tree explored by intelligent backtrack­ ing based on failure-bindings, for the example in Figure 1. Table m gives the trace of execution by intelligent backtracking based on failure-bindings for the example in Figure 1. 100 Y/b1 X/o x/q fb - X /al EZl <E> F lb - Z /c l | Z /cl X/a X/a 2 X /o 1 u/q F lb - Z /cl V/fl lb * fall urc-bln ding lb - V/fl Figure 18* Goal-tree by Intelligent Backtracking based on failure-bindings 101 goal (pl(Y , Z ) , {)) (p2CX), {)) <p3(Z), {Z/cl}) (p4(X, Y, U), {X/al, Y /bl)) (p2(X), {]) (p3(Z). {Z/cl}) (p4(X. Y, U), (X/h2t Y/bl)) (p5(Z, X.U.W ). (Z/cl, X/a2, U/dl)) (pl(Y.Z), ()) (p2(X), {}) (p3(Z), {Z/cl}) (p4(X, Y. U), {X/al, Y/bl}) (P2(X), {}) (p3(Z), {Z/cl}) (p4(X, Y, U), (X/a2,Y/bl)) (p5(Z, X.U .W ). (Z/cl.X/a2.U/dl}) (PKY.Z), ()) (p2(X). [}) (p3(Z), {Z/c2}) (p4(X, Y.U), (X/al, Y/b2)) (P2(X). ()) (p3(Z), (Z/c2)> (p4(X, Y.U), {X/a2,Y/b2}) (p5(Z, X. U. W). Z/c2. X/a2, U /dl}) (P6(V). {)) (p7(X, V), (X/a2, V/fl)) (p8(Y). {Y/b2}) (p9(X, U, V). {X/a2, U/d 1. v / n }) (P6(V),{)) (p7(X. V). (X/a2, V/f2)) (p8(Y). (Y/b2J) (p9(X, U. V), {X/a2. U/dl. V/C}) (plOCY.U), {Y/b2,U/dl}) (pll(X ,Z ), (X/a2,Z/c2)) t success/fail success success success fail success success success fail success success success fail success success success fail success success success fail success success success success success success success fail success success success success success success failure-binding binding Y/bl: Z/cl backtrack literal - - X/al - - - - - X/h2 - U/dl Y/bl; Z/cl X/al - X/al Z/cl pi - - p2 • - - - - - - X/al p2 - - X/a2 - - - U/dl - - Z/cl Pi - YA>2; Z/c2 X/al - X/a2 - U/dl W/el V/fl - - - - X/al (t) P2 - - - - - - - • - - - - - - - - - V/T2 V/fl p6 - - - - - - - - - - - - “ Table Ql: Trace of Execution by Intelligent Backtracking baaed on failure-bindings Identified from FBT(p4) search. 102 T heorem 4.3.: H ie computation of a failure-binding by the bit-vector implemen­ tation method is sound. Proof. On failure o f a goal by an alternative, a bit in its bit-vector is ANDed with a ’ 1*, if the binding, or constant, corresponding to the bit is identified as a cause o f failure by the alternative. The alternative will not satisfy any goal with this cause of failure in the argument of the goal. Thus, a bit in the bit-vector is *1 ’ if and only if the binding corresponding to the bit has been identified as a cause of failure by every alternative that has been tried so far. Consequently, if a bit is ’ 1’ after exhausting each of the alternatives then the binding corresponding to the bit has been a cause o f failure by all alternatives, and, hence, is a failure-binding. A binding or a constant is identified as a failure-binding, iff the binding or the con­ stant is identified as a cause of failure by each alternative. If a binding, or constant, is not identified as a cause of failure by an alterna­ tive, then the bit corresponding to the binding (constant) is ANDed with a ’O'. Consequently, if a bit is ’0 ’ after exhausting all the alternatives, then the binding corresponding to the bit is not a cause of failure for each of the alternatives, and, hence, is not identified as a failure-binding for the goal. Due to the fact that ’ 1’ AND *0’ « *0’ once a bit is ANDed with a ’O’, it remains *0’. Thus, the binding corresponding to this bit is not identified as a failure-binding. Hence, the identification of failure-binding by the bit-vector implementation is sound. 103 4.9. Soundness and Completeness o f c In this section we prove that the search based on failure-bindings, is sound, complete and that it preserves the order o f the solutions obtained by Prolog. A method is sound if every answer that is derived by a method is a valid (correct) one. A method is complete if the method derives every solution. No solution, valid or invalid, should go underived. The basic execution mechanism is the same as in Prolog, Intelligent backtracking is a special case o f backtracking based on failure-bindings of the current literal. T heorem 4.4.: The algorithm for selection of backtrack literal is optimal. Proof: If there are no failure-bindings for the failed literal, then common dependency-directed backtracking is applied, according to [17 - 27]. If there are failure-bindings for the failed literal then the earliest o f the generators of the failure-bindings is selected as the backtrack literal. Every failure-binding is a definite cause of failure for the literal, which needs to be rectified. If a literal which is not the earliest of the generators of the failure-bindings for the failed literal is selected as the backtrack literal then the computation would arrive, after backtracking and forward execution, at the failed literal with at least one of its unrectified failure-binding. Hence, this literal will fail again. This will occur until all the failure-bindings o f the failed literal are corrected, called late detec­ tion of failure. Hence, backtracking to any other literal which is not the earliest o f the generators of failure-bindings for a failed literal would not be of any consequence to the failed literal. Thus, the selection of the earliest o f the genera­ tors of the failure-bindings of the failed as the backtrack literal is most efficient and hence optimal. 104 T heorem 4 i . : <; is sound. Proof: A solution to a goal is reported if the goal unifies with a fact, in which case the goal is true, or if all the subgoals in a rule applicable to the goal are true, implying that the goal is true. No other solution o f a goal is reported. Hence <; is sound. T heorem 4.6.: ; is complete. Proof. The search defaults to ordinary dependency-directed backtracking when there are no failure-bindings of a goal. Intelligent backtracking is applied when there are failure-bindings for the current literal that failed. Backtracking to an intermediate literal, b, is equivalent to jumping to b in the goal-search-tree which generated a failure-binding. Resuming computation at b continues search in the next right subtree at b, discarding the subtree of b which uses a failure binding of the currently failed literal. This subtree does not contain any solution to the ini­ tial query. Hence, discarding further search in this subtree does not miss any solution. Since the identification of failure-bindings is sound, and since the selection of a backtrack literal based on failure-bindings is correct, no subtree which could possibly contain a solution is pruned. Thus no solution that could be derived by Prolog is missed. Hence, <; is complete, within the closed world assumption. T heorem 4.7.: The order of solution derived by <; is the same as those obtained by Prolog. Proof. The proof is trivial for naive backtracking, as in standard Prolog, and dependency-directed backtracking. The control mechanism is identical to that by Prolog and £ is sound and complete. Hence, <; preserves the order of the results. C hapters 5. Intelligent Forward Execution Based on Failure-Solutions 5.1. Introduction The notion o f a failure-solution of a goal is introduced in this chapter. A simple method to identify the failure-solutions of a goal is presented. A systematic method to associate the failure-solutions of a goal in a a failure solution table (FST) is illustrated. Intelligent forward execution is based on the failure-solutions of a goal. 'Hie savings in computation by intelligent forward execution is compared to the standard search by Prolog. The completeness and soundness properties o f the search method based on failure-solutions, is proved. It is also proved that <? preserves the order of solutions obtained by Prolog Exhaustive and thorough search of the goal-tree by Prolog has a shortcoming in that computations of the same successes and same failures can be repeated. One of the reason why standard, dependency-directed or intelligent backtracking may not be able to cure a failure is that the backtrack literal can have many repeated identical solutions which could result in repeated failures. Consider the execution of the body of a rule ...., p(X, Y) q(X, Y ) , T h e bindings generated by p(X, Y) must satisfy q(X, Y). Let us assume that a solution, A, of p(X, Y) does not satisfy q(X, Y). This also means that A fails to satisfy the goal that unified with the rule-head of the rule in which p(X, Y) and q(X, Y) appear, because the rule-application will not succeed with the solution A of p(X, Y). If A' is another solution of p(X, Y) and A' = A, or if A' is weaker than A (A subsumes A ')/ t The weakness property based on subsumption definition was developed in conjunction with Rundu, [33], Kundu also suggested maintaining a table of successes for each predicate p (similar to FBT(p)>. This can be used to avoid search success-tree of a subgoal if it had been executed be- 105 106 then the rule application will fail again. However, the computation encountered in an intelligent forward execution from p(X, Y) onwards with A' can be safely avoided. fore, perhaps in a diffeitnl rule, than the current rule. 107 5.2. Failure-Solutions Semantically, a goal g * (p't a ) is true (that is, satisfiable, or logically follows from the program) if and only if there is a clause instance I of o f a clause C, in the program, such that the head of I is identical to p" and all the goals in the body of 1 are true. By the procedural interpretation of a logic program, a goal g is true if and only if a) there is a fact F that unifies with p" or b) there is a rule H ;- B l, B 2 ,... Bn. such that p" unifies with H and B l, B 2 ,... , Bn are true. The subgoals in a rule are executed left-to-right. The bindings that are applica­ ble at a node in the goal-tree of g are the solutions of all the subgoals which are above it in the goal-tree of g. Prolog execution has two phases. 1) During forward execution, goals are unified with facts or rule-heads. The goal is true when it unifies with a fact. When the goal unifies with a rule head, the goal is replaced by the unified version of the rule-body. The goal is true when all the subgoals in this rule-body are true. The subgoals are executed left-to-righL Alternatives that are applicable to a goal are selected top-to-bottom from the textual description of the program. 2) When a goal fails, a backtrack literal is selected by the backward execution algorithm and execution at this literal starts again for additional solutions. Let g be the primary goal. Along the path to the solution of g many subgoals are tried. Let n = (q', P) be a subgoal in the current path to a solution to g. Let n be exe­ cuted in the state o. The successful computation of n gives a set of newer bindings, A, as its solution. The state of computation is modified from a to o '. A can possibly be empty; and n may fail in the state o, in which case A is necessarily empty. Note that the computation of n in the state o, can have other solutions, i.e., A '’s with A' = A or 108 A' * A. The computation o f n in the state a is denoted by The goal-tree of g is denoted A*. The subtree o f A* which is below the computation o f the subgoal ^ is denoted A*^ Definition 1: Hie solution „nAis a failure-solution of n for g if there is no solu­ tion for g in the subtree Aj^. Exam ple Refer to In Figure 1 there is no solution for pO(X, Y) in the subtree under pl(Y , Z) with the solution (Y /bl; Z /c l). Hence, {Y/bl, Z /c l} is a failure solution of pl(Y , Z). Forward execution will fail to find any solution o f g if a new solution, A', of subgoal n is identical or weaker than a previously detected failure-solution. A, of n for g. It is then proper to skip the redundant search represented by the search space a^ . A different solution of n is required for solving g. Exam ple In Figure 1, on backtracking to pl(Y , Z) a new solution {Y/bl, Z /c l} is obtained. This solution is identical to an earlier solution which failed to produce a solution for pO(X, Y). Obviously, this solution will fail during forward execution, as can be observed from the goal-search tree that has been explored earlier. 109 S 3 . F ailure Solution T able Definition 2 : A Failure Solution Table (FST) o f q" - (q', a ) which is executed in the state o and which is denoted FST(q”, a ), is a table containing the failuresolutions o f q" in the state o. Every tuple in the FST(q", a ) is the set of argu­ ment tuples of the goal (q", a vj A), where A is a failure-solution of q" in the state o. The operations that are required to maintain the FST(q", o ) are: 1. create(FST(q", o » - creates an empty table 2. flnd(FST(q", a ), A) - finds if A is identical or subsumed by a tuple in FST(q", o) 3. add(FST(q", o), A) - adds the argument tuple (q', a u A) to FST(q", a ) 4. destroy(FST(q", <y)) - deletes FST(q", o). An FST is associated with every node in the current path in the goal-tree of g, the primary goal. As newer subgoals are invoked, their FST’s are created. FST 's are ini­ tialized empty at the first call to a subgoal. When a subgoal exhausts its solutions or backtracking takes to a node above the subgoal in the goal-search-tree, the FST of the subgoal is destroyed. When a subgoal is selected as the backtrack literal by the back­ tracking algorithm .then the subgoal may a d d a tuple to its FST. if the latest solution o f the subgoal is a failure-solution. When a solution A to a subgoal q*' is obtained, the FST(q”, o) is searched to find, if the tuple (q', a u A) is subsumed by the existing tuples in FST(q", a ). The entries in FST(q", o ) are not applicable for q" executed in another state & # o. Therefore, on backtracking to the left of q ” the FST(q", a ) is made void (destroyed). 110 5.4. Intelligent Forward Execution Baaed on Fallure-Solution FST(q", o) is used in intelligent forward execution from q". When q" succeeds with a solution A, then find(FST(q", <j), A) is done to find if A is a previously identified failure-solution. If A is identical or weaker than any tuple in FST(q", o), then forward execution from q" is aborted and a new solution for q” is requested. Oth­ erwise, forward execution continues as usual. If the argument tuple of the goal (q', a u A), is subsumed by any existing tuple in FST(q", a ) then forward execution from q” is aborted and q" is further executed to find more solutions of q". A flag is maintained with every goal that is active. This flag is initialized to False when the goal is first invoked. Algorithm A2 gives the for­ ward execution algorithm based on failure-solutions. lil Let q" - (q', a ) be the current goal, executed in state cr. Phase 1 FST(q", o) = 0 ; flag(q". o ) * false; Phase 2: solved = exec(q"); /* exec is a function to execute a goal */ if (solved = tru e) then found = find(FST(q", o), A); /* A is the new solution of q" */ if (found = true) then Apply Algorithm A2 at Phase 2 to q". Else next-goal = fetches(goaMist) f* fetches a goal from goal-list */ If (next-goal = 0 ) f* goal-list is empty */ then report success flag(q", a) * true; Apply Algorithm A2 at Phase 2 to q". else Apply Algorithm B2 at Phase 1 to next-goal. else Apply Algorithm B2 toq". Algorithm A2: Forward Execution Algorithm based on Failure-Solutions. 112 5 i . B ackw ard Execution Baaed on Failure-Solutlon On backtracking to q" from r", the flag with r" is returned to q". The value of the flag returned identifies the failure-solution of the q". If no solution for the primary goal g is found in the interim of forward execution from q" and backtracking to q", then an addition corresponding to A is done to FST(q”, o). H ie absence or presence o f a solution of g with the present solution of q", A, is determined by the flag returned by the backtracking algorithm. If the flag returned to q” is True, then the flag(q", o ) is set to true. If the flag returned to q" is False then A is a failure solution of q" and the tuple corresponding to q" is added to FST(q", a). On backtracking from q", to b"» the flag(q", c ) is returned, to b". Algorithm B2 gives the backward execution algorithm based on Failure Solutions. Let q" be the current goal that failed. Let b” - (b \ o ') be the selected backtrack literal. if (flag(q", a ) = False) then FST(b”, o ') - add(FST(b", o '), A') /* A' is the previous soln. of bH*/ else flag(bH, o ') =■T rue; Backtrack to b”; Apply Algorithm A2 at Phase 2 to b". A lgorithm B2: B ackw ard Execution A lgorithm based on Failure-Solutions Data structures optimal for searching and insertion are ideal for maintaining FST’s. Data structures such as AVL-trees or B-trees are quite efficient for add and find operations. 113 The go&l-tree for the execution of the example of Figure 1 by intelligent forward execution is shown in Figure 19. The trace o f execution based on use o f FST is given in Table IV. 1 14 failure-solution Y/bl. Z/cl Ibl.rll V/b2, Z/c2 W /r fl Search pruned by u se of FST Success!! Figure 19. Goal-search tree explored by Intelligent Forward Execution 115 goal (pl(Y, 2). {}) tp2(X), {)) <p3(Z), {Z/cl}) (p4(X, Y ,U ).{X /slt Y /bl]) (p3(Z), (Z/cl)) (P2(X).{J) (p3(Z), (Z/cl)) (p4(X, Y,U), {Xfr2,Y/bl}) (p5(z, x . u . w ). tsyci. x a 2, u / a i }) <p4(X,Y,U), {X/a2,Y/bl}) (p3(Z), (Z/cl)) (P2(X), ()) <pl(Y,Z). ()) <pl(Y,Z), (}) <p2(X), 0 ) <p3(Z), (Z/c2J) (p4(X, Y,U), {X/al.Y/b2}) (p3(Z), (Z/c2)) (p2(X), ()) (p3(Z). (Z/c2|) (p4(X, Y, U), (X/a2,Y/b2)> (p5(Z. X, U. W). (Z/c2, X/a2, U /dl)) <p6(V). ()) (p7(X, V), (X/a2, V /fl)) <p8(Y). (Y/b2)) (p9(X, U, V), {X/b2, U/dl, VA1}) (p8(Y), (Y/b2J) (p?(X, V), (X/a2, V /fl)) < P6(V ). { )) (p7(X.V), (X/a2, V/f2)) <p8(Y). (Y/b2}> (p9(X, U, V), {X/i2.U/dl.V/f2}) (plOCY.U).(Y/b2.U/dl)) (pllfX .Z ), (X/a2, Z/c2)> success/fail success fail fail success success success fail faU fail fail f U f f f jd success success success fail fail success s u c c e ss fail success success success fail fail fail success success success success success success binding Y/bl; Z/cl Xyfcl - X/a2 - e - - U/dl - - - * - Y/bl; Z/cl Y/b2; Z/c2 X /il - X/a2 - W/el V/fl - V/12 * FST 77 - yes - backtrack literal - p3 p2 - P* p3 - Pi - p3 p2 - p3 - p8 P? p6 - ; * Table IV: Trace of Execution by Intelligent Forward Execution “ 116 5.6. Soundness and Completeness of It is proved that the search based on failurr-solutions, shown that is sound. It is also preserves the order o f solutions obtained by Prolog T heorem 5.1.: is sound. Proof. A solution to a goal g is reported if g unifies with a fact o r if all the subgoals in a rule applicable to g is true. Hence. Theorem 5.2.: is sound. is complete. P ro of If a solution A of a subgoal, n, executed in state a , is subsumed by a in FST(n. o). then forward execution from n is avoided. This indicates that A is identical to or weaker than a previously determined failure-solution of n. It can then safely be said that the subtree A*,, does not have a solution for g. Hence, pruning the search of subtree A^ does not mis any solution. The search o f a sub­ tree of the goal-tice g is pruned, by aborting forward execution, if and only if the subtree does not have a solution for g. This ensures the completeness of search, bye' T heorem 5.3.: <? preserves the order of results as obtained by Prolog. Proof. No solution is missed and every solution obtained by Prolog is obtained. The control is the same as in Prolog, i.e., left-to-right within a rule and top-tobottom selection of alternatives. Hence, <;' preserves the order of the result. T heorem S.4.: No two states in the goal-tree by s ' of a goal g which fails are identical. Proof: A state in a goal-tree corresponds to the path in the goal-search tree. Thus, every node in a goal-search tree corresponds to a state. Consider a goal g executed in the state a. Let A be a solution of g. Also assume that A is a failure-solution of g. If another solution of g, A' = A, is obtained, then forward 117 execution from g is aborted. This is done for all failure-solutions of g. This means that computation from g onwards does not encounter two identical states which lead to failure. If g does not have any solution then this is applicable to the whole goal-tree of g. As a corollary to Theorem 5.4. it can be stated that "there are no two identical paths in the goal-tree by of a goal g which fail". 118 5.7. Difficulty in Implementation of c* It should be noted that association of FST(q", o) with q" is not possible on a linear stack of goals - because of the stacking of records in the chronological order of execution. A goal can be solved by a rule whose subgoals may be solved by different rule applications and so on. This leads to the record q" being buried deep in the local-stack. Due to the simplicity of implementation o f stack, the address of this record is not know. Hence, the search space and solution o f a goal cannot be associ­ ated with it. A new data structure which is introduced in chapter 7 is needed to effect intelligent forward execution. Chapter 6 6. Intelligent Forward Jumping 6.1. Introduction The notion of forward jumping for sequential execution of Prolog is addressed and a scheme to avoid computation of subgoals independent of the corrective actions taken by backtracking is presented/ These independent subgoals fall in the range of the failed subgoal, f, and the backtrack subgoal, b, in a rule. The goals are identified from the subgoal dependencies in a rule together with the generators and consumers of the variables in the rule. The resulting search based on forward jumping, is related to the goal-tree o f Prolog, and the savings in computation is illustrated. It is proved that satisfies the completeness and soundness properties of Prolog and that it preserves the order of solutions obtained by Prolog. The notion of intelligent forward jumping is based on the observation that when backtracking occurs, say, from the subgoal position f to the subgoal position 1 £ b < f within the body o f a rule, then only some of the subgoals in the range b £ i £ f (in short, [b..f]) need to be re-evaluated. The inequalities S between the literals indicate the order of appearance of the literals in a rule. The set of subgoals that have to be re-evaluated to ensure completeness of search is denoted by redo(b, f). The rea­ son that we are able to avoid re-evaluation of the other subgoals in the range fb .f] is that the re-execution of these subgoals would proceed exactly in the same way as before, through the same series of successes, failures, and backtrackings and generat­ ing the same intermediate variable bindings, if any, on the way [33, 34], t A separate representation scheme and method for forward jumping is being independently developed by Dr. Kundu. [33 - 34] 119 120 The forward jumping scheme avoids computation of successful subgoals which are independent of the corrective action taken to cure the failure o f the currently failed subgoal. The list of subgoals that can potentially affect the cause of failure of the most recently failed subgoal is identified from the gc-lists o f the variables in the rule. After backtracking, only those subgoals that are in the redo-list are recomputed, thus effecting forward jumping over subgoals that are not in this list. Consider the rule r" : p(X, Y) i(X), s(Y), t(X, Z), u(Z, M), v(Y, T). Execution of p(X, Y) may proceed in the following manner * 1. r(X) succeeds, generating the binding X/a 2. s(Y) succeeds, generating the binding Y/bl 3. t(a, Z) succeeds, generating the binding Z/c 4. u(c, M) succeeds, generating the binding M/d 5. v (b l,T ) fails. Backtracking would take to s(Y), for a new binding for Y. In the process the search space of t(a, Z) and u(c, M) is deleted. After s(Y) succeeds, with a new bind­ ing for Y, the goals t(a, Y) and u(c, M) start from their first alternative Let the recom­ putation continue as follow: 6. s(Y) succeeds, generating the binding Y/bl 7. t(a, Z) succeeds, generating the binding Z/c 8. u(c, M) succeeds, generating the binding M/d Now, v(b2, T) is tried for solutions. Note that when s(Y) succeeds with a new binding Y/b2, t(a, Z) succeeds with the binding Z/c, and u(c, M), succeeds with the binding M/d. These recomputations of successful subgoals encountered in the previ­ ous computations need not be repeated. The execution of the goals t(X. Z) and ufZ. * These observations were developed Jointly with Kundu, [33J. 121 M) are independent of the new solution of s(Y). Forward jumping is a scheme to avoid such unnecessary successful recomputation. 122 6.2. Dependencies among subgoals The gc-list o f the variables which appear on the RHS of a rule is the list of the literals which appear on the RHS of a rule and whose declaration has the variable X, as its argument or part of its argum ent Note that since the declaration o f the literal differs throughout the program, the gc-lists are pertinent only to the rule; it is valid as long as the rule is not modified. (Refer Chapter 4) Consider a rule " q u e r y ( ...) 1,2, 3.......n." where the literals are replaced by their corresponding indices. Consider two literals i and j in the rule. Definition 6.1.: A literals b is said to be exclusive of the literal f, and vice versa, if b and f do not share any variables. In other words, there is no gc-list which contains both b and f. Definition 62.: A literal b is said to be related to the literal f, and vice versa, if b is not exclusive of f. Note that every literal is related to itself. Definition 6J.: A literal f is dependent on a literal b, f £ b, if it is related to i or if there exists a literal k, b £ k £ f, which is dependent on b. Every literal is depen­ dent on itself. Definition 6.4.: In a range of literals [b..f], a literal p is parallel to a literal b, b < m £ f, if p is not dependent on b and if there exists a literal k, p < k £ f, which is dependent on b. Definition 65.: In a range of literals [b..f| if a literal o > i is neither dependent on the literal b, nor is parallel to the literal b in the range [b..f], then the literal o is said to be orthogonal to the literal b in the range [b..f]. 123 When two goals are exclusive o f one another, they are semantically independent o f one another. W hen two goals are related to one another, they are semantically dependent on one another. If goal b appears before the goal f and if the goals b and f are related to one another, then the solution of b affects the solution o f f. If literal f is dependent on b, then the solution of f is directly or indirectly affected by the solution of b. If a literal p is parallel to literal b in the range [b..f|, then the state o f computa­ tion in which f is executed is affected by p as well as by b. If a literal o is orthogonal to b in the range [b..f], then it implies that the computation of b does not affect the computation of o and the computation of o does not affect the state in which f is exe­ cuted. 6.3. Redo-list Consider the situation when a rule r is executed and a subgoal f fails. Also, assume that the backtrack literal selected is b, which is executed in the state o. Definition 6.6.: The set redo(r, b, f, o) is the set of goals which are affected by the recomputation of b and whose solutions affect the state in which f is exe­ cuted. The use of the redo-list is inter-procedural (i.e., applicable within a rule). When the rule application is understood we represent redo(r, b, f, o ) by redo(b, f). The com­ putation of the redo-list for a range [b..f] is done to find the subgoals in this range which need to be re-executed for completeness of the search. Exam ple Refer to In Figure 1 consider the case when p4(al, b l, U) fails. The selected backtrack literal is p2(X). Thus, f = 4 and b = 2. The re-execution of p2(X) may gen­ erate a new binding for X. It is clear that no matter what the new binding of X may be, there is no need to re-evaluate p3(Z). 124 Wc denote by redo(b, f, o) the list of the subgoals i, b £ i £ f, whose reexecution after backtracking to b is necessary to assure that no potential solution to the rule head is missed. The computation of redo(b, f, o ) in / can be done using the gc-lists of the variables of f'. The redo-list, redo(b, f). can be recursively defined as* 1. b and f belong to redo(b, f). 2. If j e redo(b, 0 and j e con(r', X), then gc(r', X) <\ [b..f] belongs to redo(b, f, o). Basically, redo(b, 0 consists o f all subgoals in the range [b..f] whose re-execution can potentially affect the continuation of the computation from the subgoal b through the subgoal f. Example Consider the following rule and its gc-lists.1 r : pO(X, Y ) p l ( Y , Z), p2(X), p3(Z), p4(X, Y, U), p5(Z, W), p6(V), p7(X, V), p8(Y), p9(X, U. V), plO(Y, U), p i 1(X, Z). gc(X) « [2,4, 7 ,9 , 11] gc(U) = [4, 9, 10] gc(Y) - [ 1 . 4 , 8. 10] gc(V) - [6, 7,9] gc(Z) = [1, 3, 5, 11] gc(W) = [5] Figure 20 illustrates the possible values of redo(2, 9) and redo(2, 11) based on the various consumer lists. t The definition of rcdo(b, f) which dynamically changes with different stales was developed in conjunction with Kundu, [33 - 34]. 5 Kundu. [34], 125 Uurrent gc-lists in state o on backtracking to I con(o, X) « [2,4, 7 ,9 ,1 1 ], con(a, » [4 ,9 ,1 0 ] redocz, 9, a ) [2,4,6,7, If, 9 T con«j, Y) - [4 .8 .1 0 ], con(o, V) - [6 ,7 ,9 ] con«r, 2 ) * [3 ,5 ,1 1 ], con(a, W) - [5] con(o, X) = [2 ,4 ,7 ,9 , 11], con(a, U) « [4, 9, 10] [2,4,6,7,9] con(o, Y <—yO) = 0 , con(o, V) = [6, 7, 9] con (a, Z) = [3 ,5 ,1 1 ], con(a, W) = [5] con(C, X) = [2, 4, 7 ,9 ,1 1 ], con(flf, U) = [4, 9, 10] [2, 4, 6 ,7 , 8,9] con (a, Y) - [4, 8, 10], con (o, V) * [6 ,7 ,9 ] con(Z, Z <— zO) « 0 , con(o, W) = [5] con(o, X) = [2, 4, 7 ,9 , 11], con«J, U) = 14,9, 10] [2,4,6,7,9] con(o, Y «—yO) = 0 , con(o, V) * [6, 7, 9] con (a, Z «— zO) = 0 , con(o, W) = [5] Figure 20 (i). Possible values of redo(2,9) for different consumer lists. 126 Uurrent gc-Usts m state o on backtracking to 2 re d o (2 ,11, o) con(CT, X) * [ 2 ,4 ,7 ,9 ,1 1 ] , con(o, U) » [4 ,9 ,1 0 ] [2, 3 ,4 ,5 ,6 ,7 , 8 ,9 , 10, 11] con(o, Y) « [4 ,8 ,1 0 ], con(o, V) - [6 ,7 ,9 ] con(o, Z) » [3 ,5 ,1 1 ], con(o, W) » [5 ] con(a, X) = [2, 4, 7 ,9 , 11], con(o, U) « [4, 9, 10] [2, 3, 4 ,5 ,6 , 7, 9, 10, 11] con(a, Y <— yO) * 0 , con(a, V) ■ [6, 7, 9] con (a, Z) = [3 ,5 ,1 1 ], con(a, W) = [5] con(o, X) » [2,4, 7 ,9 , 11], con(o, U) ■ [4, 9, 10] [2, 4, 6, 7, 8, 9, 10, 11] con(o, Y) = (4, 8, 10], con(o, V) ■ [6 ,7 ,9 ] con(L, Z <— zO) = 0 , con(o, W) « [5] con(o, X) * [2, 4, 7 ,9 , 11], con(o, U) - [4 ,9 , 10] [2,4, 6, 7, 9, 10, 11] con(a, Y <— yO) = 0 , con(a, V) « [ 6 ,7 ,9 ] con(o, Z «- rO) * 0 , con(a, W) « [5] Figure 20 (ii) Possible values of redo(2, 11) for different consumer lists. Note that if a literal o is orthogonal to b and in the range [b..f], then o is orthogo­ nal to b for any range [b...fl], f l £ f, The orthogonality is to be recomputed for any other range. The states in which the dependent goals o f b are executed are directly affected by the execution of the goal b. The states in which the goals which are parallel to b are executed are not affected by the execution of b. The solutions of the goals dependent on b and the goals that are parallel to b are contributory to the state in which f is exe­ cuted. The states in which the goals that are orthogonal to b are executed are not affected by the execution o f b. The solutions of the goals that are orthogonal to b in the range [b..f] do not affect the state in which f is executed. 127 In the context o f sequential Prolog execution, f is the failed goal, b is the goal backtracked to, and dependent and parallel goals form the redo-list. The recomputa­ tion o f the orthogonal goals is redundant. The relationship between the subgoals in a rule is dynamic during execution. Consider an application / of a rule r. W hen substitution of the form X <— a is applied to head(r), the relationships among the subgoals in r which are based on the variable X are affected. This is because g c f/, X) * [0]. Also, consider a situation where the subgoals [l..j] have succeeded. Also assume that the subgoal i, 0 £ i 5 j, has generated a binding for a variable X. In this case, all members in gc(r', X) use the binding for X. by X. Hence, any subgoal g > i, g e g c(r\ X), is dependent on i. For a subgoal g \ i < g ' £ g and g ' € gc(r/, X), we can also say that the subgoal g is depen­ dent on g'. But this dependence relation is of no consequence, due to the single assignment property of logic programs. Dynamic dependence relations are used in finding redofb, 0Consider an execution state in which the goals [l..fl have succeeded. Also assume that a subgoal p, 1 £ p £ f, is orthogonal to a subgoal b in die range [b..f]- As execution proceeds, a subgoal f 1 > f, which is related to b, as well as p, may succeed. Now p is parallel to b in the range [b..fk], fk f l. Thus the relationship between two subgoals in a rule may dynamically change from being orthogonal to parallel to orthogonal, and so on. As described earlier, only the dynamic parallel and orthogo­ nal relationships, based on the dynamic dependence relationship are used in finding redo(b, f>The literals in the body of the rule are denoted by the corresponding indices. Algorithm R1 is the redo-list generation list algorithm, which uses the dynamic rela­ tionships among the subgoals in a rule. The dynamic relationships can be known from the generators and consumers of the variables in the rule. 128 Let f be the failed subgoal and b be the selected backtrack literal. redo-set« {b, f}; temp-set = (b, f J; var-set = {); temp-var-set = var-set; repeat repeat G = remove(temp-set); f* get an element from temp-set */ temp-var-set « (X | G e con(X)J until (temp-set) - 0 ) ; If ((temp-var-set - var-set) - 0 ) then break; var-set * var-set u temp-var-set; repeat X ■ remove(temp-var-set); If (b S gen(X) S f) then temp-set = temp-set u (con(var) n [b..fj); until (temp-var-set = 0 or temp-set = [b..f]); if ((temp-set - redo-set) *= 0 ) then break; redo-set = redo-set u temp-set; if (redo-set = [b..f]) then break; until; redo-list = order(remove-duplicates(redo-set)); Algorithm R l: An algorithm to generate dynamic redo(b, 0- 129 Algorithm R1 is finite and terminates, the termination conditions being i) 4 when the redo-list contains all the subgoals in the range [b..f], ii) 4 when there are no more new goals to be added to redo(b, f) iii) 4 when there are no more new variables that are affected by the re-execution o f b. 130 6.4. F o rw ard Ju m p in g The redo(b, f) is used for recomputation of intermediate subgoals during the forward-jump phase. Once this list is exhausted, the forward-execution algorithm, as described previously, is employed. After backtracking to b from f, the goals in rcdo(b, f) are re-executed. The goal b is executed for further solutions, and the rest of the goals in redofb, f) are executed from their first alternative. This is effected as fol­ lows: after selecting b and finding redofb, f), the search spaces of the goals in [b..f] redo(b, f) are saved. After the re-execution of b, the execution continues by executing the goals in redofb, f) and interleaving the search spaces, bringing back the saved search space, of the goals in [b..f] - redo(b, f) in the order of their appearance in the rule. Exam ple Consider red 0 (0 , 2, 11) of Figure 20. (ii). After backtracking to 2, computation continues as follows. compute/overlay Continue Computation of 2 Interleave the search space of 3 Compute 4 Interleave the search space of 5 Compute 6 Compute 7 Interleave the search space of 8 Compute 9 Compute 10 Compute 11 13J In the event of a failure o f a goal f € redo(b, f), b S f £ f, select a backtrack goal b'. The backtrack procedure takes us to b'. The net result of backtracking from f has resulted in backtracking to b'. Compute iedofb', f)- Discard the search space of the subgoals that belongs to redofb', f). Then continue forward execution at b'. Figure 21 shows the search tree based on from intelligent backtracking and for­ ward jumping. Table V shows the trace o f execution from intelligent backtracking and forward jumping. 132 fb = X / fb = X / a l fb = Z / c l | fb = X /a fb » Z /c J j Pruned Search epeee by Intelligent 1 b a c k track in g F fb = V/ f ] P ru n e d S earch apace by Forward Ju m p in g Success)' Figure 2 1 . Goal-search tree explored by Intelligent Backtracking and Forwaxd Jumpfag. 133 <pl(Y. Z>.()> (p2fX). (J) (pXZ), (Z*l)) (p4(X. Y.U). (U l.Y A D ) (p2(XU)> (p*(X. Y.UMX*2,YAl)> (p5(Z, X. U, W), {ZAl. X « , \m %)) (pl(Y .Z),(J) (pvz). tjycii) <p*z. X, U. W). {Z/cl. XA2. UM1)) <pl(Y, Z). U) <p*Z). (Zfc3)) (p5<Z, X, U. W), (Z/c2. XA2, IW1)) (P*™ . (J) 0 'o.txAiv/nj) (P^ . (YA2)) (p9(X.U, V). [X*2,UA».V/n)) 0*00,0) (p7(X, V). {XA2, V/!2)> (p9(X. U. V). {XA2. UMl. V/OJ) (plO(Y.UX, (YA2.U/J1)) (pllfX.Z). (XA2.ZA3)) t YAl;Z/cl X*> XA2 UM1 YA1; Z/cl YA2.ZAJ XA1 Z/cl pl.p3.p31 Z/cl pl.p3.pS ) v /n p6. pY, pA) W/el v /n v /o Tbbte V: Tncs r f E i n r i n by bMUigca Bacfcncbiag aid f a w j ) m f b | Idm tiM bon FBT(p4) M«ch 134 6.5. Soundness and Com pleteness of C* H ie search based on forward jumping. will be proved to be sound and com­ plete. It is also shown that the order of solutions obtained by is the same as obtained by Prolog. T heorem 6.1.: <;" is sound. Proof. Solutions are obtained only if a goal unifies with a fact or all the subgoals in a rule applicable to the goal are true. Hence, every solution obtained by is sound. T heorem 6.2.: is complete. Proof. In the default case, where redo(bt f) —[b..f], the search is complete. The recomputation of the goals in the redo(bt f) (other than b) from their first alterna­ tive is necessary, because the solutions of these goals can potentially affect the state in which f is executed. As observed, the computation of the goals that are not in the redo-list are independent of the corrective actions taken to cure the failure of f. This ensures that no unique search path which would succeed, or fail, is missed. Hence, is complete. T heorem 6.3.: <; preserves the order of results obtained. Proof. H ie default case when redo(b, f) = [b..f], yields the same results as those obtained by Prolog. Otherwise, the solutions of the different subgoals are inter­ leaved during forward execution in the order o f their appearance in the rule. Since the selection of control is still the same as in Prolog, the order of solutions obtained by is unaffected. 135 6.6. Difficulty in Implementation o f c” The search space of a subgoal cannot be associated with a subgoal during execu­ tion due to the nature of the linear local stack. It is not possible to isolate and store the search space o f intermediate goals while backtracking and to interleave them during the forward jumping process. The next chapter on the Segmented Stack presents a data structure that facilitates association of search spaces with goals. This can help forward jumping during sequential execution. Chapter 7 7. Execution of Logic Programs on a Segmented Stack 7.1. Introduction A new data structure, called the segmented stack, for execution of logic pro­ grams is introduced. The segmented stack can be maintained as a right-threaded tree with a heap pointer. A detailed illustration o f the segmented stack environment is presented. It can be used as the data structure for the local-stack used by Prolog. The use o f a segmented stack as the data structure to maintain the local-stack enables asso­ ciation o f search spaces and solutions with goals. This in turn results in implementsJ tion o f ^ ^ and <;". Forward and backward execution algorithms are given. The space and time complexity analysis of the segmented stack is analyzed. Prolog programs are evaluated on a linear stack of activation records, called the local-stack or the environment-stack, together with the goal-list. The goal-list is a list of goals which remain to be solved in older to to solve the initial query. It attempts to unify with the goal, t, at the top of the local-stack with its alternatives. If t unifies with a fact, then t succeeds. If t unifies with a rule-head of a rule r, then the body(r) is inserted at the head of the goal-list. If the local-stack is empty or if the goal at the top o f the local-stack succeeds, then the goal at the head of the goal-list, h, is selected for solving. This modifies the goal-list in that h is removed from the goal-list. A record o f h is stacked on top of the local stack of activation records. The goal h is tried for unification with its first alternative. If h unifies with a fact, then h succeeds. If h unifies with a rule-head of the rule r, then the body(r) is inserted at the head of the goal-list. The local-stack is initialized empty. The local-stack grows with the invoca­ tion of goals by forward execution. It contains the activation records of all the goals that are active. The records on the local-stack constitute the current path in the goalsearch tree that is being tried to solve the initial query. The goal-list is initialized with 136 137 the query goal. It is empty on successful completion of the query. When the query goal succeeds, the local-stack contains the goals falling in the current path that is being tried for a solution. Thus, forward execution modifies the goal-list and the local-stack. A goal f fails when no more alternatives are left for unification. Backward exe­ cution is as follows: The goal f is inserted at the head of the goal-list. A backtrack literal is selected. Coals are popped off the local-stack, their alternatives reset, and inserted at the head of the goal-list -the unification substitution created by this goal is undone - till the backtrack literal is encountered at the top of the stack. All the subgoals in body(r), of the rule r which unified with a goal g, and which are in the goal-list are removed from the goal-list when the goal g is encountered at the top of the local-stack. The local-stack shrinks during backtracking. The goal-fist grows and shrinks during computation. Forward execution is resumed with the goal at the top of the local-stack. When the query goal fails, the goal-list contains the query goal and the local-stack is empty. Operations on the local-stack and the goal-list occur hand-in-hand in order to implement, and execute, exhaustive search for Prolog programs. A record on the local stack contains all necessary information to implement, correctly, backtracking and continuation of search. A goal is active as long as its activation record is present on the local-stack. 138 7,2. Inapplicability o f Linear Stack to Implement c' and c" A goal may be solved by way of unification with a fact or by a rule which succeeds. The rules that are applicable for a goal, in general, have more than one subgoal, and one or more of these subgoals may be solved by using the rules applicable to them. Hence, in general, the successful search path of one goal contains more than one record on the local-stack. The search paths of different subgoals are stacked on top of one another. While backtracking, the records are popped off the stack until the backtrack point is reached. The records o f the different subgoals in a rule are not readily accessible without a linear popping o f the records from the local-stack. Con­ tinuation of search of an intermediate subgoal going back to where die system left off, cannot be implemented on a linear stack. Also, the information on a linear stack is popped off during backtracking, the search space . Subsequently, these popped records are not retrievable. A solution to a goal is obtained only when the rule succeeds. The record of the goal which succeeds is embedded deep in the stack. The solution of a goal cannot be associated with the record of the goal. Hence, it is not possible to associate FST’s with a goal. Independent search spaces cannot be saved and interleaved in a straight forward fashion. Hence, <? and cannot be imple­ mented on a linear stack o f records as data the structure for the local-stack. 139 73. Segmented Stack A linear stack structure for the local-stack does not facilitate maintenance of FST’s with goals or for saving and interleaving search spaces for forwardjumping over subgoals. A data structure facilitating depth-first search, as well as breadth-first search, is required. A new data structure, the segmented-stack, for the local-stack is proposed in order to enable both depth-first search and breadth-first search during execution of Prolog programs. Depth-first search is employed when unification succeeds and during forward execution, and breadth-first search is employed during intelligent backward execution, intelli­ gent forward execution and forward jumping. Definition of a Segm ented Stack: A node in a segmented stack, SS, has three fields. These are 1) a rule-pointer, 2) a heap-pointer and 3) data. The rules defining a segmented stack are, 1) A segmented-stack, SS, of zero nodes is an empty segmented-stack. 2) A segmented stack, SS, with a single node, which is the root of SS, is a segmented-stack. 3) A node, which is the root, together with its rule-pointer, pointing to a list o f segmented-stacks, which form the body, is a segmented-stack. 140 A segmented-stack, SSg can be used as a local-stack for execution of a goal g as follows: 1. A node for g is created when g is executed. 2. If g unifies with a fact, then the rule-pointer in the node for g is null, the tree of SS( is empty and the heap-pointer in the node for g points to itself. 3. If g unifies with a rule r, then each subgoal, in body(r) is solved on a separate segmented-stack, SS,. All such segmented-stacks, SS„ 1 £ i £ n, where n is the number of subgoals in body(r) which has been solved, form the tree o f the segmented-stack rooted at g. The rule-pointer in the node for g points to the list (SS„ SS* .... SS.}. The heap-pointer points to the node pointed to by the heap-pointer of SS.. The list of segmented-stacks together with the root g is the segmented-stack SSr Thus the heap-pointer points to the last record formed on the segmented-stack. In the context o f Prolog execution, this corresponds to a goal unifying with head(r) o f a rule r. The subgoals in body(r) are solved over the segmented-stacks pointed to by the list, pointed to by the rule-pointer. A node is an activation record of a goal. The list implementation of the segmented-stacks for different subgoals in a rule enables operation on any of these subgoals. Hence, the search space of any of the subgoals in body(r) can be deleted. Also, the heap-pointer of the segmented stack o f a subgoal can be used to continue execution of the subgoal. Thus, a subgoal in a rule solved on a segmented-stack can be deleted or continued for further solutions without affecting the search space of other subgoals in the rule. The logical connectivity among the subgoals in a rule is maintained by the list of segmented-stacks over which the subgoals are solved. The logical connectivity between a goal and the body(r) of the rule r applied to solve the goal is maintained by the rule-pointer of the record o f the goal. 141 Example Consider the facts and rules in Figure 11 and a goal r(a l, bl). A node for r ( a lt b l) is created. The rule-pointer and heap-pointer are undefined. When r(a l, b l) unifies with the first rule of r the rule-pointer points to a list o f two segmented stack. r l l ( a l ) is executed on the first segmented stack and rl2 (b l) on the second, r l l ( a l ) unifies with a fact and so the corresponding segmented stack is a single node pointing to itself. The segmented-stack needs to hold all the information that would be held in the equivalent local-stack during the execution of logic programs. Since there is a record for every goal that is active, this information would be consistent with that of a linear stack implementation of the local-stack. A segmented-stack is active as long as its root is present. An active segmentedstack can be in either of the two states: Open or Closed. If the heap-pointer of an active segmented-stack, SS,, is null, then it is said to be Open. Otherwise it is said to be Closed. In the context of Prolog execution 1. An open segmented-stack with a single node corresponds to the segmented-stack for a goal whose unification is in progress. 2. A closed segmented-stack with a single node corresponds to a segmentedstack for a goal which has succeeded by unification with a fact. 3. An open segmented-stack with multiple nodes corresponds to a segmentedstack for a goal for which a rule application has not yet terminated. 4. A closed segmented-stack with multiple nodes corresponds to a segmentedstack for a goal which has succeeded by a rule application. 142 The operations on a segmented-stack are: m k seg Segmented-stacks are created by the mk_seg() procedure. This procedure opens a segmented-stack by creating a node for the goal to be executed on this segmented-stack. close_seg Segmented-stacks are closed by the close_segO procedure. This procedure closes a segmented-stack by recording the heap-pointer at the of the segmentedstack. get-top(arg) Segmented-stacks are accessed by the get-top(arg) procedure. This procedure goes to the top of the segmented-stack referred to by the argument via the heappointer of the segmented-stack, referred to by arg. m k_null(arg) A segmented-stack is deleted by the mk-null(arg) procedure. This procedure deletes the tree of the segmented-stack referred to by arg. It also undefines, makes null, the rule-pointer and the heap-pointer at the root of this segmentedstack.. A segmented-stack is active during the interim of the mk_segO which created it and the mk-null(arg) call referring to its parent. The above procedures are sufficient to create and maintain a segmented-stack. 7.4. Forward Execution on a Segmented Stack The two main data-structures other than the goal-list and the segmented-stack are the heap and trail. The heap maintains the address o f the choice-points [32] and the trail maintains the unification substitution informations. The goal-list contains the goals to be computed to solve the primary goal, and the segmented-stack contains the nodes for the goals that have been computed, partially or fully, constituting the path from root to the present node in the goal-seaich-tree. Algorithm A3 gives the Forward Execution Algorithm on a segmented stack. 1. A segmented-stack is created when a goal, G, is first tried for solution. 2. If G unifies with a fact, then the segmented-stack corresponding to this goal is closed using the address of the node of G itself for the heap-pointer of G. 3. If G unifies with a rule, then a list of segmented-stacks are created to solve each of the subgoals in the rule-body. When each of these segmentedstacks that solve these subgoals are closed, then the segmented-stack of G is closed by updating the heap-pointer of the segmented-stack o f G with the heap-pointer of the last segmented-stack which solved the last goal in the rule. Algorithm A3 is used to build the segmented-stack as the forward execution proceeds. If any o f the subgoals fail, then backward execution is applied. Phase I if (goal*list - 0 ) then report success Apply Algorithm B3 else t_goal = get(goal-list); f* get first element from goal-list */ if t_goal = Y then close_segO; /** record the pointer to the top of the stack **/ else mk_segO /** create a new segmented stack and record the pointer of its root **/ Phase II t__list - unify(t_goal) if (t_list = fail) then report failure Apply Algorithm B3 else cons(t_list* goaMist); Apply Algorithm A3 at Phase I Phase in t-goal = get-top(b); Apply Forward Execution at Phase I A lgorithm A3: F orw ard Execution A lgorithm on Segm ented-stack. 145 7.5. Backward Execution on a Segmented Stack Backward execution allows search for other alternate solutions. During back­ ward execution, many subgoals in a rule are to be redone. After the detection of the cause o f failure of a subgoal, and subsequent detection of the backtrack-literal and the redo-list, the segmented-stack is updated to perform backtracking and forward jum p­ ing. When the backward execution algorithm is invoked, a backtrack literal, b, is selected together with the redo-list. The search space on the segmented-stack of the goals in the redo-list are deleted, the tree of the corresponding segmentcd-stack is deleted, and the rule-pointer and heap-pointer set to null. Forward execution is resumed, at Phase Q, at b. If b fails, then backward execution is applied. If b succeeds, then the forward-jumping algorithm is applied. Algorithm B3 gives the backward execution algorithm for the segmented-stack. Let f be the failed literal, b = select(backtrack-literal) generate redo(b, f) for (i e redo-list) do mk-null(i); backtrack (b); modify (FST(b)); rep eat Apply Algorithm A3 Phase II to b until (result is not subsumed in FST(b)) if (result = failure) then report failure Apply Algorithm B3 146 else for (i e rcdo(b, 0 ) do Apply Algorithm A3 Phase n to i as t_goal. Algorithm B3: Backward Execution Algorithm on a Segmented-stack. The segmented-stack representation of the local-stack for two instances from Figure 1. arc shown in Figure 22. It shows the state where pO has unified with the rule-head and when the execution of the subgoals p i, p2, p3, p4 and p5 have suc­ ceeded. Note that until all the subgoals in the rule succeed, the heap-pointer with the node for pO will remain dangling, i.e., undefined. ru le -p o in te r Dangling heap pointer heap pointe Figure 22. Execution o f Logic program* on a segm ented stack, a c u e from Figure 1. 147 7.6. Space Complexity of Segmented Stack There is an additional usage of space in implementing the segmented stack in the form of two additional fields in each frame. These are used for maintaining the rulepointer and the segment pointer. The space complexity o f the local-stack is unaltered. With m inim al overhead in space, significant efficiency in execution can be obtained. The maintenance of the segmented stack is simple and efficient. In implementing forward jumping, there is a dynamic overhead in space. This overhead in the form of saving the search subspace of the successful subgoals that do not fall in the redo-list, while backtracking and forward jumping are taking place. This dynamic overhead in the use of space is directly proportional to the savings in computations derived by forward jumping. Also, since a subgoal is computed on a separate segmented stack, the solutions of the subgoal can be associated with i t This facilitates association of FST’s with a goal, so we can implement intelligent forward execution. When space is at premium, forward jumping can be avoided by simply back­ tracking to the appropriate goal and performing the normal operations of popping the stack and only implementing Chapter 8 8. Effects of Non-logical Operators 8.1. Introduction Non-logical operators in Prolog, such as =, >, <, assert, write, cut, fail, facilitate programming. These operators have side-effects while performing mathematical operations, while avoiding search using control operations like cut and fail, and while performing input/output operations. These operators are built on top of the systematic control facility of the Prolog interpreter. It is essential that every new paradigm for Prolog, or logic programming, incorporates these facilities in a transparent manner. The operators +, *, /, =, <, >, write and read do not have any effect on the para­ digms developed in chapters 4, 5, and 6. The operator "consult" modifies the program and hence all the identified failure-bindings, failure-solutions and gc-lists stand void The effects of other non-logical operators on the different paradigms and data struc­ tures is described below. 148 149 8.2. Effect of C ut and Fail The cut is a control facility provided to the programmer to help prune certain searches. The predicate cut always succeeds. When forward execution encounters the predicate cut, all subsequent searches of the subgoals to the left of the cut in the rule, and subsequent alternatives that are applicable to the goal that unified with the head, are avoided. The effect of the cut on the identification of failure-bindings is contributory to its incompleteness. This is because not all the alternatives of a goal are tried when any of the alternative applicable to the goal execute a cut. Hence, no failure-bindings can be identified. There is no effect o f the cut on identification of failure-solutions. Similarly, the forward jumping procedure is unaltered if any of the subgoals in a rule applied to a goal contains a cut. The use of the segmented stack as a data structure for the local stack does not hinder the control implemented by the cut. The control operator ''fail” does not have any effect on the paradigms developed in the earlier chapters. ISO 8*3. Effect o f Assert and Retract Retract removes information from the database and hence does not affect either the identified failure-bindings or failure-solutions, though it could lead to not identify­ ing some failure-bindings during later execution. Assert, however, adds to the infor­ mation content of the database. This voids all identified failure-bindings and failuresolutions. Hence, FBT*s and FST’s of all predicates and goals are made void. Chapter 9 9. Summary 9.1. Conclusions W e have presented three paradigms and a new data structure for implementing these paradigms. The frame woric implementing these paradigms on the new data structure leads to very efficient execution o f logic programs. 1. The identification and use o f failure-bindings during execution leads to alleviation o f extensive oscillation o f computation between backtracking and forward execution. Although the identification o f failure-bindings is not complete, the late detection of failure is cured to a great extent by the bit-vector implementation and the use of failure-binding-tables. The time and space incurred in the identification o f failure-bindings of a goal is ident­ ical to the nodes in the goal-search tree o f a goal. 2. T he identification and use o f failure-solutions dining execution leads to elimination o f retracing of identical paths in the goal-search o f the primary goal. In other words, the states encountered by the use o f failure-solutions are unique. Thus, the resulting search is deterministic in nature. The time and space incurred in identifying a failure-solunon o f a goal equals the num ber of nodes in the goal-search tree o f the initial query which is under a subgoal. 3. The use o f forward jumping leads to further pruning o f the goal-search tree. Forward jumping leads to elimination of computations with combinations o f bindings which have been identified to cause failure. The time and space incurred in determining redo-list for forward jumping equals N^, * NrAr, lt. where Nw is the maximum number of variables used in a rule and 151 n _^| ... is 152 the number of goals in the rule. 4. As described in chapter 7, the additional space and time incurred in execut­ ing logic programs on a segmented-stack, as the data structure for the local-stack, equals two additional fields in each frame and their updating. Thus, additional savings in computation can be found by implementing the techniques described in this dissertation. 5. The effect of non-logical operators is straightforward so that these operators can be implemented properly in the context of efficient search. Figure 23 presents a flow chart of the execution box of a goal for the framework which would implement intelligent backtracking based on failure-bindings identified by the bit-vector method, intelligent forward execution based on failure-solutions, and forward jumping. Figure 24 shows the goal-tree which uses all the three paradigms for the example in Figure 1. Table VI gives the trace of execution forthe example in Figure on the use of all the three paradigms. 1 based 153 no | p r tm iy S fetch redo list I Fetch f< yes Report SUCCESS no ifa ilu rrv yes no A O t U t I O * —— until' succe* no no b -0 R eport FAILURE b >0 Figure 23. Execution Box of a goal implementing Intelligent Backtracking, Intelligent Forward Execution and Forward Juiqping 154 b l.c l (bl. Y/bl; Z/c l c u Y' b 2 - V r t X /0 2 t F ib * X /al fb = X / a U/ fb = Z / c l Pruned Search space based on Intelligent backtracking fb = V / f l Pruned Search sp ace by Forward Ju m p in g Pruned S earch ap ace by Failure S o lu tio n Success!! Figure 2 4 . G oal-tree by In telligen t B acktracking. In tellig en t Forward Execution and Forward Jum ping 155 goal (pl(Y, Z). (Y .Z ). {},{}) (p2(X), {)) <p3(Z). {Z/cl}> <p4(X. Y,U), (X/al, Y /bl]) (p2(X). {}) (p4(X. Y, U)( {X/a2, Y /bl)) <p5(Z, X. U. W). {Z/cl. X W , U /dl)) (pl(Y, Z),{}) (p5(Z, X. U. W). {Z/cl. X/h2. U /dl)) (pl(Y. Z). {)) <p3(Z), (Z/c2J) (p5(Z, X. U, W). {Z/c2, X/a2. U /dl)) (P6(V), {)) (p7(X. V). {X/a2, V/fl J) <p8(Y). {Y/b2}) <p9fX, U. V). {X/a2. U/dl. V /fl}) <P6(V}, {)) (p7(X,V), (X/a2, V/f2)) (p9(X, U. V). {X/a2, U/dl. V/E2)) (plOCY.U). {Y/b2,U/dl|) (pll(X . Z). {X/a2. Z/c2)) success/fail success success success fiul ruccess success fail success fail success success success success success success fail success success success success success binding Y/bl; Z/cl X/sl X/»2 U/dl Y/bl; Z/cl Y/b2; Z/c2 W/el v/n V/T2 * " fb X/al Z/cl Z/cl V/fl ” e PSTW yes * - b ta pi * pi p6 - redo-list (p2J (p l,p 3 | {pl,p3| (P6. p7} * " Table VI: Trace of Execution by Intelligent Backtracking. Intelligent Forward Execution and Forward Jumping t Identified from FBT(p4) search, fb and b in the header row is an acronym for failure-binding and backtrack literal, respectively. 156 Each of these paradigms is defined and systematic evaluation of these methods is presented in detail. Forward- and backward* execution algorithms that implement these paradigms are given. It is proved that the application of these paradigms is sound and complete in that the resulting execution based on these paradigms are sound and complete. Also, the application of these paradigms preserves the order of results obtained by Prolog. The properties of the use o f these paradigms and data structure are: Failure Binding (Chapter 4) Precise cause of failure. State independent. Intelligent backtracking farthest to the left than has been pre­ viously possible. Global learning of information about predicates. Failure Solution (Ch. 5) Use of history of computation. State dependent. Intelligent forward execution eliminates repetition of unsuccessful search. Local learning about the solutions of goals. Forward Jumping (Ch. 6) Use of generator consumer approach. State dependent. Eliminates repetition of successful search after backtracking. Segmented Stack (Ch. 7) Facilitates association of information about a goal with the goal. Keeps space and time complexity identical to that of linear stack. Used for interleaved depth-first and breadth-first search. A simple comparison of the number of steps performed by the application of different 157 paradigms and that by Prolog, for the example in Figure 1, from the Tables I, n, in, IV and V is given below. Standard C < 5" Prolog 45 Unified framework 34 34 22 21 This project was started in conjunction with Kundu, [33] and [59]. The concepts in Kundu, [34], differ in that the failure-bindings described in this dissertation are pre­ cise causes of failure and that by Kundu are composite faiure-bindings. The use of FBT is similar, if not identical. The representation schemes for the dependencies among the literals in a rule are different The generation of redo-list is based on the representation schemes. An implementation of an interpreter based on the paradigms described in this chapter was undertaken by Mr. Pramod Korwar, under the direction of Kundu. This interpreter implemented a prototype of the segmented stack and the bit-vector method for identification of "precise" failure-binding, as described in chapter 4 For more details on this implementation contact Kundu, [33]. 158 9.2. Future Directions The area o f efficient execution of logic programs needs to be further explored. Some o f the open issues that can be stated are as follows: a) Extension of the paradigms introduced in this dissertation to logic programs which contain generalized terms containing lists$. sup t$ b) Is it possible to find a method which is complete in identifying failurebindings of a goal? c) Can the identification of failure-bindings lead further pruning than has been described in this dissertation? d) How to make the FST and FBT table look up procedures more efficient? e) A method to identify failure-bindings of a negated goal. f) A user friendly, declarative style to control paradigm to specify control of search. g) A formal and accurate time and complexity analysis model for comparing the execution models for logic programs. t The application of failure-bindings to (he case of logic programs with generalized terms is being investigated independently Kundu, [33 -34], References 1 Hogger, C. J., Introduction to Logic Programming, APIC Studies in Data Processing, No. 21, Academic Press, Inc., New York, 1984. 2 Lloyd, J. W „ Mathematical foundations o f logic programming, Research Monograph, Dept, of Computer Science, Univ. of Melbourne, Australia, 1983. 3 Clark, K. L., Tamlund, S. A., Logic Programming, editors, APIC studies in data processing, Vol. 16, Academic Press, London. 4 Clocks in, W. F., Mellish, C. S., Programming in Prolog, Springer-Verlag, Berlin, 1981. 5 Stallman, R. M. and Sussman, G. J., Forward Reasoning and dependency directed backtracking in a system for computer aided circuit analysis, Artificial Intelligence, 9(1977). 6 Apt, K. R., van Emden, M. H., Contributions to the theory of logic pro­ gramming, JACM 29(3), pp. 841-862. 7 Kowalski, R. A., Predicate logic as a programming language, Proc. of IFIP-74 North Holland Publ., Amsterdam, pp. 569-574. 8 Kowalski, R. A., Prolog as a logic programming language, Proc. of AICA congress, Pavia, Italy, September, 1981, 23-25. 9 Kowalski, R. A., The history of logic programming. 10 Kowalski, R., in, Logic for Problem Solving, Elsevier, North Holland, New 159 160 York, NY, 1979. 11 Pereira, L. M., Porto, A., Selective Backtracking, Logic Programming, ed. K. L. Clark and S. A. Tamlund, Academic Press, 1982, pp. 107-114. 12 Cox, P. T., Finding Backtrack Points for Intelligent Backtracking, Imple­ mentations of Prolog, ed. J. A. Campbell, Ellis Horwood Limited, 1984, pp. 216-233. 13 Cox, P., Pietrzylowsld, T., Deduction Plans: A basis for Intelligent Back­ tracking, IEEE Transactions on Pattern Analysis and Machine Intelligence, P A M I-3 ,1981. 14 Bruynooghe, M., Analysis of Dependencies to Improve the Behaviour of Logic Programs, Conference on Automated Deduction, 1980, pp. 293-305. 15 Bruynooghe, M., Intelligent Backtracking for an Interpreter of Horn C ause Logic Programs, Mathematical Logic in Computer Science, Salgotaijan, Hungary, ColJoquia Mathematics Societatis Janos Bolyai, 1978. 16 Bruynooghe, M., Pereira, L. M., Deduction Revision by Intelligent Back­ tracking, in Implementations of Prolog, ed. J. A. Campbell, Ellis Horwood Limited, 1984, pp. 194-215. 17 Chang, J. H., Despain, A. M., DeGroot, D., AND-Parallelism of Logic Pro­ grams Based on a Static Data Dependency Analysis, IEEE Spring CompCon, 1985, pp. 218-225. 18 Chang, J. H., Despain, A. M., Semi-Intelligent Backtracking of Prolog Based on a Static Data Dependency Analysis, Proceedings of IEEE Sympo­ sium on Logic Programming, August, 1985, pp. 10-21. 19 Concry, J. S., Implementing Backward Execution in Nondeterministic AND-Parallel Systems, Fourth International Conference on Logic Program­ ming, MIT Press, 1987. 20 Conery, J. S., The And/Or Process Model for Parallel Interpretation of Logic Programs, PhD Thesis, University of California, Irvine, CA, June 1983. 21 Conery, J. S., Kibler, D. F., And-Parallelism and Non-Determinism in Logic Programs, New Generation Computing, 3,1985, pp. 43-70. 22 Conery, J. S., Backward Execution in Non-Deterministic And-Parallel Sys­ tems, Proceedings of Fourth International Conference on Logic Program­ ming, May 1987. 23 Conery, J. S., Kibler, D. F., Parallel Interpretation of Logic Programs, Proceedings of the ACM Conference on Functional Languages and Com­ puter Architecture, October 1981, pp. 163-170. 24 Kumar, V., Lin, Y. J., A Framework for Intelligent Backtracking in Logic Programs, Proceedings of the Sixth Conference on Foundations of Software Technology and Theoretical Computer Science, New Delhi, India, pp. ???, Springer-Verlag lecture notes #241, December 1986, 25 Kumar, V., Lin, Y. J., An Intelligent Backtracking Scheme for Prolog, IEEE Symposium on Logic Programming, San Francisco. 1987,406-114. 26 Woo, N., Choc, K., Selecting the Backtrack Literal in the AND/OR Process 162 Model, Symposium on Logic Programming, Salt Lake City, 1986, pp. 200209. 27 Rajasekhar, S, Narasimha Murthy, Variable Based Backtrcldng Method, Conference on 28 The memory management of Prolog implementations, Clark and Tamlund. 29 Warren, D. H. D., An Abstract Prolog Instruction Set, Technical Note 309, SRI International, Menlo Park, CA, October 1983. 30 Warren, D. H. D., Or-Parallel Execution Models of Prolog, Technical Note, Dept, o f Computer Science, University of Manchester, December 1986. 31 Warren, D. H. D., Implementing Prolog - compiling predicate logic pro­ grams, Research reports No. 39 and 40, Dept, of AI, Univ. of Edinburgh, Scotland, 1977. 32 Warren, D. H. D .t An improved Prolog implementation which optimizes tail recursion, Workshop on LP, 1980. 33 Kundu, S., private communications and different versions of reports exchanged, October, 1987 through March, 1989. 34 Kundu, S., paper under preparation pertaining to generalized failurebindings and their use for backtracking and forward jumping. 35 Mellish, C. S., An alternative to structure sharing in the implementation of Prolog interpreter, Clark and Tamlund. 36 Clark, K., Gregory, S., PARLOG: Parallel Programming in Logic, Research Report DOC 84/4, D ept of Computing, Imperial College of Science and Tech., London, 1984. 37 Gregory, S., Design, Application and Implementation o f a Parallel Logic Programming Language, PhD Thesis, Imperial College o f Science and Tech., London, 1985. 38 Hermenegildo, M. V„ Nasr, R. I., Efficient Management o f Backtracking in AND-Parallelism, Third International Conference on Logic Programming, Springer-Verlag, Lecture Notes in Computer Science, Vol. 225,1986. 39 Disz, T., Lusk, E., Overbeek, R., Efficient Management o f Backtracking in Or-Parallel Logic Programs, Proceedings of Fourth International Confer­ ence on Logic Programming, May 1987. 40 Kale, L. V., Warren, D. S., A Class of Architectures for Prolog Machine, Proc. of the Conference on Logic Programming, Uppasala, Sweden, July 1984, pp. 171-182. 41 Kale, L. V., Parallel Execution of Logic Programs: The Redtice-Or Process Model, Proceedings of Fourth International Conference on Logic Program­ ming, May 1987. 42 Hausmen, B., Ciepielewski, A., Haridi, S., Or-Parallel Prolog Made Efficient on Shared Memory Multiprocessors, IEEE Symposium on Logic Programming, San Francisco, 1987, pp. 69-79. 43 Degroot, D., Restricted And-Parallelism and Side-Effects, IEEE Sympo­ sium on Logic Programming, San Francisco, 1987, pp. 80-91. 44 DeGroot, D., Restricted And-Parallelism, ICOT International Conference 164 on Fifth Generation Computer Systems, 1984, pp. 471-478. 45 Kale, L. V., Completeness and Full Parallelism of Parallel Logic Program­ ming Schemes, IP.BF. Symposium on Logic Programming, San Francisco, 1987, pp. 125-133. 46 Wisboiough, W., Semantically Transparent Selective Reset for AND Paral­ lel Interpreters Based on Origin of Failures, IEEE Symposium on Logic Programming, San Francisco, 1987, pp. 134-153. 47 Ali, K. A. M., A Method for Implementing Cut in Parallel Execution of Prolog, IEEE Symposium on Logic Programming, San Francisco, 1987, pp. 449-45. 48 Ueda, K., Making Exhaustive Search Programs Deterministic, Proc. Third International Conference on Logic Programming (Lecture Notes in Com­ puter Science, Vol. 225), Springer-Verlag, 1986, pp. 270-282. 49 Ueda, K., Guarded Horn Clauses, in Proc. Logic Programming ’85, E. Wada (ed.), Lecture Notes in Computer Science, 221, Springer-Verlag, pp. 168-179, 50 Byrd, L,, Understanding the control flow of Prolog programs. Logic pro­ gramming workshop 1980. 51 Ciepielewski, A., Haridi, S., A Formal Model for Or-Parallel Execution of Logic Programs, in Information Processing, R. E. A. Mason (ed.) Elsevier Science Publishers. 1983, pp. 299-305. 52 Li, P. P., Martin, A. J., The Sync Model: A Parallel Execution Method for Logic Programming, in Proceedings of the Third Symposium on Logic Pro­ gramming, Salt Lake City. September, 1986. 53 Wise, M. J„ A Parallel Prolog: The Construction o f a Data Driven Model, Proceedings of the 1982 Conference on Lisp and Functional Programming, 1982, pp. 56-66. 54 Kasif, S., Minker, J., The Intelligent Channel: A Scheme for Result Sharing in Logic Programs, Proceedings o f the 9th UCA1, Los Angeles, August 1985, pp. 29-31.. 55 Monteiro, L., A proposal for distributed programming in Logic, in Imple­ mentations of Prolog, Ed. Campbell, Ellis Horwood 1984. 56 Borgwaidt, P., Rea, D., Distributed Semi-Intelligent Backtracking for a Stack-based AND-parallel Prolog, Proceedings of the 1986 Symposium on Logic Programming, IEEE Computer Society, 1986, pp. 211-222. 57 Kumar, A., Parameswaran, N., and Iyengar, S. S., Meta-level Control in Prolog Interpretation, submitted to CACM, May 1989. 58 Iyengar, S. S., and Kashyap, R. L „ Intelligent Autonomous Machines, IEEE Computer, June 1989, pp. 14. 59 Iyengar, Sudharsan, and Kundu, S., two reports on the ideas of failurebinding, forward jumping, intelligent forward execution and segmented stack, independent study report, March 1988. Vita Sudharsan R. Iyengar w as bom to Pankajam and R engasw am y A ravam udhan on First o f N ovem ber, 1961, in the tow n o f S rirangam , M adras, India. A fter finishing Secondary S c h o o l C ertificate at Fatim a H igh School, B om bay, and H igher S econ­ dary C ertificate, at C H M C , Bom bay, he w ent on to study for the B achelor in E ngineering D egree, at R egional E ngineering college, D urgapur. A fter obtaining the B.E. in E lectrical E ngineering, in M ay 1984, he w ent on to pursue higher education at L ouisiana State U niversity, Baton R ouge. H e got his M .S. in S ystem s Science and M .S. in E lectrical E ngineering in M ay 1987. H e is currently a can d id ate fo r his Ph.D. degree in the D epartm ent o f C om puter Science, at LSU , B aton Rouge. 166 DOCTORAL EXAMINATION AND DISSERTATION REPORT C a n d id a te : Sudharsan R. Iyengar (first) (last) Major Field: COMPUTER SCIENCE Title of Dissertation A Framework for Efficient Execution of Logic Programs, Approved: Major Professor and Chairman Dean of the Graduate EXAM INING Date of Examination: 6/ 2 9 / 8 9 C O M M ITTEE