gecoder-with-gecode 0.9.0-x86-mswin32-60
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/CHANGES +137 -0
- data/COPYING +17 -0
- data/LGPL-LICENSE +458 -0
- data/README +58 -0
- data/Rakefile +14 -0
- data/example/equation_system.rb +15 -0
- data/example/example_helper.rb +1 -0
- data/example/magic_sequence.rb +43 -0
- data/example/money.rb +36 -0
- data/example/queens.rb +42 -0
- data/example/send_more_money.rb +43 -0
- data/example/send_most_money.rb +58 -0
- data/example/square_tiling.rb +84 -0
- data/example/sudoku-set.rb +106 -0
- data/example/sudoku.rb +56 -0
- data/lib/gecode.dll +0 -0
- data/lib/gecoder.rb +5 -0
- data/lib/gecoder/bindings.rb +96 -0
- data/lib/gecoder/bindings/bindings.rb +2029 -0
- data/lib/gecoder/interface.rb +9 -0
- data/lib/gecoder/interface/binding_changes.rb +9 -0
- data/lib/gecoder/interface/branch.rb +163 -0
- data/lib/gecoder/interface/constraints.rb +471 -0
- data/lib/gecoder/interface/constraints/bool/boolean.rb +251 -0
- data/lib/gecoder/interface/constraints/bool/channel.rb +7 -0
- data/lib/gecoder/interface/constraints/bool/linear.rb +200 -0
- data/lib/gecoder/interface/constraints/bool_enum/channel.rb +68 -0
- data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +106 -0
- data/lib/gecoder/interface/constraints/bool_enum/relation.rb +55 -0
- data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +84 -0
- data/lib/gecoder/interface/constraints/bool_var_constraints.rb +155 -0
- data/lib/gecoder/interface/constraints/extensional_regexp.rb +101 -0
- data/lib/gecoder/interface/constraints/fixnum_enum/element.rb +63 -0
- data/lib/gecoder/interface/constraints/fixnum_enum/operation.rb +65 -0
- data/lib/gecoder/interface/constraints/fixnum_enum_constraints.rb +42 -0
- data/lib/gecoder/interface/constraints/int/arithmetic.rb +150 -0
- data/lib/gecoder/interface/constraints/int/channel.rb +51 -0
- data/lib/gecoder/interface/constraints/int/domain.rb +80 -0
- data/lib/gecoder/interface/constraints/int/linear.rb +143 -0
- data/lib/gecoder/interface/constraints/int/relation.rb +141 -0
- data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +63 -0
- data/lib/gecoder/interface/constraints/int_enum/channel.rb +86 -0
- data/lib/gecoder/interface/constraints/int_enum/count.rb +66 -0
- data/lib/gecoder/interface/constraints/int_enum/distinct.rb +64 -0
- data/lib/gecoder/interface/constraints/int_enum/element.rb +64 -0
- data/lib/gecoder/interface/constraints/int_enum/equality.rb +37 -0
- data/lib/gecoder/interface/constraints/int_enum/extensional.rb +187 -0
- data/lib/gecoder/interface/constraints/int_enum/sort.rb +135 -0
- data/lib/gecoder/interface/constraints/int_enum_constraints.rb +95 -0
- data/lib/gecoder/interface/constraints/int_var_constraints.rb +230 -0
- data/lib/gecoder/interface/constraints/reifiable_constraints.rb +78 -0
- data/lib/gecoder/interface/constraints/selected_set/select.rb +120 -0
- data/lib/gecoder/interface/constraints/selected_set_constraints.rb +75 -0
- data/lib/gecoder/interface/constraints/set/cardinality.rb +65 -0
- data/lib/gecoder/interface/constraints/set/channel.rb +51 -0
- data/lib/gecoder/interface/constraints/set/connection.rb +130 -0
- data/lib/gecoder/interface/constraints/set/domain.rb +156 -0
- data/lib/gecoder/interface/constraints/set/include.rb +36 -0
- data/lib/gecoder/interface/constraints/set/operation.rb +118 -0
- data/lib/gecoder/interface/constraints/set/relation.rb +155 -0
- data/lib/gecoder/interface/constraints/set_elements/relation.rb +116 -0
- data/lib/gecoder/interface/constraints/set_elements_constraints.rb +97 -0
- data/lib/gecoder/interface/constraints/set_enum/channel.rb +45 -0
- data/lib/gecoder/interface/constraints/set_enum/distinct.rb +43 -0
- data/lib/gecoder/interface/constraints/set_enum/operation.rb +69 -0
- data/lib/gecoder/interface/constraints/set_enum/select.rb +79 -0
- data/lib/gecoder/interface/constraints/set_enum_constraints.rb +84 -0
- data/lib/gecoder/interface/constraints/set_var_constraints.rb +243 -0
- data/lib/gecoder/interface/enum_matrix.rb +64 -0
- data/lib/gecoder/interface/enum_wrapper.rb +205 -0
- data/lib/gecoder/interface/model.rb +453 -0
- data/lib/gecoder/interface/model_sugar.rb +84 -0
- data/lib/gecoder/interface/search.rb +197 -0
- data/lib/gecoder/interface/variables.rb +306 -0
- data/lib/gecoder/version.rb +4 -0
- data/specs/bool_var.rb +81 -0
- data/specs/branch.rb +185 -0
- data/specs/constraints/bool/boolean.rb +317 -0
- data/specs/constraints/bool/boolean_properties.rb +51 -0
- data/specs/constraints/bool/linear.rb +213 -0
- data/specs/constraints/bool_enum/bool_enum_relation.rb +117 -0
- data/specs/constraints/bool_enum/channel.rb +102 -0
- data/specs/constraints/bool_enum/extensional.rb +225 -0
- data/specs/constraints/constraint_helper.rb +234 -0
- data/specs/constraints/constraint_receivers.rb +103 -0
- data/specs/constraints/constraints.rb +26 -0
- data/specs/constraints/fixnum_enum/element.rb +58 -0
- data/specs/constraints/fixnum_enum/operation.rb +67 -0
- data/specs/constraints/int/arithmetic.rb +149 -0
- data/specs/constraints/int/channel.rb +101 -0
- data/specs/constraints/int/domain.rb +106 -0
- data/specs/constraints/int/linear.rb +183 -0
- data/specs/constraints/int/linear_properties.rb +97 -0
- data/specs/constraints/int/relation.rb +84 -0
- data/specs/constraints/int_enum/arithmetic.rb +72 -0
- data/specs/constraints/int_enum/channel.rb +57 -0
- data/specs/constraints/int_enum/count.rb +72 -0
- data/specs/constraints/int_enum/distinct.rb +80 -0
- data/specs/constraints/int_enum/element.rb +61 -0
- data/specs/constraints/int_enum/equality.rb +29 -0
- data/specs/constraints/int_enum/extensional.rb +224 -0
- data/specs/constraints/int_enum/sort.rb +167 -0
- data/specs/constraints/operands.rb +264 -0
- data/specs/constraints/property_helper.rb +443 -0
- data/specs/constraints/reification_sugar.rb +69 -0
- data/specs/constraints/selected_set/select.rb +56 -0
- data/specs/constraints/selected_set/select_properties.rb +157 -0
- data/specs/constraints/set/cardinality.rb +58 -0
- data/specs/constraints/set/cardinality_properties.rb +46 -0
- data/specs/constraints/set/channel.rb +77 -0
- data/specs/constraints/set/connection.rb +176 -0
- data/specs/constraints/set/domain.rb +197 -0
- data/specs/constraints/set/include.rb +36 -0
- data/specs/constraints/set/operation.rb +132 -0
- data/specs/constraints/set/relation.rb +117 -0
- data/specs/constraints/set_elements/relation.rb +84 -0
- data/specs/constraints/set_enum/channel.rb +80 -0
- data/specs/constraints/set_enum/distinct.rb +59 -0
- data/specs/constraints/set_enum/operation.rb +111 -0
- data/specs/constraints/set_enum/select.rb +73 -0
- data/specs/distribution.rb +14 -0
- data/specs/enum_matrix.rb +43 -0
- data/specs/enum_wrapper.rb +179 -0
- data/specs/examples.rb +17 -0
- data/specs/int_var.rb +163 -0
- data/specs/logging.rb +24 -0
- data/specs/model.rb +325 -0
- data/specs/model_sugar.rb +30 -0
- data/specs/search.rb +383 -0
- data/specs/selected_set.rb +39 -0
- data/specs/set_elements.rb +34 -0
- data/specs/set_var.rb +82 -0
- data/specs/spec_helper.rb +265 -0
- data/tasks/all_tasks.rb +1 -0
- data/tasks/dependencies.txt +22 -0
- data/tasks/distribution.rake +194 -0
- data/tasks/rcov.rake +18 -0
- data/tasks/specs.rake +21 -0
- data/tasks/svn.rake +16 -0
- data/tasks/website.rake +51 -0
- data/vendor/gecode/win32/lib/libgecodeint.dll +0 -0
- data/vendor/gecode/win32/lib/libgecodekernel.dll +0 -0
- data/vendor/gecode/win32/lib/libgecodeminimodel.dll +0 -0
- data/vendor/gecode/win32/lib/libgecodesearch.dll +0 -0
- data/vendor/gecode/win32/lib/libgecodeset.dll +0 -0
- data/vendor/gecode/win32/lib/libgecodesupport.dll +0 -0
- data/vendor/rust/README +28 -0
- data/vendor/rust/bin/cxxgenerator.rb +93 -0
- data/vendor/rust/include/rust_checks.hh +116 -0
- data/vendor/rust/include/rust_conversions.hh +102 -0
- data/vendor/rust/rust.rb +67 -0
- data/vendor/rust/rust/attribute.rb +51 -0
- data/vendor/rust/rust/bindings.rb +172 -0
- data/vendor/rust/rust/class.rb +337 -0
- data/vendor/rust/rust/constants.rb +48 -0
- data/vendor/rust/rust/container.rb +110 -0
- data/vendor/rust/rust/cppifaceparser.rb +129 -0
- data/vendor/rust/rust/cwrapper.rb +72 -0
- data/vendor/rust/rust/cxxclass.rb +96 -0
- data/vendor/rust/rust/element.rb +81 -0
- data/vendor/rust/rust/enum.rb +63 -0
- data/vendor/rust/rust/function.rb +407 -0
- data/vendor/rust/rust/namespace.rb +61 -0
- data/vendor/rust/rust/templates/AttributeDefinition.rusttpl +17 -0
- data/vendor/rust/rust/templates/AttributeInitBinding.rusttpl +9 -0
- data/vendor/rust/rust/templates/BindingsHeader.rusttpl +24 -0
- data/vendor/rust/rust/templates/BindingsUnit.rusttpl +46 -0
- data/vendor/rust/rust/templates/CWrapperClassDefinitions.rusttpl +64 -0
- data/vendor/rust/rust/templates/ClassDeclarations.rusttpl +7 -0
- data/vendor/rust/rust/templates/ClassInitialize.rusttpl +6 -0
- data/vendor/rust/rust/templates/ConstructorStub.rusttpl +21 -0
- data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +100 -0
- data/vendor/rust/rust/templates/CxxMethodStub.rusttpl +12 -0
- data/vendor/rust/rust/templates/CxxStandaloneClassDefinitions.rusttpl +26 -0
- data/vendor/rust/rust/templates/EnumDeclarations.rusttpl +3 -0
- data/vendor/rust/rust/templates/EnumDefinitions.rusttpl +29 -0
- data/vendor/rust/rust/templates/FunctionDefinition.rusttpl +9 -0
- data/vendor/rust/rust/templates/FunctionInitAlias.rusttpl +5 -0
- data/vendor/rust/rust/templates/FunctionInitBinding.rusttpl +9 -0
- data/vendor/rust/rust/templates/MethodInitBinding.rusttpl +9 -0
- data/vendor/rust/rust/templates/ModuleDeclarations.rusttpl +3 -0
- data/vendor/rust/rust/templates/ModuleDefinitions.rusttpl +3 -0
- data/vendor/rust/rust/templates/StandaloneClassDeclarations.rusttpl +7 -0
- data/vendor/rust/rust/templates/VariableFunctionCall.rusttpl +14 -0
- data/vendor/rust/rust/type.rb +98 -0
- data/vendor/rust/test/Makefile +4 -0
- data/vendor/rust/test/constants.rb +36 -0
- data/vendor/rust/test/cppclass.cc +45 -0
- data/vendor/rust/test/cppclass.hh +67 -0
- data/vendor/rust/test/cppclass.rb +59 -0
- data/vendor/rust/test/cwrapper.c +74 -0
- data/vendor/rust/test/cwrapper.h +41 -0
- data/vendor/rust/test/cwrapper.rb +56 -0
- data/vendor/rust/test/dummyclass.hh +31 -0
- data/vendor/rust/test/lib/extension-test.rb +98 -0
- data/vendor/rust/test/operators.cc +41 -0
- data/vendor/rust/test/operators.hh +39 -0
- data/vendor/rust/test/operators.rb +39 -0
- data/vendor/rust/test/test-constants.rb +43 -0
- data/vendor/rust/test/test-cppclass.rb +82 -0
- data/vendor/rust/test/test-cwrapper.rb +80 -0
- data/vendor/rust/test/test-operators.rb +42 -0
- metadata +393 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
module Gecode::IntEnum
|
2
|
+
module IntEnumOperand
|
3
|
+
# Produces a new IntOperand representing the number of times
|
4
|
+
# +int_operand_or_fixnum+ is present in this enumeration.
|
5
|
+
#
|
6
|
+
# ==== Examples
|
7
|
+
#
|
8
|
+
# # The number of times 17 occurs in +int_enum+.
|
9
|
+
# int_enum.count(17)
|
10
|
+
#
|
11
|
+
# # The number of times +int_operand+ occurs in +int_enum+.
|
12
|
+
# int_enum.count(int_operand)
|
13
|
+
def count(int_operand_or_fixnum)
|
14
|
+
unless int_operand_or_fixnum.respond_to? :to_int_var or
|
15
|
+
int_operand_or_fixnum.kind_of?(Fixnum)
|
16
|
+
raise TypeError, 'Expected integer operand of fixnum, got ' +
|
17
|
+
"#{int_operand_or_fixnum.class}."
|
18
|
+
end
|
19
|
+
Count::IntEnumCountOperand.new(@model, self, int_operand_or_fixnum)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# A module that gathers the classes and modules used in count constraints.
|
24
|
+
module Count #:nodoc:
|
25
|
+
class IntEnumCountOperand < Gecode::Int::ShortCircuitRelationsOperand #:nodoc:
|
26
|
+
def initialize(model, int_enum, element)
|
27
|
+
super model
|
28
|
+
@enum = int_enum
|
29
|
+
@element = element
|
30
|
+
end
|
31
|
+
|
32
|
+
def relation_constraint(relation, int_operand_or_fix, params)
|
33
|
+
unless params[:negate]
|
34
|
+
relation_type =
|
35
|
+
Gecode::Util::RELATION_TYPES[relation]
|
36
|
+
else
|
37
|
+
relation_type =
|
38
|
+
Gecode::Util::NEGATED_RELATION_TYPES[relation]
|
39
|
+
end
|
40
|
+
|
41
|
+
params.update(:enum => @enum, :element => @element,
|
42
|
+
:rhs => int_operand_or_fix, :relation_type => relation_type)
|
43
|
+
CountConstraint.new(@model, params)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class CountConstraint < Gecode::ReifiableConstraint #:nodoc:
|
48
|
+
def post
|
49
|
+
enum, element, relation_type, rhs =
|
50
|
+
@params.values_at(:enum, :element, :relation_type, :rhs)
|
51
|
+
|
52
|
+
# Bind variables if needed.
|
53
|
+
unless element.kind_of? Fixnum
|
54
|
+
element = element.to_int_var.bind
|
55
|
+
end
|
56
|
+
unless rhs.kind_of? Fixnum
|
57
|
+
rhs = rhs.to_int_var.bind
|
58
|
+
end
|
59
|
+
|
60
|
+
# Post the constraint to gecode.
|
61
|
+
Gecode::Raw::count(@model.active_space, enum.to_int_enum.bind_array,
|
62
|
+
element, relation_type, rhs, *propagation_options)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Gecode::IntEnum
|
2
|
+
class IntEnumConstraintReceiver
|
3
|
+
# Constrains all integer operands in the enumeration to be distinct
|
4
|
+
# (different). The constraint can also be used with constant
|
5
|
+
# offsets, so that the operands, with specified offsets added, must
|
6
|
+
# be distinct.
|
7
|
+
#
|
8
|
+
# The constraint does not support negation nor reification.
|
9
|
+
#
|
10
|
+
# ==== Examples
|
11
|
+
#
|
12
|
+
# # Constrains all operands in +int_enum+ to be assigned different
|
13
|
+
# # values.
|
14
|
+
# int_enum.must_be.distinct
|
15
|
+
#
|
16
|
+
# # The same as above, but also selects that the strength +domain+ should
|
17
|
+
# # be used.
|
18
|
+
# int_enum.must_be.distinct(:strength => :domain)
|
19
|
+
#
|
20
|
+
# # Uses the offset to constrain that no number may be the previous number
|
21
|
+
# # incremented by one.
|
22
|
+
# numbers = int_var_array(8, 0..9)
|
23
|
+
# numbers.must_be.distinct(:offsets => (1..numbers.size).to_a.reverse)
|
24
|
+
def distinct(options = {})
|
25
|
+
if @params[:negate]
|
26
|
+
# The best we could implement it as from here would be a bunch of
|
27
|
+
# reified pairwise equality constraints.
|
28
|
+
raise Gecode::MissingConstraintError, 'A negated distinct is not ' +
|
29
|
+
'implemented.'
|
30
|
+
end
|
31
|
+
unless options[:reify].nil?
|
32
|
+
raise ArgumentError, 'Reification is not supported by the distinct ' +
|
33
|
+
'constraint.'
|
34
|
+
end
|
35
|
+
|
36
|
+
if options.has_key? :offsets
|
37
|
+
offsets = options.delete(:offsets)
|
38
|
+
unless offsets.kind_of? Enumerable
|
39
|
+
raise TypeError, 'Expected Enumerable as offsets, got ' +
|
40
|
+
"#{offsets.class}."
|
41
|
+
end
|
42
|
+
@params[:offsets] = offsets
|
43
|
+
end
|
44
|
+
@model.add_constraint Distinct::DistinctConstraint.new(@model,
|
45
|
+
@params.update(Gecode::Util.decode_options(options)))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# A module that gathers the classes and modules used in distinct constraints.
|
50
|
+
module Distinct #:nodoc:
|
51
|
+
class DistinctConstraint < Gecode::Constraint #:nodoc:
|
52
|
+
def post
|
53
|
+
# Bind lhs.
|
54
|
+
@params[:lhs] = @params[:lhs].to_int_enum.bind_array
|
55
|
+
|
56
|
+
# Fetch the parameters to Gecode.
|
57
|
+
params = @params.values_at(:offsets, :lhs)
|
58
|
+
params.delete_if{ |x| x.nil? }
|
59
|
+
params.concat propagation_options
|
60
|
+
Gecode::Raw::distinct(@model.active_space, *params)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Gecode::IntEnum
|
2
|
+
module IntEnumOperand
|
3
|
+
# This adds the adder for the methods in the modules including it. The
|
4
|
+
# reason for doing it so indirect is that the first #[] won't be defined
|
5
|
+
# before the module that this is mixed into is mixed into an enum.
|
6
|
+
def self.included(enum_mod) #:nodoc:
|
7
|
+
enum_mod.module_eval do
|
8
|
+
# Now we enter the module IntEnumOperands is mixed into.
|
9
|
+
class << self
|
10
|
+
alias_method :pre_element_included, :included
|
11
|
+
def included(mod) #:nodoc:
|
12
|
+
mod.module_eval do
|
13
|
+
if instance_methods.include? '[]'
|
14
|
+
alias_method :pre_element_access, :[]
|
15
|
+
end
|
16
|
+
|
17
|
+
# Produces an IntOperand representing the
|
18
|
+
# i:th integer operand in the enumeration, where i is the
|
19
|
+
# value of the integer operand used as index. Think of it
|
20
|
+
# as array access in the world of constraint programming.
|
21
|
+
#
|
22
|
+
# ==== Examples
|
23
|
+
#
|
24
|
+
# # The operand at the +x+:th position in +int_enum+,
|
25
|
+
# # where +x+ is an integer operand.
|
26
|
+
# int_enum[x]
|
27
|
+
#
|
28
|
+
def [](*vars)
|
29
|
+
if vars.first.respond_to? :to_int_var
|
30
|
+
return Element::ElementIntOperand.new(
|
31
|
+
model, self, vars.first)
|
32
|
+
else
|
33
|
+
pre_element_access(*vars) if respond_to? :pre_element_access
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
pre_element_included(mod)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
module Element #:nodoc:
|
45
|
+
class ElementIntOperand < Gecode::Int::ShortCircuitEqualityOperand #:nodoc:
|
46
|
+
def initialize(model, enum_op, position_int_var_op)
|
47
|
+
super model
|
48
|
+
@enum = enum_op
|
49
|
+
@position = position_int_var_op
|
50
|
+
end
|
51
|
+
|
52
|
+
def constrain_equal(int_operand, constrain, propagation_options)
|
53
|
+
enum = @enum.to_int_enum
|
54
|
+
if constrain
|
55
|
+
int_operand.must_be.in enum.domain_range
|
56
|
+
end
|
57
|
+
|
58
|
+
Gecode::Raw::element(model.active_space, enum.bind_array,
|
59
|
+
@position.to_int_var.bind, int_operand.to_int_var.bind,
|
60
|
+
*propagation_options)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Gecode::IntEnum
|
2
|
+
class IntEnumConstraintReceiver
|
3
|
+
# Constrains all operands in the enumeration to be equal.
|
4
|
+
# Neither negation nor reification is supported.
|
5
|
+
#
|
6
|
+
# ==== Examples
|
7
|
+
#
|
8
|
+
# # Constrains all operands in +int_enum+ to be equal.
|
9
|
+
# int_enum.must_be.equal
|
10
|
+
def equal(options = {})
|
11
|
+
if @params[:negate]
|
12
|
+
# The best we could implement it as from here would be a bunch of
|
13
|
+
# reified pairwise inequality constraints.
|
14
|
+
raise Gecode::MissingConstraintError, 'A negated equality is not ' +
|
15
|
+
'implemented.'
|
16
|
+
end
|
17
|
+
unless options[:reify].nil?
|
18
|
+
raise ArgumentError, 'Reification is not supported by the equality ' +
|
19
|
+
'constraint.'
|
20
|
+
end
|
21
|
+
|
22
|
+
@model.add_constraint Equality::EqualityConstraint.new(@model,
|
23
|
+
@params.update(Gecode::Util.decode_options(options)))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# A module that gathers the classes and modules used in equality constraints.
|
28
|
+
module Equality #:nodoc:
|
29
|
+
class EqualityConstraint < Gecode::Constraint #:nodoc:
|
30
|
+
def post
|
31
|
+
Gecode::Raw::rel(@model.active_space,
|
32
|
+
@params[:lhs].to_int_enum.bind_array,
|
33
|
+
Gecode::Raw::IRT_EQ, *propagation_options)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
module Gecode::IntEnum
|
2
|
+
class IntEnumConstraintReceiver
|
3
|
+
# Constrains all the operands in this enumeration to be equal to
|
4
|
+
# one of the specified tuples. Neither negation nor reification is
|
5
|
+
# supported.
|
6
|
+
#
|
7
|
+
# ==== Examples
|
8
|
+
#
|
9
|
+
# # Constrains the two integer operands in +numbers+ to either have
|
10
|
+
# # values 1 and 7, or values 47 and 11.
|
11
|
+
# numbers.must_be.in [[1,7], [47,11]]
|
12
|
+
#
|
13
|
+
# # The same as above, but preferring speed over low memory usage.
|
14
|
+
# numbers.must_be.in([[1,7], [47,11]], :kind => :speed)
|
15
|
+
def in(tuples, options = {})
|
16
|
+
if @params[:negate]
|
17
|
+
raise Gecode::MissingConstraintError, 'A negated tuple constraint is ' +
|
18
|
+
'not implemented.'
|
19
|
+
end
|
20
|
+
unless options[:reify].nil?
|
21
|
+
raise ArgumentError, 'Reification is not supported by the tuple ' +
|
22
|
+
'constraint.'
|
23
|
+
end
|
24
|
+
|
25
|
+
util = Gecode::Util
|
26
|
+
|
27
|
+
# Check that the tuples are correct.
|
28
|
+
expected_size = @params[:lhs].size
|
29
|
+
util::Extensional.perform_tuple_checks(tuples, expected_size) do |tuple|
|
30
|
+
unless tuple.all?{ |x| x.kind_of? Fixnum }
|
31
|
+
raise TypeError, 'All tuples must contain Fixnum.'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
@params[:tuples] = tuples
|
36
|
+
@model.add_constraint Extensional::TupleConstraint.new(@model,
|
37
|
+
@params.update(util.decode_options(options)))
|
38
|
+
end
|
39
|
+
|
40
|
+
# Constrains the sequence of operands in this enumeration to match
|
41
|
+
# a specified regexp in the integer domain. Neither negation nor
|
42
|
+
# reification is supported.
|
43
|
+
#
|
44
|
+
# == Regexp syntax
|
45
|
+
#
|
46
|
+
# The regular expressions are specified using arrays, integers and a
|
47
|
+
# few methods provided by Model. Arrays are used to group the
|
48
|
+
# integers in sequences that must be matched. The following array
|
49
|
+
# describes a regular expression matching a 1 followed by a 7.
|
50
|
+
#
|
51
|
+
# [1, 7]
|
52
|
+
#
|
53
|
+
# Arrays can be nested or left out when not needed. I.e. the above
|
54
|
+
# is semantically equal to
|
55
|
+
#
|
56
|
+
# [[[1], 7]]
|
57
|
+
#
|
58
|
+
# A couple of methods provided by Model are used to express patterns
|
59
|
+
# beyond mere sequences:
|
60
|
+
#
|
61
|
+
# [Model#repeat] Used for specifying patterns that include patterns
|
62
|
+
# that may be repeated a given number of times. The
|
63
|
+
# number of times to repeat a pattern can be specified
|
64
|
+
# using a lower and upper bound, but the bounds can be
|
65
|
+
# omitted to for instance allow an expression to be
|
66
|
+
# repeated any number of times.
|
67
|
+
# [Model#any] Used for specifying alternatives.
|
68
|
+
#
|
69
|
+
# Additionally Model#at_least_once and Model#at_most_once are
|
70
|
+
# provided as convenience methods.
|
71
|
+
#
|
72
|
+
# ==== Examples
|
73
|
+
#
|
74
|
+
# # Matches 1 followed by any number of 2s.
|
75
|
+
# [1, repeat(2)]
|
76
|
+
#
|
77
|
+
# # Semantically the same as above. It just has a bunch of
|
78
|
+
# # needless brackets thrown in.
|
79
|
+
# [[1], [repeat([2])]]
|
80
|
+
#
|
81
|
+
# # Matches 1 followed by [a 2 followed by a 3] at least two times.
|
82
|
+
# # Matches e.g. 1, 2, 3, 2, 3
|
83
|
+
# [1, repeat([2, 3], 2)]
|
84
|
+
#
|
85
|
+
# # Matches between one and two [2 followed by [at least three 1]]
|
86
|
+
# # followed by between three and four 3. Matches e.g.
|
87
|
+
# # 2, 1, 1, 1, 2, 1, 1, 1, 3, 3, 3
|
88
|
+
# [repeat([2, repeat(1, 3], 1, 2), repeat(3, 3, 4)]
|
89
|
+
#
|
90
|
+
# # Matches [1, 2 or 3] followed by 4. Matches e.g. 2, 4
|
91
|
+
# [any(1, 2, 3), 4]
|
92
|
+
#
|
93
|
+
# # Matches 0 followed by [[1 followed by 2] or [3 followed by 5]].
|
94
|
+
# # Matches e.g. 0, 1, 2 as well as 0, 3, 5
|
95
|
+
# [0, any([1, 2], [3, 5])]
|
96
|
+
#
|
97
|
+
# # Matches 0 followed by [[[1 followed by 7] at least two times]
|
98
|
+
# # or [[8, 9], at most two times]. Matches e.g.
|
99
|
+
# # 0, 1, 7, 1, 7, 1, 7 as well as 0, 8, 9
|
100
|
+
# [0, any(repeat([1, 7], 2), repeat([8, 9], 0, 2)]
|
101
|
+
#
|
102
|
+
# # Matches 0 followed by at least one 1.
|
103
|
+
# [0, at_least_once(1)]
|
104
|
+
#
|
105
|
+
# # Exactly the same as the above.
|
106
|
+
# [0, repeat(1, 1)]
|
107
|
+
#
|
108
|
+
# # Matches 0 followed by at least one [[1 followed by 7] or [3
|
109
|
+
# # followed by 2]]. Matches e.g. 0, 1, 7, 3, 2, 1, 7
|
110
|
+
# [0, at_least_once(any([1, 7], [3, 2]]
|
111
|
+
#
|
112
|
+
# # Matches 0 followed by at either [[1 followed by 7] at least once]
|
113
|
+
# # or [[3 followed by 2] at least once]. Matches e.g.
|
114
|
+
# # 0, 1, 7, 1, 7 but does _not_ match 0, 1, 7, 3, 2, 1, 7
|
115
|
+
# [0, any(at_least_once([1, 7]), at_least_once([3, 2])]
|
116
|
+
#
|
117
|
+
# # Matches 0, followed by at most one 1. Matches 0 as well as
|
118
|
+
# # 0, 1
|
119
|
+
# [0, at_most_once(1)]
|
120
|
+
#
|
121
|
+
# # Exactly the same as the above.
|
122
|
+
# [0, repeat(1, 0, 1)]
|
123
|
+
#
|
124
|
+
# ==== Examples
|
125
|
+
#
|
126
|
+
# # Constrains the two integer operands in +numbers+ to have
|
127
|
+
# # values 1 and 7.
|
128
|
+
# numbers.must.match [1, 7]
|
129
|
+
#
|
130
|
+
# # Constrains the integer operands in +numbers+ to contain the
|
131
|
+
# # value 47 followed by 11, with all other values set to -1.
|
132
|
+
# numbers.must.match [repeat(-1), 47, 11, repeat(-1)]
|
133
|
+
#
|
134
|
+
# # Constrains exactly three of the integer operands in +numbers+ to
|
135
|
+
# # contain 47 or 11, each followed by at least two
|
136
|
+
# # operands set to -1. All other operands are constrained to
|
137
|
+
# # equal -1.
|
138
|
+
# numbers.must.match repeat([repeat(-1), any(11, 47),
|
139
|
+
# repeat(-1, 2)], 3, 3)
|
140
|
+
#
|
141
|
+
def match(regexp, options = {})
|
142
|
+
if @params[:negate]
|
143
|
+
raise Gecode::MissingConstraintError, 'A negated regexp constraint ' +
|
144
|
+
'is not implemented.'
|
145
|
+
end
|
146
|
+
unless options[:reify].nil?
|
147
|
+
raise ArgumentError, 'Reification is not supported by the regexp ' +
|
148
|
+
'constraint.'
|
149
|
+
end
|
150
|
+
|
151
|
+
@params[:regexp] =
|
152
|
+
Gecode::Util::Extensional.parse_regexp regexp
|
153
|
+
@params.update Gecode::Util.decode_options(options)
|
154
|
+
@model.add_constraint Extensional::RegexpConstraint.new(@model, @params)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# A module that gathers the classes and modules used in extensional
|
159
|
+
# constraints.
|
160
|
+
module Extensional #:nodoc:
|
161
|
+
class TupleConstraint < Gecode::Constraint #:nodoc:
|
162
|
+
def post
|
163
|
+
# Bind lhs.
|
164
|
+
lhs = @params[:lhs].to_int_enum.bind_array
|
165
|
+
|
166
|
+
# Create the tuple set.
|
167
|
+
tuple_set = Gecode::Raw::TupleSet.new
|
168
|
+
@params[:tuples].each do |tuple|
|
169
|
+
tuple_set.add tuple
|
170
|
+
end
|
171
|
+
tuple_set.finalize
|
172
|
+
|
173
|
+
# Post the constraint.
|
174
|
+
Gecode::Raw::extensional(@model.active_space, lhs, tuple_set,
|
175
|
+
*propagation_options)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
class RegexpConstraint < Gecode::Constraint #:nodoc:
|
180
|
+
def post
|
181
|
+
lhs, regexp = @params.values_at(:lhs, :regexp)
|
182
|
+
Gecode::Raw::extensional(@model.active_space,
|
183
|
+
lhs.to_int_enum.bind_array, regexp, *propagation_options)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
module Gecode::IntEnum
|
2
|
+
class IntEnumConstraintReceiver
|
3
|
+
# Constrains the elements in this enumeration to be sorted in ascending
|
4
|
+
# order. The following options can be given in addition to the
|
5
|
+
# common constraint options:
|
6
|
+
#
|
7
|
+
# [:as] Defines a target (must be an IntEnum) that will
|
8
|
+
# hold the sorted version of the original enumerable. The original
|
9
|
+
# enumerable will not be affected (i.e. will not necessarily be
|
10
|
+
# sorted)
|
11
|
+
# [:order] Sets an IntEnum that should be used to store the
|
12
|
+
# order of the original enum's operands when sorted. The original
|
13
|
+
# enumerable will not be affected (i.e. will not necessarily be
|
14
|
+
# sorted)
|
15
|
+
#
|
16
|
+
# If neither of those options are specified then the original enumerable
|
17
|
+
# will be constrained to be sorted (otherwise not). Sort constraints with
|
18
|
+
# options do not allow negation.
|
19
|
+
#
|
20
|
+
# ==== Examples
|
21
|
+
#
|
22
|
+
# # Constrain +numbers+ to be sorted.
|
23
|
+
# numbers.must_be.sorted
|
24
|
+
#
|
25
|
+
# # Constrain +numbers+ to not be sorted.
|
26
|
+
# numbers.must_not_be.sorted
|
27
|
+
#
|
28
|
+
# # Constrain +sorted_numbers+ to be a sorted version of +numbers+.
|
29
|
+
# numbers.must_be.sorted(:as => sorted_numbers)
|
30
|
+
#
|
31
|
+
# # Constrain +order+ to be the order in which +numbers+ has to be
|
32
|
+
# # ordered to be sorted.
|
33
|
+
# numbers.must_be.sorted(:order => order)
|
34
|
+
#
|
35
|
+
# # Constrain +sorted_numbers+ to be +numbers+ sorted in the order
|
36
|
+
# # described by the IntEnum +order+.
|
37
|
+
# numbers.must_be.sorted(:as => sorted_numbers, :order => order)
|
38
|
+
#
|
39
|
+
# # Constrains +numbers+ to be sorted, reifying with the boolean
|
40
|
+
# # operand +is_sorted+, while selecting +domain+ as strength.
|
41
|
+
# numbers.must_be.sorted(:reify => :is_sorted, :strength => :domain)
|
42
|
+
def sorted(options = {})
|
43
|
+
# Extract and check options.
|
44
|
+
target = options.delete(:as)
|
45
|
+
order = options.delete(:order)
|
46
|
+
unless target.nil? or target.respond_to? :to_int_enum
|
47
|
+
raise TypeError, 'Expected int var enum as :as, got ' +
|
48
|
+
"#{target.class}."
|
49
|
+
end
|
50
|
+
unless order.nil? or order.respond_to? :to_int_enum
|
51
|
+
raise TypeError, 'Expected int var enum as :order, got ' +
|
52
|
+
"#{order.class}."
|
53
|
+
end
|
54
|
+
|
55
|
+
# Extract standard options and convert to constraint.
|
56
|
+
reified = !options[:reify].nil?
|
57
|
+
@params.update(Gecode::Util.decode_options(options))
|
58
|
+
if target.nil? and order.nil?
|
59
|
+
@model.add_constraint Sort::SortConstraint.new(@model, @params)
|
60
|
+
else
|
61
|
+
# Do not allow negation.
|
62
|
+
if @params[:negate]
|
63
|
+
raise Gecode::MissingConstraintError, 'A negated sort with options ' +
|
64
|
+
'is not implemented.'
|
65
|
+
end
|
66
|
+
if reified
|
67
|
+
raise ArgumentError, 'Reification is not supported by the sorted ' +
|
68
|
+
'constraint.'
|
69
|
+
end
|
70
|
+
|
71
|
+
@params.update(:target => target, :order => order)
|
72
|
+
@model.add_constraint Sort::SortConstraintWithOptions.new(@model,
|
73
|
+
@params)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# A module that gathers the classes and modules used in sort constraints.
|
79
|
+
module Sort #:nodoc:
|
80
|
+
class SortConstraintWithOptions < Gecode::Constraint #:nodoc:
|
81
|
+
def post
|
82
|
+
if @params[:target].nil?
|
83
|
+
# We must have a target.
|
84
|
+
lhs = @params[:lhs].to_int_enum
|
85
|
+
@params[:target] = @model.int_var_array(lhs.size, lhs.domain_range)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Prepare the parameters.
|
89
|
+
params = @params.values_at(:lhs, :target, :order).map do |param|
|
90
|
+
if param.respond_to? :to_int_enum
|
91
|
+
param.to_int_enum.bind_array
|
92
|
+
else
|
93
|
+
param
|
94
|
+
end
|
95
|
+
end.delete_if{ |param| param.nil? }
|
96
|
+
params.concat propagation_options
|
97
|
+
|
98
|
+
# Post the constraint.
|
99
|
+
Gecode::Raw::sorted(@model.active_space, *params)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class SortConstraint < Gecode::ReifiableConstraint #:nodoc:
|
104
|
+
def post
|
105
|
+
lhs, strength, kind, reif_var =
|
106
|
+
@params.values_at(:lhs, :strength, :kind, :reif)
|
107
|
+
using_reification = !reif_var.nil?
|
108
|
+
|
109
|
+
# We translate the constraint into n-1 relation constraints.
|
110
|
+
options = {
|
111
|
+
:strength =>
|
112
|
+
Gecode::Util::PROPAGATION_STRENGTHS.invert[strength],
|
113
|
+
:kind =>
|
114
|
+
Gecode::Util::PROPAGATION_KINDS.invert[kind]
|
115
|
+
}
|
116
|
+
if using_reification
|
117
|
+
reification_variables = @model.bool_var_array(lhs.size - 1)
|
118
|
+
end
|
119
|
+
(lhs.size - 1).times do |i|
|
120
|
+
first, second = lhs[i, 2]
|
121
|
+
rel_options = options.clone
|
122
|
+
if using_reification
|
123
|
+
# Reify each relation constraint and then bind them all together.
|
124
|
+
rel_options[:reify] = reification_variables[i]
|
125
|
+
end
|
126
|
+
first.must_be.less_than_or_equal_to(second, rel_options)
|
127
|
+
end
|
128
|
+
if using_reification
|
129
|
+
reification_variables.conjunction.must == reif_var
|
130
|
+
end
|
131
|
+
end
|
132
|
+
negate_using_reification
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|