-
Notifications
You must be signed in to change notification settings - Fork 2
/
workspace.lisp
410 lines (327 loc) · 15.8 KB
/
workspace.lisp
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
;---------------------------------------------
; WORKSPACE: This file contains flavor definitions and methods for the
; workspace.
;---------------------------------------------
(in-package 'user)
(defflavor workspace
; The workspace contains a list of replacements (mappings from the
; initial string to the modified string, e.g., from "abc" to "abd"),
; a vector of correspondences (mappings from the initial-string to the
; target string, e.g., from "abc" to "pqrs"), and an array of proposed
; correspondences.
((replacement-list nil) proposed-correspondence-array
correspondence-vector)
()
:gettable-instance-variables
:settable-instance-variables
:initable-instance-variables)
;---------------------------------------------
(defmethod (workspace :proposed-bond-list) ()
; Returns a list of the proposed bonds on the workspace.
(append (send *initial-string* :proposed-bond-list)
(send *target-string* :proposed-bond-list)))
;---------------------------------------------
(defmethod (workspace :bond-list) ()
; Returns a list of the built bonds on the workspace.
(append (send *initial-string* :bond-list)
(send *target-string* :bond-list)))
;---------------------------------------------
(defmethod (workspace :proposed-group-list) ()
; Returns a list of the proposed groups on the workspace.
(append (send *initial-string* :proposed-group-list)
(send *target-string* :proposed-group-list)))
;---------------------------------------------
(defmethod (workspace :group-list) ()
; Returns a list of the built groups on the workspace.
(append (send *initial-string* :group-list)
(send *target-string* :group-list)))
;---------------------------------------------
(defmethod (workspace :proposed-correspondence-list) ()
; Returns a list of the proposed-correspondences on the workspace.
(flatten (array-to-list proposed-correspondence-array)))
;---------------------------------------------
(defmethod (workspace :correspondence-list) ()
; Returns a list of the built correspondences on the workspace.
(flatten (vector-to-list correspondence-vector)))
;---------------------------------------------
(defmethod (workspace :add-replacement) (r)
; Adds a replacement to the workspace's list of replacements.
(push r replacement-list))
;---------------------------------------------
(defmethod (workspace :add-proposed-correspondence) (c)
; Adds a proposed-correspondence to the workspace's array of
; proposed-correspondences, using the string-numbers of the two
; objects as indices.
(aset (send self :proposed-correspondence-array)
(send (send c :obj1) :string-number)
(send (send c :obj2) :string-number)
(cons c (aref (send self :proposed-correspondence-array)
(send (send c :obj1) :string-number)
(send (send c :obj2) :string-number)))))
;---------------------------------------------
(defmethod (workspace :delete-proposed-correspondence) (c)
; Deletes a proposed-correspondence from the workspace's array of
; proposed-correspondences.
(aset (send self :proposed-correspondence-array)
(send (send c :obj1) :string-number)
(send (send c :obj2) :string-number)
(remove c (aref (send self :proposed-correspondence-array)
(send (send c :obj1) :string-number)
(send (send c :obj2) :string-number)))))
;---------------------------------------------
(defmethod (workspace :add-correspondence) (c)
; Adds a correspondence to the workspace's vector of
; built correspondences, using the string-number of the initial-string
; object as an index. Each object can have at most one built
; correspondence (though more than one proposed correspondences) so it is not
; necessary to store the built correspondences in an array.
(vset (send self :correspondence-vector)
(send (send c :obj1) :string-number) c))
;---------------------------------------------
(defmethod (workspace :delete-correspondence) (c)
; Deletes a correspondence from the workspace's vector of
; built correspondences.
(vset (send self :correspondence-vector)
(send (send c :obj1) :string-number) nil))
;---------------------------------------------
(defmethod (workspace :correspondence-present?)
(c &aux existing-correspondence)
; Returns t if the given correspondence exists on the workspace.
(if* (not (null (send (send c :obj1) :correspondence)))
then (setq existing-correspondence (send (send c :obj1) :correspondence))
(if* (eq (send existing-correspondence :obj2) (send c :obj2))
then existing-correspondence
else nil)
else nil))
;---------------------------------------------
(defmethod (workspace :slippage-present?) (s)
; Returns t if the given slippage exists on the workspace.
(loop for slippage in (send self :slippage-list)
when (and (eq (send s :descriptor1) (send slippage :descriptor1))
(eq (send s :descriptor2) (send slippage :descriptor2)))
return t
finally (return nil)))
;---------------------------------------------
(defmethod (workspace :object-list) ()
; Returns a list of all the objects (letters and groups) on the
; workspace.
(append (send *initial-string* :object-list)
(send *target-string* :object-list)))
;---------------------------------------------
(defmethod (workspace :letter-list) ()
; Returns a list of all the letters on the workspace.
(append (send *initial-string* :letter-list)
(send *target-string* :letter-list)))
;---------------------------------------------
(defmethod (workspace :structure-list) ()
; Returns a list of all the structures on the workspace.
(append (send self :bond-list)
(send self :group-list)
(send self :correspondence-list)
(if* *rule* then (list *rule*) else nil)))
;---------------------------------------------
(defmethod (workspace :structure-in-snag-structure-list?) (s)
; This method is used after a snag has been hit and the temperature has
; been clamped to determine whether or not to release the temperature
; clamp. This method is called from the function "update-everything"
; in the file "run.l". Returns t if the given structure is in the list of
; structures that were present when the last snag was hit. (If this method
; returns nil, that is, this structure was built since the snag was hit,
; then there is some chance that the temperature clamp will be released.)
(cond ((typep s 'bond)
(loop for structure in *snag-structure-list*
when (typep structure 'bond) do
(if* (and (eq (send structure :from-obj) (send s :from-obj))
(eq (send structure :to-obj) (send s :to-obj))
(eq (send structure :bond-category)
(send s :bond-category))
(eq (send structure :direction-category)
(send s :direction-category)))
then (return t))))
((typep s 'group)
(loop for structure in *snag-structure-list*
when (typep structure 'group) do
(if* (and (eq (send structure :left-obj) (send s :left-obj))
(eq (send structure :right-obj) (send s :right-obj))
(eq (send structure :group-category)
(send s :group-category))
(eq (send structure :direction-category)
(send s :direction-category)))
then (return t))))
((typep s 'correspondence)
(loop for structure in *snag-structure-list*
when (typep structure 'correspondence) do
(if* (and (eq (send structure :obj1) (send s :obj1))
(eq (send structure :obj2) (send s :obj2))
(>= (length (send structure
:relevant-distinguishing-cms))
(length (send s :relevant-distinguishing-cms))))
then (return t))))
((typep s 'rule)
(loop for structure in *snag-structure-list*
when (typep structure 'rule)
return (rule-equal? structure s)))))
;---------------------------------------------
(defmethod (workspace :random-string) ()
; Returns either the initial-string or the target string, chosen at random.
(random-list-item (list *initial-string* *target-string*)))
;---------------------------------------------
(defmethod (workspace :random-object) ()
; Returns a random object on the workspace.
(random-list-item (send self :object-list)))
;---------------------------------------------
(defmethod (workspace :random-group) ()
; Returns a random group on the workspace.
(random-list-item (send self :group-list)))
;---------------------------------------------
(defmethod (workspace :random-correspondence) ()
; Returns a random correspondence on the workspace.
(random-list-item (send self :correspondence-list)))
;---------------------------------------------
(defmethod (workspace :choose-object) (method &aux value-list)
; Returns an object on the workspace chosen probabilistically
; (adjusted for temperature) according to the given method.
(setq value-list (send-method-to-list (send self :object-list) method))
(nth (select-list-position (get-temperature-adjusted-value-list value-list))
(send self :object-list)))
;---------------------------------------------
(defmethod (workspace :null-replacement?) ()
; Returns t if there is at least one letter in the initial string
; that doesn't yet have a replacement.
(loop for letter in (send *initial-string* :letter-list)
when (null (send letter :replacement)) return t
finally (return nil)))
;---------------------------------------------
(defmethod (workspace :unrelated-objects) (&aux num-of-bonds result)
; Returns a list of all the objects on the workspace that have at least one
; bond-slot open. Leftmost and rightmost objects have one bond-slot,
; and other objects have two bond-slots (one on the left and one on the
; right).
(loop for object in (send self :object-list) do
(if* (and (not (send object :spans-whole-string?))
(null (send object :group)))
then (setq num-of-bonds
(length (append (send object :incoming-bonds)
(send object :outgoing-bonds))))
(if* (or (send object :leftmost-in-string?)
(send object :rightmost-in-string?))
then (if* (= num-of-bonds 0) then (push object result))
else (if* (< num-of-bonds 2) then (push object result)))))
result)
;---------------------------------------------
(defmethod (workspace :ungrouped-objects) ()
; Returns a list of all the objects on the workspace that are not in a group.
(loop for object in (send self :object-list)
when (and (not (send object :spans-whole-string?))
(null (send object :group))) collect object))
;---------------------------------------------
(defmethod (workspace :ungrouped-bonds) ()
; Returns a list of all the bonds on the workspace that are not in groups.
; A bond which is not in a group but both of whose objects are in groups
; is considered to be grouped.
(loop for bond in (send self :bond-list)
when (or (null (send (send bond :from-obj) :group))
(null (send (send bond :to-obj) :group)))
collect bond))
;---------------------------------------------
(defmethod (workspace :unreplaced-objects) ()
; Returns a list of all the objects on the initial-string that
; don't have a replacement.
(loop for letter in (send *initial-string* :letter-list)
when (null (send letter :replacement)) collect letter))
;---------------------------------------------
(defmethod (workspace :uncorresponding-objects) ()
; Returns a list of all the objects on the workspace that
; don't have a correspondence.
(loop for object in (send self :object-list)
when (null (send object :correspondence)) collect object))
;---------------------------------------------
(defmethod (workspace :rough-num-of-unrelated-objects) (&aux n)
; Returns either 'few, 'medium, or 'many. This method is used for
; "self-watching" in the function "get-num-of-codelets-to-post" in the file
; "formulas.l" -- for deciding the number of bond-scout codelets that
; should be posted.
(setq n (length (send self :unrelated-objects)))
(cond ((< n (blur 2)) 'few)
((< n (blur 4)) 'medium)
(t 'many)))
;---------------------------------------------
(defmethod (workspace :rough-num-of-ungrouped-objects) (&aux n)
; Returns either 'few, 'medium, or 'many. This method is used for
; "self-watching" in the function "get-num-of-codelets-to-post" in the file
; "formulas.l" -- for deciding the number of group-scout codelets that
; should be posted.
(setq n (length (send self :ungrouped-objects)))
(cond ((< n (blur 2)) 'few)
((< n (blur 4)) 'medium)
(t 'many)))
;---------------------------------------------
(defmethod (workspace :rough-num-of-unreplaced-objects) (&aux n)
; Returns either 'few, 'medium, or 'many. This method is used for
; "self-watching" in the function "get-num-of-codelets-to-post" in the file
; "formulas.l" -- for deciding the number of replacement-building codelets that
; should be posted.
(setq n (length (send self :unreplaced-objects)))
(cond ((< n (blur 2)) 'few)
((< n (blur 4)) 'medium)
(t 'many)))
;---------------------------------------------
(defmethod (workspace :rough-num-of-uncorresponding-objects) (&aux n)
; Returns either 'few, 'medium, or 'many. This method is used for
; "self-watching" in the function "get-num-of-codelets-to-post" in the file
; "formulas.l" -- for deciding the number of correspondence-scout codelets
; that should be posted.
(setq n (length (send self :uncorresponding-objects)))
(cond ((< n (blur 2)) 'few)
((< n (blur 4)) 'medium)
(t 'many)))
;---------------------------------------------
(defmethod (workspace :rough-importance-of-uncorresponding-objects)
(&aux uncorresponding-objects n)
; Returns either 'low, 'medium, or 'high.
(setq uncorresponding-objects (send self :uncorresponding-objects))
(if* (null uncorresponding-objects)
then 'low
else (setq n (list-max (send-method-to-list uncorresponding-objects
:relative-importance)))
(cond ((< n (blur 20)) 'low)
((< n (blur 40)) 'medium)
(t 'high))))
;---------------------------------------------
(defmethod (workspace :delete-proposed-structure) (s)
; Deletes the given proposed structure from the workspace.
(cond ((typep s 'bond)
(send (send s :string) :delete-proposed-bond s))
((typep s 'group) (send (send s :string) :delete-proposed-group s))
((typep s 'correspondence)
(send self :delete-proposed-correspondence s))))
;---------------------------------------------
(defmethod (workspace :slippage-list) ()
; Returns a list of all the slippages in all the correspondences.
(flatten (send-method-to-list (send self :correspondence-list)
:slippage-list)))
;---------------------------------------------
(defmethod (workspace :intra-string-unhappiness) ()
; Returns a weighted average of the intra-string unhappiness of objects
; on the workspace (weighted by each object's relative importance in the
; string.
(min 100 (/ (loop for obj in (send self :object-list)
sum (* (send obj :relative-importance)
(send obj :intra-string-unhappiness))) 200)))
;---------------------------------------------
(defmethod (workspace :inter-string-unhappiness) ()
; Returns a weighted average of the inter-string unhappiness of objects
; on the workspace (weighted by each object's relative importance in the
; string.
(min 100 (/ (loop for obj in (send self :object-list)
sum (* (send obj :relative-importance)
(send obj :inter-string-unhappiness))) 200)))
;---------------------------------------------
(defmethod (workspace :total-unhappiness) ()
; Returns a weighted average of the total unhappiness of objects
; on the workspace, weighted by each object's relative importance in the
; string.
(min 100 (/ (loop for obj in (send self :object-list)
sum (* (send obj :relative-importance)
(send obj :total-unhappiness))) 200)))
;---------------------------------------------