dither 0.2.2 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,120 @@
1
+ package com.github.jesg.dither;
2
+
3
+ import java.util.Arrays;
4
+
5
+ /*
6
+ * #%L
7
+ * dither
8
+ * %%
9
+ * Copyright (C) 2015 Jason Gowan
10
+ * %%
11
+ * Licensed under the Apache License, Version 2.0 (the "License");
12
+ * you may not use this file except in compliance with the License.
13
+ * You may obtain a copy of the License at
14
+ *
15
+ * http://www.apache.org/licenses/LICENSE-2.0
16
+ *
17
+ * Unless required by applicable law or agreed to in writing, software
18
+ * distributed under the License is distributed on an "AS IS" BASIS,
19
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
+ * See the License for the specific language governing permissions and
21
+ * limitations under the License.
22
+ * #L%
23
+ */
24
+
25
+ import java.util.Comparator;
26
+
27
+ class ConstraintHandler {
28
+
29
+ private final Pair[][] constraints;
30
+ private final int[] bounds;
31
+ private final int[] scratch;
32
+
33
+ ConstraintHandler(final Pair[][] constraints, final int[] bounds) {
34
+ this.constraints = constraints;
35
+ this.bounds = new int[bounds.length];
36
+ this.scratch = new int[bounds.length];
37
+ for(int i = 0; i < bounds.length; i++) {
38
+ this.bounds[i] = bounds[i] - 1;
39
+ }
40
+ Arrays.fill(scratch, -1);
41
+ Arrays.sort(this.constraints, new Comparator<Pair[]>() {
42
+ public int compare(final Pair[] a, final Pair[] b) { return a.length - b.length; }
43
+ });
44
+ }
45
+
46
+ boolean violateConstraints_(final int[] testCase) {
47
+ outer:
48
+ for(final Pair[] pairs : constraints) {
49
+ for(final Pair pair : pairs) {
50
+ final int value = testCase[pair.i];
51
+ if(value == -1 || value != pair.j) {
52
+ continue outer;
53
+ }
54
+ }
55
+ return true;
56
+ }
57
+ return false;
58
+ }
59
+
60
+ boolean violateConstraints(final int[] solution) {
61
+ if(violateConstraints_(solution)) {
62
+ return true;
63
+ }
64
+ for(int i = 0; i < solution.length; i++) {
65
+ scratch[i] = solution[i];
66
+ }
67
+ return groundSolution(scratch) == null;
68
+ }
69
+
70
+ boolean violateConstraints(final Pair[] pairs) {
71
+ Arrays.fill(scratch, -1);
72
+ for(int i = 0; i < pairs.length; i++) {
73
+ final Pair pair = pairs[i];
74
+ scratch[pair.i] = pair.j;
75
+ }
76
+ if(violateConstraints_(scratch)) {
77
+ return true;
78
+ }
79
+ return groundSolution(scratch) == null;
80
+ }
81
+
82
+ // return null if unable to find a solution
83
+ int[] groundSolution(final int[] solution) {
84
+ final int[] indexes = new int[solution.length];
85
+ int last_index = 0;
86
+ for(int i = 0; i < solution.length; i++) {
87
+ if(solution[i] == -1) {
88
+ indexes[last_index] = i;
89
+ ++last_index;
90
+ }
91
+ }
92
+ final int[] bound_values = new int[last_index + 1];
93
+ Arrays.fill(bound_values, -1);
94
+ int i = 0;
95
+
96
+ outer:
97
+ while(i < bound_values.length) {
98
+ final int max = bounds[indexes[i]];
99
+ for(int value = bound_values[i] + 1; value <= max; value++) {
100
+ solution[indexes[i]] = value;
101
+ if(violateConstraints_(solution)) {
102
+ continue;
103
+ }
104
+ bound_values[i] = value;
105
+ ++i;
106
+ continue outer;
107
+ }
108
+
109
+ if(i == 0) {
110
+ return null;
111
+ }
112
+
113
+ // unwind
114
+ bound_values[i] = -1;
115
+ solution[indexes[i]] = -1;
116
+ --i;
117
+ }
118
+ return solution;
119
+ }
120
+ }
@@ -0,0 +1,155 @@
1
+ package com.github.jesg.dither;
2
+
3
+ import java.util.Collections;
4
+ import java.util.List;
5
+ import java.util.concurrent.ExecutorService;
6
+ import java.util.concurrent.Executors;
7
+
8
+ /*
9
+ * #%L
10
+ * dither
11
+ * %%
12
+ * Copyright (C) 2015 Jason Gowan
13
+ * %%
14
+ * Licensed under the Apache License, Version 2.0 (the "License");
15
+ * you may not use this file except in compliance with the License.
16
+ * You may obtain a copy of the License at
17
+ *
18
+ * http://www.apache.org/licenses/LICENSE-2.0
19
+ *
20
+ * Unless required by applicable law or agreed to in writing, software
21
+ * distributed under the License is distributed on an "AS IS" BASIS,
22
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23
+ * See the License for the specific language governing permissions and
24
+ * limitations under the License.
25
+ * #L%
26
+ */
27
+
28
+ public class Dither {
29
+
30
+ public static final Integer[][] EMPTY_CONSTRAINTS = new Integer[][]{};
31
+ public static final Object[][] EMPTY_PREVIOUSLY_TESTED = new Object[][]{};
32
+
33
+ public static Object[][] ipog(final int t, final Object[][] params, final Integer[][] constraints, final Object[][] previouslyTested)
34
+ throws DitherError {
35
+ validateInput(t, params);
36
+ return new Ipog(params, t, constraints, previouslyTested).run();
37
+ }
38
+
39
+ public static Object[][] ipog(final int t, final Object[][] params, final Integer[][] constraints)
40
+ throws DitherError {
41
+ validateInput(t, params);
42
+ return new Ipog(params, t, constraints, EMPTY_PREVIOUSLY_TESTED).run();
43
+ }
44
+
45
+ public static Object[][] ipog(final int t, final Object[][] params)
46
+ throws DitherError {
47
+ validateInput(t, params);
48
+ return new Ipog(params, t, EMPTY_CONSTRAINTS, EMPTY_PREVIOUSLY_TESTED).run();
49
+ }
50
+
51
+ public static Object[][] ipog(final Object[][] params)
52
+ throws DitherError {
53
+ validateInput(2, params);
54
+ return new Ipog(params, 2, EMPTY_CONSTRAINTS, EMPTY_PREVIOUSLY_TESTED).run();
55
+ }
56
+
57
+ public static Object[][] ipog(final int t, final Object[] params, final Object[] constraints, final Object[] previouslyTested)
58
+ throws DitherError {
59
+ final Object[][] innerParams = new Object[params.length][];
60
+ for(int i = 0; i < innerParams.length; i++) {
61
+ innerParams[i] = (Object[]) params[i];
62
+ }
63
+ validateInput(t, innerParams);
64
+
65
+ final Integer[][] innerConstraints = new Integer[constraints.length][];
66
+ for(int i = 0; i < innerConstraints.length; i++) {
67
+ innerConstraints[i] = (Integer[]) constraints[i];
68
+ }
69
+
70
+ final Object[][] innerPerviouslyTested = new Object[previouslyTested.length][];
71
+ for(int i = 0; i < innerPerviouslyTested.length; i++) {
72
+ innerPerviouslyTested[i] = (Object[]) previouslyTested[i];
73
+ }
74
+
75
+ return new Ipog(innerParams, t, innerConstraints, innerPerviouslyTested).run();
76
+ }
77
+
78
+ @Deprecated
79
+ public static Object[][] ateg(final Object[][] params)
80
+ throws DitherError {
81
+ return aetg(params);
82
+ }
83
+
84
+ public static Object[][] aetg(final Object[][] params)
85
+ throws DitherError {
86
+ return aetg(2, params);
87
+ }
88
+
89
+ @Deprecated
90
+ public static Object[][] ateg(final int t, final Object[][] params) {
91
+ return aetg(t, params);
92
+ }
93
+
94
+ public static Object[][] aetg(final int t, final Object[][] params) {
95
+ return aetg(t, null, params, EMPTY_CONSTRAINTS, EMPTY_PREVIOUSLY_TESTED);
96
+ }
97
+
98
+ @Deprecated
99
+ public static Object[][] ateg(final int t, final Integer seed, final Object[][] params, final Integer[][] constraints, final Object[][] previouslyTested)
100
+ throws DitherError {
101
+ return aetg(t, seed, params, constraints, previouslyTested);
102
+ }
103
+
104
+ public static Object[][] aetg(final int t, final Integer seed, final Object[][] params, final Integer[][] constraints, final Object[][] previouslyTested)
105
+ throws DitherError {
106
+ validateInput(t, params);
107
+ final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
108
+ Object[][] result = new Object[][]{};
109
+ try {
110
+ result = new AetgPairwise(t, seed, params, constraints, previouslyTested, executor).toArray();
111
+ } finally {
112
+ executor.shutdownNow();
113
+ }
114
+ return result;
115
+ }
116
+
117
+ @Deprecated
118
+ public static Object[][] ateg(final int t, final Integer seed, final Object[] params, final Object[] constraints, final Object[] previouslyTested) {
119
+ return aetg(t, seed, params, constraints, previouslyTested);
120
+ }
121
+
122
+ public static Object[][] aetg(final int t, final Integer seed, final Object[] params, final Object[] constraints, final Object[] previouslyTested) {
123
+ final Object[][] innerParams = new Object[params.length][];
124
+ for(int i = 0; i < innerParams.length; i++) {
125
+ innerParams[i] = (Object[]) params[i];
126
+ }
127
+ validateInput(t, innerParams);
128
+
129
+ final Integer[][] innerConstraints = new Integer[constraints.length][];
130
+ for(int i = 0; i < innerConstraints.length; i++) {
131
+ innerConstraints[i] = (Integer[]) constraints[i];
132
+ }
133
+
134
+ final Object[][] innerPerviouslyTested = new Object[previouslyTested.length][];
135
+ for(int i = 0; i < innerPerviouslyTested.length; i++) {
136
+ innerPerviouslyTested[i] = (Object[]) previouslyTested[i];
137
+ }
138
+ return aetg(t, seed, innerParams, innerConstraints, innerPerviouslyTested);
139
+ }
140
+
141
+ private static void validateInput(final int t, final Object[][] params) throws DitherError {
142
+ if (t <= 1) {
143
+ throw new DitherError("t must be >= 2");
144
+ }
145
+
146
+ if (t > params.length) {
147
+ throw new DitherError("t must be <= params.length");
148
+ }
149
+ for (final Object[] param : params) {
150
+ if (param.length < 2) {
151
+ throw new DitherError("param length must be > 1");
152
+ }
153
+ }
154
+ }
155
+ }
@@ -0,0 +1,45 @@
1
+ package com.github.jesg.dither;
2
+
3
+ /*
4
+ * #%L
5
+ * dither
6
+ * %%
7
+ * Copyright (C) 2015 Jason Gowan
8
+ * %%
9
+ * Licensed under the Apache License, Version 2.0 (the "License");
10
+ * you may not use this file except in compliance with the License.
11
+ * You may obtain a copy of the License at
12
+ *
13
+ * http://www.apache.org/licenses/LICENSE-2.0
14
+ *
15
+ * Unless required by applicable law or agreed to in writing, software
16
+ * distributed under the License is distributed on an "AS IS" BASIS,
17
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ * See the License for the specific language governing permissions and
19
+ * limitations under the License.
20
+ * #L%
21
+ */
22
+
23
+ public class DitherError extends RuntimeException {
24
+
25
+ public DitherError() {
26
+ super();
27
+ }
28
+
29
+ public DitherError(String message, Throwable cause,
30
+ boolean enableSuppression, boolean writableStackTrace) {
31
+ super(message, cause, enableSuppression, writableStackTrace);
32
+ }
33
+
34
+ public DitherError(String message, Throwable cause) {
35
+ super(message, cause);
36
+ }
37
+
38
+ public DitherError(String message) {
39
+ super(message);
40
+ }
41
+
42
+ public DitherError(Throwable cause) {
43
+ super(cause);
44
+ }
45
+ }
@@ -0,0 +1,40 @@
1
+ package com.github.jesg.dither;
2
+
3
+ /*
4
+ * #%L
5
+ * dither
6
+ * %%
7
+ * Copyright (C) 2015 Jason Gowan
8
+ * %%
9
+ * Licensed under the Apache License, Version 2.0 (the "License");
10
+ * you may not use this file except in compliance with the License.
11
+ * You may obtain a copy of the License at
12
+ *
13
+ * http://www.apache.org/licenses/LICENSE-2.0
14
+ *
15
+ * Unless required by applicable law or agreed to in writing, software
16
+ * distributed under the License is distributed on an "AS IS" BASIS,
17
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ * See the License for the specific language governing permissions and
19
+ * limitations under the License.
20
+ * #L%
21
+ */
22
+
23
+ class IndexArrayPair {
24
+
25
+ private final int i;
26
+ private final Object[] arr;
27
+
28
+ public IndexArrayPair(final int i, final Object[] arr) {
29
+ this.i = i;
30
+ this.arr = arr;
31
+ }
32
+
33
+ public int getI() {
34
+ return i;
35
+ }
36
+
37
+ public Object[] getArr() {
38
+ return arr;
39
+ }
40
+ }
@@ -0,0 +1,405 @@
1
+ package com.github.jesg.dither;
2
+
3
+ /*
4
+ * #%L
5
+ * dither
6
+ * %%
7
+ * Copyright (C) 2015 Jason Gowan
8
+ * %%
9
+ * Licensed under the Apache License, Version 2.0 (the "License");
10
+ * you may not use this file except in compliance with the License.
11
+ * You may obtain a copy of the License at
12
+ *
13
+ * http://www.apache.org/licenses/LICENSE-2.0
14
+ *
15
+ * Unless required by applicable law or agreed to in writing, software
16
+ * distributed under the License is distributed on an "AS IS" BASIS,
17
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ * See the License for the specific language governing permissions and
19
+ * limitations under the License.
20
+ * #L%
21
+ */
22
+
23
+ import java.util.ArrayList;
24
+ import java.util.Arrays;
25
+ import java.util.HashMap;
26
+ import java.util.LinkedList;
27
+ import java.util.List;
28
+ import java.util.ListIterator;
29
+ import java.util.Map;
30
+
31
+ class Ipog {
32
+
33
+ private final int t;
34
+ private final Object[][] inputParams;
35
+ private final Map<Integer, Integer> origIndex = new HashMap<Integer, Integer>();
36
+ private final Map<Integer, Integer> inverseOrigIndex = new HashMap<Integer, Integer>();
37
+ private final Pair[][] constraints;
38
+ private final int[][] previouslyTested;
39
+ private final Pair[][] pairCache;
40
+ private final int[] mergeScratch;
41
+ private final ConstraintHandler constraintHandler;
42
+
43
+ public Ipog(final Object[][] input, final int t) {
44
+ this(input, t, new Integer[][] {}, new Object[][] {});
45
+ }
46
+
47
+ public Ipog(final Object[][] input, final int t,
48
+ final Integer[][] constraints, final Object[][] tested) {
49
+ this.t = t;
50
+ this.inputParams = input;
51
+ this.mergeScratch = new int[input.length];
52
+ this.previouslyTested = new int[tested.length][input.length];
53
+
54
+ // sort input params and create a shared object pool
55
+ final IndexArrayPair[] tmp = new IndexArrayPair[input.length];
56
+ for (int k = 0; k < tmp.length; k++) {
57
+ tmp[k] = new IndexArrayPair(k, input[k]);
58
+ }
59
+ Arrays.sort(tmp, new ArrayLengthComparator());
60
+ final Map<Integer, Map<Object, Pair>> origParamMap = new HashMap<Integer, Map<Object, Pair>>();
61
+ this.pairCache = new Pair[tmp.length][];
62
+ for (int k = 0; k < tmp.length; k++) {
63
+ this.origIndex.put(k, tmp[k].getI());
64
+ this.inverseOrigIndex.put(tmp[k].getI(), k);
65
+ this.pairCache[k] = new Pair[tmp[k].getArr().length];
66
+
67
+ origParamMap.put(tmp[k].getI(),
68
+ new HashMap<Object, Pair>());
69
+ for (int h = 0; h < this.pairCache[k].length; h++) {
70
+ this.pairCache[k][h] = new Pair(k, h);
71
+ origParamMap.get(tmp[k].getI()).put(tmp[k].getArr()[h],
72
+ this.pairCache[k][h]);
73
+ }
74
+ }
75
+
76
+ for (int j = 0; j < previouslyTested.length; j++) {
77
+ final Object[] innerTestCase = tested[j];
78
+ for (int k = 0; k < innerTestCase.length; k++) {
79
+ previouslyTested[j][k] = origParamMap.get(k).get(innerTestCase[k]).j;
80
+ }
81
+ }
82
+
83
+ // setup constraints
84
+ this.constraints = new Pair[constraints.length][];
85
+ for (int i = 0; i < constraints.length; i++) {
86
+ final Integer[] constraint = constraints[i];
87
+ final List<Pair> tmpConstraint = new ArrayList<Pair>(constraint.length);
88
+
89
+ for (int k = 0; k < constraint.length; k++) {
90
+ if (constraint[k] != null) {
91
+ tmpConstraint.add(pairCache[inverseOrigIndex.get(k)][constraint[k]]);
92
+ }
93
+ }
94
+ this.constraints[i] = tmpConstraint.toArray(new Pair[]{});
95
+ }
96
+ final int[] bounds = new int[pairCache.length];
97
+ for(int i = 0; i < bounds.length; i++) {
98
+ bounds[i] = pairCache[i].length;
99
+ }
100
+ this.constraintHandler = new ConstraintHandler(this.constraints, bounds);
101
+ }
102
+
103
+ List<int[]> allCombinations() {
104
+
105
+ final int[] prodarr = new int[t];
106
+ for (int k = 0; k < prodarr.length; k++) {
107
+ prodarr[k] = pairCache[k].length;
108
+ }
109
+
110
+ final int[][] prodArrResult = CombinatoricHelper.product(prodarr);
111
+
112
+ final List<int[]> results = new LinkedList<int[]>();
113
+ for(int i = 0; i < prodArrResult.length; i++) {
114
+ final int[] result = Arrays.copyOf(prodArrResult[i], pairCache.length);
115
+ Arrays.fill(result, t, result.length, -1);
116
+ if(!hasTested(t, result)) {
117
+ results.add(result);
118
+ }
119
+ }
120
+ return results;
121
+ }
122
+
123
+ List<Pair[]> combinations(final int i) {
124
+ final int[] innerParams = new int[i];
125
+ for (int k = 0; k < innerParams.length; k++) {
126
+ innerParams[k] = k;
127
+ }
128
+
129
+ final List<int[]> combinations = CombinatoricHelper.getCombinations(
130
+ t - 1, innerParams);
131
+ final List<int[]> combt = new ArrayList<int[]>(combinations.size());
132
+ for (int k = 0; k < combinations.size(); k++) {
133
+ final int[] newArr = Arrays.copyOf(combinations.get(k), t);
134
+ newArr[t - 1] = i;
135
+ combt.add(newArr);
136
+ }
137
+
138
+ final List<Pair[]> results = new LinkedList<Pair[]>();
139
+ for (final int[] comb : combt) {
140
+
141
+ final int[] prodarr = new int[comb.length];
142
+ for (int k = 0; k < prodarr.length; k++) {
143
+ prodarr[k] = pairCache[comb[k]].length;
144
+ }
145
+
146
+ final int[][] prodArrResult = CombinatoricHelper.product(prodarr);
147
+
148
+ for (int j = 0; j < prodArrResult.length; j++) {
149
+ final int[] innerArr = prodArrResult[j];
150
+ final Pair[] pairs = new Pair[innerArr.length];
151
+ for (int k = 0; k < innerArr.length; k++) {
152
+ pairs[k] = pairCache[comb[k]][innerArr[k]];
153
+ }
154
+ if (!hasTested(pairs)) {
155
+ results.add(pairs);
156
+ }
157
+ }
158
+ }
159
+
160
+ return results;
161
+ }
162
+
163
+ private boolean hasTested(final int[] testCase) {
164
+ for (final int[] innerCase : previouslyTested) {
165
+ if(Arrays.equals(testCase, innerCase)) {
166
+ return true;
167
+ }
168
+ }
169
+ return false;
170
+ }
171
+
172
+ private boolean hasTested(final int t, final int[] testCase) {
173
+ outer:
174
+ for (final int[] innerCase : previouslyTested) {
175
+ for(int i = 0; i < t; i++) {
176
+ if(innerCase[i] != testCase[i]) {
177
+ continue outer;
178
+ }
179
+ }
180
+ return true;
181
+ }
182
+ return false;
183
+ }
184
+
185
+ private boolean hasTested(final Pair[] testCase) {
186
+ outer:
187
+ for (final int[] innerCase : previouslyTested) {
188
+ for(final Pair pair : testCase) {
189
+ if(innerCase[pair.i] != pair.j) {
190
+ continue outer;
191
+ }
192
+ }
193
+ return true;
194
+ }
195
+ return false;
196
+ }
197
+
198
+ Object[][] run() {
199
+ final List<int[]> testSet = allCombinations();
200
+ final List<int[]> unbound = new LinkedList<int[]>();
201
+ for (int k = t; k < pairCache.length; k++) {
202
+ final List<Pair[]> pi = combinations(k);
203
+
204
+ // horizontal extension for parameter i
205
+ final ListIterator<int[]> iterTestSet = testSet.listIterator();
206
+ while(iterTestSet.hasNext()) {
207
+ final int[] testCase = iterTestSet.next();
208
+ final int max = maximizeCoverage(k,
209
+ testCase, pi);
210
+ if(max < 0) {
211
+ iterTestSet.remove();
212
+ } else {
213
+ // remove matches
214
+ final ListIterator<Pair[]> iter = pi.listIterator();
215
+ iter:
216
+ while(iter.hasNext()) {
217
+ for(final Pair pair : iter.next()) {
218
+ if(testCase[pair.i] != pair.j) {
219
+ continue iter;
220
+ }
221
+ }
222
+ iter.remove();
223
+ }
224
+ }
225
+ }
226
+
227
+ // vertical extension for parameter i
228
+ final ListIterator<Pair[]> piIter = pi.listIterator();
229
+ while (piIter.hasNext()) {
230
+ final Pair[] testCase = piIter.next();
231
+ // remove constraint violation
232
+ boolean isCaseCovered = violateConstraints(testCase);
233
+ if(!isCaseCovered) {
234
+ for (final int[] innerTestCase : testSet) {
235
+ boolean match = true;
236
+ for(final Pair pair : testCase) {
237
+ if(innerTestCase[pair.i] != pair.j) {
238
+ match = false;
239
+ break;
240
+ }
241
+ }
242
+ if(match) {
243
+ isCaseCovered = true;
244
+ break;
245
+ }
246
+ }
247
+ }
248
+
249
+ if (!isCaseCovered) {
250
+ final ListIterator<int[]> unboundIter = unbound.listIterator();
251
+ boolean isMerged = false;
252
+ int[] innerTestCase = null;
253
+ while(unboundIter.hasNext()) {
254
+ innerTestCase = unboundIter.next();
255
+ // -1 => no merge, 0 perfect merge (no unbound), 1 partial merge
256
+ final int mergeResult = merge(k, testCase, innerTestCase);
257
+ if(mergeResult == 0) {
258
+ unboundIter.remove();
259
+ testSet.add(innerTestCase);
260
+ isMerged = true;
261
+ break;
262
+ } else if(mergeResult == 1) {
263
+ isMerged = true;
264
+ break;
265
+ }
266
+ }
267
+
268
+ if (!isMerged) {
269
+ final int[] unboundTestCase = new int[pairCache.length];
270
+ Arrays.fill(unboundTestCase, -1);
271
+ for(final Pair pair : testCase) {
272
+ unboundTestCase[pair.i] = pair.j;
273
+ }
274
+ if(!violateConstraints(unboundTestCase)) {
275
+ unbound.add(unboundTestCase);
276
+ }
277
+ }
278
+ }
279
+ piIter.remove();
280
+ }
281
+ }
282
+ return testSetToArray(testSet, unbound);
283
+ }
284
+
285
+ // -1 no merge, 0 perfect merge (no unbound), 1 partial merge
286
+ public int merge(final int k, final Pair[] pairs, final int[] testCase) {
287
+ // verify merge
288
+ for(final Pair pair : pairs) {
289
+ int value = testCase[pair.i];
290
+ if(!(value == -1 || value == pair.j)) {
291
+ return -1;
292
+ }
293
+ }
294
+
295
+ for(int i = 0; i < mergeScratch.length; i++) {
296
+ mergeScratch[i] = testCase[i];
297
+ }
298
+
299
+ for(final Pair pair : pairs) {
300
+ mergeScratch[pair.i] = pair.j;
301
+ }
302
+
303
+ if(violateConstraints(mergeScratch)) {
304
+ return -1;
305
+ }
306
+
307
+ // merge
308
+ for(final Pair pair : pairs) {
309
+ testCase[pair.i] = pair.j;
310
+ }
311
+
312
+ // find unbound
313
+ for(int i = 0; i < k; i++) {
314
+ if(testCase[i] == -1) { return 1; }
315
+ }
316
+ return 0;
317
+ }
318
+
319
+ private Object[][] testSetToArray(final List<int[]> testSet, final List<int[]> unbound) {
320
+
321
+ final List<Object[]> results = new ArrayList<Object[]>(testSet.size() + unbound.size());
322
+ for(final int[] boundResult : testSet) {
323
+ final Object[] result = new Object[boundResult.length];
324
+ for (int k = 0; k < boundResult.length; k++) {
325
+ final int value = boundResult[k];
326
+ final int i = origIndex.get(k);
327
+ result[i] = inputParams[i][value];
328
+ }
329
+ if(!violateConstraints(boundResult) && !hasTested(boundResult)) {
330
+ results.add(result);
331
+ }
332
+ }
333
+
334
+ outer:
335
+ for(final int[] unboundResult : unbound) {
336
+ final Object[] result = new Object[unboundResult.length];
337
+ final int[] groundResult = constraintHandler.groundSolution(unboundResult);
338
+ if(groundResult == null) {
339
+ continue outer;
340
+ }
341
+ for(int k = 0; k < unboundResult.length; k++) {
342
+ final int i = origIndex.get(k);
343
+ final int value = groundResult[k];
344
+ result[i] = inputParams[i][value];
345
+ }
346
+ if(!hasTested(unboundResult)) {
347
+ results.add(result);
348
+ }
349
+ }
350
+
351
+ return results.toArray(new Object[][]{});
352
+ }
353
+
354
+ boolean violateConstraints(final int[] testCase) {
355
+ if(constraints.length == 0) {
356
+ return false;
357
+ }
358
+ return constraintHandler.violateConstraints(testCase);
359
+ }
360
+
361
+ boolean violateConstraints(final Pair[] testCase) {
362
+ if(constraints.length == 0) {
363
+ return false;
364
+ }
365
+ return constraintHandler.violateConstraints(testCase);
366
+ }
367
+
368
+ private int maximizeCoverage(final int i,
369
+ final int[] testCase, final List<Pair[]> pi) {
370
+ int currentMax = -1;
371
+ int currentJ = 0;
372
+
373
+ for (int j = 0; j < pairCache[i].length; j++) {
374
+ final Pair currentPair = pairCache[i][j];
375
+ testCase[currentPair.i] = currentPair.j;
376
+
377
+ if (!violateConstraints(testCase)) {
378
+ int count = 0;
379
+ outer:
380
+ for (final Pair[] innerTestCase : pi) {
381
+ for(final Pair pair : innerTestCase) {
382
+ if (testCase[pair.i] != pair.j) {
383
+ continue outer;
384
+ }
385
+ }
386
+ count++;
387
+ }
388
+
389
+ if (count > currentMax) {
390
+ currentMax = count;
391
+ currentJ = j;
392
+ }
393
+ }
394
+ testCase[i] = -1;
395
+ }
396
+
397
+ if (currentMax == -1) {
398
+ return -1;
399
+ }
400
+
401
+ final Pair pair = pairCache[i][currentJ];
402
+ testCase[pair.i] = pair.j;
403
+ return currentMax;
404
+ }
405
+ }