Class: Ibex::DeltaReducer
- Inherits:
-
Object
- Object
- Ibex::DeltaReducer
- Defined in:
- lib/ibex/delta_reducer.rb,
sig/ibex/delta_reducer.rbs
Overview
Deterministic, trial-bounded delta debugging over an ordered sequence.
Defined Under Namespace
Classes: Result
Instance Method Summary collapse
- #checked_trial!(trials) ⇒ Integer
-
#initialize(max_trials: 1_000) ⇒ DeltaReducer
constructor
A new instance of DeltaReducer.
-
#minimize(items, &failure) ⇒ void
failuremust return true while the failure of interest is preserved. - #partitions(length, count) ⇒ Array[Range[Integer]]
- #result(items, trials, complete, original_size) ⇒ Result
Constructor Details
#initialize(max_trials: 1_000) ⇒ DeltaReducer
Returns a new instance of DeltaReducer.
25 26 27 28 29 |
# File 'lib/ibex/delta_reducer.rb', line 25 def initialize(max_trials: 1_000) raise ArgumentError, "max_trials must be positive" unless max_trials.positive? @max_trials = max_trials end |
Instance Method Details
#checked_trial!(trials) ⇒ Integer
86 87 88 89 90 |
# File 'lib/ibex/delta_reducer.rb', line 86 def checked_trial!(trials) raise Ibex::Error, "(reduce):1:1: trial limit of #{@max_trials} is exhausted" if trials >= @max_trials trials + 1 end |
#minimize(items, &failure) ⇒ void
This method returns an undefined value.
failure must return true while the failure of interest is preserved.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/ibex/delta_reducer.rb', line 33 def minimize(items, &failure) raise ArgumentError, "a failure predicate is required" unless failure current = items.dup original_size = current.length trials = 0 trials = checked_trial!(trials) unless failure.call(current.freeze) raise Ibex::Error, "(reduce):1:1: original input does not reproduce the failure" end granularity = 2 while current.length >= 1 chunks = partitions(current.length, granularity) reduced = false chunks.each do |range| return result(current, trials, false, original_size) if trials >= @max_trials candidate = current.dup candidate.slice!(range) trials = checked_trial!(trials) next unless failure.call(candidate.freeze) current = candidate granularity = [granularity - 1, 2].max reduced = true break end next if reduced break if granularity >= current.length granularity = [granularity * 2, current.length].min end result(current, trials, true, original_size) end |
#partitions(length, count) ⇒ Array[Range[Integer]]
73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/ibex/delta_reducer.rb', line 73 def partitions(length, count) width = (length.to_f / count).ceil ranges = [] #: Array[Range[Integer]] count.times do |index| start = index * width break if start >= length ranges << (start...[start + width, length].min) end ranges end |