-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patheinstein.lisp
executable file
·356 lines (298 loc) · 11 KB
/
einstein.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
(in-package :cl-user)
;;;Einsteins Riddle, see generic.lisp
;;;There are five houses in five different colours starting from left to right.
;;;In each house lives a person of a different nationality.
;;;These owners all drink a certain type of beverage,
;;;smoke a certain brand of cigarette and keep a certain type of pet.
;;;No two owners have the same pet, smoke the same brand or drink the same beverage.
;;;The question is: WHO OWNS THE FISH??? Hints:
;;;
;;;The Brit lives in the red house
;;;The Swede keeps dogs as pets
;;;The Dane drinks tea
;;;The green house is on the left of the white house
;;;The green house's owner drinks coffee
;;;The person who smokes Pall Mall rears birds
;;;The owner of the yellow house smokes Dunhill
;;;The man living in the centre house drinks milk
;;;The Norwegian lives in the first house
;;;The person who smokes Marlboro lives next to the one who keeps cats
;;;The person who keeps horses lives next to the person who smokes Dunhill
;;;The person who smokes Winfield drinks beer
;;;The German smokes Rothmans
;;;The Norwegian lives next to the blue house
;;;The person who smokes Marlboro has a neigbor who drinks water
;;;To get a solution, try (test-einstein)
;;;Run tests at least twice to get clos prepared
#-fast
(eval-when
#-:gcl (:compile-toplevel :execute :load-toplevel)
#+:gcl (compile eval load)
(proclaim '(optimize (speed 0) (safety 3) (space 0)(debug 3)(compilation-speed 0)))
)
#+fast
(eval-when
#-:gcl (:compile-toplevel :execute :load-toplevel)
#+:gcl (compile eval load)
(proclaim '(optimize (speed 3) (safety 0) (space 0)(debug 0)(compilation-speed 0)))
)
(defclass Einstein-Riddle-House (solution-element)
(
(nation :accessor riddle-house-nation :initform nil)
(color :accessor riddle-house-color :initform nil)
(animal :accessor riddle-house-animal :initform nil)
(cigarette :accessor riddle-house-cigarette :initform nil)
(drink :accessor riddle-house-drink :initform nil)
)
)
(defmethod show-house-result ((me Einstein-Riddle-House))
(format t "A house with ")
(format t "Nation ~10a " (riddle-house-nation me))
(format t "Color ~10a " (riddle-house-color me))
(format t "Animal ~10a "(riddle-house-animal me))
(format t "Cigarette ~10a "(riddle-house-cigarette me))
(format t "Drink ~10a~%" (riddle-house-drink me))
)
(defclass einstein-riddle-problem (SYMBOLIC-PROBLEM-SPECIFICATION)
()
)
(defmethod all-domains-extended ((me einstein-riddle-problem))
'((:nation (:british :swedish :norwegian :german :danish))
(:color (:red :green :yellow :blue :white))
(:animal (:dog :horse :cat :bird :fish))
(:cigarette (:marlboro :winfield :rothmans :pallmall :dunhill))
(:drink (:tea :coffee :milk :beer :water))
)
)
(defmethod initialize-instance :after ((me einstein-riddle-problem) &rest initargs)
(declare (ignore initargs))
(setf (my-constraints me)
(list
(make-instance 'TWO-VALUES-IN-HOUSE-CONSTRAINT
:SELECTOR-ONE :nation
:value-one :BRITISH
:SELECTOR-two :color
:value-two :red)
(make-instance 'TWO-VALUES-IN-HOUSE-CONSTRAINT
:SELECTOR-ONE :nation
:value-one :SWEDISH
:SELECTOR-two :animal
:value-two :dog)
(make-instance 'TWO-VALUES-IN-HOUSE-CONSTRAINT
:SELECTOR-ONE :nation
:value-one :danish
:SELECTOR-two :drink
:value-two :tea)
(make-instance 'DIRECTED-DISTANCE-NEIGHBOUR-CONSTRAINT
:SELECTOR-ONE :color
:VALUE-ONE :green
:SELECTOR-TWO :color
:VALUE-TWO :white
:distance 1)
(make-instance 'TWO-VALUES-IN-HOUSE-CONSTRAINT
:SELECTOR-ONE :color
:value-one :green
:SELECTOR-two :drink
:value-two :coffee)
(make-instance 'TWO-VALUES-IN-HOUSE-CONSTRAINT
:SELECTOR-ONE :animal
:value-one :bird
:SELECTOR-two :cigarette
:value-two :pallmall)
(make-instance 'TWO-VALUES-IN-HOUSE-CONSTRAINT
:SELECTOR-ONE :color
:value-one :yellow
:SELECTOR-two :CIGARETTE
:value-two :dunhill)
(make-instance 'POSITION-AND-PROPERTY-CONSTRAINT
:POSITION 2
:SELECTOR-ONE :drink
:VALUE-ONE :milk)
(make-instance 'POSITION-AND-PROPERTY-CONSTRAINT
:POSITION 0
:SELECTOR-ONE :NATION
:VALUE-ONE :NORWEGIAN)
(make-instance 'NEIGHBOUR-CONSTRAINT
:SELECTOR-ONE :ANIMAL
:value-one :CAT
:SELECTOR-two :CIGARETTE
:value-two :MARLBORO)
(make-instance 'NEIGHBOUR-CONSTRAINT
:SELECTOR-ONE :ANIMAL
:value-one :HORSE
:SELECTOR-two :CIGARETTE
:value-two :DUNHILL)
(make-instance 'TWO-VALUES-IN-HOUSE-CONSTRAINT
:SELECTOR-ONE :CIGARETTE
:value-one :WINFIELD
:SELECTOR-two :DRINK
:value-two :beer)
(make-instance 'TWO-VALUES-IN-HOUSE-CONSTRAINT
:SELECTOR-ONE :nation
:value-one :german
:SELECTOR-two :CIGARETTE
:value-two :ROTHMANS)
(make-instance 'NEIGHBOUR-CONSTRAINT
:SELECTOR-ONE :nation
:value-one :NORWEGIAN
:SELECTOR-two :color
:value-two :blue)
(make-instance 'NEIGHBOUR-CONSTRAINT
:SELECTOR-ONE :CIGARETTE
:value-one :MARLBORO
:SELECTOR-two :DRINK
:value-two :WATER))))
(defclass einstein-partial-solution (riddle-partial-solution)
(
)
)
(defmethod partial-solution-class ((me einstein-riddle-problem))
(find-class 'einstein-partial-solution))
(defmethod solution-element-class ((me einstein-riddle-problem))
(find-class 'Einstein-Riddle-House))
#+old
(def-closures
+einstein-setf-mapper+
(list 0 #'(setf riddle-house-nation)
1 #'(setf riddle-house-color)
2 #'(setf riddle-house-animal)
3 #'(setf riddle-house-cigarette)
4 #'(setf riddle-house-drink)
))
#+old
(defmethod element-mapper ((me einstein-partial-solution))
+einstein-setf-mapper+)
#+old
(def-closures
+einstein-property-mapper+
(list :nation #'riddle-house-nation
:color #'riddle-house-color
:drink #'riddle-house-drink
:animal #'riddle-house-animal
:cigarette #'riddle-house-cigarette))
#+old
(defmethod element-property-mapper ((me EINSTEIN-PARTIAL-SOLUTION))
+einstein-property-mapper+)
(defmethod read-value-for-key ((me Einstein-Riddle-House) key)
(ecase key
(:nation (riddle-house-nation me))
(:color (riddle-house-color me))
(:animal (riddle-house-animal me))
(:cigarette (riddle-house-cigarette me))
(:drink (riddle-house-drink me))))
(defmethod EXPAND-PARTIAL-SOLUTION ((me Einstein-Riddle-House)
index value)
(ecase index
(0 (setf (riddle-house-nation me) value))
(1 (setf (riddle-house-color me) value))
(2 (setf (riddle-house-animal me) value))
(3 (setf (riddle-house-cigarette me) value))
(4 (setf (riddle-house-drink me) value))))
(defclass einstein-riddle-solver-backtracking (riddle-solver)
()
(:default-initargs
:specification (make-instance 'einstein-riddle-problem)))
;;; Test for Einsteins Riddle
(defun test-einstein (&optional (print t))
(test-backtracking "Einstein Backtracking" (make-instance 'EINSTEIN-RIDDLE-SOLVER-BACKTRACKING) print)
)
#|
(test-backtracking "Einstein Backtracking" (make-instance 'EINSTEIN-RIDDLE-SOLVER-BACKTRACKING) t)
(defparameter *solver* (make-instance 'einstein-riddle-solver-backtracking))
(defparameter *test* (GENERATE-EMPTY-SOLUTION *solver*))
(EXPAND-PARTIAL-SOLUTION *test* '(:NORWEGIAN :DANISH :BRITISH :GERMAN :SWEDISH) 0)
(PARTIAL-SOLUTION-CORRECT *solver* *test*)
(EXPAND-PARTIAL-SOLUTION *test* '(:YELLOW :BLUE :RED :GREEN :white) 1)
(PARTIAL-SOLUTION-CORRECT *solver* *test*)
(EXPAND-PARTIAL-SOLUTION *test* '(:CAT :HORSE :BIRD :FISH :DOG) 2)
(PARTIAL-SOLUTION-CORRECT *solver* *test*)
(EXPAND-PARTIAL-SOLUTION *test* '(:DUNHILL :MARLBORO :pallmall :ROTHMANS :WINFIELD) 3)
(PARTIAL-SOLUTION-CORRECT *solver* *test*)
(EXPAND-PARTIAL-SOLUTION *test* '(:WATER :TEA :MILK :COFFEE :BEER) 4)
(PARTIAL-SOLUTION-CORRECT *solver* *test*)
(time (PARTIAL-SOLUTION-CORRECT *solver* *test*))
|#
#|
(prof:with-profiling (:type :count-only)
(test-einstein))
(prof:show-call-counts)
(prof:with-profiling (:type :time)
(test-einstein))
(prof:show-flat-profile)
(prof:show-call-graph)
|#
#|
(dotimes (x 3)
#+:allegro
(mp:without-scheduling
(test-einstein))
#+:lispworks
(mp:without-preemption
(test-einstein))
#-(or :allegro :lispworks)
(test-einstein)
)
; cpu time (non-gc) 830 msec user, 0 msec system
; cpu time (gc) 0 msec user, 0 msec system
; cpu time (total) 830 msec user, 0 msec system
; real time 830 msec
; space allocation:
; 8,468 cons cells, 384 other bytes, 0 static bytes
Test:Einstein Backtracking
The solution in 31612 tries testing 185014 constraints is:
A house with Nation NORWEGIAN Color YELLOW Animal CAT Cigarette DUNHILL Drink WATER
A house with Nation DANISH Color BLUE Animal HORSE Cigarette MARLBORO Drink TEA
A house with Nation BRITISH Color RED Animal BIRD Cigarette PALLMALL Drink MILK
A house with Nation GERMAN Color GREEN Animal FISH Cigarette ROTHMANS Drink COFFEE
A house with Nation SWEDISH Color WHITE Animal DOG Cigarette WINFIELD Drink BEER
|#
#|
Original Solution
(#S(UNIT NATION NORWEGIAN HOUSE YELLOW ANIMAL CAT CIGARETTE DUNHILL DRINK WATER)
#S(UNIT NATION DANISH HOUSE BLUE ANIMAL HORSE CIGARETTE MARLBORO DRINK TEA)
#S(UNIT NATION BRITISH HOUSE RED ANIMAL BIRD CIGARETTE PALLMALL DRINK MILK)
#S(UNIT NATION GERMAN HOUSE GREEN ANIMAL FISH CIGARETTE ROTHMANS DRINK COFFEE)
#S(UNIT NATION SWEDISH HOUSE WHITE ANIMAL DOG CIGARETTE WINFIELD DRINK BEER))
; cpu time (non-gc) 770 msec user, 0 msec system
; cpu time (gc) 220 msec user, 0 msec system
; cpu time (total) 990 msec user, 0 msec system
; real time 990 msec
; space allocation:
; 346,860 cons cells, 6,289,576 other bytes, 1136 static bytes
|#
(defclass einstein-riddle-solver-gsat (gsat-riddle-solver)
()
(:default-initargs
:specification (make-instance 'einstein-riddle-problem)))
(defun test-gsat-einstein (&optional (print t))
(TEST-GSAT "Einstein Gsat" (make-instance 'EINSTEIN-RIDDLE-SOLVER-GSAT :MAX-FLIPS 500 :max-tries 50) print)
)
#|
(TEST-GSAT-EINSTEIN)
(dotimes (x 10)
(TEST-GSAT-EINSTEIN))
(setq *solver* (make-instance 'GSAT-SOLVER-EINSTEIN))
(GUESS-A-SOLUTION *SOLVER*)
|#
#|
ACL only
Profiler
(defparameter *der* nil)
(setq *der*
(let ((solver (make-instance 'gsat-solver-einstein :MAX-FLIPS 500 :max-tries 50))
)
(PROF:WITH-PROFILING (:type :time)
(solve-it solver))))
(PROF:WITH-PROFILING (:type :time)
(TEST-GSAT-EINSTEIN))
(prof:show-flat-profile)
(prof:show-call-graph)
(setq *der*
(let ((solver (make-instance 'gsat-solver-einstein :MAX-FLIPS 500 :max-tries 50))
)
(PROF:WITH-PROFILING (:type :COUNT-ONLY)
(solve-it solver))))
(PROF:WITH-PROFILING (:type :count-only)
(TEST-GSAT-EINSTEIN))
(PROF:SHOW-CALL-COUNTS)
|#