1use std::{
2 cmp::{max, min},
3 collections::{HashMap, HashSet},
4 io::{BufRead, BufReader, Read, Write},
5};
6
7use itertools::Itertools;
8
9use crate::{Node, Operation};
10
11pub fn to_aiger(f: impl Write, output: &Node) -> Result<(), String> {
14 AigerWriter::new(output, false).process(f)
15}
16
17pub fn to_aiger_binary(f: impl Write, output: &Node) -> Result<(), String> {
20 AigerWriter::new(output, true).process(f)
21}
22
23pub fn from_aiger(f: impl Read) -> Result<Node, String> {
27 let mut input = BufReader::new(f);
28 let AigerHeader {
29 is_binary,
30 input_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_literal = parse_output_literal(&mut input)?;
35 let and_gates = parse_and_gates(input_count, and_count, is_binary, &mut input)?;
36 let gates = build_named_inputs(input_literals, &mut input)?;
37
38 CircuitBuilder { gates, and_gates }.build_node(output_literal)
39}
40
41fn has_inverted_output(n: &Node) -> bool {
43 match n.operation() {
44 Operation::Variable(_) => false,
45 Operation::Constant(v) => *v,
46 Operation::Conjunction(_, _) => false,
47 Operation::Disjunction(_, _) => true,
48 Operation::Xor(_, _) => true,
49 Operation::Negation(_) => true,
50 }
51}
52
53fn and_gates_needed(n: &Node) -> usize {
55 match n.operation() {
56 Operation::Variable(_) | Operation::Constant(_) | Operation::Negation(_) => 0,
57 Operation::Conjunction(..) | Operation::Disjunction(..) => 1,
58 Operation::Xor(..) => 3,
59 }
60}
61
62fn invert(literal: u32) -> u32 {
63 literal ^ 1
64}
65
66fn aiger_encode_number(f: &mut impl Write, mut n: u32) -> Result<(), std::io::Error> {
67 while n >= 0x80 {
68 f.write_all(&[(n & 0x7f | 0x80) as u8])?;
69 n >>= 7;
70 }
71 f.write_all(&[n as u8])
72}
73
74struct AigerWriter<'a> {
75 binary_format: bool,
76 output: &'a Node,
77 node_id_to_literal: HashMap<usize, u32>,
78 input_name_to_literal: HashMap<&'a str, u32>,
79 var_count: usize,
80}
81
82impl<'a> AigerWriter<'a> {
83 pub fn new(output: &'a Node, binary_format: bool) -> Self {
84 let var_name_to_literal: HashMap<_, _> = output
88 .iter()
89 .filter_map(|n| {
90 if let Operation::Variable(name) = n.operation() {
91 Some(name.as_str())
92 } else {
93 None
94 }
95 })
96 .unique()
97 .enumerate()
98 .map(|(i, name)| {
99 let literal = 2 * (i + 1) as u32;
100 (name, literal)
101 })
102 .collect();
103 let (node_id_to_literal, var_count) = output
107 .post_visit_iter()
108 .filter(|n| {
109 !matches!(
110 n.operation(),
111 Operation::Constant(_) | Operation::Negation(_) | Operation::Variable(_)
112 )
113 })
114 .fold(
115 (HashMap::new(), var_name_to_literal.len()),
116 |(mut map, var_count), node| {
117 let gates_needed = and_gates_needed(node);
118 assert!(gates_needed > 0);
119 let var_id = var_count + gates_needed;
120 let literal = 2 * var_id as u32 + if has_inverted_output(node) { 1 } else { 0 };
121 map.insert(node.id(), literal);
122 (map, var_id)
123 },
124 );
125 Self {
126 binary_format,
127 output,
128 node_id_to_literal,
129 input_name_to_literal: var_name_to_literal,
130 var_count,
131 }
132 }
133
134 pub fn process(mut self, mut f: impl Write) -> Result<(), String> {
135 let and_gates = self.compute_and_gates();
136 self.write_out(&mut f, and_gates).map_err(|e| e.to_string())
137 }
138
139 fn compute_and_gates(&mut self) -> Vec<(u32, u32, u32)> {
140 let mut and_gates = vec![];
141 for n in self.output.post_visit_iter() {
142 let gate_var = self.literal(n);
143 match n.operation() {
144 Operation::Variable(_) | Operation::Constant(_) | Operation::Negation(_) => {}
145 Operation::Conjunction(left, right) => {
146 let left = self.literal_ref(left);
147 let right = self.literal_ref(right);
148 and_gates.push((gate_var, left, right));
149 }
150 Operation::Disjunction(left, right) => {
151 let left = self.literal_ref(left);
152 let right = self.literal_ref(right);
153 and_gates.push((gate_var, invert(left), invert(right)));
154 }
155 Operation::Xor(left, right) => {
156 let left = self.literal_ref(left);
157 let right = self.literal_ref(right);
158 let a = gate_var - 4;
159 and_gates.push((a, left, invert(right)));
160 let b = gate_var - 2;
161 and_gates.push((b, invert(left), right));
162 and_gates.push((gate_var, invert(a), invert(b)));
163 }
164 }
165 }
166 and_gates
167 }
168
169 fn write_out(
170 self,
171 f: &mut impl Write,
172 and_gates: Vec<(u32, u32, u32)>,
173 ) -> Result<(), std::io::Error> {
174 writeln!(
176 f,
177 "a{}g {} {} 0 1 {}",
178 if self.binary_format { "i" } else { "a" },
179 self.var_count,
180 self.input_name_to_literal.len(),
181 and_gates.len()
182 )?;
183 if !self.binary_format {
184 for var in self.input_name_to_literal.values().sorted() {
186 writeln!(f, "{var}")?;
187 }
188 }
189 writeln!(f, "{}", self.literal_ref(self.output))?;
191 for (out, left, right) in and_gates {
193 self.write_gate(f, (out, left, right))?;
194 }
195 for (i, (name, _)) in self
197 .input_name_to_literal
198 .iter()
199 .sorted_by_key(|(_, v)| *v)
200 .enumerate()
201 {
202 writeln!(f, "i{i} {name}")?;
203 }
204
205 Ok(())
206 }
207
208 fn write_gate(&self, f: &mut impl Write, gate: (u32, u32, u32)) -> Result<(), std::io::Error> {
209 let (gate_var, left, right) = gate;
210 let (left, right) = (max(left, right), min(left, right));
211 if self.binary_format {
212 aiger_encode_number(f, gate_var - left)?;
213 aiger_encode_number(f, left - right)
214 } else {
215 writeln!(f, "{gate_var} {left} {right}")
216 }
217 }
218
219 fn literal_ref(&self, node: &Node) -> u32 {
221 match node.operation() {
222 Operation::Constant(v) => *v as u32,
223 Operation::Variable(name) => self.input_name_to_literal[name.as_str()],
224 Operation::Negation(inner) => invert(self.literal_ref(inner)),
225 _ => self.node_id_to_literal[&node.id()],
226 }
227 }
228
229 fn literal(&self, node: &Node) -> u32 {
232 self.literal_ref(node) & !1
233 }
234}
235
236struct AigerHeader {
237 is_binary: bool,
238 input_count: usize,
239 and_count: usize,
240}
241
242fn parse_header(input: &mut impl BufRead) -> Result<AigerHeader, String> {
243 let header = read_line(input)?;
244 let (is_binary, header) = if let Some(header) = header.strip_prefix("aag ") {
245 (false, header)
246 } else if let Some(header) = header.strip_prefix("aig ") {
247 (true, header)
248 } else {
249 return Err("Invalid header".to_string());
250 };
251 let header_numbers = header
252 .split(' ')
253 .map(|n| {
254 n.parse::<usize>()
255 .map_err(|e| format!("Error reading number in header: {e}"))
256 })
257 .collect::<Result<Vec<_>, _>>()?;
258 let [_variable_count, input_count, latch_count, output_count, and_count] = header_numbers
259 .try_into()
260 .map_err(|_| "Invalid number of items in the header".to_string())?;
261
262 if latch_count != 0 {
263 return Err("Latches are not supported".to_string());
264 }
265 if output_count != 1 {
266 return Err("Only one output is supported".to_string());
267 }
268 Ok(AigerHeader {
269 is_binary,
270 input_count,
271 and_count,
272 })
273}
274
275fn parse_input_literals(
276 input_count: usize,
277 is_binary: bool,
278 f: &mut impl BufRead,
279) -> Result<Vec<u64>, String> {
280 Ok(if is_binary {
281 (0..input_count).map(|i| 2 * (i as u64 + 1)).collect()
282 } else {
283 let literals = (0..input_count)
284 .map(|_| {
285 let line = read_line(f)?;
286 line.parse::<u64>().map_err(|e| e.to_string())
287 })
288 .collect::<Result<Vec<_>, _>>()?;
289 assert_eq!(literals.len(), input_count);
290 literals
291 })
292}
293
294fn parse_output_literal(f: &mut impl BufRead) -> Result<u64, String> {
295 read_line(f)?.parse::<u64>().map_err(|e| e.to_string())
296}
297
298fn parse_and_gates(
300 input_count: usize,
301 and_count: usize,
302 is_binary: bool,
303 f: &mut impl BufRead,
304) -> Result<HashMap<u64, (u64, u64)>, String> {
305 if is_binary {
306 (0..and_count)
307 .map(|i| {
308 let output_literal = 2 * (input_count + 1 + i) as u64;
309 let delta0 = aiger_decode_number(f)? as u64;
310 let delta1 = aiger_decode_number(f)? as u64;
311 let left = output_literal - delta0;
312 let right = left - delta1;
313 Ok((output_literal, (left, right)))
314 })
315 .collect()
316 } else {
317 (0..and_count)
319 .map(|_| {
320 let line = read_line(f)?;
321 let items = line
322 .split(' ')
323 .map(|n| {
324 n.parse::<u64>()
325 .map_err(|e| format!("Error parsing gate number: {e}"))
326 })
327 .collect::<Result<Vec<_>, _>>()?;
328 match items.as_slice() {
329 [output, left, right] => {
330 if output % 2 != 0 {
331 Err(format!("Expected even literal for output: {output}"))
332 } else {
333 Ok((*output, (*left, *right)))
334 }
335 }
336 _ => Err(format!(
337 "Invalid number of gate items, expected 3 got {}",
338 items.len()
339 )),
340 }
341 })
342 .try_fold(HashMap::new(), |mut acc, res| {
343 let (output, (left, right)) = res?;
344 if acc.insert(output, (left, right)).is_none() {
345 Ok(acc)
346 } else {
347 Err(format!("Duplicate output gate ID: {output}"))
348 }
349 })
350 }
351}
352
353fn aiger_decode_number(f: &mut impl Read) -> Result<u32, String> {
354 let mut result: u32 = 0;
355 let mut buf = [0; 1];
356 for shift_amount in (0..).step_by(7) {
357 f.read_exact(&mut buf).map_err(|e| e.to_string())?;
358 let b = buf[0];
359 result |= ((b & 0x7f) as u32) << shift_amount;
360 if b & 0x80 == 0 {
361 break;
362 }
363 }
364 Ok(result)
365}
366
367fn build_named_inputs(
368 input_literals: Vec<u64>,
369 f: &mut impl BufRead,
370) -> Result<HashMap<u64, Node>, String> {
371 let mut used_input_names: HashSet<String> = Default::default();
372 let mut named_inputs = HashMap::default();
373 loop {
374 let Ok(line) = read_line(f) else {
375 break;
376 };
377 let Some(suffix) = line.strip_prefix("i") else {
378 break;
379 };
380 let parts = suffix.split(' ').collect_vec();
381 if parts.len() != 2 {
382 return Err(format!(
383 "Expected exactly two parts for input name, but got {suffix}"
384 ));
385 }
386 let index = parts[0]
387 .parse::<usize>()
388 .map_err(|e| format!("Expected input literal: {e}"))?;
389 if index >= input_literals.len() {
390 return Err(format!("Out of range for input literal name: {index}"));
391 }
392 let name = parts[1];
393 if !used_input_names.insert(name.to_string()) {
394 return Err(format!("Duplicate input name: {name}"));
395 }
396 named_inputs.insert(input_literals[index], Node::from(parts[1]));
397 }
398 let mut last_input_id = 0;
399 let anonymous_inputs = input_literals
400 .iter()
401 .filter(|lit| !named_inputs.contains_key(lit))
402 .map(|&lit| {
403 while used_input_names.contains(&format!("v_{last_input_id}")) {
404 last_input_id += 1;
405 }
406 (lit, Node::from(format!("v_{last_input_id}")))
407 })
408 .collect_vec();
409 named_inputs.extend(anonymous_inputs);
410 assert_eq!(named_inputs.len(), input_literals.len());
411 Ok(named_inputs)
412}
413
414struct CircuitBuilder {
415 gates: HashMap<u64, Node>,
416 and_gates: HashMap<u64, (u64, u64)>,
417}
418
419impl CircuitBuilder {
420 fn build_node(&mut self, literal: u64) -> Result<Node, String> {
421 if literal & 1 == 1 {
422 return Ok(!(self.build_node(literal & !1)?));
423 }
424 Ok(if let Some(n) = self.gates.get(&literal) {
425 n.clone()
426 } else {
427 let (left, right) = self
428 .and_gates
429 .get(&literal)
430 .cloned()
431 .ok_or_else(|| format!("Gate not found: {literal}"))?;
432 self.build_node(left)? & self.build_node(right)?
433 })
434 }
435}
436
437fn read_line(input: &mut impl BufRead) -> Result<String, String> {
438 let mut line = String::new();
439 match input.read_line(&mut line) {
440 Ok(0) => Err("Unexpected end of input".to_string()),
441 Ok(_n) => {
442 if line.ends_with('\n') {
443 line.pop();
444 if line.ends_with('\r') {
445 line.pop();
446 }
447 }
448 Ok(line)
449 }
450 Err(e) => Err(e.to_string()),
451 }
452}
453
454#[cfg(test)]
455mod test {
456 use super::*;
457
458 fn test_aiger_out(node: Node, expected: &str) {
459 let mut buf = vec![];
460 to_aiger(&mut buf, &node).unwrap();
461 assert_eq!(String::from_utf8(buf).unwrap(), expected);
462 }
463
464 mod output {
465 use super::*;
466 use pretty_assertions::assert_eq;
467
468 #[test]
469 fn constant_true() {
470 let output = Node::from(true);
471 test_aiger_out(output, "aag 0 0 0 1 0\n1\n");
472 }
473
474 #[test]
475 fn constant_false() {
476 let output = Node::from(false);
477 test_aiger_out(output, "aag 0 0 0 1 0\n0\n");
478 }
479
480 #[test]
481 fn inverter() {
482 let output = !Node::from("x");
483 test_aiger_out(output, "aag 1 1 0 1 0\n2\n3\ni0 x\n");
484 }
485
486 #[test]
487 fn and_gate() {
488 let output = Node::from("x") & Node::from("y");
489 test_aiger_out(output, "aag 3 2 0 1 1\n2\n4\n6\n6 4 2\ni0 x\ni1 y\n");
490 }
491
492 #[test]
493 fn or_gate() {
494 let output = Node::from("x") | Node::from("y");
495 test_aiger_out(output, "aag 3 2 0 1 1\n2\n4\n7\n6 5 3\ni0 x\ni1 y\n");
496 }
497
498 #[test]
499 fn xor_gate() {
500 let output = Node::from("x") ^ Node::from("y");
501 test_aiger_out(
502 output,
503 "aag 5 2 0 1 3\n2\n4\n11\n6 5 2\n8 4 3\n10 9 7\ni0 x\ni1 y\n",
504 );
505 }
506
507 #[test]
508 fn var_repetition() {
509 let output = Node::from("x") & Node::from("x");
511 test_aiger_out(output, "aag 2 1 0 1 1\n2\n4\n4 2 2\ni0 x\n");
512 }
513
514 #[test]
515 fn multi_stage() {
516 let a = Node::from("x") & Node::from("y");
517 let output = &a | &!&a;
518 test_aiger_out(output, "aag 4 2 0 1 2\n2\n4\n9\n6 4 2\n8 7 6\ni0 x\ni1 y\n");
519 }
520
521 #[test]
522 fn encode_number() {
523 let mut buf = vec![];
524 aiger_encode_number(&mut buf, 0x7f).unwrap();
525 assert_eq!(buf, vec![0x7f]);
526 buf.clear();
527 aiger_encode_number(&mut buf, 0x80).unwrap();
528 assert_eq!(buf, vec![0x80, 0x01]);
529 buf.clear();
530 aiger_encode_number(&mut buf, 0x81).unwrap();
531 assert_eq!(buf, vec![0x81, 0x01]);
532 buf.clear();
533 aiger_encode_number(&mut buf, 16387).unwrap();
534 assert_eq!(buf, vec![0x83, 0x80, 0x01]);
535 buf.clear();
536 }
537
538 #[test]
539 fn multi_stage_binary() {
540 let a = Node::from("x") & Node::from("y");
541 let output = &a | &!&a;
542 let mut buf = vec![];
543 to_aiger_binary(&mut buf, &output).unwrap();
544 let expected = b"aig 4 2 0 1 2\n9\n\x02\x02\x01\x01i0 x\ni1 y\n";
545 assert_eq!(buf, expected);
546 }
547 }
548
549 mod input {
550
551 use crate::evaluate;
552
553 use super::*;
554
555 fn test_function_x_y(data: &[u8], fun: &impl Fn(bool, bool) -> bool) {
556 let out = from_aiger(data).unwrap();
557 for x_val in [false, true] {
558 for y_val in [false, true] {
559 let assignments = [("x", x_val), ("y", y_val)]
560 .into_iter()
561 .map(|(n, v)| (n.to_string(), v))
562 .collect();
563 let result = evaluate(&out, &assignments);
564 assert_eq!(result, fun(x_val, y_val));
565 }
566 }
567 }
568
569 #[test]
570 fn xor_ascii() {
571 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";
572 test_function_x_y(data, &|x, y| x ^ y);
573 }
574
575 #[test]
576 fn multi_stage_binary() {
577 let data = b"aig 4 2 0 1 2\n9\n\x02\x02\x01\x01i0 x\ni1 y\n";
578 test_function_x_y(data, &|_, _| true);
579 }
580
581 #[test]
582 fn decode_number() {
583 let buf = vec![0x7f];
584 assert_eq!(aiger_decode_number(&mut &*buf).unwrap(), 0x7f);
585 let buf = vec![0x80, 0x01];
586 assert_eq!(aiger_decode_number(&mut &*buf).unwrap(), 0x80);
587 let buf = vec![0x81, 0x01];
588 assert_eq!(aiger_decode_number(&mut &*buf).unwrap(), 0x81);
589 let buf = vec![0x83, 0x80, 0x01];
590 assert_eq!(aiger_decode_number(&mut &*buf).unwrap(), 16387);
591 }
592 }
593}