cudd-rb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/CHANGELOG.md +5 -0
  2. data/Gemfile +12 -0
  3. data/Gemfile.lock +26 -0
  4. data/LICENCE.md +22 -0
  5. data/Manifest.txt +15 -0
  6. data/README.md +7 -0
  7. data/Rakefile +11 -0
  8. data/cudd-rb.gemspec +188 -0
  9. data/cudd-rb.noespec +30 -0
  10. data/lib/cudd-rb/bdd.rb +68 -0
  11. data/lib/cudd-rb/cube.rb +94 -0
  12. data/lib/cudd-rb/errors.rb +4 -0
  13. data/lib/cudd-rb/interfaces/bdd.rb +334 -0
  14. data/lib/cudd-rb/interfaces/root.rb +35 -0
  15. data/lib/cudd-rb/loader.rb +1 -0
  16. data/lib/cudd-rb/manager.rb +78 -0
  17. data/lib/cudd-rb/version.rb +14 -0
  18. data/lib/cudd-rb/wrapper.rb +58 -0
  19. data/lib/cudd-rb.rb +46 -0
  20. data/spec/cube/test_equality.rb +22 -0
  21. data/spec/cube/test_hash.rb +34 -0
  22. data/spec/cube/test_new.rb +49 -0
  23. data/spec/cube/test_to_a012.rb +34 -0
  24. data/spec/cube/test_to_bdd.rb +42 -0
  25. data/spec/cube/test_to_cube.rb +18 -0
  26. data/spec/cube/test_to_dnf.rb +55 -0
  27. data/spec/cube/test_to_hash.rb +34 -0
  28. data/spec/cube/test_to_truths.rb +34 -0
  29. data/spec/cudd/test_manager.rb +35 -0
  30. data/spec/interfaces/bdd/test_and.rb +14 -0
  31. data/spec/interfaces/bdd/test_bdd2cube.rb +32 -0
  32. data/spec/interfaces/bdd/test_bdd2dnf.rb +39 -0
  33. data/spec/interfaces/bdd/test_cofactor.rb +44 -0
  34. data/spec/interfaces/bdd/test_cube.rb +61 -0
  35. data/spec/interfaces/bdd/test_cube2bdd.rb +22 -0
  36. data/spec/interfaces/bdd/test_each_cube.rb +79 -0
  37. data/spec/interfaces/bdd/test_eval.rb +76 -0
  38. data/spec/interfaces/bdd/test_exist.rb +24 -0
  39. data/spec/interfaces/bdd/test_forall.rb +24 -0
  40. data/spec/interfaces/bdd/test_is_complement.rb +26 -0
  41. data/spec/interfaces/bdd/test_ite.rb +18 -0
  42. data/spec/interfaces/bdd/test_ith_var.rb +34 -0
  43. data/spec/interfaces/bdd/test_ith_vars.rb +40 -0
  44. data/spec/interfaces/bdd/test_new_var.rb +36 -0
  45. data/spec/interfaces/bdd/test_new_vars.rb +45 -0
  46. data/spec/interfaces/bdd/test_not.rb +18 -0
  47. data/spec/interfaces/bdd/test_one.rb +26 -0
  48. data/spec/interfaces/bdd/test_one_cube.rb +35 -0
  49. data/spec/interfaces/bdd/test_or.rb +14 -0
  50. data/spec/interfaces/bdd/test_restrict.rb +26 -0
  51. data/spec/interfaces/bdd/test_satisfiable.rb +33 -0
  52. data/spec/interfaces/bdd/test_satisfied.rb +40 -0
  53. data/spec/interfaces/bdd/test_size.rb +33 -0
  54. data/spec/interfaces/bdd/test_support.rb +66 -0
  55. data/spec/interfaces/bdd/test_var_index.rb +26 -0
  56. data/spec/interfaces/bdd/test_var_name.rb +32 -0
  57. data/spec/interfaces/bdd/test_var_names.rb +25 -0
  58. data/spec/interfaces/bdd/test_zero.rb +26 -0
  59. data/spec/manager/test_interface.rb +49 -0
  60. data/spec/shared/a_bdd.rb +15 -0
  61. data/spec/spec_helper.rb +45 -0
  62. data/spec/test_cudd-rb.rb +8 -0
  63. data/spec/wrapper/test_assumptions.rb +28 -0
  64. data/tasks/gem.rake +73 -0
  65. data/tasks/spec_test.rake +71 -0
  66. data/tasks/unit_test.rake +76 -0
  67. data/tasks/yard.rake +51 -0
  68. metadata +218 -0
@@ -0,0 +1,334 @@
1
+ module Cudd
2
+ module Interface
3
+ module BDD
4
+
5
+ ### BDD CREATION ###################################################################
6
+
7
+ # Coerce `pointer` to a BDD
8
+ def bdd(pointer, &error_handler)
9
+ return pointer if Cudd::BDD===pointer
10
+ if FFI::Pointer::NULL==pointer
11
+ raise Cudd::Error, "NULL pointer for BDD" unless error_handler
12
+ error_handler.call
13
+ end
14
+ m = self
15
+ pointer.tap do |p|
16
+ p.instance_eval{ @manager = m }
17
+ p.extend(Cudd::BDD)
18
+ end
19
+ end
20
+
21
+ ### REFERENCE COUNT ################################################################
22
+
23
+ # @see Cudd_Ref
24
+ def ref(f)
25
+ Wrapper.Ref(f)
26
+ f
27
+ end
28
+
29
+ # @see Cudd_Deref, Cudd_RecursiveDeref
30
+ #
31
+ # Uses `Cudd_RecursiveDeref` if `recursive` is true (defauts), decreasing
32
+ # reference counts of all children of `f`. Uses `Cudd_Deref` otherwise
33
+ # (use only if your are sure).
34
+ def deref(f, recursive = true)
35
+ recursive ? Wrapper.RecursiveDeref(native_manager, f) : Wrapper.Deref(f)
36
+ f
37
+ end
38
+
39
+ ### VARS ###########################################################################
40
+
41
+ # Returns the variable names
42
+ def var_names
43
+ @var_names ||= []
44
+ (@var_names.size...size).each do |i|
45
+ @var_names[i] = :"v#{i}"
46
+ end if @var_names.size < size
47
+ @var_names
48
+ end
49
+
50
+ # Sets the variable names
51
+ def var_names=(names)
52
+ @var_names = names
53
+ end
54
+
55
+ # Returns the variable name of a given bdd
56
+ def var_name(bdd)
57
+ return :zero if bdd==zero
58
+ return :one if bdd==one
59
+ var_names[var_index(bdd)]
60
+ end
61
+
62
+ # @see Cudd_ReadSize
63
+ def size
64
+ Wrapper.ReadSize(native_manager)
65
+ end
66
+ alias :bdd_count :size
67
+
68
+ # @see Cudd_NodeReadIndex
69
+ def var_index(bdd)
70
+ return nil if bdd==zero or bdd==one
71
+ Wrapper.NodeReadIndex(bdd)
72
+ end
73
+
74
+ # @see Cudd_bddIthVar
75
+ def ith_var(i)
76
+ bdd Wrapper.bddIthVar(native_manager, i)
77
+ end
78
+
79
+ # Returns the ith-vars denoted by `arg` as an Array of BDDs.
80
+ #
81
+ # Example:
82
+ # x, y, z = manager.ith_vars(0, 1, 2)
83
+ # x, y, z = manager.ith_vars(0..2)
84
+ # x, y, z = manager.ith_vars([0, 1, 2])
85
+ #
86
+ def ith_vars(*args)
87
+ args = args.first if args.size==1
88
+ Array(args).map(&:to_i).map{|i| ith_var(i)}
89
+ end
90
+
91
+ # @see Cudd_bddNewVar
92
+ def new_var(name = nil)
93
+ var = bdd Wrapper.bddNewVar(native_manager)
94
+ var_names[var_index(var)] = name if name
95
+ var
96
+ end
97
+
98
+ # Creates new variables and returns them as an Array.
99
+ #
100
+ # Example:
101
+ # x, y, z = manager.new_vars(3)
102
+ # x, y, z = manager.new_vars(:x, :y, :z)
103
+ #
104
+ def new_vars(first, *args)
105
+ _, first = args.unshift(first), args unless args.empty?
106
+ case first
107
+ when Integer then (0...first).map{ new_var }
108
+ when Enumerable then first.map{|x| new_var(x) }
109
+ else
110
+ [ new_var(first) ]
111
+ end
112
+ end
113
+
114
+ ### CONSTANTS ######################################################################
115
+
116
+ # @see Cudd_ReadOne
117
+ def one
118
+ @one ||= bdd Wrapper.ReadOne(native_manager)
119
+ end
120
+
121
+ # @see Cudd_ReadLogicZero
122
+ def zero
123
+ @zero ||= bdd Wrapper.ReadLogicZero(native_manager)
124
+ end
125
+
126
+ # @see Cudd_IsComplement
127
+ def is_complement?(bdd)
128
+ (bdd.address & 1)==1
129
+ end
130
+
131
+ ### BOOLEAN ALGEBRA ################################################################
132
+
133
+ # @see Cudd_bddIte
134
+ def ite(f, g, h)
135
+ bdd Wrapper.bddIte(native_manager, f, g, h)
136
+ end
137
+
138
+ # @see Cudd_bddNot
139
+ def not(f)
140
+ bdd Wrapper.bddNot(native_manager, f)
141
+ end
142
+
143
+ # @see Cudd_bddAnd
144
+ def and(f, g)
145
+ bdd Wrapper.bddAnd(native_manager, f, g)
146
+ end
147
+
148
+ # @see Cudd_bddOr
149
+ def or(f, g)
150
+ bdd Wrapper.bddOr(native_manager, f, g)
151
+ end
152
+
153
+ # @see Cudd_bddNand
154
+ def nand(f, g)
155
+ bdd Wrapper.bddNand(native_manager, f, g)
156
+ end
157
+
158
+ # @see Cudd_bddNor
159
+ def nor(f, g)
160
+ bdd Wrapper.bddNor(native_manager, f, g)
161
+ end
162
+
163
+ # @see Cudd_bddXor
164
+ def xor(f, g)
165
+ bdd Wrapper.bddXor(native_manager, f, g)
166
+ end
167
+
168
+ # @see Cudd_bddXnor
169
+ def xnor(f, g)
170
+ bdd Wrapper.bddXnor(native_manager, f, g)
171
+ end
172
+
173
+ ### SUPPORT ########################################################################
174
+
175
+ # @see Cudd_Support
176
+ def support(bdd)
177
+ Wrapper.Support(native_manager, bdd)
178
+ end
179
+
180
+ ### COFACTOR & GENERALIZED COFACTOR ################################################
181
+
182
+ # @see Cudd_Cofactor
183
+ def cofactor(bdd, cube)
184
+ with_bdd_cube(cube) do |c|
185
+ bdd Wrapper.Cofactor(native_manager, bdd, c)
186
+ end
187
+ end
188
+
189
+ # @see Cudd_bddRestrict
190
+ def restrict(f, g)
191
+ with_bdd_cube(g) do |c|
192
+ bdd Wrapper.bddRestrict(native_manager, f, c)
193
+ end
194
+ end
195
+
196
+ ### ABSTRACTION ####################################################################
197
+
198
+ # @see Cudd_bddExistAbstract
199
+ def exist_abstract(bdd, cube)
200
+ with_bdd_cube(cube) do |c|
201
+ bdd Wrapper.bddExistAbstract(native_manager, bdd, c)
202
+ end
203
+ end
204
+ alias :exist :exist_abstract
205
+
206
+ # @see Cudd_bddUnivAbstract
207
+ def univ_abstract(bdd, cube)
208
+ with_bdd_cube(cube) do |c|
209
+ bdd Wrapper.bddUnivAbstract(native_manager, bdd, c)
210
+ end
211
+ end
212
+ alias :univ :univ_abstract
213
+ alias :forall :univ_abstract
214
+
215
+ ### COERCIONS from & to Cubes ######################################################
216
+
217
+ # Coerces `arg` to a cube.
218
+ #
219
+ # Example (suppose three BDD variables: x, y and z):
220
+ #
221
+ # cube([1, 0, 2]) # => [1, 0, 2]
222
+ # cube([1, 0]) # same
223
+ # cube([true, false]) # same
224
+ # cube([x, !y]) # same
225
+ # cube(x => true, y => false) # same
226
+ #
227
+ def cube(arg, as = :cube)
228
+ cube = Cube.new(self, arg)
229
+ cube.send(:"to_#{as}")
230
+ rescue NoMethodError
231
+ raise ArgumentError, "Invalid 'as' option `#{as}`"
232
+ end
233
+
234
+ # @see Cudd_CubeArrayToBdd
235
+ def cube2bdd(cube_array)
236
+ with_ffi_pointer(:int, cube_array.size) do |ptr|
237
+ ptr.write_array_of_int(cube_array)
238
+ bdd Wrapper.CubeArrayToBdd(native_manager, ptr) do
239
+ raise Cudd::Error, "Cudd_CubeArrayToBdd failed on `#{cube_array.inspect}`"
240
+ end
241
+ end
242
+ end
243
+
244
+ # @see Cudd_BddToCubeArray
245
+ def bdd2cube(bdd)
246
+ s = size
247
+ with_ffi_pointer(:int, s) do |ptr|
248
+ if Wrapper.BddToCubeArray(native_manager, bdd, ptr)==1
249
+ ptr.read_array_of_int(s)
250
+ else
251
+ raise NotACubeError
252
+ end
253
+ end
254
+ end
255
+
256
+ # Converts a bdd to a disjunctive normal form
257
+ def bdd2dnf(bdd)
258
+ return "true" if bdd==one
259
+ return "false" if bdd==zero
260
+ buf, size = "", 0
261
+ each_cube(bdd) do |cube|
262
+ size += 1
263
+ buf << " | " unless buf.empty?
264
+ buf << "(" << cube.to_dnf << ")"
265
+ end
266
+ size == 1 ? buf[1...-1] : buf
267
+ end
268
+
269
+ ### EVALUATION & SATISFIABILITY ####################################################
270
+
271
+ # @see Cudd_Eval
272
+ def eval(f, cube)
273
+ with_ffi_pointer(:int, size) do |ptr|
274
+ ptr.write_array_of_int(cube(cube, :a012))
275
+ bdd Wrapper.Eval(native_manager, f, ptr)
276
+ end
277
+ end
278
+
279
+ # Returns true if `bdd` is satisfiable, false otherwise.
280
+ def satisfiable?(bdd)
281
+ !(zero == bdd)
282
+ end
283
+
284
+ # Returns true if `bdd` is satisfied by a given assignment, false otherwise.
285
+ def satisfied?(bdd, cube)
286
+ one == eval(bdd, cube)
287
+ end
288
+
289
+ # Returns the first cube satisfying `bdd`.
290
+ def one_cube(bdd)
291
+ each_cube(bdd).first
292
+ end
293
+
294
+ # @see Cudd_ForEachCube
295
+ def each_cube(bdd)
296
+ return self.enum_for(:each_cube, bdd) unless block_given?
297
+ return unless satisfiable?(bdd)
298
+ size, gen = self.size, nil
299
+ with_ffi_pointer(:pointer) do |cube_pointer|
300
+ with_ffi_pointer(:double) do |value_pointer|
301
+ gen = Wrapper.FirstCube(native_manager, bdd, cube_pointer, value_pointer)
302
+ begin
303
+ yield cube(cube_pointer.read_pointer.read_array_of_int(size))
304
+ end until Wrapper.NextCube(gen, cube_pointer, value_pointer)==0
305
+ end
306
+ end
307
+ ensure
308
+ Wrapper.GenFree(gen) if gen
309
+ end
310
+
311
+ # Returns an array with all cubes satisfying `bdd`.
312
+ def all_cubes(bdd)
313
+ each_cube(bdd).to_a
314
+ end
315
+
316
+ private
317
+
318
+ # Yields the block with a cube encoded by a BDD. If the latter must be
319
+ # built, it is automatically referenced then dereferenced after the block
320
+ # has been yield.
321
+ def with_bdd_cube(cube)
322
+ if cube.is_a?(Cudd::BDD)
323
+ yield(cube)
324
+ else
325
+ cube = cube(cube, :bdd).ref
326
+ res = yield(cube)
327
+ cube.deref
328
+ res
329
+ end
330
+ end
331
+
332
+ end # module BDD
333
+ end # module Interface
334
+ end # module Cudd
@@ -0,0 +1,35 @@
1
+ module Cudd
2
+ module Interface
3
+ module Root
4
+
5
+ def root_manager?
6
+ root_manager == self
7
+ end
8
+
9
+ # Returns an extension interface for a given name.
10
+ def interface(name)
11
+ return root_manager.interface(name) unless root_manager?
12
+ return self if name == :Root
13
+ interfaces[name] ||= begin
14
+ m = Manager.new(options, native_manager, root_manager)
15
+ m.extend Interface.const_get(name)
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def with_ffi_pointer(type = :int, size = 1)
22
+ res = nil
23
+ FFI::MemoryPointer.new(type, size) do |ptr|
24
+ res = yield(ptr)
25
+ end
26
+ res
27
+ end
28
+
29
+ def interfaces
30
+ @interfaces ||= {}
31
+ end
32
+
33
+ end # module Root
34
+ end # module Interface
35
+ end # module Cudd
@@ -0,0 +1 @@
1
+ require "ffi"
@@ -0,0 +1,78 @@
1
+ require_relative 'interfaces/root'
2
+ module Cudd
3
+ class Manager
4
+ include Interface::Root
5
+
6
+ # Options passed at construction.
7
+ attr_reader :options
8
+
9
+ # Creates a manager instance.
10
+ #
11
+ # @api private
12
+ def initialize(*args)
13
+ args.each do |arg|
14
+ @options = arg if arg.is_a?(Hash)
15
+ @root_manager = arg if arg.is_a?(Manager)
16
+ @native_manager = arg if arg.is_a?(FFI::Pointer)
17
+ end
18
+ end
19
+
20
+ # Creates a root manager by invoking `Cudd_Init`
21
+ #
22
+ # @api private
23
+ def self.root(options)
24
+ options = options.dup
25
+ bdd_vars = (options[:numVars] ||= 0)
26
+ zdd_vars = (options[:numVarsZ] ||= 0)
27
+ num_slots = (options[:numSlots] ||= 256)
28
+ cache_size = (options[:cacheSize] ||= 262144)
29
+ max_mem = (options[:maxMemory] ||= 0)
30
+ native_manager = Wrapper.Init(bdd_vars, zdd_vars, num_slots, cache_size, max_mem)
31
+ raise Cudd::Error, "Unable to create a manager" unless native_manager
32
+ Manager.new(options, native_manager).tap do |m|
33
+ ObjectSpace.define_finalizer(m, lambda{|d| d.close})
34
+ end
35
+ end
36
+
37
+ # Closes this manager by invoking `Cudd_Quit`.
38
+ def close
39
+ Wrapper.Quit(@native_manager) if @native_manager
40
+ ensure
41
+ @native_manager = nil
42
+ end
43
+
44
+ # Is this manager alive?
45
+ #
46
+ # A manager is alive between its creation (via `Cudd.manager`) and an invocation to
47
+ # `close`, either explicitely of implicitely (garbage collected by ruby).
48
+ #
49
+ # @api public
50
+ def alive?
51
+ !@native_manager.nil?
52
+ end
53
+
54
+ # Returns true if this manager has already been closed, false otherwise.
55
+ #
56
+ # @api public
57
+ def closed?
58
+ @native_manager.nil?
59
+ end
60
+
61
+ # Returns the native manager, that is, a FFI::Pointer to the CUDD's
62
+ # `DdManager`.
63
+ #
64
+ # @api public
65
+ def native_manager
66
+ @native_manager
67
+ end
68
+
69
+ private
70
+
71
+ # @api private
72
+ def root_manager
73
+ @root_manager || self
74
+ end
75
+
76
+ end # class Manager
77
+ end # module Cudd
78
+ require_relative 'interfaces/bdd'
@@ -0,0 +1,14 @@
1
+ module Cudd
2
+ module Version
3
+
4
+ MAJOR = 0
5
+ MINOR = 0
6
+ TINY = 1
7
+
8
+ def self.to_s
9
+ [ MAJOR, MINOR, TINY ].join('.')
10
+ end
11
+
12
+ end
13
+ VERSION = Version.to_s
14
+ end
@@ -0,0 +1,58 @@
1
+ module Cudd
2
+ module Wrapper
3
+ extend FFI::Library
4
+ ffi_lib ['cudd', 'libcudd'] + Dir[File.expand_path('../../../ext/*', __FILE__)]
5
+
6
+ ONE_POINTER = [ :pointer ]
7
+ TWO_POINTERS = [ :pointer, :pointer ]
8
+ THREE_POINTERS = [ :pointer, :pointer, :pointer ]
9
+ FOUR_POINTERS = [ :pointer, :pointer, :pointer, :pointer ]
10
+ FIVE_POINTERS = [ :pointer, :pointer, :pointer, :pointer, :pointer ]
11
+
12
+ def self.cudd_function(name, signature, return_type = :pointer)
13
+ attach_function name, :"Cudd_#{name}", signature, return_type
14
+ end
15
+
16
+ cudd_function :Init, Array.new(4, :uint) << :ulong
17
+ cudd_function :Quit, ONE_POINTER, :void
18
+
19
+ cudd_function :Ref, ONE_POINTER, :void
20
+ cudd_function :Deref, ONE_POINTER, :void
21
+ cudd_function :RecursiveDeref, TWO_POINTERS, :void
22
+
23
+ cudd_function :ReadSize, ONE_POINTER, :int
24
+ cudd_function :NodeReadIndex, ONE_POINTER, :int
25
+
26
+ cudd_function :ReadOne, ONE_POINTER
27
+ cudd_function :ReadZero, ONE_POINTER
28
+ cudd_function :ReadLogicZero, ONE_POINTER
29
+
30
+ cudd_function :bddIthVar, [ :pointer, :int ]
31
+ cudd_function :bddNewVar, ONE_POINTER
32
+ cudd_function :bddIte, FOUR_POINTERS
33
+ cudd_function :bddNot, TWO_POINTERS
34
+ cudd_function :bddAnd, THREE_POINTERS
35
+ cudd_function :bddOr, THREE_POINTERS
36
+ cudd_function :bddNand, THREE_POINTERS
37
+ cudd_function :bddNor, THREE_POINTERS
38
+ cudd_function :bddXor, THREE_POINTERS
39
+ cudd_function :bddXnor, THREE_POINTERS
40
+
41
+ cudd_function :Cofactor, THREE_POINTERS
42
+ cudd_function :bddRestrict, THREE_POINTERS
43
+
44
+ cudd_function :bddExistAbstract, THREE_POINTERS
45
+ cudd_function :bddUnivAbstract, THREE_POINTERS
46
+
47
+ cudd_function :Support, TWO_POINTERS
48
+
49
+ cudd_function :BddToCubeArray, THREE_POINTERS, :int
50
+ cudd_function :CubeArrayToBdd, TWO_POINTERS
51
+
52
+ cudd_function :Eval, THREE_POINTERS
53
+ cudd_function :FirstCube, FOUR_POINTERS
54
+ cudd_function :NextCube, THREE_POINTERS, :int
55
+ cudd_function :GenFree, ONE_POINTER, :int
56
+
57
+ end # module Wrapper
58
+ end # module Cudd
data/lib/cudd-rb.rb ADDED
@@ -0,0 +1,46 @@
1
+ #
2
+ # A ruby bridge to the CU Decision Diagram package (CUDD).
3
+ #
4
+ module Cudd
5
+
6
+ # initial size of subtables
7
+ UNIQUE_SLOTS = 256
8
+
9
+ # default size of the cache
10
+ CACHE_SLOTS = 262144
11
+
12
+ # Creates a manager instance.
13
+ #
14
+ # Recognized options match `Cudd_Init` arguments.
15
+ # - :numVars (defaults to 0) initial number of BDD variables (subtables)
16
+ # - :numVarsZ (defaults to 0) initial number of ZDD variables (subtables)
17
+ # - :numSlots (defaults to UNIQUE_SLOTS) initial size of the unique tables
18
+ # - :cacheSize (defaults to CACHE_SLOTS) initial size of the cache
19
+ # - :maxMemory (defaults to 0) target maximum memory occupation
20
+ #
21
+ # If a block is given, the manager is yield and automatically closed when the block
22
+ # terminates (its result is returned). Otherwise, the manager is returned and its is
23
+ # the responsibility of the caller to close it.
24
+ #
25
+ # @see Cudd_init
26
+ def self.manager(opts = {})
27
+ manager = Manager.root(opts.dup)
28
+ if block_given?
29
+ begin
30
+ yield(manager)
31
+ ensure
32
+ manager.close if manager.alive?
33
+ end
34
+ else
35
+ manager
36
+ end
37
+ end
38
+
39
+ end # module Cudd
40
+ require_relative "cudd-rb/version"
41
+ require_relative "cudd-rb/loader"
42
+ require_relative "cudd-rb/errors"
43
+ require_relative "cudd-rb/wrapper"
44
+ require_relative "cudd-rb/manager"
45
+ require_relative "cudd-rb/bdd"
46
+ require_relative "cudd-rb/cube"
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ module Cudd
3
+ describe Cube, '==' do
4
+
5
+ subject{ cube1 == cube2 }
6
+
7
+ before{ x; y; z }
8
+
9
+ context 'on equal cubes' do
10
+ let(:cube1){ cube(x => true, y => false) }
11
+ let(:cube2){ cube(x => true, y => false) }
12
+ it{ should be_true }
13
+ end
14
+
15
+ context 'on non equal cubes' do
16
+ let(:cube1){ cube(x => true, y => false) }
17
+ let(:cube2){ cube(x => false) }
18
+ it{ should be_false }
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+ module Cudd
3
+ describe Cube, 'to_truths' do
4
+
5
+ subject{ c.to_truths }
6
+
7
+ before{ x; y; z }
8
+
9
+ context 'on x' do
10
+ let(:c){ cube(x => true) }
11
+
12
+ it 'returns the expected bdd' do
13
+ subject.should eq([true, nil, nil])
14
+ end
15
+ end
16
+
17
+ context 'on !x' do
18
+ let(:c){ cube(x => false) }
19
+
20
+ it 'returns the expected bdd' do
21
+ subject.should eq([false, nil, nil])
22
+ end
23
+ end
24
+
25
+ context 'on x & y' do
26
+ let(:c){ cube(x => true, y => true) }
27
+
28
+ it 'returns the expected bdd' do
29
+ subject.should eq([true, true, nil])
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+ module Cudd
3
+ describe Cube, 'new' do
4
+
5
+ subject{ Cube.new(bdd_interface, arg) }
6
+
7
+ before{
8
+ x; y; z
9
+ subject.should be_a(Cube)
10
+ }
11
+
12
+ shared_examples_for "A cube for x=1,y=0,z=2" do
13
+ it 'has [1,0,2] has to_a012' do
14
+ subject.to_a012.should eq([1, 0, 2])
15
+ end
16
+ end
17
+
18
+ context 'when an array of 012' do
19
+ let(:arg){ [ 1, 0, 2 ] }
20
+ it_behaves_like "A cube for x=1,y=0,z=2"
21
+ end
22
+
23
+ context 'when an incomplete array of 012' do
24
+ let(:arg){ [ 1, 0 ] }
25
+ it_behaves_like "A cube for x=1,y=0,z=2"
26
+ end
27
+
28
+ context 'when truth values' do
29
+ let(:arg){ [ true, false, nil ] }
30
+ it_behaves_like "A cube for x=1,y=0,z=2"
31
+ end
32
+
33
+ context 'when an array of BDD variables' do
34
+ let(:arg){ [!y, x] }
35
+ it_behaves_like "A cube for x=1,y=0,z=2"
36
+ end
37
+
38
+ context 'when a Hash' do
39
+ let(:arg){ {x => 1, y => false} }
40
+ it_behaves_like "A cube for x=1,y=0,z=2"
41
+ end
42
+
43
+ context 'when a BDD' do
44
+ let(:arg){ x & !y }
45
+ it_behaves_like "A cube for x=1,y=0,z=2"
46
+ end
47
+
48
+ end
49
+ end