Name | Total Lines | Lines of Code | Total Coverage | Code Coverage |
---|---|---|---|---|

lib/gecoder/interface/constraints/int_enum/extensional.rb | 187 |
59 |
100.00% |
100.00% |

Code reported as executed by Ruby looks like this...and this: this line is also marked as covered.Lines considered as run by rcov, but not reported by Ruby, look like this,and this: these lines were inferred by rcov (using simple heuristics).Finally, here's a line marked as not executed.

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 Mixin. 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 Mixin are used to express patterns |

59 # beyond mere sequences: |

60 # |

61 # [Mixin#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 # [Mixin#any] Used for specifying alternatives. |

68 # |

69 # Additionally Mixin#at_least_once and Mixin#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 |

Generated on Thu Jan 08 13:27:03 +0100 2015 with rcov 1.0.0