Skip to content

Commit 22fb8ca

Browse files
authored
Merge pull request norvig#70 from pronoiac/images
Images
2 parents 08a4365 + f196af4 commit 22fb8ca

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+308
-331
lines changed

docs/chapter10.md

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,6 @@ Here is the disassembled code for f from Allegro Common Lisp for a Motorola 6800
156156
| `26:` | `unlk` | `a6` |
157157
| `28:` | `rtd` | `#8` |
158158

159-
![t0010](images/B9780080571157500108/t0010.png)
160-
161159
This may look intimidating at first glance, but you don't have to be an expert at 68000 assembler to gain some appreciation of what is going on here.
162160
The instructions labeled 0-8 (labels are in the leftmost column) comprise the typical function preamble for the 68000.
163161
They do subroutine linkage and store the new function object and constant vector into registers.
@@ -206,8 +204,6 @@ Contrast this to the code for `g`, which has no declarations and is compiled at
206204
| `82:` | `unlk` | `a6` | |
207205
| `84:` | `rtd` | `#8` | |
208206

209-
![t0015](images/B9780080571157500108/t0015.png)
210-
211207
See how much more work is done.
212208
The first four instructions ensure that the right number of arguments have been passed to `g`.
213209
If not, there is a jump to `wnaerr` (wrong-number-of-arguments-error).
@@ -339,8 +335,6 @@ We can see what these compile into for the TI Explorer, but remember that your c
339335
| ` 11 PUSH` | `LOCAL|0` | `; D` |
340336
| ` 12 RETURN CALL-4` | `FEF|3` | `; #'LIST*` |
341337

342-
![t0025](images/B9780080571157500108/t0025.png)
343-
344338
With the regular argument list, we just push the four variables on the argument stack and branch to the list function.
345339
([Chapter 22](B9780080571157500224.xhtml) explains why a tail-recursive call is just a branch statement.)
346340

@@ -365,8 +359,6 @@ Let's compare with optional arguments:
365359
| ` 33 PUSH` | `ARG|3` | ; `D` |
366360
| ` 34 TAIL-REC CALL-4` | `FEF|4` | ; `#'LIST` |
367361

368-
![t0030](images/B9780080571157500108/t0030.png)
369-
370362
Although this assembly language may be harder to read, it turns out that optional arguments are handled very efficiently.
371363
The calling sequence stores the number of optional arguments on top of the stack, and the `DISPATCH` instruction uses this to index into a table stored at location `FEF|5` (an offset five words from the start of the function).
372364
The result is that in one instruction the function branches to just the right place to initialize any unspecified arguments.
@@ -400,8 +392,6 @@ Unfortunately, keyword arguments don't fare as well:
400392
| ` 33 PUSH` | `LOCAL|4` | |
401393
| ` 34 RETURN CALL-4` | `FEF|6` | ;`#'LIST` |
402394

403-
![t0035](images/B9780080571157500108/t0035.png)
404-
405395
It is not important to be able to read all this assembly language.
406396
The point is that there is considerable overhead, even though this architecture has a specific instruction `(%STORE-KEY-WORD-ARGS)` to help deal with keyword arguments.
407397

@@ -427,8 +417,6 @@ First, here's the assembly code for reg, to give you an idea of the minimal call
427417
| `38:` | `unlk` | `a6` | |
428418
| `40:` | `rtd` | `#10` | |
429419

430-
![t0040](images/B9780080571157500108/t0040.png)
431-
432420
Now we see that `&rest` arguments take a lot more code in this system:
433421

434422
!!!(table)
@@ -460,8 +448,6 @@ Now we see that `&rest` arguments take a lot more code in this system:
460448
| `62`: | `move.l` | `#4,dl` | |
461449
| `64` | `jmp` | `(a4)` | |
462450

463-
![t0045](images/B9780080571157500108/t0045.png)
464-
465451
The loop from 20-26 builds up the `&rest` list one cons at a time.
466452
Part of the difficulty is that cons could initiate a garbage collection at any time, so the list has to be built in a place that the garbage collector will know about.
467453
The function with optional arguments is even worse, taking 34 instructions (104 bytes), and keywords are worst of all, weighing in at 71 instructions (178 bytes), and including a loop.
@@ -491,8 +477,6 @@ The inline proclamation should allow the compiler to compile a call to key as a
491477
| ` 14 PUSH CALL-1` | `FEF|3` | `; #'SORT` |
492478
| ` 15 TAIL-REC CALL-4` | `FEF|4` | `; #'NO-KEY` |
493479

494-
![t0050](images/B9780080571157500108/t0050.png)
495-
496480
The overhead only comes into play when the keywords are not known at compile time.
497481
In the following example, the compiler is forced to call key, not `no-key`, because it doesn't know what the keyword `k` will be at run time:
498482

@@ -507,8 +491,6 @@ In the following example, the compiler is forced to call key, not `no-key`, beca
507491
| ` 13 PUSH` | `ARG|2` | ; `Y` |
508492
| ` 14 TAIL-REC CALL-4` | `FEF|4` | ; `#'KEY` |
509493

510-
![t0055](images/B9780080571157500108/t0055.png)
511-
512494
Of course, in this simple example I could have replaced `no-key` with `list`, but in general there will be some more complex processing.
513495
If I had proclaimed `no-key` inline as well, then I would get the following:
514496

@@ -524,8 +506,6 @@ If I had proclaimed `no-key` inline as well, then I would get the following:
524506
| ` 14 PUSH CALL-1` | `FEF|3` | `; #'SORT` |
525507
| ` 15 TAIL-REC CALL-4` | `FEF|4` | `; #'LIST` |
526508

527-
![t0060](images/B9780080571157500108/t0060.png)
528-
529509
If you like, you can define a macro to automatically define the interface to the keyword-less function:
530510

531511
```lisp

docs/chapter11.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -489,10 +489,13 @@ We will build a single uniform data base of clauses, without distinguishing rule
489489
The simplest representation of clauses is as a cons cell holding the head and the body.
490490
For facts, the body will be empty.
491491

492-
![f11-01-9780080571157](images/B978008057115750011X/f11-01-9780080571157.jpg)
493-
Figure 11.1
494-
!!!(span) {:.fignum}
495-
Glossary for the Prolog Interpreter
492+
| []() |
493+
|---|
494+
| ![f11-01](images/chapter11/f11-01.jpg) |
495+
| Figure 11.1: Glossary for the Prolog Interpreter |
496+
497+
(ed: this should be a markdown table)
498+
496499
```lisp
497500
;; Clauses are represented as (head . body) cons cells
498501
(defun clause-head (clause) (first clause))

docs/chapter12.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,13 @@ This section presents the compiler summarized in [figure 12.1](#f0010).
9696
At the top level is the function `prolog-compile`, which takes a symbol, looks at the clauses defined for that symbol, and groups the clauses by arity.
9797
Each symbol/arity is compiled into a separate Lisp function by `compile-predicate`.
9898

99-
![f12-01-9780080571157](images/B9780080571157500121/f12-01-9780080571157.jpg)
100-
Figure 12.1
101-
!!!(span) {:.fignum}
102-
Glossary for the Prolog Compiler
99+
| []() |
100+
|---|
101+
| ![f12-01](images/chapter12/f12-01.jpg) |
102+
| Figure 12.1: Glossary for the Prolog Compiler |
103+
104+
(ed: this should be a markdown table)
105+
103106
```lisp
104107
(defun prolog-compile (symbol &optional
105108
(clauses (get-clauses symbol)))
@@ -752,8 +755,6 @@ The first column is the unification call, the second is the generated code, and
752755
| 11 | `(= ?x (f ? x))` | `nil` | `-` |
753756
| 12 | `(= ?x ?)` | `t` | `-` |
754757

755-
![t0015](images/B9780080571157500121/t0015.png)
756-
757758
From this table we can craft our new version of `compile-unify`.
758759
The first part is fairly easy.
759760
It takes care of the first three cases in this table and makes sure that `compile-unify-variable` is called with a variable as the first argument for the other cases.
@@ -1289,8 +1290,6 @@ The following table shows times in seconds to execute these routines on lists of
12891290
| `irev 20` | .22 | .010 | 22 | .028 | .0005 |
12901291
| `irev 100` | 9.81 | .054 | 181 | .139 | .0014 |
12911292

1292-
![t0020](images/B9780080571157500121/t0020.png)
1293-
12941293
This benchmark is too small to be conclusive, but on these examples the Prolog compiler is 16 to 181 times faster than the Prolog interpreter, slightly faster than interpreted Lisp, but still 17 to 90 times slower than compiled Lisp.
12951294
This suggests that the Prolog interpreter cannot be used as a practical programming tool, but the Prolog compiler can.
12961295

@@ -1436,7 +1435,9 @@ Note that these are only binary connectives, not the *n*-ary special forms used
14361435
Also, this definition negates most of the advantage of compilation.
14371436
The goals inside an and or or will be interpreted by `call`, rather than being compiled.
14381437

1439-
We can also define `not,` or at least the normal Prolog `not,` which is quite distinct from the logical `not.` In fact, in some dialects, `not` is written \+, which is supposed to be ![u12-07-9780080571157](images/B9780080571157500121/u12-07-9780080571157.jpg) , that is, "can not be derived." The interpretation is that if goal G can not be proved, then (`not G` ) is true.
1438+
We can also define `not,` or at least the normal Prolog `not,` which is quite distinct from the logical `not.`
1439+
In fact, in some dialects, `not` is written \+, which is supposed to be ⊬, that is, "can not be derived."
1440+
The interpretation is that if goal G can not be proved, then (`not G` ) is true.
14401441
Logically, there is a difference between (`not G` ) being true and being unknown, but ignoring that difference makes Prolog a more practical programming language.
14411442
See [Lloyd 1987](B9780080571157500285.xhtml#bb0745) for more on the formal semantics of negation in Prolog.
14421443

docs/chapter13.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -502,8 +502,6 @@ A third style, the *data-driven* or *generic* style, fills in only one box at a
502502
| `interest` | *generic* | | |
503503
| `...` | | | |
504504

505-
![t0010](images/B9780080571157500133/t0010.png)
506-
507505
In this table there is no particular organization to either axis; both messages and classes are listed in random order.
508506
This ignores the fact that classes are organized hierarchically: both limited-account and password-account are subclasses of account.
509507
This was implicit in the definition of the classes, because both `limited-account` and `password-account` contain accounts as components and delegate messages to those components.

docs/chapter14.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ Here is a statement in a typical slot-filler frame language:
7979

8080
This is equivalent to the logical formula:
8181

82-
∃p: person(p) ![images](images/B9780080571157500145/cap.png) name(p,Jan) ![images](images/B9780080571157500145/cap.png) age(p,32)
82+
∃p: person(p) ∧ name(p,Jan) ∧ age(p,32)
8383

8484
The frame notation has the advantage of being easier to read, in some people's opinion.
8585
However, the frame notation is less expressive.
@@ -108,7 +108,7 @@ This is easy to show: assuming the computer's memory has *n* bits, and the equat
108108

109109
b0=0∧b1=0∧b2=1...∧bn=0
110110

111-
![si1_e](images/si1_e.gif)
111+
![si1_e](images/chapter14/si1_e.gif)
112112

113113
Once we can represent a state of the computer, it becomes possible to represent any computer program in predicate calculus as a set of axioms that map one state onto another.
114114
Thus, predicate calculus is shown to be a *sufficient* language for representing anything that goes on inside a computer-it can be used as a tool for analyzing any program from the outside.
@@ -121,7 +121,7 @@ For example, we may want to manipulate numbers inside the computer by using the
121121

122122
x=y=>yxy=x
123123

124-
![si2_e](images/B9780080571157500145/si2_e.gif)
124+
![si2_e](images/chapter14/si2_e.gif)
125125

126126
Predicate calculus also serves another purpose: as a tool that can be used *by* a program rather than *on* a program.
127127
All programs need to manipulate data, and some programs will manipulate data that is considered to be in predicate calculus notation.
@@ -236,7 +236,7 @@ His problem concerned three colored blocks, but we will update it to deal with t
236236
Suppose that a certain Eastern European country, *E*, has just decided if it will remain under communist rule or become a democracy, but we do not know the outcome of the decision.
237237
*E* is situated between the democracy *D* and the communist country *C*:
238238

239-
![u14-02-9780080571157](images/B9780080571157500145/u14-02-9780080571157.jpg)
239+
![u14-02](images/chapter14/u14-02.jpg)
240240

241241
The question is: Is there a communist country next to a democracy?
242242
Moore points out that the answer is "yes," but discovering this requires reasoning by cases.
@@ -556,10 +556,11 @@ To create the index, we essentially superimpose the list structure of all the ke
556556
At each position in the tree, we create an index of the keys that have either an atom or a variable at that position.
557557
[Figure 14.1](#f0010) shows the discrimination tree for the six keys.
558558

559-
![f14-01-9780080571157](images/B9780080571157500145/f14-01-9780080571157.jpg)
560-
Figure 14.1
561-
!!!(span) {:.fignum}
562-
Discrimination Tree with Six Keys
559+
| []() |
560+
|---|
561+
| ![f14-01](images/chapter14/f14-01.jpg) |
562+
| Figure 14.1: Discrimination Tree with Six Keys |
563+
563564
Consider the query `(p ?y c)`.
564565
Either the `p` or the `c` could be used as an index.
565566
The `p` in the predicate position retrieves all six keys.

docs/chapter15.md

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ We will speak of a polynomial's *main variable, coefficients,* and *degree.* In
4343

4444
5xx3+bxx2+cxx+1
4545

46-
![si1_e](images/B9780080571157500157/si1_e.gif)
46+
![si1_e](images/chapter15/si1_e.gif)
4747

4848
the main variable is *x,* the degree is 3 (the highest power of *x*), and the coefficients are 5, *b, c* and 1.
4949
We can define an input format for polynomials as follows:
@@ -103,10 +103,13 @@ The word "polynomial" is used ambiguously to refer to both the mathematical conc
103103

104104
A glossary for the canonical simplifier program is given in [figure 15.1](#f0010).
105105

106-
![f15-01-9780080571157](images/B9780080571157500157/f15-01-9780080571157.jpg)
107-
Figure 15.1
108-
!!!(span) {:.fignum}
109-
Glossary for the Symbolic Manipulation Program
106+
| []() |
107+
|---|
108+
| ![f15-01](images/chapter15/f15-01.jpg) |
109+
| Figure 15.1: Glossary for the Symbolic Manipulation Program |
110+
111+
*(ed: should be a markdown table)*
112+
110113
The functions defining the type `polynomial` follow.
111114
Because we are concerned with efficiency, we proclaim certain short functions to be compiled inline, use the specific function `svref` (simple-vector reference) rather than the more general aref, and provide declarations for the polynomials using the special form the.
112115
More details on efficiency issues are given in [Chapter 9](B9780080571157500091.xhtml).
@@ -541,11 +544,11 @@ For example:
541544

542545
∫ax2+bxdx=ax33+bx22+c.
543546

544-
![si2_e](images/B9780080571157500157/si2_e.gif)
547+
![si2_e](images/chapter15/si2_e.gif)
545548

546549
Write a function to integrate polynomials and install it in `prefix->canon`.
547550

548-
**Exercise 15.2 [m]** Add support for *definite* integrais, such as ∫abydx !!!(span) {:.hiddenClass} ![si3_e](images/B9780080571157500157/si3_e.gif).
551+
**Exercise 15.2 [m]** Add support for *definite* integrals, such as ∫abydx !!!(span) {:.hiddenClass} ![si3_e](images/chapter15/si3_e.gif).
549552
You will need to make up a suitable notation and properly install it in both `infix->prefix` and `prefix->canon`.
550553
A full implementation of this feature would have to consider infinity as a bound, as well as the problem of integrating over singularises.
551554
You need not address these problems.
@@ -859,19 +862,19 @@ The binomial theorem states that
859862

860863
a+bn=Σi=0nn!i!n-i!aibn-i
861864

862-
![si4_e](images/B9780080571157500157/si4_e.gif)
865+
![si4_e](images/chapter15/si4_e.gif)
863866

864867
for example,
865868

866869
a+b3=b3+3ab2+3a2b+a3
867870

868-
![si5_e](images/B9780080571157500157/si5_e.gif)
871+
![si5_e](images/chapter15/si5_e.gif)
869872

870873
We can use this theorem to compute a power of a polynomial all at once, instead of computing it by repeated multiplication or squaring.
871874
Of course, a polynomial will in general be a sum of more than two components, so we have to decid`e` how to split it into the *a* and *b* pieces.
872875
There are two obvious ways: either eut the polynomial in half, so that *a* and *b* will be of equal size, or split off one component at a time.
873876
Fateman shows that the latter method is more efficient in most cases.
874-
In other words, a polynomial k1xn+k2xn-1+k3xn-2+... !!!(span) {:.hiddenClass} ![si6_e](images/B9780080571157500157/si6_e.gif) will be treated as the sum *a + b* where *a*= *k*1*xn* and *b* is the rest of the polynomial.
877+
In other words, a polynomial k1xn+k2xn-1+k3xn-2+... !!!(span) {:.hiddenClass} ![si6_e](images/chapter15/si6_e.gif) will be treated as the sum *a + b* where *a*= *k*1*xn* and *b* is the rest of the polynomial.
875878

876879
Following is the code for binomial exponentiation.
877880
It is somewhat messy, because the emphasis is on efficiency.
@@ -984,8 +987,6 @@ The following table compares the times for `r15-test` with the three versions of
984987
| 7 | iterative `poly^n` | .98 | 28 |
985988
| 8 | binomial `poly^n` | .23 | 120 |
986989

987-
![t0010](images/B9780080571157500157/t0010.png)
988-
989990
As we remarked earlier, the general techniques of memoization, indexing, and compilation provide for dramatic speed-ups.
990991
However, in the end, they do not lead to the fastest program.
991992
Instead, the fastest version was achieved by throwing out the original rule-based program, replacing it with a canonical-form-based program, and fine-tuning the algorithms within that program, using mathematical analysis.
@@ -1072,7 +1073,7 @@ For example, the following three expressions are all equivalent :
10721073

10731074
sinxcosx-π2eix-e-ix2i
10741075

1075-
![si7_e](images/B9780080571157500157/si7_e.gif)
1076+
![si7_e](images/chapter15/si7_e.gif)
10761077

10771078
If we are interested in assuring we have a canonical form, the safest thing is to allow only *e**x*** and log(*x*).
10781079
All the other functions can be defined in terms of these two.

docs/chapter16.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,12 @@ After that we will return to the main core of EMYCIN, !!!(span) {:.smallcaps} th
9393
Finally, we will show how to add some medical knowledge to EMYCIN !!!(span) {:.smallcaps} to reconstruct MYCIN.
9494
!!!(span) {:.smallcaps} A glossary of the program is in [figure 16.1](#f0010).
9595

96-
![f16-01-9780080571157](images/B9780080571157500169/f16-01-9780080571157.jpg)
97-
Figure 16.1
98-
!!!(span) {:.fignum}
99-
Glossary for the EMYCIN
100-
!!!(span) {:.smallcaps}
101-
Program
96+
| []() |
97+
|---|
98+
| ![f16-01](images/chapter16/f16-01.jpg) |
99+
| Figure 16.1: Glossary for the EMYCIN Program |
100+
101+
*(ed: this could be a markdown table)*
102102

103103
## 16.1 Dealing with Uncertainty
104104
{:#s0010}
@@ -132,7 +132,7 @@ combine (A, B) =
132132

133133
A+B-AB;A,B>0A+B+AB;A,B<0A+B1-minAB;otherwise
134134

135-
![si1_e](images/B9780080571157500169/si1_e.gif)
135+
![si1_e](images/chapter16/si1_e.gif)
136136

137137
According to this formula, combine(.60,.40) = .76, which is a compromise between the extremes of .60 and 1.00.
138138
It is the same as the probability p(A or B), assuming that A and B are independent.
@@ -648,10 +648,11 @@ Finally, there is a level for organisms found in each culture.
648648
The current organism is stored under both the `organism` and `current-instance` keys.
649649
The context tree is shown in [figure 16.2](#f0015).
650650

651-
![f16-02-9780080571157](images/B9780080571157500169/f16-02-9780080571157.jpg)
652-
Figure 16.2
653-
!!!(span) {:.fignum}
654-
A Context Tree
651+
| []() |
652+
|---|
653+
| ![f16-02](images/chapter16/f16-02.jpg) |
654+
| Figure 16.2: A Context Tree |
655+
655656
```lisp
656657
(defun new-instance (context)
657658
```

0 commit comments

Comments
 (0)