Testcase generation tool for combinatorial interaction testing
Revision | 52f55c273aad45c38fc6812416d95c7028da6c2f (tree) |
---|---|
Time | 2015-05-25 19:02:21 |
Author | t-tutiya <tatsuhiro@ieee...> |
Commiter | t-tutiya |
Merge Japanese and English versions
Change licence from BSD to zlib
Reflect missing updates made in Jar files of v1.01 but lost in source
files
@@ -1,11 +1,12 @@ | ||
1 | 1 | eclipse.preferences.version=1 |
2 | 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled |
3 | -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 | |
3 | +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate | |
4 | +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 | |
4 | 5 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve |
5 | -org.eclipse.jdt.core.compiler.compliance=1.7 | |
6 | +org.eclipse.jdt.core.compiler.compliance=1.6 | |
6 | 7 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate |
7 | 8 | org.eclipse.jdt.core.compiler.debug.localVariable=generate |
8 | 9 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate |
9 | 10 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error |
10 | 11 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error |
11 | -org.eclipse.jdt.core.compiler.source=1.7 | |
12 | +org.eclipse.jdt.core.compiler.source=1.6 |
@@ -7,24 +7,24 @@ import java.util.ArrayList; | ||
7 | 7 | import java.util.List; |
8 | 8 | |
9 | 9 | class ConstraintHandler { |
10 | - static final int sizeOfNodetable = 1000; | |
11 | - static final int sizeOfCache = 1000; | |
12 | - | |
10 | + static final int sizeOfNodetable = 10000; | |
11 | + static final int sizeOfCache = 10000; | |
12 | + | |
13 | 13 | List<VariableAndBDD> parameters = null; |
14 | 14 | BDD bdd; |
15 | 15 | int bddConstraint; |
16 | 16 | int numOfBDDvariables; |
17 | - | |
17 | + | |
18 | 18 | ConstraintHandler(PList parameterList, List<Node> constraintList) { |
19 | 19 | bdd = new BDD(sizeOfNodetable, sizeOfCache); |
20 | - bdd = new jdd.bdd.debug.DebugBDD(1000,1000); | |
21 | - | |
22 | - //parameterのリスト | |
20 | + // bdd = new jdd.bdd.debug.DebugBDD(1000,1000); | |
21 | + | |
22 | + // parameterのリスト | |
23 | 23 | parameters = setBDDforParameter(parameterList); |
24 | - | |
25 | - //contrainListから、ノードを呼ぶ | |
24 | + | |
25 | + // contrainListから、ノードを呼ぶ | |
26 | 26 | bddConstraint = setBddConstraint(constraintList); |
27 | - | |
27 | + | |
28 | 28 | // boolean 変数の総数を計算 |
29 | 29 | // numOfBooleanVariable = computeNumOfBooleanVariables |
30 | 30 | } |
@@ -32,35 +32,35 @@ class ConstraintHandler { | ||
32 | 32 | void printConstraintBDD() { |
33 | 33 | bdd.printSet(bddConstraint); |
34 | 34 | } |
35 | - | |
35 | + | |
36 | 36 | // 各パラメータにboolean変数を割り当て.総数も計算 |
37 | 37 | private List<VariableAndBDD> setBDDforParameter(PList parameterList) { |
38 | 38 | List<VariableAndBDD> res = new ArrayList<VariableAndBDD>(); |
39 | 39 | this.numOfBDDvariables = 0; |
40 | - | |
41 | - for (Parameter p: parameterList) { | |
40 | + | |
41 | + for (Parameter p : parameterList) { | |
42 | 42 | // BDD変数の設定 |
43 | 43 | int num_vars = 1; |
44 | - for (int levels = 2; ; levels *= 2) { | |
45 | - if (p.value_name.size() < levels) | |
44 | + for (int levels = 2;; levels *= 2) { | |
45 | + if (p.value_name.size() < levels) | |
46 | 46 | break; |
47 | 47 | num_vars++; |
48 | - } | |
48 | + } | |
49 | 49 | // BDD変数の総数を計算 |
50 | 50 | numOfBDDvariables += num_vars; |
51 | - | |
51 | + | |
52 | 52 | // boolean variables |
53 | 53 | // 生成された順に getVar(v): 0, 1, 2, .. |
54 | 54 | int[] var = new int[num_vars]; |
55 | 55 | for (int i = num_vars - 1; i >= 0; i--) { |
56 | 56 | var[i] = bdd.createVar(); |
57 | 57 | } |
58 | - | |
58 | + | |
59 | 59 | // 制約のBDDの設定 |
60 | 60 | // constraint for invalid values |
61 | 61 | // domain-1以下の数字のみ有効 |
62 | 62 | // bool variables の数はdomain-1をあらわせるだけはある |
63 | - // | |
63 | + // | |
64 | 64 | // domain-1の2進表現では,最上位の変数にあたるビットは常に1 |
65 | 65 | // とは限らない |
66 | 66 | int f = bdd.getZero(); |
@@ -68,36 +68,48 @@ class ConstraintHandler { | ||
68 | 68 | // domain-1より小さい数 |
69 | 69 | for (int i = var.length - 1; i >= 0; i--) { |
70 | 70 | if ((p.value_name.size() - 1 & (0x01 << i)) > 0) { |
71 | - int g = bdd.getOne(); | |
71 | + int g = bdd.getOne(); | |
72 | 72 | bdd.ref(g); |
73 | 73 | for (int j = var.length - 1; j > i; j--) { |
74 | 74 | if ((p.value_name.size() - 1 & (0x01 << j)) > 0) { |
75 | - int tmp = bdd.ref(bdd.and(g, var[j])); bdd.deref(g); g = tmp; | |
75 | + int tmp = bdd.ref(bdd.and(g, var[j])); | |
76 | + bdd.deref(g); | |
77 | + g = tmp; | |
76 | 78 | } else { |
77 | - int tmp = bdd.ref(bdd.and(g, bdd.not(var[j]))); bdd.deref(g); g = tmp; | |
79 | + int tmp = bdd.ref(bdd.and(g, bdd.not(var[j]))); | |
80 | + bdd.deref(g); | |
81 | + g = tmp; | |
78 | 82 | } |
79 | 83 | } |
80 | - int tmp = bdd.ref(bdd.and(g, bdd.not(var[i]))); bdd.deref(g); g = tmp; | |
81 | - tmp = bdd.ref(bdd.or(f, g)); bdd.deref(g); f = tmp; | |
84 | + int tmp = bdd.ref(bdd.and(g, bdd.not(var[i]))); | |
85 | + bdd.deref(g); | |
86 | + g = tmp; | |
87 | + tmp = bdd.ref(bdd.or(f, g)); | |
88 | + bdd.deref(g); | |
89 | + f = tmp; | |
82 | 90 | } |
83 | 91 | } |
84 | - | |
92 | + | |
85 | 93 | // domain - 1自身 |
86 | - int g = bdd.getOne(); | |
94 | + int g = bdd.getOne(); | |
87 | 95 | bdd.ref(g); |
88 | 96 | for (int i = var.length - 1; i >= 0; i--) { |
89 | 97 | if ((p.value_name.size() - 1 & (0x01 << i)) > 0) { |
90 | - int tmp = bdd.ref(bdd.and(g, var[i])); bdd.deref(g); g = tmp; | |
98 | + int tmp = bdd.ref(bdd.and(g, var[i])); | |
99 | + bdd.deref(g); | |
100 | + g = tmp; | |
91 | 101 | } else { |
92 | - int tmp = bdd.ref(bdd.and(g, bdd.not(var[i]))); bdd.deref(g); g = tmp; | |
102 | + int tmp = bdd.ref(bdd.and(g, bdd.not(var[i]))); | |
103 | + bdd.deref(g); | |
104 | + g = tmp; | |
93 | 105 | } |
94 | 106 | } |
95 | - | |
107 | + | |
96 | 108 | int d = bdd.or(f, g); |
97 | 109 | bdd.ref(d); |
98 | 110 | bdd.deref(f); |
99 | 111 | bdd.deref(g); |
100 | - | |
112 | + | |
101 | 113 | // var, d を listに追加 |
102 | 114 | res.add(new VariableAndBDD(var, d)); |
103 | 115 | } |
@@ -107,36 +119,43 @@ class ConstraintHandler { | ||
107 | 119 | private int setBddConstraint(List<Node> constraintList) { |
108 | 120 | int f = bdd.getOne(); |
109 | 121 | bdd.ref(f); |
110 | - | |
122 | + | |
111 | 123 | // パラメータでつかわない領域をfalseにする |
112 | 124 | for (VariableAndBDD vb : parameters) { |
113 | - int tmp = bdd.ref(bdd.and(f, vb.constraint)); bdd.deref(f); f = tmp; | |
125 | + int tmp = bdd.ref(bdd.and(f, vb.constraint)); | |
126 | + bdd.deref(f); | |
127 | + f = tmp; | |
114 | 128 | } |
115 | - | |
129 | + | |
116 | 130 | // 制約式の論理積をとる |
117 | - for (Node n: constraintList) { | |
131 | + for (Node n : constraintList) { | |
118 | 132 | int g = n.evaluate(bdd, parameters); |
119 | - int tmp = bdd.ref(bdd.and(f, g)); bdd.deref(f); bdd.deref(g); f = tmp; | |
133 | + int tmp = bdd.ref(bdd.and(f, g)); | |
134 | + bdd.deref(f); | |
135 | + bdd.deref(g); | |
136 | + f = tmp; | |
120 | 137 | } |
121 | - | |
138 | + | |
122 | 139 | // *を付加 |
123 | 140 | f = extendBddConstraint(f); |
124 | - | |
141 | + | |
125 | 142 | return f; |
126 | 143 | } |
127 | - | |
144 | + | |
128 | 145 | private int extendBddConstraint(int constraint) { |
129 | 146 | int f = constraint; |
130 | 147 | for (VariableAndBDD p : parameters) { |
131 | 148 | int cube = p.var[0]; |
132 | 149 | bdd.ref(cube); |
133 | 150 | for (int i = 1; i < p.var.length; i++) { |
134 | - int tmp = bdd.ref(bdd.and(cube, p.var[i])); bdd.deref(cube); cube = tmp; | |
151 | + int tmp = bdd.ref(bdd.and(cube, p.var[i])); | |
152 | + bdd.deref(cube); | |
153 | + cube = tmp; | |
135 | 154 | } |
136 | 155 | int tmp0 = bdd.ref(bdd.exists(f, cube)); |
137 | 156 | int tmp = bdd.ref(bdd.and(tmp0, cube)); |
138 | 157 | int newf = bdd.ref(bdd.or(f, tmp)); |
139 | - | |
158 | + | |
140 | 159 | bdd.deref(cube); |
141 | 160 | bdd.deref(tmp0); |
142 | 161 | bdd.deref(tmp); |
@@ -145,29 +164,31 @@ class ConstraintHandler { | ||
145 | 164 | } |
146 | 165 | return f; |
147 | 166 | } |
148 | - | |
167 | + | |
149 | 168 | // テストケースが制約を満たすか |
150 | - boolean isPossible (Testcase test) { | |
169 | + boolean isPossible(Testcase test) { | |
151 | 170 | int node = bddConstraint; |
152 | 171 | boolean[] bv = binarize(test); |
153 | - | |
172 | + | |
154 | 173 | while (true) { |
155 | 174 | // 恒真,恒偽 |
156 | - if (node == 0) return false; | |
157 | - else if (node == 1) return true; | |
175 | + if (node == 0) | |
176 | + return false; | |
177 | + else if (node == 1) | |
178 | + return true; | |
158 | 179 | |
159 | 180 | // このposの0, 1はノードなし |
160 | - if (bv[bdd.getVar(node)] == true) | |
181 | + if (bv[bdd.getVar(node)] == true) | |
161 | 182 | node = bdd.getHigh(node); |
162 | 183 | else |
163 | 184 | node = bdd.getLow(node); |
164 | 185 | } |
165 | 186 | } |
166 | - | |
187 | + | |
167 | 188 | private boolean[] binarize(Testcase test) { |
168 | - // assert(testcaseの長さ = parameterの数) | |
189 | + // assert(testcaseの長さ = parameterの数) | |
169 | 190 | boolean[] res = new boolean[numOfBDDvariables]; |
170 | - int pos = 0; | |
191 | + int pos = 0; | |
171 | 192 | // 各因子の値を2値で表現 |
172 | 193 | for (int i = 0; i < test.value.length; i++) { |
173 | 194 | VariableAndBDD p = parameters.get(i); |
@@ -177,21 +198,20 @@ class ConstraintHandler { | ||
177 | 198 | res[pos + j] = true; |
178 | 199 | } else { |
179 | 200 | int j0 = 0; |
180 | - for (int j = p.var.length -1 ; j >= 0; j--) { | |
181 | - if ((lv & (0x01 << j)) > 0) | |
182 | - res[pos + j0]= true; | |
183 | - else res[pos + j0] = false; | |
201 | + for (int j = p.var.length - 1; j >= 0; j--) { | |
202 | + if ((lv & (0x01 << j)) > 0) | |
203 | + res[pos + j0] = true; | |
204 | + else | |
205 | + res[pos + j0] = false; | |
184 | 206 | j0++; |
185 | 207 | } |
186 | 208 | } |
187 | 209 | pos += p.var.length; |
188 | 210 | } |
189 | 211 | /* |
190 | - this.print(); | |
191 | - for (int k = 0; k < res.length; k++) | |
192 | - System.out.print(res[k] ? 1 : 0); | |
193 | - System.out.println("<-"); | |
194 | - */ | |
212 | + * this.print(); for (int k = 0; k < res.length; k++) | |
213 | + * System.out.print(res[k] ? 1 : 0); System.out.println("<-"); | |
214 | + */ | |
195 | 215 | return res; |
196 | 216 | } |
197 | 217 | } |
@@ -6,14 +6,14 @@ import java.io.IOException; | ||
6 | 6 | import java.io.OutputStreamWriter; |
7 | 7 | |
8 | 8 | public class Error { |
9 | - | |
9 | + | |
10 | 10 | // default でエラーは標準出力 |
11 | 11 | static String filename = null; |
12 | 12 | |
13 | 13 | static void setOutputFile(String filename) { |
14 | 14 | Error.filename = filename; |
15 | 15 | } |
16 | - | |
16 | + | |
17 | 17 | static void printError(String str) { |
18 | 18 | BufferedWriter writer; |
19 | 19 | try { |
@@ -24,7 +24,9 @@ public class Error { | ||
24 | 24 | writer.write("#ERROR," + str + "\n"); |
25 | 25 | writer.close(); |
26 | 26 | } catch (IOException e) { |
27 | - System.err.print("出力ファイル" + filename + "が作成できません."); | |
27 | + System.err.print(Main.language == Main.Language.JP ? "出力ファイル" | |
28 | + + filename + "が作成できません." : "Output file " + filename | |
29 | + + " could not be created."); | |
28 | 30 | } |
29 | 31 | System.exit(1); |
30 | 32 | } |
@@ -7,23 +7,27 @@ import java.util.Random; | ||
7 | 7 | class GeneratorFactor { |
8 | 8 | |
9 | 9 | // requires parametermodel.size >= 2 |
10 | - static Generator newGenerator(ParameterModel parametermodel, GList groupList, ConstraintHandler constrainthandler, | |
11 | - List<Testcase> seed, | |
12 | - long randomseed, int strength) { | |
10 | + static Generator newGenerator(ParameterModel parametermodel, | |
11 | + GList groupList, ConstraintHandler constrainthandler, | |
12 | + List<Testcase> seed, long randomseed, int strength) { | |
13 | 13 | if (strength > parametermodel.size) |
14 | 14 | strength = parametermodel.size; |
15 | - | |
15 | + | |
16 | 16 | if (strength == 2) { |
17 | - return new Generator2(parametermodel, groupList, constrainthandler, seed, randomseed); | |
18 | - } | |
17 | + return new Generator2(parametermodel, groupList, constrainthandler, | |
18 | + seed, randomseed); | |
19 | + } | |
19 | 20 | if (strength == 3) { |
20 | - return new Generator3(parametermodel, groupList, constrainthandler, seed, randomseed); | |
21 | + return new Generator3(parametermodel, groupList, constrainthandler, | |
22 | + seed, randomseed); | |
21 | 23 | } |
22 | 24 | if (strength == 4) { |
23 | - return new Generator4(parametermodel, groupList, constrainthandler, seed, randomseed); | |
25 | + return new Generator4(parametermodel, groupList, constrainthandler, | |
26 | + seed, randomseed); | |
24 | 27 | } |
25 | 28 | if (strength == 5) { |
26 | - return new Generator5(parametermodel, groupList, constrainthandler, seed, randomseed); | |
29 | + return new Generator5(parametermodel, groupList, constrainthandler, | |
30 | + seed, randomseed); | |
27 | 31 | } |
28 | 32 | |
29 | 33 | return null; |
@@ -37,11 +41,11 @@ abstract class Generator { | ||
37 | 41 | final List<Testcase> seed; |
38 | 42 | final int numOfParameters; |
39 | 43 | final Random rnd; |
40 | - | |
44 | + | |
41 | 45 | static final int MaxNumOfTestcases = 65532; |
42 | - | |
43 | - Generator (ParameterModel parametermodel, GList groupList, ConstraintHandler constrainthandler, | |
44 | - List<Testcase> seed, | |
46 | + | |
47 | + Generator(ParameterModel parametermodel, GList groupList, | |
48 | + ConstraintHandler constrainthandler, List<Testcase> seed, | |
45 | 49 | long randomseed) { |
46 | 50 | this.parametermodel = parametermodel; |
47 | 51 | this.groupList = groupList; |
@@ -55,10 +59,10 @@ abstract class Generator { | ||
55 | 59 | |
56 | 60 | // groupで全網羅するtupleの列を生成 |
57 | 61 | protected List<List<Testcase>> generateTupleSequenceList() { |
58 | -// protected List<TupleSequence> generateTupleSequence() { | |
62 | + // protected List<TupleSequence> generateTupleSequence() { | |
59 | 63 | // TODO Auto-generated method stub |
60 | 64 | List<List<Testcase>> listOfTupleSequence = new ArrayList<List<Testcase>>(); |
61 | - for (Group g: groupList) { | |
65 | + for (Group g : groupList) { | |
62 | 66 | listOfTupleSequence.add(generateTupleSequence(g)); |
63 | 67 | } |
64 | 68 | return listOfTupleSequence; |
@@ -69,9 +73,9 @@ abstract class Generator { | ||
69 | 73 | for (int i = 0; i < g.member.length; i++) { |
70 | 74 | numOfCombinations *= parametermodel.range[g.member[i]]; |
71 | 75 | } |
72 | - | |
76 | + | |
73 | 77 | List<Testcase> testSet = new ArrayList<Testcase>(); |
74 | - | |
78 | + | |
75 | 79 | Testcase tmptest = new Testcase(parametermodel.size); |
76 | 80 | tmptest.quantify(); |
77 | 81 | for (int i = 0; i < g.member.length; i++) { |
@@ -79,7 +83,7 @@ abstract class Generator { | ||
79 | 83 | } |
80 | 84 | if (constrainthandler.isPossible(tmptest)) |
81 | 85 | testSet.add(tmptest); |
82 | - | |
86 | + | |
83 | 87 | for (int i = 1; i < numOfCombinations; i++) { |
84 | 88 | tmptest = tmptest.makeClone(); |
85 | 89 | for (int j = 0; j < g.member.length; j++) { |
@@ -93,17 +97,20 @@ abstract class Generator { | ||
93 | 97 | } |
94 | 98 | if (constrainthandler.isPossible(tmptest)) { |
95 | 99 | testSet.add(tmptest); |
96 | - if (testSet.size() > MaxNumOfTestcases) | |
97 | - Error.printError("特定因子の全網羅に上限" + MaxNumOfTestcases + "を超えるテストケースが必要です"); | |
100 | + if (testSet.size() > MaxNumOfTestcases) | |
101 | + Error.printError(Main.language == Main.Language.JP ? "特定因子の全網羅に上限" | |
102 | + + MaxNumOfTestcases + "を超えるテストケースが必要です" | |
103 | + : "The number of test cases exceeds the upper bound " | |
104 | + + MaxNumOfTestcases); | |
98 | 105 | } |
99 | 106 | } |
100 | 107 | return testSet; |
101 | 108 | } |
102 | - | |
109 | + | |
103 | 110 | protected boolean hasTuplesToCover(List<List<Testcase>> tupleSequenceList) { |
104 | 111 | // TODO Auto-generated method stub |
105 | 112 | for (List<Testcase> tupleSequence : tupleSequenceList) { |
106 | - if (tupleSequence.size() > 0) | |
113 | + if (tupleSequence.size() > 0) | |
107 | 114 | return true; |
108 | 115 | } |
109 | 116 | return false; |
@@ -112,29 +119,21 @@ abstract class Generator { | ||
112 | 119 | } |
113 | 120 | |
114 | 121 | class Generator2 extends Generator { |
115 | -/* | |
116 | - final ParameterModel parametermodel; | |
117 | - final GList groupList; | |
118 | - final ConstraintHandler constrainthandler; | |
119 | - final List<Testcase> seed; | |
120 | - final int numOfParameters; | |
121 | - final Random rnd; | |
122 | - | |
123 | - //TODO groupの追加 | |
124 | - Generator2 (ParameterModel parametermodel, GList groupList, ConstraintHandler constrainthandler, | |
125 | - List<Testcase> seed, | |
126 | - long randomseed){ | |
127 | - this.parametermodel = parametermodel; | |
128 | - this.groupList = groupList; | |
129 | - this.constrainthandler = constrainthandler; | |
130 | - this.seed = seed; | |
131 | - this.numOfParameters = parametermodel.size; | |
132 | - this.rnd = new Random(randomseed); | |
133 | - } | |
134 | - */ | |
135 | - | |
122 | + /* | |
123 | + * final ParameterModel parametermodel; final GList groupList; final | |
124 | + * ConstraintHandler constrainthandler; final List<Testcase> seed; final int | |
125 | + * numOfParameters; final Random rnd; | |
126 | + * | |
127 | + * //TODO groupの追加 Generator2 (ParameterModel parametermodel, GList | |
128 | + * groupList, ConstraintHandler constrainthandler, List<Testcase> seed, long | |
129 | + * randomseed){ this.parametermodel = parametermodel; this.groupList = | |
130 | + * groupList; this.constrainthandler = constrainthandler; this.seed = seed; | |
131 | + * this.numOfParameters = parametermodel.size; this.rnd = new | |
132 | + * Random(randomseed); } | |
133 | + */ | |
134 | + | |
136 | 135 | final int NumOfIterationForEachTest = 20; |
137 | - | |
136 | + | |
138 | 137 | Generator2(ParameterModel parametermodel, GList groupList, |
139 | 138 | ConstraintHandler constrainthandler, List<Testcase> seed, |
140 | 139 | long randomseed) { |
@@ -142,14 +141,14 @@ class Generator2 extends Generator { | ||
142 | 141 | } |
143 | 142 | |
144 | 143 | List<Testcase> generate() throws OutOfMaxNumOfTestcasesException { |
145 | - | |
144 | + | |
146 | 145 | List<Testcase> res = new ArrayList<Testcase>(); |
147 | 146 | PairTable tab = new PairTable(parametermodel); |
148 | - | |
147 | + | |
149 | 148 | // group毎,tuple列の作成 |
150 | 149 | List<List<Testcase>> tupleSequenceList = generateTupleSequenceList(); |
151 | 150 | |
152 | - // | |
151 | + // | |
153 | 152 | int numOfUncoveredTuples = checkAllTuples(tab); |
154 | 153 | |
155 | 154 | // 各<因子・値> に それが含まれる未カバーのtupleの総数を設定 |
@@ -158,61 +157,50 @@ class Generator2 extends Generator { | ||
158 | 157 | |
159 | 158 | // debug |
160 | 159 | /* |
161 | - for (int p1 = 0; p1 < parametermodel.size; p1++) { | |
162 | - System.err.print(p1 + ": "); | |
163 | - for (int i : uncovTab[p1]) { | |
164 | - System.err.print(i + ", "); | |
165 | - } | |
166 | - System.err.println(); | |
167 | - } | |
168 | - */ | |
169 | - | |
160 | + * for (int p1 = 0; p1 < parametermodel.size; p1++) { | |
161 | + * System.err.print(p1 + ": "); for (int i : uncovTab[p1]) { | |
162 | + * System.err.print(i + ", "); } System.err.println(); } | |
163 | + */ | |
164 | + | |
170 | 165 | int seedrownum = 0; |
171 | 166 | while (numOfUncoveredTuples > 0 || hasTuplesToCover(tupleSequenceList)) { |
172 | 167 | // testcase 1個生成 |
173 | - ResultOfGenerateOneTest newresult = generateOneTest(tab, seedrownum, uncovTab, tupleSequenceList); | |
174 | - | |
168 | + ResultOfGenerateOneTest newresult = generateOneTest(tab, | |
169 | + seedrownum, uncovTab, tupleSequenceList); | |
170 | + | |
175 | 171 | // debug |
176 | 172 | /* |
177 | - newresult.test.print(); | |
178 | - */ | |
179 | - | |
173 | + * newresult.test.print(); | |
174 | + */ | |
175 | + | |
180 | 176 | res.add(newresult.test); |
181 | - if (res.size() > MaxNumOfTestcases) | |
177 | + if (res.size() > MaxNumOfTestcases) | |
182 | 178 | throw new OutOfMaxNumOfTestcasesException(); |
183 | - | |
179 | + | |
184 | 180 | numOfUncoveredTuples -= newresult.numOfCoveredTuples; |
185 | 181 | seedrownum = newresult.nextSeedRow; |
186 | - | |
182 | + | |
187 | 183 | // debug |
188 | 184 | /* |
189 | - System.err.println(numOfUncoveredTuples + ", " + seedrownum); | |
190 | - */ | |
191 | - | |
185 | + * System.err.println(numOfUncoveredTuples + ", " + seedrownum); | |
186 | + */ | |
187 | + | |
192 | 188 | // debug |
193 | 189 | /* |
194 | - for (int p1 = 0; p1 < parametermodel.size; p1++) { | |
195 | - System.err.print(p1 + ": "); | |
196 | - for (int i : uncovTab[p1]) { | |
197 | - System.err.print(i + ", "); | |
198 | - } | |
199 | - System.err.println(); | |
200 | - } | |
201 | - */ | |
190 | + * for (int p1 = 0; p1 < parametermodel.size; p1++) { | |
191 | + * System.err.print(p1 + ": "); for (int i : uncovTab[p1]) { | |
192 | + * System.err.print(i + ", "); } System.err.println(); } | |
193 | + */ | |
202 | 194 | } |
203 | 195 | return res; |
204 | 196 | } |
205 | 197 | |
206 | 198 | /* |
207 | - private boolean hasTuplesToCover(List<List<Testcase>> tupleSequenceList) { | |
208 | - // TODO Auto-generated method stub | |
209 | - for (List<Testcase> tupleSequence : tupleSequenceList) { | |
210 | - if (tupleSequence.size() > 0) | |
211 | - return true; | |
212 | - } | |
213 | - return false; | |
214 | - } | |
215 | - */ | |
199 | + * private boolean hasTuplesToCover(List<List<Testcase>> tupleSequenceList) | |
200 | + * { // TODO Auto-generated method stub for (List<Testcase> tupleSequence : | |
201 | + * tupleSequenceList) { if (tupleSequence.size() > 0) return true; } return | |
202 | + * false; } | |
203 | + */ | |
216 | 204 | |
217 | 205 | private void initializeUncovTab(ArrayList<Integer>[] uncovTab, PairTable tab) { |
218 | 206 | assert (parametermodel.size == uncovTab.length); |
@@ -233,72 +221,74 @@ class Generator2 extends Generator { | ||
233 | 221 | } |
234 | 222 | } |
235 | 223 | } |
236 | - | |
237 | - | |
238 | - private ResultOfGenerateOneTest generateOneTest(PairTable tab, int seedrownum, ArrayList<Integer>[] uncovTab, List<List<Testcase>> tupleSequenceList) { | |
224 | + | |
225 | + private ResultOfGenerateOneTest generateOneTest(PairTable tab, | |
226 | + int seedrownum, ArrayList<Integer>[] uncovTab, | |
227 | + List<List<Testcase>> tupleSequenceList) { | |
239 | 228 | // 空のテストケースを1つつくる |
240 | 229 | Testcase tmp = new Testcase(parametermodel.size); |
241 | 230 | tmp.quantify(); |
242 | - | |
231 | + | |
243 | 232 | boolean isSeedUsed = false; |
244 | - | |
233 | + | |
245 | 234 | // seedのコピー 制約を満たさなかったらエラー |
246 | - if (seed.size() > 0 && seedrownum < seed.size() ) { | |
235 | + if (seed.size() > 0 && seedrownum < seed.size()) { | |
247 | 236 | isSeedUsed = true; |
248 | - Testcase seedrow = seed.get(seedrownum); | |
237 | + Testcase seedrow = seed.get(seedrownum); | |
249 | 238 | for (int i = 0; i < parametermodel.size; i++) { |
250 | 239 | tmp.set(i, seedrow.get(i)); |
251 | 240 | } |
252 | 241 | } |
253 | 242 | if (constrainthandler.isPossible(tmp) == false) { |
254 | - Error.printError("seedの" + (seedrownum + 1) + "行目が制約違反です"); | |
243 | + Error.printError(Main.language == Main.Language.JP ? "seedの" | |
244 | + + (seedrownum + 1) + "行目が制約違反です" : "The" + (seedrownum + 1) | |
245 | + + "th seeding row violates the constraints."); | |
255 | 246 | return null; |
256 | 247 | } |
257 | - | |
248 | + | |
258 | 249 | // TODO tmpにグループを追加 |
259 | 250 | addGroupedTuples(tmp, tupleSequenceList); |
260 | - | |
251 | + | |
261 | 252 | // TODO 繰り返させる |
262 | 253 | // generateTempTest では tabを更新しない |
263 | - Testcase temptest = generateTempTest(tmp, tab, uncovTab); | |
254 | + Testcase temptest = generateTempTest(tmp, tab, uncovTab); | |
264 | 255 | int count = this.computeNewlyCoveredTuples(tab, temptest); |
265 | - | |
256 | + | |
266 | 257 | // System.err.print(count + ", "); |
267 | 258 | for (int i = 1; i < this.NumOfIterationForEachTest; i++) { |
268 | 259 | Testcase newtemptest = generateTempTest(tmp, tab, uncovTab); |
269 | 260 | int newcount = this.computeNewlyCoveredTuples(tab, newtemptest); |
270 | 261 | |
271 | 262 | // System.err.print(newcount + ", "); |
272 | - | |
263 | + | |
273 | 264 | if (count < newcount) { |
274 | 265 | count = newcount; |
275 | 266 | temptest = newtemptest; |
276 | 267 | } |
277 | 268 | } |
278 | - | |
269 | + | |
279 | 270 | // System.err.println(computeNewlyCoveredTuples(tab, temptest)); |
280 | - | |
281 | - | |
271 | + | |
282 | 272 | // カバーしたペアーを実際にuncovTabに反映 |
283 | 273 | // finalizePairTableより前でないとだめ |
284 | 274 | finallizeUncoverTable(uncovTab, tab, temptest); |
285 | 275 | |
286 | 276 | // カバーしたペアーを実際にtabに反映 |
287 | 277 | int newtuples = finalizePairTable(tab, temptest); |
288 | - | |
278 | + | |
289 | 279 | // 返り値の設定 |
290 | 280 | ResultOfGenerateOneTest res = new ResultOfGenerateOneTest(); |
291 | 281 | res.test = temptest; |
292 | 282 | res.numOfCoveredTuples = newtuples; |
293 | 283 | if (isSeedUsed) { |
294 | 284 | res.nextSeedRow = seedrownum + 1; |
295 | - } else | |
285 | + } else | |
296 | 286 | res.nextSeedRow = seedrownum; |
297 | 287 | return res; |
298 | 288 | } |
299 | 289 | |
300 | - | |
301 | - private void addGroupedTuples(Testcase tmp, List<List<Testcase>> tupleSequenceList) { | |
290 | + private void addGroupedTuples(Testcase tmp, | |
291 | + List<List<Testcase>> tupleSequenceList) { | |
302 | 292 | // TODO Auto-generated method stub |
303 | 293 | for (List<Testcase> TupleSequence : tupleSequenceList) { |
304 | 294 | for (int i = 0; i < TupleSequence.size(); i++) { |
@@ -308,7 +298,7 @@ class Generator2 extends Generator { | ||
308 | 298 | break; |
309 | 299 | } |
310 | 300 | } |
311 | - } | |
301 | + } | |
312 | 302 | } |
313 | 303 | |
314 | 304 | private void finallizeUncoverTable(ArrayList<Integer>[] uncovTab, |
@@ -316,42 +306,45 @@ class Generator2 extends Generator { | ||
316 | 306 | for (int p1 = 0; p1 < this.parametermodel.size; p1++) { |
317 | 307 | int numCovered = 0; |
318 | 308 | byte v1 = temptest.get(p1); |
319 | - if (v1 < 0) continue; | |
309 | + if (v1 < 0) | |
310 | + continue; | |
320 | 311 | for (int p2 = 0; p2 < this.parametermodel.size; p2++) { |
321 | - if (p1 == p2) continue; | |
312 | + if (p1 == p2) | |
313 | + continue; | |
322 | 314 | byte v2 = temptest.get(p2); |
323 | - if (v2 < 0) continue; | |
315 | + if (v2 < 0) | |
316 | + continue; | |
324 | 317 | if (tab.get(p1, v1, p2, v2) == false) |
325 | 318 | numCovered++; |
326 | 319 | } |
327 | 320 | int numUncovered = uncovTab[p1].get(v1); |
328 | 321 | uncovTab[p1].set(v1, numUncovered - numCovered); |
329 | 322 | } |
330 | - | |
323 | + | |
331 | 324 | } |
332 | 325 | |
333 | - private Testcase generateTempTest(Testcase seedrow, PairTable tab, ArrayList<Integer>[] uncovTab) { | |
334 | - | |
326 | + private Testcase generateTempTest(Testcase seedrow, PairTable tab, | |
327 | + ArrayList<Integer>[] uncovTab) { | |
328 | + | |
335 | 329 | // tmpをコピー |
336 | 330 | Testcase tmp = seedrow.makeClone(); |
337 | - | |
331 | + | |
338 | 332 | // TODO ランダムな因子列を生成 |
339 | 333 | int[] parametersequence = new int[parametermodel.size]; |
340 | - for (int i = 0; i < parametermodel.size; i++) | |
334 | + for (int i = 0; i < parametermodel.size; i++) | |
341 | 335 | parametersequence[i] = i; |
342 | 336 | // シャッフル |
343 | 337 | for (int i = 1; i < parametermodel.size; i++) { |
344 | 338 | int dst = this.rnd.nextInt(i + 1); |
345 | 339 | int tmppara = parametersequence[i]; |
346 | - parametersequence[i] = parametersequence[dst]; | |
347 | - parametersequence[dst] = tmppara; | |
340 | + parametersequence[i] = parametersequence[dst]; | |
341 | + parametersequence[dst] = tmppara; | |
348 | 342 | } |
349 | 343 | |
350 | - /* debug | |
351 | - for (int i = 0; i < parametermodel.size; i++) | |
352 | - System.out.print(parametersequence[i] + " "); | |
353 | - System.out.println(); | |
354 | - */ | |
344 | + /* | |
345 | + * debug for (int i = 0; i < parametermodel.size; i++) | |
346 | + * System.out.print(parametersequence[i] + " "); System.out.println(); | |
347 | + */ | |
355 | 348 | |
356 | 349 | // 各因子について |
357 | 350 | for (int i = 0; i < parametermodel.size; i++) { |
@@ -373,18 +366,20 @@ class Generator2 extends Generator { | ||
373 | 366 | } |
374 | 367 | // assert (bestValue >= 0) : "error in chosing a value"; |
375 | 368 | if (bestValue == -1) { |
376 | - Error.printError("seedに制約違反の行があります"); | |
369 | + Error.printError(Main.language == Main.Language.JP ? "seedに制約違反の行があります" | |
370 | + : "Some seeding row violates the constraints."); | |
371 | + | |
377 | 372 | return null; |
378 | 373 | } |
379 | 374 | if (newlyCoveredTuples == 0) { |
380 | 375 | // TODO カバー数 0 なら,期待されるペア数を数え,最大のものを選択 |
381 | 376 | // TODO 期待するペア数には,絶対にむりなものもある(すでに値が決まっている因子とのペア) |
382 | 377 | bestValue = -1; |
383 | - int possibleTuples = -1; | |
378 | + int possibleTuples = -1; | |
384 | 379 | |
385 | 380 | // for tie breaking |
386 | - List<Byte>candidateValues = new ArrayList<Byte>(); | |
387 | - | |
381 | + List<Byte> candidateValues = new ArrayList<Byte>(); | |
382 | + | |
388 | 383 | for (byte v = 0; v < this.parametermodel.range[p]; v++) { |
389 | 384 | tmp.set(p, v); |
390 | 385 | if (constrainthandler.isPossible(tmp)) { |
@@ -394,33 +389,35 @@ class Generator2 extends Generator { | ||
394 | 389 | possibleTuples = newtuples; |
395 | 390 | } |
396 | 391 | // for tie breaking |
397 | - if (newtuples == 0 && possibleTuples == 0) | |
392 | + if (newtuples == 0 && possibleTuples == 0) | |
398 | 393 | candidateValues.add(v); |
399 | 394 | } |
400 | 395 | } |
401 | 396 | // どれを選んでも同じなら,ランダムに選ぶ |
402 | 397 | // for tie breaking |
403 | - if (possibleTuples == 0) | |
404 | - bestValue = candidateValues.get(this.rnd.nextInt(candidateValues.size())); | |
398 | + if (possibleTuples == 0) | |
399 | + bestValue = candidateValues.get(this.rnd | |
400 | + .nextInt(candidateValues.size())); | |
405 | 401 | } |
406 | 402 | tmp.set(p, bestValue); |
407 | 403 | } |
408 | 404 | } |
409 | - | |
405 | + | |
410 | 406 | // 新カバーが0ということもある |
411 | 407 | return tmp; |
412 | 408 | } |
413 | 409 | |
414 | - | |
415 | 410 | private int computeNewlyCoveredTuples(Testcase test, int p, PairTable tab) { |
416 | 411 | int numOfNewlyCoveredTuples = 0; |
417 | 412 | // bug? |
418 | -// for (int i = 0; i < numOfParameters - 1; i++) { | |
413 | + // for (int i = 0; i < numOfParameters - 1; i++) { | |
419 | 414 | for (int i = 0; i < numOfParameters; i++) { |
420 | - if (p == i) continue; | |
421 | - if (test.get(i) < 0) continue; | |
415 | + if (p == i) | |
416 | + continue; | |
417 | + if (test.get(i) < 0) | |
418 | + continue; | |
422 | 419 | if (tab.get(p, test.get(p), i, test.get(i)) == false) { |
423 | - numOfNewlyCoveredTuples++; | |
420 | + numOfNewlyCoveredTuples++; | |
424 | 421 | } |
425 | 422 | } |
426 | 423 | return numOfNewlyCoveredTuples; |
@@ -444,7 +441,7 @@ class Generator2 extends Generator { | ||
444 | 441 | // strength = 2 |
445 | 442 | int numOfPairs = 0; |
446 | 443 | for (int i = 0; i < numOfParameters - 1; i++) { |
447 | - for (int j = i + 1; j < numOfParameters; j++) { | |
444 | + for (int j = i + 1; j < numOfParameters; j++) { | |
448 | 445 | for (byte v1 = 0; v1 < parametermodel.range[i]; v1++) |
449 | 446 | for (byte v2 = 0; v2 < parametermodel.range[j]; v2++) { |
450 | 447 | // pairの生成 |
@@ -456,14 +453,14 @@ class Generator2 extends Generator { | ||
456 | 453 | // 禁則違反ならset |
457 | 454 | if (constrainthandler.isPossible(pair) == false) { |
458 | 455 | tab.set(i, v1, j, v2); |
459 | - } else | |
456 | + } else | |
460 | 457 | numOfPairs++; |
461 | 458 | } |
462 | 459 | } |
463 | 460 | } |
464 | 461 | return numOfPairs; |
465 | 462 | } |
466 | - | |
463 | + | |
467 | 464 | // 2.20 |
468 | 465 | // copy from finalize.... |
469 | 466 | private int computeNewlyCoveredTuples(PairTable tab, Testcase test) { |
@@ -491,15 +488,16 @@ abstract class TupleTable { | ||
491 | 488 | class PairTable extends TupleTable { |
492 | 489 | PairList[][] table; |
493 | 490 | ParameterModel parametermodel; |
494 | - | |
491 | + | |
495 | 492 | PairTable(ParameterModel parametermodel) { |
496 | 493 | this.parametermodel = parametermodel; |
497 | - int n = parametermodel.size; | |
494 | + int n = parametermodel.size; | |
498 | 495 | table = new PairList[n][n]; |
499 | 496 | for (int i = 0; i < n; i++) { |
500 | 497 | for (int j = 0; j < n; j++) { |
501 | 498 | if (i < j) |
502 | - table[i][j] = new PairList(parametermodel.range[i], parametermodel.range[j]); | |
499 | + table[i][j] = new PairList(parametermodel.range[i], | |
500 | + parametermodel.range[j]); | |
503 | 501 | else if (i > j) { |
504 | 502 | // TODO: エラーがでる?なんで? |
505 | 503 | // table[i][j].list = table[j][i].list.clone(); |
@@ -508,27 +506,37 @@ class PairTable extends TupleTable { | ||
508 | 506 | } |
509 | 507 | } |
510 | 508 | } |
511 | - | |
509 | + | |
512 | 510 | boolean get(int p1, byte v1, int p2, byte v2) { |
513 | 511 | // TODO Auto-generated method stub |
514 | 512 | if (p2 < p1) { |
515 | - int tmp = p1; p1 = p2; p2 = tmp; | |
516 | - byte tmv = v1; v1 = v2; v2 = tmv; | |
513 | + int tmp = p1; | |
514 | + p1 = p2; | |
515 | + p2 = tmp; | |
516 | + byte tmv = v1; | |
517 | + v1 = v2; | |
518 | + v2 = tmv; | |
517 | 519 | } |
518 | 520 | // y * xrange + x |
519 | -/* if (this.table[p1][p2].list.length <= v1 + v2 * (parametermodel.range[p1])) { | |
520 | - if (0 > v1 + v2 * (parametermodel.range[p1])) { | |
521 | - System.out.println("size p1 p2 v1 v2" + this.table[p1][p2].list.length + "," + p1+","+p2+"," + v1 + "," +v2); | |
522 | - } | |
523 | - */ | |
521 | + /* | |
522 | + * if (this.table[p1][p2].list.length <= v1 + v2 * | |
523 | + * (parametermodel.range[p1])) { if (0 > v1 + v2 * | |
524 | + * (parametermodel.range[p1])) { System.out.println("size p1 p2 v1 v2" + | |
525 | + * this.table[p1][p2].list.length + "," + p1+","+p2+"," + v1 + "," +v2); | |
526 | + * } | |
527 | + */ | |
524 | 528 | return this.table[p1][p2].list[v1 + v2 * (parametermodel.range[p1])]; |
525 | 529 | } |
526 | 530 | |
527 | 531 | // 現れない場合.すでにカバーした場合 |
528 | - void set(int p1, byte v1, int p2, byte v2) { | |
532 | + void set(int p1, byte v1, int p2, byte v2) { | |
529 | 533 | if (p2 < p1) { |
530 | - int tmp = p1; p1 = p2; p2 = tmp; | |
531 | - byte tmv = v1; v1 = v2; v2 = tmv; | |
534 | + int tmp = p1; | |
535 | + p1 = p2; | |
536 | + p2 = tmp; | |
537 | + byte tmv = v1; | |
538 | + v1 = v2; | |
539 | + v2 = tmv; | |
532 | 540 | } |
533 | 541 | // y * xrange + x |
534 | 542 | this.table[p1][p2].list[v1 + v2 * (parametermodel.range[p1])] = true; |
@@ -537,6 +545,7 @@ class PairTable extends TupleTable { | ||
537 | 545 | |
538 | 546 | class PairList { |
539 | 547 | boolean[] list; |
548 | + | |
540 | 549 | PairList(byte range1, byte range2) { |
541 | 550 | this.list = new boolean[range1 * range2]; |
542 | 551 | } |
@@ -32,19 +32,19 @@ class Generator3 extends Generator { | ||
32 | 32 | int seedrownum = 0; |
33 | 33 | while (numOfUncoveredTuples > 0 || hasTuplesToCover(tupleSequenceList)) { |
34 | 34 | // testcase 1個生成 |
35 | - ResultOfGenerateOneTest newresult | |
36 | - = generateOneTest(tab, seedrownum, uncovTab, tupleSequenceList); | |
35 | + ResultOfGenerateOneTest newresult = generateOneTest(tab, | |
36 | + seedrownum, uncovTab, tupleSequenceList); | |
37 | 37 | |
38 | 38 | res.add(newresult.test); |
39 | - if (res.size() > MaxNumOfTestcases) | |
39 | + if (res.size() > MaxNumOfTestcases) | |
40 | 40 | throw new OutOfMaxNumOfTestcasesException(); |
41 | - | |
41 | + | |
42 | 42 | numOfUncoveredTuples -= newresult.numOfCoveredTuples; |
43 | 43 | seedrownum = newresult.nextSeedRow; |
44 | 44 | } |
45 | 45 | return res; |
46 | 46 | } |
47 | - | |
47 | + | |
48 | 48 | private int checkAllTuples(TripleTable tab) { |
49 | 49 | // strength = 3 |
50 | 50 | int numOfTriples = 0; |
@@ -54,7 +54,7 @@ class Generator3 extends Generator { | ||
54 | 54 | for (byte v1 = 0; v1 < parametermodel.range[i]; v1++) |
55 | 55 | for (byte v2 = 0; v2 < parametermodel.range[j]; v2++) |
56 | 56 | for (byte v3 = 0; v3 < parametermodel.range[k]; v3++) { |
57 | - assert(i < j && j < k); | |
57 | + assert (i < j && j < k); | |
58 | 58 | // tripleの生成 |
59 | 59 | Testcase triple = new Testcase(numOfParameters); |
60 | 60 | triple.quantify(); |
@@ -73,8 +73,9 @@ class Generator3 extends Generator { | ||
73 | 73 | } |
74 | 74 | return numOfTriples; |
75 | 75 | } |
76 | - | |
77 | - private void initializeUncovTab(ArrayList<Integer>[] uncovTab, TripleTable tab) { | |
76 | + | |
77 | + private void initializeUncovTab(ArrayList<Integer>[] uncovTab, | |
78 | + TripleTable tab) { | |
78 | 79 | assert (parametermodel.size == uncovTab.length); |
79 | 80 | // uncovTabの計算.triple (strength = 3) の場合 |
80 | 81 | for (int p = 0; p < parametermodel.size; p++) { |
@@ -97,90 +98,102 @@ class Generator3 extends Generator { | ||
97 | 98 | } |
98 | 99 | } |
99 | 100 | } |
100 | - | |
101 | - private ResultOfGenerateOneTest generateOneTest(TripleTable tab, int seedrownum, ArrayList<Integer>[] uncovTab, List<List<Testcase>> tupleSequenceList) { | |
101 | + | |
102 | + private ResultOfGenerateOneTest generateOneTest(TripleTable tab, | |
103 | + int seedrownum, ArrayList<Integer>[] uncovTab, | |
104 | + List<List<Testcase>> tupleSequenceList) { | |
102 | 105 | // 空のテストケースを1つつくる |
103 | 106 | Testcase tmp = new Testcase(parametermodel.size); |
104 | 107 | tmp.quantify(); |
105 | - | |
108 | + | |
106 | 109 | boolean isSeedUsed = false; |
107 | 110 | // seedのコピー 制約を満たさなかったらエラー |
108 | - if (seed.size() > 0 && seedrownum < seed.size() ) { | |
111 | + if (seed.size() > 0 && seedrownum < seed.size()) { | |
109 | 112 | isSeedUsed = true; |
110 | - Testcase seedrow = seed.get(seedrownum); | |
113 | + Testcase seedrow = seed.get(seedrownum); | |
111 | 114 | for (int i = 0; i < parametermodel.size; i++) { |
112 | 115 | tmp.set(i, seedrow.get(i)); |
113 | 116 | } |
114 | 117 | } |
115 | 118 | if (constrainthandler.isPossible(tmp) == false) { |
116 | - Error.printError("seedの" + (seedrownum + 1) + "行目が制約違反です"); | |
119 | + Error.printError(Main.language == Main.Language.JP ? "seedの" | |
120 | + + (seedrownum + 1) + "行目が制約違反です" : "The" + (seedrownum + 1) | |
121 | + + "th seeding row violates the constraints."); | |
122 | + | |
117 | 123 | return null; |
118 | 124 | } |
119 | 125 | |
120 | 126 | // 2.20 |
121 | 127 | // tmpにグループを追加 |
122 | 128 | boolean isGroupUsed = addGroupedTuples(tmp, tupleSequenceList); |
123 | - | |
129 | + | |
124 | 130 | // TODO 繰り返させる |
125 | 131 | // generateTempTest では tabを更新しない |
126 | 132 | Testcase temptest = generateTempTest(tmp, tab, uncovTab); |
127 | 133 | // 2.20 |
128 | 134 | // 0カバーの場合 |
129 | - if (isSeedUsed == false && isGroupUsed == false && computeNewlyCoveredTuples(tab, temptest) == 0) { | |
135 | + if (isSeedUsed == false && isGroupUsed == false | |
136 | + && computeNewlyCoveredTuples(tab, temptest) == 0) { | |
130 | 137 | addUncoveredTuple(tmp, tab, uncovTab); |
131 | 138 | temptest = generateTempTest(tmp, tab, uncovTab); |
132 | 139 | } |
133 | - | |
140 | + | |
134 | 141 | // カバーしたペアーを実際にuncovTabに反映 |
135 | 142 | // finalizePairTableより前でないとだめ |
136 | 143 | finallizeUncoverTable(uncovTab, tab, temptest); |
137 | 144 | |
138 | 145 | // カバーしたペアーを実際にtabに反映 |
139 | 146 | int newtuples = finalizeTupleTable(tab, temptest); |
140 | - | |
147 | + | |
141 | 148 | // 返り値の設定 |
142 | 149 | ResultOfGenerateOneTest res = new ResultOfGenerateOneTest(); |
143 | 150 | res.test = temptest; |
144 | 151 | res.numOfCoveredTuples = newtuples; |
145 | 152 | if (isSeedUsed) { |
146 | 153 | res.nextSeedRow = seedrownum + 1; |
147 | - } else | |
154 | + } else | |
148 | 155 | res.nextSeedRow = seedrownum; |
149 | 156 | return res; |
150 | 157 | } |
151 | - | |
158 | + | |
152 | 159 | private void finallizeUncoverTable(ArrayList<Integer>[] uncovTab, |
153 | 160 | TripleTable tab, Testcase temptest) { |
154 | 161 | for (int p = 0; p < this.parametermodel.size; p++) { |
155 | 162 | int numCovered = 0; |
156 | 163 | byte v = temptest.get(p); |
157 | - if (v < 0) continue; | |
158 | - | |
164 | + if (v < 0) | |
165 | + continue; | |
166 | + | |
159 | 167 | for (int p1 = 0; p1 < this.parametermodel.size - 1; p1++) { |
160 | 168 | for (int p2 = p1 + 1; p2 < this.parametermodel.size; p2++) { |
161 | - if (p == p1 || p == p2) continue; | |
169 | + if (p == p1 || p == p2) | |
170 | + continue; | |
162 | 171 | byte v1 = temptest.get(p1); |
163 | - if (v1 < 0) continue; | |
172 | + if (v1 < 0) | |
173 | + continue; | |
164 | 174 | byte v2 = temptest.get(p2); |
165 | - if (v2 < 0) continue; | |
175 | + if (v2 < 0) | |
176 | + continue; | |
166 | 177 | if (tab.get(p, v, p1, v1, p2, v2) == false) |
167 | 178 | numCovered++; |
168 | 179 | } |
169 | 180 | } |
170 | - | |
181 | + | |
171 | 182 | int numUncovered = uncovTab[p].get(v); |
172 | 183 | uncovTab[p].set(v, numUncovered - numCovered); |
173 | 184 | } |
174 | - | |
185 | + | |
175 | 186 | } |
176 | - | |
187 | + | |
177 | 188 | private int finalizeTupleTable(TripleTable tab, Testcase test) { |
178 | 189 | int numOfNewlyCoveredTuples = 0; |
179 | 190 | for (int p0 = 0; p0 < numOfParameters - 2; p0++) { |
180 | 191 | for (int p1 = p0 + 1; p1 < numOfParameters - 1; p1++) { |
181 | 192 | for (int p2 = p1 + 1; p2 < numOfParameters; p2++) { |
182 | - if (tab.get(p0, test.get(p0), p1, test.get(p1), p2, test.get(p2)) == false) { | |
183 | - tab.set(p0, test.get(p0), p1, test.get(p1), p2, test.get(p2)); | |
193 | + if (tab.get(p0, test.get(p0), p1, test.get(p1), p2, | |
194 | + test.get(p2)) == false) { | |
195 | + tab.set(p0, test.get(p0), p1, test.get(p1), p2, | |
196 | + test.get(p2)); | |
184 | 197 | numOfNewlyCoveredTuples++; |
185 | 198 | } |
186 | 199 | } |
@@ -188,19 +201,22 @@ class Generator3 extends Generator { | ||
188 | 201 | } |
189 | 202 | return numOfNewlyCoveredTuples; |
190 | 203 | } |
191 | - | |
204 | + | |
192 | 205 | // 2.20 |
193 | 206 | // 前の位置をおぼえておく |
194 | - private void addUncoveredTuple(Testcase tmp, TripleTable tab, ArrayList<Integer>[] uncovTab) { | |
195 | - | |
196 | - for (int p0 = 0; p0 < numOfParameters - 2; p0++) | |
207 | + private void addUncoveredTuple(Testcase tmp, TripleTable tab, | |
208 | + ArrayList<Integer>[] uncovTab) { | |
209 | + | |
210 | + for (int p0 = 0; p0 < numOfParameters - 2; p0++) | |
197 | 211 | for (byte v0 = 0; v0 < this.parametermodel.range[p0]; v0++) { |
198 | - if (uncovTab[p0].get(v0) == 0) continue; | |
199 | - for (int p1 = p0 + 1; p1 < numOfParameters - 1; p1++) | |
212 | + if (uncovTab[p0].get(v0) == 0) | |
213 | + continue; | |
214 | + for (int p1 = p0 + 1; p1 < numOfParameters - 1; p1++) | |
200 | 215 | for (byte v1 = 0; v1 < this.parametermodel.range[p1]; v1++) { |
201 | - if (uncovTab[p1].get(v1) == 0) continue; | |
202 | - for (int p2 = p1 + 1; p2 < numOfParameters; p2++) | |
203 | - for (byte v2 = 0; v2 < this.parametermodel.range[p2]; v2++) | |
216 | + if (uncovTab[p1].get(v1) == 0) | |
217 | + continue; | |
218 | + for (int p2 = p1 + 1; p2 < numOfParameters; p2++) | |
219 | + for (byte v2 = 0; v2 < this.parametermodel.range[p2]; v2++) | |
204 | 220 | if (tab.get(p0, v0, p1, v1, p2, v2) == false) { |
205 | 221 | tmp.set(p0, v0); |
206 | 222 | tmp.set(p1, v1); |
@@ -210,10 +226,11 @@ class Generator3 extends Generator { | ||
210 | 226 | } |
211 | 227 | } |
212 | 228 | } |
213 | - | |
229 | + | |
214 | 230 | // 2.20 |
215 | 231 | // return true if tuples from at least one group are added. |
216 | - private boolean addGroupedTuples(Testcase tmp, List<List<Testcase>> tupleSequenceList) { | |
232 | + private boolean addGroupedTuples(Testcase tmp, | |
233 | + List<List<Testcase>> tupleSequenceList) { | |
217 | 234 | boolean isGroupAdded = false; |
218 | 235 | for (List<Testcase> TupleSequence : tupleSequenceList) { |
219 | 236 | for (int i = 0; i < TupleSequence.size(); i++) { |
@@ -224,25 +241,26 @@ class Generator3 extends Generator { | ||
224 | 241 | break; |
225 | 242 | } |
226 | 243 | } |
227 | - } | |
244 | + } | |
228 | 245 | return isGroupAdded; |
229 | 246 | } |
230 | 247 | |
231 | - private Testcase generateTempTest(Testcase seedrow, TripleTable tab, ArrayList<Integer>[] uncovTab) { | |
232 | - | |
248 | + private Testcase generateTempTest(Testcase seedrow, TripleTable tab, | |
249 | + ArrayList<Integer>[] uncovTab) { | |
250 | + | |
233 | 251 | // tmpをコピー |
234 | 252 | Testcase tmp = seedrow.makeClone(); |
235 | - | |
253 | + | |
236 | 254 | // TODO ランダムな因子列を生成 |
237 | 255 | int[] parametersequence = new int[parametermodel.size]; |
238 | - for (int i = 0; i < parametermodel.size; i++) | |
256 | + for (int i = 0; i < parametermodel.size; i++) | |
239 | 257 | parametersequence[i] = i; |
240 | 258 | // シャッフル |
241 | 259 | for (int i = 1; i < parametermodel.size; i++) { |
242 | 260 | int dst = this.rnd.nextInt(i + 1); |
243 | 261 | int tmppara = parametersequence[i]; |
244 | - parametersequence[i] = parametersequence[dst]; | |
245 | - parametersequence[dst] = tmppara; | |
262 | + parametersequence[i] = parametersequence[dst]; | |
263 | + parametersequence[dst] = tmppara; | |
246 | 264 | } |
247 | 265 | |
248 | 266 | // 各因子について |
@@ -265,17 +283,18 @@ class Generator3 extends Generator { | ||
265 | 283 | } |
266 | 284 | // assert (bestValue >= 0) : "error in chosing a value"; |
267 | 285 | if (bestValue == -1) { |
268 | - Error.printError("seedに制約違反の行があります"); | |
286 | + Error.printError(Main.language == Main.Language.JP ? "seedに制約違反の行があります" | |
287 | + : "Some seeding row violates the constraints."); | |
269 | 288 | return null; |
270 | 289 | } |
271 | 290 | if (newlyCoveredTuples == 0) { |
272 | 291 | // TODO カバー数 0 なら,期待されるペア数を数え,最大のものを選択 |
273 | 292 | // TODO 期待するペア数には,絶対にむりなものもある(すでに値が決まっている因子とのペア) |
274 | 293 | bestValue = -1; |
275 | - int possibleTuples = -1; | |
294 | + int possibleTuples = -1; | |
276 | 295 | // for tie breaking |
277 | - List<Byte>candidateValues = new ArrayList<Byte>(); | |
278 | - | |
296 | + List<Byte> candidateValues = new ArrayList<Byte>(); | |
297 | + | |
279 | 298 | for (byte v = 0; v < this.parametermodel.range[p]; v++) { |
280 | 299 | tmp.set(p, v); |
281 | 300 | if (constrainthandler.isPossible(tmp)) { |
@@ -285,19 +304,20 @@ class Generator3 extends Generator { | ||
285 | 304 | possibleTuples = newtuples; |
286 | 305 | } |
287 | 306 | // for tie breaking |
288 | - if (newtuples == 0 && possibleTuples == 0) | |
307 | + if (newtuples == 0 && possibleTuples == 0) | |
289 | 308 | candidateValues.add(v); |
290 | 309 | } |
291 | 310 | } |
292 | 311 | // どれを選んでも同じなら,ランダムに選ぶ |
293 | 312 | // for tie breaking |
294 | - if (possibleTuples == 0) | |
295 | - bestValue = candidateValues.get(this.rnd.nextInt(candidateValues.size())); | |
313 | + if (possibleTuples == 0) | |
314 | + bestValue = candidateValues.get(this.rnd | |
315 | + .nextInt(candidateValues.size())); | |
296 | 316 | } |
297 | 317 | tmp.set(p, bestValue); |
298 | 318 | } |
299 | 319 | } |
300 | - | |
320 | + | |
301 | 321 | // 新カバーが0ということもある |
302 | 322 | return tmp; |
303 | 323 | } |
@@ -306,8 +326,10 @@ class Generator3 extends Generator { | ||
306 | 326 | int numOfNewlyCoveredTuples = 0; |
307 | 327 | for (int p1 = 0; p1 < numOfParameters - 1; p1++) { |
308 | 328 | for (int p2 = p1 + 1; p2 < numOfParameters; p2++) { |
309 | - if (p == p1 || p == p2) continue; | |
310 | - if (test.get(p1) < 0 || test.get(p2) < 0) continue; | |
329 | + if (p == p1 || p == p2) | |
330 | + continue; | |
331 | + if (test.get(p1) < 0 || test.get(p2) < 0) | |
332 | + continue; | |
311 | 333 | if (tab.get(p, test.get(p), p1, test.get(p1), p2, test.get(p2)) == false) { |
312 | 334 | numOfNewlyCoveredTuples++; |
313 | 335 | } |
@@ -315,7 +337,7 @@ class Generator3 extends Generator { | ||
315 | 337 | } |
316 | 338 | return numOfNewlyCoveredTuples; |
317 | 339 | } |
318 | - | |
340 | + | |
319 | 341 | // 2.20 |
320 | 342 | // copy from finalize.... |
321 | 343 | private int computeNewlyCoveredTuples(TripleTable tab, Testcase test) { |
@@ -323,7 +345,8 @@ class Generator3 extends Generator { | ||
323 | 345 | for (int p0 = 0; p0 < numOfParameters - 2; p0++) { |
324 | 346 | for (int p1 = p0 + 1; p1 < numOfParameters - 1; p1++) { |
325 | 347 | for (int p2 = p1 + 1; p2 < numOfParameters; p2++) { |
326 | - if (tab.get(p0, test.get(p0), p1, test.get(p1), p2, test.get(p2)) == false) { | |
348 | + if (tab.get(p0, test.get(p0), p1, test.get(p1), p2, | |
349 | + test.get(p2)) == false) { | |
327 | 350 | numOfNewlyCoveredTuples++; |
328 | 351 | } |
329 | 352 | } |
@@ -333,11 +356,10 @@ class Generator3 extends Generator { | ||
333 | 356 | } |
334 | 357 | } |
335 | 358 | |
336 | - | |
337 | 359 | class TripleTable extends TupleTable { |
338 | 360 | TripleList[][][] table; |
339 | 361 | ParameterModel parametermodel; |
340 | - | |
362 | + | |
341 | 363 | TripleTable(ParameterModel parametermodel) { |
342 | 364 | this.parametermodel = parametermodel; |
343 | 365 | int n = parametermodel.size; |
@@ -346,8 +368,10 @@ class TripleTable extends TupleTable { | ||
346 | 368 | for (int j = 0; j < n; j++) { |
347 | 369 | for (int k = 0; k < n; k++) { |
348 | 370 | if (i < j && j < k) |
349 | - table[i][j][k] = new TripleList(parametermodel.range[i], | |
350 | - parametermodel.range[j], parametermodel.range[k]); | |
371 | + table[i][j][k] = new TripleList( | |
372 | + parametermodel.range[i], | |
373 | + parametermodel.range[j], | |
374 | + parametermodel.range[k]); | |
351 | 375 | else if (i > j) { |
352 | 376 | // TODO: エラーがでる?なんで? |
353 | 377 | // table[i][j].list = table[j][i].list.clone(); |
@@ -356,7 +380,7 @@ class TripleTable extends TupleTable { | ||
356 | 380 | } |
357 | 381 | } |
358 | 382 | } |
359 | - | |
383 | + | |
360 | 384 | // requires p1 != p2 != p3 |
361 | 385 | boolean get(int p1, byte v1, int p2, byte v2, int p3, byte v3) { |
362 | 386 | // TODO Auto-generated method stub |
@@ -367,25 +391,25 @@ class TripleTable extends TupleTable { | ||
367 | 391 | pv[1] = new ParameterValuePair(p2, v2); |
368 | 392 | pv[2] = new ParameterValuePair(p3, v3); |
369 | 393 | Arrays.sort(pv, new ParameterValuePairComparator()); |
370 | - | |
371 | -// return this.table[pv[1].p][pv[2].p][pv[3].p].list[getOffset(p1, v1, p2, v2, p3, v3)]; | |
394 | + | |
395 | + // return this.table[pv[1].p][pv[2].p][pv[3].p].list[getOffset(p1, v1, | |
396 | + // p2, v2, p3, v3)]; | |
372 | 397 | return this.table[pv[0].p][pv[1].p][pv[2].p].list[getOffset(pv)]; |
373 | 398 | |
374 | 399 | } |
375 | 400 | |
376 | 401 | // 現れない場合.すでにカバーした場合 |
377 | 402 | // requires p1 != p2 != p3 |
378 | - void set(int p1, byte v1, int p2, byte v2, int p3, byte v3) { | |
403 | + void set(int p1, byte v1, int p2, byte v2, int p3, byte v3) { | |
379 | 404 | ParameterValuePair[] pv = new ParameterValuePair[3]; |
380 | 405 | pv[0] = new ParameterValuePair(p1, v1); |
381 | 406 | pv[1] = new ParameterValuePair(p2, v2); |
382 | 407 | pv[2] = new ParameterValuePair(p3, v3); |
383 | 408 | Arrays.sort(pv, new ParameterValuePairComparator()); |
384 | - | |
409 | + | |
385 | 410 | this.table[pv[0].p][pv[1].p][pv[2].p].list[getOffset(pv)] = true; |
386 | 411 | } |
387 | - | |
388 | - | |
412 | + | |
389 | 413 | private int getOffset(ParameterValuePair[] pv) { |
390 | 414 | int offset = pv[0].v; |
391 | 415 | for (int i = 1; i < pv.length; i++) { |
@@ -399,9 +423,9 @@ class TripleTable extends TupleTable { | ||
399 | 423 | } |
400 | 424 | } |
401 | 425 | |
402 | - | |
403 | 426 | class TripleList { |
404 | 427 | boolean[] list; |
428 | + | |
405 | 429 | TripleList(byte range1, byte range2, byte range3) { |
406 | 430 | this.list = new boolean[range1 * range2 * range3]; |
407 | 431 | } |
@@ -410,7 +434,8 @@ class TripleList { | ||
410 | 434 | class ParameterValuePair { |
411 | 435 | int p; |
412 | 436 | byte v; |
413 | - ParameterValuePair (int p, byte v) { | |
437 | + | |
438 | + ParameterValuePair(int p, byte v) { | |
414 | 439 | this.p = p; |
415 | 440 | this.v = v; |
416 | 441 | } |
@@ -420,9 +445,11 @@ class ParameterValuePairComparator implements Comparator<ParameterValuePair> { | ||
420 | 445 | @Override |
421 | 446 | public int compare(ParameterValuePair o1, ParameterValuePair o2) { |
422 | 447 | // TODO Auto-generated method stub |
423 | - if (o1.p < o2.p) return -1; | |
424 | - if (o1.p > o2.p) return 1; | |
448 | + if (o1.p < o2.p) | |
449 | + return -1; | |
450 | + if (o1.p > o2.p) | |
451 | + return 1; | |
425 | 452 | return 0; |
426 | 453 | } |
427 | - | |
454 | + | |
428 | 455 | } |
@@ -31,19 +31,19 @@ class Generator4 extends Generator { | ||
31 | 31 | int seedrownum = 0; |
32 | 32 | while (numOfUncoveredTuples > 0 || hasTuplesToCover(tupleSequenceList)) { |
33 | 33 | // testcase 1個生成 |
34 | - ResultOfGenerateOneTest newresult | |
35 | - = generateOneTest(tab, seedrownum, uncovTab, tupleSequenceList); | |
34 | + ResultOfGenerateOneTest newresult = generateOneTest(tab, | |
35 | + seedrownum, uncovTab, tupleSequenceList); | |
36 | 36 | |
37 | 37 | res.add(newresult.test); |
38 | - if (res.size() > MaxNumOfTestcases) | |
38 | + if (res.size() > MaxNumOfTestcases) | |
39 | 39 | throw new OutOfMaxNumOfTestcasesException(); |
40 | - | |
40 | + | |
41 | 41 | numOfUncoveredTuples -= newresult.numOfCoveredTuples; |
42 | 42 | seedrownum = newresult.nextSeedRow; |
43 | 43 | } |
44 | 44 | return res; |
45 | 45 | } |
46 | - | |
46 | + | |
47 | 47 | private int checkAllTuples(QuadTable tab) { |
48 | 48 | // strength = 4 |
49 | 49 | int numOfTuples = 0; |
@@ -56,7 +56,8 @@ class Generator4 extends Generator { | ||
56 | 56 | for (byte v2 = 0; v2 < parametermodel.range[p2]; v2++) { |
57 | 57 | for (byte v3 = 0; v3 < parametermodel.range[p3]; v3++) { |
58 | 58 | // tupleの生成 |
59 | - Testcase tuple = new Testcase(numOfParameters); | |
59 | + Testcase tuple = new Testcase( | |
60 | + numOfParameters); | |
60 | 61 | tuple.quantify(); |
61 | 62 | tuple.set(p0, v0); |
62 | 63 | tuple.set(p1, v1); |
@@ -65,7 +66,8 @@ class Generator4 extends Generator { | ||
65 | 66 | // tupleのチェック |
66 | 67 | // 禁則違反ならset |
67 | 68 | if (constrainthandler.isPossible(tuple) == false) { |
68 | - tab.set(p0, v0, p1, v1, p2, v2, p3, v3); | |
69 | + tab.set(p0, v0, p1, v1, p2, v2, p3, | |
70 | + v3); | |
69 | 71 | } else |
70 | 72 | numOfTuples++; |
71 | 73 | } |
@@ -78,7 +80,7 @@ class Generator4 extends Generator { | ||
78 | 80 | } |
79 | 81 | return numOfTuples; |
80 | 82 | } |
81 | - | |
83 | + | |
82 | 84 | private void initializeUncovTab(ArrayList<Integer>[] uncovTab, QuadTable tab) { |
83 | 85 | assert (parametermodel.size == uncovTab.length); |
84 | 86 | // uncovTabの計算. strength = 4 の場合 |
@@ -86,16 +88,17 @@ class Generator4 extends Generator { | ||
86 | 88 | uncovTab[p] = new ArrayList<Integer>(); |
87 | 89 | for (byte v = 0; v < parametermodel.range[p]; v++) { |
88 | 90 | int sum = 0; |
89 | - | |
91 | + | |
90 | 92 | for (int p1 = 0; p1 < parametermodel.size - 2; p1++) { |
91 | - for (int p2 = p1 + 1; p2 < parametermodel.size -1; p2++) { | |
93 | + for (int p2 = p1 + 1; p2 < parametermodel.size - 1; p2++) { | |
92 | 94 | for (int p3 = p2 + 1; p3 < parametermodel.size; p3++) { |
93 | 95 | if (p == p1 || p == p2 || p == p3) |
94 | 96 | continue; |
95 | 97 | for (byte v1 = 0; v1 < parametermodel.range[p1]; v1++) { |
96 | 98 | for (byte v2 = 0; v2 < parametermodel.range[p2]; v2++) { |
97 | 99 | for (byte v3 = 0; v3 < parametermodel.range[p3]; v3++) { |
98 | - if (tab.get(p, v, p1, v1, p2, v2, p3, v3) == false) | |
100 | + if (tab.get(p, v, p1, v1, p2, v2, p3, | |
101 | + v3) == false) | |
99 | 102 | sum++; |
100 | 103 | } |
101 | 104 | } |
@@ -103,101 +106,113 @@ class Generator4 extends Generator { | ||
103 | 106 | } |
104 | 107 | } |
105 | 108 | } |
106 | - | |
109 | + | |
107 | 110 | uncovTab[p].add(sum); |
108 | 111 | } |
109 | 112 | } |
110 | 113 | } |
111 | - | |
112 | - private ResultOfGenerateOneTest generateOneTest(QuadTable tab, int seedrownum, ArrayList<Integer>[] uncovTab, List<List<Testcase>> tupleSequenceList) { | |
114 | + | |
115 | + private ResultOfGenerateOneTest generateOneTest(QuadTable tab, | |
116 | + int seedrownum, ArrayList<Integer>[] uncovTab, | |
117 | + List<List<Testcase>> tupleSequenceList) { | |
113 | 118 | // 空のテストケースを1つつくる |
114 | 119 | Testcase tmp = new Testcase(parametermodel.size); |
115 | 120 | tmp.quantify(); |
116 | - | |
121 | + | |
117 | 122 | boolean isSeedUsed = false; |
118 | - | |
123 | + | |
119 | 124 | // seedのコピー 制約を満たさなかったらエラー |
120 | - if (seed.size() > 0 && seedrownum < seed.size() ) { | |
125 | + if (seed.size() > 0 && seedrownum < seed.size()) { | |
121 | 126 | isSeedUsed = true; |
122 | - Testcase seedrow = seed.get(seedrownum); | |
127 | + Testcase seedrow = seed.get(seedrownum); | |
123 | 128 | for (int i = 0; i < parametermodel.size; i++) { |
124 | 129 | tmp.set(i, seedrow.get(i)); |
125 | 130 | } |
126 | 131 | } |
127 | 132 | if (constrainthandler.isPossible(tmp) == false) { |
128 | - Error.printError("seedの" + (seedrownum + 1) + "行目が制約違反です"); | |
133 | + Error.printError(Main.language == Main.Language.JP ? "seedの" | |
134 | + + (seedrownum + 1) + "行目が制約違反です" : "The" + (seedrownum + 1) | |
135 | + + "th seeding row violates the constraints."); | |
129 | 136 | return null; |
130 | 137 | } |
131 | - | |
138 | + | |
132 | 139 | // tmpにグループを追加 |
133 | 140 | // 2.20 |
134 | 141 | boolean isGroupUsed = addGroupedTuples(tmp, tupleSequenceList); |
135 | - | |
142 | + | |
136 | 143 | // TODO 繰り返させる |
137 | 144 | // generateTempTest では tabを更新しない |
138 | 145 | Testcase temptest = generateTempTest(tmp, tab, uncovTab); |
139 | 146 | // 2.20 |
140 | 147 | // 0カバーの場合 |
141 | - if (isSeedUsed == false && isGroupUsed == false && computeNewlyCoveredTuples(tab, temptest) == 0) { | |
148 | + if (isSeedUsed == false && isGroupUsed == false | |
149 | + && computeNewlyCoveredTuples(tab, temptest) == 0) { | |
142 | 150 | addUncoveredTuple(tmp, tab, uncovTab); |
143 | 151 | temptest = generateTempTest(tmp, tab, uncovTab); |
144 | 152 | } |
145 | - | |
153 | + | |
146 | 154 | // カバーしたペアーを実際にuncovTabに反映 |
147 | 155 | // finalizePairTableより前でないとだめ |
148 | 156 | finallizeUncoverTable(uncovTab, tab, temptest); |
149 | 157 | |
150 | 158 | // カバーしたペアーを実際にtabに反映 |
151 | 159 | int newtuples = finalizeTupleTable(tab, temptest); |
152 | - | |
160 | + | |
153 | 161 | // 返り値の設定 |
154 | 162 | ResultOfGenerateOneTest res = new ResultOfGenerateOneTest(); |
155 | 163 | res.test = temptest; |
156 | 164 | res.numOfCoveredTuples = newtuples; |
157 | 165 | if (isSeedUsed) { |
158 | 166 | res.nextSeedRow = seedrownum + 1; |
159 | - } else | |
167 | + } else | |
160 | 168 | res.nextSeedRow = seedrownum; |
161 | 169 | return res; |
162 | 170 | } |
163 | - | |
171 | + | |
164 | 172 | private void finallizeUncoverTable(ArrayList<Integer>[] uncovTab, |
165 | 173 | QuadTable tab, Testcase temptest) { |
166 | 174 | for (int p = 0; p < this.parametermodel.size; p++) { |
167 | 175 | int numCovered = 0; |
168 | 176 | byte v = temptest.get(p); |
169 | - if (v < 0) continue; | |
170 | - | |
177 | + if (v < 0) | |
178 | + continue; | |
179 | + | |
171 | 180 | for (int p1 = 0; p1 < this.parametermodel.size - 2; p1++) { |
172 | 181 | for (int p2 = p1 + 1; p2 < this.parametermodel.size - 1; p2++) { |
173 | 182 | for (int p3 = p2 + 1; p3 < this.parametermodel.size; p3++) { |
174 | - if (p == p1 || p == p2 || p == p3) continue; | |
183 | + if (p == p1 || p == p2 || p == p3) | |
184 | + continue; | |
175 | 185 | byte v1 = temptest.get(p1); |
176 | - if (v1 < 0) continue; | |
186 | + if (v1 < 0) | |
187 | + continue; | |
177 | 188 | byte v2 = temptest.get(p2); |
178 | - if (v2 < 0) continue; | |
189 | + if (v2 < 0) | |
190 | + continue; | |
179 | 191 | byte v3 = temptest.get(p3); |
180 | - if (v3 < 0) continue; | |
192 | + if (v3 < 0) | |
193 | + continue; | |
181 | 194 | if (tab.get(p, v, p1, v1, p2, v2, p3, v3) == false) |
182 | 195 | numCovered++; |
183 | 196 | } |
184 | 197 | } |
185 | 198 | } |
186 | - | |
199 | + | |
187 | 200 | int numUncovered = uncovTab[p].get(v); |
188 | 201 | uncovTab[p].set(v, numUncovered - numCovered); |
189 | 202 | } |
190 | - | |
203 | + | |
191 | 204 | } |
192 | - | |
205 | + | |
193 | 206 | private int finalizeTupleTable(QuadTable tab, Testcase test) { |
194 | 207 | int numOfNewlyCoveredTuples = 0; |
195 | 208 | for (int p0 = 0; p0 < numOfParameters - 3; p0++) { |
196 | 209 | for (int p1 = p0 + 1; p1 < numOfParameters - 2; p1++) { |
197 | 210 | for (int p2 = p1 + 1; p2 < numOfParameters - 1; p2++) { |
198 | 211 | for (int p3 = p2 + 1; p3 < numOfParameters; p3++) { |
199 | - if (tab.get(p0, test.get(p0), p1, test.get(p1), p2, test.get(p2), p3, test.get(p3)) == false) { | |
200 | - tab.set(p0, test.get(p0), p1, test.get(p1), p2, test.get(p2), p3, test.get(p3)); | |
212 | + if (tab.get(p0, test.get(p0), p1, test.get(p1), p2, | |
213 | + test.get(p2), p3, test.get(p3)) == false) { | |
214 | + tab.set(p0, test.get(p0), p1, test.get(p1), p2, | |
215 | + test.get(p2), p3, test.get(p3)); | |
201 | 216 | numOfNewlyCoveredTuples++; |
202 | 217 | } |
203 | 218 | } |
@@ -206,38 +221,43 @@ class Generator4 extends Generator { | ||
206 | 221 | } |
207 | 222 | return numOfNewlyCoveredTuples; |
208 | 223 | } |
209 | - | |
210 | - | |
224 | + | |
211 | 225 | // 2.20 |
212 | 226 | // 前の位置をおぼえておく |
213 | - private void addUncoveredTuple(Testcase tmp, QuadTable tab, ArrayList<Integer>[] uncovTab) { | |
214 | - for (int p0 = 0; p0 < numOfParameters - 3; p0++) | |
227 | + private void addUncoveredTuple(Testcase tmp, QuadTable tab, | |
228 | + ArrayList<Integer>[] uncovTab) { | |
229 | + for (int p0 = 0; p0 < numOfParameters - 3; p0++) | |
215 | 230 | for (byte v0 = 0; v0 < this.parametermodel.range[p0]; v0++) { |
216 | - if (uncovTab[p0].get(v0) == 0) continue; | |
217 | - for (int p1 = p0 + 1; p1 < numOfParameters - 2; p1++) | |
231 | + if (uncovTab[p0].get(v0) == 0) | |
232 | + continue; | |
233 | + for (int p1 = p0 + 1; p1 < numOfParameters - 2; p1++) | |
218 | 234 | for (byte v1 = 0; v1 < this.parametermodel.range[p1]; v1++) { |
219 | - if (uncovTab[p1].get(v1) == 0) continue; | |
235 | + if (uncovTab[p1].get(v1) == 0) | |
236 | + continue; | |
220 | 237 | for (int p2 = p1 + 1; p2 < numOfParameters - 1; p2++) |
221 | 238 | for (byte v2 = 0; v2 < this.parametermodel.range[p2]; v2++) { |
222 | - if (uncovTab[p2].get(v2) == 0) continue; | |
223 | - for (int p3 = p2 + 1; p3 < numOfParameters; p3++) | |
239 | + if (uncovTab[p2].get(v2) == 0) | |
240 | + continue; | |
241 | + for (int p3 = p2 + 1; p3 < numOfParameters; p3++) | |
224 | 242 | for (byte v3 = 0; v3 < this.parametermodel.range[p3]; v3++) { |
225 | - if (tab.get(p0, v0, p1, v1, p2, v2, p3, v3) == false) { | |
243 | + if (tab.get(p0, v0, p1, v1, p2, v2, p3, | |
244 | + v3) == false) { | |
226 | 245 | tmp.set(p0, v0); |
227 | 246 | tmp.set(p1, v1); |
228 | 247 | tmp.set(p2, v2); |
229 | 248 | tmp.set(p3, v3); |
230 | 249 | return; |
231 | 250 | } |
232 | - } | |
251 | + } | |
233 | 252 | } |
234 | 253 | } |
235 | 254 | } |
236 | 255 | } |
237 | - | |
256 | + | |
238 | 257 | // 2.20 |
239 | 258 | // return true if tuples from at least one group are added. |
240 | - private boolean addGroupedTuples(Testcase tmp, List<List<Testcase>> tupleSequenceList) { | |
259 | + private boolean addGroupedTuples(Testcase tmp, | |
260 | + List<List<Testcase>> tupleSequenceList) { | |
241 | 261 | boolean isGroupAdded = false; |
242 | 262 | for (List<Testcase> TupleSequence : tupleSequenceList) { |
243 | 263 | for (int i = 0; i < TupleSequence.size(); i++) { |
@@ -248,25 +268,26 @@ class Generator4 extends Generator { | ||
248 | 268 | break; |
249 | 269 | } |
250 | 270 | } |
251 | - } | |
271 | + } | |
252 | 272 | return isGroupAdded; |
253 | 273 | } |
254 | 274 | |
255 | - private Testcase generateTempTest(Testcase seedrow, QuadTable tab, ArrayList<Integer>[] uncovTab) { | |
256 | - | |
275 | + private Testcase generateTempTest(Testcase seedrow, QuadTable tab, | |
276 | + ArrayList<Integer>[] uncovTab) { | |
277 | + | |
257 | 278 | // tmpをコピー |
258 | 279 | Testcase tmp = seedrow.makeClone(); |
259 | - | |
280 | + | |
260 | 281 | // TODO ランダムな因子列を生成 |
261 | 282 | int[] parametersequence = new int[parametermodel.size]; |
262 | - for (int i = 0; i < parametermodel.size; i++) | |
283 | + for (int i = 0; i < parametermodel.size; i++) | |
263 | 284 | parametersequence[i] = i; |
264 | 285 | // シャッフル |
265 | 286 | for (int i = 1; i < parametermodel.size; i++) { |
266 | 287 | int dst = this.rnd.nextInt(i + 1); |
267 | 288 | int tmppara = parametersequence[i]; |
268 | - parametersequence[i] = parametersequence[dst]; | |
269 | - parametersequence[dst] = tmppara; | |
289 | + parametersequence[i] = parametersequence[dst]; | |
290 | + parametersequence[dst] = tmppara; | |
270 | 291 | } |
271 | 292 | |
272 | 293 | // 各因子について |
@@ -288,17 +309,18 @@ class Generator4 extends Generator { | ||
288 | 309 | } |
289 | 310 | } |
290 | 311 | if (bestValue == -1) { |
291 | - Error.printError("seedに制約違反の行があります"); | |
312 | + Error.printError(Main.language == Main.Language.JP ? "seedに制約違反の行があります" | |
313 | + : "Some seeding row violates the constraints."); | |
292 | 314 | return null; |
293 | 315 | } |
294 | 316 | if (newlyCoveredTuples == 0) { |
295 | 317 | // TODO カバー数 0 なら,期待されるペア数を数え,最大のものを選択 |
296 | 318 | // TODO 期待するペア数には,絶対にむりなものもある(すでに値が決まっている因子とのペア) |
297 | 319 | bestValue = -1; |
298 | - int possibleTuples = -1; | |
320 | + int possibleTuples = -1; | |
299 | 321 | // for tie breaking |
300 | - List<Byte>candidateValues = new ArrayList<Byte>(); | |
301 | - | |
322 | + List<Byte> candidateValues = new ArrayList<Byte>(); | |
323 | + | |
302 | 324 | for (byte v = 0; v < this.parametermodel.range[p]; v++) { |
303 | 325 | tmp.set(p, v); |
304 | 326 | if (constrainthandler.isPossible(tmp)) { |
@@ -308,19 +330,20 @@ class Generator4 extends Generator { | ||
308 | 330 | possibleTuples = newtuples; |
309 | 331 | } |
310 | 332 | // for tie breaking |
311 | - if (newtuples == 0 && possibleTuples == 0) | |
333 | + if (newtuples == 0 && possibleTuples == 0) | |
312 | 334 | candidateValues.add(v); |
313 | 335 | } |
314 | 336 | } |
315 | 337 | // どれを選んでも同じなら,ランダムに選ぶ |
316 | 338 | // for tie breaking |
317 | - if (possibleTuples == 0) | |
318 | - bestValue = candidateValues.get(this.rnd.nextInt(candidateValues.size())); | |
339 | + if (possibleTuples == 0) | |
340 | + bestValue = candidateValues.get(this.rnd | |
341 | + .nextInt(candidateValues.size())); | |
319 | 342 | } |
320 | 343 | tmp.set(p, bestValue); |
321 | 344 | } |
322 | 345 | } |
323 | - | |
346 | + | |
324 | 347 | // 新カバーが0ということもある |
325 | 348 | return tmp; |
326 | 349 | } |
@@ -330,9 +353,13 @@ class Generator4 extends Generator { | ||
330 | 353 | for (int p1 = 0; p1 < numOfParameters - 2; p1++) { |
331 | 354 | for (int p2 = p1 + 1; p2 < numOfParameters - 1; p2++) { |
332 | 355 | for (int p3 = p2 + 1; p3 < numOfParameters; p3++) { |
333 | - if (p == p1 || p == p2 || p == p3) continue; | |
334 | - if (test.get(p1) < 0 || test.get(p2) < 0 || test.get(p3) < 0) continue; | |
335 | - if (tab.get(p, test.get(p), p1, test.get(p1), p2, test.get(p2), p3, test.get(p3)) == false) { | |
356 | + if (p == p1 || p == p2 || p == p3) | |
357 | + continue; | |
358 | + if (test.get(p1) < 0 || test.get(p2) < 0 | |
359 | + || test.get(p3) < 0) | |
360 | + continue; | |
361 | + if (tab.get(p, test.get(p), p1, test.get(p1), p2, | |
362 | + test.get(p2), p3, test.get(p3)) == false) { | |
336 | 363 | numOfNewlyCoveredTuples++; |
337 | 364 | } |
338 | 365 | } |
@@ -340,8 +367,7 @@ class Generator4 extends Generator { | ||
340 | 367 | } |
341 | 368 | return numOfNewlyCoveredTuples; |
342 | 369 | } |
343 | - | |
344 | - | |
370 | + | |
345 | 371 | // 2.20 |
346 | 372 | // copy from finalize.... |
347 | 373 | private int computeNewlyCoveredTuples(QuadTable tab, Testcase test) { |
@@ -350,7 +376,8 @@ class Generator4 extends Generator { | ||
350 | 376 | for (int p1 = p0 + 1; p1 < numOfParameters - 2; p1++) { |
351 | 377 | for (int p2 = p1 + 1; p2 < numOfParameters - 1; p2++) { |
352 | 378 | for (int p3 = p2 + 1; p3 < numOfParameters; p3++) { |
353 | - if (tab.get(p0, test.get(p0), p1, test.get(p1), p2, test.get(p2), p3, test.get(p3)) == false) { | |
379 | + if (tab.get(p0, test.get(p0), p1, test.get(p1), p2, | |
380 | + test.get(p2), p3, test.get(p3)) == false) { | |
354 | 381 | numOfNewlyCoveredTuples++; |
355 | 382 | } |
356 | 383 | } |
@@ -361,11 +388,10 @@ class Generator4 extends Generator { | ||
361 | 388 | } |
362 | 389 | } |
363 | 390 | |
364 | - | |
365 | 391 | class QuadTable extends TupleTable { |
366 | 392 | QuadList[][][][] table; |
367 | 393 | ParameterModel parametermodel; |
368 | - | |
394 | + | |
369 | 395 | QuadTable(ParameterModel parametermodel) { |
370 | 396 | this.parametermodel = parametermodel; |
371 | 397 | int n = parametermodel.size; |
@@ -375,16 +401,20 @@ class QuadTable extends TupleTable { | ||
375 | 401 | for (int p2 = p1 + 1; p2 < n - 1; p2++) { |
376 | 402 | for (int p3 = p2 + 1; p3 < n; p3++) { |
377 | 403 | assert (p0 < p1 && p1 < p2 && p2 < p3); |
378 | - table[p0][p1][p2][p3] = new QuadList(parametermodel.range[p0], | |
379 | - parametermodel.range[p1], parametermodel.range[p2], parametermodel.range[p3]); | |
404 | + table[p0][p1][p2][p3] = new QuadList( | |
405 | + parametermodel.range[p0], | |
406 | + parametermodel.range[p1], | |
407 | + parametermodel.range[p2], | |
408 | + parametermodel.range[p3]); | |
380 | 409 | } |
381 | 410 | } |
382 | 411 | } |
383 | 412 | } |
384 | 413 | } |
385 | - | |
414 | + | |
386 | 415 | // requires p1 != p2 != p3 != p4 |
387 | - boolean get(int p1, byte v1, int p2, byte v2, int p3, byte v3, int p4, byte v4) { | |
416 | + boolean get(int p1, byte v1, int p2, byte v2, int p3, byte v3, int p4, | |
417 | + byte v4) { | |
388 | 418 | // pairの場合にも反映? |
389 | 419 | // 因子の昇順にソート |
390 | 420 | ParameterValuePair[] pv = new ParameterValuePair[4]; |
@@ -393,24 +423,23 @@ class QuadTable extends TupleTable { | ||
393 | 423 | pv[2] = new ParameterValuePair(p3, v3); |
394 | 424 | pv[3] = new ParameterValuePair(p4, v4); |
395 | 425 | Arrays.sort(pv, new ParameterValuePairComparator()); |
396 | - | |
426 | + | |
397 | 427 | return this.table[pv[0].p][pv[1].p][pv[2].p][pv[3].p].list[getOffset(pv)]; |
398 | 428 | } |
399 | 429 | |
400 | 430 | // 現れない場合.すでにカバーした場合 |
401 | 431 | // requires p1 != p2 != p3 != p4 |
402 | - void set(int p1, byte v1, int p2, byte v2, int p3, byte v3, int p4, byte v4) { | |
432 | + void set(int p1, byte v1, int p2, byte v2, int p3, byte v3, int p4, byte v4) { | |
403 | 433 | ParameterValuePair[] pv = new ParameterValuePair[4]; |
404 | 434 | pv[0] = new ParameterValuePair(p1, v1); |
405 | 435 | pv[1] = new ParameterValuePair(p2, v2); |
406 | 436 | pv[2] = new ParameterValuePair(p3, v3); |
407 | 437 | pv[3] = new ParameterValuePair(p4, v4); |
408 | 438 | Arrays.sort(pv, new ParameterValuePairComparator()); |
409 | - | |
439 | + | |
410 | 440 | this.table[pv[0].p][pv[1].p][pv[2].p][pv[3].p].list[getOffset(pv)] = true; |
411 | 441 | } |
412 | - | |
413 | - | |
442 | + | |
414 | 443 | private int getOffset(ParameterValuePair[] pv) { |
415 | 444 | int offset = pv[0].v; |
416 | 445 | for (int i = 1; i < pv.length; i++) { |
@@ -424,9 +453,9 @@ class QuadTable extends TupleTable { | ||
424 | 453 | } |
425 | 454 | } |
426 | 455 | |
427 | - | |
428 | 456 | class QuadList { |
429 | 457 | boolean[] list; |
458 | + | |
430 | 459 | QuadList(byte range1, byte range2, byte range3, byte range4) { |
431 | 460 | this.list = new boolean[range1 * range2 * range3 * range4]; |
432 | 461 | } |
@@ -16,7 +16,7 @@ class Generator5 extends Generator { | ||
16 | 16 | List<Testcase> generate() throws OutOfMaxNumOfTestcasesException { |
17 | 17 | |
18 | 18 | List<Testcase> res = new ArrayList<Testcase>(); |
19 | - //TODO: テスト数の下限見積もり if > 上限 then エラー | |
19 | + // TODO: テスト数の下限見積もり if > 上限 then エラー | |
20 | 20 | QuintTable tab = new QuintTable(parametermodel); |
21 | 21 | |
22 | 22 | // group毎,tuple列の作成 |
@@ -32,20 +32,20 @@ class Generator5 extends Generator { | ||
32 | 32 | int seedrownum = 0; |
33 | 33 | while (numOfUncoveredTuples > 0 || hasTuplesToCover(tupleSequenceList)) { |
34 | 34 | // testcase 1個生成 |
35 | - ResultOfGenerateOneTest newresult | |
36 | - = generateOneTest(tab, seedrownum, uncovTab, tupleSequenceList); | |
35 | + ResultOfGenerateOneTest newresult = generateOneTest(tab, | |
36 | + seedrownum, uncovTab, tupleSequenceList); | |
37 | 37 | |
38 | 38 | res.add(newresult.test); |
39 | - | |
40 | - if (res.size() > MaxNumOfTestcases) | |
39 | + | |
40 | + if (res.size() > MaxNumOfTestcases) | |
41 | 41 | throw new OutOfMaxNumOfTestcasesException(); |
42 | - | |
42 | + | |
43 | 43 | numOfUncoveredTuples -= newresult.numOfCoveredTuples; |
44 | 44 | seedrownum = newresult.nextSeedRow; |
45 | 45 | } |
46 | 46 | return res; |
47 | 47 | } |
48 | - | |
48 | + | |
49 | 49 | private int checkAllTuples(QuintTable tab) { |
50 | 50 | // strength = 5 |
51 | 51 | int numOfTuples = 0; |
@@ -60,7 +60,8 @@ class Generator5 extends Generator { | ||
60 | 60 | for (byte v3 = 0; v3 < parametermodel.range[p3]; v3++) { |
61 | 61 | for (byte v4 = 0; v4 < parametermodel.range[p4]; v4++) { |
62 | 62 | // tupleの生成 |
63 | - Testcase tuple = new Testcase(numOfParameters); | |
63 | + Testcase tuple = new Testcase( | |
64 | + numOfParameters); | |
64 | 65 | tuple.quantify(); |
65 | 66 | tuple.set(p0, v0); |
66 | 67 | tuple.set(p1, v1); |
@@ -69,8 +70,10 @@ class Generator5 extends Generator { | ||
69 | 70 | tuple.set(p4, v4); |
70 | 71 | // tupleのチェック |
71 | 72 | // 禁則違反ならset |
72 | - if (constrainthandler.isPossible(tuple) == false) { | |
73 | - tab.set(p0, v0, p1, v1, p2, v2, p3, v3, p4, v4); | |
73 | + if (constrainthandler | |
74 | + .isPossible(tuple) == false) { | |
75 | + tab.set(p0, v0, p1, v1, p2, | |
76 | + v2, p3, v3, p4, v4); | |
74 | 77 | } else |
75 | 78 | numOfTuples++; |
76 | 79 | } |
@@ -86,7 +89,8 @@ class Generator5 extends Generator { | ||
86 | 89 | return numOfTuples; |
87 | 90 | } |
88 | 91 | |
89 | - private void initializeUncovTab(ArrayList<Integer>[] uncovTab, QuintTable tab) { | |
92 | + private void initializeUncovTab(ArrayList<Integer>[] uncovTab, | |
93 | + QuintTable tab) { | |
90 | 94 | assert (parametermodel.size == uncovTab.length); |
91 | 95 | // uncovTabの計算. strength = 5 の場合 |
92 | 96 | for (int p = 0; p < parametermodel.size; p++) { |
@@ -104,7 +108,8 @@ class Generator5 extends Generator { | ||
104 | 108 | for (byte v2 = 0; v2 < parametermodel.range[p2]; v2++) { |
105 | 109 | for (byte v3 = 0; v3 < parametermodel.range[p3]; v3++) { |
106 | 110 | for (byte v4 = 0; v4 < parametermodel.range[p4]; v4++) { |
107 | - if (tab.get(p, v, p1, v1, p2, v2, p3, v3, p4, v4) == false) | |
111 | + if (tab.get(p, v, p1, v1, p2, | |
112 | + v2, p3, v3, p4, v4) == false) | |
108 | 113 | sum++; |
109 | 114 | } |
110 | 115 | } |
@@ -119,92 +124,104 @@ class Generator5 extends Generator { | ||
119 | 124 | } |
120 | 125 | } |
121 | 126 | } |
122 | - | |
123 | - private ResultOfGenerateOneTest generateOneTest(QuintTable tab, int seedrownum, ArrayList<Integer>[] uncovTab, List<List<Testcase>> tupleSequenceList) { | |
127 | + | |
128 | + private ResultOfGenerateOneTest generateOneTest(QuintTable tab, | |
129 | + int seedrownum, ArrayList<Integer>[] uncovTab, | |
130 | + List<List<Testcase>> tupleSequenceList) { | |
124 | 131 | // 空のテストケースを1つつくる |
125 | 132 | Testcase tmp = new Testcase(parametermodel.size); |
126 | 133 | tmp.quantify(); |
127 | - | |
134 | + | |
128 | 135 | boolean isSeedUsed = false; |
129 | - | |
136 | + | |
130 | 137 | // seedのコピー 制約を満たさなかったらエラー |
131 | - if (seed.size() > 0 && seedrownum < seed.size() ) { | |
138 | + if (seed.size() > 0 && seedrownum < seed.size()) { | |
132 | 139 | isSeedUsed = true; |
133 | - Testcase seedrow = seed.get(seedrownum); | |
140 | + Testcase seedrow = seed.get(seedrownum); | |
134 | 141 | for (int i = 0; i < parametermodel.size; i++) { |
135 | 142 | tmp.set(i, seedrow.get(i)); |
136 | 143 | } |
137 | 144 | } |
138 | 145 | if (constrainthandler.isPossible(tmp) == false) { |
139 | - Error.printError("seedの" + (seedrownum + 1) + "行目が制約違反です"); | |
146 | + Error.printError(Main.language == Main.Language.JP ? "seedの" | |
147 | + + (seedrownum + 1) + "行目が制約違反です" : "The" + (seedrownum + 1) | |
148 | + + "th seeding row violates the constraints."); | |
149 | + | |
140 | 150 | return null; |
141 | 151 | } |
142 | - | |
152 | + | |
143 | 153 | // tmpにグループを追加 |
144 | 154 | // 2.20 |
145 | 155 | boolean isGroupUsed = addGroupedTuples(tmp, tupleSequenceList); |
146 | - | |
156 | + | |
147 | 157 | // TODO 繰り返させる |
148 | 158 | // generateTempTest では tabを更新しない |
149 | 159 | Testcase temptest = generateTempTest(tmp, tab, uncovTab); |
150 | 160 | // 2.20 |
151 | 161 | // 0カバーの場合 |
152 | - if (isSeedUsed == false && isGroupUsed == false && computeNewlyCoveredTuples(tab, temptest) == 0) { | |
162 | + if (isSeedUsed == false && isGroupUsed == false | |
163 | + && computeNewlyCoveredTuples(tab, temptest) == 0) { | |
153 | 164 | addUncoveredTuple(tmp, tab, uncovTab); |
154 | 165 | temptest = generateTempTest(tmp, tab, uncovTab); |
155 | 166 | } |
156 | - | |
167 | + | |
157 | 168 | // カバーしたペアーを実際にuncovTabに反映 |
158 | 169 | // finalizePairTableより前でないとだめ |
159 | 170 | finallizeUncoverTable(uncovTab, tab, temptest); |
160 | 171 | |
161 | 172 | // カバーしたペアーを実際にtabに反映 |
162 | 173 | int newtuples = finalizeTupleTable(tab, temptest); |
163 | - | |
174 | + | |
164 | 175 | // 返り値の設定 |
165 | 176 | ResultOfGenerateOneTest res = new ResultOfGenerateOneTest(); |
166 | 177 | res.test = temptest; |
167 | 178 | res.numOfCoveredTuples = newtuples; |
168 | 179 | if (isSeedUsed) { |
169 | 180 | res.nextSeedRow = seedrownum + 1; |
170 | - } else | |
181 | + } else | |
171 | 182 | res.nextSeedRow = seedrownum; |
172 | 183 | return res; |
173 | 184 | } |
174 | - | |
185 | + | |
175 | 186 | private void finallizeUncoverTable(ArrayList<Integer>[] uncovTab, |
176 | 187 | QuintTable tab, Testcase temptest) { |
177 | 188 | for (int p = 0; p < this.parametermodel.size; p++) { |
178 | 189 | int numCovered = 0; |
179 | 190 | byte v = temptest.get(p); |
180 | - if (v < 0) continue; | |
181 | - | |
191 | + if (v < 0) | |
192 | + continue; | |
193 | + | |
182 | 194 | for (int p1 = 0; p1 < this.parametermodel.size - 3; p1++) { |
183 | 195 | for (int p2 = p1 + 1; p2 < this.parametermodel.size - 2; p2++) { |
184 | 196 | for (int p3 = p2 + 1; p3 < this.parametermodel.size - 1; p3++) { |
185 | 197 | for (int p4 = p3 + 1; p4 < this.parametermodel.size; p4++) { |
186 | - if (p == p1 || p == p2 || p == p3 || p == p4) continue; | |
198 | + if (p == p1 || p == p2 || p == p3 || p == p4) | |
199 | + continue; | |
187 | 200 | byte v1 = temptest.get(p1); |
188 | - if (v1 < 0) continue; | |
201 | + if (v1 < 0) | |
202 | + continue; | |
189 | 203 | byte v2 = temptest.get(p2); |
190 | - if (v2 < 0) continue; | |
204 | + if (v2 < 0) | |
205 | + continue; | |
191 | 206 | byte v3 = temptest.get(p3); |
192 | - if (v3 < 0) continue; | |
207 | + if (v3 < 0) | |
208 | + continue; | |
193 | 209 | byte v4 = temptest.get(p4); |
194 | - if (v4 < 0) continue; | |
210 | + if (v4 < 0) | |
211 | + continue; | |
195 | 212 | if (tab.get(p, v, p1, v1, p2, v2, p3, v3, p4, v4) == false) |
196 | 213 | numCovered++; |
197 | 214 | } |
198 | 215 | } |
199 | 216 | } |
200 | 217 | } |
201 | - | |
218 | + | |
202 | 219 | int numUncovered = uncovTab[p].get(v); |
203 | 220 | uncovTab[p].set(v, numUncovered - numCovered); |
204 | 221 | } |
205 | - | |
222 | + | |
206 | 223 | } |
207 | - | |
224 | + | |
208 | 225 | private int finalizeTupleTable(QuintTable tab, Testcase test) { |
209 | 226 | int numOfNewlyCoveredTuples = 0; |
210 | 227 | for (int p0 = 0; p0 < numOfParameters - 4; p0++) { |
@@ -212,8 +229,12 @@ class Generator5 extends Generator { | ||
212 | 229 | for (int p2 = p1 + 1; p2 < numOfParameters - 2; p2++) { |
213 | 230 | for (int p3 = p2 + 1; p3 < numOfParameters - 1; p3++) { |
214 | 231 | for (int p4 = p3 + 1; p4 < numOfParameters; p4++) { |
215 | - if (tab.get(p0, test.get(p0), p1, test.get(p1), p2, test.get(p2), p3, test.get(p3), p4, test.get(p4)) == false) { | |
216 | - tab.set(p0, test.get(p0), p1, test.get(p1), p2, test.get(p2), p3, test.get(p3), p4, test.get(p4)); | |
232 | + if (tab.get(p0, test.get(p0), p1, test.get(p1), p2, | |
233 | + test.get(p2), p3, test.get(p3), p4, | |
234 | + test.get(p4)) == false) { | |
235 | + tab.set(p0, test.get(p0), p1, test.get(p1), p2, | |
236 | + test.get(p2), p3, test.get(p3), p4, | |
237 | + test.get(p4)); | |
217 | 238 | numOfNewlyCoveredTuples++; |
218 | 239 | } |
219 | 240 | } |
@@ -223,25 +244,31 @@ class Generator5 extends Generator { | ||
223 | 244 | } |
224 | 245 | return numOfNewlyCoveredTuples; |
225 | 246 | } |
226 | - | |
247 | + | |
227 | 248 | // 2.20 |
228 | 249 | // 前の位置をおぼえておく |
229 | - private void addUncoveredTuple(Testcase tmp, QuintTable tab, ArrayList<Integer>[] uncovTab) { | |
230 | - for (int p0 = 0; p0 < numOfParameters - 4; p0++) | |
250 | + private void addUncoveredTuple(Testcase tmp, QuintTable tab, | |
251 | + ArrayList<Integer>[] uncovTab) { | |
252 | + for (int p0 = 0; p0 < numOfParameters - 4; p0++) | |
231 | 253 | for (byte v0 = 0; v0 < this.parametermodel.range[p0]; v0++) { |
232 | - if (uncovTab[p0].get(v0) == 0) continue; | |
233 | - for (int p1 = p0 + 1; p1 < numOfParameters - 3; p1++) | |
254 | + if (uncovTab[p0].get(v0) == 0) | |
255 | + continue; | |
256 | + for (int p1 = p0 + 1; p1 < numOfParameters - 3; p1++) | |
234 | 257 | for (byte v1 = 0; v1 < this.parametermodel.range[p1]; v1++) { |
235 | - if (uncovTab[p1].get(v1) == 0) continue; | |
258 | + if (uncovTab[p1].get(v1) == 0) | |
259 | + continue; | |
236 | 260 | for (int p2 = p1 + 1; p2 < numOfParameters - 2; p2++) |
237 | 261 | for (byte v2 = 0; v2 < this.parametermodel.range[p2]; v2++) { |
238 | - if (uncovTab[p2].get(v2) == 0) continue; | |
262 | + if (uncovTab[p2].get(v2) == 0) | |
263 | + continue; | |
239 | 264 | for (int p3 = p2 + 1; p3 < numOfParameters - 1; p3++) |
240 | 265 | for (byte v3 = 0; v3 < this.parametermodel.range[p3]; v3++) { |
241 | - if (uncovTab[p3].get(v3) == 0) continue; | |
242 | - for (int p4 = p3 + 1; p4 < numOfParameters; p4++) | |
266 | + if (uncovTab[p3].get(v3) == 0) | |
267 | + continue; | |
268 | + for (int p4 = p3 + 1; p4 < numOfParameters; p4++) | |
243 | 269 | for (byte v4 = 0; v4 < this.parametermodel.range[p4]; v4++) { |
244 | - if (tab.get(p0, v0, p1, v1, p2, v2, p3, v3, p4, v4) == false) { | |
270 | + if (tab.get(p0, v0, p1, v1, p2, | |
271 | + v2, p3, v3, p4, v4) == false) { | |
245 | 272 | tmp.set(p0, v0); |
246 | 273 | tmp.set(p1, v1); |
247 | 274 | tmp.set(p2, v2); |
@@ -255,10 +282,11 @@ class Generator5 extends Generator { | ||
255 | 282 | } |
256 | 283 | } |
257 | 284 | } |
258 | - | |
285 | + | |
259 | 286 | // 2.20 |
260 | 287 | // return true if tuples from at least one group are added. |
261 | - private boolean addGroupedTuples(Testcase tmp, List<List<Testcase>> tupleSequenceList) { | |
288 | + private boolean addGroupedTuples(Testcase tmp, | |
289 | + List<List<Testcase>> tupleSequenceList) { | |
262 | 290 | boolean isGroupAdded = false; |
263 | 291 | for (List<Testcase> TupleSequence : tupleSequenceList) { |
264 | 292 | for (int i = 0; i < TupleSequence.size(); i++) { |
@@ -269,27 +297,28 @@ class Generator5 extends Generator { | ||
269 | 297 | break; |
270 | 298 | } |
271 | 299 | } |
272 | - } | |
300 | + } | |
273 | 301 | return isGroupAdded; |
274 | 302 | } |
275 | 303 | |
276 | - private Testcase generateTempTest(Testcase seedrow, QuintTable tab, ArrayList<Integer>[] uncovTab) { | |
277 | - | |
304 | + private Testcase generateTempTest(Testcase seedrow, QuintTable tab, | |
305 | + ArrayList<Integer>[] uncovTab) { | |
306 | + | |
278 | 307 | // tmpをコピー |
279 | 308 | Testcase tmp = seedrow.makeClone(); |
280 | - | |
309 | + | |
281 | 310 | // TODO ランダムな因子列を生成 |
282 | 311 | int[] parametersequence = new int[parametermodel.size]; |
283 | - for (int i = 0; i < parametermodel.size; i++) | |
312 | + for (int i = 0; i < parametermodel.size; i++) | |
284 | 313 | parametersequence[i] = i; |
285 | 314 | // シャッフル |
286 | 315 | for (int i = 1; i < parametermodel.size; i++) { |
287 | 316 | int dst = this.rnd.nextInt(i + 1); |
288 | 317 | int tmppara = parametersequence[i]; |
289 | - parametersequence[i] = parametersequence[dst]; | |
290 | - parametersequence[dst] = tmppara; | |
318 | + parametersequence[i] = parametersequence[dst]; | |
319 | + parametersequence[dst] = tmppara; | |
291 | 320 | } |
292 | - | |
321 | + | |
293 | 322 | // 各因子について |
294 | 323 | for (int i = 0; i < parametermodel.size; i++) { |
295 | 324 | int p = parametersequence[i]; |
@@ -309,17 +338,18 @@ class Generator5 extends Generator { | ||
309 | 338 | } |
310 | 339 | } |
311 | 340 | if (bestValue == -1) { |
312 | - Error.printError("seedに制約違反の行があります"); | |
341 | + Error.printError(Main.language == Main.Language.JP ? "seedに制約違反の行があります" | |
342 | + : "Some seeding row violates the constraints."); | |
313 | 343 | return null; |
314 | 344 | } |
315 | 345 | if (newlyCoveredTuples == 0) { |
316 | 346 | // TODO カバー数 0 なら,期待されるペア数を数え,最大のものを選択 |
317 | 347 | // TODO 期待するペア数には,絶対にむりなものもある(すでに値が決まっている因子とのペア) |
318 | 348 | bestValue = -1; |
319 | - int possibleTuples = -1; | |
349 | + int possibleTuples = -1; | |
320 | 350 | // for tie breaking |
321 | - List<Byte>candidateValues = new ArrayList<Byte>(); | |
322 | - | |
351 | + List<Byte> candidateValues = new ArrayList<Byte>(); | |
352 | + | |
323 | 353 | for (byte v = 0; v < this.parametermodel.range[p]; v++) { |
324 | 354 | tmp.set(p, v); |
325 | 355 | if (constrainthandler.isPossible(tmp)) { |
@@ -329,19 +359,20 @@ class Generator5 extends Generator { | ||
329 | 359 | possibleTuples = newtuples; |
330 | 360 | } |
331 | 361 | // for tie breaking |
332 | - if (newtuples == 0 && possibleTuples == 0) | |
362 | + if (newtuples == 0 && possibleTuples == 0) | |
333 | 363 | candidateValues.add(v); |
334 | 364 | } |
335 | 365 | } |
336 | 366 | // どれを選んでも同じなら,ランダムに選ぶ |
337 | 367 | // for tie breaking |
338 | - if (possibleTuples == 0) | |
339 | - bestValue = candidateValues.get(this.rnd.nextInt(candidateValues.size())); | |
368 | + if (possibleTuples == 0) | |
369 | + bestValue = candidateValues.get(this.rnd | |
370 | + .nextInt(candidateValues.size())); | |
340 | 371 | } |
341 | 372 | tmp.set(p, bestValue); |
342 | 373 | } |
343 | 374 | } |
344 | - | |
375 | + | |
345 | 376 | // 新カバーが0ということもある |
346 | 377 | return tmp; |
347 | 378 | } |
@@ -352,9 +383,14 @@ class Generator5 extends Generator { | ||
352 | 383 | for (int p2 = p1 + 1; p2 < numOfParameters - 2; p2++) { |
353 | 384 | for (int p3 = p2 + 1; p3 < numOfParameters - 1; p3++) { |
354 | 385 | for (int p4 = p3 + 1; p4 < numOfParameters; p4++) { |
355 | - if (p == p1 || p == p2 || p == p3 || p == p4) continue; | |
356 | - if (test.get(p1) < 0 || test.get(p2) < 0 || test.get(p3) < 0 || test.get(p4) < 0) continue; | |
357 | - if (tab.get(p, test.get(p), p1, test.get(p1), p2, test.get(p2), p3, test.get(p3), p4, test.get(p4)) == false) { | |
386 | + if (p == p1 || p == p2 || p == p3 || p == p4) | |
387 | + continue; | |
388 | + if (test.get(p1) < 0 || test.get(p2) < 0 | |
389 | + || test.get(p3) < 0 || test.get(p4) < 0) | |
390 | + continue; | |
391 | + if (tab.get(p, test.get(p), p1, test.get(p1), p2, | |
392 | + test.get(p2), p3, test.get(p3), p4, | |
393 | + test.get(p4)) == false) { | |
358 | 394 | numOfNewlyCoveredTuples++; |
359 | 395 | } |
360 | 396 | } |
@@ -363,7 +399,7 @@ class Generator5 extends Generator { | ||
363 | 399 | } |
364 | 400 | return numOfNewlyCoveredTuples; |
365 | 401 | } |
366 | - | |
402 | + | |
367 | 403 | // 2.20 |
368 | 404 | // copy from finalize.... |
369 | 405 | private int computeNewlyCoveredTuples(QuintTable tab, Testcase test) { |
@@ -373,7 +409,9 @@ class Generator5 extends Generator { | ||
373 | 409 | for (int p2 = p1 + 1; p2 < numOfParameters - 2; p2++) { |
374 | 410 | for (int p3 = p2 + 1; p3 < numOfParameters - 1; p3++) { |
375 | 411 | for (int p4 = p3 + 1; p4 < numOfParameters; p4++) { |
376 | - if (tab.get(p0, test.get(p0), p1, test.get(p1), p2, test.get(p2), p3, test.get(p3), p4, test.get(p4)) == false) { | |
412 | + if (tab.get(p0, test.get(p0), p1, test.get(p1), p2, | |
413 | + test.get(p2), p3, test.get(p3), p4, | |
414 | + test.get(p4)) == false) { | |
377 | 415 | numOfNewlyCoveredTuples++; |
378 | 416 | } |
379 | 417 | } |
@@ -385,11 +423,10 @@ class Generator5 extends Generator { | ||
385 | 423 | } |
386 | 424 | } |
387 | 425 | |
388 | - | |
389 | 426 | class QuintTable extends TupleTable { |
390 | 427 | QuintList[][][][][] table; |
391 | 428 | ParameterModel parametermodel; |
392 | - | |
429 | + | |
393 | 430 | QuintTable(ParameterModel parametermodel) { |
394 | 431 | this.parametermodel = parametermodel; |
395 | 432 | int n = parametermodel.size; |
@@ -400,10 +437,10 @@ class QuintTable extends TupleTable { | ||
400 | 437 | for (int p3 = p2 + 1; p3 < n - 1; p3++) { |
401 | 438 | for (int p4 = p3 + 1; p4 < n; p4++) { |
402 | 439 | assert (p0 < p1 && p1 < p2 && p2 < p3 && p3 < p4); |
403 | - table[p0][p1][p2][p3][p4] = | |
404 | - new QuintList(parametermodel.range[p0], | |
405 | - parametermodel.range[p1], | |
406 | - parametermodel.range[p2], | |
440 | + table[p0][p1][p2][p3][p4] = new QuintList( | |
441 | + parametermodel.range[p0], | |
442 | + parametermodel.range[p1], | |
443 | + parametermodel.range[p2], | |
407 | 444 | parametermodel.range[p3], |
408 | 445 | parametermodel.range[p4]); |
409 | 446 | } |
@@ -412,9 +449,10 @@ class QuintTable extends TupleTable { | ||
412 | 449 | } |
413 | 450 | } |
414 | 451 | } |
415 | - | |
452 | + | |
416 | 453 | // requires p1 != p2 != p3 != p4 |
417 | - boolean get(int p1, byte v1, int p2, byte v2, int p3, byte v3, int p4, byte v4, int p5, byte v5) { | |
454 | + boolean get(int p1, byte v1, int p2, byte v2, int p3, byte v3, int p4, | |
455 | + byte v4, int p5, byte v5) { | |
418 | 456 | // pairの場合にも反映? |
419 | 457 | // 因子の昇順にソート |
420 | 458 | ParameterValuePair[] pv = new ParameterValuePair[5]; |
@@ -424,13 +462,14 @@ class QuintTable extends TupleTable { | ||
424 | 462 | pv[3] = new ParameterValuePair(p4, v4); |
425 | 463 | pv[4] = new ParameterValuePair(p5, v5); |
426 | 464 | Arrays.sort(pv, new ParameterValuePairComparator()); |
427 | - | |
465 | + | |
428 | 466 | return this.table[pv[0].p][pv[1].p][pv[2].p][pv[3].p][pv[4].p].list[getOffset(pv)]; |
429 | 467 | } |
430 | 468 | |
431 | 469 | // 現れない場合.すでにカバーした場合 |
432 | 470 | // requires p1 != p2 != p3 != p4 |
433 | - void set(int p1, byte v1, int p2, byte v2, int p3, byte v3, int p4, byte v4, int p5, byte v5) { | |
471 | + void set(int p1, byte v1, int p2, byte v2, int p3, byte v3, int p4, | |
472 | + byte v4, int p5, byte v5) { | |
434 | 473 | ParameterValuePair[] pv = new ParameterValuePair[5]; |
435 | 474 | pv[0] = new ParameterValuePair(p1, v1); |
436 | 475 | pv[1] = new ParameterValuePair(p2, v2); |
@@ -438,11 +477,10 @@ class QuintTable extends TupleTable { | ||
438 | 477 | pv[3] = new ParameterValuePair(p4, v4); |
439 | 478 | pv[4] = new ParameterValuePair(p5, v5); |
440 | 479 | Arrays.sort(pv, new ParameterValuePairComparator()); |
441 | - | |
480 | + | |
442 | 481 | this.table[pv[0].p][pv[1].p][pv[2].p][pv[3].p][pv[4].p].list[getOffset(pv)] = true; |
443 | 482 | } |
444 | - | |
445 | - | |
483 | + | |
446 | 484 | private int getOffset(ParameterValuePair[] pv) { |
447 | 485 | int offset = pv[0].v; |
448 | 486 | for (int i = 1; i < pv.length; i++) { |
@@ -456,9 +494,9 @@ class QuintTable extends TupleTable { | ||
456 | 494 | } |
457 | 495 | } |
458 | 496 | |
459 | - | |
460 | 497 | class QuintList { |
461 | 498 | boolean[] list; |
499 | + | |
462 | 500 | QuintList(byte range1, byte range2, byte range3, byte range4, byte range5) { |
463 | 501 | this.list = new boolean[range1 * range2 * range3 * range4 * range5]; |
464 | 502 | } |
@@ -5,17 +5,18 @@ import java.util.List; | ||
5 | 5 | |
6 | 6 | class GeneratorAll { |
7 | 7 | |
8 | - static List<Testcase> generate(ParameterModel parameterModel, ConstraintHandler conhndl) throws OutOfMaxNumOfTestcasesException { | |
9 | - long numOfAllCombinations = 1; | |
8 | + static List<Testcase> generate(ParameterModel parameterModel, | |
9 | + ConstraintHandler conhndl) throws OutOfMaxNumOfTestcasesException { | |
10 | + long numOfAllCombinations = 1; | |
10 | 11 | for (int p = 0; p < parameterModel.size; p++) { |
11 | 12 | numOfAllCombinations *= parameterModel.range[p]; |
12 | 13 | } |
13 | - | |
14 | + | |
14 | 15 | List<Testcase> testSet = new ArrayList<Testcase>(); |
15 | 16 | Testcase tmptest = new Testcase(parameterModel.size); |
16 | 17 | if (conhndl.isPossible(tmptest)) |
17 | 18 | testSet.add(tmptest); |
18 | - | |
19 | + | |
19 | 20 | for (int i = 1; i < numOfAllCombinations; i++) { |
20 | 21 | tmptest = tmptest.makeClone(); |
21 | 22 | for (int p = 0; p < parameterModel.size; p++) { |
@@ -28,7 +29,7 @@ class GeneratorAll { | ||
28 | 29 | } |
29 | 30 | if (conhndl.isPossible(tmptest)) { |
30 | 31 | testSet.add(tmptest); |
31 | - if (testSet.size() > Generator.MaxNumOfTestcases) | |
32 | + if (testSet.size() > Generator.MaxNumOfTestcases) | |
32 | 33 | throw new OutOfMaxNumOfTestcasesException(); |
33 | 34 | } |
34 | 35 | } |
@@ -7,10 +7,10 @@ import java.util.Comparator; | ||
7 | 7 | import java.util.Set; |
8 | 8 | |
9 | 9 | class Group { |
10 | - int[] member; | |
10 | + int[] member; | |
11 | 11 | int size; |
12 | - | |
13 | - Group(Set<Integer> memberSet) { | |
12 | + | |
13 | + Group(Set<Integer> memberSet) { | |
14 | 14 | member = new int[memberSet.size()]; |
15 | 15 | int i = 0; |
16 | 16 | for (Integer p : memberSet) { |
@@ -20,7 +20,7 @@ class Group { | ||
20 | 20 | Arrays.sort(member); |
21 | 21 | size = member.length; |
22 | 22 | } |
23 | - | |
23 | + | |
24 | 24 | boolean equiv(Group g1) { |
25 | 25 | Group g0 = this; |
26 | 26 | if (g0.member.length != g1.member.length) |
@@ -37,7 +37,7 @@ class Group { | ||
37 | 37 | class GList extends ArrayList<Group> { |
38 | 38 | private static final long serialVersionUID = -6705998890411938435L; |
39 | 39 | |
40 | - //TODO | |
40 | + // TODO | |
41 | 41 | void sort() { |
42 | 42 | Collections.sort(this, new MyComparator()); |
43 | 43 | } |
@@ -49,21 +49,20 @@ class MyComparator implements Comparator<Group> { | ||
49 | 49 | Group g1 = (Group) arg1; |
50 | 50 | if (g0.size < g1.size) { |
51 | 51 | return 1; |
52 | - } | |
53 | - else if (g0.size > g1.size) { | |
54 | - return -1; | |
52 | + } else if (g0.size > g1.size) { | |
53 | + return -1; | |
55 | 54 | } |
56 | 55 | |
57 | 56 | // g0 と g1が同サイズ |
58 | 57 | for (int i = 0; i < g0.member.length; i++) { |
59 | 58 | if (g0.member[i] > g1.member[i]) |
60 | 59 | return 1; |
61 | - else if (g0.member[i] < g1.member[i]) | |
62 | - return -1; | |
60 | + else if (g0.member[i] < g1.member[i]) | |
61 | + return -1; | |
63 | 62 | } |
64 | - | |
63 | + | |
65 | 64 | return 0; // unreachable |
66 | - | |
65 | + | |
67 | 66 | } |
68 | - | |
67 | + | |
69 | 68 | } |
@@ -13,7 +13,7 @@ import java.util.TreeSet; | ||
13 | 13 | |
14 | 14 | public class Inputer { |
15 | 15 | |
16 | - // シードで指定された部分テストの列をかえす | |
16 | + // シードで指定された部分テストの列をかえす | |
17 | 17 | // filename がnullなら大きさ0の列を返す |
18 | 18 | static List<Testcase> readSeed(String filename, InputFileData inputfiledata) { |
19 | 19 | List<Testcase> seed = new ArrayList<Testcase>(); |
@@ -23,38 +23,33 @@ public class Inputer { | ||
23 | 23 | BufferedReader reader = openFile(filename); |
24 | 24 | List<String> row = parseCSVRow(reader); |
25 | 25 | |
26 | - //debug | |
26 | + // debug | |
27 | 27 | /* |
28 | - System.out.print("seed:"); | |
29 | - for (String str: row) { | |
30 | - System.out.print(str + "\t"); | |
31 | - } | |
32 | - System.out.println(); | |
33 | - */ | |
34 | - | |
28 | + * System.out.print("seed:"); for (String str: row) { | |
29 | + * System.out.print(str + "\t"); } System.out.println(); | |
30 | + */ | |
31 | + | |
35 | 32 | // seed file は空白 |
36 | 33 | if (row == null) |
37 | 34 | return seed; |
38 | 35 | // parameters |
39 | 36 | if (isParameterConsistent(row, inputfiledata) == false) { |
40 | - Error.printError("seedファイルの因子の記述に誤りがあります"); | |
37 | + Error.printError(Main.language == Main.Language.JP ? "seedファイルの因子の記述に誤りがあります" | |
38 | + : "There is an invalid parameter in the seeding file."); | |
41 | 39 | return null; |
42 | 40 | } |
43 | 41 | |
44 | 42 | while ((row = parseCSVRow(reader)) != null) { |
45 | 43 | // TODO debug |
46 | - //debug | |
44 | + // debug | |
47 | 45 | /* |
48 | - System.out.print("seed:"); | |
49 | - for (String str: row) { | |
50 | - System.out.print(str + "\t"); | |
51 | - } | |
52 | - System.out.println(); | |
53 | - */ | |
54 | - | |
46 | + * System.out.print("seed:"); for (String str: row) { | |
47 | + * System.out.print(str + "\t"); } System.out.println(); | |
48 | + */ | |
49 | + | |
55 | 50 | /* |
56 | - System.err.print(row.size() +": "); for (String str: row) { | |
57 | - System.err.print(str + ","); } System.err.println(); | |
51 | + * System.err.print(row.size() +": "); for (String str: row) { | |
52 | + * System.err.print(str + ","); } System.err.println(); | |
58 | 53 | */ |
59 | 54 | |
60 | 55 | /* |
@@ -62,50 +57,56 @@ public class Inputer { | ||
62 | 57 | * Error.printError("seedファイルの値の記述に誤りがあります"); return null; } |
63 | 58 | */ |
64 | 59 | |
65 | - | |
66 | 60 | // Testcase 生成と追加 |
67 | 61 | Testcase newtest = createTestcase(row, inputfiledata); |
68 | - | |
69 | - | |
62 | + | |
70 | 63 | if (newtest == null) { |
71 | - Error.printError("seedファイルの値の記述に誤りがあります"); | |
64 | + Error.printError(Main.language == Main.Language.JP ? "seedファイルの値の記述に誤りがあります" | |
65 | + : "There is an invalid parameter value in the seeding file."); | |
72 | 66 | return null; |
73 | 67 | } else { |
74 | 68 | seed.add(newtest); |
75 | 69 | // debug |
76 | 70 | /* |
77 | - newtest.print(); | |
78 | - */ | |
71 | + * newtest.print(); | |
72 | + */ | |
79 | 73 | } |
80 | 74 | } |
81 | 75 | try { |
82 | 76 | reader.close(); |
83 | 77 | } catch (IOException e) { |
84 | - Error.printError("seedファイルにアクセスできません"); | |
78 | + Error.printError(Main.language == Main.Language.JP ? "seedファイルにアクセスできません" | |
79 | + : "Cannot access the seeding file."); | |
85 | 80 | } |
86 | 81 | |
87 | 82 | return seed; |
88 | 83 | } |
89 | - | |
84 | + | |
90 | 85 | private static Testcase createTestcase(List<String> row, |
91 | 86 | InputFileData inputfiledata) { |
92 | 87 | // 値が正しいか? |
93 | 88 | Testcase newtest = new Testcase(inputfiledata.parameterList.size()); |
94 | 89 | int i = 0; |
95 | - for (i = 0; i < Math.min(row.size(), inputfiledata.parameterList.size()); i++) { | |
90 | + for (i = 0; i < Math | |
91 | + .min(row.size(), inputfiledata.parameterList.size()); i++) { | |
96 | 92 | String valuename = row.get(i); |
97 | 93 | if (valuename.equals("")) { |
98 | 94 | newtest.setWildCard(i); |
99 | 95 | continue; |
100 | 96 | } |
101 | 97 | try { |
102 | - newtest.set(i, (byte) inputfiledata.parameterList.get(i).getID(valuename)); | |
98 | + // 複数同じ値があれば,最初のものとみなす | |
99 | + // newtest.set(i, (byte) | |
100 | + // inputfiledata.parameterList.get(i).getID(valuename)); | |
101 | + newtest.set(i, | |
102 | + inputfiledata.parameterList.get(i).getID(valuename) | |
103 | + .get(0).byteValue()); | |
103 | 104 | } catch (NoValueNameException e) { |
104 | 105 | return null; |
105 | 106 | } |
106 | 107 | } |
107 | 108 | // 行に全パラメータ分の値がなければ,空白を入れる |
108 | - for(; i < inputfiledata.parameterList.size(); i++) { | |
109 | + for (; i < inputfiledata.parameterList.size(); i++) { | |
109 | 110 | newtest.setWildCard(i); |
110 | 111 | } |
111 | 112 | return newtest; |
@@ -113,13 +114,13 @@ public class Inputer { | ||
113 | 114 | |
114 | 115 | private static boolean isParameterConsistent(List<String> row, |
115 | 116 | InputFileData inputfiledata) { |
116 | - // 因子数のチェック | |
117 | + // 因子数のチェック | |
117 | 118 | if (inputfiledata.parameterList.size() != row.size()) |
118 | 119 | return false; |
119 | - | |
120 | + | |
120 | 121 | for (int i = 0; i < row.size(); i++) { |
121 | 122 | try { |
122 | - if (inputfiledata.parameterList.getID(row.get(i)) != i) | |
123 | + if (inputfiledata.parameterList.getID(row.get(i)) != i) | |
123 | 124 | return false; |
124 | 125 | } catch (NoParameterNameException e) { |
125 | 126 | return false; |
@@ -136,9 +137,9 @@ public class Inputer { | ||
136 | 137 | line = reader.readLine(); |
137 | 138 | if (line == null) |
138 | 139 | break; |
139 | - | |
140 | - //TODO ,の前後の空白と#の前の空白をとって、,をセパレータに | |
141 | - // line = line.replaceAll("#", ",#,"); | |
140 | + | |
141 | + // TODO ,の前後の空白と#の前の空白をとって、,をセパレータに | |
142 | + // line = line.replaceAll("#", ",#,"); | |
142 | 143 | // #以降を消去 |
143 | 144 | line = line.replaceAll("#.*", ""); |
144 | 145 | // ,から始まる場合,行頭にスペースを入れる |
@@ -147,18 +148,18 @@ public class Inputer { | ||
147 | 148 | while (st.hasMoreTokens()) { |
148 | 149 | String token = st.nextToken(); |
149 | 150 | token = token.trim(); |
150 | -// if (token.equals("#")) | |
151 | -// break; | |
151 | + // if (token.equals("#")) | |
152 | + // break; | |
152 | 153 | token = token.trim(); |
153 | 154 | tokenList.add(token); |
154 | 155 | } |
155 | 156 | } catch (IOException e) { |
156 | - Error.printError("IO エラー"); | |
157 | + Error.printError("IO error"); | |
157 | 158 | return null; |
158 | 159 | } |
159 | 160 | // 空白だけ,コメントだけなら次の行をよむ |
160 | 161 | boolean isAllEmpty = true; |
161 | - for (String token: tokenList) { | |
162 | + for (String token : tokenList) { | |
162 | 163 | if (token.equals("") == false) { |
163 | 164 | isAllEmpty = false; |
164 | 165 | break; |
@@ -166,69 +167,60 @@ public class Inputer { | ||
166 | 167 | } |
167 | 168 | if (isAllEmpty) |
168 | 169 | tokenList.clear(); |
169 | - // if (tokenList.size() == 1) | |
170 | - // if (tokenList.get(0).equals("")) | |
171 | - // tokenList.remove(0); | |
170 | + // if (tokenList.size() == 1) | |
171 | + // if (tokenList.get(0).equals("")) | |
172 | + // tokenList.remove(0); | |
172 | 173 | |
173 | 174 | } |
174 | - | |
175 | + | |
175 | 176 | if (tokenList.size() == 0) |
176 | 177 | return null; |
177 | - else | |
178 | + else | |
178 | 179 | return tokenList; |
179 | 180 | } |
180 | 181 | |
182 | + static InputFileData readModel(String filename) { | |
181 | 183 | |
182 | - | |
183 | - static InputFileData readModel(String filename){ | |
184 | - | |
185 | 184 | BufferedReader reader = openFile(filename); |
186 | 185 | List<String> tokenList = makeTokenList(reader); |
187 | 186 | TokenHandler t = new TokenHandler(tokenList); |
188 | - | |
187 | + | |
189 | 188 | // 因子、値のよみこみ |
190 | 189 | PList parameterList = readParameter(t); |
191 | - | |
190 | + | |
192 | 191 | // テスト |
193 | 192 | /* |
194 | - for(Parameter p: parameterList) { | |
195 | - System.err.print(p.name + ": "); | |
196 | - for (String name : p.value_name) { | |
197 | - System.err.print(name + ", "); | |
198 | - } | |
199 | - System.err.println(); | |
200 | - } | |
201 | - */ | |
202 | - | |
193 | + * for(Parameter p: parameterList) { System.err.print(p.name + ": "); | |
194 | + * for (String name : p.value_name) { System.err.print(name + ", "); } | |
195 | + * System.err.println(); } | |
196 | + */ | |
197 | + | |
203 | 198 | // グループ |
204 | 199 | GList groupList = readGroup(t, parameterList); |
205 | 200 | |
206 | 201 | // テスト |
207 | - | |
202 | + | |
208 | 203 | /* |
209 | - for(Group g: groupList) { | |
210 | - for (int i = 0; i < g.size; i++) | |
211 | - System.out.print(g.member[i] + ", "); | |
212 | - System.out.println(); | |
213 | - } | |
214 | - */ | |
215 | - | |
216 | - | |
204 | + * for(Group g: groupList) { for (int i = 0; i < g.size; i++) | |
205 | + * System.out.print(g.member[i] + ", "); System.out.println(); } | |
206 | + */ | |
207 | + | |
217 | 208 | // 制約 |
218 | 209 | List<Node> constraintList = readConstraint(t, parameterList); |
219 | - | |
220 | - // close | |
210 | + | |
211 | + // close | |
221 | 212 | try { |
222 | 213 | reader.close(); |
223 | 214 | } catch (IOException e) { |
224 | - Error.printError("入力ファイルにアクセスできません"); | |
215 | + Error.printError(Main.language == Main.Language.JP ? "入力ファイルにアクセスできません" | |
216 | + : "Cannot access the input file"); | |
225 | 217 | } |
226 | 218 | return new InputFileData(parameterList, groupList, constraintList); |
227 | 219 | } |
228 | - | |
220 | + | |
229 | 221 | private static List<Node> readConstraint(TokenHandler t, PList parameterList) { |
230 | 222 | List<Node> constraintList = new ArrayList<Node>(); |
231 | - while (true){ | |
223 | + while (true) { | |
232 | 224 | if (t.peepToken() == null) { |
233 | 225 | break; |
234 | 226 | } |
@@ -238,13 +230,11 @@ public class Inputer { | ||
238 | 230 | return constraintList; |
239 | 231 | } |
240 | 232 | |
241 | - | |
242 | 233 | // グループの読み込み |
243 | 234 | private static GList readGroup(TokenHandler t, PList parameterList) { |
244 | 235 | GList groupList = new GList(); |
245 | - while (true){ | |
246 | - if (t.peepToken() == null || | |
247 | - t.peepToken().equals("(")) { | |
236 | + while (true) { | |
237 | + if (t.peepToken() == null || t.peepToken().equals("(")) { | |
248 | 238 | break; |
249 | 239 | } |
250 | 240 | try { |
@@ -252,43 +242,49 @@ public class Inputer { | ||
252 | 242 | Error.printError("{ expected"); |
253 | 243 | } |
254 | 244 | } catch (OutOfTokenStreamException e) { |
255 | - Error.printError("パラメータ指定に誤りがあります"); | |
245 | + Error.printError(Main.language == Main.Language.JP ? "パラメータ指定に誤りがあります" | |
246 | + : "Invalid parameter"); | |
256 | 247 | } |
257 | 248 | // グループのパラメータ |
258 | - Set<Integer> memberSet = new TreeSet<Integer>(); | |
249 | + Set<Integer> memberSet = new TreeSet<Integer>(); | |
259 | 250 | do { |
260 | 251 | String name = null; |
261 | 252 | try { |
262 | - name = t.getToken(); //チェックしてない | |
253 | + name = t.getToken(); // チェックしてない | |
263 | 254 | } catch (OutOfTokenStreamException e) { |
264 | - Error.printError("グループ指定に誤りがあります"); | |
255 | + Error.printError(Main.language == Main.Language.JP ? "グループ指定に誤りがあります" | |
256 | + : "Invalid grouping"); | |
265 | 257 | } |
266 | 258 | try { |
267 | - /* debug | |
268 | - System.out.print(name + " " + parameterList.getID(name) + ", "); | |
269 | - */ | |
259 | + /* | |
260 | + * debug System.out.print(name + " " + | |
261 | + * parameterList.getID(name) + ", "); | |
262 | + */ | |
270 | 263 | memberSet.add(Integer.valueOf(parameterList.getID(name))); |
271 | 264 | } catch (NoParameterNameException e) { |
272 | - Error.printError("グループ指定で因子名に誤りがあります"); | |
265 | + Error.printError(Main.language == Main.Language.JP ? "グループ指定で因子名に誤りがあります" | |
266 | + : "Invalid parameter in group"); | |
273 | 267 | } |
274 | 268 | if (t.peepToken() == null) { |
275 | - Error.printError("グループ指定に誤りがあります"); | |
269 | + Error.printError(Main.language == Main.Language.JP ? "グループ指定に誤りがあります" | |
270 | + : "Invalid grouping"); | |
276 | 271 | } |
277 | 272 | } while (t.peepToken().equals("}") == false); |
278 | 273 | Group g = new Group(memberSet); |
279 | 274 | groupList.add(g); |
280 | - | |
275 | + | |
281 | 276 | // } のよみこみ |
282 | 277 | try { |
283 | 278 | t.getToken(); |
284 | 279 | } catch (OutOfTokenStreamException e) { |
285 | - Error.printError("グループ指定に誤りがあります"); | |
280 | + Error.printError(Main.language == Main.Language.JP ? "グループ指定に誤りがあります" | |
281 | + : "Invalid grouping"); | |
286 | 282 | } |
287 | 283 | } |
288 | - //TODO groupの整列 | |
284 | + // TODO groupの整列 | |
289 | 285 | groupList.sort(); |
290 | 286 | // TODO 重複要素の削除 |
291 | - | |
287 | + | |
292 | 288 | return groupList; |
293 | 289 | } |
294 | 290 |
@@ -298,15 +294,16 @@ public class Inputer { | ||
298 | 294 | // default: standard input |
299 | 295 | return new BufferedReader(new InputStreamReader(System.in)); |
300 | 296 | } |
301 | - | |
297 | + | |
302 | 298 | try { |
303 | 299 | reader = new BufferedReader(new FileReader(filename)); |
304 | 300 | } catch (FileNotFoundException e) { |
305 | - Error.printError("ファイル" + filename + "が見つかりません."); | |
301 | + Error.printError(Main.language == Main.Language.JP ? "ファイル" | |
302 | + + filename + "が見つかりません." : "Cannot find file " + filename); | |
306 | 303 | } |
307 | 304 | return reader; |
308 | 305 | } |
309 | - | |
306 | + | |
310 | 307 | private static List<String> makeTokenList(BufferedReader reader) { |
311 | 308 | List<String> tokenList = new ArrayList<String>(); |
312 | 309 | String line; |
@@ -319,13 +316,13 @@ public class Inputer { | ||
319 | 316 | |
320 | 317 | line = line.replaceAll("\\{", " { "); |
321 | 318 | line = line.replaceAll("\\}", " } "); |
322 | - | |
319 | + | |
323 | 320 | line = line.replaceAll("\\[", " [ "); |
324 | 321 | line = line.replaceAll("\\]", " ] "); |
325 | - | |
326 | -// line = line.replaceAll(":", " : "); | |
322 | + | |
323 | + // line = line.replaceAll(":", " : "); | |
327 | 324 | line = line.replaceAll(";", " ; "); |
328 | - | |
325 | + | |
329 | 326 | StringTokenizer st = new StringTokenizer(line); |
330 | 327 | while (st.hasMoreTokens()) { |
331 | 328 | String token = st.nextToken(); |
@@ -344,7 +341,7 @@ public class Inputer { | ||
344 | 341 | // パラメータの読み込み |
345 | 342 | private static PList readParameter(TokenHandler t) { |
346 | 343 | PList parameterList = new PList(); |
347 | - | |
344 | + | |
348 | 345 | while (true) { |
349 | 346 | try { |
350 | 347 | if (t.peepToken() == null || t.peepToken().equals("{") |
@@ -359,7 +356,8 @@ public class Inputer { | ||
359 | 356 | Parameter p = new Parameter(parameter_name); |
360 | 357 | |
361 | 358 | if (t.getToken().equals("(") == false) { |
362 | - Error.printError("( がありません."); | |
359 | + Error.printError(Main.language == Main.Language.JP ? "( がありません." | |
360 | + : "( expected"); | |
363 | 361 | } |
364 | 362 | // レベルの名前 |
365 | 363 | do { |
@@ -367,7 +365,8 @@ public class Inputer { | ||
367 | 365 | checkLevelName(level_name); |
368 | 366 | p.addName(level_name); |
369 | 367 | if (t.peepToken() == null) { |
370 | - Error.printError("パラメータ指定に誤りがあります"); | |
368 | + Error.printError(Main.language == Main.Language.JP ? "パラメータ指定に誤りがあります" | |
369 | + : "Invalid parameters"); | |
371 | 370 | } |
372 | 371 | } while (t.peepToken().equals(")") == false); |
373 | 372 | // ) のよみこみ |
@@ -378,42 +377,44 @@ public class Inputer { | ||
378 | 377 | |
379 | 378 | parameterList.add(p); |
380 | 379 | } catch (OutOfTokenStreamException e) { |
381 | - Error.printError("パラメータ指定に誤りがあります"); | |
380 | + Error.printError(Main.language == Main.Language.JP ? "パラメータ指定に誤りがあります" | |
381 | + : "Invalid parameters"); | |
382 | 382 | } |
383 | 383 | } |
384 | - | |
385 | - // 因子名の重複チェック | |
384 | + | |
385 | + // 因子名の重複チェック | |
386 | 386 | if (parameterList.checkNameDuplication()) |
387 | - Error.printError("因子名が重複しています"); | |
388 | - | |
387 | + Error.printError(Main.language == Main.Language.JP ? "因子名が重複しています" | |
388 | + : "Duplicated parameters"); | |
389 | + | |
389 | 390 | // 因子数 >= 2 |
390 | 391 | if (parameterList.size() < 2) |
391 | - Error.printError("因子は2個以上必要です"); | |
392 | - | |
392 | + Error.printError(Main.language == Main.Language.JP ? "因子は2個以上必要です" | |
393 | + : "Multiple parameters required"); | |
394 | + | |
393 | 395 | return parameterList; |
394 | 396 | } |
395 | 397 | |
396 | 398 | private static void checkParameterName(String name) { |
397 | 399 | // TODO Auto-generated method stub |
398 | - if (name.contains("(") || name.contains(")") | |
399 | - || name.contains("{") || name.contains("}") | |
400 | - || name.contains("[") || name.contains("]") | |
401 | - || name.contains(";") || name.contains(",") | |
402 | - ) { | |
403 | - Error.printError("因子名に禁止文字が含まれています"); | |
404 | - } | |
400 | + if (name.contains("(") || name.contains(")") || name.contains("{") | |
401 | + || name.contains("}") || name.contains("[") | |
402 | + || name.contains("]") || name.contains(";") | |
403 | + || name.contains(",")) { | |
404 | + Error.printError(Main.language == Main.Language.JP ? "因子名に禁止文字が含まれています" | |
405 | + : "Invalid symbol in parameter name"); | |
406 | + } | |
405 | 407 | } |
406 | 408 | |
407 | 409 | private static void checkLevelName(String name) { |
408 | 410 | // TODO Auto-generated method stub |
409 | - if (name.contains("(") || name.contains(")") | |
410 | - || name.contains("{") || name.contains("}") | |
411 | - || name.contains("[") || name.contains("]") | |
412 | - || name.contains(";") || name.contains(",") | |
413 | - ) { | |
414 | - Error.printError("水準名に禁止文字が含まれています"); | |
415 | - } | |
411 | + if (name.contains("(") || name.contains(")") || name.contains("{") | |
412 | + || name.contains("}") || name.contains("[") | |
413 | + || name.contains("]") || name.contains(";") | |
414 | + || name.contains(",")) { | |
415 | + Error.printError(Main.language == Main.Language.JP ? "水準名に禁止文字が含まれています" | |
416 | + : "Invalid symbol in parameter value"); | |
417 | + } | |
416 | 418 | } |
417 | 419 | |
418 | - | |
419 | 420 | } |
@@ -9,16 +9,22 @@ public class Main { | ||
9 | 9 | static String seedFile; |
10 | 10 | static String outputFile; |
11 | 11 | static int strength = 2; // default strength |
12 | - | |
12 | + | |
13 | 13 | static final int MAX_LEVEL = 63; |
14 | - | |
14 | + | |
15 | 15 | static final int MAX_ITERATIONS = 100000; |
16 | 16 | static final int MAX_STRENGTH = 5; |
17 | 17 | static final int Max_RandomSeed = 65535; |
18 | - //static final int Max_RandomSeed = 10; | |
19 | - | |
18 | + // static final int Max_RandomSeed = 10; | |
19 | + | |
20 | 20 | static boolean debugMode = false; |
21 | - | |
21 | + | |
22 | + enum Language { | |
23 | + JP, EN | |
24 | + }; | |
25 | + | |
26 | + static Language language = Language.JP; | |
27 | + | |
22 | 28 | // Start the whole process |
23 | 29 | public static void main(String[] args) { |
24 | 30 |
@@ -28,41 +34,44 @@ public class Main { | ||
28 | 34 | |
29 | 35 | // エラー出力先設定 |
30 | 36 | Error.setOutputFile(outputFile); |
31 | - | |
37 | + | |
32 | 38 | // コマンド引数でのエラー出力 |
33 | - if (errorMessage != null) | |
39 | + if (errorMessage != null) | |
34 | 40 | Error.printError(errorMessage); |
35 | - | |
36 | - // モデル読み込み | |
37 | - InputFileData inputfiledata = Inputer.readModel(modelFile); | |
41 | + | |
42 | + // モデル読み込み | |
43 | + InputFileData inputfiledata = Inputer.readModel(modelFile); | |
38 | 44 | |
39 | 45 | // 制約処理 BDD作成 |
40 | - ConstraintHandler conhndl = new ConstraintHandler(inputfiledata.parameterList, inputfiledata.constraintList); | |
46 | + ConstraintHandler conhndl = new ConstraintHandler( | |
47 | + inputfiledata.parameterList, inputfiledata.constraintList); | |
41 | 48 | // DEBUG: BDDの表示 |
42 | 49 | /* conhndl.printConstraintBDD(); */ |
43 | 50 | |
44 | - // シード読み込み | |
51 | + // シード読み込み | |
45 | 52 | List<Testcase> seed = Inputer.readSeed(seedFile, inputfiledata); |
46 | 53 | |
47 | - | |
48 | - //テストケース生成 | |
54 | + // テストケース生成 | |
49 | 55 | List<Testcase> testSet = null; |
50 | 56 | if (strength == -1) { |
51 | 57 | // 全網羅 |
52 | 58 | try { |
53 | - testSet = GeneratorAll.generate(new ParameterModel(inputfiledata.parameterList), conhndl); | |
59 | + testSet = GeneratorAll.generate(new ParameterModel( | |
60 | + inputfiledata.parameterList), conhndl); | |
54 | 61 | } catch (OutOfMaxNumOfTestcasesException e) { |
55 | - Error.printError("テストケース数が上限" + Generator.MaxNumOfTestcases + "を超えました"); | |
62 | + Error.printError(Main.language == Main.Language.JP ? "テストケース数が上限" | |
63 | + + Generator.MaxNumOfTestcases + "を超えました" | |
64 | + : "The number of test cases exceeded the upper bound " | |
65 | + + Generator.MaxNumOfTestcases); | |
56 | 66 | } |
57 | 67 | |
58 | - new Outputer(outputFile).outputResult(testSet, inputfiledata, | |
68 | + new Outputer(outputFile).outputResult(testSet, inputfiledata, | |
59 | 69 | modelFile, outputFile); |
60 | - } | |
61 | - else { // strength >= 2 | |
70 | + } else { // strength >= 2 | |
62 | 71 | Generator generator = GeneratorFactor.newGenerator( |
63 | 72 | new ParameterModel(inputfiledata.parameterList), |
64 | - inputfiledata.groupList, | |
65 | - conhndl, seed, randomSeed, strength); | |
73 | + inputfiledata.groupList, conhndl, seed, randomSeed, | |
74 | + strength); | |
66 | 75 | try { |
67 | 76 | testSet = generator.generate(); |
68 | 77 | } catch (OutOfMaxNumOfTestcasesException e) { |
@@ -73,11 +82,12 @@ public class Main { | ||
73 | 82 | System.err.println("random seed: " + randomSeed); |
74 | 83 | // 繰り返す場合 |
75 | 84 | for (int i = 2; i < numOfIterations; i++) { |
76 | - int nextRandomSeed = (int) Math.floor(Math.random() * (Max_RandomSeed + 1)); | |
85 | + int nextRandomSeed = (int) Math.floor(Math.random() | |
86 | + * (Max_RandomSeed + 1)); | |
77 | 87 | generator = GeneratorFactor.newGenerator( |
78 | 88 | new ParameterModel(inputfiledata.parameterList), |
79 | - inputfiledata.groupList, | |
80 | - conhndl, seed, nextRandomSeed, strength); | |
89 | + inputfiledata.groupList, conhndl, seed, | |
90 | + nextRandomSeed, strength); | |
81 | 91 | |
82 | 92 | if (debugMode) |
83 | 93 | System.err.println("random seed: " + nextRandomSeed); |
@@ -94,17 +104,20 @@ public class Main { | ||
94 | 104 | testSet = nextTestSet; |
95 | 105 | randomSeed = nextRandomSeed; |
96 | 106 | } |
97 | - } | |
98 | - else if (testSet == null && nextTestSet != null) { | |
107 | + } else if (testSet == null && nextTestSet != null) { | |
99 | 108 | testSet = nextTestSet; |
100 | 109 | randomSeed = nextRandomSeed; |
101 | 110 | } |
102 | 111 | } |
103 | - if (testSet == null) | |
104 | - Error.printError("テストケース数が上限" + Generator.MaxNumOfTestcases + "を超えました"); | |
112 | + if (testSet == null) | |
113 | + Error.printError(Main.language == Main.Language.JP ? "テストケース数が上限" | |
114 | + + Generator.MaxNumOfTestcases + "を超えました" | |
115 | + : "The number of test cases exceeded the upper bound " | |
116 | + + Generator.MaxNumOfTestcases); | |
105 | 117 | |
106 | - new Outputer(outputFile).outputResult(testSet, inputfiledata, | |
107 | - randomSeed, modelFile, seedFile, outputFile, strength, numOfIterations); | |
118 | + new Outputer(outputFile).outputResult(testSet, inputfiledata, | |
119 | + randomSeed, modelFile, seedFile, outputFile, strength, | |
120 | + numOfIterations); | |
108 | 121 | } |
109 | 122 | |
110 | 123 | /* debug */ |
@@ -112,56 +125,87 @@ public class Main { | ||
112 | 125 | System.err.println("test set size: " + testSet.size()); |
113 | 126 | } |
114 | 127 | } catch (OutOfMemoryError e) { |
115 | - Error.printError("メモリ不足です."); | |
128 | + Error.printError(Main.language == Main.Language.JP ? "メモリ不足です." | |
129 | + : "Out of memory"); | |
116 | 130 | } catch (Exception e) { |
117 | - Error.printError("プログラムが異常終了しました."); | |
131 | + Error.printError(Main.language == Main.Language.JP ? "プログラムが異常終了しました." | |
132 | + : "Abnormal termination"); | |
118 | 133 | } |
119 | - } | |
134 | + } | |
120 | 135 | |
121 | 136 | // コマンド引数処理 |
122 | 137 | private static String processCommandArgument(String[] args) { |
123 | 138 | if (args.length == 0) { |
124 | - Error.printError("usage: java -jar Program.jar ..."); | |
139 | + Error.printError("usage: java -jar Program.jar [-i input] [-o output] [-policy] ..."); | |
140 | + } | |
141 | + | |
142 | + // policyの表示 | |
143 | + if (args.length == 1 && args[0].equals("-policy")) { | |
144 | + System.out | |
145 | + .println("This software (CIT-BACH 1.02) is distributed under the zlib license.\n" | |
146 | + + "The software contains Java classes from JDD, a Java BDD library " | |
147 | + + "developed by Arash Vahidi.\n" | |
148 | + + "JDD is free software distributed under the zlib license.\n" | |
149 | + + "\n" | |
150 | + + "Copyright (c) 2015, Tatsuhiro Tsuchiya\n" | |
151 | + + "This software is provided 'as-is', without any express or implied \n" | |
152 | + + "warranty. In no event will the authors be held liable for any damages \n" | |
153 | + + "arising from the use of this software. \n" | |
154 | + + "\n" | |
155 | + + "Permission is granted to anyone to use this software for any purpose, \n" | |
156 | + + "including commercial applications, and to alter it and redistribute it \n" | |
157 | + + "freely, subject to the following restrictions: \n" | |
158 | + + " \n" | |
159 | + + " 1. The origin of this software must not be misrepresented; you must not \n" | |
160 | + + " claim that you wrote the original software. If you use this software \n" | |
161 | + + " in a product, an acknowledgment in the product documentation would be \n" | |
162 | + + " appreciated but is not required. \n" | |
163 | + + " \n" | |
164 | + + " 2. Altered source versions must be plainly marked as such, and must not be \n" | |
165 | + + " misrepresented as being the original software. \n" | |
166 | + + " \n" | |
167 | + + " 3. This notice may not be removed or altered from any source \n" | |
168 | + + " distribution. \n"); | |
169 | + System.exit(0); | |
125 | 170 | } |
126 | - | |
171 | + | |
127 | 172 | // エラー表示を出力ファイルが指定されるまで遅らせる |
128 | - String errorMessage = null; | |
129 | - | |
173 | + String errorMessage = null; | |
174 | + | |
130 | 175 | for (int i = 0; i + 1 < args.length; i += 2) { |
131 | 176 | String option = args[i]; |
132 | - String str = args[i+1]; | |
177 | + String str = args[i + 1]; | |
133 | 178 | if (option.equals("-i")) { |
134 | 179 | modelFile = str; |
135 | - } | |
136 | - else if (option.equals("-o")) { | |
180 | + } else if (option.equals("-o")) { | |
137 | 181 | outputFile = str; |
138 | - } | |
139 | - else if (option.equals("-random")) { | |
182 | + } else if (option.equals("-random")) { | |
140 | 183 | try { |
141 | 184 | randomSeed = Integer.parseInt(str); |
142 | 185 | } catch (NumberFormatException e) { |
143 | - //Error.printError("invalid number"); | |
144 | - errorMessage = "ランダムシードに無効な値が指定されています."; | |
186 | + // Error.printError("invalid number"); | |
187 | + errorMessage = Main.language == Main.Language.JP ? "ランダムシードに無効な値が指定されています." | |
188 | + : "Invalid random seed"; | |
145 | 189 | continue; |
146 | 190 | } |
147 | 191 | randomSeed = Math.abs(randomSeed) % (Max_RandomSeed + 1); |
148 | - } | |
149 | - else if (option.equals("-c")) { | |
192 | + } else if (option.equals("-c")) { | |
150 | 193 | if (str.equals("all")) { |
151 | 194 | // 全網羅 |
152 | 195 | strength = -1; |
153 | - } | |
154 | - else { | |
196 | + } else { | |
155 | 197 | try { |
156 | 198 | strength = Integer.parseInt(str); |
157 | 199 | } catch (NumberFormatException e) { |
158 | 200 | // Error.printError("invalid number"); |
159 | - errorMessage = "網羅度に無効な値が指定されています."; | |
201 | + errorMessage = Main.language == Main.Language.JP ? "網羅度に無効な値が指定されています." | |
202 | + : "Invalid strength"; | |
160 | 203 | continue; |
161 | 204 | } |
162 | 205 | if (strength < 2 || MAX_STRENGTH < strength) { |
163 | - //Error.printError("invalid strength"); | |
164 | - errorMessage = "網羅度に無効な値が指定されています."; | |
206 | + // Error.printError("invalid strength"); | |
207 | + errorMessage = Main.language == Main.Language.JP ? "網羅度に無効な値が指定されています." | |
208 | + : "Invalid strength"; | |
165 | 209 | continue; |
166 | 210 | } |
167 | 211 | } |
@@ -171,34 +215,43 @@ public class Main { | ||
171 | 215 | try { |
172 | 216 | numOfIterations = Integer.parseInt(str); |
173 | 217 | } catch (NumberFormatException e) { |
174 | - //Error.printError("invalid repeating number"); | |
175 | - errorMessage = "くり返し数に無効な値が指定されています."; | |
218 | + // Error.printError("invalid repeating number"); | |
219 | + errorMessage = Main.language == Main.Language.JP ? "くり返し数に無効な値が指定されています." | |
220 | + : "Invalid number of repetition times"; | |
176 | 221 | continue; |
177 | 222 | } |
178 | 223 | if (numOfIterations <= 0 || numOfIterations > MAX_ITERATIONS) { |
179 | 224 | // Error.printError("invalid repeating number"); |
180 | - errorMessage = "くり返し数に無効な値が指定されています."; | |
225 | + errorMessage = Main.language == Main.Language.JP ? "くり返し数に無効な値が指定されています." | |
226 | + : "Invalid number of repetition times"; | |
181 | 227 | continue; |
182 | 228 | } |
183 | - } | |
184 | - else if (option.equals("-s")) { | |
185 | - seedFile = str; | |
186 | - } | |
187 | - else if (option.equals("-debug")) { | |
229 | + } else if (option.equals("-s")) { | |
230 | + seedFile = str; | |
231 | + } else if (option.equals("-debug")) { | |
188 | 232 | debugMode = true; |
189 | 233 | // 次の引数はダミー |
190 | - } | |
191 | - else { | |
234 | + } else if (option.equals("-lang")) { | |
235 | + if (str.matches("JP|jp")) { | |
236 | + Main.language = Main.Language.JP; | |
237 | + } else if (str.matches("EN|en")) { | |
238 | + Main.language = Main.Language.EN; | |
239 | + } else { | |
240 | + errorMessage = "無効な言語が指定されています (Invalid Language)"; | |
241 | + continue; | |
242 | + } | |
243 | + } else { | |
192 | 244 | // Error.printError("Invalid option"); |
193 | - errorMessage = "無効なオプションが指定されています."; | |
245 | + errorMessage = Main.language == Main.Language.JP ? "無効なオプションが指定されています." | |
246 | + : "Invalid option"; | |
194 | 247 | continue; |
195 | 248 | } |
196 | 249 | } |
197 | - | |
250 | + | |
198 | 251 | if (randomSeed == -1) { |
199 | 252 | randomSeed = (int) Math.floor(Math.random() * (Max_RandomSeed + 1)); |
200 | 253 | } |
201 | - | |
254 | + | |
202 | 255 | return errorMessage; |
203 | 256 | } |
204 | 257 | } |
@@ -1,4 +1,5 @@ | ||
1 | 1 | package v1; |
2 | + | |
2 | 3 | import jdd.bdd.*; |
3 | 4 | |
4 | 5 | import java.util.*; |
@@ -7,7 +8,7 @@ abstract class Node { | ||
7 | 8 | abstract int evaluate(BDD bdd, List<VariableAndBDD> parameters); |
8 | 9 | } |
9 | 10 | |
10 | -abstract class BooleanOperator extends Node{ | |
11 | +abstract class BooleanOperator extends Node { | |
11 | 12 | } |
12 | 13 | |
13 | 14 | abstract class BooleanUnaryOperator extends BooleanOperator { |
@@ -15,8 +16,8 @@ abstract class BooleanUnaryOperator extends BooleanOperator { | ||
15 | 16 | } |
16 | 17 | |
17 | 18 | class NotOperator extends BooleanUnaryOperator { |
18 | - int evaluate (BDD bdd, List<VariableAndBDD> parameters) { | |
19 | - int tmp = Child.evaluate(bdd, parameters); | |
19 | + int evaluate(BDD bdd, List<VariableAndBDD> parameters) { | |
20 | + int tmp = Child.evaluate(bdd, parameters); | |
20 | 21 | int res = bdd.not(tmp); |
21 | 22 | bdd.ref(res); |
22 | 23 | bdd.deref(tmp); |
@@ -29,34 +30,37 @@ abstract class BooleanBinaryOperator extends BooleanOperator { | ||
29 | 30 | } |
30 | 31 | |
31 | 32 | class IfOperator extends BooleanBinaryOperator { |
32 | - int evaluate (BDD bdd, List<VariableAndBDD> parameters) { | |
33 | + int evaluate(BDD bdd, List<VariableAndBDD> parameters) { | |
33 | 34 | int f1 = Left.evaluate(bdd, parameters); |
34 | 35 | int f2 = Right.evaluate(bdd, parameters); |
35 | 36 | int f = bdd.imp(f1, f2); |
36 | 37 | bdd.ref(f); |
37 | - bdd.deref(f1); bdd.deref(f2); | |
38 | + bdd.deref(f1); | |
39 | + bdd.deref(f2); | |
38 | 40 | return f; |
39 | 41 | } |
40 | 42 | } |
41 | 43 | |
42 | 44 | class EqualityOperator extends BooleanBinaryOperator { |
43 | - int evaluate (BDD bdd, List<VariableAndBDD> parameters) { | |
45 | + int evaluate(BDD bdd, List<VariableAndBDD> parameters) { | |
44 | 46 | int f1 = Left.evaluate(bdd, parameters); |
45 | 47 | int f2 = Right.evaluate(bdd, parameters); |
46 | 48 | int f = bdd.not(bdd.xor(f1, f2)); |
47 | 49 | bdd.ref(f); |
48 | - bdd.deref(f1); bdd.deref(f2); | |
50 | + bdd.deref(f1); | |
51 | + bdd.deref(f2); | |
49 | 52 | return f; |
50 | 53 | } |
51 | 54 | } |
52 | 55 | |
53 | 56 | class InequalityOperator extends BooleanBinaryOperator { |
54 | - int evaluate (BDD bdd, List<VariableAndBDD> parameters) { | |
57 | + int evaluate(BDD bdd, List<VariableAndBDD> parameters) { | |
55 | 58 | int f1 = Left.evaluate(bdd, parameters); |
56 | 59 | int f2 = Right.evaluate(bdd, parameters); |
57 | 60 | int f = bdd.xor(f1, f2); |
58 | 61 | bdd.ref(f); |
59 | - bdd.deref(f1); bdd.deref(f2); | |
62 | + bdd.deref(f1); | |
63 | + bdd.deref(f2); | |
60 | 64 | return f; |
61 | 65 | } |
62 | 66 | } |
@@ -66,13 +70,15 @@ abstract class BooleanTrinaryOperator extends BooleanOperator { | ||
66 | 70 | } |
67 | 71 | |
68 | 72 | class IfthenelseOperator extends BooleanTrinaryOperator { |
69 | - int evaluate (BDD bdd, List<VariableAndBDD> parameters) { | |
70 | - int f1 = Left.evaluate(bdd, parameters); | |
73 | + int evaluate(BDD bdd, List<VariableAndBDD> parameters) { | |
74 | + int f1 = Left.evaluate(bdd, parameters); | |
71 | 75 | int f2 = Middle.evaluate(bdd, parameters); |
72 | 76 | int f3 = Right.evaluate(bdd, parameters); |
73 | 77 | int f = bdd.ite(f1, f2, f3); |
74 | 78 | bdd.ref(f); |
75 | - bdd.deref(f1); bdd.deref(f2); bdd.deref(f3); | |
79 | + bdd.deref(f1); | |
80 | + bdd.deref(f2); | |
81 | + bdd.deref(f3); | |
76 | 82 | return f; |
77 | 83 | } |
78 | 84 | } |
@@ -82,45 +88,49 @@ abstract class BooleanMultinaryOperator extends BooleanOperator { | ||
82 | 88 | } |
83 | 89 | |
84 | 90 | class OrOperator extends BooleanMultinaryOperator { |
85 | - | |
86 | - int evaluate (BDD bdd, List<VariableAndBDD> parameters) { | |
91 | + | |
92 | + int evaluate(BDD bdd, List<VariableAndBDD> parameters) { | |
87 | 93 | int f1 = ChildList.get(0).evaluate(bdd, parameters); |
88 | 94 | int f2 = ChildList.get(1).evaluate(bdd, parameters); |
89 | 95 | int f = bdd.or(f1, f2); |
90 | 96 | bdd.ref(f); |
91 | - bdd.deref(f1); bdd.deref(f2); | |
97 | + bdd.deref(f1); | |
98 | + bdd.deref(f2); | |
92 | 99 | |
93 | 100 | for (int i = 2; i < ChildList.size(); i++) { |
94 | 101 | f1 = f; |
95 | 102 | f2 = ChildList.get(i).evaluate(bdd, parameters); |
96 | 103 | f = bdd.or(f1, f2); |
97 | 104 | bdd.ref(f); |
98 | - bdd.deref(f1); bdd.deref(f2); | |
105 | + bdd.deref(f1); | |
106 | + bdd.deref(f2); | |
99 | 107 | } |
100 | 108 | return f; |
101 | 109 | } |
102 | 110 | } |
103 | 111 | |
104 | 112 | class AndOperator extends BooleanMultinaryOperator { |
105 | - int evaluate (BDD bdd, List<VariableAndBDD> parameters) { | |
113 | + int evaluate(BDD bdd, List<VariableAndBDD> parameters) { | |
106 | 114 | int f1 = ChildList.get(0).evaluate(bdd, parameters); |
107 | 115 | int f2 = ChildList.get(1).evaluate(bdd, parameters); |
108 | 116 | int f = bdd.and(f1, f2); |
109 | 117 | bdd.ref(f); |
110 | - bdd.deref(f1); bdd.deref(f2); | |
118 | + bdd.deref(f1); | |
119 | + bdd.deref(f2); | |
111 | 120 | |
112 | 121 | for (int i = 2; i < ChildList.size(); i++) { |
113 | 122 | f1 = f; |
114 | 123 | f2 = ChildList.get(i).evaluate(bdd, parameters); |
115 | 124 | f = bdd.and(f1, f2); |
116 | 125 | bdd.ref(f); |
117 | - bdd.deref(f1); bdd.deref(f2); | |
126 | + bdd.deref(f1); | |
127 | + bdd.deref(f2); | |
118 | 128 | } |
119 | 129 | return f; |
120 | 130 | } |
121 | 131 | } |
122 | 132 | |
123 | -abstract class AtomicExpression extends Node{ | |
133 | +abstract class AtomicExpression extends Node { | |
124 | 134 | } |
125 | 135 | |
126 | 136 | abstract class Constant extends AtomicExpression { |
@@ -128,11 +138,11 @@ abstract class Constant extends AtomicExpression { | ||
128 | 138 | |
129 | 139 | class TrueValue extends Constant { |
130 | 140 | int evaluate(BDD bdd, List<VariableAndBDD> parameters) { |
131 | - | |
141 | + | |
132 | 142 | int f = bdd.getOne(); |
133 | 143 | bdd.ref(f); |
134 | 144 | return f; |
135 | - } | |
145 | + } | |
136 | 146 | } |
137 | 147 | |
138 | 148 | class FalseValue extends Constant { |
@@ -140,7 +150,7 @@ class FalseValue extends Constant { | ||
140 | 150 | int f = bdd.getZero(); |
141 | 151 | bdd.ref(f); |
142 | 152 | return f; |
143 | - } | |
153 | + } | |
144 | 154 | } |
145 | 155 | |
146 | 156 | abstract class ComparisonOfValueAndValue extends AtomicExpression { |
@@ -148,12 +158,10 @@ abstract class ComparisonOfValueAndValue extends AtomicExpression { | ||
148 | 158 | int v2; |
149 | 159 | } |
150 | 160 | |
151 | -/* not used | |
152 | -abstract class ComparisonOfParameterAndParameter extends AtomicExpression { | |
153 | - int p1; | |
154 | - int p2; | |
155 | -} | |
156 | -*/ | |
161 | +/* | |
162 | + * not used abstract class ComparisonOfParameterAndParameter extends | |
163 | + * AtomicExpression { int p1; int p2; } | |
164 | + */ | |
157 | 165 | |
158 | 166 | abstract class ComparisonOfParameterAndValue extends AtomicExpression { |
159 | 167 | int p; |
@@ -161,15 +169,10 @@ abstract class ComparisonOfParameterAndValue extends AtomicExpression { | ||
161 | 169 | } |
162 | 170 | |
163 | 171 | /* |
164 | -class EqualityOfValueAndValue extends ComparisonOfValueAndValue { | |
165 | - int evaluate (BDD bdd, List<VariableAndBDD> parameters) { | |
166 | - if (v1 == v2) | |
167 | - return bdd.getOne(); | |
168 | - else | |
169 | - return bdd.getZero(); | |
170 | - } | |
171 | -} | |
172 | -*/ | |
172 | + * class EqualityOfValueAndValue extends ComparisonOfValueAndValue { int | |
173 | + * evaluate (BDD bdd, List<VariableAndBDD> parameters) { if (v1 == v2) return | |
174 | + * bdd.getOne(); else return bdd.getZero(); } } | |
175 | + */ | |
173 | 176 | |
174 | 177 | class EqualityOfParameterAndValue extends ComparisonOfParameterAndValue { |
175 | 178 | int evaluate(BDD bdd, List<VariableAndBDD> parameters) { |
@@ -178,10 +181,13 @@ class EqualityOfParameterAndValue extends ComparisonOfParameterAndValue { | ||
178 | 181 | int[] var = parameters.get(this.p).var; |
179 | 182 | for (int i = var.length - 1; i >= 0; i--) { |
180 | 183 | if ((this.v & (0x01 << i)) > 0) { |
181 | - int tmp = bdd.ref(bdd.and(res, var[i])); bdd.deref(res); res = tmp; | |
182 | - } | |
183 | - else { | |
184 | - int tmp = bdd.ref(bdd.and(res, bdd.not(var[i]))); bdd.deref(res); res = tmp; | |
184 | + int tmp = bdd.ref(bdd.and(res, var[i])); | |
185 | + bdd.deref(res); | |
186 | + res = tmp; | |
187 | + } else { | |
188 | + int tmp = bdd.ref(bdd.and(res, bdd.not(var[i]))); | |
189 | + bdd.deref(res); | |
190 | + res = tmp; | |
185 | 191 | } |
186 | 192 | } |
187 | 193 | bdd.ref(res); |
@@ -7,9 +7,9 @@ import java.io.OutputStreamWriter; | ||
7 | 7 | import java.util.List; |
8 | 8 | |
9 | 9 | public class Outputer { |
10 | - | |
10 | + | |
11 | 11 | BufferedWriter writer; |
12 | - | |
12 | + | |
13 | 13 | Outputer(String filename) { |
14 | 14 | this.writer = openFile(filename); |
15 | 15 | } |
@@ -20,42 +20,44 @@ public class Outputer { | ||
20 | 20 | // default: standard output |
21 | 21 | return new BufferedWriter(new OutputStreamWriter(System.out)); |
22 | 22 | } |
23 | - | |
23 | + | |
24 | 24 | try { |
25 | 25 | writer = new BufferedWriter(new FileWriter(filename)); |
26 | 26 | } catch (IOException e) { |
27 | - //System.err.print(filename + " cannot be created."); | |
27 | + // System.err.print(filename + " cannot be created."); | |
28 | 28 | // エラーを書き込めないので直接標準エラーへ |
29 | - System.err.print("出力ファイル" + filename + "が作成できません."); | |
29 | + System.err.print(Main.language == Main.Language.JP ? "出力ファイル" | |
30 | + + filename + "が作成できません." : "Cannot create output file " | |
31 | + + filename); | |
30 | 32 | System.exit(1); |
31 | 33 | } |
32 | 34 | return writer; |
33 | 35 | } |
34 | - | |
35 | - void outputResult(List<Testcase> testSet, InputFileData inputfiledata, | |
36 | - int randomSeed, String modelFile, String seedFile, String outputFile, int strength, int numOfIterations){ | |
36 | + | |
37 | + void outputResult(List<Testcase> testSet, InputFileData inputfiledata, | |
38 | + int randomSeed, String modelFile, String seedFile, | |
39 | + String outputFile, int strength, int numOfIterations) { | |
37 | 40 | try { |
38 | - String firstline = "#SUCCESS" + "," + randomSeed + "," | |
39 | - + "i" + "," + (modelFile == null ? "" : modelFile) + "," | |
40 | - + "s" + "," + (seedFile == null ? "" : seedFile) + "," | |
41 | - + "o" + "," + (outputFile == null ? "" : outputFile) + "," | |
42 | - + "c" + "," + (strength < 0 ? "all" : strength) + "," | |
43 | - + "random" + "," + randomSeed + "," | |
44 | - + "repeat" + "," + numOfIterations + "\n" | |
45 | - ; | |
41 | + String firstline = "#SUCCESS" + "," + randomSeed + "," + "i" + "," | |
42 | + + (modelFile == null ? "" : modelFile) + "," + "s" + "," | |
43 | + + (seedFile == null ? "" : seedFile) + "," + "o" + "," | |
44 | + + (outputFile == null ? "" : outputFile) + "," + "c" + "," | |
45 | + + (strength < 0 ? "all" : strength) + "," + "random" + "," | |
46 | + + randomSeed + "," + "repeat" + "," + numOfIterations | |
47 | + + "\n"; | |
46 | 48 | this.writer.write(firstline); |
47 | - | |
49 | + | |
48 | 50 | for (int i = 0; i < inputfiledata.parameterList.size(); i++) { |
49 | 51 | if (i > 0) |
50 | 52 | writer.write(","); |
51 | 53 | writer.write(inputfiledata.parameterList.get(i).name); |
52 | 54 | } |
53 | 55 | writer.write("\n"); |
54 | - | |
56 | + | |
55 | 57 | for (Testcase test : testSet) |
56 | 58 | test.print(writer, inputfiledata); |
57 | - | |
58 | - //close | |
59 | + | |
60 | + // close | |
59 | 61 | this.writer.close(); |
60 | 62 | } catch (IOException e) { |
61 | 63 | System.err.print("Cannot write the file"); |
@@ -67,30 +69,27 @@ public class Outputer { | ||
67 | 69 | InputFileData inputfiledata, String modelFile, String outputFile) { |
68 | 70 | // TODO Auto-generated method stub |
69 | 71 | try { |
70 | - String firstline = "#SUCCESS" + "," + 0 + "," | |
71 | - + "i" + "," + (modelFile == null ? "" : modelFile) + "," | |
72 | - + "s" + "," + "," | |
73 | - + "o" + "," + (outputFile == null ? "" : outputFile) + "," | |
74 | - + "c" + "," + "all" + "," | |
75 | - + "random" + "," + 0 + "," | |
76 | - + "repeat" + "," + 1 + "\n" | |
77 | - ; | |
72 | + String firstline = "#SUCCESS" + "," + 0 + "," + "i" + "," | |
73 | + + (modelFile == null ? "" : modelFile) + "," + "s" + "," | |
74 | + + "," + "o" + "," + (outputFile == null ? "" : outputFile) | |
75 | + + "," + "c" + "," + "all" + "," + "random" + "," + 0 + "," | |
76 | + + "repeat" + "," + 1 + "\n"; | |
78 | 77 | this.writer.write(firstline); |
79 | - | |
78 | + | |
80 | 79 | for (int i = 0; i < inputfiledata.parameterList.size(); i++) { |
81 | 80 | if (i > 0) |
82 | 81 | writer.write(","); |
83 | 82 | writer.write(inputfiledata.parameterList.get(i).name); |
84 | 83 | } |
85 | 84 | writer.write("\n"); |
86 | - | |
85 | + | |
87 | 86 | for (Testcase test : testSet) |
88 | 87 | test.print(writer, inputfiledata); |
89 | - | |
90 | - //close | |
88 | + | |
89 | + // close | |
91 | 90 | this.writer.close(); |
92 | 91 | } catch (IOException e) { |
93 | 92 | System.err.print("Cannot write the file"); |
94 | - } | |
93 | + } | |
95 | 94 | } |
96 | 95 | } |
@@ -9,7 +9,7 @@ public class Parameter { | ||
9 | 9 | Parameter(String name) { |
10 | 10 | this.name = name; |
11 | 11 | } |
12 | - | |
12 | + | |
13 | 13 | void addName(String name) { |
14 | 14 | value_name.add(name); |
15 | 15 | } |
@@ -17,22 +17,36 @@ public class Parameter { | ||
17 | 17 | // 値名の重複のチェック 重複していればエラー |
18 | 18 | void check() { |
19 | 19 | if (value_name.size() <= 0 || value_name.size() > Main.MAX_LEVEL) { |
20 | - Error.printError("水準数に誤りがあります"); | |
21 | - } | |
22 | - for (int i = 0; i < value_name.size() - 1; i++) { | |
23 | - for (int j = i+1; j < value_name.size(); j++) { | |
24 | - if (value_name.get(i).equals(value_name.get(j))) | |
25 | - Error.printError("水準名が重複しています"); | |
26 | - } | |
20 | + Error.printError(Main.language == Main.Language.JP ? "水準数に誤りがあります" | |
21 | + : "Invalid number of values"); | |
27 | 22 | } |
23 | + | |
24 | + /* 水準名の重複を禁止-> comment out */ | |
25 | + /* | |
26 | + * for (int i = 0; i < value_name.size() - 1; i++) { for (int j = i+1; j | |
27 | + * < value_name.size(); j++) { if | |
28 | + * (value_name.get(i).equals(value_name.get(j))) | |
29 | + * Error.printError(Main.language == Main.Language.JP ? "水準名が重複しています" : | |
30 | + * "Overlap of parameter value name"); } } | |
31 | + */ | |
28 | 32 | } |
29 | - | |
30 | - int getID(String str) throws NoValueNameException { | |
33 | + | |
34 | + /* | |
35 | + * int getID(String str) throws NoValueNameException { for (int i = 0; i < | |
36 | + * value_name.size(); i++) { if (value_name.get(i).equals(str)) return i; } | |
37 | + * throw new NoValueNameException(); } | |
38 | + */ | |
39 | + | |
40 | + List<Integer> getID(String str) throws NoValueNameException { | |
41 | + List<Integer> ids = new ArrayList<Integer>(); | |
31 | 42 | for (int i = 0; i < value_name.size(); i++) { |
32 | 43 | if (value_name.get(i).equals(str)) |
33 | - return i; | |
44 | + ids.add(i); | |
34 | 45 | } |
35 | - throw new NoValueNameException(); | |
46 | + if (ids.size() == 0) | |
47 | + throw new NoValueNameException(); | |
48 | + else | |
49 | + return ids; | |
36 | 50 | } |
37 | 51 | |
38 | 52 | } |
@@ -45,7 +59,7 @@ class PList extends LinkedList<Parameter> { | ||
45 | 59 | |
46 | 60 | boolean checkNameDuplication() { |
47 | 61 | for (int i = 0; i < this.size() - 1; i++) |
48 | - for (int j = i + 1; j < this.size(); j++) { | |
62 | + for (int j = i + 1; j < this.size(); j++) { | |
49 | 63 | if (this.get(i).name.equals(this.get(j).name)) { |
50 | 64 | return true; |
51 | 65 | } |
@@ -55,7 +69,7 @@ class PList extends LinkedList<Parameter> { | ||
55 | 69 | |
56 | 70 | int getID(String str) throws NoParameterNameException { |
57 | 71 | for (int i = 0; i < this.size(); i++) { |
58 | - if (this.get(i).name.equals(str)) | |
72 | + if (this.get(i).name.equals(str)) | |
59 | 73 | return i; |
60 | 74 | } |
61 | 75 | throw new NoParameterNameException(); |
@@ -69,6 +83,7 @@ class NoParameterNameException extends Exception { | ||
69 | 83 | */ |
70 | 84 | private static final long serialVersionUID = 6603037538755301907L; |
71 | 85 | } |
86 | + | |
72 | 87 | class NoValueNameException extends Exception { |
73 | 88 | |
74 | 89 | /** |
@@ -13,5 +13,5 @@ public class ParameterModel { | ||
13 | 13 | range[i] = (byte) plist.get(i).value_name.size(); |
14 | 14 | } |
15 | 15 | } |
16 | - | |
16 | + | |
17 | 17 | } |
@@ -6,50 +6,57 @@ import java.util.List; | ||
6 | 6 | public class Parse { |
7 | 7 | private TokenHandler t; |
8 | 8 | private PList parameterList; |
9 | + | |
9 | 10 | Parse(TokenHandler t, PList parameterList) { |
10 | - this.t = t; | |
11 | + this.t = t; | |
11 | 12 | this.parameterList = parameterList; |
12 | 13 | } |
13 | - | |
14 | + | |
14 | 15 | public Node parseExpression() { |
15 | 16 | String token = t.peepToken(); |
16 | 17 | try { |
17 | 18 | if (token == null) { |
18 | - Error.printError("制約式に誤りがあります"); | |
19 | + Error.printError(Main.language == Main.Language.JP ? "制約式に誤りがあります" | |
20 | + : "Invalid constraints"); | |
19 | 21 | return null; |
20 | 22 | } else if (token.equals("(")) |
21 | 23 | return expressionWithParentheses(); |
22 | 24 | else { |
23 | 25 | // error |
24 | - Error.printError("制約に'('がありません"); | |
26 | + Error.printError(Main.language == Main.Language.JP ? "制約に'('がありません" | |
27 | + : "( expected in constraints"); | |
25 | 28 | return null; |
26 | 29 | } |
27 | 30 | } catch (OutOfTokenStreamException e) { |
28 | - Error.printError("制約式に誤りがあります"); | |
31 | + Error.printError(Main.language == Main.Language.JP ? "制約式に誤りがあります" | |
32 | + : "Invalid constraints"); | |
29 | 33 | return null; |
30 | 34 | } |
31 | 35 | } |
32 | - | |
36 | + | |
33 | 37 | private Node expressionWithParentheses() throws OutOfTokenStreamException { |
34 | 38 | Node res; // 戻り値 |
35 | 39 | String token = t.getToken(); |
36 | 40 | if (token.equals("(") == false) { |
37 | 41 | // error |
38 | 42 | // this block is unreachable |
39 | - Error.printError("制約に'('がありません"); | |
43 | + Error.printError(Main.language == Main.Language.JP ? "制約に'('がありません" | |
44 | + : "( expected in constraints"); | |
40 | 45 | return null; |
41 | 46 | } |
42 | 47 | // expression :: (expression) |
43 | - if (t.peepToken() == null) | |
48 | + if (t.peepToken() == null) | |
44 | 49 | throw new OutOfTokenStreamException(); |
45 | - if (t.peepToken().equals("(")) | |
50 | + if (t.peepToken().equals("(")) | |
46 | 51 | res = expressionWithParentheses(); |
47 | - else // otherwise | |
52 | + else | |
53 | + // otherwise | |
48 | 54 | res = expressionBody(); |
49 | 55 | // closed with ')' ? |
50 | 56 | if (t.getToken().equals(")") == false) { |
51 | 57 | // error |
52 | - Error.printError("制約に')'がありません"); | |
58 | + Error.printError(Main.language == Main.Language.JP ? "制約に')'がありません" | |
59 | + : ") expected in constraints"); | |
53 | 60 | return null; |
54 | 61 | } |
55 | 62 | return res; |
@@ -58,20 +65,20 @@ public class Parse { | ||
58 | 65 | private Node expressionBody() throws OutOfTokenStreamException { |
59 | 66 | // 演算子の次のトークンが ( か どうかで判断 |
60 | 67 | // case 1: ( <> ( |
61 | - // case 2: ( <> [ foo, ( <> foo | |
68 | + // case 2: ( <> [ foo, ( <> foo | |
62 | 69 | String token = t.peepNextToken(); |
63 | - if (token == null) | |
70 | + if (token == null) | |
64 | 71 | throw new OutOfTokenStreamException(); |
65 | 72 | if (token.equals("(")) |
66 | 73 | return boolExpression(); |
67 | - else | |
74 | + else | |
68 | 75 | return atomExpression(); |
69 | 76 | } |
70 | 77 | |
71 | 78 | private Node boolExpression() throws OutOfTokenStreamException { |
72 | 79 | // boolean expression with operator |
73 | 80 | String token = t.peepToken(); |
74 | - if (t.peepToken() == null) | |
81 | + if (t.peepToken() == null) | |
75 | 82 | throw new OutOfTokenStreamException(); |
76 | 83 | if (token.equals("not")) |
77 | 84 | return notExpression(); |
@@ -87,7 +94,7 @@ public class Parse { | ||
87 | 94 | return ifExpression(); |
88 | 95 | else if (token.equals("ite")) |
89 | 96 | return iteExpression(); |
90 | - else | |
97 | + else | |
91 | 98 | Error.printError(token + " is not a valid operator"); |
92 | 99 | return null; // unreachable |
93 | 100 | } |
@@ -98,7 +105,7 @@ public class Parse { | ||
98 | 105 | res.Child = parseExpression(); |
99 | 106 | return res; |
100 | 107 | } |
101 | - | |
108 | + | |
102 | 109 | private Node equalityExpression() throws OutOfTokenStreamException { |
103 | 110 | BooleanBinaryOperator res = new EqualityOperator(); |
104 | 111 | t.getToken(); |
@@ -114,17 +121,17 @@ public class Parse { | ||
114 | 121 | res.Right = parseExpression(); |
115 | 122 | return res; |
116 | 123 | } |
117 | - | |
124 | + | |
118 | 125 | private Node orExpression() throws OutOfTokenStreamException { |
119 | 126 | BooleanMultinaryOperator res = new OrOperator(); |
120 | 127 | t.getToken(); |
121 | 128 | res.ChildList.add(parseExpression()); |
122 | 129 | res.ChildList.add(parseExpression()); |
123 | - if (t.peepToken() == null) | |
130 | + if (t.peepToken() == null) | |
124 | 131 | throw new OutOfTokenStreamException(); |
125 | 132 | while (t.peepToken().equals(")") == false) { |
126 | 133 | res.ChildList.add(parseExpression()); |
127 | - if (t.peepToken() == null) | |
134 | + if (t.peepToken() == null) | |
128 | 135 | throw new OutOfTokenStreamException(); |
129 | 136 | } |
130 | 137 | return res; |
@@ -135,16 +142,16 @@ public class Parse { | ||
135 | 142 | t.getToken(); |
136 | 143 | res.ChildList.add(parseExpression()); |
137 | 144 | res.ChildList.add(parseExpression()); |
138 | - if (t.peepToken() == null) | |
145 | + if (t.peepToken() == null) | |
139 | 146 | throw new OutOfTokenStreamException(); |
140 | 147 | while (t.peepToken().equals(")") == false) { |
141 | 148 | res.ChildList.add(parseExpression()); |
142 | - if (t.peepToken() == null) | |
149 | + if (t.peepToken() == null) | |
143 | 150 | throw new OutOfTokenStreamException(); |
144 | 151 | } |
145 | 152 | return res; |
146 | 153 | } |
147 | - | |
154 | + | |
148 | 155 | private Node ifExpression() throws OutOfTokenStreamException { |
149 | 156 | BooleanBinaryOperator res = new IfOperator(); |
150 | 157 | t.getToken(); |
@@ -152,7 +159,7 @@ public class Parse { | ||
152 | 159 | res.Right = parseExpression(); |
153 | 160 | return res; |
154 | 161 | } |
155 | - | |
162 | + | |
156 | 163 | private Node iteExpression() throws OutOfTokenStreamException { |
157 | 164 | BooleanTrinaryOperator res = new IfthenelseOperator(); |
158 | 165 | t.getToken(); |
@@ -161,53 +168,55 @@ public class Parse { | ||
161 | 168 | res.Right = parseExpression(); |
162 | 169 | return res; |
163 | 170 | } |
164 | - | |
165 | - private Node atomExpression() throws OutOfTokenStreamException { | |
171 | + | |
172 | + private Node atomExpression() throws OutOfTokenStreamException { | |
166 | 173 | // 次のトークンをチェック: 演算子でないといけない |
167 | 174 | String token = t.getToken(); |
168 | - if (token.equals("==")) | |
175 | + if (token.equals("==")) | |
169 | 176 | return equalityAtomExpression(); |
170 | - else if (token.equals("<>")) | |
177 | + else if (token.equals("<>")) | |
171 | 178 | return inequalityAtomExpression(); |
172 | - else | |
173 | - Error.printError("制約式に == か <> が必要です"); | |
179 | + else | |
180 | + Error.printError(Main.language == Main.Language.JP ? "制約式に == か <> が必要です" | |
181 | + : "== or <> expected in constraints"); | |
174 | 182 | return null; |
175 | 183 | } |
176 | 184 | |
177 | 185 | private Node inequalityAtomExpression() throws OutOfTokenStreamException { |
178 | 186 | BooleanUnaryOperator res = new NotOperator(); |
179 | - res.Child = equalityAtomExpression(); | |
187 | + res.Child = equalityAtomExpression(); | |
180 | 188 | return res; |
181 | 189 | } |
182 | 190 | |
183 | 191 | private Node equalityAtomExpression() throws OutOfTokenStreamException { |
184 | 192 | // case 1 val1 val2 |
185 | - // case 2 val1 [para1] | |
193 | + // case 2 val1 [para1] | |
186 | 194 | // case 3 [para1] val1 |
187 | 195 | // case 4 [para1] [para2] |
188 | 196 | String val1, val2, para1, para2; |
189 | 197 | String token1, token2; |
190 | - | |
198 | + | |
191 | 199 | token1 = t.peepToken(); |
192 | 200 | token2 = t.peepNextToken(); |
193 | - | |
194 | - if (token1 == null || token2 == null) | |
201 | + | |
202 | + if (token1 == null || token2 == null) | |
195 | 203 | throw new OutOfTokenStreamException(); |
196 | - | |
197 | - //case 1 | |
204 | + | |
205 | + // case 1 | |
198 | 206 | if ((token1.equals("[") == false) && (token2.equals("[") == false)) { |
199 | - val1 = t.getToken(); | |
207 | + val1 = t.getToken(); | |
200 | 208 | val2 = t.getToken(); |
201 | 209 | return compareValueAndValue(val1, val2); |
202 | 210 | } |
203 | - | |
204 | - //case 2 | |
211 | + | |
212 | + // case 2 | |
205 | 213 | if ((token1.equals("[") == false) && (token2.equals("[") == true)) { |
206 | 214 | val1 = t.getToken(); |
207 | 215 | t.getToken(); // must be [ |
208 | 216 | para1 = t.getToken(); |
209 | 217 | if (t.getToken().equals("]") == false) { |
210 | - Error.printError("制約式に]が必要です"); | |
218 | + Error.printError(Main.language == Main.Language.JP ? "制約式に]が必要です" | |
219 | + : "] expected in constraints"); | |
211 | 220 | } |
212 | 221 | return compareParameterAndValue(para1, val1); |
213 | 222 | } |
@@ -216,59 +225,79 @@ public class Parse { | ||
216 | 225 | t.getToken(); // must be "[" |
217 | 226 | para1 = t.getToken(); |
218 | 227 | if (t.getToken().equals("]") == false) { |
219 | - Error.printError("制約式に]が必要です"); | |
228 | + Error.printError(Main.language == Main.Language.JP ? "制約式に]が必要です" | |
229 | + : "] expected in constraints"); | |
220 | 230 | } |
221 | 231 | token1 = t.peepToken(); |
222 | - if (token1 == null) | |
232 | + if (token1 == null) | |
223 | 233 | throw new OutOfTokenStreamException(); |
224 | - | |
234 | + | |
225 | 235 | // case 3 |
226 | 236 | if (token1.equals("[") == false) { |
227 | 237 | val1 = t.getToken(); |
228 | 238 | return compareParameterAndValue(para1, val1); |
229 | 239 | } |
230 | - | |
240 | + | |
231 | 241 | // case 4 |
232 | 242 | t.getToken(); // must be [ |
233 | 243 | para2 = t.getToken(); |
234 | 244 | if (t.getToken().equals("]") == false) { |
235 | - Error.printError("制約式に]が必要です"); | |
245 | + Error.printError(Main.language == Main.Language.JP ? "制約式に]が必要です" | |
246 | + : "] expected in constraints"); | |
236 | 247 | } |
237 | 248 | return compareParameterAndParameter(para1, para2); |
238 | 249 | } |
239 | - | |
250 | + | |
240 | 251 | private Node compareValueAndValue(String val1, String val2) { |
241 | - if (val1.equals(val2)) | |
252 | + if (val1.equals(val2)) | |
242 | 253 | return new TrueValue(); |
243 | - else | |
254 | + else | |
244 | 255 | return new FalseValue(); |
245 | 256 | } |
246 | - | |
257 | + | |
247 | 258 | private Node compareParameterAndValue(String para, String val) { |
248 | 259 | int parameterID = 0; |
249 | 260 | Parameter p; |
250 | - int value = 0; | |
261 | + // int value = 0; | |
262 | + List<Integer> valueIDs = null; | |
263 | + | |
251 | 264 | // 因子名が正しいかチェック |
252 | 265 | try { |
253 | 266 | parameterID = parameterList.getID(para); |
254 | 267 | } catch (NoParameterNameException e) { |
255 | - Error.printError("制約中の因子名に誤りがあります"); | |
268 | + Error.printError(Main.language == Main.Language.JP ? "制約中の因子名に誤りがあります" | |
269 | + : "Invalid parameter name in constraints"); | |
256 | 270 | } |
257 | 271 | p = parameterList.get(parameterID); |
258 | - | |
272 | + | |
259 | 273 | // 値名が正しいかチェック |
260 | 274 | try { |
261 | - value = p.getID(val); | |
275 | + valueIDs = p.getID(val); | |
262 | 276 | } catch (NoValueNameException e) { |
263 | - Error.printError("制約中の値名に誤りがあります"); | |
264 | - } | |
265 | - | |
266 | - ComparisonOfParameterAndValue res = new EqualityOfParameterAndValue(); | |
267 | - res.p = parameterID; | |
268 | - res.v = value; | |
269 | - return res; | |
277 | + Error.printError(Main.language == Main.Language.JP ? "制約中の値名に誤りがあります" | |
278 | + : "Invalid parameter value in constraints"); | |
279 | + } | |
280 | + | |
281 | + // 値名に重複なし | |
282 | + if (valueIDs.size() == 1) { | |
283 | + ComparisonOfParameterAndValue res = new EqualityOfParameterAndValue(); | |
284 | + res.p = parameterID; | |
285 | + res.v = valueIDs.get(0); | |
286 | + return res; | |
287 | + } | |
288 | + // 値名に重複あり | |
289 | + else { | |
290 | + BooleanMultinaryOperator res = new OrOperator(); | |
291 | + for (Integer vid : valueIDs) { | |
292 | + ComparisonOfParameterAndValue child = new EqualityOfParameterAndValue(); | |
293 | + child.p = parameterID; | |
294 | + child.v = vid; | |
295 | + res.ChildList.add(child); | |
296 | + } | |
297 | + return res; | |
298 | + } | |
270 | 299 | } |
271 | - | |
300 | + | |
272 | 301 | private Node compareParameterAndParameter(String para1, String para2) { |
273 | 302 | int parameterID1 = 0; |
274 | 303 | int parameterID2 = 0; |
@@ -278,55 +307,243 @@ public class Parse { | ||
278 | 307 | parameterID1 = parameterList.getID(para1); |
279 | 308 | parameterID2 = parameterList.getID(para2); |
280 | 309 | } catch (NoParameterNameException e) { |
281 | - Error.printError("制約中の因子名に誤りがあります"); | |
310 | + Error.printError(Main.language == Main.Language.JP ? "制約中の因子名に誤りがあります" | |
311 | + : "Invalid parameter name in constraints"); | |
282 | 312 | } |
283 | 313 | p1 = parameterList.get(parameterID1); |
284 | 314 | p2 = parameterList.get(parameterID2); |
285 | - | |
286 | - List<String> commonValueName = new ArrayList<String>(p1.value_name); | |
287 | - commonValueName.retainAll(p2.value_name); | |
315 | + | |
316 | + // 値名が一致するペアを数える | |
317 | + int count = 0; | |
318 | + for (String valName1 : p1.value_name) { | |
319 | + for (String valName2 : p2.value_name) { | |
320 | + if (valName1.equals(valName2)) | |
321 | + count++; | |
322 | + } | |
323 | + } | |
288 | 324 | |
289 | 325 | // case 1: 値名で同じものがない |
290 | - if (commonValueName.size() == 0) | |
326 | + if (count == 0) | |
291 | 327 | return new FalseValue(); |
292 | - | |
328 | + | |
293 | 329 | // case 2: 値名で同じものがひとつ |
294 | - if (commonValueName.size() == 1) { | |
295 | - String valueName = commonValueName.get(0); | |
296 | - BooleanMultinaryOperator res = new AndOperator(); | |
297 | - ComparisonOfParameterAndValue sub1 = new EqualityOfParameterAndValue(); | |
298 | - ComparisonOfParameterAndValue sub2 = new EqualityOfParameterAndValue(); | |
299 | - try { | |
300 | - sub1.p = parameterID1; | |
301 | - sub1.v = p1.getID(valueName); | |
302 | - sub2.p = parameterID2; | |
303 | - sub2.v = p2.getID(valueName); | |
304 | - } catch (NoValueNameException e) { | |
305 | - Error.printError("内部エラー"); | |
330 | + if (count == 1) { | |
331 | + for (String valName1 : p1.value_name) { | |
332 | + for (String valName2 : p2.value_name) { | |
333 | + if (valName1.equals(valName2)) { | |
334 | + BooleanMultinaryOperator res = new AndOperator(); | |
335 | + ComparisonOfParameterAndValue sub1 = new EqualityOfParameterAndValue(); | |
336 | + ComparisonOfParameterAndValue sub2 = new EqualityOfParameterAndValue(); | |
337 | + try { | |
338 | + sub1.p = parameterID1; | |
339 | + sub1.v = p1.getID(valName1).get(0).byteValue(); // .size() | |
340 | + // should | |
341 | + // be | |
342 | + // 1 | |
343 | + sub2.p = parameterID2; | |
344 | + sub2.v = p2.getID(valName2).get(0).byteValue(); | |
345 | + } catch (NoValueNameException e) { | |
346 | + Error.printError("Inner error"); | |
347 | + } | |
348 | + res.ChildList.add(sub1); | |
349 | + res.ChildList.add(sub2); | |
350 | + return res; | |
351 | + } | |
352 | + } | |
306 | 353 | } |
307 | - res.ChildList.add(sub1); | |
308 | - res.ChildList.add(sub2); | |
309 | - return res; | |
310 | 354 | } |
311 | - | |
355 | + | |
312 | 356 | // case 3: 値名で同じものが2個以上 |
313 | 357 | BooleanMultinaryOperator res = new OrOperator(); |
314 | - for (String valueName: commonValueName) { | |
315 | - BooleanMultinaryOperator child = new AndOperator(); | |
316 | - ComparisonOfParameterAndValue sub1 = new EqualityOfParameterAndValue(); | |
317 | - ComparisonOfParameterAndValue sub2 = new EqualityOfParameterAndValue(); | |
318 | - try { | |
319 | - sub1.p = parameterID1; | |
320 | - sub1.v = p1.getID(valueName); | |
321 | - sub2.p = parameterID2; | |
322 | - sub2.v = p2.getID(valueName); | |
323 | - } catch (NoValueNameException e) { | |
324 | - Error.printError("内部エラー"); | |
358 | + for (int vid1 = 0; vid1 < p1.value_name.size(); vid1++) { | |
359 | + for (int vid2 = 0; vid2 < p2.value_name.size(); vid2++) { | |
360 | + if (p1.value_name.get(vid1).equals(p2.value_name.get(vid2))) { | |
361 | + BooleanMultinaryOperator child = new AndOperator(); | |
362 | + ComparisonOfParameterAndValue sub1 = new EqualityOfParameterAndValue(); | |
363 | + ComparisonOfParameterAndValue sub2 = new EqualityOfParameterAndValue(); | |
364 | + sub1.p = parameterID1; | |
365 | + sub1.v = vid1; | |
366 | + sub2.p = parameterID2; | |
367 | + sub2.v = vid2; | |
368 | + child.ChildList.add(sub1); | |
369 | + child.ChildList.add(sub2); | |
370 | + res.ChildList.add(child); | |
371 | + } | |
325 | 372 | } |
326 | - child.ChildList.add(sub1); | |
327 | - child.ChildList.add(sub2); | |
328 | - res.ChildList.add(child); | |
329 | 373 | } |
330 | 374 | return res; |
331 | 375 | } |
376 | + | |
332 | 377 | } |
378 | + | |
379 | +/* | |
380 | + * old one public class Parse { private TokenHandler t; private PList | |
381 | + * parameterList; Parse(TokenHandler t, PList parameterList) { this.t = t; | |
382 | + * this.parameterList = parameterList; } | |
383 | + * | |
384 | + * public Node parseExpression() { String token = t.peepToken(); try { if (token | |
385 | + * == null) { Error.printError(Main.language == Main.Language.JP ? "制約式に誤りがあります" | |
386 | + * : "Invalid constraints"); return null; } else if (token.equals("(")) return | |
387 | + * expressionWithParentheses(); else { // error Error.printError(Main.language | |
388 | + * == Main.Language.JP ? "制約に'('がありません" : "( expected in constraints"); return | |
389 | + * null; } } catch (OutOfTokenStreamException e) { | |
390 | + * Error.printError(Main.language == Main.Language.JP ? "制約式に誤りがあります" : | |
391 | + * "Invalid constraints"); return null; } } | |
392 | + * | |
393 | + * private Node expressionWithParentheses() throws OutOfTokenStreamException { | |
394 | + * Node res; // 戻り値 String token = t.getToken(); if (token.equals("(") == false) | |
395 | + * { // error // this block is unreachable Error.printError(Main.language == | |
396 | + * Main.Language.JP ? "制約に'('がありません" : "( expected in constraints"); return | |
397 | + * null; } // expression :: (expression) if (t.peepToken() == null) throw new | |
398 | + * OutOfTokenStreamException(); if (t.peepToken().equals("(")) res = | |
399 | + * expressionWithParentheses(); else // otherwise res = expressionBody(); // | |
400 | + * closed with ')' ? if (t.getToken().equals(")") == false) { // error | |
401 | + * Error.printError(Main.language == Main.Language.JP ? "制約に')'がありません" : | |
402 | + * ") expected in constraints"); return null; } return res; } | |
403 | + * | |
404 | + * private Node expressionBody() throws OutOfTokenStreamException { // | |
405 | + * 演算子の次のトークンが ( か どうかで判断 // case 1: ( <> ( // case 2: ( <> [ foo, ( <> foo | |
406 | + * String token = t.peepNextToken(); if (token == null) throw new | |
407 | + * OutOfTokenStreamException(); if (token.equals("(")) return boolExpression(); | |
408 | + * else return atomExpression(); } | |
409 | + * | |
410 | + * private Node boolExpression() throws OutOfTokenStreamException { // boolean | |
411 | + * expression with operator String token = t.peepToken(); if (t.peepToken() == | |
412 | + * null) throw new OutOfTokenStreamException(); if (token.equals("not")) return | |
413 | + * notExpression(); else if (token.equals("==")) return equalityExpression(); | |
414 | + * else if (token.equals("<>")) return inequalityExpression(); else if | |
415 | + * (token.equals("or")) return orExpression(); else if (token.equals("and")) | |
416 | + * return andExpression(); else if (token.equals("if")) return ifExpression(); | |
417 | + * else if (token.equals("ite")) return iteExpression(); else | |
418 | + * Error.printError(token + " is not a valid operator"); return null; // | |
419 | + * unreachable } | |
420 | + * | |
421 | + * private Node notExpression() throws OutOfTokenStreamException { | |
422 | + * BooleanUnaryOperator res = new NotOperator(); t.getToken(); res.Child = | |
423 | + * parseExpression(); return res; } | |
424 | + * | |
425 | + * private Node equalityExpression() throws OutOfTokenStreamException { | |
426 | + * BooleanBinaryOperator res = new EqualityOperator(); t.getToken(); res.Left = | |
427 | + * parseExpression(); res.Right = parseExpression(); return res; } | |
428 | + * | |
429 | + * private Node inequalityExpression() throws OutOfTokenStreamException { | |
430 | + * BooleanBinaryOperator res = new InequalityOperator(); t.getToken(); res.Left | |
431 | + * = parseExpression(); res.Right = parseExpression(); return res; } | |
432 | + * | |
433 | + * private Node orExpression() throws OutOfTokenStreamException { | |
434 | + * BooleanMultinaryOperator res = new OrOperator(); t.getToken(); | |
435 | + * res.ChildList.add(parseExpression()); res.ChildList.add(parseExpression()); | |
436 | + * if (t.peepToken() == null) throw new OutOfTokenStreamException(); while | |
437 | + * (t.peepToken().equals(")") == false) { res.ChildList.add(parseExpression()); | |
438 | + * if (t.peepToken() == null) throw new OutOfTokenStreamException(); } return | |
439 | + * res; } | |
440 | + * | |
441 | + * private Node andExpression() throws OutOfTokenStreamException { | |
442 | + * BooleanMultinaryOperator res = new AndOperator(); t.getToken(); | |
443 | + * res.ChildList.add(parseExpression()); res.ChildList.add(parseExpression()); | |
444 | + * if (t.peepToken() == null) throw new OutOfTokenStreamException(); while | |
445 | + * (t.peepToken().equals(")") == false) { res.ChildList.add(parseExpression()); | |
446 | + * if (t.peepToken() == null) throw new OutOfTokenStreamException(); } return | |
447 | + * res; } | |
448 | + * | |
449 | + * private Node ifExpression() throws OutOfTokenStreamException { | |
450 | + * BooleanBinaryOperator res = new IfOperator(); t.getToken(); res.Left = | |
451 | + * parseExpression(); res.Right = parseExpression(); return res; } | |
452 | + * | |
453 | + * private Node iteExpression() throws OutOfTokenStreamException { | |
454 | + * BooleanTrinaryOperator res = new IfthenelseOperator(); t.getToken(); res.Left | |
455 | + * = parseExpression(); res.Middle = parseExpression(); res.Right = | |
456 | + * parseExpression(); return res; } | |
457 | + * | |
458 | + * private Node atomExpression() throws OutOfTokenStreamException { // | |
459 | + * 次のトークンをチェック: 演算子でないといけない String token = t.getToken(); if (token.equals("==")) | |
460 | + * return equalityAtomExpression(); else if (token.equals("<>")) return | |
461 | + * inequalityAtomExpression(); else Error.printError(Main.language == | |
462 | + * Main.Language.JP ? "制約式に == か <> が必要です" : | |
463 | + * "== or <> expected in constraints"); return null; } | |
464 | + * | |
465 | + * private Node inequalityAtomExpression() throws OutOfTokenStreamException { | |
466 | + * BooleanUnaryOperator res = new NotOperator(); res.Child = | |
467 | + * equalityAtomExpression(); return res; } | |
468 | + * | |
469 | + * private Node equalityAtomExpression() throws OutOfTokenStreamException { // | |
470 | + * case 1 val1 val2 // case 2 val1 [para1] // case 3 [para1] val1 // case 4 | |
471 | + * [para1] [para2] String val1, val2, para1, para2; String token1, token2; | |
472 | + * | |
473 | + * token1 = t.peepToken(); token2 = t.peepNextToken(); | |
474 | + * | |
475 | + * if (token1 == null || token2 == null) throw new OutOfTokenStreamException(); | |
476 | + * | |
477 | + * //case 1 if ((token1.equals("[") == false) && (token2.equals("[") == false)) | |
478 | + * { val1 = t.getToken(); val2 = t.getToken(); return compareValueAndValue(val1, | |
479 | + * val2); } | |
480 | + * | |
481 | + * //case 2 if ((token1.equals("[") == false) && (token2.equals("[") == true)) { | |
482 | + * val1 = t.getToken(); t.getToken(); // must be [ para1 = t.getToken(); if | |
483 | + * (t.getToken().equals("]") == false) { Error.printError(Main.language == | |
484 | + * Main.Language.JP ? "制約式に]が必要です" : "] expected in constraints"); } return | |
485 | + * compareParameterAndValue(para1, val1); } | |
486 | + * | |
487 | + * // case 3, 4 t.getToken(); // must be "[" para1 = t.getToken(); if | |
488 | + * (t.getToken().equals("]") == false) { Error.printError(Main.language == | |
489 | + * Main.Language.JP ? "制約式に]が必要です" : "] expected in constraints"); } token1 = | |
490 | + * t.peepToken(); if (token1 == null) throw new OutOfTokenStreamException(); | |
491 | + * | |
492 | + * // case 3 if (token1.equals("[") == false) { val1 = t.getToken(); return | |
493 | + * compareParameterAndValue(para1, val1); } | |
494 | + * | |
495 | + * // case 4 t.getToken(); // must be [ para2 = t.getToken(); if | |
496 | + * (t.getToken().equals("]") == false) { Error.printError(Main.language == | |
497 | + * Main.Language.JP ? "制約式に]が必要です" : "] expected in constraints"); } return | |
498 | + * compareParameterAndParameter(para1, para2); } | |
499 | + * | |
500 | + * private Node compareValueAndValue(String val1, String val2) { if | |
501 | + * (val1.equals(val2)) return new TrueValue(); else return new FalseValue(); } | |
502 | + * | |
503 | + * private Node compareParameterAndValue(String para, String val) { int | |
504 | + * parameterID = 0; Parameter p; int value = 0; // 因子名が正しいかチェック try { | |
505 | + * parameterID = parameterList.getID(para); } catch (NoParameterNameException e) | |
506 | + * { Error.printError(Main.language == Main.Language.JP ? "制約中の因子名に誤りがあります" : | |
507 | + * "Invalid parameter name in constraints"); } p = | |
508 | + * parameterList.get(parameterID); | |
509 | + * | |
510 | + * // 値名が正しいかチェック try { value = p.getID(val); } catch (NoValueNameException e) { | |
511 | + * Error.printError(Main.language == Main.Language.JP ? "制約中の値名に誤りがあります" : | |
512 | + * "Invalid parameter value in constraints"); } | |
513 | + * | |
514 | + * ComparisonOfParameterAndValue res = new EqualityOfParameterAndValue(); res.p | |
515 | + * = parameterID; res.v = value; return res; } | |
516 | + * | |
517 | + * private Node compareParameterAndParameter(String para1, String para2) { int | |
518 | + * parameterID1 = 0; int parameterID2 = 0; Parameter p1, p2; // 因子名が正しいかチェック try | |
519 | + * { parameterID1 = parameterList.getID(para1); parameterID2 = | |
520 | + * parameterList.getID(para2); } catch (NoParameterNameException e) { | |
521 | + * Error.printError(Main.language == Main.Language.JP ? "制約中の因子名に誤りがあります" : | |
522 | + * "Invalid parameter name in constraints"); } p1 = | |
523 | + * parameterList.get(parameterID1); p2 = parameterList.get(parameterID2); | |
524 | + * | |
525 | + * List<String> commonValueName = new ArrayList<String>(p1.value_name); | |
526 | + * commonValueName.retainAll(p2.value_name); | |
527 | + * | |
528 | + * // case 1: 値名で同じものがない if (commonValueName.size() == 0) return new | |
529 | + * FalseValue(); | |
530 | + * | |
531 | + * // case 2: 値名で同じものがひとつ if (commonValueName.size() == 1) { String valueName = | |
532 | + * commonValueName.get(0); BooleanMultinaryOperator res = new AndOperator(); | |
533 | + * ComparisonOfParameterAndValue sub1 = new EqualityOfParameterAndValue(); | |
534 | + * ComparisonOfParameterAndValue sub2 = new EqualityOfParameterAndValue(); try { | |
535 | + * sub1.p = parameterID1; sub1.v = p1.getID(valueName); sub2.p = parameterID2; | |
536 | + * sub2.v = p2.getID(valueName); } catch (NoValueNameException e) { | |
537 | + * Error.printError("Inner error"); } res.ChildList.add(sub1); | |
538 | + * res.ChildList.add(sub2); return res; } | |
539 | + * | |
540 | + * // case 3: 値名で同じものが2個以上 BooleanMultinaryOperator res = new OrOperator(); for | |
541 | + * (String valueName: commonValueName) { BooleanMultinaryOperator child = new | |
542 | + * AndOperator(); ComparisonOfParameterAndValue sub1 = new | |
543 | + * EqualityOfParameterAndValue(); ComparisonOfParameterAndValue sub2 = new | |
544 | + * EqualityOfParameterAndValue(); try { sub1.p = parameterID1; sub1.v = | |
545 | + * p1.getID(valueName); sub2.p = parameterID2; sub2.v = p2.getID(valueName); } | |
546 | + * catch (NoValueNameException e) { Error.printError("Inner error"); } | |
547 | + * child.ChildList.add(sub1); child.ChildList.add(sub2); | |
548 | + * res.ChildList.add(child); } return res; } } | |
549 | + */ |
@@ -8,7 +8,6 @@ package v1; | ||
8 | 8 | * |
9 | 9 | */ |
10 | 10 | |
11 | - | |
12 | 11 | import java.io.BufferedWriter; |
13 | 12 | import java.io.IOException; |
14 | 13 | import java.util.LinkedList; |
@@ -16,19 +15,20 @@ import java.util.List; | ||
16 | 15 | |
17 | 16 | public class TestcaseHandler { |
18 | 17 | final int numOfParameters; |
18 | + | |
19 | 19 | TestcaseHandler(int numOfParameters) { |
20 | 20 | this.numOfParameters = numOfParameters; |
21 | 21 | } |
22 | - | |
22 | + | |
23 | 23 | Testcase getTestcase() { |
24 | 24 | return new Testcase(numOfParameters); |
25 | 25 | } |
26 | 26 | } |
27 | 27 | |
28 | 28 | class Testcase { |
29 | - byte[] value; // 0..level-1, or <0 (wildcard) | |
30 | - | |
31 | - //これを他から読んでるとまずいかも? | |
29 | + byte[] value; // 0..level-1, or <0 (wildcard) | |
30 | + | |
31 | + // これを他から読んでるとまずいかも? | |
32 | 32 | Testcase(int n) { |
33 | 33 | this.value = new byte[n]; |
34 | 34 | } |
@@ -44,16 +44,16 @@ class Testcase { | ||
44 | 44 | byte get(int parameter) { |
45 | 45 | return value[parameter]; |
46 | 46 | } |
47 | - | |
47 | + | |
48 | 48 | int getint(int parameter) { |
49 | 49 | return (int) value[parameter]; |
50 | 50 | } |
51 | - | |
51 | + | |
52 | 52 | void quantify() { |
53 | - for (int i = 0; i < this.value.length; i++) | |
53 | + for (int i = 0; i < this.value.length; i++) | |
54 | 54 | this.value[i] = -1; |
55 | 55 | } |
56 | - | |
56 | + | |
57 | 57 | Testcase makeClone() { |
58 | 58 | Testcase newtest = new Testcase(this.value.length); |
59 | 59 | for (int i = 0; i < newtest.value.length; i++) { |
@@ -61,58 +61,64 @@ class Testcase { | ||
61 | 61 | } |
62 | 62 | return newtest; |
63 | 63 | } |
64 | - | |
64 | + | |
65 | 65 | void print() { |
66 | - for (int i = 0; i < value.length; i++) | |
66 | + for (int i = 0; i < value.length; i++) | |
67 | 67 | System.err.print(value[i] + ","); |
68 | 68 | System.err.println(); |
69 | 69 | } |
70 | 70 | |
71 | - //TODO Outputer.java に移動 | |
72 | - void print(BufferedWriter writer, InputFileData inputfiledata) throws IOException { | |
73 | - for (int i = 0; i < value.length; i++) | |
74 | - writer.write((i == 0 ? "": ",") + inputfiledata.parameterList.get(i).value_name.get(value[i])); | |
71 | + // TODO Outputer.java に移動 | |
72 | + void print(BufferedWriter writer, InputFileData inputfiledata) | |
73 | + throws IOException { | |
74 | + for (int i = 0; i < value.length; i++) | |
75 | + writer.write((i == 0 ? "" : ",") | |
76 | + + inputfiledata.parameterList.get(i).value_name | |
77 | + .get(value[i])); | |
75 | 78 | writer.write("\n"); |
76 | 79 | } |
77 | 80 | |
78 | - // tupleを重ねる | |
79 | - // return true if a tuple is superimposed | |
80 | - // 重ねた時に禁則に違反することあり->チェックする | |
81 | - boolean superimpose(Testcase tuple, ConstraintHandler h) { | |
82 | - Testcase tmp = this.makeClone(); | |
83 | - if (tmp.superimpose(tuple) == false) | |
84 | - return false; | |
85 | - if (h.isPossible(tmp) == false) | |
86 | - return false; | |
87 | - return this.superimpose(tuple); | |
88 | - // must be true; | |
89 | - } | |
90 | - | |
91 | 81 | // tupleを重ねる |
92 | 82 | // return true if a tuple is superimposed |
93 | - // 重ねた時に禁則に違反することあり->チェックしない | |
83 | + // 重ねた時に禁則に違反することあり->チェックする | |
84 | + boolean superimpose(Testcase tuple, ConstraintHandler h) { | |
85 | + Testcase tmp = this.makeClone(); | |
86 | + if (tmp.superimpose(tuple) == false) | |
87 | + return false; | |
88 | + if (h.isPossible(tmp) == false) | |
89 | + return false; | |
90 | + return this.superimpose(tuple); | |
91 | + // must be true; | |
92 | + } | |
93 | + | |
94 | + // tupleを重ねる | |
95 | + // return true if a tuple is superimposed | |
96 | + // 重ねた時に禁則に違反することあり->チェックしない | |
94 | 97 | private boolean superimpose(Testcase tuple) { |
95 | 98 | // TODO Auto-generated method stu |
96 | - for (int i = 0 ; i < value.length; i++) { | |
97 | - if (value[i] < 0 || tuple.value[i] < 0) continue; | |
98 | - if (value[i] == tuple.value[i]) continue; | |
99 | + for (int i = 0; i < value.length; i++) { | |
100 | + if (value[i] < 0 || tuple.value[i] < 0) | |
101 | + continue; | |
102 | + if (value[i] == tuple.value[i]) | |
103 | + continue; | |
99 | 104 | return false; |
100 | 105 | } |
101 | 106 | |
102 | - for (int i = 0 ; i < value.length; i++) { | |
107 | + for (int i = 0; i < value.length; i++) { | |
103 | 108 | if (value[i] < 0) |
104 | 109 | this.set(i, tuple.get(i)); |
105 | 110 | } |
106 | 111 | return true; |
107 | - } | |
112 | + } | |
108 | 113 | } |
109 | 114 | |
110 | 115 | class Testsuite { |
111 | 116 | List<Testcase> test; |
117 | + | |
112 | 118 | Testsuite() { |
113 | 119 | test = new LinkedList<Testcase>(); |
114 | 120 | } |
115 | - | |
121 | + | |
116 | 122 | void add(Testcase newtest) { |
117 | 123 | this.test.add(newtest); |
118 | 124 | } |
@@ -5,10 +5,11 @@ import java.util.List; | ||
5 | 5 | public class TokenHandler { |
6 | 6 | final List<String> tokenList; |
7 | 7 | int index = 0; |
8 | - | |
8 | + | |
9 | 9 | TokenHandler(List<String> tokenList) { |
10 | 10 | this.tokenList = tokenList; |
11 | 11 | } |
12 | + | |
12 | 13 | // 次のToken を取り出す |
13 | 14 | String getToken() throws OutOfTokenStreamException { |
14 | 15 | if (index >= tokenList.size()) |
@@ -16,14 +17,16 @@ public class TokenHandler { | ||
16 | 17 | String str = tokenList.get(index++); |
17 | 18 | return str; |
18 | 19 | } |
20 | + | |
19 | 21 | // 次のToken を見る.取り出さない |
20 | - String peepToken() { | |
22 | + String peepToken() { | |
21 | 23 | if (index >= tokenList.size()) |
22 | 24 | return null; |
23 | 25 | return tokenList.get(index); |
24 | 26 | } |
27 | + | |
25 | 28 | // 次の次のToken を見る.取り出さない |
26 | - String peepNextToken() { | |
29 | + String peepNextToken() { | |
27 | 30 | if (index + 1 >= tokenList.size()) |
28 | 31 | return null; |
29 | 32 | return tokenList.get(index + 1); |