boolean_circuit/file_formats/
aiger.rs

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
11/// Translates the [`Circuit`] to (text) AIGER format and writes it to the given writer.
12pub fn to_aiger(f: impl Write, circuit: &Circuit) -> Result<(), String> {
13    AigerWriter::new(circuit, false).process(f)
14}
15
16/// Translates the [`Circuit`] to binary AIGER format and writes it to the given writer.
17pub fn to_aiger_binary(f: impl Write, circuit: &Circuit) -> Result<(), String> {
18    AigerWriter::new(circuit, true).process(f)
19}
20
21/// Reads an AIGER file (in binary or text format) and returns the represented {Circuit}.
22/// Stores the order of the input gates.
23///
24/// Does not support latches.
25pub 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
60/// Returns true if the output of the AIG translation of the gate is inverted.
61fn 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
72/// Returns the number of AND gates required to translate this gate.
73fn 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        // Create a gate-to-literal mapping that already incorporates if the
104        // output is inverted or not.
105        // Start with inputs since this is a requirement for binary encoding.
106        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        // We skip constants and not-gates, since they do not need variables.
115        // Post-order traversal is important since the predecessor gates have to
116        // have smaller IDs.
117        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        // Header
186        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            // Inputs
197            for var in self.input_name_to_literal.values().sorted() {
198                writeln!(f, "{var}")?;
199            }
200        }
201        // Outputs
202        write!(
203            f,
204            "{}",
205            self.circuit
206                .outputs()
207                .iter()
208                .map(|o| format!("{}\n", self.literal_ref(o)))
209                .format("")
210        )?;
211        // And gates
212        for (out, left, right) in and_gates {
213            self.write_gate(f, (out, left, right))?;
214        }
215        // Symbol table
216        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    /// Returns the literal when referencing the gate, i.e. including the inversion.
245    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    /// Returns the literal when identifying the gate in the definition,
255    /// i.e. excluding the inversion.
256    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
322/// Parses the gates into a hash map of output -> (left, right).
323fn 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        // Lines of the form: (out, left, right)
342        (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    /// For the inputs, we already construct the [`Gate`].
393    /// This map contains all input gates, also the un-named.
394    inputs: HashMap<u64, Gate>,
395    /// The output names are just stored in a vector.
396    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            // Tests repetition of the same variable name but in different gates.
598            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}