1use std::io::{self, BufRead, Write};
3
4use anyhow::Error;
5
6use varisat_formula::{Lit, Var};
7
8use crate::vli_enc::{read_u64, write_u64};
9
10use super::{ClauseHash, DeleteClauseProof, ProofStep};
11
12macro_rules! step_codes {
13 ($counter:expr, $name:ident, ) => {
14 const $name: u64 = $counter;
15 };
16 ($counter:expr, $name:ident, $($names:ident),* ,) => {
17 const $name: u64 = $counter;
18 step_codes!($counter + 1, $($names),* ,);
19 };
20}
21
22step_codes!(
23 0,
24 CODE_SOLVER_VAR_NAME_UPDATE,
25 CODE_SOLVER_VAR_NAME_REMOVE,
26 CODE_USER_VAR_NAME_UPDATE,
27 CODE_USER_VAR_NAME_REMOVE,
28 CODE_DELETE_VAR,
29 CODE_CHANGE_SAMPLING_MODE_SAMPLE,
30 CODE_CHANGE_SAMPLING_MODE_WITNESS,
31 CODE_AT_CLAUSE_RED,
32 CODE_AT_CLAUSE_IRRED,
33 CODE_UNIT_CLAUSES,
34 CODE_DELETE_CLAUSE_REDUNDANT,
35 CODE_DELETE_CLAUSE_SIMPLIFIED,
36 CODE_DELETE_CLAUSE_SATISFIED,
37 CODE_CHANGE_HASH_BITS,
38 CODE_MODEL,
39 CODE_ADD_CLAUSE,
40 CODE_ASSUMPTIONS,
41 CODE_FAILED_ASSUMPTIONS,
42);
43
44const CODE_END: u64 = 0x9ac3391f4294c211;
47
48pub fn write_step<'s>(target: &mut impl Write, step: &'s ProofStep<'s>) -> io::Result<()> {
50 match *step {
51 ProofStep::SolverVarName { global, solver } => {
52 if let Some(solver) = solver {
53 write_u64(&mut *target, CODE_SOLVER_VAR_NAME_UPDATE)?;
54 write_u64(&mut *target, global.index() as u64)?;
55 write_u64(&mut *target, solver.index() as u64)?;
56 } else {
57 write_u64(&mut *target, CODE_SOLVER_VAR_NAME_REMOVE)?;
58 write_u64(&mut *target, global.index() as u64)?;
59 }
60 }
61
62 ProofStep::UserVarName { global, user } => {
63 if let Some(user) = user {
64 write_u64(&mut *target, CODE_USER_VAR_NAME_UPDATE)?;
65 write_u64(&mut *target, global.index() as u64)?;
66 write_u64(&mut *target, user.index() as u64)?;
67 } else {
68 write_u64(&mut *target, CODE_USER_VAR_NAME_REMOVE)?;
69 write_u64(&mut *target, global.index() as u64)?;
70 }
71 }
72
73 ProofStep::DeleteVar { var } => {
74 write_u64(&mut *target, CODE_DELETE_VAR)?;
75 write_u64(&mut *target, var.index() as u64)?;
76 }
77
78 ProofStep::ChangeSamplingMode { var, sample } => {
79 if sample {
80 write_u64(&mut *target, CODE_CHANGE_SAMPLING_MODE_SAMPLE)?;
81 } else {
82 write_u64(&mut *target, CODE_CHANGE_SAMPLING_MODE_WITNESS)?;
83 }
84 write_u64(&mut *target, var.index() as u64)?;
85 }
86
87 ProofStep::AddClause { clause } => {
88 write_u64(&mut *target, CODE_ADD_CLAUSE)?;
89 write_literals(&mut *target, clause)?;
90 }
91
92 ProofStep::AtClause {
93 redundant,
94 clause,
95 propagation_hashes,
96 } => {
97 if redundant {
98 write_u64(&mut *target, CODE_AT_CLAUSE_RED)?;
99 } else {
100 write_u64(&mut *target, CODE_AT_CLAUSE_IRRED)?;
101 }
102 write_literals(&mut *target, clause)?;
103 write_hashes(&mut *target, propagation_hashes)?;
104 }
105
106 ProofStep::UnitClauses { units } => {
107 write_u64(&mut *target, CODE_UNIT_CLAUSES)?;
108 write_unit_clauses(&mut *target, units)?;
109 }
110
111 ProofStep::DeleteClause { clause, proof } => {
112 match proof {
113 DeleteClauseProof::Redundant => {
114 write_u64(&mut *target, CODE_DELETE_CLAUSE_REDUNDANT)?;
115 }
116 DeleteClauseProof::Simplified => {
117 write_u64(&mut *target, CODE_DELETE_CLAUSE_SIMPLIFIED)?;
118 }
119 DeleteClauseProof::Satisfied => {
120 write_u64(&mut *target, CODE_DELETE_CLAUSE_SATISFIED)?;
121 }
122 }
123
124 write_literals(&mut *target, clause)?;
125 }
126
127 ProofStep::ChangeHashBits { bits } => {
128 write_u64(&mut *target, CODE_CHANGE_HASH_BITS)?;
129 write_u64(&mut *target, bits as u64)?;
130 }
131
132 ProofStep::Model { assignment } => {
133 write_u64(&mut *target, CODE_MODEL)?;
134 write_literals(&mut *target, assignment)?;
135 }
136
137 ProofStep::Assumptions { assumptions } => {
138 write_u64(&mut *target, CODE_ASSUMPTIONS)?;
139 write_literals(&mut *target, assumptions)?;
140 }
141
142 ProofStep::FailedAssumptions {
143 failed_core,
144 propagation_hashes,
145 } => {
146 write_u64(&mut *target, CODE_FAILED_ASSUMPTIONS)?;
147 write_literals(&mut *target, failed_core)?;
148 write_hashes(&mut *target, propagation_hashes)?;
149 }
150
151 ProofStep::End => {
152 write_u64(&mut *target, CODE_END)?;
153 }
154 }
155
156 Ok(())
157}
158
159#[derive(Default)]
160pub struct Parser {
161 lit_buf: Vec<Lit>,
162 hash_buf: Vec<ClauseHash>,
163 unit_buf: Vec<(Lit, ClauseHash)>,
164}
165
166impl Parser {
167 pub fn parse_step<'a>(&'a mut self, source: &mut impl BufRead) -> Result<ProofStep<'a>, Error> {
168 let code = read_u64(&mut *source)?;
169 match code {
170 CODE_SOLVER_VAR_NAME_UPDATE => {
171 let global = Var::from_index(read_u64(&mut *source)? as usize);
172 let solver = Some(Var::from_index(read_u64(&mut *source)? as usize));
173 Ok(ProofStep::SolverVarName { global, solver })
174 }
175 CODE_SOLVER_VAR_NAME_REMOVE => {
176 let global = Var::from_index(read_u64(&mut *source)? as usize);
177 Ok(ProofStep::SolverVarName {
178 global,
179 solver: None,
180 })
181 }
182 CODE_USER_VAR_NAME_UPDATE => {
183 let global = Var::from_index(read_u64(&mut *source)? as usize);
184 let user = Some(Var::from_index(read_u64(&mut *source)? as usize));
185 Ok(ProofStep::UserVarName { global, user })
186 }
187 CODE_USER_VAR_NAME_REMOVE => {
188 let global = Var::from_index(read_u64(&mut *source)? as usize);
189 Ok(ProofStep::UserVarName { global, user: None })
190 }
191 CODE_DELETE_VAR => {
192 let var = Var::from_index(read_u64(&mut *source)? as usize);
193 Ok(ProofStep::DeleteVar { var })
194 }
195 CODE_CHANGE_SAMPLING_MODE_SAMPLE | CODE_CHANGE_SAMPLING_MODE_WITNESS => {
196 let var = Var::from_index(read_u64(&mut *source)? as usize);
197 Ok(ProofStep::ChangeSamplingMode {
198 var,
199 sample: code == CODE_CHANGE_SAMPLING_MODE_SAMPLE,
200 })
201 }
202 CODE_ADD_CLAUSE => {
203 read_literals(&mut *source, &mut self.lit_buf)?;
204 Ok(ProofStep::AddClause {
205 clause: &self.lit_buf,
206 })
207 }
208 CODE_AT_CLAUSE_IRRED | CODE_AT_CLAUSE_RED => {
209 read_literals(&mut *source, &mut self.lit_buf)?;
210 read_hashes(&mut *source, &mut self.hash_buf)?;
211 Ok(ProofStep::AtClause {
212 redundant: code == CODE_AT_CLAUSE_RED,
213 clause: &self.lit_buf,
214 propagation_hashes: &self.hash_buf,
215 })
216 }
217 CODE_UNIT_CLAUSES => {
218 read_unit_clauses(&mut *source, &mut self.unit_buf)?;
219 Ok(ProofStep::UnitClauses {
220 units: &self.unit_buf,
221 })
222 }
223 CODE_DELETE_CLAUSE_REDUNDANT
224 | CODE_DELETE_CLAUSE_SIMPLIFIED
225 | CODE_DELETE_CLAUSE_SATISFIED => {
226 let proof = match code {
227 CODE_DELETE_CLAUSE_REDUNDANT => DeleteClauseProof::Redundant,
228 CODE_DELETE_CLAUSE_SIMPLIFIED => DeleteClauseProof::Simplified,
229 CODE_DELETE_CLAUSE_SATISFIED => DeleteClauseProof::Satisfied,
230 _ => unreachable!(),
231 };
232 read_literals(&mut *source, &mut self.lit_buf)?;
233 Ok(ProofStep::DeleteClause {
234 clause: &self.lit_buf,
235 proof,
236 })
237 }
238 CODE_CHANGE_HASH_BITS => {
239 let bits = read_u64(&mut *source)? as u32;
240 Ok(ProofStep::ChangeHashBits { bits })
241 }
242 CODE_MODEL => {
243 read_literals(&mut *source, &mut self.lit_buf)?;
244 Ok(ProofStep::Model {
245 assignment: &self.lit_buf,
246 })
247 }
248 CODE_ASSUMPTIONS => {
249 read_literals(&mut *source, &mut self.lit_buf)?;
250 Ok(ProofStep::Assumptions {
251 assumptions: &self.lit_buf,
252 })
253 }
254 CODE_FAILED_ASSUMPTIONS => {
255 read_literals(&mut *source, &mut self.lit_buf)?;
256 read_hashes(&mut *source, &mut self.hash_buf)?;
257 Ok(ProofStep::FailedAssumptions {
258 failed_core: &self.lit_buf,
259 propagation_hashes: &self.hash_buf,
260 })
261 }
262 CODE_END => Ok(ProofStep::End),
263 _ => anyhow::bail!("parse error"),
264 }
265 }
266}
267
268fn write_literals(target: &mut impl Write, literals: &[Lit]) -> io::Result<()> {
270 write_u64(&mut *target, literals.len() as u64)?;
271 for &lit in literals {
272 write_u64(&mut *target, lit.code() as u64)?;
273 }
274 Ok(())
275}
276
277fn read_literals(source: &mut impl BufRead, literals: &mut Vec<Lit>) -> Result<(), io::Error> {
279 literals.clear();
280 let len = read_u64(&mut *source)? as usize;
281 literals.reserve(len);
282 for _ in 0..len {
283 literals.push(Lit::from_code(read_u64(&mut *source)? as usize));
284 }
285 Ok(())
286}
287
288fn write_hashes(target: &mut impl Write, hashes: &[ClauseHash]) -> io::Result<()> {
290 write_u64(&mut *target, hashes.len() as u64)?;
291 for &hash in hashes {
292 write_u64(&mut *target, hash as u64)?;
293 }
294 Ok(())
295}
296
297fn read_hashes(source: &mut impl BufRead, hashes: &mut Vec<ClauseHash>) -> Result<(), io::Error> {
299 hashes.clear();
300 let len = read_u64(&mut *source)? as usize;
301 hashes.reserve(len);
302 for _ in 0..len {
303 hashes.push(read_u64(&mut *source)? as ClauseHash);
304 }
305 Ok(())
306}
307
308fn write_unit_clauses(target: &mut impl Write, units: &[(Lit, ClauseHash)]) -> io::Result<()> {
310 write_u64(&mut *target, units.len() as u64)?;
311 for &(lit, hash) in units {
312 write_u64(&mut *target, lit.code() as u64)?;
313 write_u64(&mut *target, hash as u64)?;
314 }
315 Ok(())
316}
317
318fn read_unit_clauses(
320 source: &mut impl BufRead,
321 units: &mut Vec<(Lit, ClauseHash)>,
322) -> Result<(), io::Error> {
323 units.clear();
324 let len = read_u64(&mut *source)? as usize;
325 units.reserve(len);
326 for _ in 0..len {
327 let lit = Lit::from_code(read_u64(&mut *source)? as usize);
328 let hash = read_u64(&mut *source)? as ClauseHash;
329 units.push((lit, hash));
330 }
331 Ok(())
332}