ambit 0.10.1 → 0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|