def espresso_exprs(*exprs):
    """Return a tuple of expressions optimized using Espresso.

    The variadic *exprs* argument is a sequence of expressions.

    For example::

       >>> from pyeda.boolalg.expr import exprvar
       >>> a, b, c = map(exprvar, 'abc')
       >>> f1 = Or(And(~a, ~b, ~c), And(~a, ~b, c), And(a, ~b, c), And(a, b, c), And(a, b, ~c))
       >>> f2 = Or(And(~a, ~b, c), And(a, ~b, c))
       >>> f1m, f2m = espresso_exprs(f1, f2)
       >>> f1.size, f1m.size
       (21, 10)
       >>> f1m.equivalent(f1)
       True
       >>> f2.size, f2m.size
       (9, 3)
       >>> f2m.equivalent(f2)
       True
    """
    for f in exprs:
        if not (isinstance(f, Expression) and f.is_dnf()):
            raise ValueError("expected a DNF expression")

    support = frozenset.union(*[f.support for f in exprs])
    inputs = sorted(support)

    # Gather all cubes in the cover of input functions
    fscover = set()
    for f in exprs:
        fscover.update(f.cover)

    ninputs = len(inputs)
    noutputs = len(exprs)

    cover = set()
    for fscube in fscover:
        invec = list()
        for v in inputs:
            if ~v in fscube:
                invec.append(1)
            elif v in fscube:
                invec.append(2)
            else:
                invec.append(3)
        outvec = list()
        for f in exprs:
            for fcube in f.cover:
                if fcube <= fscube:
                    outvec.append(1)
                    break
            else:
                outvec.append(0)

        cover.add((tuple(invec), tuple(outvec)))

    set_config(**CONFIG)

    cover = espresso(ninputs, noutputs, cover, intype=FTYPE)
    return _cover2exprs(inputs, noutputs, cover)
def espresso_exprs ( * exprs ) : for f in exprs : if not ( isinstance ( f , Expression ) and f . is_dnf ( ) ) : raise ValueError ( "expected a DNF expression" ) support = frozenset . union ( * [ f . support for f in exprs ] ) inputs = sorted ( support ) fscover = set ( ) for f in exprs : fscover . update ( f . cover ) ninputs = len ( inputs ) noutputs = len ( exprs ) cover = set ( ) for fscube in fscover : invec = list ( ) for v in inputs : if ~ v in fscube : invec . append ( 1 ) elif v in fscube : invec . append ( 2 ) else : invec . append ( 3 ) outvec = list ( ) for f in exprs : for fcube in f . cover : if fcube <= fscube : outvec . append ( 1 ) break else : outvec . append ( 0 ) cover . add ( ( tuple ( invec ) , tuple ( outvec ) ) ) set_config ( ** CONFIG ) cover = espresso ( ninputs , noutputs , cover , intype = FTYPE ) return _cover2exprs ( inputs , noutputs , cover )
Return a tuple of expressions optimized using Espresso.

    The variadic *exprs* argument is a sequence of expressions.

    For example::

       >>> from pyeda.boolalg.expr import exprvar
       >>> a, b, c = map(exprvar, 'abc')
       >>> f1 = Or(And(~a, ~b, ~c), And(~a, ~b, c), And(a, ~b, c), And(a, b, c), And(a, b, ~c))
       >>> f2 = Or(And(~a, ~b, c), And(a, ~b, c))
       >>> f1m, f2m = espresso_exprs(f1, f2)
       >>> f1.size, f1m.size
       (21, 10)
       >>> f1m.equivalent(f1)
       True
       >>> f2.size, f2m.size
       (9, 3)
       >>> f2m.equivalent(f2)
       True