ambit 0.10.1 → 0.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/History.txt +10 -1
  2. data/README.rdoc +65 -18
  3. data/README.txt +65 -18
  4. data/examples/example.rb +43 -0
  5. data/lib/ambit.rb +30 -7
  6. metadata +7 -13
@@ -1,4 +1,13 @@
1
- === 0.10.1 / 2011-04-26
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
 
@@ -8,13 +8,8 @@ License:: 2-clause BSD-Style (see LICENSE.txt)
8
8
 
9
9
  == DESCRIPTION:
10
10
 
11
- This is an all-ruby implementation of choose/fail nondeterministic
12
- programming with branch cut, as described in Chapter 22 of Paul Graham's
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
- 2
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 combinations which were tried in total (since +i+
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 methods Ambit::trace and Ambit::untrace can be used to enable debug
295
- tracing of Ambit operations. Repeated calls to Ambit::trace increase the
296
- verbosity of trace output (though this has no effect in the current
297
- version), and a specific trace level (as an integer) may also be passed to
298
- Ambit::trace as an optional argument.
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
- [1] Graham, Paul, <em>On Lisp</em>, Prentice Hall, 1993. Available online at http://www.paulgraham.com/onlisp.html
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
- [2] Abelson, Harold and Gerald Jay Sussman, <em>Structure and Interpretation of Computer Programs, 2nd Edition</em>, MIT Press, 1996. Available online at http://mitpress.mit.edu/sicp/
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
- [3] Sterling, Leon and Ehud Shapiro, <em>The Art of Prolog</em>, MIT Press, 1994
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
- This is an all-ruby implementation of choose/fail nondeterministic
12
- programming with branch cut, as described in Chapter 22 of Paul Graham's
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
- 2
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 combinations which were tried in total (since +i+
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 methods Ambit::trace and Ambit::untrace can be used to enable debug
295
- tracing of Ambit operations. Repeated calls to Ambit::trace increase the
296
- verbosity of trace output (though this has no effect in the current
297
- version), and a specific trace level (as an integer) may also be passed to
298
- Ambit::trace as an optional argument.
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
- [1] Graham, Paul, <em>On Lisp</em>, Prentice Hall, 1993. Available online at http://www.paulgraham.com/onlisp.html
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
- [2] Abelson, Harold and Gerald Jay Sussman, <em>Structure and Interpretation of Computer Programs, 2nd Edition</em>, MIT Press, 1996. Available online at http://mitpress.mit.edu/sicp/
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
- [3] Sterling, Leon and Ehud Shapiro, <em>The Art of Prolog</em>, MIT Press, 1994
467
+ * Sterling, Leon and Ehud Shapiro, <em>The Art of Prolog</em>, MIT Press, 1994
421
468
 
422
469
  == LICENSE:
423
470
 
@@ -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
@@ -7,7 +7,7 @@
7
7
 
8
8
  module Ambit
9
9
 
10
- VERSION = '0.10.1'
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
- @trace = lvl
35
+ @@trace = lvl
33
36
  else
34
- @trace = @trace + 1
37
+ @@trace = @trace + 1
35
38
  end
36
39
  end
37
40
 
38
41
  # Turn off tracing (to standard error) of Ambit operations
39
- def untrace
40
- @trace = 0
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 Ambit::method_missing(sym, *args, &block) # :nodoc:
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: 53
4
+ hash: 29
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 10
9
- - 1
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-10 00:00:00 Z
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
- This is an all-ruby implementation of choose/fail nondeterministic
52
- programming with branch cut, as described in Chapter 22 of Paul Graham's
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: This is an all-ruby implementation of choose/fail nondeterministic programming with branch cut, as described in Chapter 22 of Paul Graham's <em>On Lisp</em>[1], or Section 4.3 of <em>SICP</em>[2]
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