<commit_before>"""
Boolean Functions

Globals:
    VARIABLES

Interface Functions:
    num2point
    num2upoint
    num2term

    point2upoint
    point2term

    iter_points
    iter_upoints
    iter_terms

Interface Classes:
    Variable
    Function
    Slicer
    VectorFunction
"""

from pyeda.common import bit_on

VARIABLES = dict()


def num2point(num, vs):
    """Convert a number into a point in an N-dimensional space.

    Parameters
    ----------
    num : int
    vs : [Variable]
    """
    return {v: bit_on(num, i) for i, v in enumerate(vs)}

def num2upoint(num, vs):
    """Convert a number into an untyped point in an N-dimensional space.

    Parameters
    ----------
    num : int
    vs : [Variable]
    """
    upoint = [set(), set()]
    for i, v in enumerate(vs):
        upoint[bit_on(num, i)].add(v.uniqid)
    return upoint

def num2term(num, vs, conj=False):
    """Convert a number into a min/max term.

    Parameters
    ----------
    num : int
    vs : [Variable]
    conj : bool
        conj=False for minterms, conj=True for maxterms

    Examples
    --------

    Table of min/max terms for Boolean space {a, b, c}

    +-----+----------+----------+
    | num |  minterm |  maxterm |
    +=====+==========+==========+
    | 0   | a' b' c' | a  b  c  |
    | 1   | a  b' c' | a' b  c  |
    | 2   | a' b  c' | a  b' c  |
    | 3   | a  b  c' | a' b' c  |
    | 4   | a' b' c  | a  b  c' |
    | 5   | a  b' c  | a' b  c' |
    | 6   | a' b  c  | a  b' c' |
    | 7   | a  b  c  | a' b' c' |
    +-------+----------+----------+
    """
    if conj:
        return tuple(-v if bit_on(num, i) else v for i, v in enumerate(vs))
    else:
        return tuple(v if bit_on(num, i) else -v for i, v in enumerate(vs))

def point2upoint(point):
    """Convert a point into an untyped point.

    Parameters
    ----------
    point : {Variable: int}
    """
    upoint = [set(), set()]
    for v, val in point.items():
        upoint[val].add(v.uniqid)
    return upoint

def point2term(point, conj=False):
    """Convert a point in an N-dimension space into a min/max term.

    Parameters
    ----------
    point : {Variable: int}
    """
    if conj:
        return tuple(-v if val else v for v, val in point.items())
    else:
        return tuple(v if val else -v for v, val in point.items())

def iter_points(vs):
    """Iterate through all points in an N-dimensional space.

    Parameters
    ----------
    vs : [Variable]
    """
    for num in range(1 << len(vs)):
        yield num2point(num, vs)

def iter_upoints(vs):
    """Iterate through all untyped points in an N-dimensional space.

    Parameters
    ----------
    vs : [Variable]
    """
    for num in range(1 << len(vs)):
        yield num2upoint(num, vs)

def iter_terms(vs, conj=False):
    """Iterate through all min/max terms in an N-dimensional space.

    Parameters
    ----------
    vs: [Variable]
    """
    for num in range(1 << len(vs)):
        yield num2term(num, vs, conj)


class Variable(object):
    """
    Abstract base class that defines an interface for a Boolean variable.

    A Boolean variable is a numerical quantity that may assume any value in the
    set B = {0, 1}.

    This implementation includes optional indices, nonnegative integers that
    can be used to construct multi-dimensional bit vectors.
    """

    _UNIQIDS = dict()
    _CNT = 1

    def __new__(cls, name, indices=None, namespace=None):
        if indices is None:
            indices = tuple()
        elif type(indices) is int:
            indices = (indices, )
        try:
            uniqid = cls._UNIQIDS[(namespace, name, indices)]
        except KeyError:
            uniqid = cls._CNT
            cls._CNT += 1
            cls._UNIQIDS[(namespace, name, indices)] = uniqid
        try:
            self = VARIABLES[uniqid]
        except KeyError:
            self = super(Variable, cls).__new__(cls)
            self.namespace = namespace
            self.name = name
            self.indices = indices
            self.uniqid = uniqid
            VARIABLES[self.uniqid] = self
        return self

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        suffix = "".join("[{}]".format(idx) for idx in self.indices)
        return self.qualname + suffix

    def __lt__(self, other):
        if self.name == other.name:
            return self.indices < other.indices
        else:
            return self.name < other.name

    @property
    def qualname(self):
        if self.namespace is None:
            return self.name
        else:
            return self.namespace + "." + self.name


class Function(object):
    """
    Abstract base class that defines an interface for a scalar Boolean function
    of :math:`N` variables.
    """
    @property
    def support(self):
        """Return the support set of a function.

        Let :math:`f(x_1, x_2, ..., x_n)` be a Boolean function of :math:`N`
        variables. The set :math:`\{x_1, x_2, ..., x_n\}` is called the
        *support* of the function.
        """
        raise NotImplementedError()

    @property
    def inputs(self):
        """Return the support set in name/index order."""
        raise NotImplementedError()

    @property<commit_msg>Add multi-level namespaces to Variable<commit_after>"""
Boolean Functions

Globals:
    VARIABLES

Interface Functions:
    num2point
    num2upoint
    num2term

    point2upoint
    point2term

    iter_points
    iter_upoints
    iter_terms

Interface Classes:
    Variable
    Function
    Slicer
    VectorFunction
"""

from pyeda.common import bit_on

VARIABLES = dict()


def num2point(num, vs):
    """Convert a number into a point in an N-dimensional space.

    Parameters
    ----------
    num : int
    vs : [Variable]
    """
    return {v: bit_on(num, i) for i, v in enumerate(vs)}

def num2upoint(num, vs):
    """Convert a number into an untyped point in an N-dimensional space.

    Parameters
    ----------
    num : int
    vs : [Variable]
    """
    upoint = [set(), set()]
    for i, v in enumerate(vs):
        upoint[bit_on(num, i)].add(v.uniqid)
    return upoint

def num2term(num, vs, conj=False):
    """Convert a number into a min/max term.

    Parameters
    ----------
    num : int
    vs : [Variable]
    conj : bool
        conj=False for minterms, conj=True for maxterms

    Examples
    --------

    Table of min/max terms for Boolean space {a, b, c}

    +-----+----------+----------+
    | num |  minterm |  maxterm |
    +=====+==========+==========+
    | 0   | a' b' c' | a  b  c  |
    | 1   | a  b' c' | a' b  c  |
    | 2   | a' b  c' | a  b' c  |
    | 3   | a  b  c' | a' b' c  |
    | 4   | a' b' c  | a  b  c' |
    | 5   | a  b' c  | a' b  c' |
    | 6   | a' b  c  | a  b' c' |
    | 7   | a  b  c  | a' b' c' |
    +-------+----------+----------+
    """
    if conj:
        return tuple(-v if bit_on(num, i) else v for i, v in enumerate(vs))
    else:
        return tuple(v if bit_on(num, i) else -v for i, v in enumerate(vs))

def point2upoint(point):
    """Convert a point into an untyped point.

    Parameters
    ----------
    point : {Variable: int}
    """
    upoint = [set(), set()]
    for v, val in point.items():
        upoint[val].add(v.uniqid)
    return upoint

def point2term(point, conj=False):
    """Convert a point in an N-dimension space into a min/max term.

    Parameters
    ----------
    point : {Variable: int}
    """
    if conj:
        return tuple(-v if val else v for v, val in point.items())
    else:
        return tuple(v if val else -v for v, val in point.items())

def iter_points(vs):
    """Iterate through all points in an N-dimensional space.

    Parameters
    ----------
    vs : [Variable]
    """
    for num in range(1 << len(vs)):
        yield num2point(num, vs)

def iter_upoints(vs):
    """Iterate through all untyped points in an N-dimensional space.

    Parameters
    ----------
    vs : [Variable]
    """
    for num in range(1 << len(vs)):
        yield num2upoint(num, vs)

def iter_terms(vs, conj=False):
    """Iterate through all min/max terms in an N-dimensional space.

    Parameters
    ----------
    vs: [Variable]
    """
    for num in range(1 << len(vs)):
        yield num2term(num, vs, conj)


class Variable(object):
    """
    Abstract base class that defines an interface for a Boolean variable.

    A Boolean variable is a numerical quantity that may assume any value in the
    set B = {0, 1}.

    This implementation includes optional indices, nonnegative integers that
    can be used to construct multi-dimensional bit vectors.
    """

    _UNIQIDS = dict()
    _CNT = 1

    def __new__(cls, name, indices=None, namespace=None):
        if indices is None:
            indices = tuple()
        elif type(indices) is int:
            indices = (indices, )
        if namespace is None:
            namespace = tuple()
        elif type(namespace) is str:
            namespace = (namespace, )

        # Check input types
        assert type(name) is str
        assert type(indices) is tuple
        for idx in indices:
            assert type(idx) is int
        assert type(namespace) is tuple
        for n in namespace:
            assert type(n) is str

        try:
            uniqid = cls._UNIQIDS[(namespace, name, indices)]
        except KeyError:
            uniqid = cls._CNT
            cls._CNT += 1
            cls._UNIQIDS[(namespace, name, indices)] = uniqid
        try:
            self = VARIABLES[uniqid]
        except KeyError:
            self = super(Variable, cls).__new__(cls)
            self.namespace = namespace
            self.name = name
            self.indices = indices
            self.uniqid = uniqid
            VARIABLES[self.uniqid] = self
        return self

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        suffix = "".join("[{}]".format(idx) for idx in self.indices)
        return self.qualname + suffix

    def __lt__(self, other):
        if self.name == other.name:
            return self.indices < other.indices
        else:
            return self.name < other.name

    @property
    def qualname(self):
        names = [n for n in reversed(self.namespace)]
        names.append(self.name)
        return ".".join(names)


class Function(object):
    """
    Abstract base class that defines an interface for a scalar Boolean function
    of :math:`N` variables.
    """
    @property
    def support(self):
        """Return the support set of a function.

        Let :math:`f(x_1, x_2, ..., x_n)` be a Boolean function of :math:`N`
        variables. The set :math:`\{x_1, x_2, ..., x_n\}` is called the
        *support* of the function.
        """
        raise NotImplementedError()

    @property
    def inputs(self):
        """Return the support set in name/index order."""
        raise NotImplementedError()

    @property
{'fraction_non_alphanumeric': 0.13554987212276215, 'fraction_numerical': 0.005845816587504567, 'mean_word_length': 1.8424195223260644, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6493089', 'n_tokens_mistral': 3511, 'n_tokens_neox': 3382, 'n_words': 1143}