-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathLoader.java
179 lines (161 loc) · 5.95 KB
/
Loader.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
import java.io.*;
import java.util.*;
public class Loader {
private static void checkInputConstraint(boolean val) throws InvalidInputException {
// this method throws `InvalidInputException` when `val` is false
if(val == false) {
System.out.println("INVALID INPUT");
throw new InvalidInputException();
}
}
public static Graph load(String path) throws InvalidInputException, IOException {
// load a CNF file, parse, and return a `Graph` object
try {
BufferedReader br = new BufferedReader(new FileReader(path));
String problemLine = skipToProblemLine(br);
int[] nums = parseProblemLine(problemLine);
int numOfVars = nums[0];
int numOfClauses = nums[1];
return readClauses(br, numOfVars, numOfClauses);
} catch(FileNotFoundException e) {
checkInputConstraint(false);
return null;
}
}
private static String skipToProblemLine(BufferedReader br) throws InvalidInputException, IOException {
// skip all the comment lines
String line = "c";
while(line.charAt(0) == 'c') {
line = br.readLine();
}
checkInputConstraint(line != null);
return line;
}
private static int[] parseProblemLine(String line) throws InvalidInputException, IOException {
// process the problem line
final String reference = "p cnf ";
String[] words = line.split(" ");
checkInputConstraint(
words.length == 4 &&
words[0].equals("p") &&
words[1].equals("cnf")
);
int numOfVars = Integer.parseInt(words[2]);
int numOfClauses = Integer.parseInt(words[3]);
return new int[]{numOfVars, numOfClauses};
}
private static Graph readClauses(
BufferedReader br,
int numOfVars,
int numOfClauses
) throws InvalidInputException, IOException {
// process the clauses
// build the clauses string
StringBuilder remaining = new StringBuilder();
String line = "";
while(true) {
line = br.readLine();
if(line != null) {
remaining.append(line + '\n');
} else {
break;
}
}
// do the parsing
List<List<Integer>> edges = new ArrayList<List<Integer>>();
String clausesString = remaining.toString();
boolean allowMinus = true;
boolean allowDigit = true;
boolean allowWhite = false;
boolean negSign = false;
StringBuilder accumulator = new StringBuilder();
List<Integer> literals = new ArrayList<Integer>(2);
for(int i = 0; i < clausesString.length(); i++) {
char c = clausesString.charAt(i);
boolean isDigit = Character.isDigit(c);
boolean isWhite = Character.isWhitespace(c);
if(c == '-'){
checkInputConstraint(allowMinus);
// set negSign
negSign = true;
// expect a digit
allowMinus = false;
allowDigit = true;
allowWhite = false;
} else if (isDigit) {
checkInputConstraint(allowDigit);
// add character to accumulator to be parsed
accumulator.append(c);
// expect more digits or a whitespace
allowMinus = false;
allowDigit = true;
allowWhite = true;
} else if (isWhite) {
checkInputConstraint(allowWhite);
// parse current accumulator, and clean it up
Integer id = Integer.parseInt(accumulator.toString());
accumulator = new StringBuilder();
// do something with the last token
if(id == 0) {
// add current pair to edges, and clean it up
checkInputConstraint(literals.size() == 2);
edges.add(
List.of(
-literals.get(0),
literals.get(1)
)
);
edges.add(
List.of(
-literals.get(1),
literals.get(0)
)
);
literals = new ArrayList<Integer>(2);
} else if(id <= numOfVars) {
// add the last token to current pair
if(negSign) {
id *= -1;
}
literals.add(Integer.valueOf(id));
} else {
// something's wrong
checkInputConstraint(false);
}
// reset negSign, expect literal
negSign = false;
allowMinus = true;
allowDigit = true;
allowWhite = false;
} else {
// invalid char
checkInputConstraint(false);
}
}
if(literals.size() > 0) {
// add current pair to edges
checkInputConstraint(literals.size() == 2);
edges.add(
List.of(
-literals.get(0),
literals.get(1)
)
);
edges.add(
List.of(
-literals.get(1),
literals.get(0)
)
);
}
// check if the number of clauses is satisfied
checkInputConstraint(numOfClauses * 2 == edges.size());
// create all literals vertices
List<Integer> vertices = new ArrayList<Integer>(numOfVars);
for(int i = 1; i <= numOfVars; i++) {
vertices.add(i);
vertices.add(-i);
}
return new Graph(vertices, edges);
}
}