from collections.abc import Iterator
from typing import Any, Literal, overload

class AigNode:
    def __init__(self, index: int) -> None: ...
    def __hash__(self) -> int: ...
    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...
    def __lt__(self, other: AigNode | int) -> bool: ...

class AigSignal:
    def __init__(self, index: int, complement: bool) -> None: ...
    def get_index(self) -> int: ...
    def get_complement(self) -> bool: ...
    def get_data(self) -> int: ...
    def __hash__(self) -> int: ...
    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...
    def __lt__(self, other: AigSignal) -> bool: ...
    def __invert__(self) -> AigSignal: ...
    def __pos__(self) -> AigSignal: ...
    def __neg__(self) -> AigSignal: ...
    def __xor__(self, complement: bool) -> AigSignal: ...

class Aig:
    def __init__(self) -> None: ...
    def clone(self) -> Aig: ...
    def size(self) -> int: ...
    def num_gates(self) -> int: ...
    def num_pis(self) -> int: ...
    def num_pos(self) -> int: ...
    def get_node(self, s: AigSignal) -> AigNode: ...
    def make_signal(self, n: AigNode | int) -> AigSignal: ...
    def is_complemented(self, s: AigSignal) -> bool: ...
    def node_to_index(self, n: AigNode | int) -> int: ...
    def index_to_node(self, index: int) -> AigNode: ...
    def pi_index(self, n: AigNode | int) -> int: ...
    def pi_at(self, index: int) -> AigNode: ...
    def po_index(self, s: AigSignal) -> int: ...
    def po_at(self, index: int) -> AigSignal: ...
    def get_constant(self, value: bool) -> AigSignal: ...
    def create_pi(self) -> AigSignal: ...
    def create_po(self, f: AigSignal) -> int: ...
    def is_combinational(self) -> bool: ...
    def create_buf(self, a: AigSignal) -> AigSignal: ...
    def create_not(self, a: AigSignal) -> AigSignal: ...
    def create_and(self, a: AigSignal, b: AigSignal) -> AigSignal: ...
    def create_nand(self, a: AigSignal, b: AigSignal) -> AigSignal: ...
    def create_or(self, a: AigSignal, b: AigSignal) -> AigSignal: ...
    def create_nor(self, a: AigSignal, b: AigSignal) -> AigSignal: ...
    def create_xor(self, a: AigSignal, b: AigSignal) -> AigSignal: ...
    def create_xnor(self, a: AigSignal, b: AigSignal) -> AigSignal: ...
    def create_lt(self, a: AigSignal, b: AigSignal) -> AigSignal: ...
    def create_le(self, a: AigSignal, b: AigSignal) -> AigSignal: ...
    def create_maj(self, a: AigSignal, b: AigSignal, c: AigSignal) -> AigSignal: ...
    def create_ite(self, cond: AigSignal, f_then: AigSignal, f_else: AigSignal) -> AigSignal: ...
    def create_xor3(self, a: AigSignal, b: AigSignal, c: AigSignal) -> AigSignal: ...
    def create_nary_and(self, fs: list[AigSignal]) -> AigSignal: ...
    def create_nary_or(self, fs: list[AigSignal]) -> AigSignal: ...
    def create_nary_xor(self, fs: list[AigSignal]) -> AigSignal: ...
    def clone_node(self, other: Aig, source: AigNode | int, children: list[AigSignal]) -> AigSignal: ...
    def nodes(self) -> list[AigNode]: ...
    def gates(self) -> list[AigNode]: ...
    def pis(self) -> list[AigNode]: ...
    def pos(self) -> list[AigSignal]: ...
    def fanins(self, n: AigNode | int) -> list[AigSignal]: ...
    def fanin_size(self, n: AigNode | int) -> int: ...
    def fanout_size(self, n: AigNode | int) -> int: ...
    def is_constant(self, n: AigNode | int) -> bool: ...
    def is_pi(self, n: AigNode | int) -> bool: ...
    def has_and(self, a: AigSignal, b: AigSignal) -> bool: ...
    def is_and(self, n: AigNode | int) -> bool: ...
    def is_or(self, n: AigNode | int) -> bool: ...
    def is_xor(self, n: AigNode | int) -> bool: ...
    def is_maj(self, n: AigNode | int) -> bool: ...
    def is_ite(self, n: AigNode | int) -> bool: ...
    def is_xor3(self, n: AigNode | int) -> bool: ...
    def is_nary_and(self, n: AigNode | int) -> bool: ...
    def is_nary_or(self, n: AigNode | int) -> bool: ...
    def __getstate__(self) -> tuple[list[int]]: ...
    def __setstate__(self, state: tuple[list[int]]) -> Aig: ...
    def cleanup_dangling(self) -> None: ...

class DepthAig(Aig):
    def __init__(self, ntk: Aig | DepthAig | None = None) -> None: ...
    def num_levels(self) -> int: ...
    def level(self, n: AigNode | int) -> int: ...
    def is_on_critical_path(self, n: AigNode | int) -> bool: ...
    def update_levels(self) -> None: ...
    def create_po(self, f: AigSignal) -> int: ...

class FanoutAig(Aig):
    def __init__(self, ntk: Aig | FanoutAig | None = None) -> None: ...
    def fanouts(self, n: AigNode | int) -> list[AigNode]: ...

class AigRegister:
    def __init__(self, register: AigRegister | None = None) -> None: ...
    control: str
    init: int
    type: str

class SequentialAig(Aig):
    def __init__(self) -> None: ...
    def create_pi(self) -> AigSignal: ...
    def create_po(self, f: AigSignal) -> int: ...
    def create_ro(self) -> AigSignal: ...
    def create_ri(self, f: AigSignal) -> int: ...
    def is_combinational(self) -> bool: ...
    def is_ci(self, n: AigNode | int) -> bool: ...
    def is_pi(self, n: AigNode | int) -> bool: ...
    def is_ro(self, n: AigNode | int) -> bool: ...
    def num_pis(self) -> int: ...
    def num_pos(self) -> int: ...
    def num_cis(self) -> int: ...
    def num_cos(self) -> int: ...
    def num_registers(self) -> int: ...
    def pi_at(self, index: int) -> AigNode: ...
    def po_at(self, index: int) -> AigSignal: ...
    def ci_at(self, index: int) -> AigNode: ...
    def co_at(self, index: int) -> AigSignal: ...
    def ro_at(self, index: int) -> AigNode: ...
    def ri_at(self, index: int) -> AigSignal: ...
    def set_register(self, index: int, register: AigRegister) -> None: ...
    def register_at(self, index: int) -> AigRegister: ...
    def pi_index(self, n: AigNode | int) -> int: ...
    def ci_index(self, n: AigNode | int) -> int: ...
    def co_index(self, s: AigSignal) -> int: ...
    def ro_index(self, n: AigNode | int) -> int: ...
    def ri_index(self, s: AigSignal) -> int: ...
    def ro_to_ri(self, ro: AigSignal) -> AigSignal: ...
    def ri_to_ro(self, ri: AigSignal) -> AigNode: ...
    def pis(self) -> list[AigNode]: ...
    def pos(self) -> list[AigSignal]: ...
    def cis(self) -> list[AigNode]: ...
    def cos(self) -> list[AigSignal]: ...
    def ros(self) -> list[AigNode]: ...
    def ris(self) -> list[AigSignal]: ...
    def registers(self) -> list[tuple[AigSignal, AigNode]]: ...

def read_aiger_into_aig(filename: str) -> Aig: ...
def read_ascii_aiger_into_aig(filename: str) -> Aig: ...
def read_aiger_into_sequential_aig(filename: str) -> SequentialAig: ...
def read_ascii_aiger_into_sequential_aig(filename: str) -> SequentialAig: ...
def read_pla_into_aig(filename: str) -> Aig: ...
def read_verilog_into_aig(filename: str) -> Aig: ...
def write_aiger(ntk: Aig, filename: str) -> None: ...
def write_verilog(ntk: Aig, filename: str) -> None: ...
def write_dot(ntk: Aig, filename: str) -> None: ...

class AigEdge:
    def __init__(
        self,
        source: AigNode | int | None = None,
        target: AigNode | int | None = None,
        weight: int = 0,
    ) -> None: ...

    source: AigNode | int
    target: AigNode | int
    weight: int

    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...

class AigEdgeList:
    def __init__(self, ntk: Aig | None = None, edges: list[AigEdge] | None = None) -> None: ...

    ntk: Aig
    edges: list[AigEdge]

    def append(self, edge: AigEdge) -> None: ...
    def clear(self) -> None: ...
    def __iter__(self) -> Iterator[AigEdge]: ...
    def __len__(self) -> int: ...
    def __getitem__(self, index: int) -> AigEdge: ...
    def __setitem__(self, index: int, edge: AigEdge) -> None: ...

def to_edge_list(ntk: Aig | SequentialAig, regular_weight: int = 0, inverted_weight: int = 1) -> AigEdgeList: ...

class AigIndexList:
    @overload
    def __init__(self, num_pis: int = 0) -> None: ...
    @overload
    def __init__(self, values: list[int]) -> None: ...
    def raw(self) -> list[int]: ...
    def size(self) -> int: ...
    def num_gates(self) -> int: ...
    def num_pis(self) -> int: ...
    def num_pos(self) -> int: ...
    def add_inputs(self, n: int = 1) -> None: ...
    def add_and(self, lit0: int, lit1: int) -> None: ...
    def add_xor(self, lit0: int, lit1: int) -> None: ...
    def add_output(self, lit: int) -> None: ...
    def clear(self) -> None: ...
    def gates(self) -> list[tuple[int, int]]: ...
    def pos(self) -> list[int]: ...
    def __iter__(self) -> Iterator[int]: ...
    def __getitem__(self, index: int) -> int: ...
    def __setitem__(self, index: int, value: int) -> None: ...
    def __len__(self) -> int: ...

def to_index_list(ntk: Aig) -> AigIndexList: ...
def to_aig(il: AigIndexList) -> Aig: ...

class TruthTable:
    def __init__(self, num_vars: int | None = None) -> None: ...
    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...
    def __lt__(self, other: TruthTable) -> bool: ...
    def __and__(self, other: TruthTable) -> TruthTable: ...
    def __or__(self, other: TruthTable) -> TruthTable: ...
    def __xor__(self, other: TruthTable) -> TruthTable: ...
    def __invert__(self) -> TruthTable: ...
    def num_vars(self) -> int: ...
    def num_blocks(self) -> int: ...
    def num_bits(self) -> int: ...
    def __copy__(self) -> TruthTable: ...
    def __deepcopy__(self, memo: dict[Any, Any]) -> TruthTable: ...
    def __assign__(self, other: TruthTable) -> TruthTable: ...
    def __hash__(self) -> int: ...
    def set_bit(self, index: int) -> None: ...
    def get_bit(self, index: int) -> bool: ...
    def clear_bit(self, index: int) -> None: ...
    def flip_bit(self, index: int) -> None: ...
    def get_block(self, block_index: int) -> int: ...
    def create_nth_var(self, var_index: int, complement: bool = False) -> None: ...
    def create_from_binary_string(self, binary: str) -> None: ...
    def create_from_hex_string(self, hexadecimal: str) -> None: ...
    def create_random(self) -> None: ...
    def create_majority(self) -> None: ...
    def clear(self) -> None: ...
    def count_ones(self) -> int: ...
    def count_zeroes(self) -> int: ...
    def is_const0(self) -> bool: ...
    def is_const1(self) -> bool: ...
    def to_binary(self) -> str: ...
    def to_hex(self) -> str: ...

def ternary_majority(a: TruthTable, b: TruthTable, c: TruthTable) -> TruthTable: ...
def cofactor0(tt: TruthTable, var_index: int) -> TruthTable: ...
def cofactor1(tt: TruthTable, var_index: int) -> TruthTable: ...
def equivalence_checking(
    spec: Aig,
    impl: Aig,
    conflict_limit: int = 0,
    functional_reduction: bool = True,
    verbose: bool = False,
) -> bool | None: ...
def sop_refactoring(
    ntk: Aig,
    max_pis: int = 6,
    allow_zero_gain: bool = False,
    use_reconvergence_cut: bool = False,
    use_dont_cares: bool = False,
    verbose: bool = False,
) -> None: ...
def aig_resubstitution(
    ntk: Aig,
    max_pis: int = 8,
    max_divisors: int = 150,
    max_inserts: int = 2,
    skip_fanout_limit_for_roots: int = 1000,
    skip_fanout_limit_for_divisors: int = 100,
    verbose: bool = False,
    use_dont_cares: bool = False,
    window_size: int = 12,
    preserve_depth: bool = False,
) -> None: ...
def aig_cut_rewriting(
    ntk: Aig,
    cut_size: int = 4,
    cut_limit: int = 8,
    minimize_truth_table: bool = True,
    allow_zero_gain: bool = False,
    use_dont_cares: bool = False,
    min_cand_cut_size: int = 3,
    min_cand_cut_size_override: int | None = None,
    preserve_depth: bool = False,
    verbose: bool = False,
    very_verbose: bool = False,
) -> None: ...
def balancing(
    ntk: Aig,
    cut_size: int = 4,
    cut_limit: int = 8,
    minimize_truth_table: bool = True,
    only_on_critical_path: bool = False,
    rebalance_function: Literal["sop", "esop"] = "sop",
    sop_both_phases: bool = True,
    verbose: bool = False,
) -> None: ...
def simulate(ntk: Aig) -> list[TruthTable]: ...
def simulate_nodes(ntk: Aig) -> dict[int, TruthTable]: ...
