Name | Total Lines | Lines of Code | Total Coverage | Code Coverage |
---|---|---|---|---|
lib/gecoder/interface/constraints/int_var_constraints.rb | 230 | 114 | 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 # A module that deals with the operands, properties and constraints of |
2 # integer variables. |
3 module Gecode::Int #:nodoc: |
4 # A IntOperand is a combination of variables on which the |
5 # constraints defined in IntConstraintReceiver can be placed. |
6 # |
7 # Integer operands can be created either by using |
8 # Gecode::Mixin#int_var et al, or by using properties that produce |
9 # integer operands. The operands, no matter how they were created, |
10 # all respond to the properties defined by IntOperand. |
11 # |
12 # ==== Examples |
13 # |
14 # Produces a single integer operand (more specifically an IntVar) with |
15 # domain 0..9 inside a problem formulation, using |
16 # Gecode::Mixin#int_var: |
17 # |
18 # int_operand = int_var(0..9) |
19 # |
20 # Uses the IntOperand#+ property to produce a new integer |
21 # operand representing +int_operand1+ plus +int_operand2+: |
22 # |
23 # new_int_operand = int_operand1 + int_operand2 |
24 # |
25 # Uses the IntEnumOperand#max property to produce a new |
26 # integer operand representing the maximum value of the integer operands |
27 # in the enumeration +int_enum+: |
28 # |
29 # new_int_operand = int_enum.max |
30 # |
31 # Uses the IntEnumOperand#[] property to produce a new integer operand |
32 # representing the integer operand at the index decided by |
33 # +int_operand+ (which can change during search) in the enumeration |
34 # +int_enum+: |
35 # |
36 # new_int_operand = int_enum[int_operand] |
37 # |
38 # Uses the SetOperand#size property to produce a new integer operand |
39 # representing the size of +set_operand+: |
40 # |
41 # new_int_operand = set_operand.size |
42 # |
43 #-- |
44 # Classes that mix in IntOperand must define #model and #to_int_var . |
45 module IntOperand |
46 include Gecode::Operand |
47 |
48 def method_missing(method, *args) #:nodoc: |
49 if Gecode::IntVar.instance_methods.include? method.to_s |
50 # Delegate to the int var. |
51 to_int_var.method(method).call(*args) |
52 else |
53 super |
54 end |
55 end |
56 |
57 private |
58 |
59 def construct_receiver(params) |
60 IntConstraintReceiver.new(model, params) |
61 end |
62 end |
63 |
64 # An operand that short circuits integer equality. |
65 class ShortCircuitEqualityOperand #:nodoc: |
66 include Gecode::Int::IntOperand |
67 attr :model |
68 |
69 def initialize(model) |
70 @model = model |
71 end |
72 |
73 def construct_receiver(params) |
74 params.update(:lhs => self) |
75 receiver = IntConstraintReceiver.new(@model, params) |
76 op = self |
77 receiver.instance_eval{ @short_circuit = op } |
78 class <<receiver |
79 alias_method :equality_without_short_circuit, :== |
80 def ==(operand, options = {}) |
81 if !@params[:negate] and options[:reify].nil? and |
82 operand.respond_to? :to_int_var |
83 # Short circuit the constraint. |
84 @params.update Gecode::Util.decode_options(options) |
85 @model.add_constraint(Gecode::BlockConstraint.new( |
86 @model, @params) do |
87 @short_circuit.constrain_equal(operand, false, |
88 @params.values_at(:strength, :kind)) |
89 end) |
90 else |
91 equality_without_short_circuit(operand, options) |
92 end |
93 end |
94 alias_comparison_methods |
95 end |
96 |
97 return receiver |
98 end |
99 |
100 def to_int_var |
101 variable = model.int_var |
102 options = |
103 Gecode::Util.decode_options({}).values_at(:strength, :kind) |
104 model.add_interaction do |
105 constrain_equal(variable, true, options) |
106 end |
107 return variable |
108 end |
109 |
110 private |
111 |
112 # Constrains this operand to equal +int_operand+ using the |
113 # specified +propagation_options+. If +constrain_domain+ is true |
114 # then the method should also attempt to constrain the bounds of the |
115 # domain of +int_operand+. |
116 def constrain_equal(int_operand, constrain_domain, propagation_options) |
117 raise NotImplementedError, 'Abstract method has not been implemented.' |
118 end |
119 end |
120 |
121 # An operand that short circuits integer relation constraints. |
122 class ShortCircuitRelationsOperand #:nodoc: |
123 include Gecode::Int::IntOperand |
124 attr :model |
125 |
126 def initialize(model) |
127 @model = model |
128 end |
129 |
130 def construct_receiver(params) |
131 receiver = IntConstraintReceiver.new(@model, params) |
132 op = self |
133 receiver.instance_eval{ @short_circuit = op } |
134 class <<receiver |
135 Gecode::Util::COMPARISON_ALIASES.keys.each do |comp| |
136 eval <<-end_code |
137 alias_method :alias_#{comp.to_i}_without_short_circuit, :#{comp} |
138 def #{comp}(operand, options = {}) |
139 if operand.respond_to?(:to_int_var) or operand.kind_of? Fixnum |
140 # Short circuit the constraint. |
141 @params.update Gecode::Util.decode_options(options) |
142 @model.add_constraint( |
143 @short_circuit.relation_constraint( |
144 :#{comp}, operand, @params)) |
145 else |
146 alias_#{comp.to_i}_without_short_circuit(operand, options) |
147 end |
148 end |
149 end_code |
150 end |
151 alias_comparison_methods |
152 end |
153 |
154 return receiver |
155 end |
156 |
157 def to_int_var |
158 variable = model.int_var |
159 params = {} |
160 params.update Gecode::Util.decode_options({}) |
161 model.add_constraint relation_constraint(:==, variable, params) |
162 return variable |
163 end |
164 |
165 # Returns a constraint that constrains this operand to have relation |
166 # +relation+ to +int_operand_or_fix+, which is either an integer |
167 # operand or a fixnum, given the specified hash +params+ of parameters. |
168 def relation_constraint(relation, int_operand_or_fix, params) |
169 raise NotImplementedError, 'Abstract method has not been implemented.' |
170 end |
171 end |
172 |
173 # IntConstraintReceiver contains all constraints that can be |
174 # placed on an IntOperand. |
175 # |
176 # Constraints are placed by calling IntOperand#must (or any other |
177 # of the variations defined in Operand), which produces a |
178 # IntConstraintReceiver from which the desired constraint can be used. |
179 # |
180 # Each constraint accepts a number of options. See ConstraintReceiver |
181 # for more information. |
182 # |
183 # ==== Examples |
184 # |
185 # Constrains +int_operand+ to be strictly greater than 5 using |
186 # IntConstraintReceiver#>: |
187 # |
188 # int_operand.must > 5 |
189 # |
190 # Constrains +int_operand1+ plus +int_operand2+ to be strictly |
191 # greater than 5 using the IntOperand#+ property and |
192 # IntConstraintReceiver#>: |
193 # |
194 # (int_operand1 + int_operand2).must > 5 |
195 # |
196 # Constrains the maximum value of the integer operands in +int_enum+ to |
197 # _not_ be in the range 3..7 using the IntEnumOperand#max property and |
198 # IntConstraintReceiver#in: |
199 # |
200 # int_enum.max.must_not_be.in 3..7 |
201 # |
202 # Constrains the integer operand at position +int_operand+ in |
203 # +int_enum+, an enumeration of integer operands, to be greater than |
204 # or equal to +int_operand2+. This uses the IntEnumOperand#[] property |
205 # and IntConstraintReceiver#>=: |
206 # |
207 # int_enum[int_operand].must >= int_operand2 |
208 # |
209 # The same as above, but specifying that strength :domain should be |
210 # used and that the constraint should be reified with +bool_operand+: |
211 # |
212 # int_enum[int_operand].must_be.greater_or_equal(int_operand2, :strength => :domain, :reify => bool_operand) |
213 # |
214 class IntConstraintReceiver < Gecode::ConstraintReceiver |
215 # Raises TypeError unless the left hand side is an int operand. |
216 def initialize(model, params) #:nodoc: |
217 super |
218 |
219 unless params[:lhs].respond_to? :to_int_var |
220 raise TypeError, 'Must have int operand as left hand side.' |
221 end |
222 end |
223 end |
224 end |
225 |
226 require 'gecoder/interface/constraints/int/relation' |
227 require 'gecoder/interface/constraints/int/linear' |
228 require 'gecoder/interface/constraints/int/domain' |
229 require 'gecoder/interface/constraints/int/arithmetic' |
230 require 'gecoder/interface/constraints/int/channel' |
Generated on Thu Jan 08 13:27:03 +0100 2015 with rcov 1.0.0