def OneHot(*xs, simplify=True, conj=True): """ Return an expression that means "exactly one input function is true". If *simplify* is ``True``, return a simplified expression. If *conj* is ``True``, return a CNF. Otherwise, return a DNF. """ xs = [Expression.box(x).node for x in xs] terms = list() if conj: for x0, x1 in itertools.combinations(xs, 2): terms.append(exprnode.or_(exprnode.not_(x0), exprnode.not_(x1))) terms.append(exprnode.or_(*xs)) y = exprnode.and_(*terms) else: for i, xi in enumerate(xs): zeros = [exprnode.not_(x) for x in xs[:i] + xs[i + 1:]] terms.append(exprnode.and_(xi, *zeros)) y = exprnode.or_(*terms) if simplify: y = y.simplify() return _expr(y)
def OneHot(*xs, simplify=True, conj=True): """ Return an expression that means "exactly one input function is true". If *simplify* is ``True``, return a simplified expression. If *conj* is ``True``, return a CNF. Otherwise, return a DNF. """ xs = [Expression.box(x).node for x in xs] terms = list() if conj: for x0, x1 in itertools.combinations(xs, 2): terms.append(exprnode.or_(exprnode.not_(x0), exprnode.not_(x1))) terms.append(exprnode.or_(*xs)) y = exprnode.and_(*terms) else: for i, xi in enumerate(xs): zeros = [exprnode.not_(x) for x in xs[:i] + xs[i+1:]] terms.append(exprnode.and_(xi, *zeros)) y = exprnode.or_(*terms) if simplify: y = y.simplify() return _expr(y)
def NHot(n, *xs, simplify=True): """ Return an expression that means "exactly N input functions are true". If *simplify* is ``True``, return a simplified expression. """ if not isinstance(n, int): raise TypeError("expected n to be an int") if not 0 <= n <= len(xs): fstr = "expected 0 <= n <= {}, got {}" raise ValueError(fstr.format(len(xs), n)) xs = [Expression.box(x).node for x in xs] num = len(xs) terms = list() for hot_idxs in itertools.combinations(range(num), n): hot_idxs = set(hot_idxs) _xs = [ xs[i] if i in hot_idxs else exprnode.not_(xs[i]) for i in range(num) ] terms.append(exprnode.and_(*_xs)) y = exprnode.or_(*terms) if simplify: y = y.simplify() return _expr(y)
def NHot(n, *xs, simplify=True): """ Return an expression that means "exactly N input functions are true". If *simplify* is ``True``, return a simplified expression. """ if not isinstance(n, int): raise TypeError("expected n to be an int") if not 0 <= n <= len(xs): fstr = "expected 0 <= n <= {}, got {}" raise ValueError(fstr.format(len(xs), n)) xs = [Expression.box(x).node for x in xs] num = len(xs) terms = list() for hot_idxs in itertools.combinations(range(num), n): hot_idxs = set(hot_idxs) _xs = [xs[i] if i in hot_idxs else exprnode.not_(xs[i]) for i in range(num)] terms.append(exprnode.and_(*_xs)) y = exprnode.or_(*terms) if simplify: y = y.simplify() return _expr(y)
def Or(*xs, simplify=True): """Expression disjunction (sum, OR) operator If *simplify* is ``True``, return a simplified expression. """ xs = [Expression.box(x).node for x in xs] y = exprnode.or_(*xs) if simplify: y = y.simplify() return _expr(y)
def Nor(*xs, simplify=True): """Expression NOR (not OR) operator If *simplify* is ``True``, return a simplified expression. """ xs = [Expression.box(x).node for x in xs] y = exprnode.not_(exprnode.or_(*xs)) if simplify: y = y.simplify() return _expr(y)
def OneHot0(*xs, simplify=True, conj=True): """ Return an expression that means "at most one input function is true". If *simplify* is ``True``, return a simplified expression. If *conj* is ``True``, return a CNF. Otherwise, return a DNF. """ xs = [Expression.box(x).node for x in xs] terms = list() if conj: for x0, x1 in itertools.combinations(xs, 2): terms.append(exprnode.or_(exprnode.not_(x0), exprnode.not_(x1))) y = exprnode.and_(*terms) else: for _xs in itertools.combinations(xs, len(xs) - 1): terms.append(exprnode.and_(*[exprnode.not_(x) for x in _xs])) y = exprnode.or_(*terms) if simplify: y = y.simplify() return _expr(y)
def Majority(*xs, simplify=True, conj=False): """ Return an expression that means "the majority of input functions are true". If *simplify* is ``True``, return a simplified expression. If *conj* is ``True``, return a CNF. Otherwise, return a DNF. """ xs = [Expression.box(x).node for x in xs] if conj: terms = list() for _xs in itertools.combinations(xs, (len(xs) + 1) // 2): terms.append(exprnode.or_(*_xs)) y = exprnode.and_(*terms) else: terms = list() for _xs in itertools.combinations(xs, len(xs) // 2 + 1): terms.append(exprnode.and_(*_xs)) y = exprnode.or_(*terms) if simplify: y = y.simplify() return _expr(y)
def AchillesHeel(*xs, simplify=True): r""" Return the Achille's Heel function, defined as: :math:`\prod_{i=0}^{n/2-1}{X_{2i} + X_{2i+1}}`. If *simplify* is ``True``, return a simplified expression. """ nargs = len(xs) if nargs & 1: fstr = "expected an even number of arguments, got {}" raise ValueError(fstr.format(nargs)) xs = [Expression.box(x).node for x in xs] y = exprnode.and_(*[exprnode.or_(xs[2*i], xs[2*i+1]) for i in range(nargs // 2)]) if simplify: y = y.simplify() return _expr(y)
def AchillesHeel(*xs, simplify=True): r""" Return the Achille's Heel function, defined as: :math:`\prod_{i=0}^{n/2-1}{X_{2i} + X_{2i+1}}`. If *simplify* is ``True``, return a simplified expression. """ nargs = len(xs) if nargs & 1: fstr = "expected an even number of arguments, got {}" raise ValueError(fstr.format(nargs)) xs = [Expression.box(x).node for x in xs] y = exprnode.and_( *[exprnode.or_(xs[2 * i], xs[2 * i + 1]) for i in range(nargs // 2)]) if simplify: y = y.simplify() return _expr(y)
def Mux(fs, sel, simplify=True): """ Return an expression that multiplexes a sequence of input functions over a sequence of select functions. """ # convert Mux([a, b], x) to Mux([a, b], [x]) if isinstance(sel, Expression): sel = [sel] if len(sel) < clog2(len(fs)): fstr = "expected at least {} select bits, got {}" raise ValueError(fstr.format(clog2(len(fs)), len(sel))) it = boolfunc.iter_terms(sel) y = exprnode.or_(*[exprnode.and_(f.node, *[lit.node for lit in next(it)]) for f in fs]) if simplify: y = y.simplify() return _expr(y)
def Mux(fs, sel, simplify=True): """ Return an expression that multiplexes a sequence of input functions over a sequence of select functions. """ # convert Mux([a, b], x) to Mux([a, b], [x]) if isinstance(sel, Expression): sel = [sel] if len(sel) < clog2(len(fs)): fstr = "expected at least {} select bits, got {}" raise ValueError(fstr.format(clog2(len(fs)), len(sel))) it = boolfunc.iter_terms(sel) y = exprnode.or_( *[exprnode.and_(f.node, *[lit.node for lit in next(it)]) for f in fs]) if simplify: y = y.simplify() return _expr(y)
def __or__(self, other): other_node = self.box(other).node return _expr(exprnode.or_(self.node, other_node))