1use std::{
2 cmp::{max, min},
3 collections::{HashMap, HashSet},
4 io::{BufRead, BufReader, Read, Write},
5};
6
7use itertools::Itertools;
8
9use crate::{Circuit, Gate, Operation};
10
11pub fn to_aiger(f: impl Write, circuit: &Circuit) -> Result<(), String> {
13 AigerWriter::new(circuit, false).process(f)
14}
15
16pub fn to_aiger_binary(f: impl Write, circuit: &Circuit) -> Result<(), String> {
18 AigerWriter::new(circuit, true).process(f)
19}
20
21pub fn from_aiger(f: impl Read) -> Result<Circuit, String> {
26 let mut input = BufReader::new(f);
27 let AigerHeader {
28 is_binary,
29 input_count,
30 output_count,
31 and_count,
32 } = parse_header(&mut input)?;
33 let input_literals = parse_input_literals(input_count, is_binary, &mut input)?;
34 let output_literals = parse_literals(output_count, &mut input)?;
35 let and_gates = parse_and_gates(input_count, and_count, is_binary, &mut input)?;
36
37 let names = parse_names(&input_literals, output_literals.len(), &mut input)?;
38
39 let input_names = input_literals
40 .iter()
41 .map(|lit| match names.inputs[lit].operation() {
42 Operation::Variable(name) => name,
43 _ => unreachable!(),
44 })
45 .map(|name| name.as_ref().clone())
46 .collect_vec();
47
48 let mut builder = CircuitBuilder {
49 gates: names.inputs,
50 and_gates,
51 };
52 let outputs: Vec<_> = output_literals
53 .into_iter()
54 .zip_eq(names.outputs)
55 .map(|(o, name)| Ok((builder.build_gate(o)?, name)))
56 .collect::<Result<_, String>>()?;
57 Circuit::from_named_outputs(outputs).with_input_order(input_names)
58}
59
60fn has_inverted_output(n: &Gate) -> bool {
62 match n.operation() {
63 Operation::Variable(_) => false,
64 Operation::Constant(v) => *v,
65 Operation::Conjunction(_, _) => false,
66 Operation::Disjunction(_, _) => true,
67 Operation::Xor(_, _) => true,
68 Operation::Negation(_) => true,
69 }
70}
71
72fn and_gates_needed(n: &Gate) -> usize {
74 match n.operation() {
75 Operation::Variable(_) | Operation::Constant(_) | Operation::Negation(_) => 0,
76 Operation::Conjunction(..) | Operation::Disjunction(..) => 1,
77 Operation::Xor(..) => 3,
78 }
79}
80
81fn invert(literal: u32) -> u32 {
82 literal ^ 1
83}
84
85fn aiger_encode_number(f: &mut impl Write, mut n: u32) -> Result<(), std::io::Error> {
86 while n >= 0x80 {
87 f.write_all(&[(n & 0x7f | 0x80) as u8])?;
88 n >>= 7;
89 }
90 f.write_all(&[n as u8])
91}
92
93struct AigerWriter<'a> {
94 binary_format: bool,
95 circuit: &'a Circuit,
96 gate_id_to_literal: HashMap<usize, u32>,
97 input_name_to_literal: HashMap<&'a str, u32>,
98 var_count: usize,
99}
100
101impl<'a> AigerWriter<'a> {
102 pub fn new(circuit: &'a Circuit, binary_format: bool) -> Self {
103 let var_name_to_literal: HashMap<_, _> = circuit
107 .input_names()
108 .enumerate()
109 .map(|(i, name)| {
110 let literal = 2 * (i + 1) as u32;
111 (name, literal)
112 })
113 .collect();
114 let (gate_id_to_literal, var_count) = circuit
118 .post_visit_iter()
119 .filter(|n| {
120 !matches!(
121 n.operation(),
122 Operation::Constant(_) | Operation::Negation(_) | Operation::Variable(_)
123 )
124 })
125 .fold(
126 (HashMap::new(), var_name_to_literal.len()),
127 |(mut map, var_count), gate| {
128 let gates_needed = and_gates_needed(gate);
129 assert!(gates_needed > 0);
130 let var_id = var_count + gates_needed;
131 let literal = 2 * var_id as u32 + if has_inverted_output(gate) { 1 } else { 0 };
132 map.insert(gate.id(), literal);
133 (map, var_id)
134 },
135 );
136 Self {
137 binary_format,
138 circuit,
139 gate_id_to_literal,
140 input_name_to_literal: var_name_to_literal,
141 var_count,
142 }
143 }
144
145 pub fn process(mut self, mut f: impl Write) -> Result<(), String> {
146 let and_gates = self.compute_and_gates();
147 self.write_out(&mut f, and_gates).map_err(|e| e.to_string())
148 }
149
150 fn compute_and_gates(&mut self) -> Vec<(u32, u32, u32)> {
151 let mut and_gates = vec![];
152 for n in self.circuit.post_visit_iter() {
153 let gate_var = self.literal(n);
154 match n.operation() {
155 Operation::Variable(_) | Operation::Constant(_) | Operation::Negation(_) => {}
156 Operation::Conjunction(left, right) => {
157 let left = self.literal_ref(left);
158 let right = self.literal_ref(right);
159 and_gates.push((gate_var, left, right));
160 }
161 Operation::Disjunction(left, right) => {
162 let left = self.literal_ref(left);
163 let right = self.literal_ref(right);
164 and_gates.push((gate_var, invert(left), invert(right)));
165 }
166 Operation::Xor(left, right) => {
167 let left = self.literal_ref(left);
168 let right = self.literal_ref(right);
169 let a = gate_var - 4;
170 and_gates.push((a, left, invert(right)));
171 let b = gate_var - 2;
172 and_gates.push((b, invert(left), right));
173 and_gates.push((gate_var, invert(a), invert(b)));
174 }
175 }
176 }
177 and_gates
178 }
179
180 fn write_out(
181 self,
182 f: &mut impl Write,
183 and_gates: Vec<(u32, u32, u32)>,
184 ) -> Result<(), std::io::Error> {
185 writeln!(
187 f,
188 "a{}g {} {} 0 {} {}",
189 if self.binary_format { "i" } else { "a" },
190 self.var_count,
191 self.input_name_to_literal.len(),
192 self.circuit.outputs().len(),
193 and_gates.len()
194 )?;
195 if !self.binary_format {
196 for var in self.input_name_to_literal.values().sorted() {
198 writeln!(f, "{var}")?;
199 }
200 }
201 write!(
203 f,
204 "{}",
205 self.circuit
206 .outputs()
207 .iter()
208 .map(|o| format!("{}\n", self.literal_ref(o)))
209 .format("")
210 )?;
211 for (out, left, right) in and_gates {
213 self.write_gate(f, (out, left, right))?;
214 }
215 for (i, (name, _)) in self
217 .input_name_to_literal
218 .iter()
219 .sorted_by_key(|(_, v)| *v)
220 .enumerate()
221 {
222 writeln!(f, "i{i} {name}")?;
223 }
224 for (i, name) in self.circuit.output_names().iter().enumerate() {
225 if !name.is_empty() {
226 writeln!(f, "o{i} {name}")?;
227 }
228 }
229
230 Ok(())
231 }
232
233 fn write_gate(&self, f: &mut impl Write, gate: (u32, u32, u32)) -> Result<(), std::io::Error> {
234 let (gate_var, left, right) = gate;
235 let (left, right) = (max(left, right), min(left, right));
236 if self.binary_format {
237 aiger_encode_number(f, gate_var - left)?;
238 aiger_encode_number(f, left - right)
239 } else {
240 writeln!(f, "{gate_var} {left} {right}")
241 }
242 }
243
244 fn literal_ref(&self, gate: &Gate) -> u32 {
246 match gate.operation() {
247 Operation::Constant(v) => *v as u32,
248 Operation::Variable(name) => self.input_name_to_literal[name.as_str()],
249 Operation::Negation(inner) => invert(self.literal_ref(inner)),
250 _ => self.gate_id_to_literal[&gate.id()],
251 }
252 }
253
254 fn literal(&self, gate: &Gate) -> u32 {
257 self.literal_ref(gate) & !1
258 }
259}
260
261struct AigerHeader {
262 is_binary: bool,
263 input_count: usize,
264 output_count: usize,
265 and_count: usize,
266}
267
268fn parse_header(input: &mut impl BufRead) -> Result<AigerHeader, String> {
269 let header = read_line(input)?;
270 let (is_binary, header) = if let Some(header) = header.strip_prefix("aag ") {
271 (false, header)
272 } else if let Some(header) = header.strip_prefix("aig ") {
273 (true, header)
274 } else {
275 return Err("Invalid header".to_string());
276 };
277 let header_numbers = header
278 .split(' ')
279 .map(|n| {
280 n.parse::<usize>()
281 .map_err(|e| format!("Error reading number in header: {e}"))
282 })
283 .collect::<Result<Vec<_>, _>>()?;
284 let [_variable_count, input_count, latch_count, output_count, and_count] = header_numbers
285 .try_into()
286 .map_err(|_| "Invalid number of items in the header".to_string())?;
287
288 if latch_count != 0 {
289 return Err("Latches are not supported".to_string());
290 }
291 Ok(AigerHeader {
292 is_binary,
293 input_count,
294 output_count,
295 and_count,
296 })
297}
298
299fn parse_input_literals(
300 input_count: usize,
301 is_binary: bool,
302 f: &mut impl BufRead,
303) -> Result<Vec<u64>, String> {
304 if is_binary {
305 Ok((0..input_count).map(|i| 2 * (i as u64 + 1)).collect())
306 } else {
307 parse_literals(input_count, f)
308 }
309}
310
311fn parse_literals(count: usize, f: &mut impl BufRead) -> Result<Vec<u64>, String> {
312 let literals = (0..count)
313 .map(|_| {
314 let line = read_line(f)?;
315 line.parse::<u64>().map_err(|e| e.to_string())
316 })
317 .collect::<Result<Vec<_>, _>>()?;
318 assert_eq!(literals.len(), count);
319 Ok(literals)
320}
321
322fn parse_and_gates(
324 input_count: usize,
325 and_count: usize,
326 is_binary: bool,
327 f: &mut impl BufRead,
328) -> Result<HashMap<u64, (u64, u64)>, String> {
329 if is_binary {
330 (0..and_count)
331 .map(|i| {
332 let output_literal = 2 * (input_count + 1 + i) as u64;
333 let delta0 = aiger_decode_number(f)? as u64;
334 let delta1 = aiger_decode_number(f)? as u64;
335 let left = output_literal - delta0;
336 let right = left - delta1;
337 Ok((output_literal, (left, right)))
338 })
339 .collect()
340 } else {
341 (0..and_count)
343 .map(|_| {
344 let line = read_line(f)?;
345 let items = line
346 .split(' ')
347 .map(|n| {
348 n.parse::<u64>()
349 .map_err(|e| format!("Error parsing gate number: {e}"))
350 })
351 .collect::<Result<Vec<_>, _>>()?;
352 match items.as_slice() {
353 [output, left, right] => {
354 if output % 2 != 0 {
355 Err(format!("Expected even literal for output: {output}"))
356 } else {
357 Ok((*output, (*left, *right)))
358 }
359 }
360 _ => Err(format!(
361 "Invalid number of gate items, expected 3 got {}",
362 items.len()
363 )),
364 }
365 })
366 .try_fold(HashMap::new(), |mut acc, res| {
367 let (output, (left, right)) = res?;
368 if acc.insert(output, (left, right)).is_none() {
369 Ok(acc)
370 } else {
371 Err(format!("Duplicate output gate ID: {output}"))
372 }
373 })
374 }
375}
376
377fn aiger_decode_number(f: &mut impl Read) -> Result<u32, String> {
378 let mut result: u32 = 0;
379 let mut buf = [0; 1];
380 for shift_amount in (0..).step_by(7) {
381 f.read_exact(&mut buf).map_err(|e| e.to_string())?;
382 let b = buf[0];
383 result |= ((b & 0x7f) as u32) << shift_amount;
384 if b & 0x80 == 0 {
385 break;
386 }
387 }
388 Ok(result)
389}
390
391struct Names {
392 inputs: HashMap<u64, Gate>,
395 outputs: Vec<String>,
397}
398
399fn parse_names(
400 input_literals: &[u64],
401 output_count: usize,
402 f: &mut impl BufRead,
403) -> Result<Names, String> {
404 let mut used_input_names: HashSet<String> = Default::default();
405 let mut named_inputs = HashMap::default();
406 let mut output_names = vec![String::new(); output_count];
407 loop {
408 let Ok(line) = read_line(f) else {
409 break;
410 };
411 let is_input = match line.chars().next() {
412 Some('i') => true,
413 Some('o') => false,
414 _ => break,
415 };
416 let kind_name = if is_input { "input" } else { "output" };
417 let suffix = &line[1..];
418 let parts = suffix.split(' ').collect_vec();
419 let [index, name] = parts.as_slice() else {
420 return Err(format!(
421 "Expected exactly two parts for {kind_name} name, but got {suffix}"
422 ));
423 };
424 let index = index
425 .parse::<usize>()
426 .map_err(|e| format!("Expected {kind_name} literal: {e}"))?;
427
428 if (is_input && index >= input_literals.len()) || (!is_input && index >= output_count) {
429 return Err(format!(
430 "Out of range for {kind_name} literal name: {index}"
431 ));
432 }
433 if is_input {
434 if !used_input_names.insert(name.to_string()) {
435 return Err(format!("Duplicate {kind_name} name: {name}"));
436 }
437 named_inputs.insert(input_literals[index], Gate::from(*name));
438 } else {
439 output_names[index] = name.to_string();
440 }
441 }
442 let mut last_input_id = 0;
443 let anonymous_inputs = input_literals
444 .iter()
445 .filter(|lit| !named_inputs.contains_key(lit))
446 .map(|&lit| {
447 while used_input_names.contains(&format!("v_{last_input_id}")) {
448 last_input_id += 1;
449 }
450 (lit, Gate::from(format!("v_{last_input_id}")))
451 })
452 .collect_vec();
453 named_inputs.extend(anonymous_inputs);
454 assert_eq!(named_inputs.len(), input_literals.len());
455 Ok(Names {
456 inputs: named_inputs,
457 outputs: output_names,
458 })
459}
460
461struct CircuitBuilder {
462 gates: HashMap<u64, Gate>,
463 and_gates: HashMap<u64, (u64, u64)>,
464}
465
466impl CircuitBuilder {
467 fn build_gate(&mut self, literal: u64) -> Result<Gate, String> {
468 if literal & 1 == 1 {
469 return Ok(!(self.build_gate(literal & !1)?));
470 }
471 Ok(if let Some(n) = self.gates.get(&literal) {
472 n.clone()
473 } else {
474 let (left, right) = self
475 .and_gates
476 .get(&literal)
477 .cloned()
478 .ok_or_else(|| format!("Gate not found: {literal}"))?;
479 self.build_gate(left)? & self.build_gate(right)?
480 })
481 }
482}
483
484fn read_line(input: &mut impl BufRead) -> Result<String, String> {
485 let mut line = String::new();
486 match input.read_line(&mut line) {
487 Ok(0) => Err("Unexpected end of input".to_string()),
488 Ok(_n) => {
489 if line.ends_with('\n') {
490 line.pop();
491 if line.ends_with('\r') {
492 line.pop();
493 }
494 }
495 Ok(line)
496 }
497 Err(e) => Err(e.to_string()),
498 }
499}
500
501#[cfg(test)]
502mod test {
503 use super::*;
504
505 fn test_aiger_out(gate: Gate, expected: &str) {
506 let mut buf = vec![];
507 to_aiger(&mut buf, &Circuit::from_unnamed_outputs([gate])).unwrap();
508 assert_eq!(String::from_utf8(buf).unwrap(), expected);
509 }
510
511 fn test_aiger_circuit_out(circuit: &Circuit, expected: &str) {
512 let mut buf = vec![];
513 to_aiger(&mut buf, circuit).unwrap();
514 assert_eq!(String::from_utf8(buf).unwrap(), expected);
515 }
516
517 mod output {
518 use super::*;
519 use pretty_assertions::assert_eq;
520
521 #[test]
522 fn constant_true() {
523 let output = Gate::from(true);
524 test_aiger_out(output, "aag 0 0 0 1 0\n1\n");
525 }
526
527 #[test]
528 fn constant_false() {
529 let output = Gate::from(false);
530 test_aiger_out(output, "aag 0 0 0 1 0\n0\n");
531 }
532
533 #[test]
534 fn inverter() {
535 let output = !Gate::from("x");
536 test_aiger_out(output, "aag 1 1 0 1 0\n2\n3\ni0 x\n");
537 }
538
539 #[test]
540 fn simple_circuit() {
541 let circuit = Circuit::from_named_outputs([
542 (!Gate::from("x"), "out1".to_string()),
543 (Gate::from("y"), "out2".to_string()),
544 ]);
545 test_aiger_circuit_out(
546 &circuit,
547 "aag 2 2 0 2 0\n2\n4\n5\n2\ni0 y\ni1 x\no0 out1\no1 out2\n",
548 );
549 }
550
551 #[test]
552 fn and_gate() {
553 let output = Gate::from("x") & Gate::from("y");
554 test_aiger_out(output, "aag 3 2 0 1 1\n2\n4\n6\n6 4 2\ni0 x\ni1 y\n");
555 }
556
557 #[test]
558 fn or_gate() {
559 let output = Gate::from("x") | Gate::from("y");
560 test_aiger_out(output, "aag 3 2 0 1 1\n2\n4\n7\n6 5 3\ni0 x\ni1 y\n");
561 }
562
563 #[test]
564 fn xor_gate() {
565 let output = Gate::from("x") ^ Gate::from("y");
566 test_aiger_out(
567 output,
568 "aag 5 2 0 1 3\n2\n4\n11\n6 5 2\n8 4 3\n10 9 7\ni0 x\ni1 y\n",
569 );
570 }
571
572 #[test]
573 fn xor_and_circuit() {
574 let x = Gate::from("x");
575 let y = Gate::from("y");
576 let circuit = Circuit::from_named_outputs([
577 (x.clone() ^ y, "out1".to_string()),
578 (x & Gate::from("y"), "out2".to_string()),
579 ]);
580 test_aiger_circuit_out(
581 &circuit,
582 "aag 6 2 0 2 4\n2\n4\n13\n6\n6 4 2\n8 5 2\n10 4 3\n12 11 9\ni0 x\ni1 y\no0 out1\no1 out2\n"
583 );
584 }
585
586 #[test]
587 fn unnamed_out() {
588 let circuit = Circuit::from_named_outputs([
589 (!Gate::from("x"), Default::default()),
590 (Gate::from("y"), "out2".to_string()),
591 ]);
592 test_aiger_circuit_out(&circuit, "aag 2 2 0 2 0\n2\n4\n5\n2\ni0 y\ni1 x\no1 out2\n");
593 }
594
595 #[test]
596 fn var_repetition() {
597 let output = Gate::from("x") & Gate::from("x");
599 test_aiger_out(output, "aag 2 1 0 1 1\n2\n4\n4 2 2\ni0 x\n");
600 }
601
602 #[test]
603 fn multi_stage() {
604 let a = Gate::from("x") & Gate::from("y");
605 let output = &a | &!&a;
606 test_aiger_out(output, "aag 4 2 0 1 2\n2\n4\n9\n6 4 2\n8 7 6\ni0 x\ni1 y\n");
607 }
608
609 #[test]
610 fn encode_number() {
611 let mut buf = vec![];
612 aiger_encode_number(&mut buf, 0x7f).unwrap();
613 assert_eq!(buf, vec![0x7f]);
614 buf.clear();
615 aiger_encode_number(&mut buf, 0x80).unwrap();
616 assert_eq!(buf, vec![0x80, 0x01]);
617 buf.clear();
618 aiger_encode_number(&mut buf, 0x81).unwrap();
619 assert_eq!(buf, vec![0x81, 0x01]);
620 buf.clear();
621 aiger_encode_number(&mut buf, 16387).unwrap();
622 assert_eq!(buf, vec![0x83, 0x80, 0x01]);
623 buf.clear();
624 }
625
626 #[test]
627 fn multi_stage_binary() {
628 let a = Gate::from("x") & Gate::from("y");
629 let output = &a | &!&a;
630 let mut buf = vec![];
631 to_aiger_binary(&mut buf, &Circuit::from_unnamed_outputs([output])).unwrap();
632 let expected = b"aig 4 2 0 1 2\n9\n\x02\x02\x01\x01i0 x\ni1 y\n";
633 assert_eq!(buf, expected);
634 }
635
636 #[test]
637 fn multi_stage_binary_named_outputs() {
638 let a = Gate::from("x") & Gate::from("y");
639 let output = &a | &!&a;
640 let mut buf = vec![];
641 to_aiger_binary(
642 &mut buf,
643 &Circuit::from_named_outputs([(output, "out".to_string()), (a, "a".to_string())]),
644 )
645 .unwrap();
646 let expected = b"aig 4 2 0 2 2\n9\n6\n\x02\x02\x01\x01i0 x\ni1 y\no0 out\no1 a\n";
647 assert_eq!(buf, expected);
648 }
649
650 #[test]
651 fn order_of_inputs() {
652 let circuit = Circuit::from(Gate::from("x") & !Gate::from("y"));
653 test_aiger_circuit_out(&circuit, "aag 3 2 0 1 1\n2\n4\n6\n6 5 2\ni0 x\ni1 y\n");
654 let circuit = circuit.with_input_order(["y", "x"]).unwrap();
655 test_aiger_circuit_out(&circuit, "aag 3 2 0 1 1\n2\n4\n6\n6 4 3\ni0 y\ni1 x\n");
656 }
657 }
658
659 mod input {
660 use crate::evaluate;
661
662 use super::*;
663
664 fn test_function_x_y(data: &[u8], fun: &impl Fn(bool, bool) -> Vec<bool>) {
665 let out = from_aiger(data).unwrap();
666 for x_val in [false, true] {
667 for y_val in [false, true] {
668 let assignments = [("x", x_val), ("y", y_val)]
669 .into_iter()
670 .map(|(n, v)| (n.to_string(), v))
671 .collect();
672 let result = evaluate(&out, &assignments);
673 assert_eq!(result, fun(x_val, y_val));
674 }
675 }
676 }
677
678 #[test]
679 fn xor_ascii() {
680 let data = b"aag 5 2 0 1 3\n2\n4\n11\n6 5 2\n8 4 3\n10 9 7\ni0 x\ni1 y\n";
681 test_function_x_y(data, &|x, y| vec![x ^ y]);
682 }
683
684 #[test]
685 fn xor_ascii_multi() {
686 let data =
687 b"aag 5 2 0 2 3\n2\n4\n11\n10\n6 5 2\n8 4 3\n10 9 7\ni0 x\ni1 y\no0 w\no1 z\n";
688 test_function_x_y(data, &|x, y| vec![x ^ y, !(x ^ y)]);
689 }
690
691 #[test]
692 fn multi_stage_binary() {
693 let data = b"aig 4 2 0 1 2\n9\n\x02\x02\x01\x01i0 x\ni1 y\n";
694 test_function_x_y(data, &|_, _| vec![true]);
695 }
696
697 #[test]
698 fn output_names() {
699 let data =
700 b"aag 5 2 0 2 3\n2\n4\n11\n10\n6 5 2\n8 4 3\n10 9 7\ni0 x\ni1 y\no1 z\no0 w\n";
701 let circuit = from_aiger(&data[..]).unwrap();
702 assert_eq!(circuit.output_names(), ["w", "z"]);
703 }
704
705 #[test]
706 fn decode_number() {
707 let buf = vec![0x7f];
708 assert_eq!(aiger_decode_number(&mut &*buf).unwrap(), 0x7f);
709 let buf = vec![0x80, 0x01];
710 assert_eq!(aiger_decode_number(&mut &*buf).unwrap(), 0x80);
711 let buf = vec![0x81, 0x01];
712 assert_eq!(aiger_decode_number(&mut &*buf).unwrap(), 0x81);
713 let buf = vec![0x83, 0x80, 0x01];
714 assert_eq!(aiger_decode_number(&mut &*buf).unwrap(), 16387);
715 }
716
717 #[test]
718 fn order_of_inputs() {
719 let data = b"aag 3 2 0 1 1\n2\n4\n6\n6 4 3\ni0 y\ni1 x\n";
720 let circuit = from_aiger(&data[..]).unwrap();
721 assert_eq!(circuit.input_names().collect_vec(), vec!["y", "x"]);
722 }
723 }
724}