gecoder 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +11 -1
- data/Rakefile +3 -2
- data/example/raw_bindings.rb +7 -5
- data/example/sudoku-set.rb +0 -3
- data/lib/gecoder/bindings/bindings.rb +35 -1
- data/lib/gecoder/interface/binding_changes.rb +4 -8
- data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +63 -0
- data/lib/gecoder/interface/constraints/bool_enum/{boolean.rb → relation.rb} +8 -6
- data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +26 -2
- data/lib/gecoder/interface/constraints/int_enum/extensional.rb +61 -0
- data/lib/gecoder/interface/constraints/int_enum_constraints.rb +1 -0
- data/lib/gecoder/interface/model.rb +28 -6
- data/lib/gecoder/interface/search.rb +47 -18
- data/lib/gecoder/version.rb +1 -1
- data/specs/constraints/{bool_enum.rb → bool_enum_relation.rb} +5 -5
- data/specs/constraints/constraints.rb +9 -0
- data/specs/constraints/extensional.rb +106 -0
- data/specs/examples.rb +17 -0
- data/specs/search.rb +60 -0
- data/specs/set_var.rb +1 -1
- data/tasks/distribution.rake +35 -20
- data/tasks/rcov.rake +3 -2
- data/tasks/specs.rake +9 -3
- metadata +14 -6
data/CHANGES
CHANGED
@@ -1,8 +1,18 @@
|
|
1
|
+
== Version 0.8.1
|
2
|
+
This release adds tuple constraints along with a couple of minor features. It
|
3
|
+
also fixes a bug introduced in the previous version.
|
4
|
+
|
5
|
+
* [#19435] Fixed a bug causing inconsistencies during BAB-search. The bug stopped the send+more=money example from working correctly.
|
6
|
+
* Fixed the "raw_bindings" and "sudoku-set" examples, which were broken by the 0.8.0 release.
|
7
|
+
* Integers can now be used to specify singleton lower and upper bounds when creating set variables.
|
8
|
+
* Added convenience methods Model#maximize! and Model#minimize! for optimizing single variables.
|
9
|
+
* Added tuple constraints for enumerations of integer and boolean variables.
|
10
|
+
|
1
11
|
== Version 0.8.0
|
2
12
|
This release makes the jump from using Gecode 1.3.1 to using Gecode 2.1.1 .
|
3
13
|
The following changes have been made to the interface as a result of the jump.
|
4
14
|
|
5
|
-
*
|
15
|
+
* Removed the distinct constraint for sets.
|
6
16
|
* Added the propagation kind option to the non-set constraints.
|
7
17
|
|
8
18
|
== Version 0.7.1
|
data/Rakefile
CHANGED
@@ -4,10 +4,11 @@ require 'rake/rdoctask'
|
|
4
4
|
require 'rake/gempackagetask'
|
5
5
|
|
6
6
|
require 'tasks/all_tasks'
|
7
|
-
task :default => [:verify_rcov]
|
7
|
+
task :default => [:verify_rcov, :example_specs]
|
8
8
|
|
9
9
|
desc 'Performs the tasks necessary when releasing'
|
10
|
-
task :release => [:
|
10
|
+
task :release => [:clobber, :verify_rcov, :example_specs, :publish_website,
|
11
|
+
:publish_packages, :tag]
|
11
12
|
|
12
13
|
desc 'Runs all the tests'
|
13
14
|
task :test => :specs
|
data/example/raw_bindings.rb
CHANGED
@@ -12,14 +12,16 @@ s, e, n, d, m, o, r, y = (0..7).to_a.map{ |i| letters.at(i) }
|
|
12
12
|
Gecode::Raw::post(space, (s * 1000 + e * 100 + n * 10 + d +
|
13
13
|
m * 1000 + o * 100 + r * 10 + e).
|
14
14
|
equal(m * 10000 + o * 1000 + n * 100 + e * 10 + y ),
|
15
|
-
Gecode::Raw::ICL_DEF)
|
16
|
-
Gecode::Raw::rel(space, s, Gecode::Raw::IRT_NQ, 0, Gecode::Raw::ICL_DEF
|
17
|
-
Gecode::Raw::
|
18
|
-
Gecode::Raw::
|
15
|
+
Gecode::Raw::ICL_DEF, Gecode::Raw::PK_DEF)
|
16
|
+
Gecode::Raw::rel(space, s, Gecode::Raw::IRT_NQ, 0, Gecode::Raw::ICL_DEF,
|
17
|
+
Gecode::Raw::PK_DEF)
|
18
|
+
Gecode::Raw::rel(space, m, Gecode::Raw::IRT_NQ, 0, Gecode::Raw::ICL_DEF,
|
19
|
+
Gecode::Raw::PK_DEF)
|
20
|
+
Gecode::Raw::distinct(space, letters, Gecode::Raw::ICL_DEF, Gecode::Raw::PK_DEF)
|
19
21
|
|
20
22
|
# Branching.
|
21
23
|
Gecode::Raw::branch(space, letters,
|
22
|
-
Gecode::Raw::
|
24
|
+
Gecode::Raw::INT_VAR_SIZE_MIN, Gecode::Raw::INT_VAL_MIN)
|
23
25
|
|
24
26
|
# Search
|
25
27
|
COPY_DIST = 16
|
data/example/sudoku-set.rb
CHANGED
@@ -61,9 +61,6 @@ class SudokuSet < Gecode::Model
|
|
61
61
|
@sets[i].must_be.disjoint_with @sets[j]
|
62
62
|
end
|
63
63
|
end
|
64
|
-
# The above implies that the sets must be distinct (since cardinality 0 is
|
65
|
-
# not allowed), but we also explicitly add the distinctness constraint.
|
66
|
-
@sets.must_be.distinct(:size => n)
|
67
64
|
|
68
65
|
# The sets must intersect in exactly one element with each row column and
|
69
66
|
# block. I.e. an assignable number must be assigned exactly once in each
|
@@ -149,7 +149,7 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
|
|
149
149
|
enum.add_value "SRT_CMPL"
|
150
150
|
end
|
151
151
|
|
152
|
-
ns.add_enum "SetOpType
|
152
|
+
ns.add_enum "SetOpType" do |enum|
|
153
153
|
enum.add_value "SOT_UNION"
|
154
154
|
enum.add_value "SOT_DUNION"
|
155
155
|
enum.add_value "SOT_INTER"
|
@@ -337,6 +337,20 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
|
|
337
337
|
klass.add_method "debug"
|
338
338
|
end
|
339
339
|
|
340
|
+
ns.add_cxx_class "TupleSet" do |klass|
|
341
|
+
klass.add_constructor
|
342
|
+
|
343
|
+
klass.add_method "add" do |method|
|
344
|
+
method.add_parameter "Gecode::IntArgs", "tuple"
|
345
|
+
end
|
346
|
+
|
347
|
+
klass.add_method "finalize"
|
348
|
+
|
349
|
+
klass.add_method "finalized", "bool"
|
350
|
+
|
351
|
+
klass.add_method "tuples", "int"
|
352
|
+
end
|
353
|
+
|
340
354
|
ns.add_cxx_class "MBranchingDesc" do |klass|
|
341
355
|
klass.bindname = "BranchingDesc"
|
342
356
|
klass.add_constructor
|
@@ -1207,6 +1221,26 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
|
|
1207
1221
|
func.add_parameter "Gecode::PropKind", "pk"
|
1208
1222
|
end
|
1209
1223
|
|
1224
|
+
ns.add_function "extensional", "void" do |func|
|
1225
|
+
func.add_parameter "Gecode::MSpace*", "home"
|
1226
|
+
func.add_parameter "Gecode::MIntVarArray *", "x" do |param|
|
1227
|
+
param.custom_conversion = "*ruby2Gecode_MIntVarArrayPtr(argv[1], 2)->ptr()"
|
1228
|
+
end
|
1229
|
+
func.add_parameter "Gecode::TupleSet", "t"
|
1230
|
+
func.add_parameter "Gecode::IntConLevel", "icl"
|
1231
|
+
func.add_parameter "Gecode::PropKind", "pk"
|
1232
|
+
end
|
1233
|
+
|
1234
|
+
ns.add_function "extensional", "void" do |func|
|
1235
|
+
func.add_parameter "Gecode::MSpace*", "home"
|
1236
|
+
func.add_parameter "Gecode::MBoolVarArray *", "x" do |param|
|
1237
|
+
param.custom_conversion = "*ruby2Gecode_MBoolVarArrayPtr(argv[1], 2)->ptr()"
|
1238
|
+
end
|
1239
|
+
func.add_parameter "Gecode::TupleSet", "t"
|
1240
|
+
func.add_parameter "Gecode::IntConLevel", "icl"
|
1241
|
+
func.add_parameter "Gecode::PropKind", "pk"
|
1242
|
+
end
|
1243
|
+
|
1210
1244
|
# ns.add_function "regular", "void" do |func|
|
1211
1245
|
# func.add_parameter "Gecode::MSpace*", "home"
|
1212
1246
|
# func.add_parameter "Gecode::MIntVarArray *", "x" do |param|
|
@@ -291,15 +291,11 @@ module Gecode
|
|
291
291
|
|
292
292
|
private
|
293
293
|
|
294
|
-
# Transforms a lub or glb domain given as a range or enumeration
|
295
|
-
# or more parameters that describe the domain to
|
294
|
+
# Transforms a lub or glb domain given as a fixnum, range or enumeration
|
295
|
+
# into one or more parameters that describe the domain to
|
296
|
+
# Gecode::Raw::SetVar .
|
296
297
|
def domain_to_args(domain)
|
297
|
-
|
298
|
-
return domain.first, domain.last
|
299
|
-
else
|
300
|
-
elements = domain.to_a
|
301
|
-
return Gecode::Raw::IntSet.new(domain, domain.size)
|
302
|
-
end
|
298
|
+
Gecode::Constraints::Util.constant_set_to_int_set(domain)
|
303
299
|
end
|
304
300
|
|
305
301
|
# Creates a new storage array for bool variables.
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Gecode::Constraints::BoolEnum
|
2
|
+
class Expression
|
3
|
+
# Posts an equality constraint on the variables in the enum.
|
4
|
+
def in(tuples, options = {})
|
5
|
+
if @params[:negate]
|
6
|
+
raise Gecode::MissingConstraintError, 'A negated tuple constraint is ' +
|
7
|
+
'not implemented.'
|
8
|
+
end
|
9
|
+
unless options[:reify].nil?
|
10
|
+
raise ArgumentError, 'Reification is not supported by the tuple ' +
|
11
|
+
'constraint.'
|
12
|
+
end
|
13
|
+
unless tuples.respond_to?(:each) and
|
14
|
+
tuples.all?{ |tuple| tuple.respond_to?(:each) }
|
15
|
+
raise TypeError, 'Expected an enumeration with tuples, got ' +
|
16
|
+
"#{tuples.class}."
|
17
|
+
end
|
18
|
+
unless tuples.all?{ |tuple|
|
19
|
+
tuple.all?{ |x| x.kind_of?(TrueClass) or x.kind_of?(FalseClass) }}
|
20
|
+
raise TypeError, 'All tuples must contain booleans.'
|
21
|
+
end
|
22
|
+
|
23
|
+
@params[:tuples] = tuples
|
24
|
+
@model.add_constraint Extensional::TupleConstraint.new(@model,
|
25
|
+
@params.update(Gecode::Constraints::Util.decode_options(options)))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# A module that gathers the classes and modules used in extensional
|
30
|
+
# constraints.
|
31
|
+
module Extensional #:nodoc:
|
32
|
+
# Describes a tuple constraint, which constrains the variables in an
|
33
|
+
# boolean enumeration to be equal to one of the specified tuples. Neither
|
34
|
+
# negation nor reification is supported.
|
35
|
+
#
|
36
|
+
# == Example
|
37
|
+
#
|
38
|
+
# # Constrains the three boolean variables in +bools+ to either
|
39
|
+
# # be true, false, true, or false, false, true.
|
40
|
+
# bools.must_be.in [[true, false, true], [false, false, true]]
|
41
|
+
#
|
42
|
+
# # The same as above, but preferring speed over low memory usage.
|
43
|
+
# bools.must_be.in([[true, false, true], [false, false, true]],
|
44
|
+
# :kind => :speed)
|
45
|
+
class TupleConstraint < Gecode::Constraints::Constraint
|
46
|
+
def post
|
47
|
+
# Bind lhs.
|
48
|
+
lhs = @params[:lhs].to_bool_var_array
|
49
|
+
|
50
|
+
# Create the tuple set.
|
51
|
+
tuple_set = Gecode::Raw::TupleSet.new
|
52
|
+
@params[:tuples].each do |tuple|
|
53
|
+
tuple_set.add tuple.map{ |b| b ? 1 : 0 }
|
54
|
+
end
|
55
|
+
tuple_set.finalize
|
56
|
+
|
57
|
+
# Post the constraint.
|
58
|
+
Gecode::Raw::extensional(@model.active_space, lhs, tuple_set,
|
59
|
+
*propagation_options)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -3,21 +3,23 @@ module Gecode
|
|
3
3
|
# Produces an expression that can be handled as if it was a variable
|
4
4
|
# representing the conjunction of all boolean variables in the enumeration.
|
5
5
|
def conjunction
|
6
|
-
return Gecode::Constraints::BoolEnum::ConjunctionStub.new(
|
6
|
+
return Gecode::Constraints::BoolEnum::Relation::ConjunctionStub.new(
|
7
7
|
@model, :lhs => self)
|
8
8
|
end
|
9
9
|
|
10
10
|
# Produces an expression that can be handled as if it was a variable
|
11
11
|
# representing the disjunction of all boolean variables in the enumeration.
|
12
12
|
def disjunction
|
13
|
-
return Gecode::Constraints::BoolEnum::DisjunctionStub.new(
|
13
|
+
return Gecode::Constraints::BoolEnum::Relation::DisjunctionStub.new(
|
14
14
|
@model, :lhs => self)
|
15
15
|
end
|
16
16
|
end
|
17
|
-
|
17
|
+
end
|
18
|
+
|
19
|
+
module Gecode::Constraints::BoolEnum
|
18
20
|
# A module that gathers the classes and modules used by boolean enumeration
|
19
|
-
# constraints.
|
20
|
-
module
|
21
|
+
# relation constraints.
|
22
|
+
module Relation #:nodoc:
|
21
23
|
# Describes a CompositeStub for the conjunction constraint, which constrain
|
22
24
|
# the conjunction of all boolean variables in an enumeration.
|
23
25
|
#
|
@@ -83,4 +85,4 @@ module Gecode
|
|
83
85
|
end
|
84
86
|
end
|
85
87
|
end
|
86
|
-
end
|
88
|
+
end
|
@@ -1,8 +1,32 @@
|
|
1
|
-
module Gecode
|
1
|
+
module Gecode
|
2
|
+
module BoolEnumMethods
|
3
|
+
include Gecode::Constraints::LeftHandSideMethods
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
# Produces an expression for the lhs module.
|
8
|
+
def expression(params)
|
9
|
+
params.update(:lhs => self)
|
10
|
+
Constraints::BoolEnum::Expression.new(@model, params)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
2
14
|
# A module containing constraints that have enumerations of boolean variables
|
3
15
|
# as left hand side.
|
4
16
|
module Constraints::BoolEnum
|
17
|
+
# Expressions with bool enums as left hand sides.
|
18
|
+
class Expression < Gecode::Constraints::Expression #:nodoc:
|
19
|
+
# Raises TypeError unless the left hand side is a bool enum.
|
20
|
+
def initialize(model, params)
|
21
|
+
super
|
22
|
+
|
23
|
+
unless params[:lhs].respond_to? :to_bool_var_array
|
24
|
+
raise TypeError, 'Must have bool enum as left hand side.'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
5
28
|
end
|
6
29
|
end
|
7
30
|
|
8
|
-
require 'gecoder/interface/constraints/bool_enum/
|
31
|
+
require 'gecoder/interface/constraints/bool_enum/relation'
|
32
|
+
require 'gecoder/interface/constraints/bool_enum/extensional'
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Gecode::Constraints::IntEnum
|
2
|
+
class Expression
|
3
|
+
# Posts an equality constraint on the variables in the enum.
|
4
|
+
def in(tuples, options = {})
|
5
|
+
if @params[:negate]
|
6
|
+
raise Gecode::MissingConstraintError, 'A negated tuple constraint is ' +
|
7
|
+
'not implemented.'
|
8
|
+
end
|
9
|
+
unless options[:reify].nil?
|
10
|
+
raise ArgumentError, 'Reification is not supported by the tuple ' +
|
11
|
+
'constraint.'
|
12
|
+
end
|
13
|
+
unless tuples.respond_to?(:each) and
|
14
|
+
tuples.all?{ |tuple| tuple.respond_to?(:each) }
|
15
|
+
raise TypeError, 'Expected an enumeration with tuples, got ' +
|
16
|
+
"#{tuples.class}."
|
17
|
+
end
|
18
|
+
unless tuples.all?{ |tuple| tuple.all?{ |x| x.kind_of? Fixnum }}
|
19
|
+
raise TypeError, 'All tuples must contain Fixnum.'
|
20
|
+
end
|
21
|
+
|
22
|
+
@params[:tuples] = tuples
|
23
|
+
@model.add_constraint Extensional::TupleConstraint.new(@model,
|
24
|
+
@params.update(Gecode::Constraints::Util.decode_options(options)))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# A module that gathers the classes and modules used in extensional
|
29
|
+
# constraints.
|
30
|
+
module Extensional #:nodoc:
|
31
|
+
# Describes a tuple constraint, which constrains all the variables in an
|
32
|
+
# enumeration of integer variables to be equal to one of the specified
|
33
|
+
# tuples. Neither negation nor reification is supported.
|
34
|
+
#
|
35
|
+
# == Example
|
36
|
+
#
|
37
|
+
# # Constrains the two integer variables in +numbers+ to either have
|
38
|
+
# # values 1 and 7, or values 47 and 11.
|
39
|
+
# numbers.must_be.in [[1,7], [47,11]]
|
40
|
+
#
|
41
|
+
# # The same as above, but preferring speed over low memory usage.
|
42
|
+
# numbers.must_be.in([[1,7], [47,11]], :kind => :speed)
|
43
|
+
class TupleConstraint < Gecode::Constraints::Constraint
|
44
|
+
def post
|
45
|
+
# Bind lhs.
|
46
|
+
lhs = @params[:lhs].to_int_var_array
|
47
|
+
|
48
|
+
# Create the tuple set.
|
49
|
+
tuple_set = Gecode::Raw::TupleSet.new
|
50
|
+
@params[:tuples].each do |tuple|
|
51
|
+
tuple_set.add tuple
|
52
|
+
end
|
53
|
+
tuple_set.finalize
|
54
|
+
|
55
|
+
# Post the constraint.
|
56
|
+
Gecode::Raw::extensional(@model.active_space, lhs, tuple_set,
|
57
|
+
*propagation_options)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -35,3 +35,4 @@ require 'gecoder/interface/constraints/int_enum/element'
|
|
35
35
|
require 'gecoder/interface/constraints/int_enum/count'
|
36
36
|
require 'gecoder/interface/constraints/int_enum/sort'
|
37
37
|
require 'gecoder/interface/constraints/int_enum/arithmetic'
|
38
|
+
require 'gecoder/interface/constraints/int_enum/extensional'
|
@@ -67,11 +67,11 @@ module Gecode
|
|
67
67
|
end
|
68
68
|
|
69
69
|
# Creates a set variable with the specified domain for greatest lower bound
|
70
|
-
# and least upper bound (specified as either a range or enum). If
|
71
|
-
# are specified then the empty set is used as greates lower bound
|
72
|
-
# universe as least upper bound. A range for the allowed cardinality
|
73
|
-
# set can also be specified, if none is specified, or nil is given,
|
74
|
-
# default range (anything) will be used. If only a single Fixnum is
|
70
|
+
# and least upper bound (specified as either a fixnum, range or enum). If
|
71
|
+
# no bounds are specified then the empty set is used as greates lower bound
|
72
|
+
# and the universe as least upper bound. A range for the allowed cardinality
|
73
|
+
# of the set can also be specified, if none is specified, or nil is given,
|
74
|
+
# then the default range (anything) will be used. If only a single Fixnum is
|
75
75
|
# specified as cardinality_range then it's used as lower bound.
|
76
76
|
def set_var(glb_domain = [], lub_domain =
|
77
77
|
Gecode::Raw::SetLimits::MIN..Gecode::Raw::SetLimits::MAX,
|
@@ -220,6 +220,8 @@ module Gecode
|
|
220
220
|
if glb.kind_of?(Range) and lub.kind_of?(Range)
|
221
221
|
glb.first >= lub.first and glb.last <= lub.last
|
222
222
|
else
|
223
|
+
glb = [glb] if glb.kind_of?(Fixnum)
|
224
|
+
lub = [lub] if lub.kind_of?(Fixnum)
|
223
225
|
(glb.to_a - lub.to_a).empty?
|
224
226
|
end
|
225
227
|
end
|
@@ -232,7 +234,8 @@ module Gecode
|
|
232
234
|
# Retrieves the currently selected space, the one which constraints and
|
233
235
|
# variables should be bound to.
|
234
236
|
def selected_space
|
235
|
-
@active_space
|
237
|
+
return @active_space unless @active_space.nil?
|
238
|
+
self.active_space = base_space
|
236
239
|
end
|
237
240
|
|
238
241
|
# Retrieves the space that should be used for variable creation.
|
@@ -243,9 +246,28 @@ module Gecode
|
|
243
246
|
# Refreshes all cached variables. This should be called if the variables
|
244
247
|
# in an existing space were changed.
|
245
248
|
def refresh_variables
|
249
|
+
return if @variables.nil?
|
246
250
|
@variables.each do |variable|
|
247
251
|
variable.refresh if variable.cached?
|
248
252
|
end
|
249
253
|
end
|
254
|
+
|
255
|
+
# Executes any interactions with Gecode still waiting in the queue
|
256
|
+
# (emptying the queue) in the process.
|
257
|
+
def perform_queued_gecode_interactions
|
258
|
+
allow_space_access do
|
259
|
+
gecode_interaction_queue.each{ |con| con.call }
|
260
|
+
gecode_interaction_queue.clear # Empty the queue.
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
# Switches the active space used (the space from which variables are read
|
265
|
+
# and to which constraints are posted). @active_space should never be
|
266
|
+
# assigned directly.
|
267
|
+
def active_space=(new_space)
|
268
|
+
@active_space = new_space
|
269
|
+
new_space.refresh
|
270
|
+
refresh_variables
|
271
|
+
end
|
250
272
|
end
|
251
273
|
end
|
@@ -6,14 +6,14 @@ module Gecode
|
|
6
6
|
def solve!
|
7
7
|
space = dfs_engine.next
|
8
8
|
return nil if space.nil?
|
9
|
-
|
9
|
+
self.active_space = space
|
10
10
|
return self
|
11
11
|
end
|
12
12
|
|
13
13
|
# Returns to the original state, before any search was made (but propagation
|
14
14
|
# might have been performed). Returns the reset model.
|
15
15
|
def reset!
|
16
|
-
|
16
|
+
self.active_space = base_space
|
17
17
|
return self
|
18
18
|
end
|
19
19
|
|
@@ -30,7 +30,9 @@ module Gecode
|
|
30
30
|
# Yields each solution that the model has.
|
31
31
|
def each_solution(&block)
|
32
32
|
dfs = dfs_engine
|
33
|
-
|
33
|
+
next_solution = nil
|
34
|
+
while not (next_solution = dfs.next).nil?
|
35
|
+
self.active_space = next_solution
|
34
36
|
yield self
|
35
37
|
end
|
36
38
|
self.reset!
|
@@ -54,10 +56,10 @@ module Gecode
|
|
54
56
|
|
55
57
|
# Set the method used for constrain calls by the BAB-search.
|
56
58
|
Model.constrain_proc = lambda do |home_space, best_space|
|
57
|
-
|
59
|
+
self.active_space = best_space
|
58
60
|
@variable_creation_space = home_space
|
59
61
|
yield(self, self)
|
60
|
-
|
62
|
+
self.active_space = home_space
|
61
63
|
@variable_creation_space = nil
|
62
64
|
|
63
65
|
perform_queued_gecode_interactions
|
@@ -74,13 +76,49 @@ module Gecode
|
|
74
76
|
Model.constrain_proc = nil
|
75
77
|
return nil if result.nil?
|
76
78
|
|
77
|
-
#
|
78
|
-
result
|
79
|
-
refresh_variables
|
80
|
-
@active_space = result
|
79
|
+
# Switch to the result.
|
80
|
+
self.active_space = result
|
81
81
|
return self
|
82
82
|
end
|
83
83
|
|
84
|
+
# Finds the solution that maximizes a given integer variable. The name of
|
85
|
+
# the method that accesses the variable from the model should be given. To
|
86
|
+
# for instance maximize a variable named "profit", that's accessible through
|
87
|
+
# the model, one would use the following.
|
88
|
+
#
|
89
|
+
# model.maximize! :profit
|
90
|
+
#
|
91
|
+
# Returns nil if there is no solution.
|
92
|
+
def maximize!(var)
|
93
|
+
variable = self.method(var).call
|
94
|
+
unless variable.kind_of? Gecode::FreeIntVar
|
95
|
+
raise ArgumentError.new("Expected integer variable, got #{variable.class}.")
|
96
|
+
end
|
97
|
+
|
98
|
+
optimize! do |model, best_so_far|
|
99
|
+
model.method(var).call.must > best_so_far.method(var).call.value
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Finds the solution that minimizes a given integer variable. The name of
|
104
|
+
# the method that accesses the variable from the model should be given. To
|
105
|
+
# for instance minimize a variable named "cost", that's accessible through
|
106
|
+
# the model, one would use the following.
|
107
|
+
#
|
108
|
+
# model.minimize! :cost
|
109
|
+
#
|
110
|
+
# Returns nil if there is no solution.
|
111
|
+
def minimize!(var)
|
112
|
+
variable = self.method(var).call
|
113
|
+
unless variable.kind_of? Gecode::FreeIntVar
|
114
|
+
raise ArgumentError.new("Expected integer variable, got #{variable.class}.")
|
115
|
+
end
|
116
|
+
|
117
|
+
optimize! do |model, best_so_far|
|
118
|
+
model.method(var).call.must < best_so_far.method(var).call.value
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
84
122
|
class <<self
|
85
123
|
# Sets the proc that should be used to handle constrain requests.
|
86
124
|
def constrain_proc=(proc) #:nodoc:
|
@@ -111,14 +149,5 @@ module Gecode
|
|
111
149
|
Gecode::Raw::Search::Config::ADAPTIVE_DISTANCE,
|
112
150
|
nil)
|
113
151
|
end
|
114
|
-
|
115
|
-
# Executes any interactions with Gecode still waiting in the queue
|
116
|
-
# (emptying the queue) in the process.
|
117
|
-
def perform_queued_gecode_interactions
|
118
|
-
allow_space_access do
|
119
|
-
gecode_interaction_queue.each{ |con| con.call }
|
120
|
-
gecode_interaction_queue.clear # Empty the queue.
|
121
|
-
end
|
122
|
-
end
|
123
152
|
end
|
124
153
|
end
|
data/lib/gecoder/version.rb
CHANGED
@@ -17,7 +17,7 @@ end
|
|
17
17
|
|
18
18
|
# Expects @stub, which contains the started constraint and @compute_result which
|
19
19
|
# computes whether the left hand side is true or not.
|
20
|
-
describe 'bool enum constraint', :shared => true do
|
20
|
+
describe 'bool enum relation constraint', :shared => true do
|
21
21
|
it 'should handle being constrained to be true' do
|
22
22
|
@stub.must_be.true
|
23
23
|
@model.solve!
|
@@ -67,7 +67,7 @@ describe 'bool enum constraint', :shared => true do
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
describe Gecode::Constraints::BoolEnum, ' (conjunction)' do
|
70
|
+
describe Gecode::Constraints::BoolEnum::Relation, ' (conjunction)' do
|
71
71
|
before do
|
72
72
|
@model = BoolEnumSampleProblem.new
|
73
73
|
@bools = @model.bools
|
@@ -109,11 +109,11 @@ describe Gecode::Constraints::BoolEnum, ' (conjunction)' do
|
|
109
109
|
@compute_result = lambda{ @bools.all?{ |b| b.value } }
|
110
110
|
end
|
111
111
|
|
112
|
-
it_should_behave_like 'bool enum constraint'
|
112
|
+
it_should_behave_like 'bool enum relation constraint'
|
113
113
|
it_should_behave_like 'reifiable constraint'
|
114
114
|
end
|
115
115
|
|
116
|
-
describe Gecode::Constraints::BoolEnum, ' (disjunction)' do
|
116
|
+
describe Gecode::Constraints::BoolEnum::Relation, ' (disjunction)' do
|
117
117
|
before do
|
118
118
|
@model = BoolEnumSampleProblem.new
|
119
119
|
@bools = @model.bools
|
@@ -155,6 +155,6 @@ describe Gecode::Constraints::BoolEnum, ' (disjunction)' do
|
|
155
155
|
@compute_result = lambda{ @bools.any?{ |b| b.value } }
|
156
156
|
end
|
157
157
|
|
158
|
-
it_should_behave_like 'bool enum constraint'
|
158
|
+
it_should_behave_like 'bool enum relation constraint'
|
159
159
|
it_should_behave_like 'reifiable constraint'
|
160
160
|
end
|
@@ -17,6 +17,15 @@ describe Gecode::Constraints::IntEnum::Expression do
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
describe Gecode::Constraints::BoolEnum::Expression do
|
21
|
+
it 'should raise error unless lhs is a bool enum' do
|
22
|
+
lambda do
|
23
|
+
Gecode::Constraints::BoolEnum::Expression.new(Gecode::Model.new,
|
24
|
+
:lhs => 'foo', :negate => false)
|
25
|
+
end.should raise_error(TypeError)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
20
29
|
describe Gecode::Constraints::SetEnum::Expression do
|
21
30
|
it 'should raise error unless lhs is a set enum' do
|
22
31
|
lambda do
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/constraint_helper'
|
3
|
+
|
4
|
+
describe Gecode::Constraints::IntEnum::Extensional do
|
5
|
+
before do
|
6
|
+
@model = Gecode::Model.new
|
7
|
+
@tuples = [[1,7], [5,1]]
|
8
|
+
@digits = @model.int_var_array(2, 0..9)
|
9
|
+
@model.branch_on @digits
|
10
|
+
|
11
|
+
@invoke_options = lambda do |hash|
|
12
|
+
@digits.must_be.in(@tuples, hash)
|
13
|
+
@model.solve!
|
14
|
+
end
|
15
|
+
@expect_options = option_expectation do |strength, kind, reif_var|
|
16
|
+
Gecode::Raw.should_receive(:extensional).once.with(
|
17
|
+
an_instance_of(Gecode::Raw::Space),
|
18
|
+
an_instance_of(Gecode::Raw::IntVarArray),
|
19
|
+
an_instance_of(Gecode::Raw::TupleSet), strength, kind)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should constrain the domain of all variables' do
|
24
|
+
@digits.must_be.in @tuples
|
25
|
+
|
26
|
+
found_solutions = []
|
27
|
+
@model.each_solution do |m|
|
28
|
+
found_solutions << @digits.values
|
29
|
+
end
|
30
|
+
|
31
|
+
found_solutions.size.should == 2
|
32
|
+
(found_solutions - @tuples).should be_empty
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should not allow negation' do
|
36
|
+
lambda do
|
37
|
+
@digits.must_not_be.in @tuples
|
38
|
+
end.should raise_error(Gecode::MissingConstraintError)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should raise error if the right hand side is not an enumeration' do
|
42
|
+
lambda{ @digits.must_be.in 4711 }.should raise_error(TypeError)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should raise error if the right hand side does not contain tuples' do
|
46
|
+
lambda{ @digits.must_be.in [17, 4711] }.should raise_error(TypeError)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should raise error if the right hand side does not contain integer tuples' do
|
50
|
+
lambda{ @digits.must_be.in ['hello'] }.should raise_error(TypeError)
|
51
|
+
end
|
52
|
+
|
53
|
+
it_should_behave_like 'non-reifiable constraint'
|
54
|
+
end
|
55
|
+
|
56
|
+
describe Gecode::Constraints::BoolEnum::Extensional do
|
57
|
+
before do
|
58
|
+
@model = Gecode::Model.new
|
59
|
+
@tuples = [[true, false, true], [false, false, true]]
|
60
|
+
@bools = @model.bool_var_array(3)
|
61
|
+
@model.branch_on @bools
|
62
|
+
|
63
|
+
@invoke_options = lambda do |hash|
|
64
|
+
@bools.must_be.in(@tuples, hash)
|
65
|
+
@model.solve!
|
66
|
+
end
|
67
|
+
@expect_options = option_expectation do |strength, kind, reif_var|
|
68
|
+
Gecode::Raw.should_receive(:extensional).once.with(
|
69
|
+
an_instance_of(Gecode::Raw::Space),
|
70
|
+
an_instance_of(Gecode::Raw::BoolVarArray),
|
71
|
+
an_instance_of(Gecode::Raw::TupleSet), strength, kind)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should constrain the domain of all variables' do
|
76
|
+
@bools.must_be.in @tuples
|
77
|
+
|
78
|
+
found_solutions = []
|
79
|
+
@model.each_solution do |m|
|
80
|
+
found_solutions << @bools.values
|
81
|
+
end
|
82
|
+
|
83
|
+
found_solutions.size.should == 2
|
84
|
+
(found_solutions - @tuples).should be_empty
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should not allow negation' do
|
88
|
+
lambda do
|
89
|
+
@bools.must_not_be.in @tuples
|
90
|
+
end.should raise_error(Gecode::MissingConstraintError)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should raise error if the right hand side is not an enumeration' do
|
94
|
+
lambda{ @bools.must_be.in true }.should raise_error(TypeError)
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should raise error if the right hand side does not contain tuples' do
|
98
|
+
lambda{ @bools.must_be.in [true, false] }.should raise_error(TypeError)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should raise error if the right hand side does not contain boolean tuples' do
|
102
|
+
lambda{ @bools.must_be.in ['hello'] }.should raise_error(TypeError)
|
103
|
+
end
|
104
|
+
|
105
|
+
it_should_behave_like 'non-reifiable constraint'
|
106
|
+
end
|
data/specs/examples.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
require 'open3'
|
3
|
+
|
4
|
+
# This spec checks that the examples are still working.
|
5
|
+
files = Dir["#{File.dirname(__FILE__)}/../example/*.rb"]
|
6
|
+
files.delete_if do |file|
|
7
|
+
file =~ /example_helper.rb/
|
8
|
+
end
|
9
|
+
|
10
|
+
files.each do |example|
|
11
|
+
describe "Example (#{File.basename(example)})" do
|
12
|
+
it 'should not output errors' do
|
13
|
+
_, _, stderr = Open3.popen3("ruby #{example} 1> /dev/null")
|
14
|
+
stderr.gets.should be_nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/specs/search.rb
CHANGED
@@ -205,6 +205,66 @@ describe Gecode::Model, '(optimization search)' do
|
|
205
205
|
solution.z.value.should == 25
|
206
206
|
end
|
207
207
|
|
208
|
+
it 'should support maximizing singe variables given as symbols' do
|
209
|
+
solution = SampleOptimizationProblem.new.maximize! :z
|
210
|
+
solution.should_not be_nil
|
211
|
+
solution.x.value.should == 5
|
212
|
+
solution.y.value.should == 5
|
213
|
+
solution.z.value.should == 25
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'should support maximizing singe variables given as strings' do
|
217
|
+
solution = SampleOptimizationProblem.new.maximize! 'z'
|
218
|
+
solution.should_not be_nil
|
219
|
+
solution.x.value.should == 5
|
220
|
+
solution.y.value.should == 5
|
221
|
+
solution.z.value.should == 25
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'should raise error if maximize! is given a non-existing method' do
|
225
|
+
lambda do
|
226
|
+
SampleOptimizationProblem.new.maximize! :does_not_exist
|
227
|
+
end.should raise_error(NameError)
|
228
|
+
end
|
229
|
+
|
230
|
+
it 'should raise error if maximize! is given a method that does not return an integer variable' do
|
231
|
+
lambda do
|
232
|
+
SampleOptimizationProblem.new.maximize! :object_id
|
233
|
+
end.should raise_error(ArgumentError)
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'should support minimizing singe variables given as symbols' do
|
237
|
+
problem = SampleOptimizationProblem.new
|
238
|
+
problem.z.must > 2
|
239
|
+
solution = problem.minimize! :x
|
240
|
+
solution.should_not be_nil
|
241
|
+
solution.x.value.should == 1
|
242
|
+
solution.y.value.should == 3
|
243
|
+
solution.z.value.should == 3
|
244
|
+
end
|
245
|
+
|
246
|
+
it 'should support minimizing singe variables given as strings' do
|
247
|
+
problem = SampleOptimizationProblem.new
|
248
|
+
problem.z.must > 2
|
249
|
+
solution = problem.minimize! 'x'
|
250
|
+
solution.should_not be_nil
|
251
|
+
solution.x.value.should == 1
|
252
|
+
solution.y.value.should == 3
|
253
|
+
solution.z.value.should == 3
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'should raise error if minimize! is given a non-existing method' do
|
257
|
+
lambda do
|
258
|
+
SampleOptimizationProblem.new.minimize! :does_not_exist
|
259
|
+
end.should raise_error(NameError)
|
260
|
+
end
|
261
|
+
|
262
|
+
it 'should raise error if minimize! is given a method that does not return an integer variable' do
|
263
|
+
lambda do
|
264
|
+
SampleOptimizationProblem.new.minimize! :object_id
|
265
|
+
end.should raise_error(ArgumentError)
|
266
|
+
end
|
267
|
+
|
208
268
|
it 'should not be bothered by garbage collecting' do
|
209
269
|
# This goes through 400+ spaces.
|
210
270
|
solution = SampleOptimizationProblem2.new.optimize! do |model, best_so_far|
|
data/specs/set_var.rb
CHANGED
data/tasks/distribution.rake
CHANGED
@@ -7,6 +7,7 @@ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
|
7
7
|
PKG_FILE_NAME_WITH_GECODE = "#{PKG_NAME_WITH_GECODE}-#{PKG_VERSION}"
|
8
8
|
# The location where the precompiled DLL should be placed.
|
9
9
|
DLL_LOCATION = 'lib/gecode.dll'
|
10
|
+
EXT_DIR = 'ext'
|
10
11
|
|
11
12
|
desc 'Generate RDoc'
|
12
13
|
rd = Rake::RDocTask.new do |rdoc|
|
@@ -16,14 +17,19 @@ rd = Rake::RDocTask.new do |rdoc|
|
|
16
17
|
rdoc.rdoc_files.include('README', 'CHANGES', 'LGPL-LICENSE', 'lib/**/*.rb')
|
17
18
|
end
|
18
19
|
|
20
|
+
TMP_DIR = 'doc/tmp/rdoc_dev'
|
19
21
|
desc 'Generate RDoc, ignoring nodoc'
|
20
|
-
Rake::RDocTask.new(:rdoc_dev) do |rdoc|
|
22
|
+
Rake::RDocTask.new(:rdoc_dev => :prepare_rdoc_dev) do |rdoc|
|
21
23
|
rdoc.rdoc_dir = 'doc/output/rdoc_dev'
|
22
24
|
rdoc.options << '--title' << 'Gecode/R Developers RDoc' << '--line-numbers' <<
|
23
25
|
'--inline-source' << '--accessor' << 'delegate'
|
24
|
-
|
26
|
+
|
27
|
+
rdoc.rdoc_files.include("#{TMP_DIR}/**/*.rb")
|
28
|
+
end
|
29
|
+
|
30
|
+
desc 'Copies the files that RDoc should parse, removing #:nodoc:'
|
31
|
+
task :prepare_rdoc_dev do
|
25
32
|
# Copy the rdoc and remove all #:nodoc: .
|
26
|
-
TMP_DIR = 'doc/tmp/rdoc_dev'
|
27
33
|
Dir['lib/**/*.rb'].each do |source_name|
|
28
34
|
destination_name = source_name.sub('lib', TMP_DIR)
|
29
35
|
File.makedirs File.dirname(destination_name)
|
@@ -33,8 +39,6 @@ Rake::RDocTask.new(:rdoc_dev) do |rdoc|
|
|
33
39
|
end
|
34
40
|
destination.close
|
35
41
|
end
|
36
|
-
|
37
|
-
rdoc.rdoc_files.include("#{TMP_DIR}/**/*.rb")
|
38
42
|
end
|
39
43
|
|
40
44
|
spec = Gem::Specification.new do |s|
|
@@ -122,44 +126,55 @@ end
|
|
122
126
|
desc 'Removes generated distribution files'
|
123
127
|
task :clobber do
|
124
128
|
rm DLL_LOCATION if File.exists? DLL_LOCATION
|
129
|
+
FileList[
|
130
|
+
"#{EXT_DIR}/*.o",
|
131
|
+
"#{EXT_DIR}/gecode.{cc,hh}",
|
132
|
+
"#{EXT_DIR}/Makefile",
|
133
|
+
"#{EXT_DIR}/mkmf.log"
|
134
|
+
].to_a.each{ |file| rm file if File.exists? file }
|
125
135
|
end
|
126
136
|
|
127
137
|
desc 'Publish packages on RubyForge'
|
128
138
|
task :publish_packages => [:publish_gecoder_packages,
|
129
139
|
:publish_gecoder_with_gecode_packages]
|
130
140
|
|
141
|
+
# Files included in the vanilla Gecode/R release.
|
142
|
+
vanilla_release_files = [
|
143
|
+
"pkg/#{PKG_FILE_NAME}.gem",
|
144
|
+
"pkg/#{PKG_FILE_NAME}.tgz",
|
145
|
+
"pkg/#{PKG_FILE_NAME}.zip"
|
146
|
+
]
|
147
|
+
|
131
148
|
desc 'Publish Gecode/R packages on RubyForge'
|
132
|
-
task :publish_gecoder_packages => [:verify_user
|
133
|
-
release_files = FileList[
|
134
|
-
"pkg/#{PKG_FILE_NAME}.gem",
|
135
|
-
"pkg/#{PKG_FILE_NAME}.tgz",
|
136
|
-
"pkg/#{PKG_FILE_NAME}.zip"
|
137
|
-
]
|
149
|
+
task :publish_gecoder_packages => [:verify_user].concat(vanilla_release_files) do
|
138
150
|
require 'meta_project'
|
139
151
|
require 'rake/contrib/xforge'
|
140
152
|
|
141
153
|
Rake::XForge::Release.new(MetaProject::Project::XForge::RubyForge.new(PROJECT_NAME)) do |xf|
|
142
154
|
xf.user_name = ENV['RUBYFORGE_USER']
|
143
|
-
xf.files =
|
155
|
+
xf.files = vanilla_release_files.to_a
|
144
156
|
xf.release_name = "Gecode/R #{PKG_VERSION}"
|
145
157
|
xf.package_name = PKG_NAME
|
146
158
|
end
|
147
159
|
end
|
148
160
|
|
161
|
+
# Files included in the release with Gecode.
|
162
|
+
gecode_release_files = [
|
163
|
+
"pkg/#{PKG_FILE_NAME_WITH_GECODE}.gem",
|
164
|
+
"pkg/#{PKG_FILE_NAME_WITH_GECODE}.tgz",
|
165
|
+
"pkg/#{PKG_FILE_NAME_WITH_GECODE}.zip",
|
166
|
+
"pkg/#{PKG_FILE_NAME_WITH_GECODE}-mswin32.gem"
|
167
|
+
]
|
168
|
+
|
149
169
|
desc 'Publish Gecode/R with Gecode packages on RubyForge'
|
150
|
-
task :publish_gecoder_with_gecode_packages =>
|
151
|
-
|
152
|
-
"pkg/#{PKG_FILE_NAME_WITH_GECODE}*.gem",
|
153
|
-
"pkg/#{PKG_FILE_NAME_WITH_GECODE}*.tgz",
|
154
|
-
"pkg/#{PKG_FILE_NAME_WITH_GECODE}*.zip"
|
155
|
-
]
|
156
|
-
|
170
|
+
task :publish_gecoder_with_gecode_packages =>
|
171
|
+
[:verify_user].concat(gecode_release_files) do
|
157
172
|
require 'meta_project'
|
158
173
|
require 'rake/contrib/xforge'
|
159
174
|
|
160
175
|
Rake::XForge::Release.new(MetaProject::Project::XForge::RubyForge.new(PROJECT_NAME)) do |xf|
|
161
176
|
xf.user_name = ENV['RUBYFORGE_USER']
|
162
|
-
xf.files =
|
177
|
+
xf.files = gecode_release_files.to_a
|
163
178
|
xf.release_name = "Gecode/R with Gecode #{PKG_VERSION}"
|
164
179
|
xf.package_name = PKG_NAME_WITH_GECODE
|
165
180
|
end
|
data/tasks/rcov.rake
CHANGED
@@ -3,9 +3,10 @@ require 'spec/rake/verify_rcov'
|
|
3
3
|
|
4
4
|
RCOV_DIR = "#{File.dirname(__FILE__)}/../doc/output/coverage"
|
5
5
|
|
6
|
-
desc "Run all specs with rcov"
|
6
|
+
desc "Run all specs (except examples) with rcov"
|
7
7
|
Spec::Rake::SpecTask.new(:rcov) do |t|
|
8
8
|
t.spec_files = FileList['specs/**/*.rb']
|
9
|
+
t.spec_files.exclude 'examples.rb'
|
9
10
|
t.rcov = true
|
10
11
|
t.rcov_opts = ['--exclude examples', '--exclude specs']
|
11
12
|
t.rcov_dir = RCOV_DIR
|
@@ -14,4 +15,4 @@ end
|
|
14
15
|
RCov::VerifyTask.new(:verify_rcov => :rcov) do |t|
|
15
16
|
t.threshold = 100.0
|
16
17
|
t.index_html = "#{RCOV_DIR}/index.html"
|
17
|
-
end
|
18
|
+
end
|
data/tasks/specs.rake
CHANGED
@@ -3,13 +3,19 @@ require 'spec/rake/spectask'
|
|
3
3
|
spec_files = FileList['specs/**/*.rb']
|
4
4
|
|
5
5
|
desc 'Run all specs'
|
6
|
-
Spec::Rake::SpecTask.new(
|
6
|
+
Spec::Rake::SpecTask.new(:specs) do |t|
|
7
7
|
t.libs = ['lib']
|
8
8
|
t.spec_files = spec_files
|
9
9
|
end
|
10
10
|
|
11
|
+
desc 'Run specs for the examples'
|
12
|
+
Spec::Rake::SpecTask.new(:example_specs) do |t|
|
13
|
+
t.libs = ['lib']
|
14
|
+
t.spec_files = FileList['specs/examples.rb']
|
15
|
+
end
|
16
|
+
|
11
17
|
desc 'Generate an rspec html report'
|
12
|
-
Spec::Rake::SpecTask.new(
|
18
|
+
Spec::Rake::SpecTask.new(:spec_html) do |t|
|
13
19
|
t.spec_files = spec_files
|
14
20
|
t.spec_opts = ['--format html:doc/output/rspec.html','--backtrace']
|
15
|
-
end
|
21
|
+
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: gecoder
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.8.
|
7
|
-
date: 2008-04-
|
6
|
+
version: 0.8.1
|
7
|
+
date: 2008-04-20 00:00:00 +02:00
|
8
8
|
summary: Ruby interface to Gecode, an environment for constraint programming.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -34,7 +34,8 @@ files:
|
|
34
34
|
- COPYING
|
35
35
|
- README
|
36
36
|
- LGPL-LICENSE
|
37
|
-
- lib/gecoder/interface/constraints/bool_enum/
|
37
|
+
- lib/gecoder/interface/constraints/bool_enum/extensional.rb
|
38
|
+
- lib/gecoder/interface/constraints/bool_enum/relation.rb
|
38
39
|
- lib/gecoder/interface/constraints/set_enum/operation.rb
|
39
40
|
- lib/gecoder/interface/constraints/set_enum/distinct.rb
|
40
41
|
- lib/gecoder/interface/constraints/set_enum/selection.rb
|
@@ -56,6 +57,7 @@ files:
|
|
56
57
|
- lib/gecoder/interface/constraints/int_enum/count.rb
|
57
58
|
- lib/gecoder/interface/constraints/int_enum/arithmetic.rb
|
58
59
|
- lib/gecoder/interface/constraints/int_enum/element.rb
|
60
|
+
- lib/gecoder/interface/constraints/int_enum/extensional.rb
|
59
61
|
- lib/gecoder/interface/constraints/int_enum_constraints.rb
|
60
62
|
- lib/gecoder/interface/constraints/bool_enum_constraints.rb
|
61
63
|
- lib/gecoder/interface/constraints/set_enum_constraints.rb
|
@@ -156,7 +158,6 @@ files:
|
|
156
158
|
- tasks/dependencies.txt
|
157
159
|
- specs/constraints
|
158
160
|
- specs/constraints/boolean.rb
|
159
|
-
- specs/constraints/bool_enum.rb
|
160
161
|
- specs/constraints/int_domain.rb
|
161
162
|
- specs/constraints/distinct.rb
|
162
163
|
- specs/constraints/set_domain.rb
|
@@ -176,6 +177,8 @@ files:
|
|
176
177
|
- specs/constraints/channel.rb
|
177
178
|
- specs/constraints/linear.rb
|
178
179
|
- specs/constraints/set_operation.rb
|
180
|
+
- specs/constraints/extensional.rb
|
181
|
+
- specs/constraints/bool_enum_relation.rb
|
179
182
|
- specs/branch.rb
|
180
183
|
- specs/model.rb
|
181
184
|
- specs/binding_changes.rb
|
@@ -188,6 +191,7 @@ files:
|
|
188
191
|
- specs/enum_matrix.rb
|
189
192
|
- specs/spec_helper.rb
|
190
193
|
- specs/distribution.rb
|
194
|
+
- specs/examples.rb
|
191
195
|
- ext/missing.cpp
|
192
196
|
- ext/vararray.cpp
|
193
197
|
- ext/missing.h
|
@@ -195,7 +199,6 @@ files:
|
|
195
199
|
- ext/extconf.rb
|
196
200
|
test_files:
|
197
201
|
- specs/constraints/boolean.rb
|
198
|
-
- specs/constraints/bool_enum.rb
|
199
202
|
- specs/constraints/int_domain.rb
|
200
203
|
- specs/constraints/distinct.rb
|
201
204
|
- specs/constraints/set_domain.rb
|
@@ -215,6 +218,8 @@ test_files:
|
|
215
218
|
- specs/constraints/channel.rb
|
216
219
|
- specs/constraints/linear.rb
|
217
220
|
- specs/constraints/set_operation.rb
|
221
|
+
- specs/constraints/extensional.rb
|
222
|
+
- specs/constraints/bool_enum_relation.rb
|
218
223
|
- specs/branch.rb
|
219
224
|
- specs/model.rb
|
220
225
|
- specs/binding_changes.rb
|
@@ -227,6 +232,7 @@ test_files:
|
|
227
232
|
- specs/enum_matrix.rb
|
228
233
|
- specs/spec_helper.rb
|
229
234
|
- specs/distribution.rb
|
235
|
+
- specs/examples.rb
|
230
236
|
rdoc_options:
|
231
237
|
- --title
|
232
238
|
- Gecode/R
|
@@ -240,7 +246,8 @@ extra_rdoc_files:
|
|
240
246
|
- README
|
241
247
|
- CHANGES
|
242
248
|
- LGPL-LICENSE
|
243
|
-
- lib/gecoder/interface/constraints/bool_enum/
|
249
|
+
- lib/gecoder/interface/constraints/bool_enum/extensional.rb
|
250
|
+
- lib/gecoder/interface/constraints/bool_enum/relation.rb
|
244
251
|
- lib/gecoder/interface/constraints/set_enum/operation.rb
|
245
252
|
- lib/gecoder/interface/constraints/set_enum/distinct.rb
|
246
253
|
- lib/gecoder/interface/constraints/set_enum/selection.rb
|
@@ -262,6 +269,7 @@ extra_rdoc_files:
|
|
262
269
|
- lib/gecoder/interface/constraints/int_enum/count.rb
|
263
270
|
- lib/gecoder/interface/constraints/int_enum/arithmetic.rb
|
264
271
|
- lib/gecoder/interface/constraints/int_enum/element.rb
|
272
|
+
- lib/gecoder/interface/constraints/int_enum/extensional.rb
|
265
273
|
- lib/gecoder/interface/constraints/int_enum_constraints.rb
|
266
274
|
- lib/gecoder/interface/constraints/bool_enum_constraints.rb
|
267
275
|
- lib/gecoder/interface/constraints/set_enum_constraints.rb
|