-
Notifications
You must be signed in to change notification settings - Fork 0
/
chapter3.html
3412 lines (1713 loc) · 96.6 KB
/
chapter3.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<meta name="description" content="This book discusses methods to implement intelligent reasoning by means of Prolog programs. The book is written from the shared viewpoints of Computational Logic, which aims at automating various kinds of reasoning, and Artificial Intelligence, which seeks to implement aspects of intelligent behaviour on a computer.">
<!-- SWISH -->
<link href="/web/css/lpn.css" rel="stylesheet">
<link href="/web/css/jquery-ui.min.css" rel="stylesheet">
<script src="/web/js/jquery.min.js"></script>
<script src="/web/js/jquery-ui.min.js"></script>
<script src="/web/js/lpn.js"></script>
<!-- custom stylesheet -->
<!--<link href="/web/css/custom.css" rel="stylesheet">-->
<!--Reveal.js-->
<link href="/web/css/reveal.css" rel="stylesheet">
<link href="/web/css/theme/simple.css" rel="stylesheet">
<meta name=Title content="Simply Logical">
<meta name=author content="Peter Flach">
<title>Simply Logical</title>
</head>
<body>
<!--navibar-->
<div class="reveal" style="margin-top: -50px; padding-top: 50px;">
<div style="position: absolute; bottom: 1em; width: 100%; font-size: 0.4em; text-align: center;">
Peter Flach | http://www.cs.bris.ac.uk/~flach/SimplyLogical.html
</div>
<div class="slides">
<section>
<h3>Interactive lab examples</h3>
<h4>Simply Logical</h4>
</section>
<section>
<section>
<h2>Chapter 3: Logic Programming and Prolog</h2>
</section>
<section>
<h3>Declarative and procedural meaning</h3>
<p>
A distinct feature of logical reasoning is the separation between model theory and proof theory: a set of logical formulas determines the set of its models, but also the set of formulas that can be derived by applying inference rules. Another way to say the same thing is: logical formulas have both a <em>declarative</em> meaning and a <em>procedural</em> meaning. For instance, declaratively the order of the atoms in the body of a clause is irrelevant, but procedurally it may determine the order in which different answers to a query are found.</p>
</section>
<section>
<h3>Algorithm = logic + control</h3>
<p>Because of this procedural meaning of logical formulas, logic can be used as a programming language. If we want to solve a problem in a particular domain, we write down the required knowledge and apply the inference rules built into the logic programming language. Declaratively, this knowledge specifies <strong>what</strong> the problem is, rather than <strong>how</strong> it should be solved. </p>
</section>
<section>
<h3>Algorithm = logic + control (ctd.)</h3>
<p>The distinction between declarative and procedural aspects of problem solving is succinctly expressed by Kowalski’s equation</p>
<blockquote>
<p>algorithm = logic + control</p>
</blockquote>
<p>Here, <em>logic</em> refers to declarative knowledge, and <em>control</em> refers to procedural knowledge. The equation expresses that both components are needed to solve a problem algorithmically.</p>
</section>
<section>
<h3>Programming with logic</h3>
<p>In a purely declarative programming language, the programmer would have no means to express procedural knowledge, because logically equivalent programs would behave identically. However, Prolog is not a purely declarative language, and therefore the procedural meaning of Prolog programs cannot be ignored. For instance, the order of the literals in the body of a clause usually influences the efficiency of the program to a large degree. Similarly, the order of clauses in a program often determines whether a program will give an answer at all. </p>
</section>
<section>
<h3>Programming with logic (ctd.)</h3>
<p>Therefore, in this chapter we will take a closer look at Prolog’s inference engine and its built-in features (some of which are non-declarative). Also, we will discuss some common programming techniques.</p>
</section>
</section>
<section>
<section>
<h3>3.1 SLD-resolution</h3>
</section>
<section>
<h3>Prolog proof procedure</h3>
<p>Prolog’s proof procedure is based on resolution refutation in definite clause logic. Resolution refutation has been explained in the previous chapter. In order to turn it into an executable proof procedure, we have to specify how a literal to resolve upon is selected, and how the second input clause is found. Jointly, this is called a <em>resolution strategy</em>. </p>
</section>
<section>
<h3>Prolog proof procedure (ctd.)</h3>
<p>Consider the following program:</p>
<div class="extract swish" id="3.1.1">
<pre class="source swish temp AutoStyle03" data-variant-id="group-1" id="swish.3.1.1" query-text="">
student_of(X,T):-follows(X,C),teaches(T,C).
follows(paul,computer_science).
follows(paul,expert_systems).
follows(maria,ai_techniques).
teaches(adrian,expert_systems).
teaches(peter,ai_techniques).
teaches(peter,computer_science).
</pre>
</div>
</section>
<section>
<h3>Prolog proof procedure (ctd.)</h3>
<p>The query</p>
<pre><code class="Prolog">?-student_of(S,peter).
</code></pre>
<p>has two possible answers: { <code>S</code> → <code>paul</code> } and { <code>S</code> → <code>maria</code> }. In order to find these answers, we first resolve the query with the first clause, yielding</p>
<pre><code class="Prolog">?-follows(S,C),teaches(peter,C).
</code></pre>
</section>
<section>
<h3>Prolog proof procedure (ctd.)</h3>
<p>Now we have to decide whether we will search for a clause which resolves on <code>follows(S,C)</code>, or for a clause which resolves on <code>teaches(peter,C)</code>. This decision is governed by a <em>selection rule</em>. Prolog’s selection rule is left to right, thus Prolog will search for a clause with a positive literal unifying with <code>follows(S,C)</code>. There are three of these, so now we must decide which one to try first. </p>
</section>
<section>
<h3>Prolog proof procedure (ctd.)</h3>
<p>Prolog searches the clauses in the program top-down, so Prolog finds the answer { <code>S</code> → <code>paul</code> } first. Note that the second choice leads to a dead end: the resolvent is</p>
<pre><code class="Prolog">?-teaches(peter,expert_systems).
</code></pre>
<p>which doesn’t resolve with any clause in the program.</p>
</section>
<section>
<h3>SLD-resolution</h3>
<p>This process is called <em>SLD-resolution</em>: <strong>S</strong> for selection rule, <strong>L</strong> for <em>linear</em> resolution (which refers to the shape of the proof trees obtained), and <strong>D</strong> for <em>definite</em> clauses. Graphically, SLD-resolution can be depicted as in fig. 3.1. </p>
<div id="3.1">
<img src="img/figure/image022.svg" height="60%"/>
<p>
<b>Figure 3.1.</b> <p>An SLD-tree.</p>
</p>
</div>
</section>
<section>
<h3>SLD-resolution (ctd.)</h3>
<p>This <em>SLD-tree</em> should not be confused with a proof tree: first, only the resolvents are shown (no input clauses or unifiers), and second, it contains every possible resolution step. Thus, every leaf of an SLD-tree which contains the empty clause □ corresponds to a refutation and hence to a proof tree; such a leaf is also called a <em>success branch</em>. An underlined leaf which does not contain □ represents a <em>failure branch</em>.</p>
</section>
<section>
<h3>SLD-resolution (ctd.)</h3>
<div class="extract exercise" id="3.1">
<div class="AutoStyle06">
<p class="exercise AutoStyle07">
<i>Exercise 3.1.</i> <p>Draw the proof trees for the two success branches in fig. 3.1.</p>
</p>
</div>
</div>
</section>
<section>
<h3>SLD-tree</h3>
<p>As remarked already, Prolog searches the clauses in the program top-down, which is the same as traversing the SLD-tree from left to right. This not only determines the order in which answers (i.e. success branches) are found: it also determines whether any answers are found at all, because an SLD-tree may contain infinite branches, if some predicates in the program are recursive.
</section>
<section>
<h3>SLD-tree (ctd.)</h3>
As an example, consider the following program:</p>
<div class="extract swish" id="3.1.3_2">
<pre class="source swish temp AutoStyle03" data-variant-id="group-1" id="swish.3.1.3_2" query-text="">
brother_of(X,Y):-brother_of(Y,X).
brother_of(paul,peter).
</pre>
</div>
<p>An SLD-tree for the query</p>
<pre><code class="Prolog">?-brother_of(peter,B).
</code></pre>
<p>is depicted in fig. 3.2. </p>
</section>
<section>
<h3>SLD-tree (ctd.)</h3>
<div id="3.2">
<img src="img/figure/image024.svg" height="60%"/>
<p>
<b>Figure 3.2.</b> <p>An SLD-tree with infinite branches.</p>
</p>
</div>
</section>
<section>
<h3>SLD-tree (ctd.)</h3>
<p>If we descend this tree taking the left branch at every node, we will never reach a leaf. On the other hand, if we take the right branch at every node, we almost immediately reach a success branch. Taking right branches instead of left branches in an SLD-tree corresponds to searching the clauses from bottom to top.
</section>
<section>
<h3>SLD-tree (ctd.)</h3>
The same effect would be obtained by reversing the order of the clauses in the program, and the SLD-tree clearly shows that this is enough to prevent Prolog from looping on this query. This is a rule of thumb that applies to most cases: <em>put non-recursive clauses before recursive ones</em>.</p>
</section>
<section>
<h3>SLD-trees can be infinite</h3>
<p>However, note that, even after this modification, the program still has some problems. For one thing, the query <code>?-brother_of(peter,B)</code> will be answered an infinite number of times, because there are infinitely many refutations of it. But, even worse, consider a query that does <strong>not</strong> have an answer, like</p>
<pre><code class="Prolog">?-brother_of(peter,maria).
</code></pre>
<p>No matter the order in which the SLD-tree is descended, Prolog will never discover that the query has in fact no answer, <em>simply because the SLD-tree is infinite</em>. So, one should be careful with programs like the above, which define a predicate to be <em>symmetric</em>.</p>
</section>
<section>
<h3>Transitivity</h3>
<p>Another property of predicates which can cause similar problems is <em>transitivity</em>.Consider the following program:</p>
<div class="extract swish" id="3.1.4_2">
<pre class="source swish temp AutoStyle03" data-variant-id="group-1" id="swish.3.1.4_2" query-text="">
brother_of(paul,peter).
brother_of(peter,adrian).
brother_of(X,Y):-brother_of(X,Z),brother_of(Z,Y).
</pre>
</div>
<p>The third clause ensures that <code>?-brother_of(paul,adrian)</code> is a logical consequence of the program.
</section>
<section>
<h3>Transitivity (ctd.)</h3>
The SLD-tree for the query</p>
<pre><code class="Prolog">?-brother_of(paul,B).
</code></pre>
<p>is depicted in fig. 3.3. Not only is this SLD-tree infinite, but the resolvents get longer and longer on deeper levels in the tree.</p>
</section>
<section>
<h3>Transitivity (ctd.)</h3>
<div id="3.3">
<img src="img/figure/image026.svg" height="60%"/>
<p>
<b>Figure 3.3.</b> <p>An SLD-tree with infinite branches and expanding resolvents.</p>
</p>
</div>
</section>
<section>
<h3>Incompleteness</h3>
<p>We have encountered two problems with SLD-resolution: (<em>i</em>) we might never reach a success branch in the SLD-tree, because we get ‘trapped’ into an infinite subtree, and (<em>ii</em>) any infinite SLD-tree causes the inference engine to loop if no (more) answers are to be found. The first problem means that Prolog is <em>incomplete</em>: some logical consequences of a program may never be found.
</section>
<section>
<h3>Incompleteness (ctd.)</h3>
Note carefully that this incompleteness is <strong>not</strong> caused by the inference rule of resolution, which is refutation complete. Indeed, for any program and any query, all the possible answers will be represented by success branches in the SLD-tree. The incompleteness of SLD-resolution is caused by the way the SLD-tree is searched.</p>
</section>
<section>
<h3>Depth-first vs. breadth-first</h3>
<p>There exists a solution to this problem: if we descend the tree layer by layer rather than branch-by-branch, we will find any leaf before we descend to the next level. However, this also means that we must keep track of <strong>all</strong> the resolvents on a level, instead of just a single one. Therefore, this <em>breadth-first</em> search strategy needs much more memory than the <em>depth-first</em> strategy used by Prolog.
</section>
<section>
<h3>Depth-first vs. breadth-first (ctd.)</h3>
In fact, Prolog’s incompleteness was a deliberate design choice, sacrifying completeness in order to obtain an efficient use of memory<span class="CustomFootnote">
<a href="#_ftn7" name="_ftnref7" title="">
<span class="MsoFootnoteReference">
<span class="AutoStyle13">
<span class="AutoStyle14">
[7]
</span>
</span>
</span>
</a>
</span>. As we saw above, this problem can often be avoided by ordering the clauses in the program in a specific way (which means that we have to take the procedural meaning of the program into account).</p>
</section>
<section>
<h3>Semi-decidability</h3>
<p>As for the second problem, we already saw that this is due to the semi-decidability of full clausal logic, which means that there is no general solution to it.</p>
<div class="extract exercise" id="3.2">
<div class="AutoStyle06">
<p class="exercise AutoStyle07">
<i>Exercise 3.2.</i> <p>Draw the SLD-tree for the following program:</p>
<p><div class="extract swish" id="2.3.2_3">
<pre class="source swish temp AutoStyle03" data-variant-id="group-1" id="swish.2.3.2_3" query-text="">
list([]).
list([_H|T]):-list(T).
</pre>
</div></p>
<p>and the query</p>
<p><code>?-list(L).</code></p>
</p>
</div>
</div>
</section>
</section>
<section>
<section>
<h3>3.2 Pruning the search by means of cut</h3>
</section>
<section>
<h3>Backtracking</h3>
<p>As shown in the previous section, Prolog constantly searches the clauses in a program in order to reach a success branch in the SLD-tree for a query. If a failure branch is reached (i.e., a non-empty resolvent which cannot be reduced any further), Prolog has to ‘unchoose’ the last-chosen program clause, and try another one. This amounts to going up one level in the SLD-tree, and trying the next branch to the right. This process of reconsidering previous choices is called <em>backtracking</em>.
</section>
<section>
<h3>Backtracking (ctd.)</h3>
Note that backtracking requires that all previous resolvents are remembered for which not all alternatives have been tried yet, together with a pointer to the most recent program clause that has been tried at that point. Because of Prolog’s depth-first search strategy, we can easily record all previous resolvents in a <em>goal stack</em>: backtracking is then implemented by popping the upper resolvent from the stack, and searching for the next program clause to resolve with.</p>
</section>
<section>
<h3>The goal stack</h3>
<p>As an illustration, consider again the SLD-tree in fig. 3.1. The resolvent in the middle branch</p>
<pre><code class="Prolog">:-teaches(peter,expert_systems)
</code></pre>
<p>cannot be reduced any further, and thus represents a failure branch. At that point, the stack contains (top-down) the previous resolvents</p>
<pre><code class="Prolog">:-follows(S,C),teaches(peter,C)
?-student_of(S,peter)
</code></pre>
</section>
<section>
<h3>The goal stack (ctd.)</h3>
<p>The top one is popped from the stack; it has been most recently resolved with <code>follows(paul,expert_systems)</code>, so we continue searching the program from that clause, finding <code>follows(maria,ai_techniques)</code> as the next alternative.</p>
</section>
<section>
<h3>Choice points</h3>
<p>A node in the SLD-tree which is not a leaf is called a <em>choice point</em>, because the subtree rooted at that node may contain several success branches, each of which may be reached by a different choice for a program clause to resolve with.
</section>
<section>
<h3>Choice points (ctd.)</h3>
Now, suppose a subtree contains only one success branch, yielding an answer to our query. If we want to know whether there are any alternative answers, we can force Prolog to backtrack. However, since the rest of the subtree does not contain any success branches, we might as well skip it altogether, thus speeding up backtracking.
</section>
<section>
<h3>Choice points (ctd.)</h3>
But how do we tell Prolog that a subtree contains only one success branch? For this, Prolog provides a control device which is called <em>cut</em> (written <code>!</code>), because it cuts away (or prunes) part of the SLD-tree.</p>
</section>
<section>
<h3>Pruning an unncessessary choice point</h3>
<p>To illustrate the effect of cut, consider the following program.</p>
<div class="extract swish" id="3.2.2">
<pre class="source swish temp AutoStyle03" data-variant-id="group-1" id="swish.3.2.2" query-text="">
parent(X,Y):-father(X,Y).
parent(X,Y):-mother(X,Y).
father(john,paul).
mother(mary,paul).
</pre>
</div>
<p>The SLD-tree for the query</p>
<pre><code class="Prolog">?-parent(john,C).
</code></pre>
<p>is given in fig. 3.4. </p>
</section>
<section>
<h3>Pruning an unncessessary choice point (ctd.)</h3>
<div id="3.4">
<img src="img/figure/image028.svg" height="60%"/>
<p>
<b>Figure 3.4.</b> <p>SLD-tree for the query<br><code>?-parent(john,C)</code>.</p>
</p>
</div>
</section>
<section>
<h3>Pruning an unncessessary choice point (ctd.)</h3>
<p>The answer given by Prolog is { <code>C</code> → <code>paul</code> }. By asking whether there are any other answers, we force Prolog to backtrack to the most recent choice point for which there are any alternatives left, which is the root of the SLD-tree (i.e. the original query). Prolog tries the second clause for <code>parent</code>, but discovers that this leads to a failure branch.</p>
</section>
<section>
<h3>How to interpret a cut</h3>
<p>Of course, <strong>we</strong> know that this backtracking step did not make sense: if John is a father of anyone, he can’t be a mother. We can express this by adding a cut to the first <code>parent</code> clause:</p>
<div class="extract swish" id="3.2.3">
<pre class="source swish temp AutoStyle03" data-variant-id="group-1" id="swish.3.2.3" query-text="">
parent(X,Y):-father(X,Y),!.
parent(X,Y):-mother(X,Y).
father(john,paul).
mother(mary,paul).
</pre>
</div>
</section>
<section>
<h3>How to interpret a cut (ctd.)</h3>
<p>The cut says: <em>once you’ve reached me, stick to all the variable substitutions you’ve found after you entered my clause</em>. That is: don’t try to find any alternative solutions to the literals left of the cut, and also: don’t try any alternative clauses for the one in which the cut is found. </p>
</section>
<section>
<h3>How to interpret a cut (ctd.)</h3>
<p>Given this modified program, the SLD-tree for the same query is shown in fig. 3.5. </p>
<div id="3.5">
<img src="img/figure/image030.svg" height="60%"/>
<p>
<b>Figure 3.5.</b> <p>The effect of cut.</p>
</p>
</div>
</section>
<section>
<h3>How to interpret a cut (ctd.)</h3>
<p>Since <code>!</code> is true by definition, the resolvent <code>:-!</code> reduces to the empty clause. The shaded part represents the part of the SLD-tree which is pruned as a result of the cut. That is: every alternative at choice points below and including <code>?-parent(john,C)</code>, which are on the stack when the cut is reached, are pruned.
</p>
</section>
<section>
<h3>Green and red cuts</h3>
<p>A cut is harmless if it does not cut away subtrees containing success branches. If a cut prunes success branches, then some logical consequences of the program are not returned as answers, resulting in a procedural meaning different from the declarative meaning. Cuts of the first kind are called <em>green</em> cuts, while cuts of the second kind are called <em>red</em> cuts. A green cut merely stresses that the conjunction of literals to its left is <em>deterministic</em>: it does not give alternative solutions. In addition, it signifies that if those literals give a solution, the clauses below it will not result in any alternatives.</p>
</section>
<section>
<h3>Behaviour of cut depends on the query</h3>
<p>This seems to be true for the above program: John is the father of only one child, and no-one is both a father and a mother. However, note that we only analysed the situation with regard to a particular query. We can show that the cut is in fact red by asking the query</p>
<pre><code class="Prolog">?-parent(P,paul).
</code></pre>
<p>The answer { <code>P</code> → <code>mary</code> } is pruned by the cut (fig. 3.7). That is, the literal <code>father(X,Y)</code> left to the cut is only deterministic if <code>X</code> is <code>instantiated</code> (is substituted by a non-variable value).</p>
</section>
<section>
<h3>Behaviour of cut depends on the query (ctd.)</h3>
<div id="3.7">
<img src="img/figure/image034.svg" height="60%"/>
<p>
<b>Figure 3.7.</b> <p>A success branch is pruned.</p>
</p>
</div>
</section>
<section>
<h3>Not a good use of cut</h3>
<p>Note that success branches are also pruned for the first query if John has several children:</p>
<div class="extract swish" id="3.2.4">
<pre class="source swish temp AutoStyle03" data-variant-id="group-1" id="swish.3.2.4" query-text="">
parent(X,Y):-father(X,Y),!.
parent(X,Y):-mother(X,Y).
father(john,paul).
father(john,peter).
mother(mary,paul).
mother(mary,peter).
</pre>
</div>
<p>The SLD-tree for the query</p>
<pre><code class="Prolog">?-parent(john,C).
</code></pre>
<p>is given in fig. 3.8. </p>
</section>
<section>
<h3>Not a good use of cut (ctd.)</h3>
<div id="3.8">
<img src="img/figure/image036.svg" height="60%"/>
<p>
<b>Figure 3.8.</b> <p>Another success branch is pruned.</p>
</p>
</div>
</section>
<section>
<h3>Not a good use of cut (ctd.)</h3>
<p>Indeed, the second answer { <code>C</code> → <code>peter</code> } is pruned by the cut. This clearly shows that the effect of a cut is not only determined by the clause in which it occurs but also by other clauses. Therefore, the effect of a cut is often hard to understand.</p>
</section>
<section>
<h3>Cut is a low-level construct</h3>
<p>Programs with cuts are not only difficult to understand; this last example also shows that their procedural interpretation (the set of answers they produce to a query) may be different from their declarative interpretation (the set of its logical consequences).
</section>
<section>
<h3>Cut is a low-level construct (ctd.)</h3>
Logically, cut has no meaning: it always evaluates to <strong>true</strong>, and therefore it can always be added or removed from the body of a clause without affecting its declarative interpretation. Procedurally, cut may have many effects, as the preceding examples show.
</section>
<section>
<h3>Cut is a low-level construct (ctd.)</h3>
This incompatibility between declarative and procedural interpretation makes it a very problematic concept. Much research in Logic Programming aims at replacing it by higher-level constructs which have cleaner declarative meanings and which are easier to understand. The most important of these will be considered in the next two sections.</p>
</section>
<section>
<h3>Cut is a low-level construct (ctd.)</h3>
<div class="extract exercise" id="3.3">
<div class="AutoStyle06">
<p class="exercise AutoStyle07">
<i>Exercise 3.3.</i> <p>Draw the SLD-tree for the query</p>
<p><code>?-likes(A,B)</code></p>
<p>given the following program:</p>
<p><div class="extract swish" id="3.2.ex3.3_2">
<pre class="source swish temp AutoStyle03" data-variant-id="group-1" id="swish.3.2.ex3.3_2" query-text="">
likes(peter,Y):-friendly(Y).
likes(T,S):-student_of(S,T).
student_of(maria,peter).
student_of(paul,peter).
friendly(maria).
</pre>
</div></p>
<p>Add a cut in order to prune away one of the answers { <code>A</code> → <code>peter</code>, <code>B</code> → <code>maria</code> }, and indicate the result in the SLD-tree. Can this be done without pruning away the third answer?</p>
</p>
</div>
</div>
</section>
</section>
<section>
<section>
<h3>3.3 Negation as failure</h3>
</section>
<section>
<h3>Overlapping clauses</h3>
<p>The following program computes the maximum of two integers:</p>
<div class="extract swish" id="3.3.1">
<pre class="source swish temp AutoStyle03" data-variant-id="group-1" id="swish.3.3.1" query-text="">
max(M,N,M):- M >= N.
max(M,N,N):- M =< N.
</pre>
</div>
<p><code>>=</code> and <code>=<</code> are built-in predicates with meaning ‘greater than or equal’ and ‘less than or equal’, respectively<span class="CustomFootnote">
<a href="#_ftn8" name="_ftnref8" title="">
<span class="MsoFootnoteReference">
<span class="AutoStyle13">
<span class="AutoStyle14">
[8]
</span>
</span>
</span>
</a>
</span>. Declaratively, the program captures the intended meaning, but procedurally there are two different ways to solve queries of the form <code>?-max(N,N,M)</code>.
</section>
<section>
<h3>Overlapping clauses (ctd.)</h3>
The reason for this is that the bodies of the two clauses are not exclusive: they both succeed if the first two values of the <code>max</code> predicate are equal. We could of course remove one of the equality symbols, but suppose that we use a cut instead:</p>
<div class="extract swish" id="3.3.2">
<pre class="source swish temp AutoStyle03" data-variant-id="group-1" id="swish.3.3.2" query-text="">
max(M,N,M):- M >= N,!.
max(_M,N,N).
</pre>
</div>
<p>With a red cut, this program can only be understood procedurally. The question is: does the procedural meaning correspond to the intended meaning?
</section>
<section>
<h3>Overlapping clauses (ctd.)</h3>
Perhaps surprisingly, the answer is no! For instance, the query</p>
<pre><code class="Prolog">?-max(5,3,3).
</code></pre>
<p>succeeds: the cut is never reached, because the literal in the query does not unify with the head of the first clause. The second program is in fact a very bad program: the declarative and procedural meanings differ, and <strong>neither</strong> of them captures the intended meaning.</p>
</section>