from typing import List, Iterator, Optional, Union


class AigNode:
    def __init__(self, index: int) -> None: ...

    def __hash__(self) -> int: ...

    def __repr__(self) -> str: ...

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

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

    def __lt__(self, other: AigNode) -> bool: ...


class AigSignal:
    def __init__(self, index: int, complement: bool) -> None: ...

    def get_index(self) -> int: ...

    def get_complement(self) -> bool: ...

    def __hash__(self) -> int: ...

    def __repr__(self) -> str: ...

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

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

    def __lt__(self, other: AigSignal) -> bool: ...

    def __invert__(self) -> bool: ...

    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_cis(self) -> int: ...

    def num_pos(self) -> int: ...

    def num_cos(self) -> int: ...

    def get_node(self, s: AigSignal) -> AigNode: ...

    def make_signal(self, n: AigNode) -> AigSignal: ...

    def is_complemented(self, s: AigSignal) -> bool: ...

    def node_to_index(self, n: AigNode) -> int: ...

    def index_to_node(self, index: int) -> AigNode: ...

    def pi_index(self, n: AigNode) -> int: ...

    def pi_at(self, index: int) -> AigNode: ...

    def po_index(self, s: AigSignal) -> int: ...

    def po_at(self, index: int) -> AigSignal: ...

    def ci_index(self, n: AigNode) -> int: ...

    def ci_at(self, index: int) -> AigNode: ...

    def co_index(self, s: AigSignal) -> int: ...

    def co_at(self, index: int) -> AigSignal: ...

    def get_constant(self, value: bool) -> AigSignal: ...

    def create_pi(self) -> AigNode: ...

    def create_po(self, f: AigSignal) -> None: ...

    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, children: List[AigSignal]) -> AigNode: ...

    def nodes(self) -> List[AigNode]: ...

    def gates(self) -> List[AigNode]: ...

    def pis(self) -> List[AigNode]: ...

    def pos(self) -> List[AigSignal]: ...

    def cis(self) -> List[AigNode]: ...

    def cos(self) -> List[AigSignal]: ...

    def fanins(self, n: AigNode) -> List[AigSignal]: ...

    def fanin_size(self, n: AigNode) -> int: ...

    def fanout_size(self, n: AigNode) -> int: ...

    def is_constant(self, n: AigNode) -> bool: ...

    def is_pi(self, n: AigNode) -> bool: ...

    def has_and(self, a: AigSignal, b: AigSignal) -> bool: ...

    def is_and(self, n: AigNode) -> bool: ...

    def is_or(self, n: AigNode) -> bool: ...

    def is_xor(self, n: AigNode) -> bool: ...

    def is_maj(self, n: AigNode) -> bool: ...

    def is_ite(self, n: AigNode) -> bool: ...

    def is_xor3(self, n: AigNode) -> bool: ...

    def is_nary_and(self, n: AigNode) -> bool: ...

    def is_nary_or(self, n: AigNode) -> bool: ...

    def cleanup_dangling(self) -> None: ...


class DepthAig(Aig):
    def __init__(self, ntk: Optional[Union[Aig, DepthAig]] = None) -> None: ...

    def num_levels(self) -> int: ...

    def level(self, n: AigNode) -> int: ...

    def is_on_critical_path(self, n: AigNode) -> bool: ...

    def update_levels(self) -> None: ...

    def create_po(self, f: AigSignal) -> None: ...


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

    source: AigNode
    target: AigNode
    weight: int

    def __repr__(self) -> str: ...

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

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


class AigEdgeList:
    def __init__(self, ntk: Optional[Aig] = None, edges: Optional[List[AigEdge]] = 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 __repr__(self) -> str: ...


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


class TruthTable:
    def __init__(self, num_vars: Optional[int] = None) -> None: ...

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

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

    def __lt__(self, other: TruthTable) -> bool: ...

    def num_vars(self) -> int: ...

    def num_blocks(self) -> int: ...

    def num_bits(self) -> int: ...

    def __copy__(self) -> TruthTable: ...

    def __deepcopy__(self, memo: dict) -> 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, hex: str) -> None: ...

    def create_random(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 __repr__(self) -> str: ...

    def to_binary(self) -> str: ...

    def to_hex(self) -> str: ...


from typing import Optional, List


def equivalence_checking(
        spec: Aig,
        impl: Aig,
        conflict_limit: int = 0,
        functional_reduction: bool = True,
        verbose: bool = False
) -> Optional[bool]: ...


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: Optional[int] = None,
        preserve_depth: bool = False,
        verbose: bool = False,
        very_verbose: bool = False
) -> None: ...


def simulate(
        ntk: Aig
) -> List[TruthTable]: ...
