1 | // ********************************************************************* |
---|
2 | // Copyright 2000-2004, Princeton University. All rights reserved. |
---|
3 | // By using this software the USER indicates that he or she has read, |
---|
4 | // understood and will comply with the following: |
---|
5 | // |
---|
6 | // --- Princeton University hereby grants USER nonexclusive permission |
---|
7 | // to use, copy and/or modify this software for internal, noncommercial, |
---|
8 | // research purposes only. Any distribution, including commercial sale |
---|
9 | // or license, of this software, copies of the software, its associated |
---|
10 | // documentation and/or modifications of either is strictly prohibited |
---|
11 | // without the prior consent of Princeton University. Title to copyright |
---|
12 | // to this software and its associated documentation shall at all times |
---|
13 | // remain with Princeton University. Appropriate copyright notice shall |
---|
14 | // be placed on all software copies, and a complete copy of this notice |
---|
15 | // shall be included in all copies of the associated documentation. |
---|
16 | // No right is granted to use in advertising, publicity or otherwise |
---|
17 | // any trademark, service mark, or the name of Princeton University. |
---|
18 | // |
---|
19 | // |
---|
20 | // --- This software and any associated documentation is provided "as is" |
---|
21 | // |
---|
22 | // PRINCETON UNIVERSITY MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS |
---|
23 | // OR IMPLIED, INCLUDING THOSE OF MERCHANTABILITY OR FITNESS FOR A |
---|
24 | // PARTICULAR PURPOSE, OR THAT USE OF THE SOFTWARE, MODIFICATIONS, OR |
---|
25 | // ASSOCIATED DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, |
---|
26 | // TRADEMARKS OR OTHER INTELLECTUAL PROPERTY RIGHTS OF A THIRD PARTY. |
---|
27 | // |
---|
28 | // Princeton University shall not be liable under any circumstances for |
---|
29 | // any direct, indirect, special, incidental, or consequential damages |
---|
30 | // with respect to any claim by USER or any third party on account of |
---|
31 | // or arising from the use, or inability to use, this software or its |
---|
32 | // associated documentation, even if Princeton University has been advised |
---|
33 | // of the possibility of those damages. |
---|
34 | // ********************************************************************* |
---|
35 | |
---|
36 | #include <iostream> |
---|
37 | #include <fstream> |
---|
38 | #include <cstdlib> |
---|
39 | #include <cstdio> |
---|
40 | #include <cstring> |
---|
41 | #include <set> |
---|
42 | #include <vector> |
---|
43 | |
---|
44 | using namespace std; |
---|
45 | |
---|
46 | #include "SAT.h" |
---|
47 | |
---|
48 | const int MAX_LINE_LENGTH = 65536; |
---|
49 | const int MAX_WORD_LENGTH = 64; |
---|
50 | |
---|
51 | void read_cnf_omit(SAT_Manager mng, char * filename, vector<int> & omit) { |
---|
52 | char line_buffer[MAX_LINE_LENGTH]; |
---|
53 | char word_buffer[MAX_WORD_LENGTH]; |
---|
54 | set<int> clause_vars; |
---|
55 | set<int> clause_lits; |
---|
56 | unsigned omit_idx = 0; |
---|
57 | int line_num = 0; |
---|
58 | ifstream inp(filename, ios::in); |
---|
59 | if (!inp) { |
---|
60 | cerr << "Can't open input file" << endl; |
---|
61 | exit(1); |
---|
62 | } |
---|
63 | int cl_id = -1; |
---|
64 | while (inp.getline(line_buffer, MAX_LINE_LENGTH)) { |
---|
65 | ++line_num; |
---|
66 | if (line_buffer[0] == 'c') { |
---|
67 | continue; |
---|
68 | } |
---|
69 | else if (line_buffer[0] == 'p') { |
---|
70 | int var_num; |
---|
71 | int cl_num; |
---|
72 | int arg = sscanf(line_buffer, "p cnf %d %d", &var_num, &cl_num); |
---|
73 | if (arg < 2) { |
---|
74 | cerr << "Unable to read number of variables and clauses" |
---|
75 | << "at line " << line_num << endl; |
---|
76 | exit(3); |
---|
77 | } |
---|
78 | SAT_SetNumVariables(mng, var_num); // first element not used. |
---|
79 | } else { // Clause definition or continuation |
---|
80 | char *lp = line_buffer; |
---|
81 | do { |
---|
82 | char *wp = word_buffer; |
---|
83 | while (*lp && ((*lp == ' ') || (*lp == '\t'))) { |
---|
84 | lp++; |
---|
85 | } |
---|
86 | while (*lp && (*lp != ' ') && (*lp != '\t') && (*lp != '\n')) { |
---|
87 | *(wp++) = *(lp++); |
---|
88 | } |
---|
89 | *wp = '\0'; // terminate string |
---|
90 | |
---|
91 | if (strlen(word_buffer) != 0) { // check if number is there |
---|
92 | int var_idx = atoi(word_buffer); |
---|
93 | int sign = 0; |
---|
94 | |
---|
95 | if (var_idx != 0) { |
---|
96 | if (var_idx < 0) { |
---|
97 | var_idx = -var_idx; |
---|
98 | sign = 1; |
---|
99 | } |
---|
100 | clause_vars.insert(var_idx); |
---|
101 | clause_lits.insert((var_idx << 1) + sign); |
---|
102 | } else { |
---|
103 | // add this clause |
---|
104 | ++cl_id; |
---|
105 | if (omit_idx < omit.size()-1 && omit[omit_idx] < cl_id ) |
---|
106 | ++omit_idx; |
---|
107 | if (omit_idx < omit.size()) { |
---|
108 | if (omit[omit_idx] == cl_id) { |
---|
109 | clause_lits.clear(); |
---|
110 | clause_vars.clear(); |
---|
111 | } |
---|
112 | } |
---|
113 | if (clause_vars.size() != 0 && |
---|
114 | clause_vars.size() == clause_lits.size()) { |
---|
115 | vector <int> temp; |
---|
116 | for (set<int>::iterator itr = clause_lits.begin(); |
---|
117 | itr != clause_lits.end(); ++itr) { |
---|
118 | temp.push_back(*itr); |
---|
119 | } |
---|
120 | SAT_AddClause(mng, & temp.begin()[0], temp.size() ); |
---|
121 | } |
---|
122 | clause_lits.clear(); |
---|
123 | clause_vars.clear(); |
---|
124 | } |
---|
125 | } |
---|
126 | } |
---|
127 | while (*lp); |
---|
128 | } |
---|
129 | } |
---|
130 | if (!inp.eof()) { |
---|
131 | cerr << "Input line " << line_num << " too long. Unable to continue..." |
---|
132 | << endl; |
---|
133 | exit(2); |
---|
134 | } |
---|
135 | |
---|
136 | if (clause_lits.size() && clause_vars.size() == clause_lits.size()) { |
---|
137 | vector <int> temp; |
---|
138 | for (set<int>::iterator itr = clause_lits.begin(); |
---|
139 | itr != clause_lits.end(); ++itr) { |
---|
140 | temp.push_back(*itr); |
---|
141 | } |
---|
142 | SAT_AddClause(mng, & temp.begin()[0], temp.size() ); |
---|
143 | } |
---|
144 | clause_lits.clear(); |
---|
145 | clause_vars.clear(); |
---|
146 | } |
---|
147 | |
---|
148 | int get_num_clause(char * filename) { |
---|
149 | char line_buffer[MAX_LINE_LENGTH]; |
---|
150 | ifstream inp(filename, ios::in); |
---|
151 | if (!inp) { |
---|
152 | cerr << "Can't open input file" << endl; |
---|
153 | exit(1); |
---|
154 | } |
---|
155 | while (inp.getline(line_buffer, MAX_LINE_LENGTH)) { |
---|
156 | if (inp.fail()) { |
---|
157 | cerr << "Too large an input line. Unable to continue..." << endl; |
---|
158 | exit(2); |
---|
159 | } |
---|
160 | if (line_buffer[0] == 'p') { |
---|
161 | int var_num; |
---|
162 | int cl_num; |
---|
163 | int arg = sscanf(line_buffer, "p cnf %d %d", &var_num, &cl_num); |
---|
164 | if (arg < 2) { |
---|
165 | cerr << "Unable to read number of variables and clauses" << endl; |
---|
166 | exit(3); |
---|
167 | } |
---|
168 | return cl_num; |
---|
169 | } |
---|
170 | } |
---|
171 | cerr << "Can't find the header in CNF: p cnf NumVar NumCls " << endl; |
---|
172 | exit(1); |
---|
173 | return 0; |
---|
174 | } |
---|
175 | |
---|
176 | void handle_result(SAT_Manager mng, int outcome, char * filename) { |
---|
177 | string result = "UNKNOWN"; |
---|
178 | switch (outcome) { |
---|
179 | case SATISFIABLE: |
---|
180 | cout << "Instance satisfiable" << endl; |
---|
181 | // following lines will print out a solution if a solution exist |
---|
182 | for (unsigned i = 1, sz = SAT_NumVariables(mng); i <= sz; ++i) { |
---|
183 | switch (SAT_GetVarAsgnment(mng, i)) { |
---|
184 | case -1: |
---|
185 | cout << "(" << i<< ")"; |
---|
186 | break; |
---|
187 | case 0: |
---|
188 | cout << "-" << i; |
---|
189 | break; |
---|
190 | case 1: |
---|
191 | cout << i; |
---|
192 | break; |
---|
193 | default: |
---|
194 | cerr << "Unknown variable value state"<< endl; |
---|
195 | exit(4); |
---|
196 | } |
---|
197 | cout << " "; |
---|
198 | } |
---|
199 | result = "SAT"; |
---|
200 | cout << endl; |
---|
201 | break; |
---|
202 | case UNSATISFIABLE: |
---|
203 | result = "UNSAT"; |
---|
204 | cout << "Instance unsatisfiable" << endl; |
---|
205 | break; |
---|
206 | case TIME_OUT: |
---|
207 | result = "ABORT : TIME OUT"; |
---|
208 | cout << "Time out, unable to determine the outcome of the instance"; |
---|
209 | cout << endl; |
---|
210 | break; |
---|
211 | case MEM_OUT: |
---|
212 | result = "ABORT : MEM OUT"; |
---|
213 | cout << "Memory out, unable to determine the outcome of the instance"; |
---|
214 | cout << endl; |
---|
215 | break; |
---|
216 | default: |
---|
217 | cerr << "Unknown outcome" << endl; |
---|
218 | exit(5); |
---|
219 | } |
---|
220 | cout << "Max Decision Level\t\t\t" << SAT_MaxDLevel(mng) << endl; |
---|
221 | cout << "Num. of Decisions\t\t\t" << SAT_NumDecisions(mng) << endl; |
---|
222 | cout << "Num. of Variables\t\t\t" << SAT_NumVariables(mng) << endl; |
---|
223 | cout << "Original Num Clauses\t\t\t" << SAT_InitNumClauses(mng) << endl; |
---|
224 | cout << "Original Num Literals\t\t\t" << SAT_InitNumLiterals(mng) << endl; |
---|
225 | cout << "Added Conflict Clauses\t\t\t" << SAT_NumAddedClauses(mng) - |
---|
226 | SAT_InitNumClauses(mng)<< endl; |
---|
227 | cout << "Added Conflict Literals\t\t\t" << SAT_NumAddedLiterals(mng) - |
---|
228 | SAT_InitNumLiterals(mng) << endl; |
---|
229 | cout << "Deleted Unrelevant clause\t\t" << SAT_NumDeletedClauses(mng) <<endl; |
---|
230 | cout << "Deleted Unrelevant literals\t\t" <<SAT_NumDeletedLiterals(mng) <<endl; |
---|
231 | cout << "Number of Implication\t\t\t" << SAT_NumImplications(mng)<< endl; |
---|
232 | |
---|
233 | // other statistics comes here |
---|
234 | cout << "Total Run Time\t\t\t\t" << SAT_GetCPUTime(mng) << endl << endl; |
---|
235 | cout << result << endl; |
---|
236 | } |
---|
237 | |
---|
238 | void output_status(SAT_Manager mng) { |
---|
239 | cout << "Dec: " << SAT_NumDecisions(mng) << "\t "; |
---|
240 | cout << "AddCl: " << SAT_NumAddedClauses(mng) << "\t"; |
---|
241 | cout << "AddLit: " << SAT_NumAddedLiterals(mng) << "\t"; |
---|
242 | cout << "DelCl: " << SAT_NumDeletedClauses(mng) << "\t"; |
---|
243 | cout << "DelLit: " << SAT_NumDeletedLiterals(mng) << "\t"; |
---|
244 | cout << "NumImp: " << SAT_NumImplications(mng) << "\t"; |
---|
245 | cout << "AveBubbleMove: " << SAT_AverageBubbleMove(mng) << "\t"; |
---|
246 | // other statistics comes here |
---|
247 | cout << "RunTime:" << SAT_GetElapsedCPUTime(mng) << endl; |
---|
248 | } |
---|
249 | |
---|
250 | void verify_solution(SAT_Manager mng) { |
---|
251 | int num_verified = 0; |
---|
252 | for (int cl_idx = SAT_GetFirstClause (mng); cl_idx >= 0; |
---|
253 | cl_idx = SAT_GetNextClause(mng, cl_idx)) { |
---|
254 | int len = SAT_GetClauseNumLits(mng, cl_idx); |
---|
255 | int * lits = new int[len+1]; |
---|
256 | SAT_GetClauseLits(mng, cl_idx, lits); |
---|
257 | int i; |
---|
258 | for (i = 0; i < len; ++i) { |
---|
259 | int v_idx = lits[i] >> 1; |
---|
260 | int sign = lits[i] & 0x1; |
---|
261 | int var_value = SAT_GetVarAsgnment(mng, v_idx); |
---|
262 | if ((var_value == 1 && sign == 0) || |
---|
263 | (var_value == 0 && sign == 1)) |
---|
264 | break; |
---|
265 | } |
---|
266 | if (i >= len) { |
---|
267 | cerr << "Verify Satisfiable solution failed, please " |
---|
268 | << "file a bug report, thanks. " << endl; |
---|
269 | exit(6); |
---|
270 | } |
---|
271 | delete [] lits; |
---|
272 | ++num_verified; |
---|
273 | } |
---|
274 | cout << num_verified << " Clauses are true, Verify Solution successful. "; |
---|
275 | } |
---|
276 | |
---|
277 | int main(int argc, char ** argv) { |
---|
278 | if (argc != 2) { |
---|
279 | cerr << "ZMinimal: Find Minimal Core. " << endl; |
---|
280 | cerr << "Copyright 2003-2004, Princeton University" << endl << endl; |
---|
281 | cerr << "Usage: "<< argv[0] << " cnf_file " << endl; |
---|
282 | return 2; |
---|
283 | } |
---|
284 | vector<int> omit; |
---|
285 | int num_cls = get_num_clause(argv[1]); |
---|
286 | cout << "Total : " << num_cls << " passes"; |
---|
287 | for (int i = 0; i < num_cls; ++i) { |
---|
288 | if (i % 50 == 0) |
---|
289 | cout << endl << i << ":\t"; |
---|
290 | if (i % 10 == 0) |
---|
291 | cout << " "; |
---|
292 | cout.flush(); |
---|
293 | SAT_Manager mng = SAT_InitManager(); |
---|
294 | omit.push_back(i); |
---|
295 | read_cnf_omit(mng, argv[1], omit); |
---|
296 | int result = SAT_Solve(mng); |
---|
297 | if (result != SATISFIABLE) { |
---|
298 | cout << "*" ; |
---|
299 | } else { |
---|
300 | cout << "-"; |
---|
301 | omit.pop_back(); |
---|
302 | } |
---|
303 | cout.flush(); |
---|
304 | SAT_ReleaseManager(mng); |
---|
305 | } |
---|
306 | cout << endl; |
---|
307 | cout << "Instance Cls: " << num_cls << " MinCore Cls: " |
---|
308 | << num_cls - omit.size() << " Diff: " << omit.size() << endl; |
---|
309 | cout << "Unneeded clauses are: "; |
---|
310 | for (unsigned i = 0; i < omit.size(); ++i) { |
---|
311 | if (i % 20 == 0) |
---|
312 | cout << endl; |
---|
313 | cout << omit[i] << " "; |
---|
314 | } |
---|
315 | cout << endl; |
---|
316 | return 0; |
---|
317 | } |
---|