1use rustc_hash::FxHashSet;
22
23use nom::bytes::complete::tag;
24use nom::character::complete::{char, line_ending, multispace0, space0, space1, u64};
25use nom::combinator::{consumed, cut, eof, value};
26use nom::error::{ContextError, ErrorKind, FromExternalError, ParseError, context};
27use nom::multi::many0_count;
28use nom::sequence::{preceded, terminated};
29use nom::{Err, IResult};
30
31use crate::util::{
32 self, MAX_CAPACITY, context_loc, eol, fail, fail_with_contexts, line_span, word, word_span,
33};
34use crate::{ParseOptions, Problem, Tree, Var, VarSet};
35
36#[allow(clippy::upper_case_acronyms)]
39#[derive(Clone, Copy, PartialEq, Eq, Debug)]
40enum Format {
41 CNF,
42 SAT { xor: bool, eq: bool },
43}
44#[rustfmt::skip]
45const SAT: Format = Format::SAT { xor: false, eq: false };
46#[rustfmt::skip]
47const SATX: Format = Format::SAT { xor: true, eq: false };
48#[rustfmt::skip]
49const SATE: Format = Format::SAT { xor: false, eq: false };
50#[rustfmt::skip]
51const SATEX: Format = Format::SAT { xor: true, eq: true };
52
53fn format<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
54 input: &'a [u8],
55) -> IResult<&'a [u8], Format, E> {
56 let inner = |input: &'a [u8]| match input {
57 [b'c', b'n', b'f', r @ ..] => Ok((r, Format::CNF)),
58 [b's', b'a', b't', b'e', b'x', r @ ..] => Ok((r, SATEX)),
59 [b's', b'a', b't', b'e', r @ ..] => Ok((r, SATE)),
60 [b's', b'a', b't', b'x', r @ ..] => Ok((r, SATX)),
61 [b's', b'a', b't', r @ ..] => Ok((r, SAT)),
62 _ => Err(Err::Error(E::from_error_kind(input, ErrorKind::Alt))),
63 };
64
65 context_loc(
66 || word_span(input),
67 "format must be one of 'cnf', 'sat', 'satx', 'sate', or 'satex'",
68 word(inner),
69 )(input)
70}
71
72fn problem_line<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
78 input: &'a [u8],
79) -> IResult<&'a [u8], ((&'a [u8], Format), (&'a [u8], usize), (&'a [u8], usize)), E> {
80 let inner = |input| {
81 let (input, _) = context(
82 "all lines in the preamble must begin with 'c' or 'p'",
83 cut(char('p')),
84 )(input)?;
85 let (input, _) = space1(input)?;
86 let (input, fmt) = consumed(format)(input)?;
87 let (input, _) = space1(input)?;
88 let (input, num_vars) = consumed(u64)(input)?;
89 if num_vars.1 > MAX_CAPACITY {
90 return fail(num_vars.0, "too many variables");
91 }
92 let num_vars = (num_vars.0, num_vars.1 as usize);
93 if fmt.1 == Format::CNF {
94 let msg = "expected the number of clauses (CNF format)";
95 let (input, _) = context(msg, space1)(input)?;
96 let (input, num_clauses) = context_loc(|| word_span(input), msg, consumed(u64))(input)?;
97 if num_clauses.1 > MAX_CAPACITY {
98 return fail(num_clauses.0, "too many clauses");
99 }
100 let num_clauses = (num_clauses.0, num_clauses.1 as usize);
101 let (input, _) = space0(input)?;
102 value((fmt, num_vars, num_clauses), line_ending)(input)
103 } else {
104 let (input, _) = space0(input)?;
105 context(
106 "expected a line break (SAT formats do not take a number of clauses)",
107 value((fmt, num_vars, ([].as_slice(), 0)), line_ending),
108 )(input)
109 }
110 };
111
112 context_loc(
113 || line_span(input),
114 "problem line must have format 'p <format> <#vars> [<#clauses>]'",
115 cut(inner),
116 )(input)
117}
118
119#[derive(Clone, PartialEq, Eq, Debug)]
120struct Preamble {
121 format: Format,
122 vars: VarSet,
123 num_clauses: usize,
125 clause_tree: Option<Tree<usize>>,
126}
127
128fn preamble<'a, E>(
137 parse_var_order: bool,
138 parse_clause_tree: bool,
139) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Preamble, E>
140where
141 E: ParseError<&'a [u8]> + ContextError<&'a [u8]> + FromExternalError<&'a [u8], String>,
142{
143 move |mut input| {
144 if parse_var_order || parse_clause_tree {
147 let mut vars = VarSet {
148 len: 0,
149 order: Vec::new(),
150 order_tree: None,
151 names: Vec::new(),
152 };
153
154 let mut max_var_span = [].as_slice(); let mut tree_max_var = ([].as_slice(), 0); let mut name_set: FxHashSet<&str> = Default::default();
157
158 let mut clause_tree = None;
160 let mut clause_order_span = [].as_slice();
161 let mut max_clause = ([].as_slice(), 0); loop {
164 let next_input = match preceded(char::<_, E>('c'), space1)(input) {
165 Ok((i, _)) => i,
166 Err(_) => break,
167 };
168 if let Ok((next_input, _)) = preceded(tag("co"), space1::<_, E>)(next_input) {
169 if parse_clause_tree {
170 if clause_tree.is_some() {
171 return fail(line_span(input), "clause order may only be given once");
172 }
173 let t: Tree<usize>;
174 (input, (clause_order_span, (t, max_clause))) =
175 terminated(consumed(util::tree(false, false)), eol)(next_input)?;
176 clause_tree = Some(t);
177 } else {
178 input = match memchr::memchr(b'\n', input) {
179 Some(i) => &input[i + 1..],
180 None => &input[input.len()..],
181 };
182 }
183 } else if let Ok((next_input, _)) = preceded(tag("vo"), space1::<_, E>)(next_input)
184 {
185 if vars.order_tree.is_some() {
187 let msg = "variable order tree may only be given once";
188 return fail(line_span(input), msg);
189 }
190 let t: Tree<Var>;
191 (input, (t, tree_max_var)) =
192 terminated(util::tree(true, true), eol)(next_input)?;
193
194 vars.order.clear();
196 vars.order.reserve(tree_max_var.1 + 1);
197 t.flatten_into(&mut vars.order);
198 vars.order_tree = Some(t);
199 } else if let Ok((next_input, ((var_span, var), name))) =
200 util::var_order_record::<E>(next_input)
201 {
202 input = next_input;
204 if var == 0 {
205 return fail(var_span, "variable number must be greater than 0");
206 }
207 if var > MAX_CAPACITY {
208 return fail(var_span, "variable number too large");
209 }
210
211 let num_vars = var as usize;
212 let var = num_vars - 1;
213
214 if num_vars > vars.names.len() {
215 vars.names.resize(num_vars, None);
216 vars.order.reserve(num_vars - vars.names.len());
217 max_var_span = var_span;
218 } else if vars.names[var].is_some() {
219 return fail(var_span, "second occurrence of variable in order");
220 }
221 vars.names[var] = Some(if let Some(name) = name {
223 let Ok(name) = std::str::from_utf8(name) else {
224 return fail(name, "invalid UTF-8");
225 };
226 if !name_set.insert(name) {
227 return fail(name.as_bytes(), "second occurrence of variable name");
228 }
229 name.to_owned()
230 } else {
231 String::new()
232 });
233 if vars.order_tree.is_none() {
234 vars.order.push(var);
235 }
236 } else {
237 return fail(
238 line_span(input),
239 "expected a variable order record ('c <var> [<name>]'), a variable order tree ('c vo <tree>'), or a clause order tree ('c co <tree>')",
240 );
241 }
242 }
243
244 if vars.order_tree.is_none() && vars.names.len() != vars.order.len() {
245 return fail_with_contexts([
246 (input, "expected another variable order line"),
247 (max_var_span, "note: maximal variable number given here"),
248 ]);
249 }
250
251 let (next_input, (format, num_vars, num_clauses)) = problem_line(input)?;
252 if vars.order_tree.is_none() {
253 if !vars.order.is_empty() && num_vars.1 != vars.order.len() {
254 return fail_with_contexts([
255 (num_vars.0, "number of variables does not match"),
256 (max_var_span, "note: maximal variable number given here"),
257 ]);
258 }
259 } else {
260 if num_vars.1 != tree_max_var.1 + 1 {
261 return fail_with_contexts([
262 (num_vars.0, "number of variables does not match"),
263 (tree_max_var.0, "note: maximal variable number given here"),
264 ]);
265 }
266 if vars.names.len() > num_vars.1 {
267 return fail_with_contexts([
268 (max_var_span, "name assigned to non-existing variable"),
269 (num_vars.0, "note: number of variables given here"),
270 ]);
271 }
272 }
273
274 if clause_tree.is_some() {
275 if format.1 != Format::CNF {
276 let msg0 = "clause tree only supported for 'cnf' format";
277 return fail_with_contexts([
278 (clause_order_span, msg0),
279 (format.0, "note: format given here"),
280 ]);
281 }
282 if max_clause.1 != num_clauses.1 - 1 {
283 return fail_with_contexts([
284 (num_clauses.0, "number of clauses does not match"),
285 (max_clause.0, "note: maximal clause number given here"),
286 ]);
287 }
288 }
289
290 while let Some(name) = vars.names.last() {
292 if !name.as_ref().is_some_and(String::is_empty) {
293 break;
294 }
295 vars.names.pop();
296 }
297 for name in &mut vars.names {
298 if name.as_ref().is_some_and(String::is_empty) {
299 *name = None;
300 }
301 }
302
303 vars.len = num_vars.1;
304 #[cfg(debug_assertions)]
305 vars.check_valid();
306 let preamble = Preamble {
307 format: format.1,
308 vars,
309 num_clauses: num_clauses.1,
310 clause_tree,
311 };
312 Ok((next_input, preamble))
313 } else {
314 let (input, (format, num_vars, num_clauses)) =
315 preceded(many0_count(util::comment), problem_line)(input)?;
316 let preamble = Preamble {
317 format: format.1,
318 vars: VarSet::new(num_vars.1),
319 num_clauses: num_clauses.1,
320 clause_tree: None,
321 };
322 Ok((input, preamble))
323 }
324 }
325}
326
327mod cnf {
328 use nom::branch::alt;
329 use nom::character::complete::{char, multispace0, one_of, u64};
330 use nom::combinator::{consumed, eof, iterator, map, recognize};
331 use nom::error::{ContextError, ErrorKind, FromExternalError, ParseError, context};
332 use nom::sequence::preceded;
333 use nom::{Err, IResult};
334
335 use crate::util::fail;
336 use crate::{Circuit, GateKind, Literal, Problem, Tree};
337
338 use super::Preamble;
339
340 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
341 enum CNFTokenKind {
342 Int(u64),
343 Neg,
344 Xor,
345 }
346
347 #[derive(Clone, PartialEq, Eq, Debug)]
348 struct CNFToken<'a> {
349 span: &'a [u8],
350 kind: CNFTokenKind,
351 }
352
353 fn lex<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
354 input: &'a [u8],
355 ) -> IResult<&'a [u8], CNFToken<'a>, E> {
356 let tok = alt((
357 map(consumed(u64), |(span, n)| CNFToken {
358 span,
359 kind: CNFTokenKind::Int(n),
360 }),
361 map(recognize(char('-')), |span| CNFToken {
362 span,
363 kind: CNFTokenKind::Neg,
364 }),
365 map(recognize(one_of("xX")), |span| CNFToken {
366 span,
367 kind: CNFTokenKind::Xor,
368 }),
369 ));
370
371 preceded(multispace0, tok)(input)
372 }
373
374 fn make_conj_tree(
375 circuit: &mut Circuit,
376 conjuncts: &[Literal],
377 tree: Tree<usize>,
378 stack: &mut Vec<Literal>,
379 ) -> Literal {
380 match tree {
381 Tree::Inner(children) => {
382 let saved_stack_len = stack.len();
383 for child in children {
384 let l = make_conj_tree(circuit, conjuncts, child, stack);
385 stack.push(l);
386 }
387 let root = circuit.push_gate(GateKind::And);
388 circuit.push_gate_inputs(stack[saved_stack_len..].iter().copied());
389 stack.truncate(saved_stack_len);
390 root
391 }
392 Tree::Leaf(i) => conjuncts[i],
393 }
394 }
395
396 pub fn parse<'a, E>(
397 preamble: Preamble,
398 ) -> impl FnOnce(&'a [u8]) -> IResult<&'a [u8], Problem, E>
399 where
400 E: ParseError<&'a [u8]> + ContextError<&'a [u8]> + FromExternalError<&'a [u8], String>,
401 {
402 move |input| {
403 let Preamble {
404 vars,
405 num_clauses,
406 clause_tree: clause_order_tree,
407 ..
408 } = preamble;
409 let num_vars = vars.len();
410 let mut circuit = Circuit::new(vars);
411 circuit.push_gate(GateKind::Or);
412
413 let mut neg = false;
414
415 let mut it = iterator(input, lex::<E>);
416 for token in &mut it {
417 match token.kind {
418 CNFTokenKind::Int(0) => {
419 circuit.push_gate(GateKind::Or);
420 }
421 CNFTokenKind::Int(n) => {
422 if n > num_vars as u64 {
423 return fail(token.span, "variables must be in range [1, #vars]");
424 }
425 circuit.push_gate_input(Literal::from_input(neg, (n - 1) as usize));
426 neg = false;
427 }
428 CNFTokenKind::Neg if !neg => neg = true,
429 CNFTokenKind::Neg => return fail(token.span, "expected a variable"),
430 CNFTokenKind::Xor => {
431 if let Some(gate) = circuit.last_gate() {
432 if !gate.inputs.is_empty() {
433 return fail(
434 token.span,
435 "XOR clauses must be marked as such at the beginning of the clause",
436 );
437 }
438 circuit.set_last_gate_kind(GateKind::Xor);
439 }
440 }
441 }
442 }
443
444 let (input, ()) = it.finish()?;
445 let (input, _) = multispace0(input)?;
446 let (input, _) = context("expected a literal or '0'", eof)(input)?;
447
448 let num_gates = circuit.num_gates();
449 if num_gates != num_clauses {
450 if num_gates == num_clauses + 1 && circuit.last_gate().unwrap().inputs.is_empty() {
453 circuit.pop_gate();
454 } else {
455 return Err(Err::Failure(E::from_external_error(
456 input,
457 ErrorKind::Fail,
458 format!("expected {num_clauses} clauses, got {num_gates}"),
459 )));
460 }
461 }
462 let num_gates = circuit.num_gates(); let root = if num_gates == 0 {
465 Literal::TRUE
466 } else {
467 let mut is_false = false;
468 let mut conj = Vec::with_capacity(num_gates);
469 let mut gate = 0;
470 circuit.retain_gates(|inputs| {
471 if is_false {
472 return false;
473 }
474 match inputs {
475 [] => {
476 is_false = true;
477 false
478 }
479 [l] => {
480 conj.push(*l);
481 false
482 }
483 _ => {
484 conj.push(Literal::from_gate(false, gate));
485 gate += 1;
486 true
487 }
488 }
489 });
490
491 if is_false {
492 circuit.clear_gates();
493 Literal::FALSE
494 } else if let Some(tree) = clause_order_tree {
495 let mut stack = Vec::with_capacity(num_clauses);
496 make_conj_tree(&mut circuit, &conj, tree, &mut stack)
497 } else {
498 let root = circuit.push_gate(GateKind::And);
499 circuit.push_gate_inputs(conj);
500 root
501 }
502 };
503
504 Ok((
505 input,
506 Problem {
507 circuit,
508 details: crate::ProblemDetails::Root(root),
509 },
510 ))
511 }
512 }
513}
514
515mod sat {
516 use nom::Err;
517 use nom::IResult;
518 use nom::branch::alt;
519 use nom::bytes::complete::tag;
520 use nom::character::complete::{char, multispace0, u64};
521 use nom::combinator::{consumed, map, recognize, value};
522 use nom::error::{ContextError, ErrorKind, ParseError};
523
524 use crate::util::{fail, map_res_fail, word};
525 use crate::{Circuit, GateKind, Literal, Problem, ProblemDetails, Var, VarSet};
526
527 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
528 enum TokenKind {
529 Var(Var),
530 Lpar,
531 Rpar,
532 Neg,
533 And,
534 Or,
535 Xor,
536 Eq,
537 }
538
539 #[derive(Clone, PartialEq, Eq, Debug)]
540 struct Token<'a> {
541 span: &'a [u8],
542 kind: TokenKind,
543 }
544
545 macro_rules! match_tok {
546 ($matcher:expr, $tok:ident) => {
547 map(recognize($matcher), |span| {
548 Some(Token {
549 span,
550 kind: TokenKind::$tok,
551 })
552 })
553 };
554 }
555
556 fn lex<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
557 num_vars: usize,
558 ) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Option<Token<'a>>, E> {
559 move |input| {
560 let (input, _) = multispace0(input)?; if input.is_empty() {
562 return Ok((input, None));
563 }
564 alt((
565 map_res_fail(consumed(u64), |(span, n)| {
566 if n == 0 || n > num_vars as u64 {
567 Err((span, "variables must be in range [1, #vars]"))
568 } else {
569 Ok(Some(Token {
570 span,
571 kind: TokenKind::Var(n as usize),
572 }))
573 }
574 }),
575 match_tok!(char('('), Lpar),
576 match_tok!(char(')'), Rpar),
577 match_tok!(char('-'), Neg),
578 match_tok!(char('*'), And),
579 match_tok!(char('+'), Or),
580 match_tok!(word(tag("xor")), Xor),
581 match_tok!(char('='), Eq),
582 ))(input)
583 }
584 }
585
586 #[derive(Debug)]
587 enum SatParserErr<'a, E> {
588 E(E),
589 Rpar { input: &'a [u8], span: &'a [u8] },
590 }
591 impl<'a, E: ParseError<&'a [u8]>> ParseError<&'a [u8]> for SatParserErr<'a, E> {
592 fn from_error_kind(input: &'a [u8], kind: ErrorKind) -> Self {
593 Self::E(E::from_error_kind(input, kind))
594 }
595
596 fn append(input: &'a [u8], kind: ErrorKind, other: Self) -> Self {
597 match other {
598 Self::E(other) => Self::E(E::append(input, kind, other)),
599 Self::Rpar { .. } => unreachable!(),
600 }
601 }
602 }
603 impl<'a, E: ContextError<&'a [u8]>> ContextError<&'a [u8]> for SatParserErr<'a, E> {
604 fn add_context(input: &'a [u8], ctx: &'static str, other: Self) -> Self {
605 match other {
606 Self::E(other) => Self::E(E::add_context(input, ctx, other)),
607 Self::Rpar { .. } => other,
608 }
609 }
610 }
611
612 fn expect<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
613 kind: TokenKind,
614 err: &'static str,
615 num_vars: usize,
616 ) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], (), E> {
617 move |input| {
618 let (input, tok) = lex(num_vars)(input)?;
619 match tok {
620 None => fail(input, err),
621 Some(tok) if tok.kind != kind => fail(tok.span, err),
622 _ => Ok((input, ())),
623 }
624 }
625 }
626
627 fn formula<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
628 allow_xor: bool,
629 allow_eq: bool,
630 circuit: &mut Circuit,
631 stack: &mut Vec<Literal>,
632 input: &'a [u8],
633 ) -> IResult<&'a [u8], Literal, SatParserErr<'a, E>> {
634 let num_vars = circuit.inputs().len();
635 let (input, tok) = lex(num_vars)(input)?;
636 let tok = match tok {
637 Some(tok) => tok,
638 None => return fail(input, "expected a formula"),
639 };
640
641 match tok.kind {
642 TokenKind::Var(n) => Ok((input, Literal::from_input(false, n - 1))),
643 TokenKind::Lpar => {
644 let (input, l) = formula(allow_xor, allow_eq, circuit, stack, input)?;
645 value(l, expect(TokenKind::Rpar, "expected ')'", num_vars))(input)
646 }
647 TokenKind::Rpar => Err(Err::Error(SatParserErr::Rpar {
648 input,
649 span: tok.span,
650 })),
651 TokenKind::Neg => {
652 let (input, tok) = lex(num_vars)(input)?;
653 let tok = match tok {
654 Some(t) => t,
655 None => return fail(input, "expected a variable or '('"),
656 };
657 match tok.kind {
658 TokenKind::Var(n) => Ok((input, Literal::from_input(true, n - 1))),
659 TokenKind::Lpar => {
660 let (input, l) = formula(allow_xor, allow_eq, circuit, stack, input)?;
661 value(!l, expect(TokenKind::Rpar, "expected ')'", num_vars))(input)
662 }
663 _ => fail(tok.span, "expected a variable or '('"),
664 }
665 }
666 TokenKind::Xor if !allow_xor => fail(
667 tok.span,
668 "'xor' is only allowed in formats 'satx' and 'satex'",
669 ),
670 TokenKind::Eq if !allow_eq => fail(
671 tok.span,
672 "'=' is only allowed in formats 'sate' and 'satex'",
673 ),
674 _ => {
675 let (mut input, ()) = expect(TokenKind::Lpar, "expected '('", num_vars)(input)?;
676
677 let saved_stack_len = stack.len();
678 let input = loop {
679 match formula(allow_xor, allow_eq, circuit, stack, input) {
680 Ok((i, sub)) => {
681 input = i;
682 stack.push(sub)
683 }
684 Err(Err::Error(SatParserErr::Rpar { input, .. })) => break input,
685 Err(f) => {
686 stack.truncate(saved_stack_len);
687 return Err(f);
688 }
689 }
690 };
691
692 let children = &stack[saved_stack_len..];
693 let literal = match children {
694 [] => match tok.kind {
695 TokenKind::And | TokenKind::Eq => Literal::TRUE,
696 TokenKind::Or | TokenKind::Xor => Literal::FALSE,
697 _ => unreachable!(),
698 },
699 [l] => *l,
700 _ => {
701 let l = circuit.push_gate(match tok.kind {
702 TokenKind::And => GateKind::And,
703 TokenKind::Or => GateKind::Or,
704 _ => GateKind::Xor,
705 });
706
707 circuit.push_gate_inputs(children.iter().copied());
708
709 if tok.kind == TokenKind::Eq && children.len().is_multiple_of(2) {
710 !l
711 } else {
712 l
713 }
714 }
715 };
716 stack.truncate(saved_stack_len);
717
718 Ok((input, literal))
719 }
720 }
721 }
722
723 pub fn parse<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
724 vars: VarSet,
725 allow_xor: bool,
726 allow_eq: bool,
727 ) -> impl FnOnce(&'a [u8]) -> IResult<&'a [u8], Problem, E> {
728 let num_vars = vars.len();
729 let mut circuit = Circuit::new(vars);
730 let mut stack = Vec::with_capacity(2 * num_vars);
731 move |input| match formula(allow_xor, allow_eq, &mut circuit, &mut stack, input) {
732 Ok((input, root)) => Ok((
733 input,
734 Problem {
735 circuit,
736 details: ProblemDetails::Root(root),
737 },
738 )),
739 Err(e) => Err(e.map(|e| match e {
740 SatParserErr::E(e) => e,
741 SatParserErr::Rpar { input, span } => E::add_context(
742 span,
743 "expected a formula",
744 E::from_error_kind(input, ErrorKind::Fail),
745 ),
746 })),
747 }
748 }
749}
750
751pub fn parse<'a, E>(options: &ParseOptions) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Problem, E>
753where
754 E: ParseError<&'a [u8]> + ContextError<&'a [u8]> + FromExternalError<&'a [u8], String>,
755{
756 let parse_var_order = options.var_order;
757 let parse_clause_tree = options.clause_tree;
758 move |input| {
759 let (input, preamble) = preamble(parse_var_order, parse_clause_tree)(input)?;
760 match preamble.format {
761 Format::CNF => cnf::parse(preamble)(input),
762 Format::SAT { xor, eq } => {
763 let (input, res) = sat::parse(preamble.vars, xor, eq)(input)?;
764 let (input, _) = context(
765 "expected end of file (SAT files may only contain a single formula)",
766 preceded(multispace0, eof),
767 )(input)?;
768 Ok((input, res))
769 }
770 }
771 }
772}
773
774#[cfg(test)]
775mod tests {
776 use nom::Finish;
777
778 use crate::util::test::*;
779 use crate::{Gate, Literal};
780
781 use super::*;
782
783 #[test]
784 fn example_cnf() {
785 let input = "c Example CNF format file
786c
787p cnf 4 3
7881 3 -4 0
7894 0 2
790-3";
791 let (input, problem) = parse::<()>(&OPTS_NO_ORDER)(input.as_bytes())
792 .finish()
793 .unwrap();
794 assert!(input.is_empty());
795
796 let (circuit, root) = unwrap_problem(problem);
797 let inputs = circuit.inputs();
798 assert_eq!(inputs.len(), 4);
799 assert!(inputs.order().is_none());
800
801 assert_eq!(root, g(2));
802 assert_eq!(circuit.gate(root), Some(Gate::and(&[g(0), v(3), g(1)])));
803 assert_eq!(circuit.gate(g(0)), Some(Gate::or(&[v(0), v(2), !v(3)])));
804 assert_eq!(circuit.gate(g(1)), Some(Gate::or(&[v(1), !v(2)])));
805 }
806
807 #[test]
808 fn example_cnf_0term() {
809 let input = "c Example CNF format file
810c
811p cnf 4 3
8121 3 -4 0
8134 0 2
814-3 0";
815 let (input, problem) = parse::<()>(&OPTS_NO_ORDER)(input.as_bytes())
816 .finish()
817 .unwrap();
818 assert!(input.is_empty());
819
820 let (circuit, root) = unwrap_problem(problem);
821 let inputs = circuit.inputs();
822 assert_eq!(inputs.len(), 4);
823 assert!(inputs.order().is_none());
824
825 assert_eq!(root, g(2));
826 assert_eq!(circuit.gate(root), Some(Gate::and(&[g(0), v(3), g(1)])));
827 assert_eq!(circuit.gate(g(0)), Some(Gate::or(&[v(0), v(2), !v(3)])));
828 assert_eq!(circuit.gate(g(1)), Some(Gate::or(&[v(1), !v(2)])));
829 }
830
831 #[test]
832 fn empty_cnf() {
833 let input = "p cnf 0 0\n";
834 let (input, problem) = parse::<()>(&OPTS_NO_ORDER)(input.as_bytes())
835 .finish()
836 .unwrap();
837 assert!(input.is_empty());
838
839 let (circuit, root) = unwrap_problem(problem);
840 let inputs = circuit.inputs();
841 assert_eq!(inputs.len(), 0);
842
843 assert_eq!(root, Literal::TRUE);
844 }
845
846 #[test]
847 fn example_sat() {
848 let input = "c Sample SAT format
849c
850p sat 4
851(*(+(1 3 -4)
852 +(4)
853 +(2 3)))";
854 let (input, problem) = parse::<()>(&OPTS_NO_ORDER)(input.as_bytes())
855 .finish()
856 .unwrap();
857 assert!(input.is_empty());
858
859 let (circuit, root) = unwrap_problem(problem);
860 let inputs = circuit.inputs();
861 assert_eq!(inputs.len(), 4);
862 assert!(inputs.order().is_none());
863
864 assert_eq!(root, g(2));
865 assert_eq!(circuit.gate(root), Some(Gate::and(&[g(0), v(3), g(1)])));
866 assert_eq!(circuit.gate(g(0)), Some(Gate::or(&[v(0), v(2), !v(3)])));
867 assert_eq!(circuit.gate(g(1)), Some(Gate::or(&[v(1), v(2)])));
868 }
869
870 #[test]
871 fn preamble_satx() {
872 let (input, preamble) = preamble::<()>(false, false)(b"p satx 1337 \n").unwrap();
873 assert!(input.is_empty());
874 assert_eq!(
875 preamble,
876 Preamble {
877 format: SATX,
878 vars: VarSet::new(1337),
879 num_clauses: 0,
880 clause_tree: None
881 }
882 );
883 }
884
885 #[test]
886 fn preamble_sate() {
887 let (input, preamble) = preamble::<()>(false, false)(b"p sate 1\n").unwrap();
888 assert!(input.is_empty());
889 assert_eq!(
890 preamble,
891 Preamble {
892 format: SATE,
893 vars: VarSet::new(1),
894 num_clauses: 0,
895 clause_tree: None
896 }
897 );
898 }
899
900 #[test]
901 fn preamble_satex() {
902 let (input, preamble) = preamble::<()>(false, false)(b"p satex 42 \n").unwrap();
903 assert!(input.is_empty());
904 assert_eq!(
905 preamble,
906 Preamble {
907 format: SATEX,
908 vars: VarSet::new(42),
909 num_clauses: 0,
910 clause_tree: None
911 }
912 );
913 }
914}