ambit 0.10.1 → 0.11
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +10 -1
- data/README.rdoc +65 -18
- data/README.txt +65 -18
- data/examples/example.rb +43 -0
- data/lib/ambit.rb +30 -7
- metadata +7 -13
data/History.txt
CHANGED
@@ -1,4 +1,13 @@
|
|
1
|
-
=== 0.
|
1
|
+
=== 0.11 / 2012-10-12
|
2
|
+
|
3
|
+
* Additional documentation on side effects and rewinding.
|
4
|
+
|
5
|
+
* Fixed Ambit::trace and Ambit::untrace to work as described in the docs.
|
6
|
+
This breaks the (undocumented) ability to turn on tracing
|
7
|
+
generator-by-generator, but buys the ability to trace operation of the
|
8
|
+
anonymous generator used by Ambit::choose.
|
9
|
+
|
10
|
+
=== 0.10.1 / 2012-10-10
|
2
11
|
|
3
12
|
* Updated repo path -- no functional change.
|
4
13
|
|
data/README.rdoc
CHANGED
@@ -8,13 +8,8 @@ License:: 2-clause BSD-Style (see LICENSE.txt)
|
|
8
8
|
|
9
9
|
== DESCRIPTION:
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
<em>On Lisp</em>[1], or Section 4.3 of <em>SICP</em>[2].
|
14
|
-
|
15
|
-
Due to Ruby containing a true call/cc, this is a much straighter port of
|
16
|
-
Paul Graham's scheme version of this code than his Common Lisp or my C
|
17
|
-
versions are. :-)
|
11
|
+
Ambit is a ruby non-deterministic programming system with backtracking and
|
12
|
+
branch cut.
|
18
13
|
|
19
14
|
== REQUIREMENTS:
|
20
15
|
|
@@ -116,7 +111,7 @@ enumerable is returned <em>from the same call to Ambit::choose</em>:
|
|
116
111
|
Ambit::fail! unless a.even?
|
117
112
|
puts a
|
118
113
|
prints
|
119
|
-
|
114
|
+
2
|
120
115
|
(and only "2")
|
121
116
|
|
122
117
|
<em>This means that computation now proceeds as if that had been the value
|
@@ -181,21 +176,68 @@ prints
|
|
181
176
|
2
|
182
177
|
|
183
178
|
instead of only "2" -- the printing has already been done by the time we
|
184
|
-
call Ambit::fail!.
|
179
|
+
call Ambit::fail!.
|
180
|
+
|
181
|
+
Likewise, this code:
|
182
|
+
|
183
|
+
x = 1
|
184
|
+
y = Ambit::choose([1, 2, 3])
|
185
|
+
if y == 2
|
186
|
+
puts x
|
187
|
+
else
|
188
|
+
x = 42
|
189
|
+
end
|
190
|
+
Ambit::fail! unless a.even?
|
191
|
+
|
192
|
+
prints
|
193
|
+
42
|
194
|
+
|
195
|
+
, not +1+, as Ambit does not rewind the setting of 'x' after the first
|
196
|
+
return from Ambit::choose.
|
185
197
|
|
186
198
|
Such side effects can also be useful, however. This code:
|
187
199
|
|
188
200
|
i = 0
|
189
201
|
first = Ambit.choose(1..10)
|
202
|
+
i += 1
|
190
203
|
second = Ambit.choose(1..10)
|
204
|
+
i += 1
|
191
205
|
third = Ambit.choose(1..10)
|
192
206
|
i += 1
|
193
207
|
Ambit.fail! unless open_lock(first, second, third)
|
194
208
|
puts i
|
195
209
|
|
196
|
-
prints out the number of
|
210
|
+
prints out the number of values which were chosen in total (since +i+
|
197
211
|
remains incremented even when we rewind computation).
|
198
212
|
|
213
|
+
If we wanted to avoid this type of side effect, one option would be to use a
|
214
|
+
function argument to capture this setting, as function calls (and thus the
|
215
|
+
value of their arguments and local variables) are rewindable. This version,
|
216
|
+
for instance:
|
217
|
+
|
218
|
+
def try_first
|
219
|
+
i = 0
|
220
|
+
first = Ambit::choose(1..10)
|
221
|
+
try_second(i + 1, first)
|
222
|
+
end
|
223
|
+
|
224
|
+
def try_second i, first
|
225
|
+
second = Ambit::choose(1..10)
|
226
|
+
try_third(i + 1, first, second)
|
227
|
+
end
|
228
|
+
|
229
|
+
def try_third i, first, second
|
230
|
+
third = Ambit::choose(1..10)
|
231
|
+
Ambit.fail! unless open_lock(first, second, third)
|
232
|
+
puts i+1
|
233
|
+
end
|
234
|
+
|
235
|
+
try_first
|
236
|
+
|
237
|
+
will always print +3+ -- the number of values tried in the ultimately
|
238
|
+
successful series of choices, rather than the number of combinations tried
|
239
|
+
over all.
|
240
|
+
|
199
241
|
==== More Than One Answer
|
200
242
|
|
201
243
|
Often, more than one combination of choices is interesting to consider -- it
|
@@ -291,11 +333,11 @@ commit to all choices made so far.
|
|
291
333
|
|
292
334
|
==== Watching Ambit work
|
293
335
|
|
294
|
-
The
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
336
|
+
The class method Ambit::trace can be used to enable debug tracing of Ambit
|
337
|
+
operations. Repeated calls to Ambit::trace increase the verbosity of trace
|
338
|
+
output (though this has no effect in the current version), and a specific
|
339
|
+
trace level (as an integer) may also be passed to Generator#trace as an
|
340
|
+
optional argument.
|
299
341
|
|
300
342
|
Trace output is written to STDERR. Trace output can be disabled by
|
301
343
|
specifying a trace level of 0, or by calling Ambit::untrace.
|
@@ -413,11 +455,16 @@ a given N.
|
|
413
455
|
|
414
456
|
=== References
|
415
457
|
|
416
|
-
|
458
|
+
For more information on nondeterministic programming, see
|
459
|
+
|
460
|
+
* Abelson, Harold and Gerald Jay Sussman, <em>Structure and Interpretation
|
461
|
+
of Computer Programs, 2nd Edition</em>, Section 4.3, MIT Press, 1996.
|
462
|
+
Available online at http://mitpress.mit.edu/sicp/
|
417
463
|
|
418
|
-
|
464
|
+
* Graham, Paul, <em>On Lisp</em>, Chapter 22, Prentice Hall, 1993. Available
|
465
|
+
online at http://www.paulgraham.com/onlisp.html
|
419
466
|
|
420
|
-
|
467
|
+
* Sterling, Leon and Ehud Shapiro, <em>The Art of Prolog</em>, MIT Press, 1994
|
421
468
|
|
422
469
|
== LICENSE:
|
423
470
|
|
data/README.txt
CHANGED
@@ -8,13 +8,8 @@ License:: 2-clause BSD-Style (see LICENSE.txt)
|
|
8
8
|
|
9
9
|
== DESCRIPTION:
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
<em>On Lisp</em>[1], or Section 4.3 of <em>SICP</em>[2].
|
14
|
-
|
15
|
-
Due to Ruby containing a true call/cc, this is a much straighter port of
|
16
|
-
Paul Graham's scheme version of this code than his Common Lisp or my C
|
17
|
-
versions are. :-)
|
11
|
+
Ambit is a ruby non-deterministic programming system with backtracking and
|
12
|
+
branch cut.
|
18
13
|
|
19
14
|
== REQUIREMENTS:
|
20
15
|
|
@@ -116,7 +111,7 @@ enumerable is returned <em>from the same call to Ambit::choose</em>:
|
|
116
111
|
Ambit::fail! unless a.even?
|
117
112
|
puts a
|
118
113
|
prints
|
119
|
-
|
114
|
+
2
|
120
115
|
(and only "2")
|
121
116
|
|
122
117
|
<em>This means that computation now proceeds as if that had been the value
|
@@ -181,21 +176,68 @@ prints
|
|
181
176
|
2
|
182
177
|
|
183
178
|
instead of only "2" -- the printing has already been done by the time we
|
184
|
-
call Ambit::fail!.
|
179
|
+
call Ambit::fail!.
|
180
|
+
|
181
|
+
Likewise, this code:
|
182
|
+
|
183
|
+
x = 1
|
184
|
+
y = Ambit::choose([1, 2, 3])
|
185
|
+
if y == 2
|
186
|
+
puts x
|
187
|
+
else
|
188
|
+
x = 42
|
189
|
+
end
|
190
|
+
Ambit::fail! unless a.even?
|
191
|
+
|
192
|
+
prints
|
193
|
+
42
|
194
|
+
|
195
|
+
, not +1+, as Ambit does not rewind the setting of 'x' after the first
|
196
|
+
return from Ambit::choose.
|
185
197
|
|
186
198
|
Such side effects can also be useful, however. This code:
|
187
199
|
|
188
200
|
i = 0
|
189
201
|
first = Ambit.choose(1..10)
|
202
|
+
i += 1
|
190
203
|
second = Ambit.choose(1..10)
|
204
|
+
i += 1
|
191
205
|
third = Ambit.choose(1..10)
|
192
206
|
i += 1
|
193
207
|
Ambit.fail! unless open_lock(first, second, third)
|
194
208
|
puts i
|
195
209
|
|
196
|
-
prints out the number of
|
210
|
+
prints out the number of values which were chosen in total (since +i+
|
197
211
|
remains incremented even when we rewind computation).
|
198
212
|
|
213
|
+
If we wanted to avoid this type of side effect, one option would be to use a
|
214
|
+
function argument to capture this setting, as function calls (and thus the
|
215
|
+
value of their arguments and local variables) are rewindable. This version,
|
216
|
+
for instance:
|
217
|
+
|
218
|
+
def try_first
|
219
|
+
i = 0
|
220
|
+
first = Ambit::choose(1..10)
|
221
|
+
try_second(i + 1, first)
|
222
|
+
end
|
223
|
+
|
224
|
+
def try_second i, first
|
225
|
+
second = Ambit::choose(1..10)
|
226
|
+
try_third(i + 1, first, second)
|
227
|
+
end
|
228
|
+
|
229
|
+
def try_third i, first, second
|
230
|
+
third = Ambit::choose(1..10)
|
231
|
+
Ambit.fail! unless open_lock(first, second, third)
|
232
|
+
puts i+1
|
233
|
+
end
|
234
|
+
|
235
|
+
try_first
|
236
|
+
|
237
|
+
will always print +3+ -- the number of values tried in the ultimately
|
238
|
+
successful series of choices, rather than the number of combinations tried
|
239
|
+
over all.
|
240
|
+
|
199
241
|
==== More Than One Answer
|
200
242
|
|
201
243
|
Often, more than one combination of choices is interesting to consider -- it
|
@@ -291,11 +333,11 @@ commit to all choices made so far.
|
|
291
333
|
|
292
334
|
==== Watching Ambit work
|
293
335
|
|
294
|
-
The
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
336
|
+
The class method Ambit::trace can be used to enable debug tracing of Ambit
|
337
|
+
operations. Repeated calls to Ambit::trace increase the verbosity of trace
|
338
|
+
output (though this has no effect in the current version), and a specific
|
339
|
+
trace level (as an integer) may also be passed to Generator#trace as an
|
340
|
+
optional argument.
|
299
341
|
|
300
342
|
Trace output is written to STDERR. Trace output can be disabled by
|
301
343
|
specifying a trace level of 0, or by calling Ambit::untrace.
|
@@ -413,11 +455,16 @@ a given N.
|
|
413
455
|
|
414
456
|
=== References
|
415
457
|
|
416
|
-
|
458
|
+
For more information on nondeterministic programming, see
|
459
|
+
|
460
|
+
* Abelson, Harold and Gerald Jay Sussman, <em>Structure and Interpretation
|
461
|
+
of Computer Programs, 2nd Edition</em>, Section 4.3, MIT Press, 1996.
|
462
|
+
Available online at http://mitpress.mit.edu/sicp/
|
417
463
|
|
418
|
-
|
464
|
+
* Graham, Paul, <em>On Lisp</em>, Chapter 22, Prentice Hall, 1993. Available
|
465
|
+
online at http://www.paulgraham.com/onlisp.html
|
419
466
|
|
420
|
-
|
467
|
+
* Sterling, Leon and Ehud Shapiro, <em>The Art of Prolog</em>, MIT Press, 1994
|
421
468
|
|
422
469
|
== LICENSE:
|
423
470
|
|
data/examples/example.rb
CHANGED
@@ -59,3 +59,46 @@ rescue Ambit::ChoicesExhausted
|
|
59
59
|
end
|
60
60
|
|
61
61
|
find_boxes
|
62
|
+
|
63
|
+
Ambit::clear!
|
64
|
+
|
65
|
+
# Simple combination lock example, used in README
|
66
|
+
|
67
|
+
# test if we have the right combination
|
68
|
+
def open_lock x, y, z
|
69
|
+
[x, y, z] == [3, 7, 2]
|
70
|
+
end
|
71
|
+
|
72
|
+
# version with global variable -- counts calls to #choose
|
73
|
+
def try_combinations
|
74
|
+
i = 0
|
75
|
+
first = Ambit.choose(1..10)
|
76
|
+
i += 1
|
77
|
+
second = Ambit.choose(1..10)
|
78
|
+
i += 1
|
79
|
+
third = Ambit.choose(1..10)
|
80
|
+
i += 1
|
81
|
+
Ambit.fail! unless open_lock(first, second, third)
|
82
|
+
i
|
83
|
+
end
|
84
|
+
|
85
|
+
puts try_combinations
|
86
|
+
|
87
|
+
def try_first
|
88
|
+
i = 0
|
89
|
+
first = Ambit::choose(1..10)
|
90
|
+
try_second(i + 1, first)
|
91
|
+
end
|
92
|
+
|
93
|
+
def try_second i, first
|
94
|
+
second = Ambit::choose(1..10)
|
95
|
+
try_third(i + 1, first, second)
|
96
|
+
end
|
97
|
+
|
98
|
+
def try_third i, first, second
|
99
|
+
third = Ambit::choose(1..10)
|
100
|
+
Ambit.fail! unless open_lock(first, second, third)
|
101
|
+
i+1
|
102
|
+
end
|
103
|
+
|
104
|
+
puts try_first
|
data/lib/ambit.rb
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
|
8
8
|
module Ambit
|
9
9
|
|
10
|
-
VERSION = '0.
|
10
|
+
VERSION = '0.11'
|
11
11
|
|
12
12
|
# A ChoicesExhausted exception is raised if the outermost choose invocation of
|
13
13
|
# a Generator has run out of choices, indicating that no (more) solutions are possible.
|
@@ -15,6 +15,7 @@ module Ambit
|
|
15
15
|
end
|
16
16
|
|
17
17
|
class Generator
|
18
|
+
@@trace = 0
|
18
19
|
# Allocate a new private Generator. Usually not needed -- use Ambit::choose et al, instead.
|
19
20
|
#
|
20
21
|
# See "Private Generators" in the README for details
|
@@ -25,19 +26,23 @@ module Ambit
|
|
25
26
|
|
26
27
|
# Turn on tracing (to standard error) of Ambit operations
|
27
28
|
#
|
29
|
+
# intended for use by Ambit::trace
|
30
|
+
#
|
28
31
|
# The optional level argument sets the verbosity -- if not passed, each
|
29
32
|
# call to this method increases verbosity
|
30
|
-
def trace lvl=false
|
33
|
+
def self.trace lvl=false
|
31
34
|
if lvl
|
32
|
-
|
35
|
+
@@trace = lvl
|
33
36
|
else
|
34
|
-
|
37
|
+
@@trace = @trace + 1
|
35
38
|
end
|
36
39
|
end
|
37
40
|
|
38
41
|
# Turn off tracing (to standard error) of Ambit operations
|
39
|
-
|
40
|
-
|
42
|
+
#
|
43
|
+
# intended for use by Ambit::untrace
|
44
|
+
def self.untrace
|
45
|
+
@@trace = 0
|
41
46
|
end
|
42
47
|
|
43
48
|
# Clear all outstanding choices registered with this generator.
|
@@ -131,8 +136,26 @@ module Ambit
|
|
131
136
|
end
|
132
137
|
end
|
133
138
|
|
139
|
+
# Turn on tracing (to standard error) of Ambit operations
|
140
|
+
#
|
141
|
+
# See ``Watching Ambit Work'' in README.rdoc
|
142
|
+
#
|
143
|
+
# The optional level argument sets the verbosity -- if not passed, each
|
144
|
+
# call to this method increases verbosity
|
145
|
+
def self.trace lvl = false
|
146
|
+
Generator::trace lvl
|
147
|
+
end
|
148
|
+
|
149
|
+
# Turn off tracing (to standard error) of Ambit operations
|
150
|
+
#
|
151
|
+
# See ``Watching Ambit Work'' in README.rdoc
|
152
|
+
#
|
153
|
+
def self.untrace
|
154
|
+
Generator::untrace
|
155
|
+
end
|
156
|
+
|
134
157
|
# forward method invocations on this module to the default Generator.
|
135
|
-
def
|
158
|
+
def self.method_missing(sym, *args, &block) # :nodoc:
|
136
159
|
Ambit::Default_Generator.send(sym, *args, &block)
|
137
160
|
end
|
138
161
|
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ambit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 29
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
|
10
|
-
version: 0.10.1
|
8
|
+
- 11
|
9
|
+
version: "0.11"
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Jim Wise
|
@@ -15,7 +14,7 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2012-01-
|
17
|
+
date: 2012-01-12 00:00:00 Z
|
19
18
|
dependencies:
|
20
19
|
- !ruby/object:Gem::Dependency
|
21
20
|
name: rdoc
|
@@ -48,13 +47,8 @@ dependencies:
|
|
48
47
|
type: :development
|
49
48
|
version_requirements: *id002
|
50
49
|
description: |-
|
51
|
-
|
52
|
-
|
53
|
-
<em>On Lisp</em>[1], or Section 4.3 of <em>SICP</em>[2].
|
54
|
-
|
55
|
-
Due to Ruby containing a true call/cc, this is a much straighter port of
|
56
|
-
Paul Graham's scheme version of this code than his Common Lisp or my C
|
57
|
-
versions are. :-)
|
50
|
+
Ambit is a ruby non-deterministic programming system with backtracking and
|
51
|
+
branch cut.
|
58
52
|
email:
|
59
53
|
- jwise@draga.com
|
60
54
|
executables: []
|
@@ -113,6 +107,6 @@ rubyforge_project: ambit
|
|
113
107
|
rubygems_version: 1.8.13
|
114
108
|
signing_key:
|
115
109
|
specification_version: 3
|
116
|
-
summary:
|
110
|
+
summary: Ambit is a ruby non-deterministic programming system with backtracking and branch cut.
|
117
111
|
test_files:
|
118
112
|
- test/test_ambit.rb
|