specs/constraints/channel.rb in gecoder-0.8.2 vs specs/constraints/channel.rb in gecoder-0.8.3
- old
+ new
@@ -24,14 +24,27 @@
def initialize
@bool_enum = bool_var_array(4)
@int = int_var(0..3)
@bool = bool_var
- branch_on wrap_enum([@int])
+ branch_on @int
end
end
+class SetChannelSampleProblem < Gecode::Model
+ attr :bool_enum
+ attr :set
+
+ def initialize
+ @bool_enum = bool_var_array(4)
+ @set = set_var([], 0..3)
+
+ branch_on @bool_enum
+ end
+end
+
+
describe Gecode::Constraints::IntEnum::Channel, ' (two int enums)' do
before do
@model = ChannelSampleProblem.new
@positions = @model.positions
@elements = @model.elements
@@ -71,14 +84,14 @@
it 'should raise error for unsupported right hand sides' do
lambda{ @elements.must.channel 'hello' }.should raise_error(TypeError)
end
- it_should_behave_like 'reifiable constraint'
+ it_should_behave_like 'non-reifiable constraint'
end
-describe Gecode::Constraints::IntEnum::Channel, ' (one int enum and one set enum)' do
+describe Gecode::Constraints::SetEnum::Channel::IntChannelConstraint, ' (channel with set as right hand side)' do
before do
@model = ChannelSampleProblem.new
@positions = @model.positions
@sets = @model.sets
@@ -111,11 +124,11 @@
end
it_should_behave_like 'non-reifiable set constraint'
end
-describe Gecode::Constraints::SetEnum, ' (channel with set as left hand side)' do
+describe Gecode::Constraints::SetEnum::Channel::IntChannelConstraint, ' (channel with set as left hand side)' do
before do
@model = ChannelSampleProblem.new
@positions = @model.positions
@sets = @model.sets
@@ -351,6 +364,91 @@
@int.must.channel 'hello'
end.should raise_error(TypeError)
end
it_should_behave_like 'channel constraint between bool enum and int variable'
+end
+
+# Requires @model, @bool_enum and @set. Also requires @place_constraint which
+# is a method that takes four variables: a boolean enum, a set variable,
+# whether or not the constraint should be negated and a hash of options, and
+# places the channel constraint on them.
+describe 'channel constraint between set variable and bool enum', :shared => true do
+ before do
+ @invoke_options = lambda do |hash|
+ @place_constraint.call(@bools, @set, false, hash)
+ @model.solve!
+ end
+ @expect_options = option_expectation do |strength, kind, reif_var|
+ Gecode::Raw.should_receive(:channel).once.with(
+ an_instance_of(Gecode::Raw::Space),
+ an_instance_of(Gecode::Raw::BoolVarArray),
+ an_instance_of(Gecode::Raw::SetVar))
+ end
+ end
+
+ it 'should channel the bool enum with the set variable' do
+ @set.must_be.superset_of [0, 2]
+ @place_constraint.call(@bools, @set, false, {})
+ @model.solve!.should_not be_nil
+ set_values = @set.value
+ @bools.values.each_with_index do |bool, index|
+ bool.should == set_values.include?(index)
+ end
+ end
+
+ it 'should not allow negation' do
+ lambda do
+ @place_constraint.call(@bools, @set, true, {})
+ end.should raise_error(Gecode::MissingConstraintError)
+ end
+
+ it_should_behave_like 'non-reifiable set constraint'
+end
+
+describe Gecode::Constraints::Set::Channel, ' (set variable as lhs with bool enum)' do
+ before do
+ @model = SetChannelSampleProblem.new
+ @bools = @model.bool_enum
+ @set = @model.set
+
+ @place_constraint = lambda do |bools, set, negate, options|
+ unless negate
+ set.must.channel(bools, options)
+ else
+ set.must_not.channel(bools, options)
+ end
+ end
+ end
+
+ it 'should raise error if a boolean enum is not given as right hand side' do
+ lambda do
+ @set.must.channel 'hello'
+ end.should raise_error(TypeError)
+ end
+
+ it_should_behave_like 'channel constraint between set variable and bool enum'
+end
+
+describe Gecode::Constraints::Set::Channel, ' (bool enum as lhs with set variable)' do
+ before do
+ @model = SetChannelSampleProblem.new
+ @bools = @model.bool_enum
+ @set = @model.set
+
+ @place_constraint = lambda do |bools, set, negate, options|
+ unless negate
+ bools.must.channel(set, options)
+ else
+ bools.must_not.channel(set, options)
+ end
+ end
+ end
+
+ it 'should raise error if an integer variable is not given as right hand side' do
+ lambda do
+ @bools.must.channel 'hello'
+ end.should raise_error(TypeError)
+ end
+
+ it_should_behave_like 'channel constraint between set variable and bool enum'
end