dither 0.1.5-java → 0.2.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +6 -1
- data/README.md +3 -0
- data/Rakefile +4 -0
- data/dither.gemspec +5 -1
- data/ext/dither/README.md +2 -0
- data/ext/dither/base_constraint_handler.h +36 -0
- data/ext/dither/combinations.h +127 -0
- data/ext/dither/dither.cc +47 -0
- data/ext/dither/dither.h +31 -0
- data/ext/dither/dither_types.h +32 -0
- data/ext/dither/extconf.rb +4 -0
- data/ext/dither/ipog.cc +451 -0
- data/ext/dither/ipog.h +128 -0
- data/ext/dither/simple_constraint_handler.cc +105 -0
- data/ext/dither/simple_constraint_handler.h +39 -0
- data/lib/dither/api.rb +21 -0
- data/lib/dither/version.rb +1 -1
- data/lib/{dither-0.1.3.jar → dither-0.1.4.jar} +0 -0
- data/lib/dither.rb +65 -14
- data/spec/dither/dither_spec.rb +28 -97
- metadata +42 -22
- data/lib/dither/ipog.rb +0 -58
- data/lib/dither/ipog_helper.rb +0 -161
- data/lib/dither/mipog.rb +0 -85
- data/lib/dither/param.rb +0 -19
- data/lib/dither/test_case.rb +0 -80
- data/lib/dither/unbound_param.rb +0 -17
data/lib/dither/ipog_helper.rb
DELETED
@@ -1,161 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
module Dither
|
4
|
-
module IPOGHelper
|
5
|
-
attr_reader :params, :t, :constraints, :test_set, :orig_params, :unbound_param_pool, :tested
|
6
|
-
private :params, :t, :constraints, :test_set, :orig_params, :unbound_param_pool, :tested
|
7
|
-
|
8
|
-
def initialize(params, opts = {})
|
9
|
-
init_params(params, (opts[:previously_tested] || []))
|
10
|
-
@t = opts[:t]
|
11
|
-
unless opts[:constraints].nil?
|
12
|
-
@constraints = opts[:constraints].map(&:to_a)
|
13
|
-
.map { |a| a.map { |b| @params[@map_to_orig_index.key(b[0])][b[1]] } }
|
14
|
-
.map(&:to_set)
|
15
|
-
end
|
16
|
-
|
17
|
-
raise Dither::Error, 't must be >= 2' if opts[:t] < 2
|
18
|
-
raise Dither::Error, 't must be <= params.length' if opts[:t] > params.length
|
19
|
-
params.each do |param|
|
20
|
-
raise Dither::Error, 'param length must be > 1' if param.length < 2
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def init_params(user_params, previously_tested)
|
25
|
-
tmp = []
|
26
|
-
@input_params = user_params
|
27
|
-
user_params.each_with_index { |e, i| tmp << [i, e] }
|
28
|
-
@orig_params = tmp.sort_by { |a| a[1].length }
|
29
|
-
.reverse!
|
30
|
-
|
31
|
-
orig_param_map = {}
|
32
|
-
@map_to_orig_index = {}
|
33
|
-
@orig_params.each_with_index do |e, i|
|
34
|
-
@map_to_orig_index[i] = e[0]
|
35
|
-
orig_param_map[e[0]] = {}
|
36
|
-
end
|
37
|
-
|
38
|
-
@params = []
|
39
|
-
@unbound_param_pool = []
|
40
|
-
orig_params.each_with_index do |e, i|
|
41
|
-
@params << (0...e[1].length).map do |j|
|
42
|
-
local_param = Param.new(i, j)
|
43
|
-
orig_param_map[e[0]][e[1][j]] = local_param
|
44
|
-
local_param
|
45
|
-
end
|
46
|
-
@unbound_param_pool << UnboundParam.new(i)
|
47
|
-
end
|
48
|
-
|
49
|
-
@tested = []
|
50
|
-
previously_tested.each do |a|
|
51
|
-
local_params = []
|
52
|
-
a.each_with_index do |e, i|
|
53
|
-
local_params << orig_param_map[i][e]
|
54
|
-
end
|
55
|
-
@tested << TestCase.create(params, unbound_param_pool, local_params)
|
56
|
-
end
|
57
|
-
|
58
|
-
params
|
59
|
-
end
|
60
|
-
|
61
|
-
# return nil if unable to satisfy constraints
|
62
|
-
def maximize_coverage(i, test_case, pi)
|
63
|
-
current_max = 0
|
64
|
-
current_max_j = 0
|
65
|
-
current_matches = []
|
66
|
-
|
67
|
-
(0...params[i].length).each do |j|
|
68
|
-
current_param = params[i][j]
|
69
|
-
test_case << current_param
|
70
|
-
unless violates_constraints?(test_case)
|
71
|
-
matches = pi.select { |a| a.subset?(test_case) }
|
72
|
-
count = matches.count
|
73
|
-
|
74
|
-
if count > current_max
|
75
|
-
current_max = count
|
76
|
-
current_max_j = j
|
77
|
-
current_matches = matches
|
78
|
-
end
|
79
|
-
end
|
80
|
-
test_case.delete(current_param)
|
81
|
-
end
|
82
|
-
|
83
|
-
return nil if violates_constraints?(test_case)
|
84
|
-
test_case << params[i][current_max_j]
|
85
|
-
|
86
|
-
current_matches
|
87
|
-
end
|
88
|
-
|
89
|
-
def violates_constraints?(params)
|
90
|
-
return false if constraints.nil?
|
91
|
-
constraints.any? { |b| b.subset?(params) }
|
92
|
-
end
|
93
|
-
|
94
|
-
private
|
95
|
-
|
96
|
-
def comb
|
97
|
-
ranges = (0...t).to_a.inject([]) do |a, i|
|
98
|
-
a << (0...params[i].length).map { |j| params[i][j] }
|
99
|
-
end
|
100
|
-
|
101
|
-
products = ranges[1..-1].inject(ranges[0]) do |a, b|
|
102
|
-
a = a.product(b)
|
103
|
-
end
|
104
|
-
|
105
|
-
result = products.map(&:flatten)
|
106
|
-
.map { |a| TestCase.create(params, unbound_param_pool, a) }
|
107
|
-
result.reject { |a| tested?(a) }
|
108
|
-
end
|
109
|
-
|
110
|
-
def comb_i(param_i)
|
111
|
-
values = (0...param_i).to_a.combination((t-1)).to_a
|
112
|
-
values.each do |a|
|
113
|
-
a << param_i
|
114
|
-
end
|
115
|
-
result = []
|
116
|
-
values.each do |a|
|
117
|
-
result += a[1..-1]
|
118
|
-
.inject((0...params[a[0]].length).map { |b| params[a[0]][b] }) { |p, i| p.product((0...params[i].length).to_a.map { |c| params[i][c] }) }
|
119
|
-
.map(&:flatten)
|
120
|
-
.map { |b| TestCase.create(params, unbound_param_pool, b) }
|
121
|
-
end
|
122
|
-
result.reject { |a| tested?(a) }.to_set
|
123
|
-
end
|
124
|
-
|
125
|
-
def tested?(test_case)
|
126
|
-
@tested.any? { |a| test_case.subset?(a) }
|
127
|
-
end
|
128
|
-
|
129
|
-
def fill_unbound(data)
|
130
|
-
arr = Array.new(params.length)
|
131
|
-
data.each do |param|
|
132
|
-
unless param.unbound?
|
133
|
-
i = @map_to_orig_index[param.i]
|
134
|
-
arr[i] = @input_params[i][param.j]
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
arr.each_with_index do |e, i|
|
139
|
-
next unless e.nil?
|
140
|
-
|
141
|
-
orig_param = @input_params[i]
|
142
|
-
(0...orig_param.length).each do |j|
|
143
|
-
data << params[@map_to_orig_index.key(i)][j]
|
144
|
-
if violates_constraints?(data)
|
145
|
-
data.delete(params[@map_to_orig_index.key(i)][j])
|
146
|
-
next
|
147
|
-
else
|
148
|
-
arr[i] = orig_param[j]
|
149
|
-
break
|
150
|
-
end
|
151
|
-
end
|
152
|
-
return nil if arr[i].nil?
|
153
|
-
end
|
154
|
-
|
155
|
-
return nil if violates_constraints?(data)
|
156
|
-
return nil if tested?(data)
|
157
|
-
|
158
|
-
arr
|
159
|
-
end
|
160
|
-
end # IPOGHelper
|
161
|
-
end # Dither
|
data/lib/dither/mipog.rb
DELETED
@@ -1,85 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
module Dither
|
4
|
-
class MIPOG
|
5
|
-
include Dither::IPOGHelper
|
6
|
-
|
7
|
-
def maximize_unbound_coverage(i, test_case, pi)
|
8
|
-
all_unbound = test_case.unbound
|
9
|
-
.map { |a| a.create_params(params[a.i].length) }
|
10
|
-
.flatten
|
11
|
-
|
12
|
-
current_max = 0
|
13
|
-
current_max_j = 0
|
14
|
-
current_outer_param = all_unbound[0]
|
15
|
-
current_matches = []
|
16
|
-
|
17
|
-
all_unbound.each do |outer_param|
|
18
|
-
test_case << outer_param
|
19
|
-
|
20
|
-
(0...params[i].length).each do |j|
|
21
|
-
current_param = params[i][j]
|
22
|
-
test_case << current_param
|
23
|
-
count = pi.count { |a| a.subset?(test_case) }
|
24
|
-
|
25
|
-
if count > current_max
|
26
|
-
current_max = count
|
27
|
-
current_max_j = j
|
28
|
-
current_outer_param = outer_param
|
29
|
-
end
|
30
|
-
test_case.delete(current_param)
|
31
|
-
end
|
32
|
-
test_case.delete(outer_param)
|
33
|
-
end
|
34
|
-
|
35
|
-
test_case << params[i][current_max_j]
|
36
|
-
test_case << current_outer_param
|
37
|
-
test_case.delete(unbound_param_pool[current_outer_param.i])
|
38
|
-
|
39
|
-
current_matches
|
40
|
-
end
|
41
|
-
|
42
|
-
def run
|
43
|
-
# add into test set a test for each combination of values
|
44
|
-
# of the first t parameter
|
45
|
-
test_set = comb
|
46
|
-
|
47
|
-
(t...params.length).each do |i|
|
48
|
-
# let pi
|
49
|
-
# be the set of t-way combinations of values involving
|
50
|
-
# parameter Pi and t -1 parameters among the first i – 1
|
51
|
-
# parameters
|
52
|
-
pi = comb_i(i)
|
53
|
-
|
54
|
-
# horizontal extension for parameter i
|
55
|
-
test_set.each do |test_case|
|
56
|
-
if !test_case.contains_unbound?
|
57
|
-
cover = maximize_coverage(i, test_case, pi)
|
58
|
-
else
|
59
|
-
cover = maximize_unbound_coverage(i, test_case, pi)
|
60
|
-
end
|
61
|
-
|
62
|
-
# remove covered combinations
|
63
|
-
pi -= cover
|
64
|
-
end
|
65
|
-
|
66
|
-
# vertical extension for parameter i
|
67
|
-
until pi.empty?
|
68
|
-
pi.sort!
|
69
|
-
test_case, coverage = maximize_vertical_coverage(i, pi[0].dup, pi)
|
70
|
-
test_set << test_case.create_unbound(i)
|
71
|
-
pi -= coverage
|
72
|
-
end
|
73
|
-
end
|
74
|
-
test_set.map { |a| fill_unbound(a) }
|
75
|
-
end
|
76
|
-
|
77
|
-
def maximize_vertical_coverage(i, test_case, pi)
|
78
|
-
coverage = [pi[0]]
|
79
|
-
pi[1..-1].each do |a|
|
80
|
-
coverage << a unless test_case.merge_without_conflict(i, a).nil?
|
81
|
-
end
|
82
|
-
[test_case, coverage]
|
83
|
-
end
|
84
|
-
end # MIPOG
|
85
|
-
end # Dither
|
data/lib/dither/param.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
|
2
|
-
module Dither
|
3
|
-
Param = Struct.new(:i, :j) do
|
4
|
-
def <=>(param)
|
5
|
-
return 1 if param.unbound?
|
6
|
-
|
7
|
-
a = i <=> param.i
|
8
|
-
if a == 0
|
9
|
-
return j <=> param.j
|
10
|
-
else
|
11
|
-
return a
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def unbound?
|
16
|
-
false
|
17
|
-
end
|
18
|
-
end # Param
|
19
|
-
end # Dither
|
data/lib/dither/test_case.rb
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
|
2
|
-
module Dither
|
3
|
-
class TestCase < Set
|
4
|
-
|
5
|
-
attr_accessor :bound_param_pool, :unbound_param_pool
|
6
|
-
|
7
|
-
def self.create(bound_param_pool, unbound_param_pool, params)
|
8
|
-
test_case = TestCase.new(params)
|
9
|
-
test_case.bound_param_pool = bound_param_pool
|
10
|
-
test_case.unbound_param_pool = unbound_param_pool
|
11
|
-
test_case
|
12
|
-
end
|
13
|
-
|
14
|
-
def contains_unbound?
|
15
|
-
self.any?(&:unbound?)
|
16
|
-
end
|
17
|
-
|
18
|
-
def unbound
|
19
|
-
self.select(&:unbound?)
|
20
|
-
end
|
21
|
-
|
22
|
-
def <=>(test_case)
|
23
|
-
result = 0
|
24
|
-
l = length <= test_case.length ? length : test_case.length
|
25
|
-
self.zip(test_case)[0...l].each do |arr|
|
26
|
-
first, second = arr
|
27
|
-
result = first <=> second
|
28
|
-
break if result != 0
|
29
|
-
end
|
30
|
-
result
|
31
|
-
end
|
32
|
-
|
33
|
-
def create_unbound(i)
|
34
|
-
bound_params = self.reject(&:unbound?).map(&:i)
|
35
|
-
((0..i).to_a - bound_params).each do |a|
|
36
|
-
self << unbound_param_pool[a]
|
37
|
-
end
|
38
|
-
self
|
39
|
-
end
|
40
|
-
|
41
|
-
def to_ipog_array(i)
|
42
|
-
arr = Array.new(i)
|
43
|
-
self.each do |param|
|
44
|
-
arr[param.i] = param.j unless param.unbound?
|
45
|
-
end
|
46
|
-
arr
|
47
|
-
end
|
48
|
-
|
49
|
-
# return nil if there is a conflict
|
50
|
-
# return self if no conflict
|
51
|
-
def merge_without_conflict(i, test_case, &block)
|
52
|
-
new_elements = []
|
53
|
-
self.to_ipog_array(i).zip(test_case.to_ipog_array(i))
|
54
|
-
.each_with_index do |arr, a|
|
55
|
-
first, second = arr
|
56
|
-
|
57
|
-
if first.nil? && second.nil?
|
58
|
-
new_elements << unbound_param_pool[a]
|
59
|
-
elsif (first == second) || second.nil?
|
60
|
-
next
|
61
|
-
elsif first.nil?
|
62
|
-
new_elements << bound_param_pool[a][second]
|
63
|
-
else
|
64
|
-
return nil
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
new_self = self.clone
|
69
|
-
new_elements.each { |a| new_self << a }
|
70
|
-
|
71
|
-
return nil if block_given? && block.call(new_self)
|
72
|
-
|
73
|
-
new_elements.each do |a|
|
74
|
-
self.delete(unbound_param_pool[a.i]) unless a.unbound?
|
75
|
-
self << a
|
76
|
-
end
|
77
|
-
self
|
78
|
-
end
|
79
|
-
end # TestCase
|
80
|
-
end # Dither
|
data/lib/dither/unbound_param.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
|
2
|
-
module Dither
|
3
|
-
UnboundParam = Struct.new(:i) do
|
4
|
-
def <=>(param)
|
5
|
-
return -1 unless param.unbound?
|
6
|
-
i <=> param.i
|
7
|
-
end
|
8
|
-
|
9
|
-
def unbound?
|
10
|
-
true
|
11
|
-
end
|
12
|
-
|
13
|
-
def create_params(j)
|
14
|
-
(0...j).map { |a| Param.new(i, a) }
|
15
|
-
end
|
16
|
-
end # UnboundParam
|
17
|
-
end # Dither
|